1 /*
2 * vala-panel-appmenu
3 * Copyright (C) 2018 Konstantin Pugin <ria.freelander@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "section.h"
20 #include "item.h"
21 enum
22 {
23 PROP_NULL = 0,
24 PROP_PARENT_MODEL = 1,
25 PROP_SECTION_INDEX = 2,
26 NUM_PROPS
27 };
28
29 static GParamSpec *properties[NUM_PROPS] = { NULL };
30
G_DEFINE_TYPE(DBusMenuSectionModel,dbus_menu_section_model,G_TYPE_MENU_MODEL)31 G_DEFINE_TYPE(DBusMenuSectionModel, dbus_menu_section_model, G_TYPE_MENU_MODEL)
32
33 static int dbus_menu_section_model_is_mutable(GMenuModel *model)
34 {
35 return true;
36 }
37
dbus_menu_section_model_get_n_items(GMenuModel * model)38 static gint dbus_menu_section_model_get_n_items(GMenuModel *model)
39 {
40 DBusMenuSectionModel *menu = DBUS_MENU_SECTION_MODEL(model);
41 GSequence *items = dbus_menu_model_items(menu->parent_model);
42 int begin = 0, end = -1;
43 for (GSequenceIter *iter = g_sequence_get_begin_iter(items); !g_sequence_iter_is_end(iter);
44 iter = g_sequence_iter_next(iter))
45 {
46 DBusMenuItem *item = (DBusMenuItem *)g_sequence_get(iter);
47 if (item->section_num == menu->section_index && item->place == -1)
48 begin = g_sequence_iter_get_position(iter);
49 end = g_sequence_iter_get_position(iter);
50 if (item->section_num == menu->section_index + 1 && item->place == -1)
51 {
52 end--;
53 break;
54 }
55 }
56 return end - begin;
57 }
58
dbus_menu_section_model_get_item_attributes(GMenuModel * model,gint position,GHashTable ** table)59 static void dbus_menu_section_model_get_item_attributes(GMenuModel *model, gint position,
60 GHashTable **table)
61 {
62 DBusMenuSectionModel *menu = DBUS_MENU_SECTION_MODEL(model);
63 GSequence *items = dbus_menu_model_items(menu->parent_model);
64 for (GSequenceIter *iter = g_sequence_get_begin_iter(items); !g_sequence_iter_is_end(iter);
65 iter = g_sequence_iter_next(iter))
66 {
67 DBusMenuItem *item = (DBusMenuItem *)g_sequence_get(iter);
68 if (item->section_num == menu->section_index && item->place == position)
69 {
70 *table = g_hash_table_ref(item->attrs);
71 return;
72 }
73 }
74 }
75
dbus_menu_section_model_get_item_links(GMenuModel * model,gint position,GHashTable ** table)76 static void dbus_menu_section_model_get_item_links(GMenuModel *model, gint position,
77 GHashTable **table)
78 {
79 DBusMenuSectionModel *menu = DBUS_MENU_SECTION_MODEL(model);
80 GSequence *items = dbus_menu_model_items(menu->parent_model);
81 for (GSequenceIter *iter = g_sequence_get_begin_iter(items); !g_sequence_iter_is_end(iter);
82 iter = g_sequence_iter_next(iter))
83 {
84 DBusMenuItem *item = (DBusMenuItem *)g_sequence_get(iter);
85 if (item->section_num == menu->section_index && item->place == position)
86 {
87 if (g_hash_table_contains(item->links, G_MENU_LINK_SECTION))
88 g_warning("Item has section, but should not\n");
89 *table = g_hash_table_ref(item->links);
90 return;
91 }
92 }
93 }
dbus_menu_section_model_init(DBusMenuSectionModel * menu)94 static void dbus_menu_section_model_init(DBusMenuSectionModel *menu)
95 {
96 menu->parent_model = NULL;
97 }
98
dbus_menu_section_model_finalize(GObject * object)99 static void dbus_menu_section_model_finalize(GObject *object)
100 {
101 G_OBJECT_CLASS(dbus_menu_section_model_parent_class)->finalize(object);
102 }
103
install_properties(GObjectClass * object_class)104 static void install_properties(GObjectClass *object_class)
105 {
106 properties[PROP_PARENT_MODEL] =
107 g_param_spec_object("parent-model",
108 "parent-model",
109 "parent-model",
110 dbus_menu_model_get_type(),
111 (GParamFlags)(G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE |
112 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
113
114 properties[PROP_SECTION_INDEX] =
115 g_param_spec_uint("section-index",
116 "section-index",
117 "section-index",
118 0,
119 UINT_MAX,
120 0,
121 (GParamFlags)(G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
122 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
123
124 g_object_class_install_properties(object_class, NUM_PROPS, properties);
125 }
126
dbus_menu_section_model_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)127 static void dbus_menu_section_model_set_property(GObject *object, guint property_id,
128 const GValue *value, GParamSpec *pspec)
129 {
130 DBusMenuSectionModel *menu = DBUS_MENU_SECTION_MODEL(object);
131
132 switch (property_id)
133 {
134 case PROP_PARENT_MODEL:
135 menu->parent_model = DBUS_MENU_MODEL(g_value_get_object(value));
136 break;
137 case PROP_SECTION_INDEX:
138 menu->section_index = g_value_get_uint(value);
139 break;
140 default:
141 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
142 break;
143 }
144 }
145
dbus_menu_section_model_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)146 static void dbus_menu_section_model_get_property(GObject *object, guint property_id, GValue *value,
147 GParamSpec *pspec)
148 {
149 DBusMenuSectionModel *menu = DBUS_MENU_SECTION_MODEL(object);
150
151 switch (property_id)
152 {
153 case PROP_PARENT_MODEL:
154 g_value_set_object(value, menu->parent_model);
155 break;
156 case PROP_SECTION_INDEX:
157 g_value_set_uint(value, menu->section_index);
158 break;
159 default:
160 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
161 break;
162 }
163 }
164
dbus_menu_section_model_constructed(GObject * object)165 static void dbus_menu_section_model_constructed(GObject *object)
166 {
167 G_OBJECT_CLASS(dbus_menu_section_model_parent_class)->constructed(object);
168 }
169
dbus_menu_section_model_class_init(DBusMenuSectionModelClass * klass)170 static void dbus_menu_section_model_class_init(DBusMenuSectionModelClass *klass)
171 {
172 GMenuModelClass *model_class = G_MENU_MODEL_CLASS(klass);
173 GObjectClass *object_class = G_OBJECT_CLASS(klass);
174
175 object_class->finalize = dbus_menu_section_model_finalize;
176 object_class->set_property = dbus_menu_section_model_set_property;
177 object_class->get_property = dbus_menu_section_model_get_property;
178 object_class->constructed = dbus_menu_section_model_constructed;
179
180 model_class->is_mutable = dbus_menu_section_model_is_mutable;
181 model_class->get_n_items = dbus_menu_section_model_get_n_items;
182 model_class->get_item_attributes = dbus_menu_section_model_get_item_attributes;
183 model_class->get_item_links = dbus_menu_section_model_get_item_links;
184 install_properties(object_class);
185 }
186
dbus_menu_section_model_new(DBusMenuModel * parent,int section_index)187 DBusMenuSectionModel *dbus_menu_section_model_new(DBusMenuModel *parent, int section_index)
188 {
189 return DBUS_MENU_SECTION_MODEL(g_object_new(dbus_menu_section_model_get_type(),
190 "parent-model",
191 parent,
192 "section-index",
193 section_index,
194 NULL));
195 }
196