Skip to content

Commit

Permalink
Move desktop options to desktop module and add desktop widgets opti…
Browse files Browse the repository at this point in the history
…on (#332)
  • Loading branch information
HeitorAugustoLN authored Aug 24, 2024
1 parent 5919d0f commit 311435f
Show file tree
Hide file tree
Showing 19 changed files with 594 additions and 226 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ broken when used with plasma 5. If you want the best experience with
At the moment `plasma-manager` supports configuring the following:
- KDE configuration files (via the `files` module)
- Global themes, colorschemes, icons, cursortheme, wallpaper (via the `workspace` module)
- Desktop icons, widgets, and mouse actions (via the `desktop` module)
- Configuration of spectacle shortcuts (via the `spectacle` module)
- Shortcuts (via the `shortcuts` module)
- Hotkeys (via the `hotkeys` module)
Expand Down
1 change: 1 addition & 0 deletions modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{
imports = [
./apps
./desktop.nix
./files.nix
./fonts.nix
./hotkeys.nix
Expand Down
269 changes: 269 additions & 0 deletions modules/desktop.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
{ config, lib, ... }: let
cfg = config.programs.plasma;

widgets = import ./widgets { inherit lib; };

desktopIconSortingModeId = {
manual = -1;
name = 0;
size = 1;
date = 2;
type = 6;
};

mouseActions = {
applicationLauncher = "org.kde.applauncher";
contextMenu = "org.kde.contextmenu";
paste = "org.kde.paste";
switchActivity = "switchactivity";
switchVirtualDesktop = "org.kde.switchdesktop";
switchWindow = "switchwindow";
};

mouseActionNamesEnum = lib.types.enum (builtins.attrNames mouseActions);

# Becomes true if any option under "cfg.desktop.icons" is set to something other than null.
anyDesktopFolderSettingsSet =
let
recurse = l: lib.any (v: if builtins.isAttrs v then recurse v else v != null) (builtins.attrValues l);
in
recurse cfg.desktop.icons;

# Becomes true if any option under "cfg.desktop.mouseActions" is set to something other than null.
anyDesktopMouseActionsSet = lib.any (v: v != null) (builtins.attrValues cfg.desktop.mouseActions);
in
{
imports = [
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "arrangement" ] ["programs" "plasma" "desktop" "icons" "arrangement"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "alignment" ] ["programs" "plasma" "desktop" "icons" "alignment"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "lockInPlace" ] ["programs" "plasma" "desktop" "icons" "lockInPlace"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "sorting" "mode" ] ["programs" "plasma" "desktop" "icons" "sorting" "mode"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "sorting" "descending" ] ["programs" "plasma" "desktop" "icons" "sorting" "descending"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "sorting" "foldersFirst" ] ["programs" "plasma" "desktop" "icons" "sorting" "foldersFirst"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "size" ] ["programs" "plasma" "desktop" "icons" "size"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "folderPreviewPopups" ] ["programs" "plasma" "desktop" "icons" "folderPreviewPopups"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "icons" "previewPlugins" ] ["programs" "plasma" "desktop" "icons" "previewPlugins"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "mouseActions" "leftClick" ] ["programs" "plasma" "desktop" "mouseActions" "leftClick"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "mouseActions" "middleClick" ] ["programs" "plasma" "desktop" "mouseActions" "middleClick"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "mouseActions" "rightClick" ] ["programs" "plasma" "desktop" "mouseActions" "rightClick"])
(lib.mkRenamedOptionModule ["programs" "plasma" "workspace" "desktop" "mouseActions" "verticalScroll" ] ["programs" "plasma" "desktop" "mouseActions" "verticalScroll"])
];

options.programs.plasma.desktop = {
icons = {
arrangement = lib.mkOption {
type = with lib.types; nullOr (enum [ "leftToRight" "topToBottom" ]);
default = null;
example = "topToBottom";
description = ''
The direction, in which desktop icons are to be arranged.
'';
};

alignment = lib.mkOption {
type = with lib.types; nullOr (enum [ "left" "right" ]);
default = null;
example = "right";
description = ''
Whether to align the icons on the left (the default) or right
side of the screen.
'';
};

lockInPlace = lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
example = true;
description = ''
Locks the position of all desktop icons to the order and placement
defined by `arrangement`, `alignment` and the `sorting` options
so they can’t be manually moved.
'';
};

sorting = {
mode = lib.mkOption {
type = with lib.types; nullOr (enum (builtins.attrNames desktopIconSortingModeId));
default = null;
example = "type";
description = ''
Specifies the sort mode for the desktop icons. By default they are
sorted by name.
'';
apply = sortMode: if (sortMode == null) then null else desktopIconSortingModeId.${sortMode};
};

descending = lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
example = true;
description = ''
Reverses the sorting order if enabled. Sorting is ascending by default.
'';
};

foldersFirst = lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
example = false;
description = ''
Folders are sorted separately from files by default. This means
folders appear first, sorted for example ascending by name,
followed by files, also sorted ascending by name.
If this option is disabled, all items are sorted irrespective
of their type.
'';
};
};

size = lib.mkOption {
type = with lib.types; nullOr (ints.between 0 6);
default = null;
example = 2;
description = ''
The desktop icon size, which is normally configured via a slider
with seven possible values ranging from small (0) to large (6).
The fourth position (3) is the default.
'';
};

folderPreviewPopups = lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
example = false;
description = ''
Enables the arrow button when hovering over a folder on the desktop
which shows a preview popup of the folder’s contents.
Is enabled by default.
'';
};

