Class DesktopFile

Represents .desktop file.

class DesktopFile
  : IniLikeFile ;

Constructors

NameDescription
this Reads desktop file from file.
this Reads desktop file from IniLikeReader, e.g. acquired from iniLikeFileReader or iniLikeStringReader.
this Constructs DesktopFile with "Desktop Entry" group and Version set to 1.1

Methods

NameDescription
action Get additional application action by name.
byAction Iterating over existing actions.
desktopEntry
expandExecValue Expand "Exec" value into the array of command line arguments to use to start the program. It applies unquoting and unescaping.
id See Desktop File ID
id See Desktop File ID
joinValues Join range of multiple values into a string using semicolon as separator. Adds trailing semicolon.
removeGroup Removes group by name. You can't remove "Desktop Entry" group with this function.
splitValues Some keys can have multiple values, separated by semicolon. This function helps to parse such kind of strings into the range.
start Starts application or open link depending on desktop entry type.
startApplication Starts the application associated with this .desktop file using urls as command line params.
startApplication Starts the application associated with this .desktop file using url as command line params.
startLink Opens url defined in .desktop file using xdg-open.
type Type of desktop entry.
addGenericGroup Create new group using groupName.
appendLeadingComment Add leading comment. This will be appended to the list of leadingComments.
byGroup Range of groups in order how they were defined in file.
byNode Iterate over GroupNodes.
clearLeadingComments Remove all coments met before groups.
escapedValue Shortcut to IniLikeGroup.escapedValue of given group. Returns null if the group does not exist.
escapedValue ditto, localized version
fileName File path where the object was loaded from.
getNode Get GroupNode by groupName.
group Get group by name.
leadingComments Leading comments.
moveGroupAfter Move group after other.
moveGroupBefore Move group before other.
moveGroupToBack Move the group to make it the last.
moveGroupToFront Move the group to make it the first.
prependLeadingComment Prepend leading comment (e.g. for setting shebang line).
save Use Output range or delegate to retrieve strings line by line. Those strings can be written to the file or be showed in text area.
saveToFile Save object to the file using .ini-like format.
saveToString Save object to string using .ini like format.
unescapedValue Shortcut to IniLikeGroup.unescapedValue of given group. Returns null if the group does not exist.
isActionName Check if groupName is name of Desktop Action group.
createEmptyGroup Can be used in derived classes to create instance of IniLikeGroup.
createGroupByName Reimplement in derive class.
insertGroup Insert group into IniLikeFile object and use its name as key.
onCommentInGroup Add comment for group. This function is called only in constructor and can be reimplemented in derived classes.
onGroup Create IniLikeGroup by groupName during file parsing.
onKeyValue Add key/value pair for group. This function is called only in constructor and can be reimplemented in derived classes.
onLeadingComment Add comment before groups. This function is called only in constructor and can be reimplemented in derived classes.
putGroup Append group to group list without associating group name with it. Can be used to add groups with duplicated names.

Inner structs

NameDescription
DesktopReadOptions Options to manage desktop file reading
GroupNode Wrapper for internal ListMap node.
ReadOptions Behavior of ini-like file reading.
WriteOptions Behavior of ini-like file saving.

Enums

NameDescription
ActionGroupPolicy Policy about reading Desktop Action groups.
ExtensionGroupPolicy Policy about reading extension groups (those start with 'X-').
UnknownGroupPolicy Policy about reading groups with names which meaning is unknown, i.e. it's not extension nor Desktop Action.
DuplicateGroupPolicy Behavior on group with duplicate name in the file.
DuplicateKeyPolicy Behavior on duplicate key in the group.

Aliases

NameDescription
Type Alias for backward compatibility.

Example

import std.file;
string desktopFileContents =
`[Desktop Entry]
# Comment
Name=Double Commander
Name[ru]=Двухпанельный коммандер
GenericName=File manager
GenericName[ru]=Файловый менеджер
Comment=Double Commander is a cross platform open source file manager with two panels side by side.
Comment[ru]=Double Commander - кроссплатформенный файловый менеджер.
Terminal=false
Icon=doublecmd
Icon[ru]=doublecmd_ru
Exec=doublecmd %f
TryExec=doublecmd
Type=Application
Categories=Application;Utility;FileManager;
Keywords=folder;manager;disk;filesystem;operations;
Keywords[ru]=папка;директория;диск;файловый;менеджер;
Actions=OpenDirectory;NotPresented;Settings;X-NoName;
MimeType=inode/directory;application/x-directory;
NoDisplay=false
Hidden=false
StartupNotify=true
DBusActivatable=true
Path=/opt/doublecmd
OnlyShowIn=GNOME;XFCE;LXDE;
NotShowIn=KDE;

[Desktop Action OpenDirectory]
Name=Open directory
Name[ru]=Открыть папку
Icon=open
Exec=doublecmd %u

[X-NoName]
Icon=folder

[Desktop Action Settings]
Name=Settings
Name[ru]=Настройки
Icon=edit
Exec=doublecmd settings

[Desktop Action Notspecified]
Name=Notspecified Action`;

