~helene-verhaeghe27/cairo-dock-core/bugfix

« back to all changes in this revision

Viewing changes to src/cairo-dock.c

  • Committer: Fabrice Rey
  • Date: 2011-07-02 23:42:38 UTC
  • Revision ID: fabounet03@gmail.com-20110702234238-ytaffs7gts947ui4
updated the Help module to make it a real applet + updated its hints. => 2.4.0-beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
**    If you don't know what that means take a look at:
28
28
**       http://www.gnu.org/licenses/licenses.html#GPL
29
29
**
 
30
*********************** VERSION 0 (2006) *********************
 
31
**
30
32
** Original idea :
31
 
**    Mirco Mueller, June 2006.
32
 
**
33
 
*********************** VERSION 0 (2006)*********************
34
 
** author(s):
35
 
**    Mirco "MacSlow" Mueller <macslow@bangang.de>
 
33
**    Mirco "MacSlow" Mueller <macslow@bangang.de>, June 2006.
 
34
** With the help of:
36
35
**    Behdad Esfahbod <behdad@behdad.org>
37
36
**    David Reveman <davidr@novell.com>
38
37
**    Karl Lattimer <karl@qdh.org.uk>
39
 
**
40
 
** notes :
41
 
**    Originally conceived as a stress-test for cairo, librsvg, and glitz.
42
 
**
43
 
** notes from original author:
44
 
**
45
 
**    I just know that some folks will bug me regarding this, so... yes there's
46
 
**    nearly everything hard-coded, it is not nice, it is not very usable for
47
 
**    easily (without any hard work) making a full dock-like application out of
48
 
**    this, please don't email me asking to me to do so... for everybody else
49
 
**    feel free to make use of it beyond this being a small but heavy stress
50
 
**    test. I've written this on an Ubuntu-6.06 box running Xgl/compiz. The
51
 
**    icons used are from the tango-project...
52
 
**
53
 
**        http://tango-project.org/
54
 
**
55
 
**    Over the last couple of days Behdad and David helped me (MacSlow) out a
56
 
**    great deal by sending me additional tweaked and optimized versions. I've
57
 
**    now merged all that with my recent additions.
58
 
**
59
 
*********************** VERSION 0.1.0 and above (2007-2011)*********************
 
38
** Originally conceived as a stress-test for cairo, librsvg, and glitz.
 
39
**
 
40
*********************** VERSION 0.1 and above (2007-2011) *********************
60
41
**
61
42
** author(s) :
62
43
**     Fabrice Rey <fabounet@glx-dock.org>
63
 
**
64
 
** notes :
65
 
**     I've completely rewritten the calculation part, and the callback system.
66
 
**     Plus added a conf file that allows to dynamically modify most of the parameters.
67
 
**     Plus a visible zone that make the hiding/showing more friendly.
68
 
**     Plus a menu and the drag'n'drop ability.
69
 
**     Also I've separated functions in several files in order to make the code more readable.
70
 
**     Now it sems more like a real dock !
71
 
**
72
 
**     Edit : plus a taskbar, plus an applet system,
73
 
**            plus the container ability, plus different views, plus the top and vertical position, ...
74
 
**
 
44
** With the help of:
 
45
**     A lot of people !!!
75
46
**
76
47
*******************************************************************************/
77
48
 
107
78
#include "cairo-dock-file-manager.h"
108
79
#include "cairo-dock-log.h"
109
80
#include "cairo-dock-draw-opengl.h"
110
 
#include "cairo-dock-launcher-manager.h"  // cairo_dock_launch_command_sync
 
81
#include "cairo-dock-launcher-manager.h"  // cairo_dock_launch_command
111
82
 
112
83
#include "cairo-dock-gui-manager.h"
113
84
#include "cairo-dock-gui-items.h"
114
85
#include "cairo-dock-gui-backend.h"
115
86
#include "cairo-dock-user-interaction.h"
 
87
#include "cairo-dock-help.h"
116
88
#include "cairo-dock-core.h"
117
89
 
118
90
//#define CAIRO_DOCK_THEME_SERVER "http://themes.glx-dock.org"
145
117
gboolean g_bForceCairo = FALSE;
146
118
gboolean g_bLocked;
147
119
 
 
120
static gboolean s_bSucessfulLaunch = FALSE;
148
121
static gchar *s_cLaunchCommand = NULL;
149
122
static gchar *s_cLastVersion = NULL;
150
 
gboolean g_bEnterHelpOnce = FALSE;
151
 
static gboolean s_bShowTips = TRUE;
152
 
static int s_iLastTipGroup = -1;
153
 
static int s_iLastTipKey = -1;
154
123
static gchar *s_cDefaulBackend = NULL;
155
 
static gboolean s_bTestComposite = TRUE;
156
124
static gint s_iGuiMode = 0;  // 0 = simple mode, 1 = advanced mode
157
125
static gint s_iLastYear = 0;
158
126
static void (*s_activate_composite) (gboolean) = NULL;
159
127
 
160
 
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data);
161
 
 
162
 
static void _set_metacity_composite (gboolean bActive)
163
 
{
164
 
        int r;
165
 
        if (bActive)
166
 
                r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool true");
167
 
        else
168
 
                r = system ("gconftool-2 -s '/apps/metacity/general/compositing_manager' --type bool false");
169
 
}
170
 
 
171
 
static void _set_xfwm_composite (gboolean bActive)
172
 
{
173
 
        int r;
174
 
        if (bActive)
175
 
                r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'");
176
 
        else
177
 
                r = system ("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'");
178
 
}
179
 
 
180
 
