aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils.c
blob: a05363887d842ab238d7f2aa09f5cb571d8be8be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
 * Copyright (C) 2021 Collabora Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gio/gio.h>

#include "utils.h"

/* Search by descending quality level */
static const gchar *icon_sizes[] = {
    "scalable",
    "512x512",
    "256x256",
    "192x192",
    "128x128",
    "96x96",
    "72x72",
    "64x64",
    "48x48",
    "32x32",
    "24x24",
    "16x16",
    "symbolic",
    NULL
};

/*
 * Recursively search the `base_path` folder for a file whose name
 * starts with `icon_name`: this way we don't care about the extension
 * and can also get files with an extended name (for example,
 * "`icon_name`-symbolic.png" would still be recognized as a valid match)
 */
static gchar *find_icon(const gchar *base_path, const gchar *icon_name)
{
    g_autoptr(GFile) base_dir = g_file_new_for_path(base_path);
    g_autoptr(GFileEnumerator) child_list =
            g_file_enumerate_children(base_dir, "*", G_FILE_QUERY_INFO_NONE,
                                      NULL, NULL);

    if (!child_list)
        return NULL;

    while (TRUE) {
        GFile *current_file;
        GFileInfo *current_file_info;

        g_file_enumerator_iterate(child_list, &current_file_info,
                                  &current_file, NULL, NULL);
        if (!current_file_info || !current_file)
            break;

        if (g_file_info_get_file_type(current_file_info) == G_FILE_TYPE_DIRECTORY) {
            gchar *icon_path = find_icon(g_file_get_path(current_file), icon_name);
            if (icon_path)
                return icon_path;
        } else if (g_str_has_prefix(g_file_get_basename(current_file), icon_name)) {
            return g_strdup(g_file_get_path(current_file));
        }
    }

    return NULL;
}

/*
 * Search through a list of folders for the `icon_name` icon file
 */
gchar *applaunchd_utils_get_icon(GStrv dir_list, const gchar *icon_name)
{
    gchar *icon_path = NULL;

    for (GStrv base_path = dir_list; *base_path != NULL ; base_path++) {
        g_autoptr(GFile) base_dir = g_file_new_build_filename(*base_path,
                                                              "icons", NULL);

        g_autoptr(GFileEnumerator) child_list =
                g_file_enumerate_children(base_dir, "standard::type=directory",
                                          G_FILE_QUERY_INFO_NONE, NULL, NULL);

        if (!child_list)
            continue;

        while (TRUE) {
            GFile *theme_dir;
            g_file_enumerator_iterate(child_list, NULL, &theme_dir,
                                      NULL, NULL);
            if (!theme_dir)
                break;

            for (gint i = 0; icon_sizes[i]; i++) {
                g_autofree gchar *theme_path =
                        g_build_filename(g_file_get_path(theme_dir),
                                         icon_sizes[i], NULL);
                icon_path = find_icon(theme_path, icon_name);
                if (icon_path)
                    return icon_path;
            }
        }
    }

    return NULL;
}