previewPlugins = lib.mkOption {
type = with lib.types; nullOr (listOf str);
default = null;
example = [ "audiothumbnail" "fontthumbnail" ];
description = ''
Configures the preview plugins used to preview desktop files and folders.
'';
};
};

mouseActions = {
leftClick = lib.mkOption {
type = lib.types.nullOr mouseActionNamesEnum;
default = null;
example = "appLauncher";
description = "Action for a left click on the desktop.";
apply = value: if (value == null) then null else mouseActions.${value};
};

middleClick = lib.mkOption {
type = lib.types.nullOr mouseActionNamesEnum;
default = null;
example = "switchWindow";
description = "Action for a click on the desktop with the middle mouse button.";
apply = value: if (value == null) then null else mouseActions.${value};
};

rightClick = lib.mkOption {
type = lib.types.nullOr mouseActionNamesEnum;
default = null;
example = "contextMenu";
description = "Action for a right click on the desktop.";
apply = value: if (value == null) then null else mouseActions.${value};
};

verticalScroll = lib.mkOption {
type = lib.types.nullOr mouseActionNamesEnum;
default = null;
example = "switchVirtualDesktop";
description = "Action for scrolling (vertically) while hovering over the desktop.";
apply = value: if (value == null) then null else mouseActions.${value};
};
};

widgets = lib.mkOption {
type = with lib.types; nullOr (listOf widgets.desktopType);
default = null;
example = [
{
name = "org.kde.plasma.digitalclock";
position = { horizontal = 51; vertical = 100; };
size = { width = 250; height = 250; };
config.Appearance.showDate = false;
}
{
plasmusicToolbar = {
position = { horizontal = 51; vertical = 300; };
size = { width = 250; height = 400; };
background = "transparentShadow";
};
}
];
description = ''
A list of widgets to be added to the desktop.
'';
apply = option: if option == null then null else (map widgets.desktopConvert option);
};
};

config = (lib.mkIf cfg.enable {
programs.plasma.startup = {
desktopScript."set_desktop_folder_settings" = (lib.mkIf anyDesktopFolderSettingsSet {
text = ''
// Desktop folder settings
let allDesktops = desktops();
for (const desktop of allDesktops) {
desktop.currentConfigGroup = ["General"];
${lib.optionalString (cfg.desktop.icons.arrangement == "topToBottom") ''desktop.writeConfig("arrangement", 1);''}
${lib.optionalString (cfg.desktop.icons.alignment == "right") ''desktop.writeConfig("alignment", 1);''}
${lib.optionalString (cfg.desktop.icons.lockInPlace == true) ''desktop.writeConfig("locked", true);''}
${widgets.lib.stringIfNotNull cfg.desktop.icons.size ''desktop.writeConfig("iconSize", ${builtins.toString cfg.desktop.icons.size});''}
${lib.optionalString (cfg.desktop.icons.folderPreviewPopups == false) ''desktop.writeConfig("popups", false);''}
${widgets.lib.stringIfNotNull cfg.desktop.icons.previewPlugins ''desktop.writeConfig("previewPlugins", "${lib.strings.concatStringsSep "," cfg.desktop.icons.previewPlugins}");''}
${widgets.lib.stringIfNotNull cfg.desktop.icons.sorting.mode ''desktop.writeConfig("sortMode", ${builtins.toString cfg.desktop.icons.sorting.mode});''}
${lib.optionalString (cfg.desktop.icons.sorting.descending == true) ''desktop.writeConfig("sortDesc", true);''}
${lib.optionalString (cfg.desktop.icons.sorting.foldersFirst == false) ''desktop.writeConfig("sortDirsFirst", false);''}
}
'';
priority = 3;
});

desktopScript."set_desktop_mouse_actions" = (lib.mkIf anyDesktopMouseActionsSet {
text = ''
// Mouse actions
let configFile = ConfigFile('plasma-org.kde.plasma.desktop-appletsrc');
configFile.group = 'ActionPlugins';
// References the section [ActionPlugins][0].
let actionPluginSubSection = ConfigFile(configFile, 0)
${widgets.lib.stringIfNotNull cfg.desktop.mouseActions.leftClick ''actionPluginSubSection.writeEntry("LeftButton;NoModifier", "${cfg.desktop.mouseActions.leftClick}");''}
${widgets.lib.stringIfNotNull cfg.desktop.mouseActions.middleClick ''actionPluginSubSection.writeEntry("MiddleButton;NoModifier", "${cfg.desktop.mouseActions.middleClick}");''}
${widgets.lib.stringIfNotNull cfg.desktop.mouseActions.rightClick ''actionPluginSubSection.writeEntry("RightButton;NoModifier", "${cfg.desktop.mouseActions.rightClick}");''}
${widgets.lib.stringIfNotNull cfg.desktop.mouseActions.verticalScroll ''actionPluginSubSection.writeEntry("wheel:Vertical;NoModifier", "${cfg.desktop.mouseActions.verticalScroll}");''}
'';
priority = 3;
restartServices = [ "plasma-plasmashell" ];
});

desktopScript."set_desktop_widgets" = (lib.mkIf (cfg.desktop.widgets != null) {
text = ''
// Desktop widgets
let allDesktops = desktops();
// Remove all desktop widgets
allDesktops.forEach((desktop) => {
desktop.widgets().forEach((widget) => {
widget.remove();
});
});
for (let i = 0; i < allDesktops.length; i++) {
const desktop = allDesktops[i];
${widgets.lib.addDesktopWidgetStmts "desktop" "desktopWidgets" cfg.desktop.widgets}
}
'';
priority = 2;
});
};
});
}
6 changes: 5 additions & 1 deletion modules/panels.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ let
cfg = config.programs.plasma;
inherit (import ../lib/wallpapers.nix { inherit lib; }) wallpaperFillModeTypes;