static void _set_kwin_composite (gboolean bActive)
181
 
{
182
 
        int r;
183
 
        if (bActive)
184
 
                r = system ("[ \"$(qdbus org.kde.kwin /KWin compositingActive)\" == \"false\" ] && qdbus org.kde.kwin /KWin toggleCompositing");  // not active, so activating
185
 
        else
186
 
                r = system ("[ \"$(qdbus org.kde.kwin /KWin compositingActive)\" == \"true\" ] && qdbus org.kde.kwin /KWin toggleCompositing");  // active, so deactivating
187
 
}
188
 
 
189
 
static inline void _cancel_wm_composite (void)
190
 
{
191
 
        s_activate_composite (FALSE);
192
 
}
193
 
static void _accept_wm_composite (int iClickedButton, GtkWidget *pInteractiveWidget, gpointer data, CairoDialog *pDialog)
194
 
{
195
 
        cd_debug ("%s (%d)", __func__, iClickedButton);
196
 
        if (iClickedButton == 1 || iClickedButton == -2)  // clic explicite sur "cancel", ou Echap ou auto-delete.
197
 
        {
198
 
                _cancel_wm_composite ();
199
 
        }
200
 
        gboolean *bAccepted = data;
201
 
        *bAccepted = TRUE;  // l'utilisateur a valide son choix.
202
 
}
203
 
static void _on_free_wm_dialog (gpointer data)
204
 
{
205
 
        gboolean *bAccepted = data;
206
 
        cd_debug ("%s (%d)", __func__, *bAccepted);
207
 
        if (! *bAccepted)  // le dialogue s'est detruit sans que l'utilisateur n'ait valide la question => on annule tout.
208
 
        {
209
 
                _cancel_wm_composite ();
210
 
        }
211
 
        g_free (data);
212
 
}
213
 
 
214
 
static void _toggle_remember_choice (GtkCheckButton *pButton, GtkWidget *pDialog)
215
 
{
216
 
        g_object_set_data (G_OBJECT (pDialog), "remember", GINT_TO_POINTER (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pButton))));
217
 
}
218
128
static gboolean _cairo_dock_successful_launch (gpointer data)
219
129
{
 
130
        // successful launch, remove the maintenance mode from the command line.
220
131
        if (g_str_has_suffix (s_cLaunchCommand, " -m"))
221
132
                s_cLaunchCommand[strlen (s_cLaunchCommand)-3] = '\0';  // on enleve le mode maintenance.
222
 
        
223
 
        //\___________________ On teste le composite maintenant (au demarrage, le composite manager peut ne pas etre lance).
224
 
        if (s_bTestComposite)
225
 
        {
226
 
                GdkScreen *pScreen = gdk_screen_get_default ();
227
 
                if (! myContainersParam.bUseFakeTransparency && ! gdk_screen_is_composited (pScreen))
228
 
                {
229
 
                        cd_warning ("no composite manager found");
230
 
                        // find the current WM.
231
 
                        gchar *cPsef = cairo_dock_launch_command_sync ("pgrep metacity");  // 'ps' ne marche pas, il faut le lancer dans un script :-/
232
 
                        if (cPsef != NULL && *cPsef != '\0')
233
 
                        {
234
 
                                s_activate_composite = _set_metacity_composite;
235
 
                        }
236
 
                        else
237
 
                        {
238
 
                                cPsef = cairo_dock_launch_command_sync ("pgrep xfwm");
239
 
                                if (cPsef != NULL && *cPsef != '\0')
240
 
                                {
241
 
                                        s_activate_composite = _set_xfwm_composite;
242
 
                                }
243
 
                                else
244
 
                                {
245
 
                                        cPsef = cairo_dock_launch_command_sync ("pgrep kwin");
246
 
                                        if (cPsef != NULL && *cPsef != '\0')
247
 
                                        {
248
 
                                                s_activate_composite = _set_kwin_composite;
249
 
                                        }
250
 
                                }
251
 
                        }
252
 
                        
253
 
                        // if the WM can handle the composite, ask the user if he wants to activate it.
254
 
                        if (s_activate_composite != NULL)  // the WM can activate the composite.
255
 
                        {
256
 
                                Icon *pIcon = cairo_dock_get_dialogless_icon ();
257
 
                                GtkWidget *pAskBox = gtk_hbox_new (FALSE, 3);
258
 
                                GtkWidget *label = gtk_label_new (_("Don't ask me any more"));
259
 
                                cairo_dock_set_dialog_widget_text_color (label);
260
 
                                GtkWidget *pCheckBox = gtk_check_button_new ();
261
 
                                gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
262
 
                                gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
263
 
                                g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_toggle_remember_choice), pAskBox);
264
 
                                int iClickedButton = cairo_dock_show_dialog_and_wait (_("To remove the black rectangle around the dock, you need to activate a composite manager.\nDo you want to activate it now?"), pIcon, CAIRO_CONTAINER (g_pMainDock), 0., NULL, pAskBox);
265
 
                                
266
 
                                gboolean bRememberChoice = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pCheckBox));
267
 
                                gtk_widget_destroy (pAskBox); // le widget survit a un dialogue bloquant.
268
 
                                if (bRememberChoice)
269
 
                                {
270
 
                                        s_bTestComposite = FALSE;
271
 
                                }
272
 
                                if (iClickedButton == 0 || iClickedButton == -1)  // ok or Enter.
