Skip to content

Commit 0ba34d9

Browse files
committed
Add listAssociatedApplications
1 parent e976623 commit 0ba34d9

File tree

12 files changed

+139
-65
lines changed

12 files changed

+139
-65
lines changed

dub.selections.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"fileVersion": 1,
33
"versions": {
4-
"desktopfile": "1.0.0-beta4",
4+
"desktopfile": "1.0.0-beta5",
55
"isfreedesktop": "0.1.0",
6-
"inilike": "1.0.0-beta2",
7-
"xdgpaths": "0.2.1",
6+
"inilike": "1.0.0-beta3",
7+
"xdgpaths": "0.2.2",
88
"findexecutable": "0.1.0"
99
}
1010
}

examples/list/dub.selections.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"fileVersion": 1,
33
"versions": {
4-
"desktopfile": "1.0.0-beta4",
4+
"desktopfile": "1.0.0-beta5",
55
"isfreedesktop": "0.1.0",
6-
"inilike": "1.0.0-beta2",
7-
"xdgpaths": "0.2.1",
6+
"inilike": "1.0.0-beta3",
7+
"xdgpaths": "0.2.2",
88
"findexecutable": "0.1.0"
99
}
1010
}

examples/open/dub.selections.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
"fileVersion": 1,
33
"versions": {
44
"mime": "0.3.3",
5-
"desktopfile": "1.0.0-beta4",
5+
"desktopfile": "1.0.0-beta5",
66
"isfreedesktop": "0.1.0",
7-
"xdgpaths": "0.2.1",
7+
"xdgpaths": "0.2.2",
88
"findexecutable": "0.1.0",
9-
"inilike": "1.0.0-beta2"
9+
"inilike": "1.0.0-beta3"
1010
}
1111
}

examples/test/dub.selections.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"fileVersion": 1,
33
"versions": {
4-
"desktopfile": "1.0.0-beta4",
4+
"desktopfile": "1.0.0-beta5",
55
"isfreedesktop": "0.1.0",
6-
"inilike": "1.0.0-beta2",
7-
"xdgpaths": "0.2.1",
6+
"inilike": "1.0.0-beta3",
7+
"xdgpaths": "0.2.2",
88
"findexecutable": "0.1.0"
99
}
1010
}

examples/update/dub.selections.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"fileVersion": 1,
33
"versions": {
4-
"desktopfile": "1.0.0-beta4",
4+
"desktopfile": "1.0.0-beta5",
55
"isfreedesktop": "0.1.0",
6-
"inilike": "1.0.0-beta2",
7-
"xdgpaths": "0.2.1",
6+
"inilike": "1.0.0-beta3",
7+
"xdgpaths": "0.2.2",
88
"findexecutable": "0.1.0"
99
}
1010
}

source/mimeapps.d

Lines changed: 118 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ static if (isFreedesktop)
124124

125125
/**
126126
* Find all writable mimeapps.list files locations. Found paths are not checked for existence.
127-
* Note: This function is available only on Freedesktop.
127+
*
128+
* $(BLUE This function is Freedesktop only).
128129
* See_Also: $(D mimeAppsListPaths)
129130
*/
130131
@safe string[] writableMimeAppsListPaths() nothrow
@@ -143,8 +144,9 @@ static if (isFreedesktop)
143144

144145
/**
145146
* Find all known mimeapps.list files locations. Found paths are not checked for existence.
147+
*
148+
* $(BLUE This function is Freedesktop only).
146149
* Returns: Paths of mimeapps.list files in the system.
147-
* Note: This function is available only on Freedesktop.
148150
* See_Also: $(LINK2 https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s02.html, File name and location)
149151
*/
150152
@safe string[] mimeAppsListPaths() nothrow
@@ -177,8 +179,9 @@ static if (isFreedesktop)
177179

