mirror of
https://github.com/nix-community/plasma-manager.git
synced 2024-11-29 15:03:49 +03:00
Add widget-specific options for panels (#161)
This commit is contained in:
parent
4b56c71c9c
commit
1554e19ede
@ -61,7 +61,19 @@
|
||||
# widget will add them with the default configuration.
|
||||
"org.kde.plasma.marginsseparator"
|
||||
"org.kde.plasma.systemtray"
|
||||
"org.kde.plasma.digitalclock"
|
||||
# If you need configuration for your widget, instead of specifying the
|
||||
# the keys and values directly using the config attribute as shown
|
||||
# above, plasma-manager also provides some higher-level interfaces for
|
||||
# configuring the widgets. See modules/widgets for supported widgets
|
||||
# and options for these widgets. The widget below shows an example of
|
||||
# usage, where we add a digital clock, setting 12h time and first day
|
||||
# of the week to sunday.
|
||||
{
|
||||
digitalClock = {
|
||||
calendar.firstDayOfWeek = "sunday";
|
||||
time.format = "12h";
|
||||
};
|
||||
}
|
||||
];
|
||||
hiding = "autohide";
|
||||
}
|
||||
|
@ -1,27 +1,13 @@
|
||||
{ config, lib, ... }:
|
||||
{ config
|
||||
, lib
|
||||
, ...
|
||||
} @ args:
|
||||
let
|
||||
cfg = config.programs.plasma;
|
||||
|
||||
# Widget types
|
||||
widgetType = lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "org.kde.plasma.kickoff";
|
||||
description = "The name of the widget to add.";
|
||||
};
|
||||
config = lib.mkOption {
|
||||
type = with lib.types; nullOr (attrsOf (attrsOf (either str (listOf str))));
|
||||
default = null;
|
||||
example = {
|
||||
General.icon = "nix-snowflake-white";
|
||||
};
|
||||
description = "Extra configuration-options for the widget.";
|
||||
};
|
||||
};
|
||||
};
|
||||
widgets = import ./widgets args;
|
||||
|
||||
panelType = lib.types.submodule ({config, ...}: {
|
||||
panelType = lib.types.submodule ({ config, ... }: {
|
||||
options = {
|
||||
height = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
@ -47,8 +33,8 @@ let
|
||||
description = "The maximum allowed length/width of the panel.";
|
||||
};
|
||||
lengthMode = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.enum ["fit" "fill" "custom"]);
|
||||
default =
|
||||
type = lib.types.nullOr (lib.types.enum [ "fit" "fill" "custom" ]);
|
||||
default =
|
||||
if config.minLength != null || config.maxLength != null then
|
||||
"custom"
|
||||
else
|
||||
@ -90,7 +76,7 @@ let
|
||||
};
|
||||
floating = lib.mkEnableOption "Enable or disable floating style (plasma 6 only).";
|
||||
widgets = lib.mkOption {
|
||||
type = with lib.types; listOf (either str widgetType);
|
||||
type = with lib.types; listOf (either str widgets.type);
|
||||
default = [
|
||||
"org.kde.plasma.kickoff"
|
||||
"org.kde.plasma.pager"
|
||||
@ -179,38 +165,42 @@ let
|
||||
}
|
||||
'';
|
||||
|
||||
panelAddWidgetStr = widget: let
|
||||
createWidget = name: ''panelWidgets["${name}"] = panel.addWidget("${name}");'';
|
||||
in
|
||||
if builtins.isString widget then
|
||||
createWidget widget
|
||||
panelAddWidgetStr = widget:
|
||||
let
|
||||
widget' = widgets.convert widget;
|
||||
createWidget = name: ''panelWidgets["${name}"] = panel.addWidget("${name}");'';
|
||||
in
|
||||
if builtins.isString widget
|
||||
then createWidget widget
|
||||
else
|
||||
''
|
||||
${createWidget widget.name}
|
||||
${stringIfNotNull widget.config (widgetConfigsToStr widget.name widget.config)}
|
||||
${createWidget widget'.name}
|
||||
${stringIfNotNull widget'.config (widgetConfigsToStr widget'.name widget'.config)}
|
||||
'';
|
||||
|
||||
panelToLayout = panel: let
|
||||
inherit (lib) boolToString optionalString;
|
||||
inherit (builtins) toString;
|
||||
in ''
|
||||
var panel = new Panel;
|
||||
panel.height = ${toString panel.height};
|
||||
panel.floating = ${boolToString panel.floating};
|
||||
${stringIfNotNull panel.alignment ''panel.alignment = "${panel.alignment}";''}
|
||||
${stringIfNotNull panel.hiding ''panel.hiding = "${panel.hiding}";''}
|
||||
${stringIfNotNull panel.location ''panel.location = "${panel.location}";''}
|
||||
${stringIfNotNull panel.lengthMode (plasma6OnlyCmd ''panel.lengthMode = "${panel.lengthMode}";'')}
|
||||
${stringIfNotNull panel.maxLength "panel.maximumLength = ${toString panel.maxLength};"}
|
||||
${stringIfNotNull panel.minLength "panel.minimumLength = ${toString panel.minLength};"}
|
||||
${stringIfNotNull panel.offset "panel.offset = ${toString panel.offset};"}
|
||||
${optionalString (panel.screen != 0) ''panel.writeConfig("lastScreen[$i]", ${toString panel.screen});''}
|
||||
panelToLayout = panel:
|
||||
let
|
||||
inherit (lib) boolToString optionalString;
|
||||
inherit (builtins) toString;
|
||||
in
|
||||
''
|
||||
var panel = new Panel;
|
||||
panel.height = ${toString panel.height};
|
||||
panel.floating = ${boolToString panel.floating};
|
||||
${stringIfNotNull panel.alignment ''panel.alignment = "${panel.alignment}";''}
|
||||
${stringIfNotNull panel.hiding ''panel.hiding = "${panel.hiding}";''}
|
||||
${stringIfNotNull panel.location ''panel.location = "${panel.location}";''}
|
||||
${stringIfNotNull panel.lengthMode (plasma6OnlyCmd ''panel.lengthMode = "${panel.lengthMode}";'')}
|
||||
${stringIfNotNull panel.maxLength "panel.maximumLength = ${toString panel.maxLength};"}
|
||||
${stringIfNotNull panel.minLength "panel.minimumLength = ${toString panel.minLength};"}
|
||||
${stringIfNotNull panel.offset "panel.offset = ${toString panel.offset};"}
|
||||
${optionalString (panel.screen != 0) ''panel.writeConfig("lastScreen[$i]", ${toString panel.screen});''}
|
||||
|
||||
var panelWidgets = {};
|
||||
${lib.concatMapStringsSep "\n" panelAddWidgetStr panel.widgets}
|
||||
var panelWidgets = {};
|
||||
${lib.concatMapStringsSep "\n" panelAddWidgetStr panel.widgets}
|
||||
|
||||
${stringIfNotNull panel.extraSettings panel.extraSettings}
|
||||
'';
|
||||
${stringIfNotNull panel.extraSettings panel.extraSettings}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.programs.plasma.panels = lib.mkOption {
|
||||
|
51
modules/widgets/default.nix
Normal file
51
modules/widgets/default.nix
Normal file
@ -0,0 +1,51 @@
|
||||
{ lib, ... } @ args:
|
||||
let
|
||||
sources = lib.mergeAttrsList (map (s: import s args) [
|
||||
./digital-clock.nix
|
||||
./system-monitor.nix
|
||||
]);
|
||||
|
||||
compositeWidgetType = lib.pipe sources [
|
||||
(builtins.mapAttrs (_: s:
|
||||
lib.mkOption {
|
||||
inherit (s) description;
|
||||
type = lib.types.submodule {
|
||||
options = s.opts;
|
||||
};
|
||||
}))
|
||||
lib.types.attrTag
|
||||
];
|
||||
|
||||
simpleWidgetType = lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "org.kde.plasma.kickoff";
|
||||
description = "The name of the widget to add.";
|
||||
};
|
||||
config = lib.mkOption {
|
||||
type = with lib.types; nullOr (attrsOf (attrsOf (either str (listOf str))));
|
||||
default = null;
|
||||
example = {
|
||||
General.icon = "nix-snowflake-white";
|
||||
};
|
||||
description = "Extra configuration-options for the widget.";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
type = lib.types.either compositeWidgetType simpleWidgetType;
|
||||
|
||||
convert = composite:
|
||||
let
|
||||
inherit (builtins) length head attrNames hasAttr mapAttrs isAttrs;
|
||||
keys = attrNames composite;
|
||||
type = head keys;
|
||||
|
||||
converters = mapAttrs (_: s: s.convert) sources;
|
||||
in
|
||||
if isAttrs composite && length keys == 1 && hasAttr type converters
|
||||
then converters.${type} composite.${type}
|
||||
else composite; # not a known composite type
|
||||
}
|
245
modules/widgets/digital-clock.nix
Normal file
245
modules/widgets/digital-clock.nix
Normal file
@ -0,0 +1,245 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkEnableOption mkOption types;
|
||||
|
||||
fontType = types.submodule {
|
||||
options = {
|
||||
family = mkOption {
|
||||
type = types.str;
|
||||
example = "Noto Sans";
|
||||
description = "The family of the font.";
|
||||
};
|
||||
bold = mkEnableOption "bold text";
|
||||
italic = mkEnableOption "italic text";
|
||||
weight = mkOption {
|
||||
type = types.ints.between 1 1000;
|
||||
default = 50;
|
||||
description = "The weight of the font.";
|
||||
};
|
||||
style = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "The custom style of the font.";
|
||||
};
|
||||
size = mkOption {
|
||||
type = types.ints.positive;
|
||||
default = 10;
|
||||
description = "The size of the font.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enums = {
|
||||
date = {
|
||||
format = [ "shortDate" "longDate" "isoDate" ];
|
||||
position = [ "adaptive" "besideTime" "belowTime" ];
|
||||
};
|
||||
time = {
|
||||
showSeconds = [ "never" "onlyInTooltip" "always" ];
|
||||
format = [ "12h" "default" "24h" ];
|
||||
};
|
||||
timeZone.format = [ "code" "city" "offset" ];
|
||||
calendar.weekdays = [ "sunday" "monday" "tuesday" "wednesday" "thursday" "friday" "saturday" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
digitalClock = {
|
||||
description = "A digital clock widget.";
|
||||
|
||||
opts = {
|
||||
date = {
|
||||
enable = mkEnableOption "showing the current date" // { default = true; };
|
||||
|
||||
format = mkOption {
|
||||
type = types.nullOr (types.either (types.enum enums.date.format) (types.submodule {
|
||||
options.custom = mkOption {
|
||||
type = types.str;
|
||||
example = "ddd d";
|
||||
description = "The custom date format to use.";
|
||||
};
|
||||
}));
|
||||
default = null;
|
||||
example = { custom = "d.MM.yyyy"; };
|
||||
description = ''
|
||||
The date format used for this clock.
|
||||
|
||||
Could be as a short date, long date, a ISO 8601 date (yyyy-mm-dd), or a custom date format.
|
||||
Short and long date formats are locale-dependent.
|
||||
'';
|
||||
};
|
||||
|
||||
position = mkOption {
|
||||
type = types.nullOr (types.enum enums.date.position);
|
||||
default = null;
|
||||
description = ''
|
||||
The position where the date is displayed.
|
||||
|
||||
Could be adaptive, always beside the displayed time, or below the displayed time.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
time = {
|
||||
showSeconds = mkOption {
|
||||
type = types.nullOr (types.enum enums.time.showSeconds);
|
||||
default = null;
|
||||
description = ''
|
||||
When and where the seconds should be shown on the clock.
|
||||
|
||||
Could be never, only in the tooltip on hover, or always.
|
||||
'';
|
||||
};
|
||||
format = mkOption {
|
||||
type = types.nullOr (types.enum enums.time.format);
|
||||
default = null;
|
||||
description = ''
|
||||
The time format used for this clock.
|
||||
|
||||
Could be 12-hour, the default for your locale, or 24-hour.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
timeZone = {
|
||||
selected = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
example = [ "Europe/Berlin" "Asia/Shanghai" ];
|
||||
description = ''
|
||||
The timezones that are configured for this clock.
|
||||
|
||||
The special value "Local" indicates the system's current timezone.
|
||||
'';
|
||||
};
|
||||
lastSelected = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The timezone to show upon widget restore.
|
||||
|
||||
The special value "Local" indicates the system's current timezone.
|
||||
'';
|
||||
};
|
||||
changeOnScroll = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Allow changing the displayed timezone by scrolling on the widget with the mouse wheel.";
|
||||
};
|
||||
format = mkOption {
|
||||
type = types.nullOr (types.enum enums.timeZone.format);
|
||||
default = null;
|
||||
example = "code";
|
||||
description = ''
|
||||
The format of the timezone displayed, whether as a
|
||||
code, full name of the city that the timezone belongs to,
|
||||
or as an UTC offset.
|
||||
|
||||
For example, for the timezone Asia/Shanghai, the three formats
|
||||
listed above would display "CST", "Shanghai" and "+8" respectively.
|
||||
'';
|
||||
};
|
||||
alwaysShow = mkEnableOption "always showing the selected timezone, when it's the same with the system timezone";
|
||||
};
|
||||
|
||||
calendar = {
|
||||
firstDayOfWeek = mkOption {
|
||||
type = types.nullOr (types.enum enums.calendar.weekdays);
|
||||
default = null;
|
||||
example = "monday";
|
||||
description = ''
|
||||
The first day of the week that the calendar uses.
|
||||
|
||||
If null, then the default for the user locale is used.
|
||||
'';
|
||||
};
|
||||
plugins = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
description = "List of enabled calendar plugins, where additional event data can be sourced from.";
|
||||
};
|
||||
showWeekNumbers = mkEnableOption "showing week numbers in the calendar";
|
||||
};
|
||||
|
||||
font = mkOption {
|
||||
type = types.nullOr fontType;
|
||||
default = null;
|
||||
example = {
|
||||
family = "Noto Sans";
|
||||
bold = true;
|
||||
size = 16;
|
||||
};
|
||||
description = ''
|
||||
The font used for this clock.
|
||||
|
||||
If null, then it will use the system font and automatically expand to fill available space.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
convert =
|
||||
{ date
|
||||
, time
|
||||
, timeZone
|
||||
, calendar
|
||||
, font
|
||||
,
|
||||
}:
|
||||
let
|
||||
inherit (builtins) toString;
|
||||
inherit (lib) boolToString;
|
||||
|
||||
getEnum = es: e:
|
||||
if e == null
|
||||
then null
|
||||
else
|
||||
toString (
|
||||
lib.lists.findFirstIndex
|
||||
(x: x == e)
|
||||
(throw "getEnum: nonexistent key ${e}! This is a bug!")
|
||||
es
|
||||
);
|
||||
in
|
||||
{
|
||||
name = "org.kde.plasma.digitalclock";
|
||||
config.Appearance = lib.filterAttrs (_: v: v != null) (
|
||||
{
|
||||
showDate = boolToString date.enable;
|
||||
dateDisplayFormat = getEnum enums.date.position date.position;
|
||||
dateFormat =
|
||||
if date.format ? custom
|
||||
then "custom"
|
||||
else date.format;
|
||||
customDateFormat =
|
||||
if date.format ? custom
|
||||
then date.format.custom
|
||||
else null;
|
||||
|
||||
showSeconds = getEnum enums.time.showSeconds time.showSeconds;
|
||||
use24hFormat = getEnum enums.time.format time.format;
|
||||
|
||||
selectedTimeZones = timeZone.selected;
|
||||
lastSelectedTimezone = timeZone.lastSelected;
|
||||
wheelChangesTimezone = boolToString timeZone.changeOnScroll;
|
||||
displayTimezoneFormat = getEnum enums.timeZone.format timeZone.format;
|
||||
showLocalTimezone = boolToString timeZone.alwaysShow;
|
||||
|
||||
firstDayOfWeek =
|
||||
if calendar.firstDayOfWeek != null
|
||||
then getEnum enums.calendar.weekdays calendar.firstDayOfWeek
|
||||
else null;
|
||||
enabledCalendarPlugins = calendar.plugins;
|
||||
|
||||
autoFontAndSize = boolToString (font == null);
|
||||
}
|
||||
// lib.optionalAttrs (font != null) {
|
||||
fontFamily = font.family;
|
||||
boldText = boolToString font.bold;
|
||||
italicText = boolToString font.italic;
|
||||
fontWeight = toString font.weight;
|
||||
fontStyleName = font.styleName;
|
||||
fontSize = toString font.size;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
126
modules/widgets/system-monitor.nix
Normal file
126
modules/widgets/system-monitor.nix
Normal file
@ -0,0 +1,126 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
systemMonitor = {
|
||||
description = "A system monitor widget.";
|
||||
|
||||
opts = {
|
||||
title = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "The title of this system monitor.";
|
||||
};
|
||||
displayStyle = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "org.kde.ksysguard.barchart";
|
||||
description = "The display style of the chart. Uses the internal plugin name.";
|
||||
};
|
||||
sensors = mkOption {
|
||||
type = types.nullOr (types.listOf (types.submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
example = "cpu/all/usage";
|
||||
description = "The name of the sensor.";
|
||||
};
|
||||
color = mkOption {
|
||||
type = types.str; # TODO maybe use a better type
|
||||
example = "255,255,255";
|
||||
description = "The color of the sensor, as a string containing 8-bit integral RGB values separated by commas";
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = null;
|
||||
example = [
|
||||
{
|
||||
name = "gpu/gpu1/usage";
|
||||
color = "180,190,254";
|
||||
}
|
||||
];
|
||||
description = ''
|
||||
The list of sensors displayed as a part of the graph/chart.
|
||||
'';
|
||||
};
|
||||
|
||||
totalSensors = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
example = [ "cpu/all/usage" ];
|
||||
description = ''
|
||||
The list of "total sensors" displayed on top of the graph/chart.
|
||||
'';
|
||||
};
|
||||
textOnlySensors = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
example = [ "cpu/all/averageTemperature" "cpu/all/averageFrequency" ];
|
||||
description = ''
|
||||
The list of text-only sensors, displayed in the pop-up upon clicking the widget.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
convert =
|
||||
{ title
|
||||
, displayStyle
|
||||
, totalSensors
|
||||
, sensors
|
||||
, textOnlySensors
|
||||
,
|
||||
}:
|
||||
let
|
||||
# KDE expects a key/value pair like this:
|
||||
# ```ini
|
||||
# highPrioritySensorIds=["cpu/all/usage", "cpu/all/averageTemperature"]
|
||||
# ```
|
||||
#
|
||||
# Which is **different** to what would happen if you pass a list of strings to the JS script:
|
||||
# ```ini
|
||||
# highPrioritySensorIds=cpu/all/usage,cpu/all/averageTemperature
|
||||
# ```
|
||||
#
|
||||
# So, to satisfy the expected format we must quote the ENTIRE string as a valid JS string,
|
||||
# which means constructing a string that looks like this in the source code:
|
||||
# "[\"cpu/all/usage\", \"cpu/all/averageTemperature\"]"
|
||||
toEscapedList = ids:
|
||||
if ids != null
|
||||
then "[${lib.concatMapStringsSep ", " (x: ''\"${x}\"'') ids}]"
|
||||
else null;
|
||||
|
||||
# {name, color} -> {name, value}
|
||||
# Convert the sensor attrset into a name-value pair expected by listToAttrs
|
||||
toColorKV =
|
||||
{ name
|
||||
, color
|
||||
,
|
||||
}: {
|
||||
inherit name;
|
||||
value = color;
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "org.kde.plasma.systemmonitor";
|
||||
config = lib.filterAttrsRecursive (_: v: v != null) {
|
||||
Appearance = {
|
||||
inherit title;
|
||||
chartFace = displayStyle;
|
||||
};
|
||||
SensorColors =
|
||||
if sensors != null
|
||||
then builtins.listToAttrs (map toColorKV sensors)
|
||||
else null;
|
||||
Sensors = {
|
||||
highPrioritySensorIds =
|
||||
if sensors != null
|
||||
then toEscapedList (map (s: s.name) sensors)
|
||||
else null;
|
||||
lowPrioritySensorIds = toEscapedList textOnlySensors;
|
||||
totalSensors = toEscapedList totalSensors;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user