hasWidget = widgetName: builtins.any (panel: builtins.any (widget: widget.name == widgetName) panel.widgets) cfg.panels;
desktopWidgets = if cfg.desktop.widgets != null then cfg.desktop.widgets else [];

hasWidget = widgetName:
builtins.any (panel: builtins.any (widget: widget.name == widgetName) panel.widgets) cfg.panels ||
builtins.any (widget: widget.name == widgetName) desktopWidgets;

# An attrset keeping track of the packages which should be added when a
# widget is present in the config.
Expand Down
15 changes: 14 additions & 1 deletion modules/widgets/application-title-bar.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
let
inherit (lib) mkOption types;
inherit (import ./lib.nix { inherit lib; }) configValueType;
inherit (import ./default.nix { inherit lib; }) positionType sizeType;

mkBoolOption = description: lib.mkOption {
type = with lib.types; nullOr bool;
Expand Down Expand Up @@ -114,6 +115,16 @@ in
description = "KDE plasmoid with window title and buttons";

opts = {
position = mkOption {
type = positionType;
example = { horizontal = 100; vertical = 300; };
description = "The position of the widget. (Only for desktop widget)";
};
size = mkOption {
type = sizeType;
example = { width = 500; height = 50; };
description = "The size of the widget. (Only for desktop widget)";
};
layout = {
widgetMargins = mkOption {
type = types.nullOr types.ints.unsigned;
Expand Down Expand Up @@ -455,7 +466,9 @@ in
};
};
convert =
{ layout
{ position
, size
, layout
, windowControlButtons
, windowTitle
, overrideForMaximized
Expand Down
30 changes: 23 additions & 7 deletions modules/widgets/battery.nix
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
{ lib, ... }:
let
inherit (import ./lib.nix { inherit lib; }) configValueType;
inherit (import ./default.nix { inherit lib; }) positionType sizeType;
in {
battery = {
description = "The battery indicator widget.";

# See https://invent.kde.org/plasma/plasma-workspace/-/blob/master/applets/batterymonitor/package/contents/config/main.xml for the accepted raw options
opts = {
position = lib.mkOption {
type = positionType;
example = { horizontal = 250; vertical = 50; };
description = "The position of the widget. (Only for desktop widget)";
};
size = lib.mkOption {
type = sizeType;
example = { width = 500; height = 500; };
description = "The size of the widget. (Only for desktop widget)";
};
showPercentage = lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
Expand All @@ -25,13 +36,18 @@ in {
};
};

convert = { showPercentage, settings }: {
name = "org.kde.plasma.battery";
config = lib.recursiveUpdate {
General = lib.filterAttrs (_: v: v != null) {
inherit showPercentage;
};
} settings;
convert =
{ position
, size
, showPercentage
, settings
}: {
name = "org.kde.plasma.battery";
config = lib.recursiveUpdate {
General = lib.filterAttrs (_: v: v != null) {
inherit showPercentage;
};
} settings;
};
};
}
Loading

0 comments on commit 311435f

Please sign in to comment.