auto df = new DesktopFile(iniLikeStringReader(desktopFileContents), "doublecmd.desktop");
assert(df.desktopEntry().groupName() == "Desktop Entry");
assert(df.fileName() == "doublecmd.desktop");
assert(df.displayName() == "Double Commander");
assert(df.localizedDisplayName("ru_RU") == "Двухпанельный коммандер");
assert(df.genericName() == "File manager");
assert(df.localizedGenericName("ru_RU") == "Файловый менеджер");
assert(df.comment() == "Double Commander is a cross platform open source file manager with two panels side by side.");
assert(df.localizedComment("ru_RU") == "Double Commander - кроссплатформенный файловый менеджер.");
assert(df.iconName() == "doublecmd");
assert(df.localizedIconName("ru_RU") == "doublecmd_ru");
assert(df.tryExecValue() == "doublecmd");
assert(!df.terminal());
assert(!df.noDisplay());
assert(!df.hidden());
assert(df.startupNotify());
assert(df.dbusActivable());
assert(df.workingDirectory() == "/opt/doublecmd");
assert(df.type() == DesktopFile.Type.Application);
assert(equal(df.keywords(), ["folder", "manager", "disk", "filesystem", "operations"]));
assert(equal(df.localizedKeywords("ru_RU"), ["папка", "директория", "диск", "файловый", "менеджер"]));
assert(equal(df.categories(), ["Application", "Utility", "FileManager"]));
assert(equal(df.actions(), ["OpenDirectory", "NotPresented", "Settings", "X-NoName"]));
assert(equal(df.mimeTypes(), ["inode/directory", "application/x-directory"]));
assert(equal(df.onlyShowIn(), ["GNOME", "XFCE", "LXDE"]));
assert(equal(df.notShowIn(), ["KDE"]));
assert(df.group("X-NoName") !is null);

assert(equal(df.byAction().map!(desktopAction =>
tuple(desktopAction.displayName(), desktopAction.localizedDisplayName("ru"), desktopAction.iconName(), desktopAction.execValue())),
             [tuple("Open directory", "Открыть папку", "open", "doublecmd %u"), tuple("Settings", "Настройки", "edit", "doublecmd settings")]));

DesktopAction desktopAction = df.action("OpenDirectory");
assert(desktopAction !is null);
assert(desktopAction.expandExecValue(["path/to/file"]) == ["doublecmd", "path/to/file"]);

assert(df.action("NotPresented") is null);
assert(df.action("Notspecified") is null);
assert(df.action("X-NoName") is null);
assert(df.action("Settings") !is null);

assert(df.saveToString() == desktopFileContents);

assert(df.contains("Icon"));
df.removeEntry("Icon");
assert(!df.contains("Icon"));
df.setEscapedValue("Icon", "files");
assert(df.contains("Icon"));

string contents =
`# First comment
[Desktop Entry]
Key=Value
# Comment in group`;

df = new DesktopFile(iniLikeStringReader(contents), "test.desktop");
assert(df.fileName() == "test.desktop");
df.removeGroup("Desktop Entry");
assert(df.group("Desktop Entry") !is null);
assert(df.desktopEntry() !is null);

contents =
`[X-SomeGroup]
Key=Value`;

auto thrown = collectException!IniLikeReadException(new DesktopFile(iniLikeStringReader(contents)));
assert(thrown !is null);
assert(thrown.lineNumber == 0);

df = new DesktopFile();
df.desktopEntry().setUnescapedValue("$Invalid", "Valid value", IniLikeGroup.InvalidKeyPolicy.save);
assert(df.desktopEntry().escapedValue("$Invalid") == "Valid value");
df.desktopEntry().setUnescapedValue("Another$Invalid", "Valid value", IniLikeGroup.InvalidKeyPolicy.skip);
assert(df.desktopEntry().escapedValue("Another$Invalid") is null);
df.terminal = true;
df.type = DesktopFile.Type.Application;
df.categories = ["Development", "Compilers", "One;Two", "Three\\;Four", "New\nLine"];

assert(df.terminal() == true);
assert(df.type() == DesktopFile.Type.Application);
assert(equal(df.categories(), ["Development", "Compilers", "One;Two", "Three\\;Four","New\nLine"]));

df.displayName = "Program name";
assert(df.displayName() == "Program name");
df.genericName = "Program";
assert(df.genericName() == "Program");
df.comment = "Do\nthings";
assert(df.comment() == "Do\nthings");

df.execValue = "utilname";
assert(df.execValue() == "utilname");

df.noDisplay = true;
assert(df.noDisplay());
df.hidden = true;
assert(df.hidden());
df.dbusActivable = true;
assert(df.dbusActivable());
df.startupNotify = true;
assert(df.startupNotify());

df.url = "/some/url";
assert(df.url == "/some/url");