OpenClonk
diskview.c
Go to the documentation of this file.
1 /*
2  * mape - C4 Landscape.txt editor
3  *
4  * Copyright (c) 2005-2009, Armin Burgmeier
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <gdk/gdkkeysyms.h>
20 
21 #include "mape/group.h"
22 #include "mape/fileicon.h"
23 #include "mape/configfile.h"
24 #include "mape/mattexview.h"
25 #include "mape/editview.h"
26 #include "mape/diskview.h"
27 
28 static gboolean mape_disk_view_find_iter(MapeDiskView* disk_view,
29  GtkTreeIter* child,
30  GtkTreeIter* parent,
31  const gchar* file)
32 {
33  gboolean result;
34  gchar* filename;
35 
36  result = gtk_tree_model_iter_children(
37  disk_view->tree_store,
38  child,
39  parent
40  );
41 
42  while(result == TRUE)
43  {
44  gtk_tree_model_get(
45  disk_view->tree_store,
46  child,
48  &filename,
49  -1
50  );
51 
52  if(g_strcasecmp(filename, file) == 0)
53  {
54  g_free(filename);
55  return TRUE;
56  }
57 
58  g_free(filename);
59  result = gtk_tree_model_iter_next(disk_view->tree_store, child);
60  }
61 
62  return FALSE;
63 }
64 
65 static gchar* mape_disk_view_get_file_path(MapeDiskView* disk_view,
66  GtkTreeIter* file)
67 {
68  gboolean result;
69  GtkTreeIter parent;
70  GtkTreeIter child;
71  gchar* cur_path;
72  gchar* component;
73  gchar* temp_path;
74 
75  child = *file;
76 
77  gtk_tree_model_get(
78  disk_view->tree_store,
79  file,
81  &cur_path,
82  -1
83  );
84 
85  for(;;)
86  {
87  result = gtk_tree_model_iter_parent(
88  disk_view->tree_store,
89  &parent,
90  &child
91  );
92 
93  if(result == FALSE)
94  break;
95 
96  gtk_tree_model_get(
97  disk_view->tree_store,
98  &parent,
100  &component,
101  -1
102  );
103 
104 #ifdef G_OS_WIN32
105  temp_path = g_build_filename(component, cur_path, NULL);
106 #else
107  /* Add leading "/" to filename for absolute path */
108  temp_path = g_build_filename("/", component, cur_path, NULL);
109 #endif
110  g_free(component); g_free(cur_path);
111  cur_path = temp_path;
112 
113  child = parent;
114  }
115 
116  return cur_path;
117 }
118 
119 static gboolean mape_disk_view_load_materials(MapeDiskView* disk_view,
120  GtkTreeIter* material_iter,
121  GError** error)
122 {
123  GtkTreeIter parent_iter;
124  GtkTreeIter new_parent;
125  gboolean has_parent;
126  gboolean result;
127  gchar* mat_path;
128 
129  MapeGroup* group;
130  MapeGroup* parent_group;
131  MapeGroup* overloaded_group;
132 
133  MapeTextureMap* texture_map;
134  gboolean overload_materials;
135  gboolean overload_textures;
136 
137  /* Open Material.ocg group */
138  gtk_tree_model_get(
139  disk_view->tree_store,
140  material_iter,
142  &group,
143  -1
144  );
145 
146  has_parent = gtk_tree_model_iter_parent(
147  disk_view->tree_store,
148  &parent_iter,
149  material_iter
150  );
151 
152  if(has_parent == TRUE)
153  {
154  gtk_tree_model_get(
155  disk_view->tree_store,
156  &parent_iter,
158  &parent_group,
159  -1
160  );
161 
162  g_assert(parent_group != NULL);
163  }
164  else
165  {
166  parent_group = disk_view->group_top;
167  }
168 
169  if(group == NULL)
170  {
171  group = mape_group_open_child(
172  parent_group,
173  "Material.ocg",
174  error
175  );
176 
177  if(group == NULL) return FALSE;
178 
179  gtk_tree_store_set(
180  GTK_TREE_STORE(disk_view->tree_store),
181  material_iter,
183  group,
184  -1
185  );
186  }
187 
188  /* Load texture map. Note that this effectively only reads the
189  * OverloadMaterials and OverloadTextures flags, because the indices
190  * cannot be assigned yet, because materials and textures have not
191  * been loaded. However, materials and textures can only be loaded
192  * once we know whether we are overloading or not. */
193  texture_map = mape_texture_map_new();
194  if(mape_texture_map_load_map(texture_map, group, error) == FALSE)
195  {
196  g_object_unref(texture_map);
197  return FALSE;
198  }
199 
200  overload_materials = mape_texture_map_get_overload_materials(texture_map);
201  overload_textures = mape_texture_map_get_overload_textures(texture_map);
202 
203  overloaded_group = NULL;
204  if(overload_materials || overload_textures)
205  {
206  /* Look for overloaded Material.ocg */
207  has_parent = gtk_tree_model_iter_parent(
208  disk_view->tree_store,
209  &parent_iter,
210  material_iter
211  );
212 
213  for(;;)
214  {
215  has_parent = gtk_tree_model_iter_parent(
216  disk_view->tree_store,
217  &new_parent,
218  &parent_iter
219  );
220 
221  if(has_parent == FALSE)
222  break;
223 
224  parent_iter = new_parent;
225 
226  gtk_tree_model_get(
227  disk_view->tree_store,
228  &parent_iter,
230  &overloaded_group,
231  -1
232  );
233 
234  if(mape_group_has_entry(overloaded_group, "Material.ocg") ==
235  TRUE)
236  {
237  /* TODO: Check if the group is already open!
238  (mape_disk_view_find_iter). */
239  overloaded_group = mape_group_open_child(
240  overloaded_group,
241  "Material.ocg",
242  error
243  );
244 
245  if(overloaded_group == NULL)
246  {
247  g_object_unref(texture_map);
248  return FALSE;
249  }
250 
251  break;
252  }
253  }
254  }
255 
256  mat_path = mape_disk_view_get_file_path(disk_view, material_iter);
258  disk_view->config,
259  "material_path",
260  mat_path
261  );
262  g_free(mat_path);
263 
264  result = mape_mat_tex_view_reload(
265  disk_view->mat_tex,
266  texture_map,
267  group,
268  overload_materials,
269  overload_textures,
270  overloaded_group,
271  error
272  );
273 
274  g_object_unref(texture_map);
275  mape_mapgen_set_root_group(parent_group);
276 
277 #if 0
278  if(overloaded_group != NULL)
279  mape_group_destroy(overloaded_group);
280 #endif
281 
282  mape_edit_view_reload(disk_view->edit_view);
283 
284  return result;
285 }
286 
287 static gboolean mape_disk_view_load(MapeDiskView* disk_view,
288  GtkTreeIter* parent_iter,
289  GError** error)
290 {
291  GtkTreeIter child_iter;
292  GtkTreeIter group_iter;
293  GtkTreeIter temp_iter;
294 
295  MapeGroup* child_group;
296  MapeGroup* parent_group;
297 
298  MapeFileIcon* icon;
299  MapeFileIconType icon_type;
300  const char* fileext;
301  char* filename;
302  char* utf8_file;
303  gboolean deplevel;
304 
305  if(parent_iter != NULL)
306  {
307  gtk_tree_model_get(
308  disk_view->tree_store,
309  parent_iter,
311  &parent_group,
312  -1
313  );
314 
315  /* Group is already open */
316  if(parent_group != NULL)
317  return TRUE;
318 
319  /* Get parent group */
320  deplevel = gtk_tree_model_iter_parent(
321  disk_view->tree_store,
322  &group_iter,
323  parent_iter
324  );
325 
326  if(deplevel == TRUE)
327  {
328  gtk_tree_model_get(
329  disk_view->tree_store,
330  &group_iter,
332  &parent_group,
333  -1
334  );
335 
336  g_assert(parent_group != NULL);
337  }
338  else
339  {
340  /* Parent is at top-level */
341  parent_group = disk_view->group_top;
342  }
343  }
344  else
345  {
346  parent_group = NULL;
347  }
348 
349  if(parent_group != NULL)
350  {
351  gtk_tree_model_get(
352  disk_view->tree_store,
353  parent_iter,
355  &utf8_file,
356  -1
357  );
358 
359 #ifdef G_OS_WIN32
360  filename = g_convert(
361  utf8_file,
362  -1,
363  "LATIN1",
364  "UTF-8",
365  NULL,
366  NULL,
367  NULL
368  );
369 #else
370  filename = g_filename_from_utf8(
371  utf8_file,
372  -1,
373  NULL,
374  NULL,
375  NULL
376  );
377 #endif
378 
379  g_free(utf8_file);
380 
381  child_group = mape_group_open_child(
382  parent_group,
383  filename,
384  error
385  );
386 
387  g_free(filename);
388 
389  if(child_group == NULL)
390  return FALSE;
391 
392  /* Store child group in parent */
393  gtk_tree_store_set(
394  GTK_TREE_STORE(disk_view->tree_store),
395  parent_iter,
397  (gpointer)child_group,
398  -1
399  );
400  }
401  else
402  {
403  /* Group is already open */
404  if(disk_view->group_top != NULL)
405  return TRUE;
406 
407  disk_view->group_top = mape_group_new();
408  if(!mape_group_open(disk_view->group_top, "/", error))
409  {
410  g_object_unref(disk_view->group_top);
411  disk_view->group_top = NULL;
412  return FALSE;
413  }
414 
415  child_group = disk_view->group_top;
416  }
417 
418  while( (filename = mape_group_get_next_entry(child_group)) != NULL)
419  {
420  /* Check if this entry is a directory (we are hiding files). */
421  if(mape_group_is_child_folder(child_group, filename) == FALSE)
422  {
423  g_free(filename);
424  continue;
425  }
426 
427 #ifdef G_OS_WIN32
428  utf8_file = g_convert(
429  filename,
430  -1,
431  "UTF-8",
432  "LATIN1",
433  NULL,
434  NULL,
435  NULL
436  );
437 #else
438  utf8_file = g_filename_to_utf8(
439  filename,
440  -1,
441  NULL,
442  NULL,
443  NULL
444  );
445 #endif
446 
447  g_free(filename);
448  filename = utf8_file;
449 
450  /* Invalid file name */
451  if(filename == NULL)
452  continue;
453 
454  gtk_tree_store_append(
455  GTK_TREE_STORE(disk_view->tree_store),
456  &child_iter,
457  parent_iter
458  );
459 
460  /* Create temporary entry to show the expander arrow */
461  if(g_strcasecmp(filename, "Material.ocg") != 0)
462  {
463  gtk_tree_store_append(
464  GTK_TREE_STORE(disk_view->tree_store),
465  &temp_iter,
466  &child_iter
467  );
468  }
469 
470  fileext = strrchr(filename, '.');
471  icon_type = MAPE_FILE_ICON_FOLDER;
472 
473  if(fileext != NULL)
474  {
475  if(g_strcasecmp(fileext, ".ocd") == 0)
476  icon_type = MAPE_FILE_ICON_C4OBJECT;
477  else if(g_strcasecmp(fileext, ".ocf") == 0)
478  icon_type = MAPE_FILE_ICON_C4FOLDER;
479  else if(g_strcasecmp(fileext, ".ocg") == 0)
480  icon_type = MAPE_FILE_ICON_C4GROUP;
481  else if(g_strcasecmp(fileext, ".ocs") == 0)
482  icon_type = MAPE_FILE_ICON_C4SCENARIO;
483  }
484 
485  if(mape_group_is_drive_container(child_group))
486  icon_type = MAPE_FILE_ICON_DRIVE;
487 
489  disk_view->icon_set,
490  icon_type
491  );
492 
493  gtk_tree_store_set(
494  GTK_TREE_STORE(disk_view->tree_store),
495  &child_iter,
497  mape_file_icon_get(icon),
499  filename,
501  NULL,/*(gpointer)child_group,*/
502  -1
503  );
504 
505  gtk_tree_model_ref_node(
506  disk_view->tree_store,
507  &child_iter
508  );
509 
510  g_free(filename);
511  }
512 
513  /* TODO: Close group if no content */
514 
515  return TRUE;
516 }
517 
518 static gboolean mape_disk_view_cb_key_press_event(GtkWidget* widget,
519  GdkEventKey* event,
520  gpointer user_data)
521 {
522  MapeDiskView* disk_view;
523  GtkTreePath* path;
524  gboolean result;
525 
526  disk_view = (MapeDiskView*)user_data;
527 
528  if(event->keyval != GDK_KEY_Left && event->keyval != GDK_KEY_Right)
529  return FALSE;
530 
531  gtk_tree_view_get_cursor(
532  GTK_TREE_VIEW(disk_view->view),
533  &path,
534  NULL
535  );
536 
537  if(path == NULL) return FALSE;
538 
539  switch(event->keyval)
540  {
541  case GDK_KEY_Left:
542  result = gtk_tree_view_row_expanded(
543  GTK_TREE_VIEW(disk_view->view),
544  path
545  );
546 
547  if(result == TRUE)
548  {
549  gtk_tree_view_collapse_row(
550  GTK_TREE_VIEW(disk_view->view),
551  path
552  );
553  }
554  else
555  {
556  if(gtk_tree_path_get_depth(path) > 1)
557  {
558  result = gtk_tree_path_up(path);
559  g_assert(result == TRUE);
560 
561  gtk_tree_view_set_cursor(
562  GTK_TREE_VIEW(disk_view->view),
563  path,
564  NULL,
565  FALSE
566  );
567  }
568  }
569 
570  break;
571  case GDK_KEY_Right:
572  result = gtk_tree_view_row_expanded(
573  GTK_TREE_VIEW(disk_view->view),
574  path
575  );
576 
577  if(result == TRUE)
578  {
579  gtk_tree_path_down(path);
580 
581  gtk_tree_view_set_cursor(
582  GTK_TREE_VIEW(disk_view->view),
583  path,
584  NULL,
585  FALSE
586  );
587  }
588  else
589  {
590  gtk_tree_view_expand_row(
591  GTK_TREE_VIEW(disk_view->view),
592  path,
593  FALSE
594  );
595  }
596 
597  break;
598  default:
599  g_assert_not_reached();
600  break;
601  }
602 
603  gtk_tree_path_free(path);
604  return TRUE;
605 }
606 
607 static gboolean mape_disk_view_cb_button_press_event(GtkWidget* widget,
608  GdkEventButton* event,
609  gpointer user_data)
610 {
611  MapeDiskView* disk_view;
612  GtkTreePath* path;
613  GtkTreeIter iter;
614  gboolean result;
615  gchar* filename;
616  GError* error = NULL;
617  GtkWidget* error_dialog;
618 
619  disk_view = (MapeDiskView*)user_data;
620 
621  if(event->type == GDK_2BUTTON_PRESS)
622  {
623  gtk_tree_view_get_cursor(
624  GTK_TREE_VIEW(disk_view->view),
625  &path,
626  NULL
627  );
628 
629  if(path == NULL) return FALSE;
630 
631  gtk_tree_model_get_iter(
632  disk_view->tree_store,
633  &iter,
634  path
635  );
636 
637  gtk_tree_model_get(
638  disk_view->tree_store,
639  &iter,
641  &filename,
642  -1
643  );
644 
645  /* Load Material.ocg */
646  if(g_strcasecmp(filename, "Material.ocg") == 0)
647  {
648  result = mape_disk_view_load_materials(
649  disk_view,
650  &iter,
651  &error
652  );
653 
654  if(result == FALSE)
655  {
656  error_dialog = gtk_message_dialog_new(
657  NULL,
658  GTK_DIALOG_MODAL,
659  GTK_MESSAGE_ERROR,
660  GTK_BUTTONS_OK,
661  "%s",
662  error->message
663  );
664 
665  g_error_free(error);
666  gtk_dialog_run(GTK_DIALOG(error_dialog) );
667  gtk_widget_destroy(error_dialog);
668  }
669  }
670  else
671  {
672  result = gtk_tree_view_row_expanded(
673  GTK_TREE_VIEW(disk_view->view),
674  path
675  );
676 
677  if(result == TRUE)
678  {
679  gtk_tree_view_collapse_row(
680  GTK_TREE_VIEW(disk_view->view),
681  path
682  );
683  }
684  else
685  {
686  gtk_tree_view_expand_row(
687  GTK_TREE_VIEW(disk_view->view),
688  path,
689  FALSE
690  );
691  }
692  }
693 
694  g_free(filename);
695  gtk_tree_path_free(path);
696  return TRUE;
697  }
698 
699  return FALSE;
700 }
701 
702 static void mape_disk_view_cb_row_expanded(GtkTreeView* treeview,
703  GtkTreeIter* row,
704  GtkTreePath* path,
705  gpointer user_data)
706 {
707  MapeDiskView* disk_view;
708  MapeGroup* group;
709  GtkTreeIter iter;
710  GtkTreeIter temp_iter;
711  gboolean result;
712  GError* error = NULL;
713  GtkWidget* error_dialog;
714 
715  disk_view = (MapeDiskView*)user_data;
716  result = gtk_tree_model_get_iter(
717  disk_view->tree_store,
718  &iter,
719  path
720  );
721 
722  g_assert(result == TRUE);
723 
724  /* Remove temporary entry if group is not already loaded */
725  gtk_tree_model_get(
726  disk_view->tree_store,
727  &iter,
729  &group,
730  -1
731  );
732 
733  if(group == NULL)
734  {
735  g_assert(
736  gtk_tree_model_iter_n_children(
737  disk_view->tree_store,
738  &iter
739  ) == 1
740  );
741 
742  result = gtk_tree_model_iter_children(
743  disk_view->tree_store,
744  &temp_iter,
745  &iter
746  );
747 
748  g_assert(result == TRUE);
749 
750  result = gtk_tree_store_remove(
751  GTK_TREE_STORE(disk_view->tree_store),
752  &temp_iter
753  );
754 
755  g_assert(result == FALSE);
756  }
757 
758  if(mape_disk_view_load(disk_view, &iter, &error) == FALSE)
759  {
760  error_dialog = gtk_message_dialog_new(
761  NULL,
762  GTK_DIALOG_MODAL,
763  GTK_MESSAGE_ERROR,
764  GTK_BUTTONS_OK,
765  "%s",
766  error->message
767  );
768 
769  g_error_free(error);
770  gtk_dialog_run(GTK_DIALOG(error_dialog) );
771  gtk_widget_destroy(error_dialog);
772 
773  return;
774  }
775 
776  if(group == NULL)
777  {
778  gtk_tree_view_expand_row(
779  GTK_TREE_VIEW(disk_view->view),
780  path,
781  FALSE
782  );
783  }
784 }
785 
786 static void mape_disk_view_close_groups(MapeDiskView* disk_view,
787  GtkTreeIter* iter)
788 {
789  MapeGroup* group;
790  GtkTreeIter child;
791  gboolean has_child, has_next;
792 
793  gtk_tree_model_get(
794  disk_view->tree_store,
795  iter,
797  &group,
798  -1
799  );
800 
801  has_child = gtk_tree_model_iter_children(
802  disk_view->tree_store,
803  &child,
804  iter
805  );
806 
807  has_next = gtk_tree_model_iter_next(
808  disk_view->tree_store,
809  iter
810  );
811 
812  if(has_child == TRUE)
813  mape_disk_view_close_groups(disk_view, &child);
814 
815  if(group != NULL)
816  g_object_unref(group);
817 
818  if(has_next == TRUE)
819  mape_disk_view_close_groups(disk_view, iter);
820 }
821 
822 
824  MapeMatTexView* mat_tex,
825  MapeEditView* edit_view,
826  MapeConfigFile* config,
827  GError** error)
828 {
829  MapeDiskView* view;
830 
831  view = malloc(sizeof(MapeDiskView) );
832 
833  view->group_top = NULL;
834  view->icon_set = icon_set;
835  view->mat_tex = mat_tex;
836  view->edit_view = edit_view;
837  view->config = config;
838 
839  view->tree_store = GTK_TREE_MODEL(
840  gtk_tree_store_new(
842  GDK_TYPE_PIXBUF,
843  G_TYPE_STRING,
844  G_TYPE_POINTER
845  )
846  );
847 
848  view->renderer_icon = gtk_cell_renderer_pixbuf_new();
849  view->renderer_file = gtk_cell_renderer_text_new();
850 
851  /*view->col_icon = gtk_tree_view_column_new_with_attributes(
852  "Icon",
853  view->renderer_icon,
854  "pixbuf", MAPE_DISK_VIEW_COLUMN_ICON,
855  NULL
856  );*/
857 
858  view->col_file = gtk_tree_view_column_new();
859 
860 /* view->col_file = gtk_tree_view_column_new_with_attributes(
861  "Filename",
862  view->renderer_file,
863  "text", MAPE_DISK_VIEW_COLUMN_FILE,
864  "pixbuf", MAPE_DISK_VIEW_COLUMN_ICON,
865  NULL
866  );*/
867 
868  gtk_tree_view_column_pack_start(
869  view->col_file,
870  view->renderer_icon,
871  FALSE
872  );
873 
874  gtk_tree_view_column_pack_start(
875  view->col_file,
876  view->renderer_file,
877  TRUE
878  );
879 
880  gtk_tree_view_column_set_attributes(
881  view->col_file,
882  view->renderer_icon,
883  "pixbuf", MAPE_DISK_VIEW_COLUMN_ICON,
884  NULL
885  );
886 
887  gtk_tree_view_column_set_attributes(
888  view->col_file,
889  view->renderer_file,
891  NULL
892  );
893 
894  gtk_tree_view_column_set_spacing(
895  view->col_file,
896  5
897  );
898 
899  view->view = gtk_tree_view_new_with_model(
900  GTK_TREE_MODEL(view->tree_store)
901  );
902 
903  gtk_widget_add_events(
904  view->view,
905  GDK_BUTTON_PRESS_MASK |
906  GDK_KEY_PRESS_MASK
907  );
908 
909  gtk_tree_view_append_column(GTK_TREE_VIEW(view->view), view->col_file);
910 
911  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view->view), FALSE);
912  gtk_tree_sortable_set_sort_column_id(
913  GTK_TREE_SORTABLE(view->tree_store),
915  GTK_SORT_ASCENDING
916  );
917 
918  g_signal_connect(
919  G_OBJECT(view->view),
920  "row-expanded",
921  G_CALLBACK(mape_disk_view_cb_row_expanded),
922  view
923  );
924 
925  g_signal_connect(
926  G_OBJECT(view->view),
927  "button-press-event",
928  G_CALLBACK(mape_disk_view_cb_button_press_event),
929  view
930  );
931 
932  g_signal_connect(
933  G_OBJECT(view->view),
934  "key-press-event",
935  G_CALLBACK(mape_disk_view_cb_key_press_event),
936  view
937  );
938 
939  if(mape_disk_view_load(view, NULL, error) == FALSE)
940  {
941  /* TODO: Free cell renderers? */
942  gtk_widget_destroy(view->view);
943  g_object_unref(G_OBJECT(view->tree_store) );
944 
945  free(view);
946  return NULL;
947  }
948 
949  gtk_widget_show(view->view);
950 
951  view->window = gtk_scrolled_window_new(NULL, NULL);
952  gtk_container_add(
953  GTK_CONTAINER(view->window),
954  view->view
955  );
956 
957  gtk_scrolled_window_set_policy(
958  GTK_SCROLLED_WINDOW(view->window),
959  GTK_POLICY_AUTOMATIC,
960  GTK_POLICY_AUTOMATIC
961  );
962 
963  gtk_scrolled_window_set_shadow_type(
964  GTK_SCROLLED_WINDOW(view->window),
965  GTK_SHADOW_IN
966  );
967 
968  gtk_widget_set_size_request(view->window, 150, -1);
969  gtk_widget_show(view->window);
970 
971  return view;
972 }
973 
975 {
976  /* Close open groups */
977  GtkTreeIter iter;
978  if(gtk_tree_model_get_iter_first(disk_view->tree_store, &iter))
979  mape_disk_view_close_groups(disk_view, &iter);
980 
981  /* TODO: unref cell renderers? */
982  /*mape_file_icon_set_destroy(disk_view->icon_set);*/
983  g_object_unref(disk_view->group_top);
984 
985  g_object_unref(G_OBJECT(disk_view->tree_store) );
986  free(disk_view);
987 }
988 
990  const gchar* filepath,
991  GError** error)
992 {
993  gchar** path_components;
994  gchar** cur_component;
995  gchar* file;
996  GtkTreeIter parent;
997  GtkTreeIter child;
998  gboolean result;
999  GtkTreePath* path;
1000  gboolean got_parent;
1001 
1002  path_components = g_strsplit_set(filepath, "/\\", 0);
1003 
1004  /* Begin at top-level: no parent */
1005  got_parent = FALSE;
1006 
1007  for(cur_component = path_components;
1008  *cur_component != NULL;
1009  ++ cur_component)
1010  {
1011  file = *cur_component;
1012  if(*file == '\0') continue;
1013  if(strcmp(file, ".") == 0) continue;
1014 
1015  if(strcmp(file, "..") == 0)
1016  {
1017  if(got_parent == FALSE)
1018  {
1019  g_set_error(
1020  error,
1021  g_quark_from_static_string(
1022  "MAPE_DISK_VIEW_ERROR"
1023  ),
1025  "%s: Invalid path",
1026  filepath
1027  );
1028 
1029  g_strfreev(path_components);
1030  return FALSE;
1031  }
1032  else
1033  {
1034  child = parent;
1035 
1036  got_parent = gtk_tree_model_iter_parent(
1037  GTK_TREE_MODEL(disk_view->tree_store),
1038  &parent,
1039  &child
1040  );
1041  }
1042  }
1043  else
1044  {
1045  if(got_parent == FALSE)
1046  {
1047  result = mape_disk_view_find_iter(
1048  disk_view,
1049  &child,
1050  NULL,
1051  file
1052  );
1053  }
1054  else
1055  {
1056  result = mape_disk_view_find_iter(
1057  disk_view,
1058  &child,
1059  &parent,
1060  file
1061  );
1062  }
1063 
1064  /* File is not reachable in file system */
1065  if(result == FALSE)
1066  {
1067  g_set_error(
1068  error,
1069  g_quark_from_static_string(
1070  "MAPE_DISK_VIEW_ERROR"
1071  ),
1073  "%s: No such file or directory",
1074  filepath
1075  );
1076 
1077  g_strfreev(path_components);
1078  return FALSE;
1079  }
1080 
1081  if(g_ascii_strcasecmp(file, "Material.ocg") == 0)
1082  {
1083  /* Assume end of path */
1084  result = mape_disk_view_load_materials(
1085  disk_view,
1086  &child,
1087  error
1088  );
1089 
1090  g_strfreev(path_components);
1091  return result;
1092  }
1093  else
1094  {
1095  /* Convert child to path to preserve
1096  position while expanding */
1097  path = gtk_tree_model_get_path(
1098  disk_view->tree_store,
1099  &child
1100  );
1101 
1102  gtk_tree_view_expand_row(
1103  GTK_TREE_VIEW(disk_view->view),
1104  path,
1105  FALSE
1106  );
1107 
1108  /* Child is new parent for next iteration */
1109  gtk_tree_model_get_iter(
1110  disk_view->tree_store,
1111  &parent,
1112  path
1113  );
1114  got_parent = TRUE;
1115 
1116  gtk_tree_path_free(path);
1117  }
1118  }
1119  }
1120 
1121  /* All nodes expanded without opening Material.ocg */
1122  g_strfreev(path_components);
1123  return TRUE;
1124 }
void mape_config_file_set_entry(MapeConfigFile *file, const gchar *key, const gchar *value)
Definition: configfile.c:143
gboolean mape_disk_view_extend_to_path(MapeDiskView *disk_view, const gchar *filepath, GError **error)
Definition: diskview.c:989
void mape_disk_view_destroy(MapeDiskView *disk_view)
Definition: diskview.c:974
MapeDiskView * mape_disk_view_new(MapeFileIconSet *icon_set, MapeMatTexView *mat_tex, MapeEditView *edit_view, MapeConfigFile *config, GError **error)
Definition: diskview.c:823
GtkTreeModel * tree_store
Definition: diskview.h:42
MapeEditView * edit_view
Definition: diskview.h:50
@ MAPE_DISK_VIEW_COLUMN_COUNT
Definition: diskview.h:29
@ MAPE_DISK_VIEW_COLUMN_FILE
Definition: diskview.h:26
@ MAPE_DISK_VIEW_COLUMN_ICON
Definition: diskview.h:25
@ MAPE_DISK_VIEW_COLUMN_GROUP
Definition: diskview.h:27
GtkTreeViewColumn * col_file
Definition: diskview.h:47
GtkWidget * view
Definition: diskview.h:40
GtkCellRenderer * renderer_icon
Definition: diskview.h:44
MapeMatTexView * mat_tex
Definition: diskview.h:49
MapeGroup * group_top
Definition: diskview.h:53
MapeConfigFile * config
Definition: diskview.h:54
@ MAPE_DISK_VIEW_ERROR_NOENT
Definition: diskview.h:33
MapeFileIconSet * icon_set
Definition: diskview.h:52
GtkCellRenderer * renderer_file
Definition: diskview.h:45
GtkWidget * window
Definition: diskview.h:39
void mape_edit_view_reload(MapeEditView *edit_view)
Definition: editview.c:764
MapeFileIcon * mape_file_icon_set_lookup(MapeFileIconSet *set, MapeFileIconType type)
Definition: fileicon.c:129
GdkPixbuf * mape_file_icon_get(MapeFileIcon *icon)
Definition: fileicon.c:137
@ MAPE_FILE_ICON_FOLDER
Definition: fileicon.h:26
@ MAPE_FILE_ICON_C4GROUP
Definition: fileicon.h:27
@ MAPE_FILE_ICON_C4OBJECT
Definition: fileicon.h:29
@ MAPE_FILE_ICON_C4SCENARIO
Definition: fileicon.h:28
@ MAPE_FILE_ICON_C4FOLDER
Definition: fileicon.h:30
@ MAPE_FILE_ICON_DRIVE
Definition: fileicon.h:25
enum MapeFileIconType_ MapeFileIconType
MapeGroup * mape_group_open_child(MapeGroup *group, const gchar *entry, GError **error)
Definition: group.c:301
gchar * mape_group_get_next_entry(MapeGroup *group)
Definition: group.c:496
MapeGroup * mape_group_new(void)
Definition: group.c:206
gboolean mape_group_is_drive_container(MapeGroup *group)
Definition: group.c:603
gboolean mape_group_is_child_folder(MapeGroup *group, const gchar *child)
Definition: group.c:631
gboolean mape_group_open(MapeGroup *group, const gchar *path, GError **error)
Definition: group.c:249
gboolean mape_group_has_entry(MapeGroup *group, const gchar *entry)
Definition: group.c:424
void mape_mapgen_set_root_group(MapeGroup *group)
Definition: mapgen.c:169
gboolean mape_mat_tex_view_reload(MapeMatTexView *view, MapeTextureMap *new_tex_map, MapeGroup *base_group, gboolean overload_materials, gboolean overload_textures, MapeGroup *overload_from, GError **error)
Definition: mattexview.c:93
gboolean mape_texture_map_get_overload_textures(MapeTextureMap *texture_map)
Definition: texture.c:443
MapeTextureMap * mape_texture_map_new(void)
Definition: texture.c:247
gboolean mape_texture_map_get_overload_materials(MapeTextureMap *texture_map)
Definition: texture.c:427
gboolean mape_texture_map_load_map(MapeTextureMap *texture_map, MapeGroup *group, GError **error)
Definition: texture.c:265