178180
/**
179181
* Find all known mimeinfo.cache files locations. Found paths are not checked for existence.
182+
*
183+
* $(BLUE This function is Freedesktop only).
180184
* Returns: Paths of mimeinfo.cache files in the system.
181-
* Note: This function is available only on Freedesktop.
182185
*/
183186
@safe string[] mimeInfoCachePaths() nothrow
184187
{
@@ -760,7 +763,8 @@ static if (isFreedesktop)
760763
{
761764
/**
762765
* ditto, but automatically read $(D MimeAppsListFile) objects from determined system paths.
763-
* Note: Available only on Freedesktop.
766+
*
767+
* $(BLUE This function is Freedesktop only).
764768
*/
765769
@safe MimeAppsListFile[] mimeAppsListFiles() nothrow {
766770
return mimeAppsListFiles(mimeAppsListPaths());
@@ -790,7 +794,8 @@ static if (isFreedesktop)
790794
{
791795
/**
792796
* ditto, but automatically read MimeInfoCacheFile objects from determined system paths.
793-
* Note: Available only on Freedesktop.
797+
*
798+
* $(BLUE This function is Freedesktop only).
794799
*/
795800
@safe MimeInfoCacheFile[] mimeInfoCacheFiles() nothrow {
796801
return mimeInfoCacheFiles(mimeInfoCachePaths());
@@ -811,7 +816,7 @@ interface IDesktopFileProvider
811816
}
812817

813818
/**
814-
* Implementation of desktop file provider.
819+
* Implementation of simple desktop file provider.
815820
*/
816821
class DesktopFileProvider : IDesktopFileProvider
817822
{
@@ -837,11 +842,16 @@ public:
837842
}
838843

839844
/// ditto, but determine binPaths from PATH environment variable automatically.
840-
@trusted this(const(string)[] applicationsPaths, DesktopFile.DesktopReadOptions options = DesktopFile.DesktopReadOptions.init) {
845+
@trusted this(in string[] applicationsPaths, DesktopFile.DesktopReadOptions options = DesktopFile.DesktopReadOptions.init) {
841846
this(applicationsPaths, binPaths().array, options);
842847
}
843848

844-
///
849+
/**
850+
* Get DesktopFile by desktop id.
851+
* This implementation searches applicationsPaths given in constructor to find, parse and cache .desktop file.
852+
* If found file has TryExec value it also checks if executable can be find in binPaths.
853+
* Note: Exec value is left unchecked.
854+
*/
845855
override const(DesktopFile) getByDesktopId(string desktopId)
846856
{
847857
auto itemIn = desktopId in _cache;
@@ -904,10 +914,11 @@ private enum FindAssocFlag {
904914
ignoreRemovedGroup = 2
905915
}
906916

907-
private const(DesktopFile)[] findAssociatedApplicationsImpl(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, IDesktopFileProvider desktopFileProvider, FindAssocFlag flag = FindAssocFlag.none)
917+
private string[] listAssociatedApplicationsImpl(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, FindAssocFlag flag = FindAssocFlag.none)
908918
{
909919
string[] removed;
910-
const(DesktopFile)[] desktopFiles;
920+
string[] desktopIds;
921+
911922
foreach(mimeAppsListFile; mimeAppsListFiles) {
912923
if (mimeAppsListFile is null) {
913924
continue;
@@ -920,17 +931,10 @@ private const(DesktopFile)[] findAssociatedApplicationsImpl(ListRange, CacheRang
920931
auto addedAppsGroup = mimeAppsListFile.addedAssociations();
921932
if (addedAppsGroup !is null) {
922933
foreach(desktopId; addedAppsGroup.appsForMimeType(mimeType)) {
923-
if (removed.canFind(desktopId)) {
934+
if (removed.canFind(desktopId) || desktopIds.canFind(desktopId)) {
924935
continue;
925936
}
926-
auto desktopFile = desktopFileProvider.getByDesktopId(desktopId);
927-
if (desktopFile) {
928-
if (flag & FindAssocFlag.onlyFirst) {
929-
return [desktopFile];
930-
}
931-
desktopFiles ~= desktopFile;
932-
}
933-
removed ~= desktopId;
937+
desktopIds ~= desktopId;
934938
}
935939
}
936940
}
@@ -941,33 +945,100 @@ private const(DesktopFile)[] findAssociatedApplicationsImpl(ListRange, CacheRang
941945
}
942946

943947
foreach(desktopId; mimeInfoCacheFile.appsForMimeType(mimeType)) {
944-
if (removed.canFind(desktopId)) {
948+
if (removed.canFind(desktopId) || desktopIds.canFind(desktopId)) {
945949
continue;
946950
}
947-
auto desktopFile = desktopFileProvider.getByDesktopId(desktopId);
948-
if (desktopFile) {
949-
if (flag & FindAssocFlag.onlyFirst) {
950-
return [desktopFile];
951-
}
952-
desktopFiles ~= desktopFile;
953-
}
954-
removed ~= desktopId;
951+
desktopIds ~= desktopId;
955952
}
956953
}
957954

955+
return desktopIds;
956+
}
957+
958+
private const(DesktopFile)[] findAssociatedApplicationsImpl(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, IDesktopFileProvider desktopFileProvider, FindAssocFlag flag = FindAssocFlag.none)
959+
{
960+
const(DesktopFile)[] desktopFiles;
961+
foreach(desktopId; listAssociatedApplicationsImpl(mimeType, mimeAppsListFiles, mimeInfoCacheFiles, flag)) {
962+
auto desktopFile = desktopFileProvider.getByDesktopId(desktopId);
963+
if (desktopFile && desktopFile.value("Exec").length != 0) {
964+
if (flag & FindAssocFlag.onlyFirst) {
965+
return [desktopFile];
966+
}
967+
desktopFiles ~= desktopFile;
968+
}
969+
}
958970
return desktopFiles;
959971
}
972+
/**
973+
* List associated applications for mimeType.
974+
* Params:
975+
* mimeType = MIME type or uri scheme handler in question.
976+
* mimeAppsListFiles = Range of $(D MimeAppsListFile) objects to use in searching.
977+
* mimeInfoCacheFiles = Range of $(D MimeInfoCacheFile) objects to use in searching.
978+
* Returns: Array of desktop ids of applications that are capable of opening of given MIME type or url of given scheme.
979+
* Note: It does not check if returned desktop ids point to valid .desktop files.
980+
* See_Also: $(D findAssociatedApplications)
981+
*/
982+
string[] listAssociatedApplications(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles) if(isForwardRange!ListRange && is(ElementType!ListRange : const(MimeAppsListFile))
983+
&& isForwardRange!CacheRange && is(ElementType!CacheRange : const(MimeInfoCacheFile)))
984+
{
985+
return listAssociatedApplicationsImpl(mimeType, mimeAppsListFiles, mimeInfoCacheFiles);
986+
}
987+
988+
/**
989+
* List all known associated applications for mimeType, including explicitly removed by user.
990+
* Params:
991+
* mimeType = MIME type or uri scheme handler in question.
992+
* mimeAppsListFiles = Range of $(D MimeAppsListFile) objects to use in searching.
993+
* mimeInfoCacheFiles = Range of $(D MimeInfoCacheFile) objects to use in searching.
994+
* Returns: Array of desktop ids of applications that are capable of opening of given MIME type or url of given scheme.
995+
* Note: It does not check if returned desktop ids point to valid .desktop files.
996+
* See_Also: $(D listAssociatedApplications), $(D findKnownAssociatedApplications)
997+
*/
998+
string[] listKnownAssociatedApplications(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles)
999+
if(isForwardRange!ListRange && is(ElementType!ListRange : const(MimeAppsListFile))
1000+
&& isForwardRange!CacheRange && is(ElementType!CacheRange : const(MimeInfoCacheFile)))
1001+
{
1002+
return listAssociatedApplicationsImpl(mimeType, mimeAppsListFiles, mimeInfoCacheFiles, FindAssocFlag.ignoreRemovedGroup);
1003+
}
1004+
1005+
/**
1006+
* List explicitily set default applications for mimeType.
1007+
* Params:
1008+
* mimeType = MIME type or uri scheme handler in question.
1009+
* mimeAppsListFiles = Range of $(D MimeAppsListFile) objects to use in searching.
1010+
* Returns: Array of desktop ids of default applications.
1011+
* Note: It does not check if returned desktop ids point to valid .desktop files.
1012+
* See_Also: $(D findDefaultApplication)
1013+
*/
1014+
string[] listDefaultApplications(ListRange)(string mimeType, ListRange mimeAppsListFiles)
1015+
if(isForwardRange!ListRange && is(ElementType!ListRange : const(MimeAppsListFile)))
1016+
{
1017+
string[] defaultApplications;
1018+
foreach(mimeAppsListFile; mimeAppsListFiles) {
1019+
if (mimeAppsListFile is null) {
1020+
continue;
1021+
}
1022+
auto defaultAppsGroup = mimeAppsListFile.defaultApplications();
1023+
if (defaultAppsGroup !is null) {
1024+
foreach(desktopId; defaultAppsGroup.appsForMimeType(mimeType)) {
1025+
defaultApplications ~= desktopId;
1026+
}
1027+
}
1028+
}
1029+
return defaultApplications;
1030+
}
9601031

9611032
/**
9621033
* Find associated applications for mimeType.
9631034
* Params:
9641035
* mimeType = MIME type or uri scheme handler in question.
9651036
* mimeAppsListFiles = Range of $(D MimeAppsListFile) objects to use in searching.
9661037
* mimeInfoCacheFiles = Range of $(D MimeInfoCacheFile) objects to use in searching.
967-
* desktopFileProvider = Desktop file provider instance.
968-
* Returns: Array of found $(B DesktopFile) object capable of opening file of given MIME type or url of given scheme.
1038+
* desktopFileProvider = Desktop file provider instance. Must be non-null.
1039+
* Returns: Array of found $(B DesktopFile) objects capable of opening file of given MIME type or url of given scheme.
9691040
* Note: If no applications found for this mimeType, you may consider to use this function on parent MIME type.
970-
* See_Also: $(LINK2 https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s03.html, Adding/removing associations)
1041+
* See_Also: $(LINK2 https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s03.html, Adding/removing associations), $(D findKnownAssociatedApplications), $(D listAssociatedApplications)
9711042
*/
9721043
const(DesktopFile)[] findAssociatedApplications(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, IDesktopFileProvider desktopFileProvider)
9731044
if(isForwardRange!ListRange && is(ElementType!ListRange : const(MimeAppsListFile))
@@ -997,10 +1068,13 @@ unittest
9971068
* mimeType = MIME type or uri scheme handler in question.
9981069
* mimeAppsListFiles = Range of $(D MimeAppsListFile) objects to use in searching.
9991070
* mimeInfoCacheFiles = Range of $(D MimeInfoCacheFile) objects to use in searching.
1000-
* desktopFileProvider = Desktop file provider instance.
1001-
* Returns: Array of found $(B DesktopFile) object capable of opening file of given MIME type or url of given scheme.
1071+
* desktopFileProvider = Desktop file provider instance. Must be non-null.
1072+
* Returns: Array of found $(B DesktopFile) objects capable of opening file of given MIME type or url of given scheme.
1073+
* See_Also: $(D findAssociatedApplications), $(D listKnownAssociatedApplications)
10021074
*/
1003-
const(DesktopFile)[] findKnownAssociatedApplications(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, IDesktopFileProvider desktopFileProvider)
1075+
const(DesktopFile)[] findKnownAssociatedApplications(ListRange, CacheRange)(string mimeType, ListRange mimeAppsListFiles, CacheRange mimeInfoCacheFiles, IDesktopFileProvider desktopFileProvider)
1076+
if(isForwardRange!ListRange && is(ElementType!ListRange : const(MimeAppsListFile))
1077+
&& isForwardRange!CacheRange && is(ElementType!CacheRange : const(MimeInfoCacheFile)))
10041078
in {
10051079
assert(desktopFileProvider !is null);
10061080
}
@@ -1036,18 +1110,10 @@ in {
10361110
assert(desktopFileProvider !is null);
10371111
}
10381112
body {
1039-
foreach(mimeAppsListFile; mimeAppsListFiles) {
1040-
if (mimeAppsListFile is null) {
1041-
continue;
1042-
}
1043-
auto defaultAppsGroup = mimeAppsListFile.defaultApplications();
1044-
if (defaultAppsGroup !is null) {
1045-
foreach(desktopId; defaultAppsGroup.appsForMimeType(mimeType)) {
1046-
auto desktopFile = desktopFileProvider.getByDesktopId(desktopId);
1047-
if (desktopFile !is null) {
1048-
return desktopFile;
1049-
}
1050-
}
1113+
foreach(desktopId; listDefaultApplications(mimeType, mimeAppsListFiles)) {
1114+
auto desktopFile = desktopFileProvider.getByDesktopId(desktopId);
1115+
if (desktopFile !is null && desktopFile.value("Exec").length != 0) {
1116+
return desktopFile;
10511117
}
10521118
}
10531119

@@ -1193,11 +1259,13 @@ static if (isFreedesktop)
11931259
{
11941260
/**
11951261
* Apply query for writable mimeapps.list files.
1196-
* For compatibility purposes this overwrites both $XDG_CONFIG_HOME/mimeapps.list and $XDG_DATA_HOME/applications/mimeapps.list
1262+
*
1263+
* For compatibility purposes this overwrites both $XDG_CONFIG_HOME/mimeapps.list and $XDG_DATA_HOME/applications/mimeapps.list.
1264+
*
1265+
* $(BLUE This function is Freedesktop only).
11971266
* See_Also: $(D writableMimeAppsListPaths)
1198-
* Warning: Since this library is in development this function should be used with care.
1199-
* Developer can't guarantee yet that it will not damage your file associations settings.
1200-
* Note: This function is available only on freedesktop.
1267+
* Warning: $(RED Since this library is in development this function should be used with care.
1268+
* Developer can't guarantee yet that it will not damage your file associations settings.)
12011269
*/
12021270
@safe void updateAssociations(ref AssociationUpdateQuery query)
12031271
{

test/applications/emacs.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=Emacs
33
Exec=emacs
4+
Type=Application

test/applications/geany.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=Geany
33
Exec=geany
4+
Type=Application

test/applications/gthumb.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=gThumb
33
Exec=gthumb
4+
Type=Application

test/applications/gwenview.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=Gwenview
33
Exec=gwenview
4+
Type=Application

test/applications/kate.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=Kate
33
Exec=kate
4+
Type=Application

test/applications/okular.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[Desktop Entry]
22
Name=Okular
33
Exec=okular
4+
Type=Application

0 commit comments

Comments
 (0)