/**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "config.h"
#include "cairo-dock-struct.h"
#include "cairo-dock-keyfile-utilities.h"
#include "cairo-dock-module-manager.h"
#include "cairo-dock-gui-factory.h"
#include "cairo-dock-log.h"
#include "cairo-dock-menu.h" // cairo_dock_add_in_menu_with_stock_and_data
#include "cairo-dock-desktop-manager.h" // gldi_desktop_get_width
#include "cairo-dock-gui-manager.h" // cairo_dock_show_module_instance_gui
#include "cairo-dock-gui-backend.h" // cairo_dock_show_module_gui
#include "cairo-dock-gui-commons.h" // cairo_dock_get_third_party_applets_link
#include "cairo-dock-widget-plugins.h"
#define CAIRO_DOCK_PREVIEW_HEIGHT 250 // matttbe: 200
#define CAIRO_DOCK_PLUGINS_ICON_SIZE 32
extern gchar *g_cConfFile;
extern GldiContainer *g_pPrimaryContainer;
static void _widget_plugins_reload (CDWidget *pCdWidget);
static void _cairo_dock_activate_one_module (G_GNUC_UNUSED GtkCellRendererToggle * cell_renderer, gchar * path, GtkTreeModel * model)
{
GtkTreeIter iter;
if (! gtk_tree_model_get_iter_from_string (model, &iter, path))
return ;
gchar *cModuleName = NULL;
gboolean bState;
gtk_tree_model_get (model, &iter,
CAIRO_DOCK_MODEL_RESULT, &cModuleName,
CAIRO_DOCK_MODEL_ACTIVE, &bState, -1);
bState = !bState;
gtk_list_store_set (GTK_LIST_STORE (model), &iter, CAIRO_DOCK_MODEL_ACTIVE, bState, -1);
GldiModule *pModule = gldi_module_get (cModuleName);
if (g_pPrimaryContainer == NULL)
{
cairo_dock_add_remove_element_to_key (g_cConfFile, "System", "modules", cModuleName, bState);
}
else if (pModule->pInstancesList == NULL)
{
gldi_module_activate (pModule);
}
else
{
gldi_module_deactivate (pModule);
} // la ligne passera en gras automatiquement.
g_free (cModuleName);
}
static void _cairo_dock_initiate_config_module (G_GNUC_UNUSED GtkMenuItem *pMenuItem, GldiModule *pModule)
{
GldiModuleInstance *pModuleInstance = (pModule->pInstancesList ? pModule->pInstancesList->data : NULL);
if (pModuleInstance)
cairo_dock_show_module_instance_gui (pModuleInstance, -1);
else
cairo_dock_show_module_gui (pModule->pVisitCard->cModuleName);
}
static gboolean _on_click_module_tree_view (GtkTreeView *pTreeView, GdkEventButton* pButton, G_GNUC_UNUSED gpointer data)
{
if ((pButton->button == 3 && pButton->type == GDK_BUTTON_RELEASE) // right click
|| (pButton->button == 1 && pButton->type == GDK_2BUTTON_PRESS)) // double click
{
GtkTreeSelection *pSelection = gtk_tree_view_get_selection (pTreeView);
GtkTreeModel *pModel;
GtkTreeIter iter;
if (! gtk_tree_selection_get_selected (pSelection, &pModel, &iter))
return FALSE;
gchar *cModuleName = NULL;
gtk_tree_model_get (pModel, &iter,
CAIRO_DOCK_MODEL_RESULT, &cModuleName, -1);
GldiModule *pModule = gldi_module_get (cModuleName);
if (pModule == NULL)
return FALSE;
if (pModule->pInstancesList == NULL) // on ne gere pas la config d'un module non actif, donc inutile de presenter le menu dans ce cas-la.
return FALSE;
if (pButton->button == 3)
{
GtkWidget *pMenu = gtk_menu_new ();
cairo_dock_add_in_menu_with_stock_and_data (_("Configure this applet"), GTK_STOCK_PROPERTIES, G_CALLBACK (_cairo_dock_initiate_config_module), pMenu, pModule);
gtk_widget_show_all (pMenu);
gtk_menu_popup (GTK_MENU (pMenu),
NULL,
NULL,
NULL,
NULL,
1,
gtk_get_current_event_time ());
}
else
{
_cairo_dock_initiate_config_module (NULL, pModule);
}
}
return FALSE;
}
static void _cairo_dock_render_module_name (G_GNUC_UNUSED GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model,GtkTreeIter *iter, G_GNUC_UNUSED gpointer data)
{
gboolean bActive = FALSE;
gtk_tree_model_get (model, iter, CAIRO_DOCK_MODEL_ACTIVE, &bActive, -1);
if (bActive)
g_object_set (cell, "weight", 800, "weight-set", TRUE, NULL);
else
g_object_set (cell, "weight", 400, "weight-set", FALSE, NULL);
}
static void _cairo_dock_render_category (G_GNUC_UNUSED GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *model,GtkTreeIter *iter, G_GNUC_UNUSED gpointer data)
{
const gchar *cCategory=NULL;
gint iCategory = 0;
gtk_tree_model_get (model, iter, CAIRO_DOCK_MODEL_STATE, &iCategory, -1);
switch (iCategory)
{
case CAIRO_DOCK_CATEGORY_APPLET_FILES:
cCategory = _("Files");
g_object_set (cell, "foreground", "#004EA1", NULL); // blue
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_APPLET_INTERNET:
cCategory = _("Internet");
g_object_set (cell, "foreground", "#FF5555", NULL); // orange
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_APPLET_DESKTOP:
cCategory = _("Desktop");
g_object_set (cell, "foreground", "#116E08", NULL); // green
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_APPLET_ACCESSORY:
cCategory = _("Accessory");
g_object_set (cell, "foreground", "#900009", NULL); // red
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_APPLET_SYSTEM:
cCategory = _("System");
g_object_set (cell, "foreground", "#A58B0D", NULL); // yellow
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_APPLET_FUN:
cCategory = _("Fun");
g_object_set (cell, "foreground", "#FF55FF", NULL); // purple
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
case CAIRO_DOCK_CATEGORY_BEHAVIOR: // help applet
cCategory = _("Behaviour");
g_object_set (cell, "foreground", "#000066", NULL); // dark blue
g_object_set (cell, "foreground-set", TRUE, NULL);
break;
default:
cd_warning ("incorrect category (%d)", iCategory);
break;
}
if (cCategory != NULL)
{
g_object_set (cell, "text", cCategory, NULL);
}
}
static gboolean _cairo_dock_add_module_to_modele (gchar *cModuleName, GldiModule *pModule, GtkListStore *pModel)
{
if (pModule->pVisitCard->iCategory != CAIRO_DOCK_CATEGORY_THEME // don't display the animations plug-ins
&& ! gldi_module_is_auto_loaded (pModule)) // don't display modules that can't be disabled
{
//g_print (" + %s\n", pModule->pVisitCard->cIconFilePath);
gchar *cIcon = cairo_dock_get_icon_for_gui (pModule->pVisitCard->cModuleName,
pModule->pVisitCard->cIconFilePath,
pModule->pVisitCard->cShareDataDir,
CAIRO_DOCK_PLUGINS_ICON_SIZE,
TRUE);
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cIcon, CAIRO_DOCK_PLUGINS_ICON_SIZE, CAIRO_DOCK_PLUGINS_ICON_SIZE, NULL);
g_free (cIcon);
GtkTreeIter iter;
memset (&iter, 0, sizeof (GtkTreeIter));
gtk_list_store_append (GTK_LIST_STORE (pModel), &iter);
gtk_list_store_set (GTK_LIST_STORE (pModel), &iter,
CAIRO_DOCK_MODEL_NAME, pModule->pVisitCard->cTitle,
CAIRO_DOCK_MODEL_RESULT, cModuleName,
CAIRO_DOCK_MODEL_DESCRIPTION_FILE, dgettext (pModule->pVisitCard->cGettextDomain, pModule->pVisitCard->cDescription),
CAIRO_DOCK_MODEL_IMAGE, pModule->pVisitCard->cPreviewFilePath,
CAIRO_DOCK_MODEL_ICON, pixbuf,
CAIRO_DOCK_MODEL_STATE, pModule->pVisitCard->iCategory,
CAIRO_DOCK_MODEL_ACTIVE, (pModule->pInstancesList != NULL), -1);
g_object_unref (pixbuf);
}
return FALSE;
}
static GtkWidget *_cairo_dock_build_modules_treeview (void)
{
//\______________ On construit le treeview des modules.
GtkWidget *pOneWidget = cairo_dock_gui_make_tree_view (FALSE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pOneWidget), TRUE);
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pOneWidget), TRUE);
g_signal_connect (G_OBJECT (pOneWidget), "button-release-event", G_CALLBACK (_on_click_module_tree_view), NULL); // pour le menu du clic droit
g_signal_connect (G_OBJECT (pOneWidget), "button-press-event", G_CALLBACK (_on_click_module_tree_view), NULL); // pour le menu du clic droit
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pOneWidget));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
//\______________ On remplit le modele avec les modules de la categorie.
GtkTreeModel *pModel = gtk_tree_view_get_model (GTK_TREE_VIEW (pOneWidget));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (pModel), CAIRO_DOCK_MODEL_STATE, GTK_SORT_ASCENDING);
gldi_module_foreach ((GHRFunc) _cairo_dock_add_module_to_modele, pModel);
//\______________ On definit l'affichage du modele dans le tree-view.
GtkTreeViewColumn* col;
GtkCellRenderer *rend;
// case a cocher
rend = gtk_cell_renderer_toggle_new ();
col = gtk_tree_view_column_new_with_attributes (NULL, rend, "active", CAIRO_DOCK_MODEL_ACTIVE, NULL);
gtk_tree_view_column_set_sort_column_id (col, CAIRO_DOCK_MODEL_ACTIVE);
gtk_tree_view_append_column (GTK_TREE_VIEW (pOneWidget), col);
g_signal_connect (G_OBJECT (rend), "toggled", (GCallback) _cairo_dock_activate_one_module, pModel);
// icone
rend = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (pOneWidget), -1, NULL, rend, "pixbuf", CAIRO_DOCK_MODEL_ICON, NULL);
// nom
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Plug-in"), rend, "text", CAIRO_DOCK_MODEL_NAME, NULL);
gtk_tree_view_column_set_cell_data_func (col, rend, (GtkTreeCellDataFunc)_cairo_dock_render_module_name, NULL, NULL);
gtk_tree_view_column_set_sort_column_id (col, CAIRO_DOCK_MODEL_NAME);
gtk_tree_view_append_column (GTK_TREE_VIEW (pOneWidget), col);
// categorie
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Category"), rend, "text", CAIRO_DOCK_MODEL_STATE, NULL);
gtk_tree_view_column_set_cell_data_func (col, rend, (GtkTreeCellDataFunc)_cairo_dock_render_category, NULL, NULL);
gtk_tree_view_column_set_sort_column_id (col, CAIRO_DOCK_MODEL_STATE);
gtk_tree_view_append_column (GTK_TREE_VIEW (pOneWidget), col);
return pOneWidget;
}
static void _build_plugins_widget (PluginsWidget *pPluginsWidget)
{
//\_____________ On construit le tree-view.
pPluginsWidget->pTreeView = _cairo_dock_build_modules_treeview ();
//\_____________ On l'ajoute a la fenetre.
GtkWidget *pKeyBox = _gtk_hbox_new (CAIRO_DOCK_GUI_MARGIN);
GtkWidget *pScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
g_object_set (pScrolledWindow, "height-request", MIN (2*CAIRO_DOCK_PREVIEW_HEIGHT, gldi_desktop_get_height() - 210), NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrolledWindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
#if GTK_CHECK_VERSION (3, 8, 0)
gtk_container_add (GTK_CONTAINER (pScrolledWindow), pPluginsWidget->pTreeView);
#else
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pScrolledWindow), pPluginsWidget->pTreeView);
#endif
gtk_box_pack_start (GTK_BOX (pKeyBox), pScrolledWindow, TRUE, TRUE, 0);
//\______________ On construit le widget de prevue et on le rajoute a la suite.
GPtrArray *pDataGarbage = g_ptr_array_new ();
gchar *cDefaultMessage = g_strdup_printf ("%s", _("Click on an applet in order to have a preview and a description for it."));
GtkWidget *pPreviewBox = cairo_dock_gui_make_preview_box (pKeyBox, pPluginsWidget->pTreeView, FALSE, 1, cDefaultMessage, CAIRO_DOCK_SHARE_DATA_DIR"/images/"CAIRO_DOCK_LOGO, pDataGarbage); // vertical packaging.
GtkWidget *pScrolledWindow2 = gtk_scrolled_window_new (NULL, NULL);
g_object_set (pScrolledWindow, "height-request", MIN (2*CAIRO_DOCK_PREVIEW_HEIGHT, gldi_desktop_get_height() - 210), NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrolledWindow2), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
#if GTK_CHECK_VERSION (3, 8, 0)
gtk_container_add (GTK_CONTAINER (pScrolledWindow2), pPreviewBox);
#else
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pScrolledWindow2), pPreviewBox);
#endif
gtk_box_pack_start (GTK_BOX (pKeyBox), pScrolledWindow2, FALSE, FALSE, 0);
g_free (cDefaultMessage);
GtkWidget *pVBox = _gtk_vbox_new (CAIRO_DOCK_GUI_MARGIN);
gtk_box_pack_start (GTK_BOX (pVBox), pKeyBox, TRUE, TRUE, 0);
//\______________ Add a link to the third-party applet (Note: it's somewhere around here that we could add a third-party addons selector).
gchar *cLink = cairo_dock_get_third_party_applets_link ();
GtkWidget *pLink = gtk_link_button_new_with_label (cLink, _("Get more applets!"));
g_free (cLink);
gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
pPluginsWidget->widget.pWidget = pVBox;
pPluginsWidget->widget.pDataGarbage = pDataGarbage;
}
PluginsWidget *cairo_dock_plugins_widget_new (void)
{
PluginsWidget *pPluginsWidget = g_new0 (PluginsWidget, 1);
pPluginsWidget->widget.iType = WIDGET_PLUGINS;
pPluginsWidget->widget.apply = NULL; // no apply button
pPluginsWidget->widget.reset = NULL; // nothing special to clean
pPluginsWidget->widget.reload = _widget_plugins_reload;
_build_plugins_widget (pPluginsWidget);
return pPluginsWidget;
}
static gboolean _update_module_checkbox (GtkTreeModel *pModel, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter, gpointer *data)
{
gchar *cWantedModuleName = data[0];
gchar *cModuleName = NULL;
gtk_tree_model_get (pModel, iter,
CAIRO_DOCK_MODEL_RESULT, &cModuleName, -1);
if (cModuleName && strcmp (cModuleName, cWantedModuleName) == 0)
{
gtk_list_store_set (GTK_LIST_STORE (pModel), iter, CAIRO_DOCK_MODEL_ACTIVE, data[1], -1);
g_free (cModuleName);
return TRUE;
}
g_free (cModuleName);
return FALSE;
}
void cairo_dock_widget_plugins_update_module_state (PluginsWidget *pPluginsWidget, const gchar *cModuleName, gboolean bActive)
{
GtkTreeModel *pModel = gtk_tree_view_get_model (GTK_TREE_VIEW (pPluginsWidget->pTreeView));
gpointer data[2] = {(gpointer)cModuleName, GINT_TO_POINTER (bActive)};
gtk_tree_model_foreach (GTK_TREE_MODEL (pModel), (GtkTreeModelForeachFunc) _update_module_checkbox, data);
}
static void _widget_plugins_reload (CDWidget *pCdWidget)
{
PluginsWidget *pPluginsWidget = PLUGINS_WIDGET (pCdWidget);
GtkTreeModel *pModel = gtk_tree_view_get_model (GTK_TREE_VIEW (pPluginsWidget->pTreeView));
g_return_if_fail (pModel != NULL);
gtk_list_store_clear (GTK_LIST_STORE (pModel));
gldi_module_foreach ((GHRFunc) _cairo_dock_add_module_to_modele, pModel);
}