sourceview: Fix a crash with Scintilla
[anjuta.git] / plugins / document-manager / anjuta-docman.c
blob0f3bbba0ebd567b3faeb3ca21427789e6c5ac653
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 anjuta-docman.c
4 Copyright (C) 2003-2007 Naba Kumar <naba@gnome.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <libanjuta/resources.h>
22 #include <libanjuta/anjuta-utils.h>
23 #include <libanjuta/anjuta-preferences.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/interfaces/ianjuta-file.h>
26 #include <libanjuta/interfaces/ianjuta-markable.h>
27 #include <libanjuta/interfaces/ianjuta-file-savable.h>
28 #include <libanjuta/interfaces/ianjuta-editor.h>
29 #include <libanjuta/interfaces/ianjuta-editor-factory.h>
31 #include <stdlib.h>
32 #include <gtk/gtk.h>
34 #include "anjuta-docman.h"
35 #include "file_history.h"
36 #include "plugin.h"
37 #include "action-callbacks.h"
39 #define MENU_PLACEHOLDER "/MenuMain/PlaceHolderDocumentsMenus/Documents/PlaceholderDocuments"
41 static gpointer parent_class;
43 enum
45 DOC_ADDED,
46 DOC_CHANGED,
47 LAST_SIGNAL
50 /* Preference keys */
51 #define EDITOR_TABS_POS "docman-tabs-pos"
52 #define EDITOR_TABS_HIDE "docman-tabs-hide"
53 #define EDITOR_TABS_ORDERING "docman-tabs-ordering"
54 #define EDITOR_TABS_RECENT_FIRST "docman-tabs-recent-first"
56 typedef struct _AnjutaDocmanPage AnjutaDocmanPage;
58 struct _AnjutaDocmanPriv {
59 DocmanPlugin *plugin;
60 GSettings* settings;
61 GList *pages; /* list of AnjutaDocmanPage's */
63 GtkWidget *fileselection;
65 GtkWidget *popup_menu; /* shared context-menu for main-notebook pages */
66 gboolean tab_pressed; /* flag for deferred notebook page re-arrangement */
67 gboolean shutingdown;
69 GSList* radio_group;
70 GtkActionGroup *documents_action_group;
71 gint documents_merge_id;
74 struct _AnjutaDocmanPage {
75 IAnjutaDocument *doc; /* a IAnjutaDocument */
76 GtkWidget *widget; /* notebook-page widget */
77 GtkWidget *box; /* notebook-tab-label parent widget */
78 GtkWidget *menu_box; /* notebook-tab-menu parent widget */
79 GtkWidget *close_image;
80 GtkWidget *close_button;
81 GtkWidget *mime_icon;
82 GtkWidget *menu_icon;
83 GtkWidget *label;
84 GtkWidget *menu_label; /* notebook page-switch menu-label */
85 gboolean is_current;
88 static guint docman_signals[LAST_SIGNAL] = { 0 };
90 static void anjuta_docman_order_tabs (AnjutaDocman *docman);
91 static void anjuta_docman_update_page_label (AnjutaDocman *docman,
92 IAnjutaDocument *doc);
93 static void anjuta_docman_grab_text_focus (AnjutaDocman *docman);
94 static void on_notebook_switch_page (GtkNotebook *notebook,
95 GtkWidget *page,
96 gint page_num, AnjutaDocman *docman);
97 static AnjutaDocmanPage *
98 anjuta_docman_get_page_for_document (AnjutaDocman *docman,
99 IAnjutaDocument *doc);
100 static AnjutaDocmanPage *
101 anjuta_docman_get_nth_page (AnjutaDocman *docman, gint page_num);
103 static AnjutaDocmanPage *
104 anjuta_docman_get_current_page (AnjutaDocman *docman);
106 static void
107 on_document_toggled (GtkAction* action,
108 AnjutaDocman* docman)
110 gint n;
112 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) == FALSE)
113 return;
115 n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
116 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), n);
119 static void
120 anjuta_docman_update_documents_menu_status (AnjutaDocman* docman)
122 AnjutaDocmanPriv *priv = docman->priv;
123 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
124 NULL));
125 GtkAction* action;
126 gint n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (docman));
127 gint current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (docman));
128 gchar *action_name;
130 action = gtk_ui_manager_get_action (ui,
131 "/MenuMain/PlaceHolderDocumentsMenus/Documents/PreviousDocument");
132 g_object_set (action, "sensitive", current_page > 0, NULL);
133 action = gtk_ui_manager_get_action (ui,
134 "/MenuMain/PlaceHolderDocumentsMenus/Documents/NextDocument");
135 g_object_set (action, "sensitive", (current_page + 1) < n_pages, NULL);
136 action_name = g_strdup_printf ("Tab_%d", current_page);
137 action = gtk_action_group_get_action (docman->priv->documents_action_group, action_name);
138 g_free (action_name);
139 if (action)
140 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
143 static void
144 anjuta_docman_update_documents_menu (AnjutaDocman* docman)
146 AnjutaDocmanPriv *priv = docman->priv;
147 GtkUIManager* ui = GTK_UI_MANAGER (anjuta_shell_get_ui (ANJUTA_PLUGIN (priv->plugin)->shell,
148 NULL));
149 GList *actions, *l;
150 gint n, i;
151 guint id;
152 GSList *group = NULL;
154 g_return_if_fail (priv->documents_action_group != NULL);
156 if (priv->documents_merge_id != 0)
157 gtk_ui_manager_remove_ui (ui,
158 priv->documents_merge_id);
160 actions = gtk_action_group_list_actions (priv->documents_action_group);
161 for (l = actions; l != NULL; l = l->next)
163 g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),
164 G_CALLBACK (on_document_toggled),
165 docman);
166 gtk_action_group_remove_action (priv->documents_action_group,
167 GTK_ACTION (l->data));
169 g_list_free (actions);
171 n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (docman));
173 id = (n > 0) ? gtk_ui_manager_new_merge_id (ui) : 0;
175 for (i = 0; i < n; i++)
177 AnjutaDocmanPage* page;
178 GtkRadioAction *action;
179 gchar *action_name;
180 const gchar *tab_name;
181 gchar *accel;
183 page = anjuta_docman_get_nth_page (docman, i);
185 /* NOTE: the action is associated to the position of the tab in
186 * the notebook not to the tab itself! This is needed to work
187 * around the gtk+ bug #170727: gtk leaves around the accels
188 * of the action. Since the accel depends on the tab position
189 * the problem is worked around, action with the same name always
190 * get the same accel.
192 action_name = g_strdup_printf ("Tab_%d", i);
193 tab_name = gtk_label_get_label (GTK_LABEL (page->label));
195 /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
196 accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
198 action = gtk_radio_action_new (action_name,
199 tab_name,
200 NULL,
201 NULL,
204 if (group != NULL)
205 gtk_radio_action_set_group (action, group);
207 /* note that group changes each time we add an action, so it must be updated */
208 group = gtk_radio_action_get_group (action);
210 gtk_action_group_add_action_with_accel (priv->documents_action_group,
211 GTK_ACTION (action),
212 accel);
214 g_signal_connect (action,
215 "toggled",
216 G_CALLBACK (on_document_toggled),
217 docman);
219 gtk_ui_manager_add_ui (ui,
221 MENU_PLACEHOLDER,
222 action_name, action_name,
223 GTK_UI_MANAGER_MENUITEM,
224 FALSE);
226 if (i == gtk_notebook_get_current_page (GTK_NOTEBOOK (docman)))
227 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
229 g_object_unref (action);
231 g_free (action_name);
232 g_free (accel);
234 anjuta_docman_update_documents_menu_status (docman);
235 priv->documents_merge_id = id;
238 static void
239 on_notebook_page_close_button_click (GtkButton* button,
240 AnjutaDocman* docman)
242 AnjutaDocmanPage *page;
244 page = anjuta_docman_get_current_page (docman);
245 if (page == NULL || page->close_button != GTK_WIDGET (button))
247 /* the close function works only on the current document */
248 GList* node;
249 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
251 page = (AnjutaDocmanPage *) node->data;
252 if (page->close_button == GTK_WIDGET (button))
254 anjuta_docman_set_current_document (docman, page->doc);
255 break;
258 if (node == NULL)
259 return;
262 if (page != NULL)
263 on_close_file_activate (NULL, docman->priv->plugin);
266 static void
267 on_notebook_page_close_button_enter (GtkButton *button,
268 AnjutaDocmanPage *page)
270 g_return_if_fail (page != NULL);
272 gtk_widget_set_sensitive (page->close_image, TRUE);
275 static void
276 on_notebook_page_close_button_leave (GtkButton* button,
277 AnjutaDocmanPage *page)
279 g_return_if_fail (page != NULL);
281 if (! page->is_current)
282 gtk_widget_set_sensitive (page->close_image,FALSE);
285 /* for managing deferred tab re-arrangement */
286 static gboolean
287 on_notebook_tab_btnpress (GtkWidget *wid, GdkEventButton *event, AnjutaDocman* docman)
289 if (event->type == GDK_BUTTON_PRESS && event->button != 3) /* right-click is for menu */
290 docman->priv->tab_pressed = TRUE;
292 return FALSE;
295 static gboolean
296 on_notebook_tab_btnrelease (GtkWidget *widget, GdkEventButton *event, AnjutaDocman* docman)
298 AnjutaDocmanPage *page;
299 AnjutaDocmanPage *curr_page = NULL;
301 docman->priv->tab_pressed = FALSE;
303 /* close on middle click */
304 if (event->button == 2)
306 /* the close function works only on the current document */
307 GList* node;
308 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
310 page = (AnjutaDocmanPage *) node->data;
311 if (page->box == widget)
313 /* we've found the page that user wants to close. Save the current
314 * page for a later setup
316 curr_page = anjuta_docman_get_current_page (docman);
317 anjuta_docman_set_current_document (docman, page->doc);
318 break;
321 if (node == NULL)
322 return FALSE;
324 if (page != NULL)
326 on_close_file_activate (NULL, docman->priv->plugin);
328 if (curr_page != NULL)
330 /* set the old current page */
331 anjuta_docman_set_current_document (docman, curr_page->doc);
335 return FALSE;
338 /* normal button click close */
339 if (g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_RECENT_FIRST))
341 GList *node;
343 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
345 AnjutaDocmanPage *page;
347 page = (AnjutaDocmanPage *)node->data;
348 if (page->box == widget)
350 gtk_notebook_reorder_child (GTK_NOTEBOOK (docman), page->widget, 0);
351 break;
356 return FALSE;
359 static gboolean
360 on_notebook_tab_double_click(GtkWidget *widget, GdkEventButton *event,
361 AnjutaDocman* docman)
363 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
365 if(!docman->maximized)
366 anjuta_shell_maximize_widget(docman->shell, "AnjutaDocumentManager", NULL);
367 else
368 anjuta_shell_unmaximize(docman->shell, NULL);
369 docman->maximized = docman->maximized ? FALSE:TRUE;
372 return FALSE;
375 static void
376 on_notebook_page_reordered (GtkNotebook *notebook, GtkWidget *child,
377 guint page_num, AnjutaDocman *docman)
379 anjuta_docman_update_documents_menu(docman);
382 static GdkPixbuf*
383 anjuta_docman_get_pixbuf_for_file (GFile* file)
385 /* add a nice mime-type icon if we can */
386 const gchar** icon_names;
387 GtkIconInfo* icon_info;
388 GIcon* icon;
389 GdkPixbuf* pixbuf;
390 GFileInfo* file_info;
391 GError* err = NULL;
393 g_return_val_if_fail (file != NULL, NULL);
395 file_info = g_file_query_info (file,
396 "standard::*",
397 G_FILE_QUERY_INFO_NONE,
398 NULL,
399 &err);
400 if (err)
401 DEBUG_PRINT ("GFile-Error %s", err->message);
403 if (file_info != NULL)
405 icon = g_file_info_get_icon (file_info);
406 g_object_get (icon, "names", &icon_names, NULL);
407 icon_info = gtk_icon_theme_choose_icon (gtk_icon_theme_get_default(),
408 icon_names,
409 GTK_ICON_SIZE_MENU,
410 GTK_ICON_LOOKUP_GENERIC_FALLBACK);
411 pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
412 gtk_icon_info_free(icon_info);
413 g_object_unref (icon);
415 if (pixbuf != NULL)
417 return pixbuf;
420 return NULL;
423 static void
424 anjuta_docman_page_init (AnjutaDocman *docman, IAnjutaDocument *doc,
425 GFile* file, AnjutaDocmanPage *page)
427 GtkWidget *close_button;
428 GtkWidget *close_pixmap;
429 GtkWidget *label, *menu_label;
430 GtkWidget *box, *menu_box;
431 GtkWidget *event_hbox;
432 GtkWidget *event_box;
433 gint h, w;
434 GdkColor color;
435 const gchar *filename;
436 gchar *ruri;
438 g_return_if_fail (IANJUTA_IS_DOCUMENT (doc));
440 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
442 close_pixmap = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
443 gtk_widget_show (close_pixmap);
445 /* setup close button, zero out {x,y} thickness to get smallest possible size */
446 close_button = gtk_button_new();
447 gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE);
448 gtk_container_add(GTK_CONTAINER(close_button), close_pixmap);
449 gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE);
451 gtk_widget_set_name (close_button, "anjuta-tab-close-button");
453 gtk_widget_set_size_request (close_button, w, h);
454 gtk_widget_set_tooltip_text (close_button, _("Close file"));
456 filename = ianjuta_document_get_filename (doc, NULL);
457 label = gtk_label_new (filename);
458 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
459 gtk_widget_show (label);
461 menu_label = gtk_label_new (filename);
462 gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
463 gtk_widget_show (menu_label);
464 menu_box = gtk_hbox_new(FALSE, 2);
466 color.red = 0;
467 color.green = 0;
468 color.blue = 0;
470 gtk_widget_modify_fg (close_button, GTK_STATE_NORMAL, &color);
471 gtk_widget_modify_fg (close_button, GTK_STATE_INSENSITIVE, &color);
472 gtk_widget_modify_fg (close_button, GTK_STATE_ACTIVE, &color);
473 gtk_widget_modify_fg (close_button, GTK_STATE_PRELIGHT, &color);
474 gtk_widget_modify_fg (close_button, GTK_STATE_SELECTED, &color);
475 gtk_widget_show(close_button);
477 box = gtk_hbox_new (FALSE, 2);
478 /* create our layout/event boxes */
479 event_box = gtk_event_box_new();
480 gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
482 event_hbox = gtk_hbox_new (FALSE, 2);
484 page->menu_icon = gtk_image_new();
485 page->mime_icon = gtk_image_new();
486 gtk_box_pack_start (GTK_BOX (event_hbox), page->mime_icon, FALSE, FALSE, 0);
487 gtk_box_pack_start (GTK_BOX (menu_box), page->menu_icon, FALSE, FALSE, 0);
488 if (file != NULL)
490 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
491 if (pixbuf != NULL)
493 gtk_image_set_from_pixbuf (GTK_IMAGE (page->menu_icon), pixbuf);
494 gtk_image_set_from_pixbuf (GTK_IMAGE (page->mime_icon), pixbuf);
495 g_object_unref (pixbuf);
497 ruri = g_file_get_parse_name (file);
498 if (ruri != NULL)
500 /* set the tab-tooltip */
501 gchar *tip;
502 tip = g_markup_printf_escaped ("<b>%s</b> %s", _("Path:"), ruri);
503 gtk_widget_set_tooltip_markup (event_box, tip);
505 g_free (ruri);
506 g_free (tip);
510 gtk_box_pack_start (GTK_BOX (event_hbox), label, TRUE, TRUE, 0);
511 gtk_box_pack_start (GTK_BOX (event_hbox), close_button, FALSE, FALSE, 0);
512 gtk_container_add (GTK_CONTAINER (event_box), event_hbox);
514 /* setup the data hierarchy */
515 g_object_set_data (G_OBJECT (box), "event_box", event_box);
517 /* pack our top-level layout box */
518 gtk_box_pack_start (GTK_BOX (box), event_box, TRUE, TRUE, 0);
520 /* show the widgets of the tab */
521 gtk_widget_show_all(box);
523 /* menu box */
524 gtk_box_pack_start (GTK_BOX (menu_box), menu_label, TRUE, TRUE, 0);
525 gtk_widget_show_all (menu_box);
527 /* main box */
528 g_signal_connect (G_OBJECT (close_button), "clicked",
529 G_CALLBACK (on_notebook_page_close_button_click),
530 docman);
531 g_signal_connect (G_OBJECT (close_button), "enter",
532 G_CALLBACK (on_notebook_page_close_button_enter),
533 page);
534 g_signal_connect (G_OBJECT (close_button), "leave",
535 G_CALLBACK (on_notebook_page_close_button_leave),
536 page);
537 g_signal_connect (G_OBJECT (box), "button-press-event",
538 G_CALLBACK (on_notebook_tab_btnpress),
539 docman);
540 g_signal_connect (G_OBJECT (box), "button-release-event",
541 G_CALLBACK (on_notebook_tab_btnrelease),
542 docman);
543 g_signal_connect (G_OBJECT (box), "event",
544 G_CALLBACK (on_notebook_tab_double_click),
545 docman);
547 page->widget = GTK_WIDGET (doc); /* this is the notebook-page child widget */
548 page->doc = doc;
549 page->box = box;
550 page->close_image = close_pixmap;
551 page->close_button = close_button;
552 page->label = label;
553 page->menu_box = menu_box;
554 page->menu_label = menu_label;
556 gtk_widget_show_all (page->widget);
559 static AnjutaDocmanPage *
560 anjuta_docman_page_new (void)
562 AnjutaDocmanPage *page;
564 page = g_new0 (AnjutaDocmanPage, 1); /* don't try to survive a memory-crunch */
565 return page;
568 static void
569 anjuta_docman_page_destroy (AnjutaDocmanPage *page)
571 /* Notebook holds a reference on the widget of page and destroys
572 * them properly
574 g_free (page);
577 static void
578 on_open_filesel_response (GtkDialog* dialog, gint id, AnjutaDocman *docman)
580 gchar *uri;
581 // unused gchar *entry_filename = NULL;
582 int i;
583 GSList * list;
584 int elements;
586 if (id != GTK_RESPONSE_ACCEPT)
588 gtk_widget_hide (docman->priv->fileselection);
589 return;
592 list = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(dialog));
593 if (list != NULL)
595 elements = g_slist_length(list);
596 for (i = 0; i < elements; i++)
598 uri = g_slist_nth_data (list, i);
599 if (uri)
601 GFile* file = g_file_new_for_uri (uri);
602 anjuta_docman_goto_file_line (docman, file, -1);
603 g_object_unref (file);
604 g_free (uri);
607 g_slist_free (list);
609 /* if (entry_filename)
611 list = g_slist_remove(list, entry_filename);
612 g_free(entry_filename);
618 static GtkWidget*
619 create_file_open_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
621 GtkWidget* dialog =
622 gtk_file_chooser_dialog_new (_("Open file"),
623 parent,
624 GTK_FILE_CHOOSER_ACTION_OPEN,
625 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
626 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
627 NULL);
628 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
629 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog), TRUE);
630 g_signal_connect (G_OBJECT (dialog), "response",
631 G_CALLBACK (on_open_filesel_response), docman);
632 g_signal_connect_swapped (G_OBJECT (dialog), "delete-event",
633 G_CALLBACK (gtk_widget_hide), dialog);
634 return dialog;
637 static GtkWidget*
638 create_file_save_dialog_gui (GtkWindow* parent, AnjutaDocman* docman)
640 GtkWidget* dialog =
641 gtk_file_chooser_dialog_new (_("Save file as"),
642 parent,
643 GTK_FILE_CHOOSER_ACTION_SAVE,
644 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
645 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
646 NULL);
647 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
648 return dialog;
651 void
652 anjuta_docman_open_file (AnjutaDocman *docman)
654 if (!docman->priv->fileselection)
656 GtkWidget *parent;
657 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
658 docman->priv->fileselection =
659 create_file_open_dialog_gui(GTK_WINDOW (parent), docman);
661 if (gtk_widget_get_visible (docman->priv->fileselection))
662 gtk_window_present (GTK_WINDOW (docman->priv->fileselection));
663 else
664 gtk_widget_show (docman->priv->fileselection);
667 gboolean
668 anjuta_docman_save_document_as (AnjutaDocman *docman, IAnjutaDocument *doc,
669 GtkWidget *parent_window)
671 gchar* uri;
672 GFile* file;
673 const gchar* filename;
674 GtkWidget *parent;
675 GtkWidget *dialog;
676 gint response;
677 gboolean file_saved = TRUE;
679 g_return_val_if_fail (ANJUTA_IS_DOCMAN (docman), FALSE);
680 g_return_val_if_fail (IANJUTA_IS_DOCUMENT (doc), FALSE);
682 if (parent_window)
684 parent = parent_window;
686 else
688 parent = gtk_widget_get_toplevel (GTK_WIDGET (docman));
691 dialog = create_file_save_dialog_gui (GTK_WINDOW (parent), docman);
693 if ((file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL)) != NULL)
695 gchar* file_uri = g_file_get_uri (file);
696 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (dialog), file_uri);
697 g_free (file_uri);
698 g_object_unref (file);
700 else if ((filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
701 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
702 else
703 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "");
705 response = gtk_dialog_run (GTK_DIALOG (dialog));
706 if (response != GTK_RESPONSE_ACCEPT)
708 gtk_widget_destroy (dialog);
709 return FALSE;
712 uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
713 file = g_file_new_for_uri (uri);
714 if (g_file_query_exists (file, NULL))
716 GtkWidget *msg_dialog;
717 gchar* parse_uri = g_file_get_parse_name (file);
718 msg_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
719 GTK_DIALOG_DESTROY_WITH_PARENT,
720 GTK_MESSAGE_QUESTION,
721 GTK_BUTTONS_NONE,
722 _("The file '%s' already exists.\n"
723 "Do you want to replace it with the"
724 " one you are saving?"),
725 parse_uri);
726 g_free (parse_uri);
727 gtk_dialog_add_button (GTK_DIALOG (msg_dialog),
728 GTK_STOCK_CANCEL,
729 GTK_RESPONSE_CANCEL);
730 anjuta_util_dialog_add_button (GTK_DIALOG (msg_dialog),
731 _("_Replace"),
732 GTK_STOCK_REFRESH,
733 GTK_RESPONSE_YES);
734 if (gtk_dialog_run (GTK_DIALOG (msg_dialog)) == GTK_RESPONSE_YES)
735 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), file,
736 NULL);
737 else
738 file_saved = FALSE;
739 gtk_widget_destroy (msg_dialog);
741 else
743 ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (doc), file, NULL);
746 if (g_settings_get_boolean (docman->priv->settings,
747 EDITOR_TABS_ORDERING))
748 anjuta_docman_order_tabs (docman);
750 gtk_widget_destroy (dialog);
751 g_free (uri);
753 if (file_saved)
755 /* Update mime icons */
756 AnjutaDocmanPage* page = anjuta_docman_get_page_for_document (docman, doc);
757 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
758 if (pixbuf)
760 gtk_image_set_from_pixbuf (GTK_IMAGE(page->menu_icon), pixbuf);
761 gtk_image_set_from_pixbuf (GTK_IMAGE(page->mime_icon), pixbuf);
762 g_object_unref (pixbuf);
765 g_object_unref (file);
767 return file_saved;
770 gboolean
771 anjuta_docman_save_document (AnjutaDocman *docman, IAnjutaDocument *doc,
772 GtkWidget *parent_window)
774 GFile* file;
775 gboolean ret;
777 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
779 if (file == NULL)
781 anjuta_docman_set_current_document (docman, doc);
782 ret = anjuta_docman_save_document_as (docman, doc, parent_window);
784 else
786 /* Error checking must be done by the IAnjutaFile */
787 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
788 g_object_unref (file);
789 ret = TRUE;
791 return ret;
794 static void
795 anjuta_docman_dispose (GObject *obj)
797 AnjutaDocman *docman;
798 GList *node;
800 docman = ANJUTA_DOCMAN (obj);
801 docman->priv->shutingdown = TRUE;
803 DEBUG_PRINT ("%s", "Disposing AnjutaDocman object");
804 if (docman->priv->popup_menu)
806 gtk_widget_destroy (docman->priv->popup_menu);
807 docman->priv->popup_menu = NULL;
809 if (docman->priv->pages)
811 /* Destroy all page data (more than just the notebook-page-widgets) */
812 GList *pages;
814 g_signal_handlers_disconnect_by_func (G_OBJECT (docman),
815 (gpointer) on_notebook_switch_page,
816 (gpointer) docman);
817 pages = docman->priv->pages; /*work with copy so var can be NULL'ed ASAP*/
818 docman->priv->pages = NULL;
819 for (node = pages; node != NULL; node = g_list_next (node))
821 /* this also tries to destroy any notebook-page-widgets, in case
822 they're not gone already
823 CHECKME at shutdown do we need "destroy" signals in case other plugins
824 hold refs on any page(s) or their contents ?
826 anjuta_docman_page_destroy ((AnjutaDocmanPage *)node->data);
828 g_list_free (pages);
830 G_OBJECT_CLASS (parent_class)->dispose (obj);
833 static void
834 anjuta_docman_finalize (GObject *obj)
836 AnjutaDocman *docman;
838 DEBUG_PRINT ("%s", "Finalising AnjutaDocman object");
839 docman = ANJUTA_DOCMAN (obj);
840 if (docman->priv)
842 if (docman->priv->fileselection)
843 gtk_widget_destroy (docman->priv->fileselection);
844 g_free (docman->priv);
845 docman->priv = NULL;
847 G_OBJECT_CLASS (parent_class)->finalize (obj);
850 static void
851 anjuta_docman_instance_init (AnjutaDocman *docman)
853 docman->priv = g_new0 (AnjutaDocmanPriv, 1);
854 /*g_new0 NULL's all content
855 docman->priv->popup_menu = NULL;
856 docman->priv->popup_menu_det = NULL;
857 docman->priv->fileselection = NULL;
859 gtk_notebook_popup_enable (GTK_NOTEBOOK (docman));
860 gtk_notebook_set_scrollable (GTK_NOTEBOOK (docman), TRUE);
861 g_signal_connect (G_OBJECT (docman), "switch-page",
862 G_CALLBACK (on_notebook_switch_page), docman);
863 /* update pages-list after re-ordering (or deleting) */
864 g_signal_connect (G_OBJECT (docman), "page-reordered",
865 G_CALLBACK (on_notebook_page_reordered), docman);
868 static void
869 anjuta_docman_class_init (AnjutaDocmanClass *klass)
871 static gboolean initialized;
872 GObjectClass *object_class = G_OBJECT_CLASS (klass);
874 parent_class = g_type_class_peek_parent (klass);
875 object_class->finalize = anjuta_docman_finalize;
876 object_class->dispose = anjuta_docman_dispose;
878 if (!initialized)
880 initialized = TRUE;
882 /* Signals */
883 docman_signals [DOC_ADDED] =
884 g_signal_new ("document-added",
885 ANJUTA_TYPE_DOCMAN,
886 G_SIGNAL_RUN_LAST,
887 G_STRUCT_OFFSET (AnjutaDocmanClass, document_added),
888 NULL, NULL,
889 g_cclosure_marshal_VOID__OBJECT,
890 G_TYPE_NONE,
892 G_TYPE_OBJECT);
893 docman_signals [DOC_CHANGED] =
894 g_signal_new ("document-changed",
895 ANJUTA_TYPE_DOCMAN,
896 G_SIGNAL_RUN_LAST,
897 G_STRUCT_OFFSET (AnjutaDocmanClass, document_changed),
898 NULL, NULL,
899 g_cclosure_marshal_VOID__OBJECT,
900 G_TYPE_NONE,
902 G_TYPE_OBJECT);
906 gtk_rc_parse_string ("style \"anjuta-tab-close-button-style\"\n"
907 "{\n"
908 "GtkWidget::focus-padding = 0\n"
909 "GtkWidget::focus-line-width = 0\n"
910 "xthickness = 0\n"
911 "ythickness = 0\n"
912 "}\n"
913 "widget \"*.anjuta-tab-close-button\" style \"anjuta-tab-close-button-style\"");
916 GtkWidget*
917 anjuta_docman_new (DocmanPlugin* plugin)
920 GtkWidget *docman;
921 docman = gtk_widget_new (ANJUTA_TYPE_DOCMAN, NULL);
922 if (docman)
924 AnjutaUI* ui;
925 AnjutaDocman* real_docman = ANJUTA_DOCMAN (docman);
926 real_docman->priv->plugin = plugin;
927 real_docman->priv->settings = plugin->settings;
928 real_docman->priv->documents_action_group = gtk_action_group_new ("ActionGroupDocument");
929 real_docman->maximized = FALSE;
930 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
931 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), real_docman->priv->documents_action_group, 0);
932 g_object_unref (real_docman->priv->documents_action_group);
935 return docman;
938 /*! state flag for Ctrl-TAB */
939 static gboolean g_tabbing = FALSE;
941 static void
942 on_notebook_switch_page (GtkNotebook *notebook,
943 GtkWidget *notebook_page,
944 gint page_num, AnjutaDocman *docman)
946 if (!docman->priv->shutingdown)
948 AnjutaDocmanPage *page;
950 page = anjuta_docman_get_nth_page (docman, page_num);
951 g_signal_handlers_block_by_func (G_OBJECT (docman),
952 (gpointer) on_notebook_switch_page,
953 (gpointer) docman);
954 anjuta_docman_set_current_document (docman, page->doc);
955 g_signal_handlers_unblock_by_func (G_OBJECT (docman),
956 (gpointer) on_notebook_switch_page,
957 (gpointer) docman);
958 /* TTimo: reorder so that the most recently used files are
959 * at the beginning of the tab list
961 if (!docman->priv->tab_pressed /* after a tab-click, sorting is done upon release */
962 && !g_tabbing
963 && !g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_ORDERING)
964 && g_settings_get_boolean (docman->priv->settings, EDITOR_TABS_RECENT_FIRST))
966 gtk_notebook_reorder_child (notebook, page->widget, 0);
968 /* activate the right item in the documents menu */
969 anjuta_docman_update_documents_menu_status (docman);
970 g_signal_emit_by_name (G_OBJECT (docman), "document-changed", page->doc);
974 static void
975 on_document_update_save_ui (IAnjutaDocument *doc,
976 AnjutaDocman *docman)
978 anjuta_docman_update_page_label (docman, doc);
981 static void
982 on_document_destroy (IAnjutaDocument *doc, AnjutaDocman *docman)
984 AnjutaDocmanPage *page;
985 gint page_num;
987 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
988 G_CALLBACK (on_document_update_save_ui),
989 docman);
990 g_signal_handlers_disconnect_by_func (G_OBJECT (doc),
991 G_CALLBACK (on_document_destroy),
992 docman);
994 page = anjuta_docman_get_page_for_document (docman, doc);
995 docman->priv->pages = g_list_remove (docman->priv->pages, page);
997 if (!docman->priv->shutingdown)
999 if ((page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (docman))) == -1)
1000 anjuta_docman_set_current_document (docman, NULL);
1001 else
1003 AnjutaDocmanPage *next_page;
1004 /* set a replacement active document */
1005 next_page = anjuta_docman_get_nth_page (docman, page_num);
1006 anjuta_docman_set_current_document (docman, next_page->doc);
1009 anjuta_docman_page_destroy (page);
1013 * anjuta_docman_add_editor:
1014 * @docman: pointer to docman data struct
1015 * @uri: string with uri of file to edit, may be "" or NULL
1016 * @name: string with name of file to edit, may be absolute path or just a basename or "" or NULL
1018 * Add a new editor, working on specified uri or filename if any
1020 * Return value: the editor
1022 IAnjutaEditor *
1023 anjuta_docman_add_editor (AnjutaDocman *docman, GFile* file,
1024 const gchar *name)
1026 IAnjutaEditor *te;
1027 IAnjutaEditorFactory* factory;
1029 factory = anjuta_shell_get_interface (docman->shell, IAnjutaEditorFactory, NULL);
1031 te = ianjuta_editor_factory_new_editor (factory, file, name, NULL);
1032 /* if file cannot be loaded, text-editor brings up an error dialog ? */
1033 if (te != NULL)
1035 if (IANJUTA_IS_EDITOR (te))
1036 ianjuta_editor_set_popup_menu (te, docman->priv->popup_menu, NULL);
1037 anjuta_docman_add_document (docman, IANJUTA_DOCUMENT (te), file);
1039 return te;
1042 void
1043 anjuta_docman_add_document (AnjutaDocman *docman, IAnjutaDocument *doc,
1044 GFile* file)
1046 AnjutaDocmanPage *page;
1048 page = anjuta_docman_page_new ();
1049 anjuta_docman_page_init (docman, doc, file, page);
1051 /* list order matches pages in book, initially at least */
1052 docman->priv->pages = g_list_prepend (docman->priv->pages, (gpointer)page);
1054 gtk_notebook_prepend_page_menu (GTK_NOTEBOOK (docman), page->widget,
1055 page->box, page->menu_box);
1056 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (docman), page->widget,
1057 TRUE);
1059 g_signal_connect (G_OBJECT (doc), "update-save-ui",
1060 G_CALLBACK (on_document_update_save_ui), docman);
1061 g_signal_connect (G_OBJECT (doc), "destroy",
1062 G_CALLBACK (on_document_destroy), docman);
1064 g_object_ref (doc);
1066 anjuta_docman_set_current_document (docman, doc);
1067 anjuta_shell_present_widget (docman->shell, GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1068 anjuta_docman_update_documents_menu (docman);
1069 g_signal_emit_by_name (docman, "document-added", doc);
1072 void
1073 anjuta_docman_remove_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1075 AnjutaDocmanPage *page;
1077 if (!doc)
1078 doc = anjuta_docman_get_current_document (docman);
1080 if (!doc)
1081 return;
1083 page = anjuta_docman_get_page_for_document (docman, doc);
1084 if (page)
1086 gtk_container_remove (GTK_CONTAINER (docman), page->widget);
1087 docman->priv->pages = g_list_remove (docman->priv->pages, (gpointer)page);
1088 if (!g_list_length (docman->priv->pages))
1089 g_signal_emit (G_OBJECT (docman), docman_signals[DOC_CHANGED], 0, NULL);
1090 g_free (page);
1092 anjuta_docman_update_documents_menu(docman);
1093 g_object_unref (doc);
1096 void
1097 anjuta_docman_set_popup_menu (AnjutaDocman *docman, GtkWidget *menu)
1099 if (menu)
1100 g_object_ref (G_OBJECT (menu));
1101 if (docman->priv->popup_menu)
1102 gtk_widget_destroy (docman->priv->popup_menu);
1103 docman->priv->popup_menu = menu;
1107 GtkWidget *
1108 anjuta_docman_get_current_focus_widget (AnjutaDocman *docman)
1110 GtkWidget *widget;
1111 widget = gtk_widget_get_toplevel (GTK_WIDGET (docman));
1112 if (gtk_widget_is_toplevel (widget) &&
1113 gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
1115 return gtk_window_get_focus (GTK_WINDOW (widget));
1117 return NULL;
1120 GtkWidget *
1121 anjuta_docman_get_current_popup (AnjutaDocman *docman)
1123 return docman->priv->popup_menu;
1126 static AnjutaDocmanPage *
1127 anjuta_docman_get_page_for_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1129 GList *node;
1130 node = docman->priv->pages;
1131 while (node)
1133 AnjutaDocmanPage *page;
1135 page = node->data;
1136 g_assert (page);
1137 if (page->doc == doc)
1138 return page;
1139 node = g_list_next (node);
1141 return NULL;
1144 static AnjutaDocmanPage *
1145 anjuta_docman_get_nth_page (AnjutaDocman *docman, gint page_num)
1147 GtkWidget *widget;
1148 GList *node;
1150 widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (docman), page_num);
1151 node = docman->priv->pages;
1152 while (node)
1154 AnjutaDocmanPage *page;
1156 page = node->data;
1157 g_assert (page);
1158 if (page->widget == widget)
1159 return page;
1160 node = g_list_next (node);
1163 return NULL;
1166 static AnjutaDocmanPage*
1167 anjuta_docman_get_current_page (AnjutaDocman* docman)
1169 AnjutaDocmanPage* page = anjuta_docman_get_nth_page (docman,
1170 gtk_notebook_get_current_page(GTK_NOTEBOOK(docman)));
1171 return page;
1174 IAnjutaDocument *
1175 anjuta_docman_get_current_document (AnjutaDocman *docman)
1177 AnjutaDocmanPage* page = anjuta_docman_get_current_page (docman);
1178 if (page)
1179 return page->doc;
1180 else
1181 return NULL;
1184 void
1185 anjuta_docman_set_current_document (AnjutaDocman *docman, IAnjutaDocument *doc)
1187 AnjutaDocmanPage *page;
1188 IAnjutaDocument *defdoc;
1190 defdoc = anjuta_docman_get_current_document(docman);
1192 if (doc != NULL)
1194 page = anjuta_docman_get_page_for_document (docman, doc);
1195 /* proceed only if page data has been added before */
1196 if (page)
1198 gint page_num;
1200 if (defdoc != NULL)
1202 AnjutaDocmanPage *oldpage;
1203 oldpage = anjuta_docman_get_page_for_document (docman, defdoc);
1204 if (oldpage)
1206 oldpage->is_current = FALSE;
1207 if (oldpage->close_button != NULL)
1209 gtk_widget_set_sensitive (oldpage->close_image, FALSE);
1210 if (oldpage->mime_icon)
1211 gtk_widget_set_sensitive (oldpage->mime_icon, FALSE);
1216 page->is_current = TRUE;
1217 if (page->close_button != NULL)
1219 gtk_widget_set_sensitive (page->close_image, TRUE);
1220 if (page->mime_icon)
1221 gtk_widget_set_sensitive (page->mime_icon, TRUE);
1223 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (docman),
1224 page->widget);
1225 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), page_num);
1227 if (g_settings_get_boolean (docman->priv->settings,
1228 EDITOR_TABS_ORDERING))
1229 anjuta_docman_order_tabs (docman);
1231 gtk_widget_grab_focus (GTK_WIDGET (doc));
1232 anjuta_docman_grab_text_focus (docman);
1233 ianjuta_document_grab_focus (IANJUTA_DOCUMENT (doc), NULL);
1236 else /* doc == NULL */
1238 if (defdoc != NULL)
1240 page = anjuta_docman_get_current_page (docman);
1241 if (page)
1243 page->is_current = FALSE;
1244 if (page->close_button != NULL)
1246 gtk_widget_set_sensitive (page->close_image, FALSE);
1247 if (page->mime_icon)
1248 gtk_widget_set_sensitive (page->mime_icon, FALSE);
1255 IAnjutaEditor *
1256 anjuta_docman_goto_file_line (AnjutaDocman *docman, GFile* file, gint lineno)
1258 return anjuta_docman_goto_file_line_mark (docman, file, lineno, FALSE);
1261 IAnjutaEditor *
1262 anjuta_docman_goto_file_line_mark (AnjutaDocman *docman, GFile* file,
1263 gint line, gboolean mark)
1265 IAnjutaDocument *doc;
1266 IAnjutaEditor *te;
1267 AnjutaDocmanPage *page;
1269 g_return_val_if_fail (file != NULL, NULL);
1271 if (!g_file_query_exists (file, NULL))
1273 return NULL;
1276 /* Save current uri and line in document history list */
1277 page = anjuta_docman_get_current_page (docman);
1278 if (page && page->doc && IANJUTA_IS_FILE (page->doc))
1280 GFile* file = ianjuta_file_get_file (IANJUTA_FILE (page->doc), NULL);
1282 if (file)
1284 gint line = 0;
1286 if (IANJUTA_IS_EDITOR (page->doc))
1288 line = ianjuta_editor_get_lineno (IANJUTA_EDITOR (page->doc), NULL);
1291 an_file_history_push (file, line);
1295 /* if possible, use a document that's already open */
1296 doc = anjuta_docman_get_document_for_file (docman, file);
1297 if (doc == NULL)
1299 te = anjuta_docman_add_editor (docman, file, NULL);
1300 doc = IANJUTA_DOCUMENT (te);
1302 else if (IANJUTA_IS_EDITOR (doc))
1304 te = IANJUTA_EDITOR (doc);
1306 else
1308 doc = NULL;
1309 te = NULL;
1312 if (te != NULL)
1314 if (line >= 0)
1316 ianjuta_editor_goto_line (te, line, NULL);
1317 if (mark && IANJUTA_IS_MARKABLE (doc))
1319 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (doc),
1320 IANJUTA_MARKABLE_LINEMARKER,
1321 NULL);
1322 ianjuta_markable_mark (IANJUTA_MARKABLE (doc), line,
1323 IANJUTA_MARKABLE_LINEMARKER, NULL, NULL);
1327 if (doc != NULL)
1329 anjuta_docman_present_notebook_page (docman, doc);
1330 ianjuta_document_grab_focus (IANJUTA_DOCUMENT (doc), NULL);
1333 return te;
1336 GFile*
1337 anjuta_docman_get_file (AnjutaDocman *docman, const gchar *fn)
1339 IAnjutaDocument *doc;
1340 GList *node;
1341 gchar *real_path;
1342 gchar *fname;
1344 g_return_val_if_fail (fn, NULL);
1346 /* If it is full and absolute path, there is no need to
1347 go further, even if the file is not found*/
1348 if (g_path_is_absolute(fn))
1350 return g_file_new_for_path (fn);
1353 /* First, check if we can get the file straightaway */
1354 real_path = anjuta_util_get_real_path (fn);
1355 if (g_file_test (real_path, G_FILE_TEST_IS_REGULAR))
1357 return g_file_new_for_path (real_path);
1359 g_free(real_path);
1361 /* Get the name part of the file */
1362 fname = g_path_get_basename (fn);
1364 /* Next, check if the current text editor buffer matches this name */
1365 if (NULL != (doc = anjuta_docman_get_current_document (docman)))
1367 if (strcmp(ianjuta_document_get_filename(doc, NULL), fname) == 0)
1369 g_free (fname);
1370 return ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1373 /* Next, see if the name matches any of the opened files */
1374 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1376 AnjutaDocmanPage *page;
1378 page = (AnjutaDocmanPage *) node->data;
1379 if (strcmp (fname, ianjuta_document_get_filename (page->doc, NULL)) == 0)
1381 g_free (fname);
1382 return ianjuta_file_get_file (IANJUTA_FILE (page->doc), NULL);
1385 g_free (fname);
1386 return NULL;
1389 void
1390 anjuta_docman_present_notebook_page (AnjutaDocman *docman, IAnjutaDocument *doc)
1392 GList *node;
1394 if (!doc)
1395 return;
1397 node = docman->priv->pages;
1399 while (node)
1401 AnjutaDocmanPage* page;
1402 page = (AnjutaDocmanPage *)node->data;
1403 if (page && page->doc == doc)
1405 gint curindx;
1406 curindx = gtk_notebook_page_num (GTK_NOTEBOOK (docman), page->widget);
1407 if (curindx != -1)
1409 if (curindx != gtk_notebook_get_current_page (GTK_NOTEBOOK (docman)))
1410 gtk_notebook_set_current_page (GTK_NOTEBOOK (docman), curindx);
1411 else
1412 /* Make sure current page is visible */
1413 anjuta_docman_grab_text_focus (docman);
1415 break;
1417 node = g_list_next (node);
1421 static void
1422 anjuta_docman_update_page_label (AnjutaDocman *docman, IAnjutaDocument *doc)
1424 AnjutaDocmanPage *page;
1425 gchar *basename;
1426 GFile* file;
1427 const gchar* doc_filename;
1428 gchar* dirty_char;
1429 gchar* read_only;
1430 gchar* label;
1432 if (doc == NULL)
1433 return;
1435 page = anjuta_docman_get_page_for_document (docman, doc);
1436 if (!page || page->label == NULL || page->menu_label == NULL)
1437 return;
1439 if (!ianjuta_file_savable_is_dirty(IANJUTA_FILE_SAVABLE (doc), NULL))
1441 dirty_char = "";
1443 else
1445 dirty_char = "*";
1447 if (ianjuta_file_savable_is_read_only (IANJUTA_FILE_SAVABLE (doc), NULL))
1449 read_only = _("[read-only]");
1451 else
1453 read_only = "";
1456 file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1457 if (file)
1459 basename = g_file_get_basename (file);
1460 label = g_strconcat(dirty_char, basename, read_only, NULL);
1461 gtk_label_set_text (GTK_LABEL (page->label), label);
1462 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1463 g_free (label);
1464 g_free (basename);
1466 if (ianjuta_file_savable_is_conflict (IANJUTA_FILE_SAVABLE (doc), NULL))
1468 gtk_image_set_from_stock (GTK_IMAGE (page->menu_icon), GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
1469 gtk_image_set_from_stock (GTK_IMAGE (page->mime_icon), GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
1471 else
1473 GdkPixbuf* pixbuf = anjuta_docman_get_pixbuf_for_file (file);
1475 if (pixbuf)
1477 gtk_image_set_from_pixbuf (GTK_IMAGE(page->menu_icon), pixbuf);
1478 gtk_image_set_from_pixbuf (GTK_IMAGE(page->mime_icon), pixbuf);
1479 g_object_unref (pixbuf);
1482 g_object_unref (file);
1484 else if ((doc_filename = ianjuta_document_get_filename (doc, NULL)) != NULL)
1486 label = g_strconcat (dirty_char, doc_filename, read_only, NULL);
1487 gtk_label_set_text (GTK_LABEL (page->label), label);
1488 gtk_label_set_text (GTK_LABEL (page->menu_label), label);
1489 g_free (label);
1493 static void
1494 anjuta_docman_grab_text_focus (AnjutaDocman *docman)
1496 anjuta_shell_present_widget (docman->shell,
1497 GTK_WIDGET (docman->priv->plugin->vbox), NULL);
1500 void
1501 anjuta_docman_delete_all_markers (AnjutaDocman *docman, gint marker)
1503 GList *node;
1505 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1507 AnjutaDocmanPage *page;
1509 page = (AnjutaDocmanPage *) node->data;
1510 if (IANJUTA_IS_EDITOR (page->doc))
1512 IAnjutaEditor* te;
1514 te = IANJUTA_EDITOR (page->doc);
1515 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (te), marker, NULL);
1520 void
1521 anjuta_docman_delete_all_indicators (AnjutaDocman *docman)
1523 GList *node;
1525 for (node = docman->priv->pages; node; node = g_list_next (node))
1527 AnjutaDocmanPage *page;
1529 page = (AnjutaDocmanPage *) node->data;
1530 if (IANJUTA_IS_EDITOR (page->doc))
1532 ianjuta_markable_unmark (IANJUTA_MARKABLE (page->doc), -1, -1, NULL);
1537 /* Saves a file to keep it synchronized with external programs */
1538 /* CHECKME unused */
1539 void
1540 anjuta_docman_save_file_if_modified (AnjutaDocman *docman, GFile* file)
1542 IAnjutaDocument *doc;
1544 g_return_if_fail (file != NULL);
1546 doc = anjuta_docman_get_document_for_file (docman, file);
1547 if (doc)
1549 if(ianjuta_file_savable_is_dirty (IANJUTA_FILE_SAVABLE (doc), NULL))
1551 ianjuta_file_savable_save (IANJUTA_FILE_SAVABLE (doc), NULL);
1556 /* If an external program changed the file, we must reload it */
1557 /* CHECKME unused */
1558 void
1559 anjuta_docman_reload_file (AnjutaDocman *docman, GFile* file)
1561 IAnjutaDocument *doc;
1563 g_return_if_fail (file != NULL);
1565 doc = anjuta_docman_get_document_for_file (docman, file);
1566 if (doc && IANJUTA_IS_EDITOR (doc))
1568 IAnjutaEditor *te;
1569 te = IANJUTA_EDITOR (doc);
1570 glong nNowPos = ianjuta_editor_get_lineno (te, NULL);
1571 ianjuta_file_open (IANJUTA_FILE (doc), file, NULL);
1572 ianjuta_editor_goto_line (te, nNowPos, NULL);
1576 typedef struct _order_struct order_struct;
1577 struct _order_struct
1579 const gchar *m_label;
1580 GtkWidget *m_widget;
1583 static int
1584 do_ordertab1 (const void *a, const void *b)
1586 order_struct aos,bos;
1587 aos = *(order_struct*)a;
1588 bos = *(order_struct*)b;
1589 return (g_ascii_strcasecmp (aos.m_label, bos.m_label)); /* need g_utf8_collate() ? */
1592 static void
1593 anjuta_docman_order_tabs (AnjutaDocman *docman)
1595 gint i, num_pages;
1596 GList *node;
1597 AnjutaDocmanPage *page;
1598 order_struct *tab_labels;
1599 GtkNotebook *notebook;
1601 notebook = GTK_NOTEBOOK (docman);
1603 num_pages = gtk_notebook_get_n_pages (notebook);
1604 if (num_pages < 2)
1605 return;
1606 tab_labels = g_new0 (order_struct, num_pages);
1607 node = docman->priv->pages;
1608 for (i = 0; i < num_pages; i++)
1610 if (node != NULL && node->data != NULL)
1612 page = node->data;
1613 tab_labels[i].m_widget = page->widget; /* CHECKME needed ? */
1614 tab_labels[i].m_label = ianjuta_document_get_filename (page->doc, NULL);
1615 node = g_list_next (node);
1618 qsort (tab_labels, num_pages, sizeof(order_struct), do_ordertab1);
1619 g_signal_handlers_block_by_func (G_OBJECT (notebook),
1620 (gpointer) on_notebook_page_reordered,
1621 (gpointer) docman);
1622 for (i = 0; i < num_pages; i++)
1623 gtk_notebook_reorder_child (notebook, tab_labels[i].m_widget, i);
1624 g_signal_handlers_unblock_by_func (G_OBJECT (notebook),
1625 (gpointer) on_notebook_page_reordered,
1626 (gpointer) docman);
1627 g_free (tab_labels);
1628 anjuta_docman_update_documents_menu(docman);
1631 IAnjutaDocument *
1632 anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
1634 IAnjutaDocument *file_doc = NULL;
1635 GList *node;
1636 gchar *path;
1637 gchar *local_real_path = NULL;
1639 g_return_val_if_fail (file != NULL, NULL);
1642 path = g_file_get_path (file);
1643 if (path)
1645 local_real_path = anjuta_util_get_real_path (path);
1646 if (local_real_path)
1648 g_free (path);
1650 else
1652 local_real_path = path;
1655 else
1657 return NULL;
1660 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1662 AnjutaDocmanPage *page;
1663 GFile* doc_file;
1665 page = (AnjutaDocmanPage *) node->data;
1667 if (page && page->widget && IANJUTA_IS_DOCUMENT (page->doc))
1669 IAnjutaDocument *doc;
1671 doc = page->doc;
1672 doc_file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
1673 if (doc_file)
1676 /* Try exact match first */
1677 if (g_file_equal (file, doc_file))
1679 g_object_unref (doc_file);
1680 file_doc = doc;
1681 break;
1684 /* Try a local file alias */
1685 if ((file_doc == NULL) && (local_real_path))
1687 gchar *path = g_file_get_path (doc_file);
1688 if (path)
1690 gchar *doc_real_path = anjuta_util_get_real_path (path);
1691 if (doc_real_path)
1693 g_free (path);
1695 else
1697 doc_real_path = path;
1699 if ((strcmp (doc_real_path, local_real_path) == 0))
1701 file_doc = doc;
1703 g_free (doc_real_path);
1706 g_object_unref (doc_file);
1710 g_free (local_real_path);
1712 return file_doc;
1715 GList*
1716 anjuta_docman_get_all_doc_widgets (AnjutaDocman *docman)
1718 GList *wids;
1719 GList *node;
1721 wids = NULL;
1722 for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
1724 AnjutaDocmanPage *page;
1725 page = (AnjutaDocmanPage *) node->data;
1726 if (page && page->doc)
1727 wids = g_list_prepend (wids, page->doc);
1729 if (wids)
1730 wids = g_list_reverse (wids);
1731 return wids;
1734 ANJUTA_TYPE_BEGIN(AnjutaDocman, anjuta_docman, GTK_TYPE_NOTEBOOK);
1735 ANJUTA_TYPE_END;