273
 
                                {
274
 
                                        s_activate_composite (TRUE);
275
 
                                        pIcon = cairo_dock_get_dialogless_icon ();
276
 
                                        cairo_dock_show_dialog_full (_("Do you want to keep this setting?\nIn 15 seconds, the previous setting will be restored."), pIcon, CAIRO_CONTAINER (g_pMainDock), 15e3, NULL, NULL, (CairoDockActionOnAnswerFunc) _accept_wm_composite, g_new0 (gboolean, 1), (GFreeFunc)_on_free_wm_dialog);
277
 
                                }
278
 
                        }
279
 
                        else  // sinon il a droit a un "message a caractere informatif".
280
 
                        {
281
 
                                cairo_dock_show_general_message (_("To remove the black rectangle around the dock, you will need to activate a composite manager.\nFor instance, this can be done by activating desktop effects, launching Compiz, or activating the composition in Metacity.\nIf your machine can't support composition, Cairo-Dock can emulate it. This option is in the 'System' module of the configuration, at the bottom of the page."), 0);
282
 
                        }
283
 
                        g_free (cPsef);
284
 
                }
285
 
                else  // a priori peu utile de le retester, surtout que le composite risque de ne pas etre actif tout de suite au demarrage.
286
 
                {
287
 
                        s_bTestComposite = FALSE;
288
 
                }
289
 
                
290
 
                if (! s_bTestComposite)
291
 
                {
292
 
                        gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
293
 
                        cairo_dock_update_conf_file (cConfFilePath,
294
 
                                G_TYPE_BOOLEAN, "Launch", "test composite", s_bTestComposite,
295
 
                                G_TYPE_INVALID);
296
 
                        g_free (cConfFilePath);
297
 
                }
298
 
        }
299
 
        
 
133
        s_bSucessfulLaunch = TRUE;
 
134
        
 
135
        // new year greetings.
300
136
        time_t t = time (NULL);
301
137
        struct tm st;
302
138
        localtime_r (&t, &st);
303
139
        
304
 
        if (st.tm_mday <= 15 && st.tm_mon == 0 && s_iLastYear < st.tm_year + 1900)  // 2 premieres semaines de janvier.
 
140
        if (!data && st.tm_mday <= 15 && st.tm_mon == 0 && s_iLastYear < st.tm_year + 1900)  // first 2 weeks of january + not first launch
305
141
        {
306
142
                s_iLastYear = st.tm_year + 1900;
307
143
                gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
365
201
        return FALSE;  // TRUE <=> ne pas detruire la fenetre.
366
202
}
367
203
 
368
 
static void _entered_help_once (CairoDockModuleInstance *pInstance, GKeyFile *pKeyFile)
369
 
{
370
 
        if (!g_bEnterHelpOnce)
371
 
        {
372
 
                g_bEnterHelpOnce = TRUE;
373
 
                gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
374
 
                cairo_dock_update_conf_file (cConfFilePath,
375
 
                        G_TYPE_BOOLEAN, "Help", "entered once", g_bEnterHelpOnce,
376
 
                        G_TYPE_INVALID);
377
 
                g_free (cConfFilePath);
378
 
        }
379
 
}
380
 
static void _register_help_module (void)
381
 
{
382
 
        //\________________ ceci est un vilain hack ...mais je trouvais ca lourd de compiler un truc qui n'a aucun code, et puis comme ca on a l'aide meme sans les plug-ins.
383
 
        CairoDockModule *pHelpModule = g_new0 (CairoDockModule, 1);
384
 
        CairoDockVisitCard *pVisitCard = g_new0 (CairoDockVisitCard, 1);
385
 
        pVisitCard->cModuleName = "Help";
386
 
        pVisitCard->cTitle = _("Help");
387
 
        pVisitCard->iMajorVersionNeeded = 2;
388
 
        pVisitCard->iMinorVersionNeeded = 0;
389
 
        pVisitCard->iMicroVersionNeeded = 0;
390
 
        pVisitCard->cPreviewFilePath = NULL;
391
 
        pVisitCard->cGettextDomain = NULL;
392
 
        pVisitCard->cDockVersionOnCompilation = CAIRO_DOCK_VERSION;
393
 
        pVisitCard->cUserDataDir = "help";
394
 
        pVisitCard->cShareDataDir = CAIRO_DOCK_SHARE_DATA_DIR;
395
 
        pVisitCard->cConfFileName = "help.conf";
396
 
        pVisitCard->cModuleVersion = "0.1.2";
397
 
        pVisitCard->iCategory = CAIRO_DOCK_CATEGORY_BEHAVIOR;
398
 
        pVisitCard->cIconFilePath = CAIRO_DOCK_SHARE_DATA_DIR"/icon-help.svg";
399
 
        pVisitCard->iSizeOfConfig = 0;
400
 
        pVisitCard->iSizeOfData = 0;
401
 
        pVisitCard->cDescription = N_("A useful FAQ which also contains a lot of hints.\nRoll your mouse over a sentence to make helpful popups appear.");
402
 
        pVisitCard->cAuthor = "Fabounet";
403
 
        
404
 
        CairoDockModuleInterface *pInterface = g_new0 (CairoDockModuleInterface, 1);
405
 
        pInterface->load_custom_widget = _entered_help_once;
406
 
        
407
 
        pHelpModule->pVisitCard = pVisitCard;
408
 
        pHelpModule->pInterface = pInterface;
409
 
        cairo_dock_register_module (pHelpModule);  // il sera vu par le modules-manager comme un module auto-loaded. 
410
 
}
411
 
 
412
 
 
413
 
