mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-17 03:00:19 +00:00
fix: native GTK theme import, proper file:// paths
This commit is contained in:
@@ -508,36 +508,72 @@ chanlist_match_topic_button_toggled (GtkWidget * wid, server *serv)
|
||||
serv->gui->chanlist_match_wants_topic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid));
|
||||
}
|
||||
|
||||
static GSList *
|
||||
chanlist_get_selection (server *serv, int column)
|
||||
{
|
||||
GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (serv->gui->chanlist_list));
|
||||
GtkTreeModel *model = GET_MODEL (serv);
|
||||
GList *rows;
|
||||
GList *cur;
|
||||
GSList *result = NULL;
|
||||
|
||||
rows = gtk_tree_selection_get_selected_rows (sel, &model);
|
||||
for (cur = rows; cur != NULL; cur = cur->next)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
char *value;
|
||||
|
||||
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)cur->data))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, column, &value, -1);
|
||||
result = g_slist_prepend (result, value);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
|
||||
return g_slist_reverse (result);
|
||||
}
|
||||
|
||||
static char *
|
||||
chanlist_get_selected (server *serv, gboolean get_topic)
|
||||
{
|
||||
char *chan;
|
||||
GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (serv->gui->chanlist_list));
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GSList *selection = chanlist_get_selection (serv, get_topic ? COL_TOPIC : COL_CHANNEL);
|
||||
char *value;
|
||||
|
||||
if (!gtk_tree_selection_get_selected (sel, &model, &iter))
|
||||
if (!selection)
|
||||
return NULL;
|
||||
|
||||
gtk_tree_model_get (model, &iter, get_topic ? COL_TOPIC : COL_CHANNEL, &chan, -1);
|
||||
return chan;
|
||||
value = selection->data;
|
||||
selection->data = NULL;
|
||||
g_slist_free_full (selection, g_free);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
chanlist_join (GtkWidget * wid, server *serv)
|
||||
{
|
||||
char tbuf[CHANLEN + 6];
|
||||
char *chan = chanlist_get_selected (serv, FALSE);
|
||||
if (chan)
|
||||
GSList *selection;
|
||||
GSList *item;
|
||||
gboolean joined = FALSE;
|
||||
|
||||
selection = chanlist_get_selection (serv, COL_CHANNEL);
|
||||
for (item = selection; item != NULL; item = item->next)
|
||||
{
|
||||
if (serv->connected && (strcmp (chan, "*") != 0))
|
||||
char *chan = item->data;
|
||||
|
||||
if (serv->connected && strcmp (chan, "*") != 0)
|
||||
{
|
||||
g_snprintf (tbuf, sizeof (tbuf), "join %s", chan);
|
||||
handle_command (serv->server_session, tbuf, FALSE);
|
||||
} else
|
||||
gdk_display_beep (gdk_display_get_default ());
|
||||
g_free (chan);
|
||||
joined = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!joined && selection)
|
||||
gdk_display_beep (gdk_display_get_default ());
|
||||
|
||||
g_slist_free_full (selection, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -656,23 +692,47 @@ chanlist_menu_destroy (GtkWidget *menu, gpointer userdata)
|
||||
static void
|
||||
chanlist_copychannel (GtkWidget *item, server *serv)
|
||||
{
|
||||
char *chan = chanlist_get_selected (serv, FALSE);
|
||||
if (chan)
|
||||
GSList *selection = chanlist_get_selection (serv, COL_CHANNEL);
|
||||
GSList *cur;
|
||||
GString *text;
|
||||
|
||||
if (!selection)
|
||||
return;
|
||||
|
||||
text = g_string_new ("");
|
||||
for (cur = selection; cur != NULL; cur = cur->next)
|
||||
{
|
||||
gtkutil_copy_to_clipboard (item, NULL, chan);
|
||||
g_free (chan);
|
||||
if (text->len)
|
||||
g_string_append_c (text, '\n');
|
||||
g_string_append (text, (char *)cur->data);
|
||||
}
|
||||
|
||||
gtkutil_copy_to_clipboard (item, NULL, text->str);
|
||||
g_string_free (text, TRUE);
|
||||
g_slist_free_full (selection, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
chanlist_copytopic (GtkWidget *item, server *serv)
|
||||
{
|
||||
char *topic = chanlist_get_selected (serv, TRUE);
|
||||
if (topic)
|
||||
GSList *selection = chanlist_get_selection (serv, COL_TOPIC);
|
||||
GSList *cur;
|
||||
GString *text;
|
||||
|
||||
if (!selection)
|
||||
return;
|
||||
|
||||
text = g_string_new ("");
|
||||
for (cur = selection; cur != NULL; cur = cur->next)
|
||||
{
|
||||
gtkutil_copy_to_clipboard (item, NULL, topic);
|
||||
g_free (topic);
|
||||
if (text->len)
|
||||
g_string_append_c (text, '\n');
|
||||
g_string_append (text, (char *)cur->data);
|
||||
}
|
||||
|
||||
gtkutil_copy_to_clipboard (item, NULL, text->str);
|
||||
g_string_free (text, TRUE);
|
||||
g_slist_free_full (selection, g_free);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -689,10 +749,12 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)
|
||||
if (!gtk_tree_view_get_path_at_pos (tree, event->x, event->y, &path, 0, 0, 0))
|
||||
return FALSE;
|
||||
|
||||
/* select what they right-clicked on */
|
||||
sel = gtk_tree_view_get_selection (tree);
|
||||
gtk_tree_selection_unselect_all (sel);
|
||||
gtk_tree_selection_select_path (sel, path);
|
||||
if (!gtk_tree_selection_path_is_selected (sel, path))
|
||||
{
|
||||
gtk_tree_selection_unselect_all (sel);
|
||||
gtk_tree_selection_select_path (sel, path);
|
||||
}
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
@@ -879,6 +941,7 @@ chanlist_opengui (server *serv, int do_refresh)
|
||||
chanlist_add_column (view, COL_USERS, 50, _("Users"), TRUE);
|
||||
chanlist_add_column (view, COL_TOPIC, 50, _("Topic"), FALSE);
|
||||
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
|
||||
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), GTK_SELECTION_MULTIPLE);
|
||||
/* this is a speed up, but no horizontal scrollbar :( */
|
||||
/*gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE);*/
|
||||
gtk_widget_show (view);
|
||||
|
||||
@@ -1339,22 +1339,61 @@ fe_open_url_inner (const char *url)
|
||||
g_free (escaped_url);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fe_open_url_is_local_path (const char *url)
|
||||
{
|
||||
if (g_path_is_absolute (url) || g_file_test (url, G_FILE_TEST_EXISTS))
|
||||
return TRUE;
|
||||
|
||||
#ifdef WIN32
|
||||
if (g_ascii_isalpha (url[0]) && url[1] == ':' &&
|
||||
(url[2] == '\\' || url[2] == '/'))
|
||||
return TRUE;
|
||||
|
||||
if (url[0] == '\\' && url[1] == '\\')
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
fe_open_url (const char *url)
|
||||
{
|
||||
int url_type = url_check_word (url);
|
||||
char *uri;
|
||||
char *path;
|
||||
char *path_uri;
|
||||
|
||||
if (fe_open_url_is_local_path (url))
|
||||
{
|
||||
path = g_canonicalize_filename (url, NULL);
|
||||
path_uri = g_filename_to_uri (path, NULL, NULL);
|
||||
g_free (path);
|
||||
|
||||
if (path_uri)
|
||||
{
|
||||
fe_open_url_inner (path_uri);
|
||||
g_free (path_uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* gvfs likes file:// */
|
||||
if (url_type == WORD_PATH)
|
||||
{
|
||||
#ifndef WIN32
|
||||
uri = g_strconcat ("file://", url, NULL);
|
||||
fe_open_url_inner (uri);
|
||||
g_free (uri);
|
||||
#else
|
||||
fe_open_url_inner (url);
|
||||
#endif
|
||||
path = g_canonicalize_filename (url, NULL);
|
||||
path_uri = g_filename_to_uri (path, NULL, NULL);
|
||||
g_free (path);
|
||||
if (path_uri)
|
||||
{
|
||||
fe_open_url_inner (path_uri);
|
||||
g_free (path_uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_open_url_inner (url);
|
||||
}
|
||||
}
|
||||
/* IPv6 addr. Add http:// */
|
||||
else if (url_type == WORD_HOST6)
|
||||
|
||||
@@ -670,7 +670,7 @@ mg_spellcheck_cb (SexySpellEntry *entry, gchar *word, gpointer data)
|
||||
{
|
||||
/* This can cause freezes on long words, nicks arn't very long anyway. */
|
||||
if (strlen (word) > 20)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
/* Ignore anything we think is a valid url */
|
||||
if (url_check_word (word) != 0)
|
||||
|
||||
@@ -964,6 +964,9 @@ default_word_check(SexySpellEntry *entry, const gchar *word)
|
||||
/* We only want to check words */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_utf8_strlen (word, -1) > 20)
|
||||
return FALSE;
|
||||
for (li = entry->priv->dict_list; li; li = g_slist_next (li)) {
|
||||
struct EnchantDict *dict = (struct EnchantDict *) li->data;
|
||||
if (enchant_dict_check(dict, word, strlen(word)) == 0) {
|
||||
@@ -1161,13 +1164,34 @@ check_color:
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
attr_list_has_attrs (PangoAttrList *attrs)
|
||||
{
|
||||
PangoAttrIterator *it;
|
||||
GSList *list;
|
||||
gboolean has = FALSE;
|
||||
|
||||
if (!attrs)
|
||||
return FALSE;
|
||||
|
||||
it = pango_attr_list_get_iterator (attrs);
|
||||
if (!it)
|
||||
return FALSE;
|
||||
|
||||
list = pango_attr_iterator_get_attrs (it);
|
||||
has = (list != NULL);
|
||||
g_slist_free_full (list, (GDestroyNotify) pango_attribute_destroy);
|
||||
pango_attr_iterator_destroy (it);
|
||||
|
||||
return has;
|
||||
}
|
||||
|
||||
static void
|
||||
sexy_spell_entry_recheck_all(SexySpellEntry *entry)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *widget = GTK_WIDGET(entry);
|
||||
PangoLayout *layout;
|
||||
int length, i, text_len;
|
||||
const char *text;
|
||||
|
||||
@@ -1196,8 +1220,7 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
layout = gtk_entry_get_layout(GTK_ENTRY(entry));
|
||||
pango_layout_set_attributes(layout, entry->priv->attr_list);
|
||||
gtk_entry_set_attributes (GTK_ENTRY (entry), attr_list_has_attrs (entry->priv->attr_list) ? entry->priv->attr_list : NULL);
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET(entry)))
|
||||
{
|
||||
@@ -1213,13 +1236,6 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
|
||||
static gboolean
|
||||
sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr)
|
||||
{
|
||||
SexySpellEntry *entry = SEXY_SPELL_ENTRY(widget);
|
||||
GtkEntry *gtk_entry = GTK_ENTRY(widget);
|
||||
PangoLayout *layout;
|
||||
|
||||
layout = gtk_entry_get_layout(gtk_entry);
|
||||
pango_layout_set_attributes(layout, entry->priv->attr_list);
|
||||
|
||||
return GTK_WIDGET_CLASS(parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
|
||||
@@ -1392,26 +1392,34 @@ theme_preferences_populate_gtk3 (theme_preferences_ui *ui)
|
||||
g_ptr_array_unref (themes);
|
||||
}
|
||||
|
||||
static void
|
||||
theme_preferences_gtk3_import_path (theme_preferences_ui *ui, char *path)
|
||||
{
|
||||
char *id = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!zoitechat_gtk3_theme_service_import (path, &id, &error))
|
||||
theme_preferences_show_message (ui, GTK_MESSAGE_ERROR,
|
||||
error ? error->message : _("Failed to import GTK3 theme."));
|
||||
g_clear_error (&error);
|
||||
g_free (id);
|
||||
g_free (path);
|
||||
theme_preferences_populate_gtk3 (ui);
|
||||
}
|
||||
|
||||
static void
|
||||
theme_preferences_gtk3_import_cb (GtkWidget *button, gpointer user_data)
|
||||
{
|
||||
theme_preferences_ui *ui = user_data;
|
||||
GtkWidget *dialog;
|
||||
GtkFileChooserNative *dialog;
|
||||
GtkFileFilter *filter;
|
||||
GtkWidget *folder_dialog;
|
||||
char *path;
|
||||
char *id = NULL;
|
||||
GError *error = NULL;
|
||||
gint response;
|
||||
|
||||
(void)button;
|
||||
dialog = gtk_file_chooser_dialog_new (_("Import GTK3 Theme"), ui->parent,
|
||||
dialog = gtk_file_chooser_native_new (_("Import GTK3 Theme"), ui->parent,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
_("Import _Folder"), 1,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Import"), GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
theme_manager_attach_window (dialog);
|
||||
_("_Import"),
|
||||
_("_Cancel"));
|
||||
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
|
||||
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), FALSE);
|
||||
filter = gtk_file_filter_new ();
|
||||
@@ -1426,43 +1434,15 @@ theme_preferences_gtk3_import_cb (GtkWidget *button, gpointer user_data)
|
||||
gtk_file_filter_add_pattern (filter, "*.tbz");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
if (response == 1)
|
||||
if (gtk_native_dialog_run (GTK_NATIVE_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
gtk_widget_destroy (dialog);
|
||||
folder_dialog = gtk_file_chooser_dialog_new (_("Import GTK3 Theme Folder"), ui->parent,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_Import"), GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
theme_manager_attach_window (folder_dialog);
|
||||
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (folder_dialog), TRUE);
|
||||
if (gtk_dialog_run (GTK_DIALOG (folder_dialog)) != GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
gtk_widget_destroy (folder_dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (folder_dialog));
|
||||
gtk_widget_destroy (folder_dialog);
|
||||
}
|
||||
else if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_destroy (dialog);
|
||||
g_object_unref (dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zoitechat_gtk3_theme_service_import (path, &id, &error))
|
||||
theme_preferences_show_message (ui, GTK_MESSAGE_ERROR,
|
||||
error ? error->message : _("Failed to import GTK3 theme."));
|
||||
g_clear_error (&error);
|
||||
g_free (path);
|
||||
theme_preferences_populate_gtk3 (ui);
|
||||
path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
g_object_unref (dialog);
|
||||
theme_preferences_gtk3_import_path (ui, path);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user