mirror of
https://github.com/moparisthebest/hexchat
synced 2024-12-24 08:38:54 -05:00
617 lines
15 KiB
C++
617 lines
15 KiB
C++
/***************************************************************************
|
|
main.cpp - description
|
|
-------------------
|
|
begin : Wed Jan 1 19:06:46 GMT+4 2003
|
|
copyright : (C) 2003 - 2005 by Alex Shaduri
|
|
email : ashaduri '@' gmail.com
|
|
***************************************************************************/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <stdlib.h>
|
|
#include <sstream>
|
|
#include <gtk/gtk.h>
|
|
|
|
#ifdef _WIN32
|
|
#include "win32util.h"
|
|
#include <io.h>
|
|
#else
|
|
#include <sys/stat.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "interface.h"
|
|
#include "callbacks.h"
|
|
#include "support.h"
|
|
|
|
#include "main.h"
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
GtkWidget* g_main_window = 0;
|
|
// GtkWidget* g_fontsel_dialog = 0;
|
|
|
|
|
|
static std::string s_tmp_file;
|
|
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
static std::string gchar_to_string(gchar* gstr)
|
|
{
|
|
std::string str = (gstr ? gstr : "");
|
|
g_free(gstr);
|
|
return str;
|
|
}
|
|
|
|
|
|
|
|
std::string get_home_dir()
|
|
{
|
|
std::string dir;
|
|
|
|
if (g_get_home_dir())
|
|
dir = g_get_home_dir();
|
|
|
|
#ifdef _WIN32
|
|
if (dir == "") {
|
|
dir = win32_get_registry_value_string(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal");
|
|
}
|
|
if (dir == "") {
|
|
dir = win32_get_registry_value_string(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "User");
|
|
}
|
|
#endif
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
static std::string s_orig_theme;
|
|
static std::string s_orig_font;
|
|
|
|
std::string& get_orig_theme()
|
|
{
|
|
return s_orig_theme;
|
|
}
|
|
|
|
|
|
std::string& get_orig_font()
|
|
{
|
|
return s_orig_font;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
std::string get_current_theme()
|
|
{
|
|
|
|
GtkSettings* settings = gtk_settings_get_default();
|
|
gchar* theme;
|
|
g_object_get(settings, "gtk-theme-name", &theme, NULL);
|
|
|
|
return gchar_to_string(theme);
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string get_current_font()
|
|
{
|
|
return gchar_to_string(pango_font_description_to_string(gtk_rc_get_style(g_main_window)->font_desc));
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
std::string get_selected_theme()
|
|
{
|
|
GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "main_themelist"));
|
|
GtkTreeModel* model = gtk_tree_view_get_model(treeview);
|
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
|
|
|
GtkTreeIter iter;
|
|
gtk_tree_selection_get_selected(selection, 0, &iter);
|
|
|
|
gchar* theme_name;
|
|
gtk_tree_model_get(model, &iter, 0, &theme_name, -1);
|
|
// std::cout << theme_name << "\n";
|
|
return gchar_to_string(theme_name);
|
|
}
|
|
|
|
|
|
|
|
std::string get_selected_font()
|
|
{
|
|
// GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
|
|
// return gtk_entry_get_text(GTK_ENTRY(fontentry));
|
|
|
|
bool default_font = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(g_main_window, "main_use_default_font_radio")));
|
|
|
|
if (default_font)
|
|
return "";
|
|
|
|
GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
|
|
return gtk_font_button_get_font_name(GTK_FONT_BUTTON(fontbutton));
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
static void themelist_selection_changed_cb(GtkTreeSelection* selection, gpointer data)
|
|
{
|
|
if (gtk_tree_selection_get_selected (selection, 0, 0))
|
|
apply_theme(get_selected_theme(), get_current_font());
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
static void populate_with_themes(GtkWidget* w)
|
|
{
|
|
|
|
std::string search_path = gchar_to_string(gtk_rc_get_theme_dir());
|
|
//std::string search_path = gchar_to_string(g_build_filename("lib", "gtk-2.0", "2.10.0", "engines", NULL));
|
|
|
|
if (search_path.size() && search_path[search_path.size() -1] != G_DIR_SEPARATOR)
|
|
search_path += G_DIR_SEPARATOR_S;
|
|
|
|
GDir* gdir = g_dir_open(search_path.c_str(), 0, NULL);
|
|
if (gdir == NULL)
|
|
return;
|
|
|
|
|
|
char* name;
|
|
GList* glist = 0;
|
|
|
|
while ( (name = const_cast<char*>(g_dir_read_name(gdir))) != NULL ) {
|
|
std::string filename = name;
|
|
|
|
// if (g_ascii_strup(fname.c_str(), -1) == "Default")
|
|
// continue;
|
|
|
|
std::string fullname = search_path + filename;
|
|
std::string rc = fullname; rc += G_DIR_SEPARATOR_S; rc += "gtk-2.0"; rc += G_DIR_SEPARATOR_S; rc += "gtkrc";
|
|
|
|
bool is_dir = 0;
|
|
if (g_file_test(fullname.c_str(), G_FILE_TEST_IS_DIR))
|
|
is_dir = 1;
|
|
|
|
if (is_dir && g_file_test(rc.c_str(), G_FILE_TEST_IS_REGULAR)) {
|
|
glist = g_list_insert_sorted(glist, g_strdup(filename.c_str()), (GCompareFunc)strcmp);
|
|
}
|
|
}
|
|
|
|
g_dir_close(gdir);
|
|
|
|
|
|
|
|
|
|
// ---------------- tree
|
|
|
|
|
|
GtkTreeView* treeview = GTK_TREE_VIEW(w);
|
|
GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
|
|
gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
|
|
|
|
GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes (
|
|
"Theme", gtk_cell_renderer_text_new(),
|
|
"text", 0,
|
|
NULL);
|
|
gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
|
|
|
|
|
GtkTreeIter iter;
|
|
|
|
int i =0, curr=0;
|
|
while (char* theme = (char*)g_list_nth_data(glist, i)) {
|
|
gtk_list_store_append (store, &iter);
|
|
gtk_list_store_set (store, &iter, 0, theme, -1);
|
|
|
|
if (strcmp(theme, get_current_theme().c_str()) == 0) {
|
|
curr = i;
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
|
|
GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
|
|
|
// set the default theme
|
|
|
|
// THIS IS IMPORTANT!!!
|
|
gtk_widget_grab_focus(w);
|
|
|
|
std::stringstream str;
|
|
str << curr;
|
|
GtkTreePath* selpath = gtk_tree_path_new_from_string (str.str().c_str());
|
|
if (selpath) {
|
|
gtk_tree_selection_select_path(selection, selpath);
|
|
gtk_tree_view_scroll_to_cell(treeview, selpath, NULL, true, 0.5, 0.0);
|
|
gtk_tree_path_free(selpath);
|
|
}
|
|
|
|
g_signal_connect (G_OBJECT (selection), "changed",
|
|
G_CALLBACK (themelist_selection_changed_cb), NULL);
|
|
|
|
g_object_unref (G_OBJECT (store));
|
|
|
|
|
|
// ---------------- font
|
|
|
|
// GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
|
|
// gtk_entry_set_text(GTK_ENTRY(fontentry), get_current_font().c_str());
|
|
|
|
GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
|
|
gtk_font_button_set_font_name(GTK_FONT_BUTTON(fontbutton), get_current_font().c_str());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------
|
|
|
|
#ifdef _WIN32
|
|
static void redirect_to_file (const gchar* log_domain, GLogLevelFlags log_level,
|
|
const gchar* message, gpointer user_data)
|
|
{
|
|
/* only write logs if running in portable mode, otherwise
|
|
we would get a permission error in program files */
|
|
if ((_access( "portable-mode", 0 )) != -1)
|
|
{
|
|
std::fstream f;
|
|
f.open("gtk2-prefs.log", std::ios::app);
|
|
f << message << "\n";
|
|
f.close();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// ------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
// work around pango weirdness
|
|
#ifdef _WIN32
|
|
// no longer needed as of pango 1.2.5, but won't do any harm
|
|
// putenv("PANGO_WIN32_NO_UNISCRIBE=1");
|
|
#endif
|
|
|
|
|
|
|
|
|
|
std::string user = g_get_user_name();
|
|
std::string tmp = g_get_tmp_dir();
|
|
std::string tmp_file = tmp + G_DIR_SEPARATOR_S + "gtk_prefs_tmprc_" + user;
|
|
s_tmp_file = tmp_file;
|
|
gtk_rc_add_default_file(tmp_file.c_str());
|
|
|
|
|
|
|
|
gtk_init (&argc, &argv);
|
|
|
|
// redirect gtk warnings to file when in win32
|
|
#if defined _WIN32 && !defined DEBUG
|
|
g_log_set_handler ("GLib", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("GModule", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("GLib-GObject", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("GThread", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("Gtk", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("Gdk", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
g_log_set_handler ("GdkPixbuf", GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
|
| G_LOG_FLAG_RECURSION), redirect_to_file, NULL);
|
|
#endif
|
|
|
|
|
|
add_pixmap_directory(".");
|
|
|
|
g_main_window = create_main_window();
|
|
|
|
|
|
populate_with_themes(lookup_widget(g_main_window, "main_themelist"));
|
|
|
|
|
|
std::string about_text = std::string("GTK+ Preference Tool") + "\n\
|
|
\n\
|
|
by Alex Shaduri <ashaduri@gmail.com>\n\
|
|
\n\
|
|
The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided \"AS IS\", and you, its user, assume the entire risk as to its quality and accuracy.\n\
|
|
\n\
|
|
This is free software, and you are welcome to redistribute it under terms of GNU General Public License v2.";
|
|
|
|
|
|
gtk_label_set_text(GTK_LABEL(lookup_widget(g_main_window, "about_label")), about_text.c_str());
|
|
|
|
|
|
GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "preview_treeview"));
|
|
GtkTreeStore *store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
|
|
gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
|
|
|
|
|
|
GtkTreeViewColumn* column1 = gtk_tree_view_column_new_with_attributes ("Text", gtk_cell_renderer_text_new(), "text", 0, NULL);
|
|
gtk_tree_view_column_set_sizing(column1, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
|
|
gtk_tree_view_column_set_resizable(column1, true);
|
|
gtk_tree_view_column_set_reorderable (column1, true);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column1);
|
|
|
|
GtkTreeViewColumn* column2 = gtk_tree_view_column_new_with_attributes ("Number", gtk_cell_renderer_text_new(), "text", 1, NULL);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column2);
|
|
|
|
|
|
GtkTreeIter iter1, iter2;
|
|
|
|
gtk_tree_store_append (store, &iter1, NULL);
|
|
gtk_tree_store_set (store, &iter1, 0, "Parent 2", 1, 66, -1);
|
|
|
|
gtk_tree_store_append (store, &iter1, NULL);
|
|
gtk_tree_store_set (store, &iter1, 0, "Parent 1", 1, 65, -1);
|
|
|
|
gtk_tree_store_append (store, &iter2, &iter1);
|
|
gtk_tree_store_set (store, &iter2, 0, "Child 1", 1, 67, -1);
|
|
|
|
gtk_tree_view_column_set_sort_column_id(column1, 0);
|
|
gtk_tree_view_column_set_sort_order (column1, GTK_SORT_ASCENDING);
|
|
gtk_tree_view_column_set_sort_indicator(column1, true);
|
|
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), 0, GTK_SORT_ASCENDING);
|
|
|
|
g_object_unref (G_OBJECT (store));
|
|
|
|
|
|
get_orig_theme() = get_current_theme();
|
|
get_orig_font() = get_current_font();
|
|
|
|
|
|
gtk_widget_show (g_main_window);
|
|
|
|
|
|
gtk_main();
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------
|
|
|
|
|
|
|
|
void set_theme(const std::string& theme_name, const std::string& font)
|
|
{
|
|
// set widgets accordingly
|
|
|
|
// tree
|
|
GtkTreeView* treeview = GTK_TREE_VIEW(lookup_widget(g_main_window, "main_themelist"));
|
|
GtkTreeModel* model = gtk_tree_view_get_model(treeview);
|
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(treeview);
|
|
|
|
GtkTreeIter iter;
|
|
gtk_tree_model_get_iter_first(model, &iter);
|
|
|
|
while(gtk_tree_model_iter_next(model, &iter)) {
|
|
|
|
gchar* text;
|
|
gtk_tree_model_get (model, &iter, 0, &text, -1);
|
|
std::string theme = gchar_to_string(text);
|
|
|
|
if (theme_name == theme) {
|
|
gtk_tree_selection_select_iter(selection, &iter);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// font
|
|
// GtkWidget* fontentry = lookup_widget(g_main_window, "main_fontentry");
|
|
// gtk_entry_set_text(GTK_ENTRY(fontentry), font.c_str());
|
|
|
|
if (font != "") {
|
|
GtkWidget* fontbutton = lookup_widget(g_main_window, "main_font_selector_button");
|
|
gtk_font_button_set_font_name(GTK_FONT_BUTTON(fontbutton), get_current_font().c_str());
|
|
}
|
|
|
|
|
|
apply_theme(get_selected_theme(), get_selected_font());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void apply_theme(const std::string& theme_name, const std::string& font)
|
|
{
|
|
|
|
std::stringstream strstr;
|
|
strstr << "gtk-theme-name = \"" << theme_name << "\"\n";
|
|
|
|
if (font != "")
|
|
strstr << "style \"user-font\"\n{\nfont_name=\"" << font << "\"\n}\nwidget_class \"*\" style \"user-font\"";
|
|
|
|
// std::cout << strstr.str() << "\n\n\n";
|
|
std::fstream f;
|
|
f.open(s_tmp_file.c_str(), std::ios::out);
|
|
f << strstr.str();
|
|
f.close();
|
|
|
|
|
|
GtkSettings* settings = gtk_settings_get_default();
|
|
|
|
gtk_rc_reparse_all_for_settings (settings, true);
|
|
// gtk_rc_parse_string(strstr.str().c_str());
|
|
// gtk_rc_parse("/root/.gtk-tmp");
|
|
// gtk_rc_reset_styles(settings);
|
|
|
|
unlink(s_tmp_file.c_str());
|
|
|
|
while (gtk_events_pending())
|
|
gtk_main_iteration();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
#ifdef HAVE_DIRECT_H
|
|
#include <direct.h>
|
|
#define mkdir(a) _mkdir(a)
|
|
#else
|
|
#define mkdir(a, b) mkdir(a)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
bool save_current_theme()
|
|
{
|
|
|
|
std::string conf_file = "";
|
|
|
|
if ((_access( "portable-mode", 0 )) != -1) {
|
|
|
|
char* themes_dir_c = gtk_rc_get_theme_dir();
|
|
char* conf_file_c = g_build_filename("etc", "gtk-2.0", "gtkrc", NULL);
|
|
|
|
conf_file = (conf_file_c ? conf_file_c : "");
|
|
|
|
// file doesn't exist, try to get it from gtk.
|
|
if (!g_file_test(conf_file.c_str(), G_FILE_TEST_EXISTS)) {
|
|
|
|
gchar** rc_files = gtk_rc_get_default_files();
|
|
if (rc_files[0] != 0) {
|
|
conf_file = rc_files[0];
|
|
}
|
|
|
|
}
|
|
|
|
|
|
g_free(themes_dir_c);
|
|
g_free(conf_file_c);
|
|
|
|
|
|
// mkdir a directory, only one level deep
|
|
char* etc = g_path_get_dirname(conf_file.c_str());
|
|
if (!g_file_test(etc, G_FILE_TEST_IS_DIR)) {
|
|
mkdir(etc, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
}
|
|
g_free(etc);
|
|
|
|
|
|
} else {
|
|
|
|
conf_file = get_home_dir();
|
|
|
|
if (conf_file[conf_file.length()-1] != G_DIR_SEPARATOR)
|
|
conf_file += G_DIR_SEPARATOR_S;
|
|
|
|
conf_file += ".gtkrc-2.0";
|
|
|
|
}
|
|
|
|
|
|
|
|
// ask
|
|
|
|
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
GtkWidget* dialog = gtk_dialog_new_with_buttons ("Query", GTK_WINDOW(window),
|
|
GtkDialogFlags(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL),
|
|
GTK_STOCK_NO, GTK_RESPONSE_REJECT,
|
|
GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
|
|
GtkWidget* hbox = gtk_hbox_new(1, 1);
|
|
gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
|
|
|
|
gtk_container_add (GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
|
|
gtk_container_add (GTK_CONTAINER(hbox),
|
|
gtk_label_new((std::string("\n\nThe file \"") + conf_file + "\" will be overwritten.\nAre you sure?\n\n").c_str()));
|
|
|
|
gtk_widget_show_all (dialog);
|
|
|
|
bool ret = 0;
|
|
gint result = gtk_dialog_run (GTK_DIALOG (dialog));
|
|
switch (result) {
|
|
case GTK_RESPONSE_ACCEPT:
|
|
ret = 1;
|
|
break;
|
|
}
|
|
gtk_widget_destroy(dialog);
|
|
gtk_widget_destroy(window);
|
|
|
|
if (!ret) // the user pressed "No".
|
|
return false;
|
|
|
|
|
|
std::string font = get_selected_font();
|
|
|
|
std::fstream f;
|
|
f.open(conf_file.c_str(), std::ios::out);
|
|
f << "# Auto-written by gtk2_prefs. Do not edit.\n\n";
|
|
f << "gtk-theme-name = \"" << get_selected_theme() << "\"\n";
|
|
|
|
if (font != "")
|
|
f << "style \"user-font\"\n{\n\tfont_name=\"" << font << "\"\n}\nwidget_class \"*\" style \"user-font\"";
|
|
f.close();
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void program_shutdown()
|
|
{
|
|
gtk_main_quit();
|
|
}
|
|
|
|
|
|
|
|
|
|
|