typedef struct {
414
 
        GKeyFile *pKeyFile;
415
 
        gchar **pGroupList;
416
 
        gint iNbGroups;
417
 
        gchar **pKeyList;  // keys of the current group
418
 
        gint iNbKeys;
419
 
        gint iNumTipGroup;  // current group being displayed.
420
 
        gint iNumTipKey;  // current key being displayed.
421
 
        gboolean bSkipTips;
422
 
        GtkWidget *pCategoryCombo;
423
 
        } CDTipsData;
424
 
 
425
 
static void _cairo_dock_get_next_tip (CDTipsData *pTips)
426
 
{
427
 
        pTips->iNumTipKey ++;  // skip the current expander to go to the current label, which will be skipped in the first iteration.
428
 
        const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
429
 
        gboolean bOk;
430
 
        do
431
 
        {
432
 
                pTips->iNumTipKey ++;
433
 
                if (pTips->iNumTipKey >= pTips->iNbKeys)  // no more key, go to next group.
434
 
                {
435
 
                        pTips->iNumTipGroup ++;
436
 
                        if (pTips->iNumTipGroup >= pTips->iNbGroups)  // no more group, restart from first group.
437
 
                                pTips->iNumTipGroup = 0;
438
 
                        pTips->iNumTipKey = 0;
439
 
                        
440
 
                        // since the group has changed, get the keys again.
441
 
                        g_strfreev (pTips->pKeyList);
442
 
                        cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
443
 
                        pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
444
 
                        
445
 
                        // and update the category in the comb
446
 
                        g_signal_handlers_block_matched (pTips->pCategoryCombo,
447
 
                                G_SIGNAL_MATCH_FUNC,
448
 
                                0,
449
 
                                0,
450
 
                                0,
451
 
                                _on_tips_category_changed,
452
 
                                NULL);
453
 
                        gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
454
 
                        g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
455
 
                                G_SIGNAL_MATCH_FUNC,
456
 
                                0,
457
 
                                0,
458
 
                                0,
459
 
                                _on_tips_category_changed,
460
 
                                NULL);
461
 
                }
462
 
                
463
 
                // check if the key is an expander widget.
464
 
                const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
465
 
                gchar *cKeyComment =  g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
466
 
                bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER);  // whether it's an expander.
467
 
                g_free (cKeyComment);
468
 
        } while (!bOk);
469
 
}
470
 
 
471
 
static void _cairo_dock_get_previous_tip (CDTipsData *pTips)
472
 
{
473
 
        pTips->iNumTipKey --;
474
 
        
475
 
        const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
476
 
        gboolean bOk;
477
 
        do
478
 
        {
479
 
                pTips->iNumTipKey --;
480
 
                if (pTips->iNumTipKey < 0)  // no more key, go to previous group.
481
 
                {
482
 
                        pTips->iNumTipGroup --;
483
 
                        if (pTips->iNumTipGroup < 0)  // no more group, restart from the last group.
484
 
                                pTips->iNumTipGroup = pTips->iNbGroups - 1;
485
 
                        
486
 
                        // since the group has changed, get the keys again.
487
 
                        g_strfreev (pTips->pKeyList);
488
 
                        cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
489
 
                        pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
490
 
 
491
 
                        pTips->iNumTipKey = pTips->iNbKeys - 2;
492
 
                        
493
 
                        // and update the category in the comb
494
 
                        g_signal_handlers_block_matched (pTips->pCategoryCombo,
495
 
                                G_SIGNAL_MATCH_FUNC,
496
 
                                0,
497
 
                                0,
498
 
                                0,
499
 
                                _on_tips_category_changed,
500
 
                                NULL);
501
 
                        gtk_combo_box_set_active (GTK_COMBO_BOX (pTips->pCategoryCombo), pTips->iNumTipGroup);
502
 
                        g_signal_handlers_unblock_matched (pTips->pCategoryCombo,
503
 
                                G_SIGNAL_MATCH_FUNC,
504
 
                                0,
505
 
                                0,
506
 
                                0,
507
 
                                _on_tips_category_changed,
508
 
                                NULL);
509
 
                }
510
 
                
511
 
                // check if the key is an expander widget.
512
 
                const gchar *cKeyName = pTips->pKeyList[pTips->iNumTipKey];
513
 
                gchar *cKeyComment =  g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName, NULL);
514
 
                bOk = (cKeyComment && *cKeyComment == CAIRO_DOCK_WIDGET_EXPANDER);  // whether it's an expander.
515
 
        } while (!bOk);
516
 
}
517
 
 
518
 
static gchar *_build_tip_text (CDTipsData *pTips)
519
 
{
520
 
        const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
521
 
        const gchar *cKeyName1 = pTips->pKeyList[pTips->iNumTipKey];
522
 
        const gchar *cKeyName2 = pTips->pKeyList[pTips->iNumTipKey+1];
523
 
        
524
 
        char iElementType;
525
 
        guint iNbElements = 0;
526
 
        gboolean bAligned;
527
 
        const gchar *cHint1 = NULL;  // points on the comment.
528
 
        gchar **pAuthorizedValuesList1 = NULL;
529
 
        gchar *cKeyComment1 =  g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName1, NULL);
530
 
        const gchar *cText1 = cairo_dock_parse_key_comment (cKeyComment1, &iElementType, &iNbElements, &pAuthorizedValuesList1, &bAligned, &cHint1);  // points on the comment.
531
 
        
532
 
        const gchar *cHint2 = NULL;
533
 
        gchar **pAuthorizedValuesList2 = NULL;
