#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <gui/gtkutils.h>
#include <gui/GladeApp.h>
#include <config/ConfigParser.h>
#include <config/config_utils.h>
//=====================================================================
// A missing routine in gtk.
// Returns the current item in an option menu
//=====================================================================
gint gtk_option_menu_get_history(GtkOptionMenu * option_menu)
{
GtkWidget *active_widget;
g_return_val_if_fail(GTK_IS_OPTION_MENU(option_menu), -1);
active_widget = gtk_menu_get_active(GTK_MENU(option_menu->menu));
if (active_widget)
return g_list_index(GTK_MENU_SHELL(option_menu->menu)->children,
active_widget);
else
return -1;
}
gint gtk_menu_get_history(GtkMenu * menu)
{
GtkWidget *active_widget;
g_return_val_if_fail(GTK_IS_MENU(menu), -1);
active_widget = gtk_menu_get_active(menu);
if (active_widget)
return g_list_index(GTK_MENU_SHELL(menu)->children, active_widget);
else
return -1;
}
/* This is an internally used function to create pixmaps. */
GtkWidget*
create_pixmap (GtkWidget *widget,
const gchar *filename)
{
GtkWidget *pixmap;
std::string fnam = filename;
std::string path = GladeApp::find_file( fnam );
if (path.empty())
{
std::cout << "Could not find " << filename << std::endl;
return 0;
}
pixmap = gtk_image_new_from_file (path.c_str());
g_object_ref( pixmap );
return pixmap;
}
void change_button_pixmap(GtkWidget *btn, GtkWidget *img)
{
g_return_if_fail( GTK_IS_BUTTON(btn) );
if ( img == NULL )
return;
GtkContainer *bin = GTK_CONTAINER(btn);
GList *children;
GtkWidget *child;
bool done = false;
while (!done)
{
children = gtk_container_get_children(bin);
for ( ; children; children = children->next )
{
child = GTK_WIDGET(children->data);
if ( GTK_IS_CONTAINER(child) )
{
bin = GTK_CONTAINER(child);
break;
}
else if ( GTK_IS_IMAGE(child) )
{
gtk_container_remove (GTK_CONTAINER(bin), child);
gtk_container_add(GTK_CONTAINER(bin), img);
done = true;
break;
}
}
}
gtk_widget_show_all(btn);
}
/**
* Filters are given as an array of filters in the form <name>|<regex>
*/
#ifdef G_OS_WIN32
#include <windows.h>
#include <Shlobj.h>
std::string get_folder_name(const char *title, const char *init_folder)
{
std::string out;
BROWSEINFO bi = { 0 };
bi.lpszTitle = title;
LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
if ( pidl != 0 )
{
// get the name of the folder
TCHAR path[MAX_PATH];
if ( SHGetPathFromIDList ( pidl, path ) )
{
out = path;
}
// free memory used
IMalloc * imalloc = 0;
if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
{
imalloc->Free ( pidl );
imalloc->Release ( );
}
}
return out;
}
std::string get_file_name(const char *title, GetFileNameAction for_open, const char *init_folder, const char **filters )
{
OPENFILENAME of;
int retval;
char fname[512];
char startdir[512];
fname[0] = '\0';
if ( for_open == a_OpenFolder )
return get_folder_name(title, init_folder);
GString *str = g_string_new("");
if (filters)
{
int i, nchar;
for (i = 0; filters[i]; i++)
{
gchar *ff = g_strdup(filters[i]);
gchar *p = strchr(ff,'|');
if (*p)
{
*p++ = 0;
g_string_append(str, ff);
g_string_append_c(str, '\0');
g_string_append(str, p);
g_string_append_c(str, '\0');
}
else
{
g_string_append(str, "My filter");
g_string_append_c(str, '\0');
g_string_append(str, ff);
g_string_append_c(str, '\0');
}
g_free(ff);
}
g_string_append(str, "All");
g_string_append_c(str, '\0');
g_string_append(str, "*.*");
g_string_append_c(str, '\0');
g_string_append_c(str, '\0');
}
getcwd(startdir, 512);
/* initialize file dialog info struct */
memset(&of, 0, sizeof of);
#ifdef OPENFILENAME_SIZE_VERSION_400
of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
of.lStructSize = sizeof of;
#endif
of.hwndOwner = NULL;
of.lpstrFilter = str->str;
of.lpstrCustomFilter = 0;
of.nFilterIndex = 1;
of.lpstrFile = fname;
of.nMaxFile = sizeof fname;
of.lpstrFileTitle = NULL;
of.lpstrInitialDir = init_folder;
of.lpstrTitle = title;
of.lpstrDefExt = NULL;
of.Flags = OFN_HIDEREADONLY;
if (for_open == a_OpenFile)
retval = GetOpenFileName(&of);
else /* a file save action */
retval = GetSaveFileName(&of);
g_string_free(str, TRUE);
if (!retval) {
return std::string();
}
return fname;
}
gchar *get_registry_key(const gchar *path, const gchar *key);
gchar *get_help_path()
{
gchar *path = get_registry_key("SOFTWARE\\AlibavaSL", "HELPDIR");
}
#else
std::string get_file_name(const char *title, GetFileNameAction for_open, const char *init_folder=0, const char **filters)
{
std::string out;
GtkWidget *fsel;
#if GTK_CHECK_VERSION(2,4,0)
int i;
GtkFileFilter *filter = 0;
GtkFileChooserAction action;
switch (for_open)
{
case a_OpenFile:
action = GTK_FILE_CHOOSER_ACTION_OPEN;
break;
case a_SaveFile:
action = GTK_FILE_CHOOSER_ACTION_SAVE;
break;
case a_OpenFolder:
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
break;
}
fsel = gtk_file_chooser_dialog_new(title, NULL, action,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if (init_folder)
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(fsel), init_folder);
if (filters)
{
for (i = 0; filters[i]; i++)
{
filter = gtk_file_filter_new();
gchar *ff = g_strdup(filters[i]);
gchar *p = strchr(ff,'|');
if (!p)
gtk_file_filter_add_pattern(filter, filters[i]);
else
{
*p++ = 0;
gtk_file_filter_set_name(filter, ff);
gtk_file_filter_add_pattern(filter, p);
}
g_free(ff);
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER (fsel), filter);
}
}
#define fsel_get_file(fsel) gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fsel))
#define the_good_answer GTK_RESPONSE_ACCEPT
#else
fsel = gtk_file_selection_new(title);
#define fsel_get_file(fsel) gtk_file_selection_get_filename (GTK_FILE_SELECTION (fsel))
#define the_good_answer GTK_RESPONSE_OK
#endif
if (gtk_dialog_run(GTK_DIALOG(fsel)) == the_good_answer)
out = fsel_get_file(fsel);
gtk_widget_destroy(fsel);
return out;
}
#endif
void
gtk_help_display(const gchar *link_id)
{
GError *err=0;
#ifndef G_OS_WIN32
gchar *path = g_build_filename(HELPDIR, "index.html", NULL);
#else
gchar *gdir = get_help_path();
gchar *path = g_build_filename(gdir, "index.html", NULL);
g_free(gdir);
#endif
gchar *uri = g_filename_to_uri(path, 0, &err);
if (err)
{
printf("Error opening help file: %s\n", err->message);
g_error_free(err);
err = 0;
}
else
{
/** TODO: what do we do if gtk_show_uri is not there in older Gtk version ?
*
*/
#if GTK_CHECK_VERSION(2,14,0)
#ifdef G_OS_WIN32
/* This is a ugly hack, should be fixed in glib */
if (!(ShellExecute(NULL, "open", uri, NULL, NULL, SW_SHOWNORMAL) > (HINSTANCE)32)) {
err = g_error_new_literal(0, 0, "failed to open webpage");
}
#else
gtk_show_uri(0, uri, GDK_CURRENT_TIME, &err);
#endif
if (err)
{
printf("Error opening help file: %s\n", err->message);
g_error_free(err);
}
#endif
}
g_free(uri);
g_free(path);
}
std::string get_a_string(const std::string &title, const std::string &prompt)
{
std::string out;
GtkWidget *dialog = gtk_dialog_new_with_buttons (
title.c_str(),
(GtkWindow *)0,
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
GtkWidget *vbox = gtk_vbox_new( FALSE, 2 );
gtk_container_set_border_width( GTK_CONTAINER(vbox), 5 );
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, FALSE, FALSE, 0);
GtkWidget *label = gtk_label_new(prompt.c_str());
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
GtkWidget *answ = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), answ, FALSE, FALSE, 0);
gtk_button_box_set_layout( GTK_BUTTON_BOX(GTK_DIALOG(dialog)->action_area),
GTK_BUTTONBOX_END);
gtk_widget_show_all( dialog );
if ( gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT )
{
out = gtk_entry_get_text(GTK_ENTRY(answ));
}
gtk_widget_hide(dialog);
gtk_widget_destroy(dialog);
return out;
}
int get_a_string_list(const std::string &title, const std::string &prompt, std::vector<std::string> &values)
{
std::vector<std::string> msg;
stringtok< std::vector<std::string> >(msg, prompt,":;");
std::vector<std::string>::iterator ip;
values.clear();
GtkWidget *dialog = gtk_dialog_new_with_buttons (
title.c_str(),
(GtkWindow *)0,
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
GtkWidget *vbox = gtk_vbox_new( FALSE, 2 );
gtk_container_set_border_width( GTK_CONTAINER(vbox), 5 );
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, FALSE, FALSE, 0);
std::vector< GtkWidget *> entries;
for (ip=msg.begin();ip!=msg.end();ip++)
{
GtkWidget *label = gtk_label_new((*ip).c_str());
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
GtkWidget *answ = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), answ, FALSE, FALSE, 0);
entries.push_back(answ);
}
gtk_button_box_set_layout( GTK_BUTTON_BOX(GTK_DIALOG(dialog)->action_area),
GTK_BUTTONBOX_END);
gtk_widget_show_all( dialog );
if ( gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT )
{
std::vector< GtkWidget *>::iterator iw;
for (iw=entries.begin(); iw!=entries.end();iw++)
{
values.push_back( gtk_entry_get_text(GTK_ENTRY( *iw )));
}
}
gtk_widget_hide(dialog);
gtk_widget_destroy(dialog);
return values.size();
}