mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-09-20 06:39:57 +00:00
2552 lines
99 KiB
C
2552 lines
99 KiB
C
/* X-Chat
|
|
* Copyright (C) 2004-2007 Peter Zelezny.
|
|
*
|
|
* 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 2 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "../common/zoitechat.h"
|
|
|
|
#include <gio/gio.h>
|
|
#include <glib/gstdio.h>
|
|
#include "../common/cfgfiles.h"
|
|
#include "../common/fe.h"
|
|
#include "../common/text.h"
|
|
#include "../common/userlist.h"
|
|
#include "../common/util.h"
|
|
#include "../common/zoitechatc.h"
|
|
#include "../common/outbound.h"
|
|
#include "fe-gtk.h"
|
|
#include "theme/theme-manager.h"
|
|
#include "theme/theme-preferences.h"
|
|
#include "gtkutil.h"
|
|
#include "maingui.h"
|
|
#include "pixmaps.h"
|
|
#include "menu.h"
|
|
#include "preferences-persistence.h"
|
|
#include "plugin-tray.h"
|
|
#include "notifications/notification-backend.h"
|
|
|
|
#ifdef WIN32
|
|
#include "../common/fe.h"
|
|
#endif
|
|
#include "sexy-spell-entry.h"
|
|
|
|
#define LABEL_INDENT 12
|
|
|
|
static GtkWidget *setup_window = NULL;
|
|
static int last_selected_page = 0;
|
|
static int last_selected_row = 0; /* sound row */
|
|
static gboolean color_change;
|
|
static struct zoitechatprefs setup_prefs;
|
|
static GtkWidget *cancel_button;
|
|
static GtkWidget *font_dialog = NULL;
|
|
static GtkWidget *setup_topicbar_multiline_toggle = NULL;
|
|
|
|
enum
|
|
{
|
|
ST_END,
|
|
ST_TOGGLE,
|
|
ST_TOGGLR,
|
|
ST_3OGGLE,
|
|
ST_ENTRY,
|
|
ST_EFONT,
|
|
ST_EFILE,
|
|
ST_EFOLDER,
|
|
ST_MENU,
|
|
ST_RADIO,
|
|
ST_NUMBER,
|
|
ST_HSCALE,
|
|
ST_HEADER,
|
|
ST_LABEL,
|
|
ST_ALERTHEAD
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
int type;
|
|
char *label;
|
|
int offset;
|
|
char *tooltip;
|
|
char const *const *list;
|
|
int extra;
|
|
} setting;
|
|
|
|
typedef GtkWidget *(*setup_page_factory) (const setting *settings);
|
|
|
|
#define SETUP_MAX_PAGES 12
|
|
static setup_page_factory setup_page_factories[SETUP_MAX_PAGES];
|
|
static const setting *setup_page_settings[SETUP_MAX_PAGES];
|
|
static GtkWidget *setup_page_containers[SETUP_MAX_PAGES];
|
|
static int setup_page_count = 0;
|
|
|
|
#ifdef WIN32
|
|
static const char *const langsmenu[] =
|
|
{
|
|
N_("Afrikaans"),
|
|
N_("Albanian"),
|
|
N_("Amharic"),
|
|
N_("Asturian"),
|
|
N_("Azerbaijani"),
|
|
N_("Basque"),
|
|
N_("Belarusian"),
|
|
N_("Bulgarian"),
|
|
N_("Catalan"),
|
|
N_("Chinese (Simplified)"),
|
|
N_("Chinese (Traditional)"),
|
|
N_("Czech"),
|
|
N_("Danish"),
|
|
N_("Dutch"),
|
|
N_("English (British)"),
|
|
N_("English"),
|
|
N_("Estonian"),
|
|
N_("Finnish"),
|
|
N_("French"),
|
|
N_("Galician"),
|
|
N_("German"),
|
|
N_("Greek"),
|
|
N_("Gujarati"),
|
|
N_("Hindi"),
|
|
N_("Hungarian"),
|
|
N_("Indonesian"),
|
|
N_("Italian"),
|
|
N_("Japanese"),
|
|
N_("Kannada"),
|
|
N_("Kinyarwanda"),
|
|
N_("Korean"),
|
|
N_("Latvian"),
|
|
N_("Lithuanian"),
|
|
N_("Macedonian"),
|
|
N_("Malay"),
|
|
N_("Malayalam"),
|
|
N_("Norwegian (Bokmal)"),
|
|
N_("Norwegian (Nynorsk)"),
|
|
N_("Polish"),
|
|
N_("Portuguese"),
|
|
N_("Portuguese (Brazilian)"),
|
|
N_("Punjabi"),
|
|
N_("Russian"),
|
|
N_("Serbian"),
|
|
N_("Slovak"),
|
|
N_("Slovenian"),
|
|
N_("Spanish"),
|
|
N_("Swedish"),
|
|
N_("Thai"),
|
|
N_("Turkish"),
|
|
N_("Ukrainian"),
|
|
N_("Vietnamese"),
|
|
N_("Walloon"),
|
|
NULL
|
|
};
|
|
#endif
|
|
|
|
static const setting appearance_settings[] =
|
|
{
|
|
{ST_HEADER, N_("General"),0,0,0},
|
|
#ifdef WIN32
|
|
{ST_MENU, N_("Language:"), P_OFFINTNL(hex_gui_lang), 0, langsmenu, 0},
|
|
{ST_EFONT, N_("Main font:"), P_OFFSETNL(hex_text_font_main), 0, 0, sizeof prefs.hex_text_font_main},
|
|
#else
|
|
{ST_EFONT, N_("Font:"), P_OFFSETNL(hex_text_font), 0, 0, sizeof prefs.hex_text_font},
|
|
#endif
|
|
|
|
{ST_HEADER, N_("Text Box"),0,0,0},
|
|
{ST_TOGGLE, N_("Colored nick names"), P_OFFINTNL(hex_text_color_nicks), N_("Give each person on IRC a different color"),0,0},
|
|
{ST_TOGGLR, N_("Indent nick names"), P_OFFINTNL(hex_text_indent), N_("Make nick names right-justified"),0,0},
|
|
{ST_TOGGLE, N_ ("Show marker line"), P_OFFINTNL (hex_text_show_marker), N_ ("Insert a red line after the last read text."), 0, 0},
|
|
{ST_TOGGLE, N_("Keep search position when closing"), P_OFFINTNL(hex_text_search_keep_position), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Timestamps"),0,0,0},
|
|
{ST_TOGGLE, N_("Enable timestamps"), P_OFFINTNL(hex_stamp_text),0,0,1},
|
|
{ST_ENTRY, N_("Timestamp format:"), P_OFFSETNL(hex_stamp_text_format),
|
|
#ifdef WIN32
|
|
N_("See the strftime MSDN article for details."),0,sizeof prefs.hex_stamp_text_format},
|
|
#else
|
|
N_("See the strftime manpage for details."),0,sizeof prefs.hex_stamp_text_format},
|
|
#endif
|
|
|
|
{ST_HEADER, N_("Title Bar"),0,0,0},
|
|
{ST_TOGGLE, N_("Show channel modes"), P_OFFINTNL(hex_gui_win_modes),0,0,0},
|
|
{ST_TOGGLR, N_("Show number of users"), P_OFFINTNL(hex_gui_win_ucount),0,0,0},
|
|
{ST_TOGGLE, N_("Show nickname"), P_OFFINTNL(hex_gui_win_nick),0,0,0},
|
|
|
|
{ST_HEADER, N_("Topic Bar"),0,0,0},
|
|
{ST_TOGGLE, N_("Place mode buttons beside the topic"), P_OFFINTNL(hex_gui_mode_buttons_inline), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Allow multi-line topics"), P_OFFINTNL(hex_gui_topicbar_multiline), 0, 0, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting appearance_advanced_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Advanced"),0,0,0},
|
|
{ST_EFILE, N_ ("Background image:"), P_OFFSETNL (hex_text_background), 0, 0, sizeof prefs.hex_text_background},
|
|
{ST_HSCALE, N_("Window opacity:"), P_OFFINTNL(hex_gui_transparency),0,0,0},
|
|
{ST_HSCALE, N_("Mouse wheel scroll speed (Slower ← → Faster):"), P_OFFINTNL(hex_gui_mouse_scroll_speed), 0, 0, 100},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const tabcompmenu[] =
|
|
{
|
|
N_("A-Z"),
|
|
N_("Last-spoke order"),
|
|
NULL
|
|
};
|
|
|
|
static const setting inputbox_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Input Box"),0,0,0},
|
|
{ST_TOGGLE, N_("Render colors and attributes"), P_OFFINTNL (hex_gui_input_attr),0,0,0},
|
|
{ST_TOGGLE, N_("Show nick box"), P_OFFINTNL(hex_gui_input_nick),0,0,1},
|
|
{ST_TOGGLE, N_("Show user mode icon in nick box"), P_OFFINTNL(hex_gui_input_icon),0,0,0},
|
|
{ST_TOGGLE, N_("Spell checking"), P_OFFINTNL(hex_gui_input_spell),0,0,1},
|
|
{ST_ENTRY, N_("Dictionaries to use:"), P_OFFSETNL(hex_text_spell_langs),0,0,sizeof prefs.hex_text_spell_langs},
|
|
#ifdef WIN32
|
|
{ST_LABEL, N_("Use language codes (for example, \"en_US\").\nOn Windows 8 and newer, dictionaries are provided by Windows. Separate multiple entries with commas.")},
|
|
#else
|
|
{ST_LABEL, N_("Use language codes. Separate multiple entries with commas.")},
|
|
#endif
|
|
|
|
{ST_HEADER, N_("Nick Completion"),0,0,0},
|
|
{ST_ENTRY, N_("Nick completion suffix:"), P_OFFSETNL(hex_completion_suffix),0,0,sizeof prefs.hex_completion_suffix},
|
|
{ST_MENU, N_("Nick completion sorted:"), P_OFFINTNL(hex_completion_sort), 0, tabcompmenu, 0},
|
|
{ST_NUMBER, N_("Nick completion amount:"), P_OFFINTNL(hex_completion_amount), N_("Threshold of nicks to start listing instead of completing"), (const char **)N_("nicks."), 1000},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const lagmenutext[] =
|
|
{
|
|
N_("Off"),
|
|
N_("Graphical"),
|
|
N_("Text"),
|
|
N_("Both"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const ulmenutext[] =
|
|
{
|
|
N_("A-Z, ops first"),
|
|
N_("A-Z"),
|
|
N_("Z-A, ops last"),
|
|
N_("Z-A"),
|
|
N_("Unsorted"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const cspos[] =
|
|
{
|
|
N_("Left (upper)"),
|
|
N_("Left (lower)"),
|
|
N_("Right (upper)"),
|
|
N_("Right (lower)"),
|
|
N_("Top"),
|
|
N_("Bottom"),
|
|
N_("Hidden"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const ulpos[] =
|
|
{
|
|
N_("Left (upper)"),
|
|
N_("Left (lower)"),
|
|
N_("Right (upper)"),
|
|
N_("Right (lower)"),
|
|
NULL
|
|
};
|
|
|
|
static const setting userlist_settings[] =
|
|
{
|
|
{ST_HEADER, N_("User List"),0,0,0},
|
|
{ST_TOGGLE, N_("Show hostnames in user list"), P_OFFINTNL(hex_gui_ulist_show_hosts), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Show icons for user modes"), P_OFFINTNL(hex_gui_ulist_icons), N_("Use graphical icons instead of text symbols in the user list."), 0, 0},
|
|
{ST_TOGGLE, N_("Color nicknames in userlist"), P_OFFINTNL(hex_gui_ulist_color), N_("Will color nicknames the same as in chat."), 0, 0},
|
|
{ST_TOGGLE, N_("Show user count in channels"), P_OFFINTNL(hex_gui_ulist_count), 0, 0, 0},
|
|
{ST_MENU, N_("User list sorted by:"), P_OFFINTNL(hex_gui_ulist_sort), 0, ulmenutext, 0},
|
|
{ST_MENU, N_("Show user list at:"), P_OFFINTNL(hex_gui_ulist_pos), 0, ulpos, 1},
|
|
|
|
{ST_HEADER, N_("Away Tracking"),0,0,0},
|
|
{ST_TOGGLE, N_("Track the away status of users and mark them in a different color"), P_OFFINTNL(hex_away_track),0,0,1},
|
|
{ST_NUMBER, N_("On channels smaller than:"), P_OFFINTNL(hex_away_size_max),0,0,10000},
|
|
|
|
{ST_HEADER, N_("Action Upon Double Click"),0,0,0},
|
|
{ST_ENTRY, N_("Execute command:"), P_OFFSETNL(hex_gui_ulist_doubleclick), 0, 0, sizeof prefs.hex_gui_ulist_doubleclick},
|
|
|
|
{ST_HEADER, N_("Extra Gadgets"),0,0,0},
|
|
{ST_MENU, N_("Lag meter:"), P_OFFINTNL(hex_gui_lagometer), 0, lagmenutext, 0},
|
|
{ST_MENU, N_("Throttle meter:"), P_OFFINTNL(hex_gui_throttlemeter), 0, lagmenutext, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const tabwin[] =
|
|
{
|
|
N_("Windows"),
|
|
N_("Tabs"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const focusnewtabsmenu[] =
|
|
{
|
|
N_("Never"),
|
|
N_("Always"),
|
|
N_("Only requested tabs"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const noticeposmenu[] =
|
|
{
|
|
N_("Automatic"),
|
|
N_("In an extra tab"),
|
|
N_("In the front tab"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const swtype[] =
|
|
{
|
|
N_("Tabs"),
|
|
"",
|
|
N_("Tree"),
|
|
NULL
|
|
};
|
|
|
|
static const setting tabs_settings[] =
|
|
{
|
|
{ST_RADIO, N_("Switcher type:"),P_OFFINTNL(hex_gui_tab_layout), 0, swtype, 0},
|
|
{ST_TOGGLE, N_("Open an extra tab for server messages"), P_OFFINTNL(hex_gui_tab_server), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Open a new tab when you receive a private message"), P_OFFINTNL(hex_gui_autoopen_dialog), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Sort tabs in alphabetical order"), P_OFFINTNL(hex_gui_tab_sort), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Show icons in the channel tree"), P_OFFINTNL(hex_gui_tab_icons), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Show dotted lines in the channel tree"), P_OFFINTNL(hex_gui_tab_dots), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Scroll mouse-wheel to change tabs"), P_OFFINTNL (hex_gui_tab_scrollchans), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Show close button on tabs"), P_OFFINTNL(hex_gui_tab_closebuttons), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Middle click to close tab"), P_OFFINTNL(hex_gui_tab_middleclose), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Smaller text"), P_OFFINTNL(hex_gui_tab_small), 0, 0, 0},
|
|
{ST_EFONT, N_("Tab font:"), P_OFFSETNL(hex_gui_tab_font),
|
|
N_("Font for server and channel tabs in the Tabs layout. Leave blank to use the theme font. Smaller text still applies."),
|
|
0, sizeof prefs.hex_gui_tab_font},
|
|
{ST_MENU, N_("Focus new tabs:"), P_OFFINTNL(hex_gui_tab_newtofront), 0, focusnewtabsmenu, 0},
|
|
{ST_MENU, N_("Placement of notices:"), P_OFFINTNL(hex_irc_notice_pos), 0, noticeposmenu, 0},
|
|
{ST_MENU, N_("Show channel switcher at:"), P_OFFINTNL(hex_gui_tab_pos), 0, cspos, 1},
|
|
{ST_NUMBER, N_("Shorten tab labels to:"), P_OFFINTNL(hex_gui_tab_trunc), 0, (const char **)N_("letters."), 99},
|
|
|
|
{ST_HEADER, N_("Tabs or Windows"),0,0,0},
|
|
{ST_MENU, N_("Open channels in:"), P_OFFINTNL(hex_gui_tab_chans), 0, tabwin, 0},
|
|
{ST_MENU, N_("Open dialogs in:"), P_OFFINTNL(hex_gui_tab_dialogs), 0, tabwin, 0},
|
|
{ST_MENU, N_("Open utilities in:"), P_OFFINTNL(hex_gui_tab_utils), N_("Open DCC, Ignore, Notify etc, in tabs or windows?"), tabwin, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const dccaccept[] =
|
|
{
|
|
N_("Ask for confirmation"),
|
|
N_("Ask for download folder"),
|
|
N_("Save without interaction"),
|
|
NULL
|
|
};
|
|
|
|
static const setting filexfer_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Files and Directories"), 0, 0, 0},
|
|
{ST_MENU, N_("Auto accept file offers:"), P_OFFINTNL(hex_dcc_auto_recv), 0, dccaccept, 0},
|
|
{ST_EFOLDER,N_("Download files to:"), P_OFFSETNL(hex_dcc_dir), 0, 0, sizeof prefs.hex_dcc_dir},
|
|
{ST_EFOLDER,N_("Move completed files to:"), P_OFFSETNL(hex_dcc_completed_dir), 0, 0, sizeof prefs.hex_dcc_completed_dir},
|
|
{ST_TOGGLE, N_("Save nick name in filenames"), P_OFFINTNL(hex_dcc_save_nick), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Auto Open DCC Windows"),0,0,0},
|
|
{ST_TOGGLE, N_("Send window"), P_OFFINTNL(hex_gui_autoopen_send), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Receive window"), P_OFFINTNL(hex_gui_autoopen_recv), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Chat window"), P_OFFINTNL(hex_gui_autoopen_chat), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Maximum File Transfer Speeds (KiB/s or MiB/s)"), 0, 0, 0},
|
|
{ST_NUMBER, N_("One upload:"), P_OFFINTNL(hex_dcc_max_send_cps),
|
|
N_("Maximum speed for one transfer"), 0, 10000000},
|
|
{ST_NUMBER, N_("One download:"), P_OFFINTNL(hex_dcc_max_get_cps),
|
|
N_("Maximum speed for one transfer"), 0, 10000000},
|
|
{ST_NUMBER, N_("All uploads combined:"), P_OFFINTNL(hex_dcc_global_max_send_cps),
|
|
N_("Maximum speed for all files"), 0, 10000000},
|
|
{ST_NUMBER, N_("All downloads combined:"), P_OFFINTNL(hex_dcc_global_max_get_cps),
|
|
N_("Maximum speed for all files"), 0, 10000000},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const int balloonlist[3] =
|
|
{
|
|
P_OFFINTNL(hex_input_balloon_chans), P_OFFINTNL(hex_input_balloon_priv), P_OFFINTNL(hex_input_balloon_hilight)
|
|
};
|
|
|
|
static const int trayblinklist[3] =
|
|
{
|
|
P_OFFINTNL(hex_input_tray_chans), P_OFFINTNL(hex_input_tray_priv), P_OFFINTNL(hex_input_tray_hilight)
|
|
};
|
|
|
|
static const int taskbarlist[3] =
|
|
{
|
|
P_OFFINTNL(hex_input_flash_chans), P_OFFINTNL(hex_input_flash_priv), P_OFFINTNL(hex_input_flash_hilight)
|
|
};
|
|
|
|
static const int beeplist[3] =
|
|
{
|
|
P_OFFINTNL(hex_input_beep_chans), P_OFFINTNL(hex_input_beep_priv), P_OFFINTNL(hex_input_beep_hilight)
|
|
};
|
|
|
|
static const setting alert_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Alerts"),0,0,0},
|
|
|
|
{ST_ALERTHEAD},
|
|
|
|
|
|
{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
|
|
{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
|
|
{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
|
|
#ifdef WIN32
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play the \"Instant Message Notification\" system sound upon the selected events"), (void *)beeplist, 0},
|
|
#else
|
|
#ifdef USE_LIBCANBERRA
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play \"message-new-instant\" from the freedesktop.org sound theme upon the selected events"), (void *)beeplist, 0},
|
|
#else
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play a GTK beep upon the selected events"), (void *)beeplist, 0},
|
|
#endif
|
|
#endif
|
|
|
|
{ST_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL(hex_away_omit_alerts), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Tray Behavior"), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
|
|
{ST_TOGGLE, N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
|
|
{ST_TOGGLE, N_("Only show notifications when hidden or iconified"), P_OFFINTNL(hex_gui_tray_quiet), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Highlighted Messages"),0,0,0},
|
|
{ST_LABEL, N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
|
|
|
|
{ST_ENTRY, N_("Extra words to highlight:"), P_OFFSETNL(hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
|
|
{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL(hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
|
|
{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL(hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
|
|
{ST_LABEL, N_("Separate multiple words with commas.\nWildcards are accepted.")},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting alert_settings_nonotifications[] =
|
|
{
|
|
{ST_HEADER, N_("Alerts"),0,0,0},
|
|
|
|
{ST_ALERTHEAD},
|
|
{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
|
|
#ifdef HAVE_GTK_MAC
|
|
{ST_3OGGLE, N_("Bounce dock icon on:"), 0, 0, (void *)taskbarlist, 0},
|
|
#else
|
|
#ifndef __APPLE__
|
|
{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
|
|
#endif
|
|
#endif
|
|
#ifdef WIN32
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play the \"Instant Message Notification\" system sound upon the selected events"), (void *)beeplist, 0},
|
|
#else
|
|
#ifdef USE_LIBCANBERRA
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play \"message-new-instant\" from the freedesktop.org sound theme upon the selected events"), (void *)beeplist, 0},
|
|
#else
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play a GTK beep upon the selected events"), (void *)beeplist, 0},
|
|
#endif
|
|
#endif
|
|
|
|
{ST_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL(hex_away_omit_alerts), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Tray Behavior"), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
|
|
{ST_TOGGLE, N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
|
|
|
|
{ST_HEADER, N_("Highlighted Messages"),0,0,0},
|
|
{ST_LABEL, N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
|
|
|
|
{ST_ENTRY, N_("Extra words to highlight:"), P_OFFSETNL(hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
|
|
{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL(hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
|
|
{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL(hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
|
|
{ST_LABEL, N_("Separate multiple words with commas.\nWildcards are accepted.")},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting alert_settings_unity[] =
|
|
{
|
|
{ST_HEADER, N_("Alerts"),0,0,0},
|
|
|
|
{ST_ALERTHEAD},
|
|
{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
|
|
{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, 0, (void *)beeplist, 0},
|
|
|
|
{ST_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL(hex_away_omit_alerts), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Highlighted Messages"),0,0,0},
|
|
{ST_LABEL, N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
|
|
|
|
{ST_ENTRY, N_("Extra words to highlight:"), P_OFFSETNL(hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
|
|
{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL(hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
|
|
{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL(hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
|
|
{ST_LABEL, N_("Separate multiple words with commas.\nWildcards are accepted.")},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting alert_settings_unityandnonotifications[] =
|
|
{
|
|
{ST_HEADER, N_("Alerts"), 0, 0, 0},
|
|
|
|
{ST_ALERTHEAD},
|
|
{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
|
|
{ST_3OGGLE, N_("Make a beep sound on:"), 0, 0, (void *)beeplist, 0},
|
|
|
|
{ST_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL (hex_away_omit_alerts), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL (hex_gui_focus_omitalerts), 0, 0, 0},
|
|
|
|
{ST_HEADER, N_("Highlighted Messages"), 0, 0, 0},
|
|
{ST_LABEL, N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
|
|
|
|
{ST_ENTRY, N_("Extra words to highlight:"), P_OFFSETNL (hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
|
|
{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL (hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
|
|
{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL (hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
|
|
{ST_LABEL, N_("Separate multiple words with commas.\nWildcards are accepted.")},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting general_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Default Messages"),0,0,0},
|
|
{ST_ENTRY, N_("Quit:"), P_OFFSETNL(hex_irc_quit_reason), 0, 0, sizeof prefs.hex_irc_quit_reason},
|
|
{ST_ENTRY, N_("Leave channel:"), P_OFFSETNL(hex_irc_part_reason), 0, 0, sizeof prefs.hex_irc_part_reason},
|
|
{ST_ENTRY, N_("Away:"), P_OFFSETNL(hex_away_reason), 0, 0, sizeof prefs.hex_away_reason},
|
|
|
|
{ST_HEADER, N_("Away"),0,0,0},
|
|
{ST_TOGGLE, N_("Show away once"), P_OFFINTNL(hex_away_show_once), N_("Show identical away messages only once."), 0, 0},
|
|
{ST_TOGGLE, N_("Automatically unmark away"), P_OFFINTNL(hex_away_auto_unmark), N_("Unmark yourself as away before sending messages."), 0, 0},
|
|
|
|
{ST_HEADER, N_("Miscellaneous"),0,0,0},
|
|
{ST_TOGGLE, N_("Display MODEs in raw form"), P_OFFINTNL(hex_irc_raw_modes), 0, 0, 0},
|
|
{ST_TOGGLE, N_("WHOIS on notify"), P_OFFINTNL(hex_notify_whois_online), N_("Sends a /WHOIS when a user comes online in your notify list."), 0, 0},
|
|
{ST_TOGGLE, N_("Hide join and part messages"), P_OFFINTNL(hex_irc_conf_mode), N_("Hide channel join/part messages by default."), 0, 0},
|
|
{ST_TOGGLE, N_("Hide nick change messages"), P_OFFINTNL(hex_irc_hide_nickchange), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Hide hostmasks in join and part messages"), P_OFFINTNL(hex_irc_hide_join_part_hostmask), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Enable Ctrl+Q to quit"), P_OFFINTNL(hex_gui_ctrlq_quit), 0, 0, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const bantypemenu[] =
|
|
{
|
|
N_("*!*@*.host"),
|
|
N_("*!*@domain"),
|
|
N_("*!*user@*.host"),
|
|
N_("*!*user@domain"),
|
|
NULL
|
|
};
|
|
|
|
static const setting advanced_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Auto Copy Behavior"),0,0,0},
|
|
{ST_TOGGLE, N_("Automatically copy selected text"), P_OFFINTNL(hex_text_autocopy_text),
|
|
N_("Copy selected text to clipboard when left mouse button is released. "
|
|
"Otherwise, Ctrl+Shift+C will copy the "
|
|
"selected text to the clipboard."), 0, 0},
|
|
{ST_TOGGLE, N_("Automatically include timestamps"), P_OFFINTNL(hex_text_autocopy_stamp),
|
|
N_("Automatically include timestamps in copied lines of text. Otherwise, "
|
|
"include timestamps if the Shift key is held down while selecting."), 0, 0},
|
|
{ST_TOGGLE, N_("Automatically include color information"), P_OFFINTNL(hex_text_autocopy_color),
|
|
N_("Automatically include color information in copied lines of text. "
|
|
"Otherwise, include color information if the Ctrl key is held down "
|
|
"while selecting."), 0, 0},
|
|
|
|
{ST_HEADER, N_("Miscellaneous"), 0, 0, 0},
|
|
{ST_ENTRY, N_("Real name:"), P_OFFSETNL(hex_irc_real_name), 0, 0, sizeof prefs.hex_irc_real_name},
|
|
#ifdef WIN32
|
|
{ST_ENTRY, N_("Alternative fonts:"), P_OFFSETNL(hex_text_font_alternative), N_("Separate multiple entries with commas without spaces before or after."), 0, sizeof prefs.hex_text_font_alternative},
|
|
#endif
|
|
{ST_TOGGLE, N_("Display lists in compact mode"), P_OFFINTNL(hex_gui_compact), N_("Use less spacing between user list/channel tree rows."), 0, 0},
|
|
{ST_TOGGLE, N_("Use server time if supported"), P_OFFINTNL(hex_irc_cap_server_time), N_("Display timestamps obtained from server if it supports the time-server extension."), 0, 0},
|
|
{ST_TOGGLE, N_("Automatically reconnect to servers on disconnect"), P_OFFINTNL(hex_net_auto_reconnect), 0, 0, 1},
|
|
{ST_NUMBER, N_("Lag check interval:"), P_OFFINTNL(hex_net_lag_check), 0, (const char **)N_("seconds."), 9999},
|
|
{ST_NUMBER, N_("Auto reconnect delay:"), P_OFFINTNL(hex_net_reconnect_delay), 0, 0, 9999},
|
|
{ST_NUMBER, N_("Auto join delay:"), P_OFFINTNL(hex_irc_join_delay), 0, 0, 9999},
|
|
{ST_MENU, N_("Ban Type:"), P_OFFINTNL(hex_irc_ban_type), N_("Attempt to use this banmask when banning or quieting. (requires irc_who_join)"), bantypemenu, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting logging_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Logging"),0,0,0},
|
|
{ST_TOGGLE, N_("Display scrollback from previous session"), P_OFFINTNL(hex_text_replay), 0, 0, 0},
|
|
{ST_NUMBER, N_("Scrollback lines:"), P_OFFINTNL(hex_text_max_lines),0,0,100000},
|
|
{ST_TOGGLE, N_("Enable logging of conversations to disk"), P_OFFINTNL(hex_irc_logging), 0, 0, 0},
|
|
{ST_ENTRY, N_("Log filename:"), P_OFFSETNL(hex_irc_logmask), 0, 0, sizeof prefs.hex_irc_logmask},
|
|
{ST_LABEL, N_("%s=Server %c=Channel %n=Network.")},
|
|
|
|
{ST_HEADER, N_("Timestamps"),0,0,0},
|
|
{ST_TOGGLE, N_("Insert timestamps in logs"), P_OFFINTNL(hex_stamp_log), 0, 0, 1},
|
|
{ST_ENTRY, N_("Log timestamp format:"), P_OFFSETNL(hex_stamp_log_format), 0, 0, sizeof prefs.hex_stamp_log_format},
|
|
#ifdef WIN32
|
|
{ST_LABEL, N_("See the strftime MSDN article for details.")},
|
|
#else
|
|
{ST_LABEL, N_("See the strftime manpage for details.")},
|
|
#endif
|
|
|
|
{ST_HEADER, N_("URLs"),0,0,0},
|
|
{ST_TOGGLE, N_("Enable logging of URLs to disk"), P_OFFINTNL(hex_url_logging), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Enable URL grabber"), P_OFFINTNL(hex_url_grabber), 0, 0, 1},
|
|
{ST_NUMBER, N_("Maximum number of URLs to grab:"), P_OFFINTNL(hex_url_grabber_limit), 0, 0, 9999},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const char *const proxytypes[] =
|
|
{
|
|
N_("(Disabled)"),
|
|
N_("Wingate"),
|
|
N_("SOCKS4"),
|
|
N_("SOCKS5"),
|
|
N_("HTTP"),
|
|
N_("Auto"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const proxyuse[] =
|
|
{
|
|
N_("All connections"),
|
|
N_("IRC server only"),
|
|
N_("DCC only"),
|
|
NULL
|
|
};
|
|
|
|
static const setting network_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Your Address"), 0, 0, 0, 0},
|
|
{ST_ENTRY, N_("Bind to:"), P_OFFSETNL(hex_net_bind_host), 0, 0, sizeof prefs.hex_net_bind_host},
|
|
{ST_LABEL, N_("Only useful for computers with multiple addresses.")},
|
|
|
|
{ST_HEADER, N_("File Transfers"), 0, 0, 0},
|
|
{ST_TOGGLE, N_("Get my address from the IRC server"), P_OFFINTNL(hex_dcc_ip_from_server),
|
|
N_("Asks the IRC server for your real address. Use this if you have a 192.168.*.* address!"), 0, 0},
|
|
{ST_ENTRY, N_("DCC IP address:"), P_OFFSETNL(hex_dcc_ip),
|
|
N_("Claim you are at this address when offering files."), 0, sizeof prefs.hex_dcc_ip},
|
|
{ST_NUMBER, N_("First DCC listen port:"), P_OFFINTNL(hex_dcc_port_first), 0, 0, 65535},
|
|
{ST_NUMBER, N_("Last DCC listen port:"), P_OFFINTNL(hex_dcc_port_last), 0,
|
|
(const char **)N_("!Leave ports at zero for full range."), 65535},
|
|
|
|
{ST_HEADER, N_("Proxy Server"), 0, 0, 0, 0},
|
|
{ST_ENTRY, N_("Hostname:"), P_OFFSETNL(hex_net_proxy_host), 0, 0, sizeof prefs.hex_net_proxy_host},
|
|
{ST_NUMBER, N_("Port:"), P_OFFINTNL(hex_net_proxy_port), 0, 0, 65535},
|
|
{ST_MENU, N_("Type:"), P_OFFINTNL(hex_net_proxy_type), 0, proxytypes, 0},
|
|
{ST_MENU, N_("Use proxy for:"), P_OFFINTNL(hex_net_proxy_use), 0, proxyuse, 0},
|
|
|
|
{ST_HEADER, N_("Connection Health"), 0, 0, 0, 0},
|
|
{ST_NUMBER, N_("TCP keepalive idle:"), P_OFFINTNL(hex_net_keepalive_idle), 0, (const char **)N_("seconds."), 7200},
|
|
{ST_NUMBER, N_("TCP keepalive interval:"), P_OFFINTNL(hex_net_keepalive_interval), 0, (const char **)N_("seconds."), 600},
|
|
{ST_NUMBER, N_("TCP keepalive probes:"), P_OFFINTNL(hex_net_keepalive_count), 0, 0, 20},
|
|
|
|
{ST_HEADER, N_("Proxy Authentication"), 0, 0, 0, 0},
|
|
{ST_TOGGLE, N_("Use authentication (HTTP or SOCKS5 only)"), P_OFFINTNL(hex_net_proxy_auth), 0, 0, 0},
|
|
{ST_ENTRY, N_("Username:"), P_OFFSETNL(hex_net_proxy_user), 0, 0, sizeof prefs.hex_net_proxy_user},
|
|
{ST_ENTRY, N_("Password:"), P_OFFSETNL(hex_net_proxy_pass), 0, GINT_TO_POINTER(1), sizeof prefs.hex_net_proxy_pass},
|
|
|
|
{ST_HEADER, N_("Remote Media"), 0, 0, 0, 0},
|
|
{ST_TOGGLE, N_("Allow loading remote media (inline images) when clicked"),
|
|
P_OFFINTNL(hex_net_remote_media),
|
|
N_("Loading remote media contacts the site hosting it, which can reveal your IP address and that you viewed the message. You are asked for confirmation before each new domain is contacted."), 0, 0},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static const setting identd_settings[] =
|
|
{
|
|
{ST_HEADER, N_("Identd Server"), 0, 0, 0, 0},
|
|
{ST_TOGGLE, N_("Enabled"), P_OFFINTNL(hex_identd_server), N_("Server will respond with the networks username"), 0, 1},
|
|
{ST_NUMBER, N_("Port:"), P_OFFINTNL(hex_identd_port), N_("You must have permissions to listen on this port. "
|
|
"If not 113 (0 defaults to this) then you must configure port-forwarding."), 0, 65535},
|
|
|
|
{ST_END, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
#define setup_get_str(pr,set) (((char *)pr)+set->offset)
|
|
#define setup_get_int(pr,set) *(((int *)pr)+set->offset)
|
|
#define setup_get_int3(pr,off) *(((int *)pr)+off)
|
|
|
|
#define setup_set_int(pr,set,num) *((int *)pr+set->offset)=num
|
|
#define setup_set_str(pr,set,str) strcpy(((char *)pr)+set->offset,str)
|
|
|
|
typedef enum
|
|
{
|
|
SETUP_ALIGN_START,
|
|
SETUP_ALIGN_CENTER,
|
|
SETUP_ALIGN_FILL
|
|
} setup_align;
|
|
|
|
static GtkAlign
|
|
setup_align_to_gtk (setup_align align)
|
|
{
|
|
switch (align)
|
|
{
|
|
case SETUP_ALIGN_FILL:
|
|
return GTK_ALIGN_FILL;
|
|
case SETUP_ALIGN_CENTER:
|
|
return GTK_ALIGN_CENTER;
|
|
case SETUP_ALIGN_START:
|
|
default:
|
|
return GTK_ALIGN_START;
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_table_attach (GtkWidget *table, GtkWidget *child,
|
|
guint left_attach, guint right_attach,
|
|
guint top_attach, guint bottom_attach,
|
|
gboolean hexpand, gboolean vexpand,
|
|
setup_align halign, setup_align valign,
|
|
guint xpad, guint ypad)
|
|
{
|
|
gtk_widget_set_hexpand (child, hexpand);
|
|
gtk_widget_set_vexpand (child, vexpand);
|
|
gtk_widget_set_halign (child, setup_align_to_gtk (halign));
|
|
gtk_widget_set_valign (child, setup_align_to_gtk (valign));
|
|
gtk_widget_set_margin_start (child, xpad);
|
|
gtk_widget_set_margin_end (child, xpad);
|
|
gtk_widget_set_margin_top (child, ypad);
|
|
gtk_widget_set_margin_bottom (child, ypad);
|
|
|
|
gtk_grid_attach (GTK_GRID (table), child, left_attach, top_attach,
|
|
right_attach - left_attach, bottom_attach - top_attach);
|
|
}
|
|
|
|
|
|
static void
|
|
setup_3oggle_cb (GtkToggleButton *but, unsigned int *setting)
|
|
{
|
|
*setting = gtk_toggle_button_get_active (but);
|
|
}
|
|
|
|
static void
|
|
setup_headlabel (GtkWidget *tab, int row, int col, char *text)
|
|
{
|
|
GtkWidget *label;
|
|
char buf[128];
|
|
char *sp;
|
|
|
|
g_snprintf (buf, sizeof (buf), "<b><span size=\"smaller\">%s</span></b>", text);
|
|
sp = strchr (buf + 17, ' ');
|
|
if (sp)
|
|
*sp = '\n';
|
|
|
|
label = gtk_label_new (NULL);
|
|
gtk_label_set_markup (GTK_LABEL (label), buf);
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
setup_table_attach (tab, label, col, col + 1, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER, 4, 0);
|
|
}
|
|
|
|
static void
|
|
setup_create_alert_header (GtkWidget *tab, int row, const setting *set)
|
|
{
|
|
setup_headlabel (tab, row, 3, _("Channel Message"));
|
|
setup_headlabel (tab, row, 4, _("Private Message"));
|
|
setup_headlabel (tab, row, 5, _("Highlighted Message"));
|
|
}
|
|
|
|
/* makes 3 toggles side-by-side */
|
|
|
|
static void
|
|
setup_create_3oggle (GtkWidget *tab, int row, const setting *set)
|
|
{
|
|
GtkWidget *label, *wid;
|
|
int *offsets = (int *)set->list;
|
|
|
|
label = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
if (set->tooltip)
|
|
{
|
|
gtk_widget_set_tooltip_text (label, _(set->tooltip));
|
|
}
|
|
setup_table_attach (tab, label, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
wid = gtk_check_button_new ();
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid),
|
|
setup_get_int3 (&setup_prefs, offsets[0]));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_3oggle_cb), ((int *)&setup_prefs) + offsets[0]);
|
|
setup_table_attach (tab, wid, 3, 4, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_CENTER, SETUP_ALIGN_CENTER, 0, 0);
|
|
|
|
wid = gtk_check_button_new ();
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid),
|
|
setup_get_int3 (&setup_prefs, offsets[1]));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_3oggle_cb), ((int *)&setup_prefs) + offsets[1]);
|
|
setup_table_attach (tab, wid, 4, 5, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_CENTER, SETUP_ALIGN_CENTER, 0, 0);
|
|
|
|
wid = gtk_check_button_new ();
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid),
|
|
setup_get_int3 (&setup_prefs, offsets[2]));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_3oggle_cb), ((int *)&setup_prefs) + offsets[2]);
|
|
setup_table_attach (tab, wid, 5, 6, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_CENTER, SETUP_ALIGN_CENTER, 0, 0);
|
|
}
|
|
|
|
static void
|
|
setup_toggle_cb (GtkToggleButton *but, const setting *set)
|
|
{
|
|
GtkWidget *label, *disable_wid;
|
|
|
|
setup_set_int (&setup_prefs, set, gtk_toggle_button_get_active (but));
|
|
|
|
/* does this toggle also enable/disable another widget? */
|
|
disable_wid = g_object_get_data (G_OBJECT (but), "nxt");
|
|
if (disable_wid)
|
|
{
|
|
gtk_widget_set_sensitive (disable_wid, gtk_toggle_button_get_active (but));
|
|
label = g_object_get_data (G_OBJECT (disable_wid), "lbl");
|
|
gtk_widget_set_sensitive (label, gtk_toggle_button_get_active (but));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_toggle_sensitive_cb (GtkToggleButton *but, GtkWidget *wid)
|
|
{
|
|
gtk_widget_set_sensitive (wid, gtk_toggle_button_get_active (but));
|
|
}
|
|
|
|
static void
|
|
setup_topicbar_inline_toggled_cb (GtkToggleButton *but, gpointer userdata)
|
|
{
|
|
(void) userdata;
|
|
|
|
if (setup_topicbar_multiline_toggle)
|
|
gtk_widget_set_sensitive (setup_topicbar_multiline_toggle,
|
|
!gtk_toggle_button_get_active (but));
|
|
}
|
|
|
|
static void
|
|
setup_create_toggleR (GtkWidget *tab, int row, const setting *set)
|
|
{
|
|
GtkWidget *wid;
|
|
|
|
wid = gtk_check_button_new_with_label (_(set->label));
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid),
|
|
setup_get_int (&setup_prefs, set));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_toggle_cb), (gpointer)set);
|
|
if (set->tooltip)
|
|
gtk_widget_set_tooltip_text (wid, _(set->tooltip));
|
|
setup_table_attach (tab, wid, 4, 5, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_toggleL (GtkWidget *tab, int row, const setting *set)
|
|
{
|
|
GtkWidget *wid;
|
|
|
|
wid = gtk_check_button_new_with_label (_(set->label));
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid),
|
|
setup_get_int (&setup_prefs, set));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_toggle_cb), (gpointer)set);
|
|
if (set->offset == STRUCT_OFFSET_INT (struct zoitechatprefs, hex_gui_mode_buttons_inline))
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_topicbar_inline_toggled_cb), NULL);
|
|
if (set->offset == STRUCT_OFFSET_INT (struct zoitechatprefs, hex_gui_topicbar_multiline))
|
|
{
|
|
setup_topicbar_multiline_toggle = wid;
|
|
gtk_widget_set_sensitive (wid, !setup_prefs.hex_gui_mode_buttons_inline);
|
|
}
|
|
if (set->tooltip)
|
|
gtk_widget_set_tooltip_text (wid, _(set->tooltip));
|
|
setup_table_attach (tab, wid, 2, row==6 ? 6 : 4, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, LABEL_INDENT, 0);
|
|
|
|
return wid;
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_italic_label (char *text)
|
|
{
|
|
GtkWidget *label;
|
|
char buf[256];
|
|
|
|
label = gtk_label_new (NULL);
|
|
g_snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", text);
|
|
gtk_label_set_markup (GTK_LABEL (label), buf);
|
|
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
|
|
|
return label;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
const setting *set;
|
|
GtkSpinButton *spin;
|
|
GtkComboBox *unit;
|
|
} setup_dcc_speed_data;
|
|
|
|
static gboolean
|
|
setup_is_dcc_speed_setting (const setting *set)
|
|
{
|
|
return set->offset == P_OFFINTNL (hex_dcc_max_send_cps)
|
|
|| set->offset == P_OFFINTNL (hex_dcc_max_get_cps)
|
|
|| set->offset == P_OFFINTNL (hex_dcc_global_max_send_cps)
|
|
|| set->offset == P_OFFINTNL (hex_dcc_global_max_get_cps);
|
|
}
|
|
|
|
static int
|
|
setup_dcc_speed_multiplier (GtkComboBox *combo)
|
|
{
|
|
return gtk_combo_box_get_active (combo) == 1 ? 1024 * 1024 : 1024;
|
|
}
|
|
|
|
static void
|
|
setup_dcc_speed_spin_range (setup_dcc_speed_data *data)
|
|
{
|
|
int max = data->set->extra / setup_dcc_speed_multiplier (data->unit);
|
|
gtk_spin_button_set_range (data->spin, 0, max > 0 ? max : 0);
|
|
}
|
|
|
|
static void
|
|
setup_dcc_speed_store (setup_dcc_speed_data *data)
|
|
{
|
|
int value = gtk_spin_button_get_value_as_int (data->spin);
|
|
int speed = value * setup_dcc_speed_multiplier (data->unit);
|
|
if (speed > data->set->extra)
|
|
speed = data->set->extra;
|
|
setup_set_int (&setup_prefs, data->set, speed);
|
|
}
|
|
|
|
static void
|
|
setup_dcc_speed_spin_cb (GtkSpinButton *spin, setup_dcc_speed_data *data)
|
|
{
|
|
(void)spin;
|
|
setup_dcc_speed_store (data);
|
|
}
|
|
|
|
static void
|
|
setup_dcc_speed_unit_cb (GtkComboBox *combo, setup_dcc_speed_data *data)
|
|
{
|
|
int speed = setup_get_int (&setup_prefs, data->set);
|
|
int multiplier;
|
|
int value;
|
|
|
|
(void)combo;
|
|
setup_dcc_speed_spin_range (data);
|
|
multiplier = setup_dcc_speed_multiplier (data->unit);
|
|
value = (speed + (multiplier / 2)) / multiplier;
|
|
gtk_spin_button_set_value (data->spin, value);
|
|
setup_dcc_speed_store (data);
|
|
}
|
|
|
|
static void
|
|
setup_spin_cb (GtkSpinButton *spin, const setting *set)
|
|
{
|
|
setup_set_int (&setup_prefs, set, gtk_spin_button_get_value_as_int (spin));
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_spin (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
GtkWidget *label, *wid, *rbox;
|
|
char *text;
|
|
|
|
label = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, label, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
rbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
|
|
gtk_widget_set_halign (rbox, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (rbox, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, rbox, 3, 4, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
wid = gtk_spin_button_new_with_range (0, set->extra, 1);
|
|
g_object_set_data (G_OBJECT (wid), "lbl", label);
|
|
if (set->tooltip)
|
|
gtk_widget_set_tooltip_text (wid, _(set->tooltip));
|
|
if (setup_is_dcc_speed_setting (set))
|
|
{
|
|
GtkWidget *unit;
|
|
setup_dcc_speed_data *data = g_new0 (setup_dcc_speed_data, 1);
|
|
int speed = setup_get_int (&setup_prefs, set);
|
|
int use_mib = speed >= (1024 * 1024) && speed % (1024 * 1024) == 0;
|
|
int multiplier;
|
|
|
|
data->set = set;
|
|
data->spin = GTK_SPIN_BUTTON (wid);
|
|
|
|
unit = gtk_combo_box_text_new ();
|
|
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (unit), _("KiB/s"));
|
|
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (unit), _("MiB/s"));
|
|
gtk_combo_box_set_wrap_width (GTK_COMBO_BOX (unit), 1);
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (unit), use_mib ? 1 : 0);
|
|
data->unit = GTK_COMBO_BOX (unit);
|
|
|
|
setup_dcc_speed_spin_range (data);
|
|
multiplier = setup_dcc_speed_multiplier (data->unit);
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid), (speed + (multiplier / 2)) / multiplier);
|
|
|
|
g_signal_connect (G_OBJECT (wid), "value-changed",
|
|
G_CALLBACK (setup_dcc_speed_spin_cb), data);
|
|
g_signal_connect (G_OBJECT (unit), "changed",
|
|
G_CALLBACK (setup_dcc_speed_unit_cb), data);
|
|
|
|
gtk_box_pack_start (GTK_BOX (rbox), wid, 0, 0, 0);
|
|
gtk_box_pack_start (GTK_BOX (rbox), unit, 0, 0, 6);
|
|
} else
|
|
{
|
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (wid),
|
|
setup_get_int (&setup_prefs, set));
|
|
g_signal_connect (G_OBJECT (wid), "value-changed",
|
|
G_CALLBACK (setup_spin_cb), (gpointer)set);
|
|
gtk_box_pack_start (GTK_BOX (rbox), wid, 0, 0, 0);
|
|
}
|
|
|
|
if (set->list)
|
|
{
|
|
text = _((char *)set->list);
|
|
if (text[0] == '!')
|
|
label = setup_create_italic_label (text + 1);
|
|
else
|
|
label = gtk_label_new (text);
|
|
gtk_box_pack_start (GTK_BOX (rbox), label, 0, 0, 6);
|
|
}
|
|
|
|
return wid;
|
|
}
|
|
|
|
static guint setup_trans_apply_tag = 0;
|
|
/* the window opacity the dialog opened with, so cancelling can undo the
|
|
* live preview done by the slider */
|
|
static int setup_transparency_snapshot;
|
|
|
|
static gint
|
|
setup_apply_trans (gpointer userdata)
|
|
{
|
|
prefs.hex_gui_transparency = setup_prefs.hex_gui_transparency;
|
|
if (current_sess)
|
|
gtk_widget_set_opacity (current_sess->gui->window,
|
|
(prefs.hex_gui_transparency / 255.));
|
|
|
|
setup_trans_apply_tag = 0;
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
setup_hscale_cb (GtkRange *wid, const setting *set)
|
|
{
|
|
setup_set_int (&setup_prefs, set, (int) gtk_range_get_value (wid));
|
|
|
|
if (setup_trans_apply_tag == 0)
|
|
setup_trans_apply_tag = g_idle_add ((GSourceFunc) setup_apply_trans, NULL);
|
|
}
|
|
|
|
static void
|
|
setup_create_hscale (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
GtkWidget *wid;
|
|
|
|
wid = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (wid, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
wid = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0., 255., 1.);
|
|
gtk_scale_set_value_pos (GTK_SCALE (wid), GTK_POS_RIGHT);
|
|
gtk_range_set_value (GTK_RANGE (wid), setup_get_int (&setup_prefs, set));
|
|
g_signal_connect (G_OBJECT(wid), "value-changed",
|
|
G_CALLBACK (setup_hscale_cb), (gpointer)set);
|
|
setup_table_attach (table, wid, 3, 6, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
#ifndef WIN32 /* Windows always supports this */
|
|
/* Only used for transparency currently */
|
|
if (current_sess &&
|
|
!gdk_screen_is_composited (gtk_widget_get_screen (current_sess->gui->window)))
|
|
gtk_widget_set_sensitive (wid, FALSE);
|
|
#endif
|
|
}
|
|
|
|
|
|
static GtkWidget *proxy_user;
|
|
static GtkWidget *proxy_pass;
|
|
|
|
static void
|
|
setup_menu_cb (GtkWidget *cbox, const setting *set)
|
|
{
|
|
int n = gtk_combo_box_get_active (GTK_COMBO_BOX (cbox));
|
|
|
|
/* set the prefs.<field> */
|
|
setup_set_int (&setup_prefs, set, n + set->extra);
|
|
|
|
if (set->list == proxytypes)
|
|
{
|
|
/* only HTTP and SOCKS5 can use a username/pass */
|
|
gtk_widget_set_sensitive (proxy_user, (n == 3 || n == 4 || n == 5));
|
|
gtk_widget_set_sensitive (proxy_pass, (n == 3 || n == 4 || n == 5));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_radio_cb (GtkWidget *item, const setting *set)
|
|
{
|
|
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item)))
|
|
{
|
|
int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "n"));
|
|
/* set the prefs.<field> */
|
|
setup_set_int (&setup_prefs, set, n);
|
|
}
|
|
}
|
|
|
|
static int
|
|
setup_create_radio (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
GtkWidget *wid, *hbox;
|
|
int i;
|
|
const char **text = (const char **)set->list;
|
|
GSList *group;
|
|
|
|
wid = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (wid, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
|
|
setup_table_attach (table, hbox, 3, 4, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
i = 0;
|
|
group = NULL;
|
|
while (text[i])
|
|
{
|
|
if (text[i][0] != 0)
|
|
{
|
|
wid = gtk_radio_button_new_with_mnemonic (group, _(text[i]));
|
|
/*if (set->tooltip)
|
|
gtk_widget_set_tooltip_text (wid, _(set->tooltip));*/
|
|
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (wid));
|
|
gtk_container_add (GTK_CONTAINER (hbox), wid);
|
|
if (i == setup_get_int (&setup_prefs, set))
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid), TRUE);
|
|
g_object_set_data (G_OBJECT (wid), "n", GINT_TO_POINTER (i));
|
|
g_signal_connect (G_OBJECT (wid), "toggled",
|
|
G_CALLBACK (setup_radio_cb), (gpointer)set);
|
|
}
|
|
i++;
|
|
row++;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
static const char *id_strings[] =
|
|
{
|
|
"",
|
|
"*",
|
|
"%C4*%C18%B%B",
|
|
"%U"
|
|
};
|
|
|
|
static void
|
|
setup_id_menu_cb (GtkWidget *item, char *dest)
|
|
{
|
|
int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "n"));
|
|
|
|
strcpy (dest, id_strings[n]);
|
|
}
|
|
|
|
static void
|
|
setup_create_id_menu (GtkWidget *table, char *label, int row, char *dest)
|
|
{
|
|
GtkWidget *wid, *menu, *item;
|
|
int i, def = 0;
|
|
static const char *text[] =
|
|
{
|
|
("(disabled)"),
|
|
("A star (*)"),
|
|
("A red star (*)"),
|
|
("Underlined")
|
|
};
|
|
|
|
wid = gtk_label_new (label);
|
|
gtk_widget_set_halign (wid, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
wid = gtk_option_menu_new ();
|
|
menu = gtk_menu_new ();
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (strcmp (id_strings[i], dest) == 0)
|
|
{
|
|
def = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
while (text[i])
|
|
{
|
|
item = gtk_menu_item_new_with_label (_(text[i]));
|
|
g_object_set_data (G_OBJECT (item), "n", GINT_TO_POINTER (i));
|
|
|
|
gtk_widget_show (item);
|
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
G_CALLBACK (setup_id_menu_cb), dest);
|
|
i++;
|
|
}
|
|
|
|
gtk_option_menu_set_menu (GTK_OPTION_MENU (wid), menu);
|
|
gtk_option_menu_set_history (GTK_OPTION_MENU (wid), def);
|
|
|
|
setup_table_attach (table, wid, 3, 4, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
}
|
|
|
|
*/
|
|
|
|
static void
|
|
setup_create_menu (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
GtkWidget *wid, *cbox, *box;
|
|
const char **text = (const char **)set->list;
|
|
int i;
|
|
|
|
wid = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (wid, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
cbox = gtk_combo_box_text_new ();
|
|
|
|
for (i = 0; text[i]; i++)
|
|
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cbox), _(text[i]));
|
|
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (cbox),
|
|
setup_get_int (&setup_prefs, set) - set->extra);
|
|
g_signal_connect (G_OBJECT (cbox), "changed",
|
|
G_CALLBACK (setup_menu_cb), (gpointer)set);
|
|
|
|
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), cbox, 0, 0, 0);
|
|
setup_table_attach (table, box, 3, 4, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
}
|
|
|
|
static void
|
|
setup_filereq_cb (GtkWidget *entry, char *file)
|
|
{
|
|
if (file)
|
|
{
|
|
if (file[0])
|
|
gtk_entry_set_text (GTK_ENTRY (entry), file);
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_browsefile_response_cb (GtkNativeDialog *dialog, gint response, gpointer user_data)
|
|
{
|
|
GtkWidget *entry = user_data;
|
|
|
|
if (response == GTK_RESPONSE_ACCEPT)
|
|
{
|
|
char *file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
|
setup_filereq_cb (entry, file);
|
|
g_free (file);
|
|
}
|
|
|
|
g_object_unref (dialog);
|
|
}
|
|
|
|
static void
|
|
setup_browsefile_cb (GtkWidget *button, GtkWidget *entry)
|
|
{
|
|
GtkFileChooserNative *dialog;
|
|
GtkFileFilter *filefilter;
|
|
const char *current;
|
|
char *dirname;
|
|
|
|
(void)button;
|
|
dialog = gtk_file_chooser_native_new (_("Select an Image File"),
|
|
GTK_WINDOW (setup_window),
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
_("_Open"),
|
|
_("_Cancel"));
|
|
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
|
|
|
current = gtk_entry_get_text (GTK_ENTRY (entry));
|
|
if (current && current[0])
|
|
{
|
|
dirname = g_path_get_dirname (current);
|
|
if (dirname && dirname[0] && g_file_test (dirname, G_FILE_TEST_IS_DIR))
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dirname);
|
|
else if (g_file_test (current, G_FILE_TEST_IS_DIR))
|
|
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), current);
|
|
g_free (dirname);
|
|
}
|
|
|
|
filefilter = gtk_file_filter_new ();
|
|
#ifdef WIN32
|
|
gtk_file_filter_add_pattern (filefilter, "*.png");
|
|
gtk_file_filter_add_pattern (filefilter, "*.tiff");
|
|
gtk_file_filter_add_pattern (filefilter, "*.gif");
|
|
gtk_file_filter_add_pattern (filefilter, "*.jpeg");
|
|
gtk_file_filter_add_pattern (filefilter, "*.jpg");
|
|
#else
|
|
gtk_file_filter_add_mime_type (filefilter, "image/*");
|
|
#endif
|
|
gtk_file_filter_set_name (filefilter, _("Images"));
|
|
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filefilter);
|
|
|
|
g_signal_connect (G_OBJECT (dialog), "response",
|
|
G_CALLBACK (setup_browsefile_response_cb), entry);
|
|
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
|
}
|
|
|
|
|
|
static void
|
|
setup_fontchooser_response (GtkDialog *dialog, gint response, GtkWidget *entry)
|
|
{
|
|
if (response == GTK_RESPONSE_OK)
|
|
{
|
|
char *font_name;
|
|
|
|
font_name = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (dialog));
|
|
if (font_name)
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (entry), font_name);
|
|
g_free (font_name);
|
|
}
|
|
}
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
font_dialog = NULL;
|
|
}
|
|
|
|
static void
|
|
setup_browsefolder_cb (GtkWidget *button, GtkEntry *entry)
|
|
{
|
|
gtkutil_file_req (GTK_WINDOW (setup_window), _("Select Download Folder"), setup_filereq_cb, entry, (char*)gtk_entry_get_text (entry), NULL, FRF_CHOOSEFOLDER|FRF_MODAL);
|
|
}
|
|
|
|
static void
|
|
setup_browsefont_cb (GtkWidget *button, GtkWidget *entry)
|
|
{
|
|
GtkWidget *dialog;
|
|
const char *font_name;
|
|
|
|
dialog = gtk_font_chooser_dialog_new (_("Select font"), GTK_WINDOW (setup_window));
|
|
theme_manager_attach_window (dialog);
|
|
font_dialog = dialog; /* global var */
|
|
|
|
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
|
|
|
font_name = gtk_entry_get_text (GTK_ENTRY (entry));
|
|
if (font_name[0])
|
|
gtk_font_chooser_set_font (GTK_FONT_CHOOSER (dialog), font_name);
|
|
|
|
g_signal_connect (G_OBJECT (dialog), "response",
|
|
G_CALLBACK (setup_fontchooser_response), entry);
|
|
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
static void
|
|
setup_entry_cb (GtkEntry *entry, setting *set)
|
|
{
|
|
int size;
|
|
int pos;
|
|
unsigned char *p = (unsigned char*)gtk_entry_get_text (entry);
|
|
size_t len = strlen ((const char *) p);
|
|
|
|
/* need to truncate? */
|
|
if (len >= set->extra)
|
|
{
|
|
len = pos = 0;
|
|
while (1)
|
|
{
|
|
size = g_utf8_skip [*p];
|
|
len += size;
|
|
p += size;
|
|
/* truncate to "set->extra" BYTES */
|
|
if (len >= set->extra)
|
|
{
|
|
gtk_editable_delete_text (GTK_EDITABLE (entry), pos, -1);
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
setup_set_str (&setup_prefs, set, gtk_entry_get_text (entry));
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_create_label (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
setup_table_attach (table, setup_create_italic_label (_(set->label)),
|
|
set->extra ? 1 : 3, 5, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_entry (GtkWidget *table, int row, const setting *set)
|
|
{
|
|
GtkWidget *label;
|
|
GtkWidget *wid, *bwid;
|
|
|
|
label = gtk_label_new (_(set->label));
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, label, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
|
|
LABEL_INDENT, 0);
|
|
|
|
wid = gtk_entry_new ();
|
|
g_object_set_data (G_OBJECT (wid), "lbl", label);
|
|
if (set->list)
|
|
gtk_entry_set_visibility (GTK_ENTRY (wid), FALSE);
|
|
if (set->tooltip)
|
|
gtk_widget_set_tooltip_text (wid, _(set->tooltip));
|
|
gtk_entry_set_max_length (GTK_ENTRY (wid), set->extra - 1);
|
|
gtk_entry_set_text (GTK_ENTRY (wid), setup_get_str (&setup_prefs, set));
|
|
g_signal_connect (G_OBJECT (wid), "changed",
|
|
G_CALLBACK (setup_entry_cb), (gpointer)set);
|
|
|
|
if (set->offset == P_OFFSETNL(hex_net_proxy_user))
|
|
proxy_user = wid;
|
|
if (set->offset == P_OFFSETNL(hex_net_proxy_pass))
|
|
proxy_pass = wid;
|
|
|
|
/* only http and Socks5 can auth */
|
|
if ( (set->offset == P_OFFSETNL(hex_net_proxy_pass) ||
|
|
set->offset == P_OFFSETNL(hex_net_proxy_user)) &&
|
|
(setup_prefs.hex_net_proxy_type != 4 && setup_prefs.hex_net_proxy_type != 3 && setup_prefs.hex_net_proxy_type != 5) )
|
|
gtk_widget_set_sensitive (wid, FALSE);
|
|
|
|
if (set->type == ST_ENTRY)
|
|
setup_table_attach (table, wid, 3, 6, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
else
|
|
{
|
|
setup_table_attach (table, wid, 3, 5, row, row + 1, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_CENTER, 0, 0);
|
|
bwid = gtk_button_new_with_label (_("Browse..."));
|
|
setup_table_attach (table, bwid, 5, 6, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
if (set->type == ST_EFILE)
|
|
g_signal_connect (G_OBJECT (bwid), "clicked",
|
|
G_CALLBACK (setup_browsefile_cb), wid);
|
|
if (set->type == ST_EFONT)
|
|
g_signal_connect (G_OBJECT (bwid), "clicked",
|
|
G_CALLBACK (setup_browsefont_cb), wid);
|
|
if (set->type == ST_EFOLDER)
|
|
g_signal_connect (G_OBJECT (bwid), "clicked",
|
|
G_CALLBACK (setup_browsefolder_cb), wid);
|
|
}
|
|
|
|
return wid;
|
|
}
|
|
|
|
static void
|
|
setup_create_header (GtkWidget *table, int row, char *labeltext)
|
|
{
|
|
GtkWidget *label;
|
|
char buf[128];
|
|
|
|
if (row == 0)
|
|
g_snprintf (buf, sizeof (buf), "<b>%s</b>", _(labeltext));
|
|
else
|
|
g_snprintf (buf, sizeof (buf), "\n<b>%s</b>", _(labeltext));
|
|
|
|
label = gtk_label_new (NULL);
|
|
gtk_label_set_markup (GTK_LABEL (label), buf);
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
setup_table_attach (table, label, 0, 4, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER, 0, 5);
|
|
}
|
|
|
|
static void
|
|
setup_create_button (GtkWidget *table, int row, char *label, GCallback callback)
|
|
{
|
|
GtkWidget *but = gtk_button_new_with_label (label);
|
|
setup_table_attach (table, but, 2, 3, row, row + 1, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 5);
|
|
g_signal_connect (G_OBJECT (but), "clicked", callback, NULL);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_frame (void)
|
|
{
|
|
GtkWidget *tab;
|
|
|
|
tab = gtkutil_grid_new (3, 2, FALSE);
|
|
gtk_container_set_border_width (GTK_CONTAINER (tab), 6);
|
|
gtk_grid_set_row_spacing (GTK_GRID (tab), 2);
|
|
gtk_grid_set_column_spacing (GTK_GRID (tab), 3);
|
|
|
|
return tab;
|
|
}
|
|
|
|
static void
|
|
open_data_cb (GtkWidget *button, gpointer data)
|
|
{
|
|
fe_open_url (get_xdir ());
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_page (const setting *set)
|
|
{
|
|
int i, row, do_disable;
|
|
GtkWidget *tab;
|
|
GtkWidget *wid = NULL, *parentwid = NULL;
|
|
|
|
tab = setup_create_frame ();
|
|
gtk_container_set_border_width (GTK_CONTAINER (tab), 6);
|
|
|
|
i = row = do_disable = 0;
|
|
while (set[i].type != ST_END)
|
|
{
|
|
switch (set[i].type)
|
|
{
|
|
case ST_HEADER:
|
|
setup_create_header (tab, row, set[i].label);
|
|
break;
|
|
case ST_EFONT:
|
|
case ST_ENTRY:
|
|
case ST_EFILE:
|
|
case ST_EFOLDER:
|
|
wid = setup_create_entry (tab, row, &set[i]);
|
|
break;
|
|
case ST_TOGGLR:
|
|
row--;
|
|
setup_create_toggleR (tab, row, &set[i]);
|
|
break;
|
|
case ST_TOGGLE:
|
|
wid = setup_create_toggleL (tab, row, &set[i]);
|
|
if (set[i].extra)
|
|
do_disable = set[i].extra;
|
|
break;
|
|
case ST_3OGGLE:
|
|
setup_create_3oggle (tab, row, &set[i]);
|
|
break;
|
|
case ST_MENU:
|
|
setup_create_menu (tab, row, &set[i]);
|
|
break;
|
|
case ST_RADIO:
|
|
row += setup_create_radio (tab, row, &set[i]);
|
|
break;
|
|
case ST_NUMBER:
|
|
wid = setup_create_spin (tab, row, &set[i]);
|
|
break;
|
|
case ST_HSCALE:
|
|
setup_create_hscale (tab, row, &set[i]);
|
|
break;
|
|
case ST_LABEL:
|
|
setup_create_label (tab, row, &set[i]);
|
|
break;
|
|
case ST_ALERTHEAD:
|
|
setup_create_alert_header (tab, row, &set[i]);
|
|
}
|
|
|
|
if (do_disable)
|
|
{
|
|
if (GTK_IS_WIDGET (parentwid))
|
|
{
|
|
g_signal_connect (G_OBJECT (parentwid), "toggled", G_CALLBACK(setup_toggle_sensitive_cb), wid);
|
|
gtk_widget_set_sensitive (wid, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (parentwid)));
|
|
do_disable--;
|
|
if (!do_disable)
|
|
parentwid = NULL;
|
|
}
|
|
else
|
|
parentwid = wid;
|
|
}
|
|
|
|
i++;
|
|
row++;
|
|
}
|
|
|
|
if (set == logging_settings)
|
|
{
|
|
setup_create_button (tab, row, _("Open Data Folder"), G_CALLBACK(open_data_cb));
|
|
}
|
|
|
|
return tab;
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_theme_page (void)
|
|
{
|
|
return theme_preferences_create_page (GTK_WINDOW (setup_window),
|
|
&setup_prefs,
|
|
&color_change);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_appearance_page (void)
|
|
{
|
|
GtkWidget *box;
|
|
GtkWidget *appearance_page;
|
|
GtkWidget *theme_label;
|
|
GtkWidget *theme_page;
|
|
GtkWidget *advanced_page;
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
|
appearance_page = setup_create_page (appearance_settings);
|
|
theme_label = gtk_label_new (NULL);
|
|
theme_page = setup_create_theme_page ();
|
|
advanced_page = setup_create_page (appearance_advanced_settings);
|
|
|
|
{
|
|
char *markup = g_markup_printf_escaped ("<b>%s</b>", _("GTK3 Theme"));
|
|
gtk_label_set_markup (GTK_LABEL (theme_label), markup);
|
|
g_free (markup);
|
|
}
|
|
gtk_widget_set_halign (theme_label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (theme_label, GTK_ALIGN_CENTER);
|
|
gtk_widget_set_margin_start (theme_label, 2);
|
|
gtk_widget_set_margin_end (theme_label, 2);
|
|
gtk_widget_set_margin_top (theme_label, 1);
|
|
gtk_widget_set_margin_bottom (theme_label, 1);
|
|
|
|
gtk_box_pack_start (GTK_BOX (box), appearance_page, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), theme_label, FALSE, FALSE, 2);
|
|
gtk_box_pack_start (GTK_BOX (box), theme_page, FALSE, FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (box), advanced_page, FALSE, FALSE, 0);
|
|
|
|
return box;
|
|
}
|
|
|
|
/* === GLOBALS for sound GUI === */
|
|
|
|
static GtkWidget *sndfile_entry;
|
|
static int ignore_changed = FALSE;
|
|
|
|
extern struct text_event te[]; /* text.c */
|
|
extern char *sound_files[];
|
|
|
|
static void
|
|
setup_snd_populate (GtkTreeView * treeview)
|
|
{
|
|
GtkListStore *store;
|
|
GtkTreeIter iter;
|
|
GtkTreeSelection *sel;
|
|
GtkTreePath *path;
|
|
int i;
|
|
|
|
sel = gtk_tree_view_get_selection (treeview);
|
|
store = (GtkListStore *)gtk_tree_view_get_model (treeview);
|
|
|
|
for (i = NUM_XP-1; i >= 0; i--)
|
|
{
|
|
gtk_list_store_prepend (store, &iter);
|
|
if (sound_files[i])
|
|
gtk_list_store_set (store, &iter, 0, te[i].name, 1, sound_files[i], 2, i, -1);
|
|
else
|
|
gtk_list_store_set (store, &iter, 0, te[i].name, 1, "", 2, i, -1);
|
|
if (i == last_selected_row)
|
|
{
|
|
gtk_tree_selection_select_iter (sel, &iter);
|
|
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
|
|
if (path)
|
|
{
|
|
gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.5);
|
|
gtk_tree_view_set_cursor (treeview, path, NULL, FALSE);
|
|
gtk_tree_path_free (path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
setup_snd_get_selected (GtkTreeSelection *sel, GtkTreeIter *iter)
|
|
{
|
|
int n;
|
|
GtkTreeModel *model;
|
|
|
|
if (!gtk_tree_selection_get_selected (sel, &model, iter))
|
|
return -1;
|
|
|
|
gtk_tree_model_get (model, iter, 2, &n, -1);
|
|
return n;
|
|
}
|
|
|
|
static void
|
|
setup_snd_row_cb (GtkTreeSelection *sel, gpointer user_data)
|
|
{
|
|
int n;
|
|
GtkTreeIter iter;
|
|
|
|
n = setup_snd_get_selected (sel, &iter);
|
|
if (n == -1)
|
|
return;
|
|
last_selected_row = n;
|
|
|
|
ignore_changed = TRUE;
|
|
if (sound_files[n])
|
|
gtk_entry_set_text (GTK_ENTRY (sndfile_entry), sound_files[n]);
|
|
else
|
|
gtk_entry_set_text (GTK_ENTRY (sndfile_entry), "");
|
|
ignore_changed = FALSE;
|
|
}
|
|
|
|
static void
|
|
setup_snd_add_columns (GtkTreeView * treeview)
|
|
{
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeModel *model;
|
|
|
|
/* event column */
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
|
|
-1, _("Event"), renderer,
|
|
"text", 0, NULL);
|
|
|
|
/* file column */
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
|
|
-1, _("Sound file"), renderer,
|
|
"text", 1, NULL);
|
|
|
|
model = GTK_TREE_MODEL (gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT));
|
|
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model);
|
|
g_object_unref (model);
|
|
}
|
|
|
|
static void
|
|
setup_snd_filereq_cb (GtkWidget *entry, char *file)
|
|
{
|
|
if (file)
|
|
{
|
|
if (file[0])
|
|
{
|
|
/* Use just the filename if the given sound file is in the default <config>/sounds directory.
|
|
* We're comparing absolute paths so this won't work in portable mode which uses a relative path.
|
|
*/
|
|
if (!strcmp (g_path_get_dirname (file), g_build_filename (get_xdir (), ZOITECHAT_SOUND_DIR, NULL)))
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (entry), g_path_get_basename (file));
|
|
}
|
|
else
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (entry), file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry)
|
|
{
|
|
char *sounds_dir = g_build_filename (get_xdir (), ZOITECHAT_SOUND_DIR, NULL);
|
|
char *filter = NULL;
|
|
int filter_type;
|
|
#ifdef WIN32 /* win32 only supports wav, others could support anything */
|
|
filter = "*.wav";
|
|
filter_type = FRF_EXTENSIONS;
|
|
#else
|
|
filter = "audio/*";
|
|
filter_type = FRF_MIMETYPES;
|
|
#endif
|
|
|
|
gtkutil_file_req (GTK_WINDOW (setup_window), _("Select a sound file"), setup_snd_filereq_cb, entry,
|
|
sounds_dir, filter, FRF_MODAL|FRF_FILTERISINITIAL|filter_type);
|
|
g_free (sounds_dir);
|
|
}
|
|
|
|
static void
|
|
setup_snd_play_cb (GtkWidget *button, GtkEntry *entry)
|
|
{
|
|
sound_play (gtk_entry_get_text (entry), FALSE);
|
|
}
|
|
|
|
static void
|
|
setup_snd_changed_cb (GtkEntry *ent, GtkTreeView *tree)
|
|
{
|
|
int n;
|
|
GtkTreeIter iter;
|
|
GtkListStore *store;
|
|
GtkTreeSelection *sel;
|
|
|
|
if (ignore_changed)
|
|
return;
|
|
|
|
sel = gtk_tree_view_get_selection (tree);
|
|
n = setup_snd_get_selected (sel, &iter);
|
|
if (n == -1)
|
|
return;
|
|
|
|
/* get the new sound file */
|
|
g_free (sound_files[n]);
|
|
sound_files[n] = g_strdup (gtk_entry_get_text (GTK_ENTRY (ent)));
|
|
|
|
/* update the TreeView list */
|
|
store = (GtkListStore *)gtk_tree_view_get_model (tree);
|
|
gtk_list_store_set (store, &iter, 1, sound_files[n], -1);
|
|
|
|
gtk_widget_set_sensitive (cancel_button, FALSE);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_create_sound_page (void)
|
|
{
|
|
GtkWidget *vbox1;
|
|
GtkWidget *vbox2;
|
|
GtkWidget *scrolledwindow1;
|
|
GtkWidget *sound_tree;
|
|
GtkWidget *table1;
|
|
GtkWidget *sound_label;
|
|
GtkWidget *sound_browse;
|
|
GtkWidget *sound_play;
|
|
GtkTreeSelection *sel;
|
|
|
|
vbox1 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox1), 6);
|
|
gtk_widget_show (vbox1);
|
|
|
|
vbox2 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
|
|
gtk_widget_show (vbox2);
|
|
gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);
|
|
|
|
scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_widget_show (scrolledwindow1);
|
|
gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow1, TRUE, TRUE, 0);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow1),
|
|
GTK_SHADOW_IN);
|
|
|
|
sound_tree = gtk_tree_view_new ();
|
|
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sound_tree));
|
|
gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
|
|
setup_snd_add_columns (GTK_TREE_VIEW (sound_tree));
|
|
setup_snd_populate (GTK_TREE_VIEW (sound_tree));
|
|
g_signal_connect (G_OBJECT (sel), "changed",
|
|
G_CALLBACK (setup_snd_row_cb), NULL);
|
|
gtk_widget_show (sound_tree);
|
|
gtk_container_add (GTK_CONTAINER (scrolledwindow1), sound_tree);
|
|
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (sound_tree), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
|
|
|
|
table1 = gtkutil_grid_new (2, 3, FALSE);
|
|
gtk_widget_show (table1);
|
|
gtk_box_pack_start (GTK_BOX (vbox2), table1, FALSE, TRUE, 8);
|
|
gtk_grid_set_row_spacing (GTK_GRID (table1), 2);
|
|
gtk_grid_set_column_spacing (GTK_GRID (table1), 4);
|
|
|
|
sound_label = gtk_label_new_with_mnemonic (_("Sound file:"));
|
|
gtk_widget_show (sound_label);
|
|
setup_table_attach (table1, sound_label, 0, 1, 0, 1, FALSE, FALSE,
|
|
SETUP_ALIGN_START, SETUP_ALIGN_CENTER, 0, 0);
|
|
|
|
sndfile_entry = gtk_entry_new ();
|
|
g_signal_connect (G_OBJECT (sndfile_entry), "changed",
|
|
G_CALLBACK (setup_snd_changed_cb), sound_tree);
|
|
gtk_widget_show (sndfile_entry);
|
|
setup_table_attach (table1, sndfile_entry, 0, 1, 1, 2, TRUE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
sound_browse = gtk_button_new_with_mnemonic (_("_Browse..."));
|
|
g_signal_connect (G_OBJECT (sound_browse), "clicked",
|
|
G_CALLBACK (setup_snd_browse_cb), sndfile_entry);
|
|
gtk_widget_show (sound_browse);
|
|
setup_table_attach (table1, sound_browse, 1, 2, 1, 2, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
sound_play = gtkutil_button_new_from_stock ("gtk-media-play", _("_Play"));
|
|
g_signal_connect (G_OBJECT (sound_play), "clicked",
|
|
G_CALLBACK (setup_snd_play_cb), sndfile_entry);
|
|
gtk_widget_show (sound_play);
|
|
setup_table_attach (table1, sound_play, 2, 3, 1, 2, FALSE, FALSE,
|
|
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
|
|
|
|
setup_snd_row_cb (sel, NULL);
|
|
|
|
return vbox1;
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_page_from_settings (const setting *settings)
|
|
{
|
|
return setup_create_page (settings);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_page_from_appearance (const setting *settings)
|
|
{
|
|
(void)settings;
|
|
return setup_create_appearance_page ();
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_page_from_sound (const setting *settings)
|
|
{
|
|
(void)settings;
|
|
return setup_create_sound_page ();
|
|
}
|
|
|
|
static void
|
|
setup_add_page (const char *title, GtkWidget *book, GtkWidget *tab)
|
|
{
|
|
GtkWidget *label, *vvbox, *viewport;
|
|
GtkScrolledWindow *sw;
|
|
char buf[128];
|
|
|
|
vvbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
|
|
|
|
/* label */
|
|
label = gtk_label_new (NULL);
|
|
g_snprintf (buf, sizeof (buf), "<b><big>%s</big></b>", _(title));
|
|
gtk_label_set_markup (GTK_LABEL (label), buf);
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
|
gtk_widget_set_margin_start (label, 2);
|
|
gtk_widget_set_margin_end (label, 2);
|
|
gtk_widget_set_margin_top (label, 1);
|
|
gtk_widget_set_margin_bottom (label, 1);
|
|
gtk_box_pack_start (GTK_BOX (vvbox), label, FALSE, FALSE, 2);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vvbox), tab, TRUE, TRUE, 0);
|
|
|
|
sw = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new (NULL, NULL));
|
|
gtk_scrolled_window_set_shadow_type (sw, GTK_SHADOW_IN);
|
|
gtk_scrolled_window_set_policy (sw, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
gtk_container_add (GTK_CONTAINER (sw), vvbox);
|
|
|
|
viewport = gtk_bin_get_child (GTK_BIN(sw));
|
|
gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
|
|
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (book), GTK_WIDGET(sw), NULL);
|
|
}
|
|
|
|
static void
|
|
setup_register_page (const char *title, GtkWidget *book, setup_page_factory factory, const setting *settings)
|
|
{
|
|
GtkWidget *container;
|
|
|
|
if (setup_page_count >= SETUP_MAX_PAGES)
|
|
return;
|
|
|
|
setup_page_factories[setup_page_count] = factory;
|
|
setup_page_settings[setup_page_count] = settings;
|
|
container = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
|
|
setup_page_containers[setup_page_count] = container;
|
|
setup_add_page (title, book, container);
|
|
setup_page_count++;
|
|
}
|
|
|
|
static void
|
|
setup_ensure_page_created (int page)
|
|
{
|
|
GList *children;
|
|
GtkWidget *page_widget;
|
|
GtkWidget *container;
|
|
|
|
if (page < 0 || page >= setup_page_count)
|
|
return;
|
|
|
|
container = setup_page_containers[page];
|
|
children = gtk_container_get_children (GTK_CONTAINER (container));
|
|
if (children != NULL)
|
|
{
|
|
g_list_free (children);
|
|
return;
|
|
}
|
|
|
|
page_widget = setup_page_factories[page] (setup_page_settings[page]);
|
|
gtk_container_add (GTK_CONTAINER (container), page_widget);
|
|
gtk_widget_show_all (container);
|
|
}
|
|
|
|
static const char *const cata_interface[] =
|
|
{
|
|
N_("Appearance"),
|
|
N_("Input box"),
|
|
N_("User list"),
|
|
N_("Channel switcher"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const cata_chatting[] =
|
|
{
|
|
N_("General"),
|
|
N_("Alerts"),
|
|
N_("Sounds"),
|
|
N_("Logging"),
|
|
N_("Advanced"),
|
|
NULL
|
|
};
|
|
|
|
static const char *const cata_network[] =
|
|
{
|
|
N_("Network setup"),
|
|
N_("File transfers"),
|
|
N_("Identd"),
|
|
NULL
|
|
};
|
|
|
|
static GtkWidget *
|
|
setup_create_pages (GtkWidget *box)
|
|
{
|
|
GtkWidget *book;
|
|
GtkWindow *win = GTK_WINDOW (setup_window);
|
|
|
|
(void)box;
|
|
book = gtk_notebook_new ();
|
|
|
|
memset (setup_page_factories, 0, sizeof (setup_page_factories));
|
|
memset (setup_page_settings, 0, sizeof (setup_page_settings));
|
|
memset (setup_page_containers, 0, sizeof (setup_page_containers));
|
|
setup_page_count = 0;
|
|
|
|
setup_register_page (cata_interface[0], book, setup_page_from_appearance, NULL);
|
|
setup_register_page (cata_interface[1], book, setup_page_from_settings, inputbox_settings);
|
|
setup_register_page (cata_interface[2], book, setup_page_from_settings, userlist_settings);
|
|
setup_register_page (cata_interface[3], book, setup_page_from_settings, tabs_settings);
|
|
|
|
setup_register_page (cata_chatting[0], book, setup_page_from_settings, general_settings);
|
|
|
|
if (!gtkutil_tray_icon_supported (win) && !notification_backend_supported ())
|
|
{
|
|
setup_register_page (cata_chatting[1], book, setup_page_from_settings, alert_settings_unityandnonotifications);
|
|
}
|
|
else if (!gtkutil_tray_icon_supported (win))
|
|
{
|
|
setup_register_page (cata_chatting[1], book, setup_page_from_settings, alert_settings_unity);
|
|
}
|
|
else if (!notification_backend_supported ())
|
|
{
|
|
setup_register_page (cata_chatting[1], book, setup_page_from_settings, alert_settings_nonotifications);
|
|
}
|
|
else
|
|
{
|
|
setup_register_page (cata_chatting[1], book, setup_page_from_settings, alert_settings);
|
|
}
|
|
|
|
setup_register_page (cata_chatting[2], book, setup_page_from_sound, NULL);
|
|
setup_register_page (cata_chatting[3], book, setup_page_from_settings, logging_settings);
|
|
setup_register_page (cata_chatting[4], book, setup_page_from_settings, advanced_settings);
|
|
|
|
setup_register_page (cata_network[0], book, setup_page_from_settings, network_settings);
|
|
setup_register_page (cata_network[1], book, setup_page_from_settings, filexfer_settings);
|
|
setup_register_page (cata_network[2], book, setup_page_from_settings, identd_settings);
|
|
|
|
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (book), FALSE);
|
|
gtk_notebook_set_show_border (GTK_NOTEBOOK (book), FALSE);
|
|
gtk_box_pack_start (GTK_BOX (box), book, TRUE, TRUE, 0);
|
|
|
|
return book;
|
|
}
|
|
|
|
static void
|
|
setup_tree_cb (GtkTreeView *treeview, GtkWidget *book)
|
|
{
|
|
GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *model;
|
|
int page;
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
{
|
|
gtk_tree_model_get (model, &iter, 1, &page, -1);
|
|
if (page != -1)
|
|
{
|
|
setup_ensure_page_created (page);
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (book), page);
|
|
last_selected_page = page;
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
setup_tree_select_filter (GtkTreeSelection *selection, GtkTreeModel *model,
|
|
GtkTreePath *path, gboolean path_selected,
|
|
gpointer data)
|
|
{
|
|
if (gtk_tree_path_get_depth (path) > 1)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
setup_create_tree (GtkWidget *box, GtkWidget *book)
|
|
{
|
|
GtkWidget *tree;
|
|
GtkWidget *frame;
|
|
GtkTreeStore *model;
|
|
GtkTreeIter iter;
|
|
GtkTreeIter child_iter;
|
|
GtkTreeIter *sel_iter = NULL;
|
|
GtkCellRenderer *renderer;
|
|
GtkTreeSelection *sel;
|
|
int i, page;
|
|
|
|
model = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
|
|
|
|
page = 0;
|
|
|
|
gtk_tree_store_append (model, &iter, NULL);
|
|
gtk_tree_store_set (model, &iter, 0, _("Interface"), 1, -1, -1);
|
|
for (i = 0; cata_interface[i]; i++)
|
|
{
|
|
gtk_tree_store_append (model, &child_iter, &iter);
|
|
gtk_tree_store_set (model, &child_iter, 0, _(cata_interface[i]), 1, page, -1);
|
|
if (page == last_selected_page)
|
|
sel_iter = gtk_tree_iter_copy (&child_iter);
|
|
page++;
|
|
}
|
|
|
|
gtk_tree_store_append (model, &iter, NULL);
|
|
gtk_tree_store_set (model, &iter, 0, _("Chatting"), 1, -1, -1);
|
|
for (i = 0; cata_chatting[i]; i++)
|
|
{
|
|
gtk_tree_store_append (model, &child_iter, &iter);
|
|
gtk_tree_store_set (model, &child_iter, 0, _(cata_chatting[i]), 1, page, -1);
|
|
if (page == last_selected_page)
|
|
sel_iter = gtk_tree_iter_copy (&child_iter);
|
|
page++;
|
|
}
|
|
|
|
gtk_tree_store_append (model, &iter, NULL);
|
|
gtk_tree_store_set (model, &iter, 0, _("Network"), 1, -1, -1);
|
|
for (i = 0; cata_network[i]; i++)
|
|
{
|
|
gtk_tree_store_append (model, &child_iter, &iter);
|
|
gtk_tree_store_set (model, &child_iter, 0, _(cata_network[i]), 1, page, -1);
|
|
if (page == last_selected_page)
|
|
sel_iter = gtk_tree_iter_copy (&child_iter);
|
|
page++;
|
|
}
|
|
|
|
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
|
g_object_unref (G_OBJECT (model));
|
|
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
|
|
gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE);
|
|
gtk_tree_selection_set_select_function (sel, setup_tree_select_filter,
|
|
NULL, NULL);
|
|
g_signal_connect (G_OBJECT (tree), "cursor-changed",
|
|
G_CALLBACK (setup_tree_cb), book);
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree),
|
|
-1, _("Categories"), renderer, "text", 0, NULL);
|
|
gtk_tree_view_expand_all (GTK_TREE_VIEW (tree));
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_container_add (GTK_CONTAINER (frame), tree);
|
|
gtk_box_pack_start (GTK_BOX (box), frame, 0, 0, 0);
|
|
gtk_box_reorder_child (GTK_BOX (box), frame, 0);
|
|
|
|
if (sel_iter)
|
|
{
|
|
gtk_tree_selection_select_iter (sel, sel_iter);
|
|
gtk_tree_iter_free (sel_iter);
|
|
setup_tree_cb (GTK_TREE_VIEW (tree), book);
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_apply_to_sess (session_gui *gui)
|
|
{
|
|
mg_update_xtext (gui->xtext);
|
|
|
|
mg_apply_session_font_prefs (gui);
|
|
|
|
if (prefs.hex_gui_ulist_buttons)
|
|
gtk_widget_show (gui->button_box);
|
|
else
|
|
gtk_widget_hide (gui->button_box);
|
|
|
|
/* update active languages */
|
|
sexy_spell_entry_deactivate_language((SexySpellEntry *)gui->input_box,NULL);
|
|
sexy_spell_entry_activate_default_languages((SexySpellEntry *)gui->input_box);
|
|
|
|
sexy_spell_entry_set_checked ((SexySpellEntry *)gui->input_box, prefs.hex_gui_input_spell);
|
|
sexy_spell_entry_set_parse_attributes ((SexySpellEntry *)gui->input_box, prefs.hex_gui_input_attr);
|
|
}
|
|
|
|
static void
|
|
unslash (char *dir)
|
|
{
|
|
if (dir[0])
|
|
{
|
|
size_t len = strlen (dir) - 1;
|
|
#ifdef WIN32
|
|
if (dir[len] == '/' || dir[len] == '\\')
|
|
#else
|
|
if (dir[len] == '/')
|
|
#endif
|
|
dir[len] = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
setup_apply_real (const ThemeChangedEvent *event)
|
|
{
|
|
GSList *list;
|
|
session *sess;
|
|
int done_main = FALSE;
|
|
|
|
/* remove trailing slashes */
|
|
unslash (prefs.hex_dcc_dir);
|
|
unslash (prefs.hex_dcc_completed_dir);
|
|
|
|
g_mkdir (prefs.hex_dcc_dir, 0700);
|
|
g_mkdir (prefs.hex_dcc_completed_dir, 0700);
|
|
|
|
if (theme_changed_event_has_reason (event, THEME_CHANGED_REASON_PIXMAP))
|
|
{
|
|
if (channelwin_pix)
|
|
cairo_surface_destroy (channelwin_pix);
|
|
channelwin_pix = pixmap_load_from_file (prefs.hex_text_background);
|
|
}
|
|
|
|
theme_manager_reload_input_style ();
|
|
|
|
list = sess_list;
|
|
while (list)
|
|
{
|
|
sess = list->data;
|
|
if (sess->gui->is_tab)
|
|
{
|
|
/* only apply to main tabwindow once */
|
|
if (!done_main)
|
|
{
|
|
done_main = TRUE;
|
|
setup_apply_to_sess (sess->gui);
|
|
}
|
|
} else
|
|
{
|
|
setup_apply_to_sess (sess->gui);
|
|
}
|
|
|
|
log_open_or_close (sess);
|
|
|
|
if (theme_changed_event_has_reason (event, THEME_CHANGED_REASON_USERLIST))
|
|
userlist_rehash (sess);
|
|
|
|
list = list->next;
|
|
}
|
|
|
|
mg_apply_setup ();
|
|
menu_update_quit_accel ();
|
|
tray_apply_setup ();
|
|
zoitechat_reinit_timers ();
|
|
|
|
if (theme_changed_event_has_reason (event, THEME_CHANGED_REASON_LAYOUT))
|
|
menu_change_layout ();
|
|
|
|
if (theme_changed_event_has_reason (event, THEME_CHANGED_REASON_IDENTD))
|
|
handle_command (current_sess, "IDENTD reload", FALSE);
|
|
}
|
|
|
|
static void
|
|
setup_apply (struct zoitechatprefs *pr)
|
|
{
|
|
#ifdef WIN32
|
|
PangoFontDescription *old_desc;
|
|
PangoFontDescription *new_desc;
|
|
char buffer[4 * FONTNAMELEN + 1];
|
|
#endif
|
|
int noapply = FALSE;
|
|
ThemeChangedEvent event;
|
|
struct zoitechatprefs old_prefs = prefs;
|
|
int old_dark_mode = prefs.hex_gui_dark_mode;
|
|
mg_live_prefs live_changes;
|
|
|
|
memset (&live_changes, 0, sizeof (live_changes));
|
|
|
|
#define DIFF(a) (pr->a != prefs.a)
|
|
|
|
#ifdef WIN32
|
|
if (DIFF (hex_gui_lang))
|
|
noapply = TRUE;
|
|
#endif
|
|
/* server tabs are only created when a connection is opened, so
|
|
existing connections keep their current tabs until a restart;
|
|
the channel tree indentation is still re-applied below */
|
|
if (DIFF (hex_gui_tab_server))
|
|
{
|
|
noapply = TRUE;
|
|
live_changes.chanview = TRUE;
|
|
}
|
|
|
|
if (DIFF (hex_gui_compact))
|
|
{
|
|
live_changes.chanview = TRUE;
|
|
live_changes.ulist_columns = TRUE;
|
|
}
|
|
if (DIFF (hex_gui_input_icon) || DIFF (hex_gui_input_nick))
|
|
live_changes.input_box = TRUE;
|
|
if (DIFF (hex_gui_lagometer) || DIFF (hex_gui_throttlemeter))
|
|
live_changes.meters = TRUE;
|
|
if (DIFF (hex_gui_mode_buttons_inline) || DIFF (hex_gui_topicbar_multiline))
|
|
live_changes.topic_bar = TRUE;
|
|
if (DIFF (hex_gui_tab_icons) || DIFF (hex_gui_tab_closebuttons) ||
|
|
DIFF (hex_gui_tab_small))
|
|
live_changes.chanview = TRUE;
|
|
if (pr->hex_gui_tab_layout == 0 &&
|
|
strcmp (pr->hex_gui_tab_font, prefs.hex_gui_tab_font) != 0)
|
|
live_changes.chanview = TRUE;
|
|
if (DIFF (hex_gui_tab_sort))
|
|
live_changes.tab_resort = TRUE;
|
|
if (DIFF (hex_gui_tab_trunc))
|
|
live_changes.tab_trunc = TRUE;
|
|
if (DIFF (hex_gui_ulist_count))
|
|
live_changes.ulist_count = TRUE;
|
|
if (DIFF (hex_gui_ulist_icons))
|
|
live_changes.ulist_rows = TRUE;
|
|
if (DIFF (hex_gui_ulist_show_hosts))
|
|
{
|
|
live_changes.ulist_columns = TRUE;
|
|
live_changes.ulist_rows = TRUE; /* hostnames may be stale */
|
|
}
|
|
if (DIFF (hex_gui_ulist_sort))
|
|
live_changes.ulist_sort = TRUE;
|
|
/* compare against the pre-dialog value: the slider previews the
|
|
opacity live on the current window only, so OK still needs to
|
|
apply it to the other windows */
|
|
if (pr->hex_gui_transparency != setup_transparency_snapshot)
|
|
live_changes.transparency = TRUE;
|
|
|
|
if ((pr->hex_gui_tab_pos == 5 || pr->hex_gui_tab_pos == 6) &&
|
|
pr->hex_gui_tab_layout == 2 && pr->hex_gui_tab_pos != prefs.hex_gui_tab_pos)
|
|
fe_message (_("You cannot place the tree on the top or bottom!\n"
|
|
"Please change to the <b>Tabs</b> layout in the <b>View</b>"
|
|
" menu first."),
|
|
FE_MSG_WARN | FE_MSG_MARKUP);
|
|
|
|
/* format cannot be blank, there is already a setting for this */
|
|
if (pr->hex_stamp_text_format[0] == 0)
|
|
{
|
|
pr->hex_stamp_text = 0;
|
|
strcpy (pr->hex_stamp_text_format, prefs.hex_stamp_text_format);
|
|
}
|
|
|
|
memcpy (&prefs, pr, sizeof (prefs));
|
|
|
|
event = theme_manager_on_preferences_changed (&old_prefs, &prefs, old_dark_mode, &color_change);
|
|
|
|
#ifdef WIN32
|
|
/* merge hex_font_main and hex_font_alternative into hex_font_normal */
|
|
old_desc = pango_font_description_from_string (prefs.hex_text_font_main);
|
|
sprintf (buffer, "%s,%s", pango_font_description_get_family (old_desc), prefs.hex_text_font_alternative);
|
|
new_desc = pango_font_description_from_string (buffer);
|
|
pango_font_description_set_weight (new_desc, pango_font_description_get_weight (old_desc));
|
|
pango_font_description_set_style (new_desc, pango_font_description_get_style (old_desc));
|
|
pango_font_description_set_size (new_desc, pango_font_description_get_size (old_desc));
|
|
sprintf (prefs.hex_text_font, "%s", pango_font_description_to_string (new_desc));
|
|
|
|
/* FIXME this is not required after pango_font_description_from_string()
|
|
g_free (old_desc);
|
|
g_free (new_desc);
|
|
*/
|
|
#endif
|
|
|
|
if (prefs.hex_irc_real_name[0] == 0)
|
|
{
|
|
fe_message (_("The Real name option cannot be left blank. Falling back to \"realname\"."), FE_MSG_WARN);
|
|
strcpy (prefs.hex_irc_real_name, "realname");
|
|
}
|
|
|
|
theme_manager_dispatch_setup_apply (&event);
|
|
|
|
mg_apply_live_prefs (&live_changes);
|
|
|
|
if (noapply)
|
|
fe_message (_("Some settings were changed that require a"
|
|
" restart to take full effect."), FE_MSG_WARN);
|
|
|
|
#ifndef WIN32
|
|
if (prefs.hex_dcc_auto_recv == 2) /* Auto */
|
|
{
|
|
if (!strcmp ((char *)g_get_home_dir (), prefs.hex_dcc_dir))
|
|
{
|
|
fe_message (_("*WARNING*\n"
|
|
"Auto accepting DCC to your home directory\n"
|
|
"can be dangerous and is exploitable. Eg:\n"
|
|
"Someone could send you a .bash_profile"), FE_MSG_WARN);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
setup_ok_cb (GtkWidget *but, GtkWidget *win)
|
|
{
|
|
PreferencesPersistenceResult save_result;
|
|
struct zoitechatprefs old_prefs;
|
|
char buffer[192];
|
|
|
|
memcpy (&old_prefs, &prefs, sizeof (prefs));
|
|
setup_apply (&setup_prefs);
|
|
theme_preferences_stage_apply ();
|
|
save_result = preferences_persistence_save_all ();
|
|
if (save_result.success)
|
|
{
|
|
theme_preferences_stage_commit ();
|
|
/* the previewed values were accepted, so the close handler
|
|
must not revert them */
|
|
setup_transparency_snapshot = prefs.hex_gui_transparency;
|
|
gtk_widget_destroy (win);
|
|
return;
|
|
}
|
|
|
|
memcpy (&prefs, &old_prefs, sizeof (prefs));
|
|
theme_preferences_stage_discard ();
|
|
|
|
if (save_result.partial_failure)
|
|
{
|
|
fe_message (_("Preferences were partially saved. zoitechat.conf succeeded, colors.conf failed. Retry is possible."), FE_MSG_ERROR);
|
|
return;
|
|
}
|
|
|
|
g_snprintf (buffer, sizeof (buffer), _("Could not save preferences (%s). Retry is possible."), save_result.failed_file ? save_result.failed_file : _("unknown file"));
|
|
fe_message (buffer, FE_MSG_ERROR);
|
|
}
|
|
|
|
static GtkWidget *
|
|
setup_window_open (void)
|
|
{
|
|
GtkWidget *wid, *win, *vbox, *hbox, *hbbox;
|
|
char buf[128];
|
|
|
|
g_snprintf(buf, sizeof(buf), _("Preferences - %s"), _(DISPLAY_NAME));
|
|
win = gtkutil_window_new (buf, "prefs", 0, 600, 2);
|
|
setup_window = win;
|
|
|
|
vbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 5);
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
|
|
gtk_container_add (GTK_CONTAINER (win), vbox);
|
|
|
|
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 4);
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
|
|
|
|
setup_create_tree (hbox, setup_create_pages (hbox));
|
|
|
|
/* prepare the button box */
|
|
hbbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
|
|
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_END);
|
|
gtk_box_set_spacing (GTK_BOX (hbbox), 4);
|
|
gtk_box_pack_end (GTK_BOX (vbox), hbbox, FALSE, FALSE, 0);
|
|
|
|
cancel_button = wid = gtkutil_button_new_from_stock ("gtk-cancel", _("_Cancel"));
|
|
g_signal_connect (G_OBJECT (wid), "clicked",
|
|
G_CALLBACK (gtkutil_destroy), win);
|
|
gtk_box_pack_start (GTK_BOX (hbbox), wid, FALSE, FALSE, 0);
|
|
|
|
wid = gtkutil_button_new_from_stock ("gtk-ok", _("_OK"));
|
|
g_signal_connect (G_OBJECT (wid), "clicked",
|
|
G_CALLBACK (setup_ok_cb), win);
|
|
gtk_box_pack_start (GTK_BOX (hbbox), wid, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show_all (win);
|
|
|
|
return win;
|
|
}
|
|
|
|
static void
|
|
setup_close_cb (GtkWidget *win, GtkWidget **swin)
|
|
{
|
|
*swin = NULL;
|
|
|
|
/* drop any pending transparency preview and undo the previewed
|
|
opacity when the dialog is cancelled; after OK the snapshot
|
|
was updated so this is a no-op */
|
|
if (setup_trans_apply_tag)
|
|
{
|
|
g_source_remove (setup_trans_apply_tag);
|
|
setup_trans_apply_tag = 0;
|
|
}
|
|
if (prefs.hex_gui_transparency != setup_transparency_snapshot)
|
|
{
|
|
mg_live_prefs revert_changes;
|
|
|
|
prefs.hex_gui_transparency = setup_transparency_snapshot;
|
|
memset (&revert_changes, 0, sizeof (revert_changes));
|
|
revert_changes.transparency = TRUE;
|
|
mg_apply_live_prefs (&revert_changes);
|
|
}
|
|
|
|
theme_preferences_stage_discard ();
|
|
|
|
if (font_dialog)
|
|
{
|
|
gtk_widget_destroy (font_dialog);
|
|
font_dialog = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
setup_open (void)
|
|
{
|
|
if (setup_window)
|
|
{
|
|
gtk_window_present (GTK_WINDOW (setup_window));
|
|
return;
|
|
}
|
|
|
|
memcpy (&setup_prefs, &prefs, sizeof (prefs));
|
|
|
|
color_change = FALSE;
|
|
setup_transparency_snapshot = prefs.hex_gui_transparency;
|
|
theme_preferences_stage_begin ();
|
|
setup_window = setup_window_open ();
|
|
|
|
g_signal_connect (G_OBJECT (setup_window), "destroy",
|
|
G_CALLBACK (setup_close_cb), &setup_window);
|
|
}
|