|
| 1 | +#include <gtk/gtk.h> |
| 2 | +#include <string.h> |
| 3 | + |
| 4 | +enum { |
| 5 | + COL_NAME = 0, |
| 6 | + COL_PATH, |
| 7 | + NUM_COLS |
| 8 | +} ; |
| 9 | + |
| 10 | +GtkWidget *list = NULL; |
| 11 | +GtkListStore *store = NULL; |
| 12 | +GtkWidget *entry_search = NULL; |
| 13 | +GtkWidget *entry_replace = NULL; |
| 14 | +GtkWidget *checkbox = NULL; |
| 15 | +GRegex *rx_name = NULL; |
| 16 | +GRegex *rx_path = NULL; |
| 17 | +GRegex *rx_replace = NULL; |
| 18 | +GRegex *rx_split = NULL; |
| 19 | + |
| 20 | +int g_rename(const gchar *oldfilename, const gchar *newfilename); |
| 21 | +void destroy(void); |
| 22 | + |
| 23 | +/* ************************************************************************ * |
| 24 | + * UTILITY FUNCTIONS |
| 25 | + * ************************************************************************ */ |
| 26 | +gchar *replace_str(gchar *str, gchar *orig, gchar *rep) |
| 27 | +{ |
| 28 | + static gchar buffer[4096]; |
| 29 | + gchar *p; |
| 30 | + |
| 31 | + strncpy(buffer, str, strlen(str)); |
| 32 | + buffer[strlen(str)] = '\0'; |
| 33 | + |
| 34 | + while((p = strstr(str, orig))) // Is 'orig' even in 'str'? |
| 35 | + { |
| 36 | + strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$ |
| 37 | + buffer[p-str] = '\0'; |
| 38 | + |
| 39 | + sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); |
| 40 | + str = buffer; |
| 41 | + } |
| 42 | + return str; |
| 43 | +} |
| 44 | + |
| 45 | +/* ************************************************************************ * |
| 46 | + * POPULATING THE LIST (DRAG-N-DROP) |
| 47 | + * ************************************************************************ */ |
| 48 | +void view_onDragDataReceived(GtkWidget *wgt, GdkDragContext *context, int x, int y, |
| 49 | + GtkSelectionData *seldata, guint info, guint time) |
| 50 | +{ |
| 51 | + GtkTreeIter iter; |
| 52 | + gchar **strings = g_regex_split(rx_split, (gchar*)seldata->data, 0); |
| 53 | + gchar *input = NULL; |
| 54 | + int index = 0; |
| 55 | + |
| 56 | + while (strings[index] != NULL && strcmp(strings[index], "") != 0) |
| 57 | + { |
| 58 | + input = strings[index]; |
| 59 | + gtk_list_store_append(GTK_LIST_STORE(store), &iter); |
| 60 | + gtk_list_store_set(GTK_LIST_STORE(store), &iter, COL_NAME, |
| 61 | + g_regex_replace(rx_name, input, strlen(input), 0, "\\1", 0, NULL), -1); |
| 62 | +#ifdef WIN_32 |
| 63 | + gtk_list_store_set(GTK_LIST_STORE(store), &iter, COL_PATH, |
| 64 | + replace_str(g_regex_replace(rx_path, |
| 65 | + input, |
| 66 | + strlen(input), |
| 67 | + 0, "\\1", 0, |
| 68 | + NULL), "%20", " "), -1); |
| 69 | +#else |
| 70 | + gtk_list_store_set(GTK_LIST_STORE(store), &iter, COL_PATH, |
| 71 | + g_regex_replace(rx_path, input, strlen(input), 0, "\\1", 0, NULL), -1); |
| 72 | +#endif |
| 73 | + ++index; |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +/* ************************************************************************ * |
| 78 | + * REMOVING ITEMS FROM THE LIST |
| 79 | + * ************************************************************************ */ |
| 80 | +gboolean get_reference_foreach (GtkTreeModel *model, |
| 81 | + GtkTreePath *path, |
| 82 | + GtkTreeIter *iter, |
| 83 | + GList **rowref_list) |
| 84 | +{ |
| 85 | + *rowref_list = g_list_append(*rowref_list, gtk_tree_row_reference_new(model, path)); |
| 86 | + return TRUE; |
| 87 | +} |
| 88 | + |
| 89 | +void clear_selected() |
| 90 | +{ |
| 91 | + GList *selected = NULL; /* references of selected items */ |
| 92 | + GList *node; |
| 93 | + |
| 94 | + gtk_tree_selection_selected_foreach(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), |
| 95 | + (GtkTreeSelectionForeachFunc) get_reference_foreach, |
| 96 | + &selected); |
| 97 | + |
| 98 | + for ( node = selected; node != NULL; node = node->next ) |
| 99 | + { |
| 100 | + GtkTreePath *path = gtk_tree_row_reference_get_path((GtkTreeRowReference*)node->data); |
| 101 | + |
| 102 | + if (path) |
| 103 | + { |
| 104 | + GtkTreeIter iter; |
| 105 | + |
| 106 | + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) |
| 107 | + { gtk_list_store_remove(store, &iter); } |
| 108 | + |
| 109 | + gtk_tree_path_free(path); |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + g_list_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); |
| 114 | + g_list_free(selected); |
| 115 | + g_list_free(node); |
| 116 | + gtk_tree_view_columns_autosize(GTK_TREE_VIEW(list)); |
| 117 | +} |
| 118 | + |
| 119 | +void clear_list() |
| 120 | +{ |
| 121 | + gtk_tree_selection_select_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list))); |
| 122 | + clear_selected(); |
| 123 | +} |
| 124 | + |
| 125 | +/* ************************************************************************ * |
| 126 | + * PERFORMING THE SEARCH AND REPLACE |
| 127 | + * ************************************************************************ */ |
| 128 | +gboolean rename_foreach (GtkTreeModel *model, |
| 129 | + GtkTreePath *path, |
| 130 | + GtkTreeIter *iter) |
| 131 | +{ |
| 132 | + gchar *_name, *_path, *_name2; |
| 133 | + |
| 134 | + gtk_tree_model_get (model, iter, COL_NAME, &_name, -1); |
| 135 | + gtk_tree_model_get (model, iter, COL_PATH, &_path, -1); |
| 136 | + |
| 137 | + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox))) { |
| 138 | + _name2 = g_regex_replace(rx_replace, _name, strlen(_name), 0, |
| 139 | + gtk_entry_get_text(GTK_ENTRY(entry_replace)), 0, NULL); |
| 140 | + } else { |
| 141 | + _name2 = replace_str(_name, (gchar*) gtk_entry_get_text(GTK_ENTRY(entry_search)), |
| 142 | + (gchar*) gtk_entry_get_text(GTK_ENTRY(entry_replace))); |
| 143 | + } |
| 144 | + |
| 145 | + if (g_rename(g_strconcat(_path, _name, NULL), g_strconcat(_path, _name2, NULL)) == 0) |
| 146 | + { gtk_list_store_set (store, iter, COL_NAME, _name2, -1); } |
| 147 | + |
| 148 | + return FALSE; |
| 149 | +} |
| 150 | + |
| 151 | +void search_and_replace(void) |
| 152 | +{ |
| 153 | + rx_replace = g_regex_new(gtk_entry_get_text(GTK_ENTRY(entry_search)), G_REGEX_OPTIMIZE, 0, NULL); |
| 154 | + |
| 155 | + gtk_tree_model_foreach(GTK_TREE_MODEL(store), |
| 156 | + (GtkTreeModelForeachFunc) rename_foreach, |
| 157 | + NULL); |
| 158 | + |
| 159 | + gtk_tree_view_columns_autosize(GTK_TREE_VIEW(list)); |
| 160 | +} |
| 161 | + |
| 162 | +/* ************************************************************************ * |
| 163 | + * KEY PRESS HANDLERS |
| 164 | + * ************************************************************************ */ |
| 165 | + gboolean key_press_event (GtkWidget *widget, |
| 166 | + GdkEventKey *event, |
| 167 | + gpointer user_data) |
| 168 | +{ |
| 169 | + if(event->keyval == 65307) /* Escape Key */ |
| 170 | + { destroy(); } |
| 171 | + else if((GTK_WIDGET_HAS_FOCUS(entry_search) || GTK_WIDGET_HAS_FOCUS(entry_replace)) |
| 172 | + && (event->keyval == 65293 || event->keyval == 65421)) /* Enter Keys */ |
| 173 | + { search_and_replace(); } |
| 174 | + else if(GTK_WIDGET_HAS_FOCUS(list) && event->keyval == 65535) /* Delete Key */ |
| 175 | + { clear_selected(); } |
| 176 | + |
| 177 | + return FALSE; |
| 178 | +} |
| 179 | + |
| 180 | +/* ************************************************************************ * |
| 181 | + * DESTRUCTOR |
| 182 | + * ************************************************************************ */ |
| 183 | +void destroy(void) |
| 184 | +{ |
| 185 | + g_regex_unref(rx_name); |
| 186 | + g_regex_unref(rx_path); |
| 187 | + g_regex_unref(rx_split); |
| 188 | + if (rx_replace != NULL) |
| 189 | + g_regex_unref(rx_replace); |
| 190 | + gtk_main_quit(); |
| 191 | +} |
| 192 | + |
| 193 | +/* ************************************************************************ * |
| 194 | + * WIDGETS & BASE SETUP |
| 195 | + * ************************************************************************ */ |
| 196 | +static GtkWidget *create_view_and_model (void) |
| 197 | +{ |
| 198 | + GtkCellRenderer *renderer; |
| 199 | + GtkWidget *view; |
| 200 | + |
| 201 | + view = gtk_tree_view_new (); |
| 202 | + |
| 203 | + /* --- Column #1 --- */ |
| 204 | + renderer = gtk_cell_renderer_text_new (); |
| 205 | + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), |
| 206 | + -1, |
| 207 | + "File Name", |
| 208 | + renderer, |
| 209 | + "text", COL_NAME, |
| 210 | + NULL); |
| 211 | + |
| 212 | + /* --- Column #2 --- */ |
| 213 | + renderer = gtk_cell_renderer_text_new (); |
| 214 | + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), |
| 215 | + -1, |
| 216 | + "Path", |
| 217 | + renderer, |
| 218 | + "text", COL_PATH, |
| 219 | + NULL); |
| 220 | + |
| 221 | + store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING); |
| 222 | + gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (store)); |
| 223 | + |
| 224 | + /* Make tree view a destination for Drag'n'Drop */ |
| 225 | + if (1) |
| 226 | + { |
| 227 | + enum { |
| 228 | + TARGET_STRING, |
| 229 | + TARGET_URL |
| 230 | + }; |
| 231 | + |
| 232 | + static GtkTargetEntry targetentries[] = |
| 233 | + { |
| 234 | + { "STRING", 0, TARGET_STRING }, |
| 235 | + { "text/plain", 0, TARGET_STRING }, |
| 236 | + { "text/uri-list", 0, TARGET_URL }, |
| 237 | + }; |
| 238 | + |
| 239 | + gtk_drag_dest_set(view, GTK_DEST_DEFAULT_ALL, targetentries, 3, |
| 240 | + GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK); |
| 241 | + |
| 242 | + g_signal_connect(view, "drag_data_received", |
| 243 | + G_CALLBACK(view_onDragDataReceived), NULL); |
| 244 | + } |
| 245 | + |
| 246 | + return view; |
| 247 | +} |
| 248 | + |
| 249 | +int main (int argc, char *argv[]) |
| 250 | +{ |
| 251 | + GtkWidget *win = NULL; |
| 252 | + GtkWidget *vbox = NULL; |
| 253 | + GtkWidget *hbox = NULL; |
| 254 | + GtkWidget *table = NULL; |
| 255 | + GtkWidget *scroll = NULL; |
| 256 | + GtkWidget *align = NULL; |
| 257 | + GtkWidget *label = NULL; |
| 258 | + GtkWidget *button = NULL; |
| 259 | + |
| 260 | + /* Initialize GTK+ */ |
| 261 | + g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL); |
| 262 | + gtk_init (&argc, &argv); |
| 263 | + g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL); |
| 264 | + |
| 265 | + /* Create the main window */ |
| 266 | + win = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
| 267 | + gtk_window_set_default_size(GTK_WINDOW(win), 500, 380); |
| 268 | + gtk_container_set_border_width (GTK_CONTAINER (win), 8); |
| 269 | + gtk_window_set_title (GTK_WINDOW (win), "Multi-File Renamer - v1.1.2"); /* Jul / 20 / 2008 */ |
| 270 | + gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_NONE); |
| 271 | + gtk_widget_realize (win); |
| 272 | + g_signal_connect (win, "destroy", destroy, NULL); |
| 273 | + gtk_signal_connect (GTK_OBJECT (win), "key_press_event", |
| 274 | + GTK_SIGNAL_FUNC (key_press_event), |
| 275 | + NULL); |
| 276 | + |
| 277 | + /* Form-wide Widgets */ |
| 278 | + vbox = gtk_vbox_new (FALSE, 6); |
| 279 | + gtk_container_add (GTK_CONTAINER (win), vbox); |
| 280 | + |
| 281 | + /* First row of the Form */ |
| 282 | + scroll = gtk_scrolled_window_new(NULL, NULL); |
| 283 | + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| 284 | + gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); |
| 285 | + |
| 286 | + list = create_view_and_model(); |
| 287 | + gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), GTK_SELECTION_MULTIPLE); |
| 288 | + gtk_container_add(GTK_CONTAINER(scroll), list); |
| 289 | + |
| 290 | + /* Second / Third rows of the Form */ |
| 291 | + table = gtk_table_new(2, 2, FALSE); |
| 292 | + gtk_table_set_row_spacings(GTK_TABLE(table), 6); |
| 293 | + gtk_table_set_col_spacings(GTK_TABLE(table), 6); |
| 294 | + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); |
| 295 | + |
| 296 | + label = gtk_label_new("Search:"); |
| 297 | + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); |
| 298 | + entry_search = gtk_entry_new(); |
| 299 | + gtk_table_attach_defaults(GTK_TABLE(table), entry_search, 1, 2, 0, 1); |
| 300 | + |
| 301 | + label = gtk_label_new("Replace:"); |
| 302 | + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); |
| 303 | + entry_replace = gtk_entry_new(); |
| 304 | + gtk_table_attach_defaults(GTK_TABLE(table), entry_replace, 1, 2, 1, 2); |
| 305 | + |
| 306 | + /* Fourth row of the Form */ |
| 307 | + hbox = gtk_hbox_new(FALSE, 6); |
| 308 | + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
| 309 | + |
| 310 | + checkbox = gtk_check_button_new_with_label("Use Regex"); |
| 311 | + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), TRUE); |
| 312 | + gtk_box_pack_start(GTK_BOX(hbox), checkbox, FALSE, FALSE, 0); |
| 313 | + |
| 314 | + align = gtk_alignment_new(1, 0, 0, 0); |
| 315 | + gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 0); |
| 316 | + |
| 317 | + button = gtk_button_new_with_label ("Clear List"); |
| 318 | + g_signal_connect (button, "clicked", G_CALLBACK (clear_list), NULL); |
| 319 | + gtk_container_add(GTK_CONTAINER(align), button); |
| 320 | + |
| 321 | + button = gtk_button_new_with_label ("Search and Replace"); |
| 322 | + g_signal_connect (button, "clicked", G_CALLBACK (search_and_replace), NULL); |
| 323 | + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); |
| 324 | + |
| 325 | + /* Complie Regex Patterns */ |
| 326 | +#ifdef WIN_32 |
| 327 | + rx_name = g_regex_new(".*/([^/\r]+)\r?$", G_REGEX_OPTIMIZE, 0, NULL); |
| 328 | + rx_path = g_regex_new("file:///(.*?/)[^/]+$", G_REGEX_OPTIMIZE, 0, NULL); |
| 329 | +#else |
| 330 | + rx_name = g_regex_new(".*/([^/]+)$", G_REGEX_OPTIMIZE, 0, NULL); |
| 331 | + rx_path = g_regex_new("file://(.*?/)[^/]+$", G_REGEX_OPTIMIZE, 0, NULL); |
| 332 | +#endif |
| 333 | + rx_split = g_regex_new("\n", G_REGEX_OPTIMIZE, 0, NULL); |
| 334 | + |
| 335 | + /* Enter the main loop */ |
| 336 | + gtk_widget_show_all (win); |
| 337 | + gtk_main (); |
| 338 | + |
| 339 | + return 0; |
| 340 | +} |
0 commit comments