534
 
        gchar *cKeyComment2 =  g_key_file_get_comment (pTips->pKeyFile, cGroupName, cKeyName2, NULL);
535
 
        const gchar *cText2 = cairo_dock_parse_key_comment (cKeyComment2, &iElementType, &iNbElements, &pAuthorizedValuesList2, &bAligned, &cHint2);
536
 
        
537
 
        gchar *cText = g_strdup_printf ("<b>%s</b>\n\n<i>%s</i>\n\n%s",
538
 
                _("Tips and Tricks"),
539
 
                gettext (pAuthorizedValuesList1?pAuthorizedValuesList1[0]:""),
540
 
                cText2);
541
 
        
542
 
        g_strfreev (pAuthorizedValuesList1);
543
 
        g_strfreev (pAuthorizedValuesList2);
544
 
        g_free (cKeyComment1);
545
 
        g_free (cKeyComment2);
546
 
        return cText;
547
 
}
548
 
static void _update_tip_text (CDTipsData *pTips, CairoDialog *pDialog)
549
 
{
550
 
        gchar *cText = _build_tip_text (pTips);
551
 
        
552
 
        myDialogsParam.dialogTextDescription.bUseMarkup = TRUE;
553
 
        cairo_dock_set_dialog_message (pDialog, cText);
554
 
        myDialogsParam.dialogTextDescription.bUseMarkup = FALSE;
555
 
        
556
 
        g_free (cText);
557
 
}
558
 
static void _tips_dialog_action (int iClickedButton, GtkWidget *pInteractiveWidget, CDTipsData *pTips, CairoDialog *pDialog)
559
 
{
560
 
        cd_debug ("%s (%d)", __func__, iClickedButton);
561
 
        if (iClickedButton == 2 || iClickedButton == -1)  // click on "next", or Enter.
562
 
        {
563
 
                // show the next tip
564
 
                _cairo_dock_get_next_tip (pTips);
565
 
                
566
 
                _update_tip_text (pTips, pDialog);
567
 
                
568
 
                cairo_dock_dialog_reference (pDialog);  // keep the dialog alive.
569
 
        }
570
 
        else if (iClickedButton == 1)  // click on "previous"
571
 
        {
572
 
                // show the previous tip
573
 
                _cairo_dock_get_previous_tip (pTips);
574
 
                
575
 
                _update_tip_text (pTips, pDialog);
576
 
                
577
 
                cairo_dock_dialog_reference (pDialog);  // keep the dialog alive.
578
 
        }
579
 
        else  // click on "close" or Escape
580
 
        {
581
 
                
582
 
                gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", g_cCairoDockDataDir);
583
 
                cairo_dock_update_conf_file (cConfFilePath,
584
 
                        G_TYPE_BOOLEAN, "Help", "skip tips", pTips->bSkipTips,
585
 
                        G_TYPE_INT, "Help", "last tip group", pTips->iNumTipGroup,
586
 
                        G_TYPE_INT, "Help", "last tip key", pTips->iNumTipKey,
587
 
                        G_TYPE_INVALID);
588
 
                g_free (cConfFilePath);
589
 
        }
590
 
}
591
 
static void _on_free_tips_dialog (CDTipsData *pTips)
592
 
{
593
 
        g_key_file_free (pTips->pKeyFile);
594
 
        g_strfreev (pTips->pGroupList);
595
 
        g_strfreev (pTips->pKeyList);
596
 
        g_free (pTips);
597
 
}
598
 
 
599
 
static void _on_tips_on_startup_toggled (GtkCheckButton *pButton, CDTipsData *pTips)
600
 
{
601
 
        pTips->bSkipTips = ! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pButton));
602
 
}
603
 
static void _on_tips_category_changed (GtkComboBox *pWidget, gpointer *data)
604
 
{
605
 
        CDTipsData *pTips = data[0];
606
 
        CairoDialog *pDialog = data[1];
607
 
        
608
 
        int iNumItem = gtk_combo_box_get_active (pWidget);
609
 
        g_return_if_fail (iNumItem < pTips->iNbGroups);
610
 
        
611
 
        pTips->iNumTipGroup = iNumItem;
612
 
        
613
 
        // since the group has changed, get the keys again.
614
 
        g_strfreev (pTips->pKeyList);
615
 
        const gchar *cGroupName = pTips->pGroupList[pTips->iNumTipGroup];
616
 
        pTips->pKeyList = g_key_file_get_keys (pTips->pKeyFile, cGroupName, &pTips->iNbKeys, NULL);
617
 
        pTips->iNumTipKey = 0;
618
 
        
619
 
        _update_tip_text (pTips, pDialog);
620
 
}
621
 
void cairo_dock_show_tips (int iLastGroup, int iLastKey)
622
 
