2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include "applet-struct.h"
24
#include "applet-tips-dialog.h"
26
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data);
32
gchar **pKeyList; // keys of the current group
34
gint iNumTipGroup; // current group being displayed.
35
gint iNumTipKey; // current key being displayed.
36
GtkWidget *pCategoryCombo;
39
static void _cairo_dock_get_next_tip (CDTipsData *pTips)
41
pTips->iNumTipKey ++; // skip the current expander to go to the current label, which will be skipped in the first iteration.
42
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
47
if (pTips->iNumTipKey >= (gint) pTips->iNbKeys) // no more key, go to next group.
49
pTips->iNumTipGroup ++;
50
if (pTips->iNumTipGroup >= pTips->iNbGroups) // no more group, restart from first group.
51
pTips->iNumTipGroup = 0;
52
pTips->iNumTipKey = 0;
54
// since the group has changed, get the keys again.
55
g_strfreev (pTips->pKeyList);
56
cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
57
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
59
// and update the category in the comb
60
g_signal_handlers_block_matched (pTips->pCategoryCombo,
65
_on_tips_category_changed,
67
gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
68
g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
73
_on_tips_category_changed,
77
// check if the key is an expander widget.
78
const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
79
gchar *cKeyComment = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
80
bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER); // whether it's an expander.
85
static void _cairo_dock_get_previous_tip (CDTipsData *pTips)
89
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
94
if (pTips->iNumTipKey < 0) // no more key, go to previous group.
96
pTips->iNumTipGroup --;
97
if (pTips->iNumTipGroup < 0) // no more group, restart from the last group.
98
pTips->iNumTipGroup = pTips->iNbGroups - 1;
100
// since the group has changed, get the keys again.
101
g_strfreev (pTips->pKeyList);
102
cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
103
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
105
pTips->iNumTipKey = pTips->iNbKeys - 2;
107
// and update the category in the comb
108
g_signal_handlers_block_matched (pTips->pCategoryCombo,
113
_on_tips_category_changed,
115
gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
116
g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
121
_on_tips_category_changed,
125
// check if the key is an expander widget.
126
const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
127
gchar *cKeyComment = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
128
bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER); // whether it's an expander.
132
static gchar *_build_tip_text (CDTipsData *pTips)
134
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
135
const gchar *cKeyName1 = pTips->pKeyList[pTips->iNumTipKey];
136
const gchar *cKeyName2 = pTips->pKeyList[pTips->iNumTipKey+1];
139
guint iNbElements = 0;
141
const gchar *cHint1 = NULL; // points on the comment.
142
gchar **pAuthorizedValuesList1 = NULL;
143
gchar *cKeyComment1 = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName1, NULL);
144
cairo_dock_parse_key_comment (cKeyComment1, &iElementType, &iNbElements, &pAuthorizedValuesList1, &bAligned, &cHint1); // points on the comment.
146
const gchar *cHint2 = NULL;
147
gchar **pAuthorizedValuesList2 = NULL;
148
gchar *cKeyComment2 = g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName2, NULL);
149
const gchar *cText2 = cairo_dock_parse_key_comment (cKeyComment2, &iElementType, &iNbElements, &pAuthorizedValuesList2, &bAligned, &cHint2);
151
gchar *cText = g_strdup_printf ("<b>%s</b>\n\n<i>%s</i>\n\n%s",
152
_("Tips and Tricks"),
153
(pAuthorizedValuesList1 ? gettext (pAuthorizedValuesList1[0]) : ""),
156
g_strfreev (pAuthorizedValuesList1);
157
g_strfreev (pAuthorizedValuesList2);
158
g_free (cKeyComment1);
159
g_free (cKeyComment2);
162
static void _update_tip_text (CDTipsData *pTips, CairoDialog *pDialog)
164
gchar *cText = _build_tip_text (pTips);
166
cairo_dock_set_dialog_message (pDialog, cText);
170
static void _tips_dialog_action (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, CDTipsData *pTips, CairoDialog *pDialog)
172
cd_debug ("%s (%d)", __func__, iClickedButton);
173
if (iClickedButton == 2 || iClickedButton == -1) // click on "next", or Enter.
176
_cairo_dock_get_next_tip (pTips);
178
_update_tip_text (pTips, pDialog);
180
cairo_dock_dialog_reference (pDialog); // keep the dialog alive.
182
else if (iClickedButton == 1) // click on "previous"
184
// show the previous tip
185
_cairo_dock_get_previous_tip (pTips);
187
_update_tip_text (pTips, pDialog);
189
cairo_dock_dialog_reference (pDialog); // keep the dialog alive.
191
else // click on "close" or Escape
193
myData.iLastTipGroup = pTips->iNumTipGroup;
194
myData.iLastTipKey = pTips->iNumTipKey;
195
gchar *cConfFilePath = g_strdup_printf ("%s/.help", g_cCairoDockDataDir);
196
cairo_dock_update_conf_file (cConfFilePath,
197
G_TYPE_INT, "Last Tip", "group", pTips->iNumTipGroup,
198
G_TYPE_INT, "Last Tip", "key", pTips->iNumTipKey,
200
g_free (cConfFilePath);
202
cd_debug ("tips : %d/%d", pTips->iNumTipGroup, pTips->iNumTipKey);
204
static void _on_free_tips_dialog (CDTipsData *pTips)
206
g_key_file_free (pTips->pKeyFile);
207
g_strfreev (pTips->pGroupList);
208
g_strfreev (pTips->pKeyList);
212
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data)
214
CDTipsData *pTips = data[0];
215
CairoDialog *pDialog = data[1];
217
int iNumItem = gtk_combo_box_get_active (pWidget);
218
g_return_if_fail (iNumItem < pTips->iNbGroups);
220
pTips->iNumTipGroup = iNumItem;
222
// since the group has changed, get the keys again.
223
g_strfreev (pTips->pKeyList);
224
const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
225
pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
226
pTips->iNumTipKey = 0;
228
_update_tip_text (pTips, pDialog);
231
void cairo_dock_show_tips (void)
233
if (myData.iSidGetParams != 0)
236
// open the tips file
237
const gchar *cConfFilePath = CD_APPLET_MY_CONF_FILE;
238
GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
239
g_return_if_fail (pKeyFile != NULL);
242
gchar **pGroupList = g_key_file_get_groups (pKeyFile, &iNbGroups);
243
iNbGroups -= 4; // skip the last 4 groups (Troubleshooting and Contribute + Icon and Desklet).
244
g_return_if_fail (pGroupList != NULL && iNbGroups > 0);
246
// get the last displayed tip.
247
guint iNumTipGroup, iNumTipKey;
248
if (myData.iLastTipGroup < 0 || myData.iLastTipKey < 0) // first time we display a tip.
250
iNumTipGroup = iNumTipKey = 0;
254
iNumTipGroup = myData.iLastTipGroup;
255
iNumTipKey = myData.iLastTipKey;
256
if (iNumTipGroup >= iNbGroups) // be sure to stay inside the limits.
258
iNumTipGroup = iNbGroups - 1;
262
const gchar *cGroupName = pGroupList[iNumTipGroup];
265
gchar **pKeyList = g_key_file_get_keys (pKeyFile, cGroupName, &iNbKeys, NULL);
266
g_return_if_fail (pKeyList != NULL && iNbKeys > 0);
267
if (iNumTipKey >= iNbKeys) // be sure to stay inside the limits.
270
CDTipsData *pTips = g_new0 (CDTipsData, 1);
271
pTips->pKeyFile = pKeyFile;
272
pTips->pGroupList = pGroupList;
273
pTips->iNbGroups = iNbGroups;
274
pTips->pKeyList = pKeyList;
275
pTips->iNbKeys = iNbKeys;
276
pTips->iNumTipGroup = iNumTipGroup;
277
pTips->iNumTipKey = iNumTipKey;
279
// update to the next tip.
280
if (myData.iLastTipGroup >= 0 && myData.iLastTipKey >= 0) // a previous tip exist => take the next one;
281
_cairo_dock_get_next_tip (pTips);
283
// build a list of the available groups.
284
GtkWidget *pInteractiveWidget = _gtk_vbox_new (3);
285
#if (GTK_MAJOR_VERSION < 3 && GTK_MINOR_VERSION < 24)
286
GtkWidget *pComboBox = gtk_combo_box_new_text ();
288
GtkWidget *pComboBox = gtk_combo_box_text_new ();
291
for (i = 0; i < iNbGroups; i ++)
293
#if (GTK_MAJOR_VERSION < 3 && GTK_MINOR_VERSION < 24)
294
gtk_combo_box_append_text (GTK_COMBO_BOX (pComboBox), gettext (pGroupList[i]));
296
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pComboBox), gettext (pGroupList[i]));
299
gtk_combo_box_set_active (GTK_COMBO_BOX (pComboBox), pTips->iNumTipGroup);
300
pTips->pCategoryCombo = pComboBox;
301
static gpointer data_combo[2];
302
data_combo[0] = pTips; // the 2nd data is the dialog, we'll set it after we make it.
303
g_signal_connect (G_OBJECT (pComboBox), "changed", G_CALLBACK(_on_tips_category_changed), data_combo);
304
GtkWidget *pJumpBox = _gtk_hbox_new (3);
305
GtkWidget *label = gtk_label_new (_("Category"));
306
cairo_dock_set_dialog_widget_text_color (label);
307
gtk_box_pack_end (GTK_BOX (pJumpBox), pComboBox, FALSE, FALSE, 0);
308
gtk_box_pack_end (GTK_BOX (pJumpBox), label, FALSE, FALSE, 0);
309
gtk_box_pack_start (GTK_BOX (pInteractiveWidget), pJumpBox, FALSE, FALSE, 0);
312
gchar *cText = _build_tip_text (pTips);
313
CairoDialogAttribute attr;
314
memset (&attr, 0, sizeof (CairoDialogAttribute));
316
attr.cImageFilePath = NULL;
317
attr.pInteractiveWidget = pInteractiveWidget;
318
attr.pActionFunc = (CairoDockActionOnAnswerFunc)_tips_dialog_action;
319
attr.pUserData = pTips;
320
attr.pFreeDataFunc = (GFreeFunc)_on_free_tips_dialog;
321
const gchar *cButtons[] = {"cancel", GTK_STOCK_GO_FORWARD"-rtl", GTK_STOCK_GO_FORWARD"-ltr", NULL};
322
attr.cButtonsImage = cButtons;
323
attr.bUseMarkup = TRUE;
325
CairoDialog *pTipsDialog = cairo_dock_build_dialog (&attr, myIcon, myContainer);
327
data_combo[1] = pTipsDialog;