| 1 /* |
|
| 2 * Pidgin - Internet Messenger |
|
| 3 * Copyright (C) Pidgin Developers <devel@pidgin.im> |
|
| 4 * |
|
| 5 * Pidgin is the legal property of its developers, whose names are too numerous |
|
| 6 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 7 * source distribution. |
|
| 8 * |
|
| 9 * This program is free software; you can redistribute it and/or modify |
|
| 10 * it under the terms of the GNU General Public License as published by |
|
| 11 * the Free Software Foundation; either version 2 of the License, or |
|
| 12 * (at your option) any later version. |
|
| 13 * |
|
| 14 * This program is distributed in the hope that it will be useful, |
|
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 17 * GNU General Public License for more details. |
|
| 18 * |
|
| 19 * You should have received a copy of the GNU General Public License |
|
| 20 * along with this program; if not, see <https://www.gnu.org/licenses/>. |
|
| 21 */ |
|
| 22 |
|
| 23 #include "pidginstatuseditor.h" |
|
| 24 |
|
| 25 #include "pidginstatusprimitivechooser.h" |
|
| 26 |
|
| 27 enum { |
|
| 28 PROP_0, |
|
| 29 PROP_STATUS, |
|
| 30 N_PROPERTIES |
|
| 31 }; |
|
| 32 static GParamSpec *properties[N_PROPERTIES] = {NULL, }; |
|
| 33 |
|
| 34 enum { |
|
| 35 RESPONSE_USE, |
|
| 36 RESPONSE_SAVE |
|
| 37 }; |
|
| 38 |
|
| 39 struct _PidginStatusEditor { |
|
| 40 GtkDialog parent; |
|
| 41 |
|
| 42 PurpleSavedStatus *status; |
|
| 43 |
|
| 44 GtkTextBuffer *buffer; |
|
| 45 |
|
| 46 GtkWidget *title; |
|
| 47 GtkWidget *primitive; |
|
| 48 }; |
|
| 49 |
|
| 50 G_DEFINE_TYPE(PidginStatusEditor, pidgin_status_editor, GTK_TYPE_DIALOG) |
|
| 51 |
|
| 52 /****************************************************************************** |
|
| 53 * Helpers |
|
| 54 *****************************************************************************/ |
|
| 55 static void |
|
| 56 pidgin_status_editor_set_status(PidginStatusEditor *editor, |
|
| 57 PurpleSavedStatus *status) |
|
| 58 { |
|
| 59 PurpleStatusPrimitive primitive; |
|
| 60 PidginStatusPrimitiveChooser *chooser = NULL; |
|
| 61 const gchar *title = NULL, *message = NULL; |
|
| 62 |
|
| 63 editor->status = status; |
|
| 64 |
|
| 65 if(editor->status != NULL) { |
|
| 66 title = purple_savedstatus_get_title(editor->status); |
|
| 67 primitive = purple_savedstatus_get_primitive_type(editor->status); |
|
| 68 message = purple_savedstatus_get_message(editor->status); |
|
| 69 } else { |
|
| 70 primitive = PURPLE_STATUS_AWAY; |
|
| 71 } |
|
| 72 |
|
| 73 if(title == NULL) { |
|
| 74 title = ""; |
|
| 75 } |
|
| 76 |
|
| 77 if(message == NULL) { |
|
| 78 message = ""; |
|
| 79 } |
|
| 80 |
|
| 81 gtk_editable_set_text(GTK_EDITABLE(editor->title), title); |
|
| 82 chooser = PIDGIN_STATUS_PRIMITIVE_CHOOSER(editor->primitive); |
|
| 83 pidgin_status_primitive_chooser_set_selected(chooser, primitive); |
|
| 84 gtk_text_buffer_set_text(editor->buffer, message, -1); |
|
| 85 |
|
| 86 g_object_notify_by_pspec(G_OBJECT(editor), properties[PROP_STATUS]); |
|
| 87 } |
|
| 88 |
|
| 89 static void |
|
| 90 pidgin_status_editor_save_status(PidginStatusEditor *editor) { |
|
| 91 PidginStatusPrimitiveChooser *chooser = NULL; |
|
| 92 PurpleStatusPrimitive primitive; |
|
| 93 GtkTextIter start; |
|
| 94 GtkTextIter end; |
|
| 95 gchar *message = NULL; |
|
| 96 const gchar *title = NULL; |
|
| 97 |
|
| 98 title = gtk_editable_get_text(GTK_EDITABLE(editor->title)); |
|
| 99 |
|
| 100 chooser = PIDGIN_STATUS_PRIMITIVE_CHOOSER(editor->primitive); |
|
| 101 primitive = pidgin_status_primitive_chooser_get_selected(chooser); |
|
| 102 |
|
| 103 gtk_text_buffer_get_start_iter(editor->buffer, &start); |
|
| 104 gtk_text_buffer_get_end_iter(editor->buffer, &end); |
|
| 105 message = gtk_text_buffer_get_text(editor->buffer, &start, &end, FALSE); |
|
| 106 |
|
| 107 if(editor->status == NULL) { |
|
| 108 editor->status = purple_savedstatus_new(title, primitive); |
|
| 109 } else { |
|
| 110 const gchar *current_title = NULL; |
|
| 111 |
|
| 112 /* purple_savedstatus_set_title throws a warning if you try to save a |
|
| 113 * status with an existing title, which means we can't just save the |
|
| 114 * title if it hasn't changed. |
|
| 115 */ |
|
| 116 current_title = purple_savedstatus_get_title(editor->status); |
|
| 117 if(!purple_strequal(title, current_title)) { |
|
| 118 purple_savedstatus_set_title(editor->status, title); |
|
| 119 } |
|
| 120 |
|
| 121 purple_savedstatus_set_primitive_type(editor->status, primitive); |
|
| 122 } |
|
| 123 |
|
| 124 purple_savedstatus_set_message(editor->status, message); |
|
| 125 |
|
| 126 g_free(message); |
|
| 127 } |
|
| 128 |
|
| 129 /****************************************************************************** |
|
| 130 * Callbacks |
|
| 131 *****************************************************************************/ |
|
| 132 static void |
|
| 133 pidgin_status_editor_response_cb(GtkDialog *dialog, gint response_id, |
|
| 134 gpointer data) |
|
| 135 { |
|
| 136 PidginStatusEditor *editor = data; |
|
| 137 |
|
| 138 switch(response_id) { |
|
| 139 case RESPONSE_USE: |
|
| 140 pidgin_status_editor_save_status(editor); |
|
| 141 purple_savedstatus_activate(editor->status); |
|
| 142 break; |
|
| 143 case RESPONSE_SAVE: |
|
| 144 pidgin_status_editor_save_status(editor); |
|
| 145 break; |
|
| 146 } |
|
| 147 |
|
| 148 gtk_window_destroy(GTK_WINDOW(dialog)); |
|
| 149 } |
|
| 150 |
|
| 151 static void |
|
| 152 pidgin_status_editor_title_changed_cb(G_GNUC_UNUSED GtkEditable *editable, |
|
| 153 gpointer data) |
|
| 154 { |
|
| 155 PidginStatusEditor *editor = data; |
|
| 156 gboolean title_changed = FALSE, sensitive = FALSE; |
|
| 157 const gchar *title = NULL; |
|
| 158 |
|
| 159 title = gtk_editable_get_text(GTK_EDITABLE(editor->title)); |
|
| 160 |
|
| 161 if(editor->status != NULL) { |
|
| 162 /* If we're editing a status, check if the title is the same. */ |
|
| 163 title_changed = !purple_strequal(title, |
|
| 164 purple_savedstatus_get_title(editor->status)); |
|
| 165 } else { |
|
| 166 /* If this is a new status, check if the title is empty or not. */ |
|
| 167 title_changed = !purple_strequal(title, ""); |
|
| 168 } |
|
| 169 |
|
| 170 if(title_changed) { |
|
| 171 gboolean duplicated = purple_savedstatus_find(title) != NULL; |
|
| 172 |
|
| 173 if(duplicated) { |
|
| 174 gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), |
|
| 175 RESPONSE_USE, FALSE); |
|
| 176 gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), |
|
| 177 RESPONSE_SAVE, FALSE); |
|
| 178 |
|
| 179 return; |
|
| 180 } |
|
| 181 } |
|
| 182 |
|
| 183 sensitive = !purple_strequal(title, ""); |
|
| 184 |
|
| 185 gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), RESPONSE_USE, |
|
| 186 sensitive); |
|
| 187 gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), RESPONSE_SAVE, |
|
| 188 sensitive); |
|
| 189 } |
|
| 190 |
|
| 191 /****************************************************************************** |
|
| 192 * GObject Implementation |
|
| 193 *****************************************************************************/ |
|
| 194 static void |
|
| 195 pidgin_status_editor_get_property(GObject *obj, guint param_id, GValue *value, |
|
| 196 GParamSpec *pspec) |
|
| 197 { |
|
| 198 PidginStatusEditor *editor = PIDGIN_STATUS_EDITOR(obj); |
|
| 199 |
|
| 200 switch(param_id) { |
|
| 201 case PROP_STATUS: |
|
| 202 g_value_set_pointer(value, |
|
| 203 pidgin_status_editor_get_status(editor)); |
|
| 204 break; |
|
| 205 default: |
|
| 206 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); |
|
| 207 break; |
|
| 208 } |
|
| 209 } |
|
| 210 |
|
| 211 static void |
|
| 212 pidgin_status_editor_set_property(GObject *obj, guint param_id, |
|
| 213 const GValue *value, GParamSpec *pspec) |
|
| 214 { |
|
| 215 PidginStatusEditor *editor = PIDGIN_STATUS_EDITOR(obj); |
|
| 216 |
|
| 217 switch(param_id) { |
|
| 218 case PROP_STATUS: |
|
| 219 pidgin_status_editor_set_status(editor, |
|
| 220 g_value_get_pointer(value)); |
|
| 221 break; |
|
| 222 default: |
|
| 223 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); |
|
| 224 break; |
|
| 225 } |
|
| 226 } |
|
| 227 |
|
| 228 static void |
|
| 229 pidgin_status_editor_init(PidginStatusEditor *manager) { |
|
| 230 gtk_widget_init_template(GTK_WIDGET(manager)); |
|
| 231 } |
|
| 232 |
|
| 233 static void |
|
| 234 pidgin_status_editor_class_init(PidginStatusEditorClass *klass) { |
|
| 235 GObjectClass *obj_class = G_OBJECT_CLASS(klass); |
|
| 236 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); |
|
| 237 |
|
| 238 obj_class->get_property = pidgin_status_editor_get_property; |
|
| 239 obj_class->set_property = pidgin_status_editor_set_property; |
|
| 240 |
|
| 241 /** |
|
| 242 * PidginStatusEditor:status: |
|
| 243 * |
|
| 244 * The [type@Purple.SavedStatus] that this editor is responsible for. |
|
| 245 * This may be %NULL if it is creating a new status. |
|
| 246 * |
|
| 247 * Since: 3.0.0. |
|
| 248 */ |
|
| 249 /* we don't used boxed here because of the way status are currently |
|
| 250 * managed. |
|
| 251 */ |
|
| 252 properties[PROP_STATUS] = g_param_spec_pointer( |
|
| 253 "status", "status", |
|
| 254 "The saved status we're editing", |
|
| 255 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
|
| 256 |
|
| 257 g_object_class_install_properties(obj_class, N_PROPERTIES, properties); |
|
| 258 |
|
| 259 gtk_widget_class_set_template_from_resource( |
|
| 260 widget_class, |
|
| 261 "/im/pidgin/Pidgin3/Status/editor.ui" |
|
| 262 ); |
|
| 263 |
|
| 264 gtk_widget_class_bind_template_child(widget_class, PidginStatusEditor, |
|
| 265 buffer); |
|
| 266 |
|
| 267 gtk_widget_class_bind_template_child(widget_class, PidginStatusEditor, |
|
| 268 title); |
|
| 269 gtk_widget_class_bind_template_child(widget_class, PidginStatusEditor, |
|
| 270 primitive); |
|
| 271 |
|
| 272 gtk_widget_class_bind_template_callback(widget_class, |
|
| 273 pidgin_status_editor_response_cb); |
|
| 274 gtk_widget_class_bind_template_callback(widget_class, |
|
| 275 pidgin_status_editor_title_changed_cb); |
|
| 276 } |
|
| 277 |
|
| 278 /****************************************************************************** |
|
| 279 * Public API |
|
| 280 *****************************************************************************/ |
|
| 281 GtkWidget * |
|
| 282 pidgin_status_editor_new(PurpleSavedStatus *status) { |
|
| 283 return g_object_new( |
|
| 284 PIDGIN_TYPE_STATUS_EDITOR, |
|
| 285 "status", status, |
|
| 286 NULL); |
|
| 287 } |
|
| 288 |
|
| 289 PurpleSavedStatus * |
|
| 290 pidgin_status_editor_get_status(PidginStatusEditor *editor) { |
|
| 291 g_return_val_if_fail(PIDGIN_IS_STATUS_EDITOR(editor), NULL); |
|
| 292 |
|
| 293 return editor->status; |
|
| 294 } |
|