{
623
 
        // open the tips file
624
 
        const gchar *cConfFilePath = CAIRO_DOCK_SHARE_DATA_DIR"/help.conf";
625
 
        GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
626
 
        g_return_if_fail (pKeyFile != NULL);
627
 
        
628
 
        gsize iNbGroups = 0;
629
 
        gchar **pGroupList = g_key_file_get_groups (pKeyFile, &iNbGroups);
630
 
        iNbGroups -= 2;   // skip the last 2 groups (Troubleshooting and Contribute)
631
 
        g_return_if_fail (pGroupList != NULL && iNbGroups > 0);
632
 
        
633
 
        // get the last displayed tip.
634
 
        guint iNumTipGroup, iNumTipKey;
635
 
        if (iLastGroup < 0 || iLastKey < 0)  // first time we display a tip.
636
 
        {
637
 
                iNumTipGroup = iNumTipKey = 0;
638
 
        }
639
 
        else
640
 
        {
641
 
                iNumTipGroup = iLastGroup;
642
 
                iNumTipKey = iLastKey;
643
 
                if (iNumTipGroup >= iNbGroups)  // be sure to stay inside the limits.
644
 
                {
645
 
                        iNumTipGroup = iNbGroups - 1;
646
 
                        iNumTipKey = 0;
647
 
                }
648
 
        }
649
 
        const gchar *cGroupName = pGroupList[iNumTipGroup];
650
 
        
651
 
        gsize iNbKeys = 0;
652
 
        gchar **pKeyList = g_key_file_get_keys (pKeyFile, cGroupName, &iNbKeys, NULL);
653
 
        g_return_if_fail (pKeyList != NULL && iNbKeys > 0);
654
 
        if (iNumTipKey >= iNbKeys)  // be sure to stay inside the limits.
655
 
                iNumTipKey = 0;
656
 
        
657
 
        CDTipsData *pTips = g_new0 (CDTipsData, 1);
658
 
        pTips->pKeyFile = pKeyFile;
659
 
        pTips->pGroupList = pGroupList;
660
 
        pTips->iNbGroups = iNbGroups;
661
 
        pTips->pKeyList = pKeyList;
662
 
        pTips->iNbKeys = iNbKeys;
663
 
        pTips->iNumTipGroup = iNumTipGroup;
664
 
        pTips->iNumTipKey = iNumTipKey;
665
 
        
666
 
        // update to the next tip.
667
 
        if (iLastGroup >= 0 && iLastKey >= 0)  // a previous tip exist => take the next one;
668
 
                _cairo_dock_get_next_tip (pTips);
669
 
        
670
 
        // build a list of the available groups.
671
 
        GtkWidget *pInteractiveWidget = gtk_vbox_new (FALSE, 3);
672
 
        GtkWidget *pComboBox = gtk_combo_box_new_text ();
673
 
        guint i;
674
 
        for (i = 0; i < iNbGroups; i ++)
675
 
        {
676
 
                gtk_combo_box_append_text (GTK_COMBO_BOX (pComboBox), gettext (pGroupList[i]));
677
 
        }
678
 
        gtk_combo_box_set_active (GTK_COMBO_BOX (pComboBox), pTips->iNumTipGroup);
679
 
        pTips->pCategoryCombo = pComboBox;
680
 
        static gpointer data_combo[2];
681
 
        data_combo[0] = pTips;  // the 2nd data is the dialog, we'll set it after we make it.
682
 
        g_signal_connect (G_OBJECT (pComboBox), "changed", G_CALLBACK(_on_tips_category_changed), data_combo);
683
 
        GtkWidget *pJumpBox = gtk_hbox_new (FALSE, 3);
684
 
        GtkWidget *label = gtk_label_new (_("Category"));
685
 
        cairo_dock_set_dialog_widget_text_color (label);
686
 
        gtk_box_pack_end (GTK_BOX (pJumpBox), pComboBox, FALSE, FALSE, 0);
687
 
        gtk_box_pack_end (GTK_BOX (pJumpBox), label, FALSE, FALSE, 0);
688
 
        gtk_box_pack_start (GTK_BOX (pInteractiveWidget), pJumpBox, FALSE, FALSE, 0);
689
 
        
690
 
        // build a check-button to display or not on startup.
691
 
        GtkWidget *pAskBox = gtk_hbox_new (FALSE, 3);
692
 
        label = gtk_label_new (_("Show tips on startup"));
693
 
        cairo_dock_set_dialog_widget_text_color (label);
694
 
        GtkWidget *pCheckBox = gtk_check_button_new ();
695
 
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pCheckBox), TRUE);
696
 
        g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_on_tips_on_startup_toggled), pTips);
697
 
        gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
698
 
        gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
699
 
        gtk_box_pack_start (GTK_BOX (pInteractiveWidget), pAskBox, FALSE, FALSE, 0);
700
 
        
701
 
        // build the dialog.
702
 
        gchar *cText = _build_tip_text (pTips);
703
 
        CairoDialogAttribute attr;
704
 
        memset (&attr, 0, sizeof (CairoDialogAttribute));
705
 
        attr.cText = cText;
706
 
        attr.cImageFilePath = NULL;
707
 
        attr.pInteractiveWidget = pInteractiveWidget;
708
 
        attr.pActionFunc = (CairoDockActionOnAnswerFunc)_tips_dialog_action;
709
 
        attr.pUserData = pTips;
710
 
        attr.pFreeDataFunc = (GFreeFunc)_on_free_tips_dialog;
711
 
        const gchar *cButtons[] = {"cancel", GTK_STOCK_GO_FORWARD"-rtl", GTK_STOCK_GO_FORWARD"-ltr", NULL};
712
 
        attr.cButtonsImage = cButtons;
713
 
        
714
 
        Icon *pIcon = cairo_dock_get_dialogless_icon ();
715
 
        myDialogsParam.dialogTextDescription.bUseMarkup = TRUE;
716
 
        CairoDialog *pTipsDialog = cairo_dock_build_dialog (&attr, pIcon, CAIRO_CONTAINER (g_pMainDock));
717
 
        myDialogsParam.dialogTextDescription.bUseMarkup = FALSE;
718
 
        
719
 
        data_combo[1] = pTipsDialog;
720
 
        
721
 
        g_free (cText);
722
 
}
723
 
 
724
204
static void _cairo_dock_get_global_config (const gchar *cCairoDockDataDir)
725
205
{
726
206
        gchar *cConfFilePath = g_strdup_printf ("%s/.cairo-dock", cCairoDockDataDir);
735
215
                        g_free (s_cDefaulBackend);
736
216
                        s_cDefaulBackend = NULL;
737
217
                }
738
 
                s_bTestComposite = g_key_file_get_boolean (pKeyFile, "Launch", "test composite", NULL);
739
 
                g_bEnterHelpOnce = g_key_file_get_boolean (pKeyFile, "Help", "entered once", NULL);
740
 
                s_bShowTips = ! g_key_file_get_boolean (pKeyFile, "Help", "skip tips", NULL);  // TRUE by default
741
 
                if (g_key_file_has_key (pKeyFile, "Help", "last tip group", NULL))
742
 
                {
743
 
                        s_iLastTipGroup = g_key_file_get_integer (pKeyFile, "Help", "last tip group", NULL);
744
 
                        s_iLastTipKey = g_key_file_get_integer (pKeyFile, "Help", "last tip key", NULL);
745
 
                }
 
218
                
746
219
                s_iGuiMode = g_key_file_get_integer (pKeyFile, "Gui", "mode", NULL);  // 0 by default
747
220
                s_iLastYear = g_key_file_get_integer (pKeyFile, "Launch", "last year", NULL);  // 0 by default
748
221
        }
749
 
        else  // ancienne methode.
 
222
        else  // first launch or old version, the file doesn't exist yet.
750
223
        {
751
224
                gchar *cLastVersionFilePath = g_strdup_printf ("%s/.cairo-dock-last-version", cCairoDockDataDir);
752
225
                if (g_file_test (cLastVersionFilePath, G_FILE_TEST_EXISTS))
762
235
                g_key_file_set_string (pKeyFile, "Launch", "last version", s_cLastVersion);
763
236
                
764
237
                g_key_file_set_string (pKeyFile, "Launch", "default backend", "");
765
 
                g_key_file_set_boolean (pKeyFile, "Launch", "test composite", TRUE);
766
 
                
767
 
                gchar *cHelpHistory = g_strdup_printf ("%s/.help/entered-once", cCairoDockDataDir);
768
 
                if (g_file_test (cHelpHistory, G_FILE_TEST_EXISTS))
769
 
                {
770
 
                        g_bEnterHelpOnce = TRUE;
771
 
                }
772
 
                gchar *cCommand = g_strdup_printf ("rm -rf \"%s/.help\"", cCairoDockDataDir);
773
 
                int r = system (cCommand);
774
 
                g_free (cCommand);
775
 
                g_free (cHelpHistory);
776
 
                g_key_file_set_boolean (pKeyFile, "Help", "entered once", g_bEnterHelpOnce);
777
 
                
778
 
                g_key_file_set_boolean (pKeyFile, "Help", "skip tips", !s_bShowTips);
779
 
                
780
 
                g_key_file_set_integer (pKeyFile, "Help", "last tip group", s_iLastTipGroup);
781
 
                g_key_file_set_integer (pKeyFile, "Help", "last tip key", s_iLastTipKey);
782
238
                
783
239
                g_key_file_set_integer (pKeyFile, "Gui", "mode", s_iGuiMode);
784
240
                
790
246
        g_free (cConfFilePath);
791
247
}
792
248
 
793
 
static gboolean _show_tips_idle (gpointer data)
794
 
{
795
 
        cairo_dock_show_tips (s_iLastTipGroup, s_iLastTipKey);
796
 
        return FALSE;
797
 
}
798
249
 
799
250
int main (int argc, char** argv)
800
251
{
807
258
                //g_print ("'%s'\n", argv[i]);
808
259
                if (strcmp (argv[i], "-m") == 0)
809
260
                        iNbMaintenance ++;
810
 
                
 
261
                if (strcmp (argv[i], "-q") == 0)
 
262
                {
 
263
                        argc = i;
 
264
                        break;
 
265
                }
811
266
                g_string_append_printf (sCommandString, " %s", argv[i]);
812
267
        }
813
268
        if (iNbMaintenance > 1)
815
270
                g_print ("Sorry, Cairo-Dock has encoutered some problems, and will quit.\n");
816
271
                return 1;
817
272
        }
818
 
        g_string_append (sCommandString, " -m");  // on relance avec le mode maintenance.
 
273
        g_string_append (sCommandString, " -m");  // if it crashes before 5s, we'll restart it quietly 1 time.
819
274
        s_cLaunchCommand = sCommandString->str;
820
275
        g_string_free (sCommandString, FALSE);
821
276
        
1027
482
                        GtkWidget *pCheckBox = gtk_check_button_new ();
1028
483
                        gtk_box_pack_end (GTK_BOX (pAskBox), pCheckBox, FALSE, FALSE, 0);
1029
484
                        gtk_box_pack_end (GTK_BOX (pAskBox), label, FALSE, FALSE, 0);
1030
 
                        g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_toggle_remember_choice), dialog);
 
485
                        ///g_signal_connect (G_OBJECT (pCheckBox), "toggled", G_CALLBACK(_toggle_remember_choice), dialog);
1031
486
                        
1032
487
                        gtk_widget_show_all (dialog);
1033
488
                        
1034
489
                        gint iAnswer = gtk_dialog_run (GTK_DIALOG (dialog));  // lance sa propre main loop, c'est pourquoi on peut le faire avant le gtk_main().
1035
 
                        gboolean bRememberChoice = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "remember"));
 
490
                        ///gboolean bRememberChoice = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "remember"));
 
491
                        gboolean bRememberChoice = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pCheckBox));
1036
492
                        gtk_widget_destroy (dialog);
1037
493
                        if (iAnswer == GTK_RESPONSE_NO)
1038
494
                        {
1084
540
                        cUserDefinedModuleDir = NULL;
1085
541
                }
1086
542
        }
1087
 
        
1088
 
        _register_help_module ();
 
543
        cairo_dock_register_help_module ();  // this applet is made for Cairo-Dock, not gldi; therefore, it's not installed as a separate library, so we manually register it.
1089
544
        
1090
545
        //\___________________ define GUI backend.
1091
546
        cairo_dock_load_user_gui_backend (s_iGuiMode);
1234
689
                return 0;
1235
690
        }
1236
691
        
1237
 
        //\___________________ On affiche un petit message de bienvenue ou de changelog ou d'erreur.
 
692
        //\___________________ display the changelog in case of a new version.
1238
693
        gboolean bNewVersion = (s_cLastVersion == NULL || strcmp (s_cLastVersion, CAIRO_DOCK_VERSION) != 0);
1239
694
        if (bNewVersion)
1240
695
        {
1245
700
                g_free (cConfFilePath);
1246
701
        }
1247
702
        
1248
 
        g_print ("bFirstLaunch: %d; s_bShowTips: %d; bNewVersion: %d\n", bFirstLaunch, s_bShowTips, bNewVersion);
1249
 
        if (bFirstLaunch)  // tout premier lancement -> bienvenue !
 
703
        g_print ("bFirstLaunch: %d; bNewVersion: %d\n", bFirstLaunch, bNewVersion);
 
704
        if (bFirstLaunch)  // first launch => set up config
1250
705
        {
1251
 
                //g_idle_add ((GSourceFunc)_show_tips_idle, NULL);
1252
 
                cairo_dock_show_general_message (_("Welcome in Cairo-Dock2 !\nA default and simple theme has been loaded.\nYou can either familiarize yourself with the dock or choose another theme with right-click -> Cairo-Dock -> Manage themes.\nA useful help is available by right-click -> Cairo-Dock -> Help.\nIf you have any question/request/remark, please pay us a visit at http://glx-dock.org.\nHope you will enjoy this soft !\n  (you can now click on this dialog to close it)"), 0);
1253
 
                
1254
706
                g_timeout_add_seconds (4, _cairo_dock_first_launch_setup, NULL);
1255
707
        }
1256
708
        else if (bNewVersion)  // nouvelle version -> changelog (si c'est le 1er lancement, inutile de dire ce qui est nouveau, et de plus on a deja le message de bienvenue).
1272
724
                        }
1273
725
                        g_key_file_free (pKeyFile);
1274
726
                }
1275
 
                // a new version but there is maybe a new version of Compiz and Gtk...
 
727
                // In case something has changed in Compiz/Gtk/others, we also run the script on a new version of the dock.
1276
728
                g_timeout_add_seconds (4, _cairo_dock_first_launch_setup, NULL);
1277
729
        }
1278
730
        else if (cExcludeModule != NULL && ! bMaintenance)
1284
736
                cairo_dock_show_temporary_dialog_with_icon (cMessage, icon, CAIRO_CONTAINER (g_pMainDock), 15000., (pModule ? pModule->pVisitCard->cIconFilePath : NULL));
1285
737
                g_free (cMessage);
1286
738
        }
1287
 
        else if (s_bShowTips)
1288
 
        {
1289
 
                g_idle_add ((GSourceFunc)_show_tips_idle, NULL);
1290
 
        }
1291
739
        
1292
740
        if (! bTesting)
1293
 
                g_timeout_add_seconds (5, _cairo_dock_successful_launch, NULL);
 
741
                g_timeout_add_seconds (5, _cairo_dock_successful_launch, GINT_TO_POINTER (bFirstLaunch));
1294
742
        
1295
743
        g_print ("\n\nTODO:\n"
1296
744
        "- old systray (in dialog mode?)\n"
1297
745
        "- test drop (Shortcuts, between applets or applis, Panel view, etc).\n"
1298
 
        "- test new Dbus methods\n"
1299
746
        "- draw a preview of the dock in opengl\n"
1300
747
        "- test locale on third-party applets\n"
1301
748
        "- handle icon path in .desktop files.\n"
1302
749
        "- compil kde integration\n"
1303
750
        "- find Kwin config tool for Composite-manager\n"
1304
751
        "- test multi-stacks\n"
1305
 
        "- use Power-Manager dbus API\n"
1306
 
        "- test Widget Layer on Compiz 0.9\n"
 
752
        "- review Help hints\n"
 
753
        "- handle first crash nicely\n"
1307
754
        "\n");
1308
755
        
1309
 
        GList *pApps = cairo_dock_fm_list_apps_for_file ("trash:/");
1310
 
        GList *a;
1311
 
        gchar **pAppInfo;
1312
 
        gchar *cIconPath;
1313
 
        gpointer *app;
1314
 
        for (a = pApps; a != NULL; a = a->next)
1315
 
        {
1316
 
                pAppInfo = a->data;
1317
 
                
1318
 
                g_print (" === %s / %s\n", pAppInfo[0], pAppInfo[1]);
1319
 
        }
1320
 
        
1321
756
        gtk_main ();
1322
757
        
1323
758
        signal (SIGSEGV, NULL);  // Segmentation violation