diff options
| author | 2009-08-04 12:46:28 +0200 | |
|---|---|---|
| committer | 2009-08-04 12:46:28 +0200 | |
| commit | a8ef94eb87ed1a7f5e155eed8c3139bc60040293 (patch) | |
| tree | 05abb793008e6597a28824c33c6ae1bb0afeb461 /src | |
| download | gnome-plist-editor-a8ef94eb87ed1a7f5e155eed8c3139bc60040293.tar.gz gnome-plist-editor-a8ef94eb87ed1a7f5e155eed8c3139bc60040293.tar.bz2 | |
Add initial sources with ability to open and view .plist files
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 17 | ||||
| -rw-r--r-- | src/gnome-plist-editor.c | 377 | ||||
| -rw-r--r-- | src/gnome-plist-editor.ui | 353 | ||||
| -rw-r--r-- | src/plist-utils.c | 51 | ||||
| -rw-r--r-- | src/plist-utils.h | 29 | 
5 files changed, 827 insertions, 0 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f5cf7a8 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,17 @@ +bin_PROGRAMS = gnome-plist-editor + +gnome_plist_editor_SOURCES = \ +	gnome-plist-editor.c \ +	plist-utils.c + +gnome_plist_editor_CFLAGS = \ +	-Wl,--export-dynamic \ +	$(GLIB_CFLAGS) \ +	$(GTK_CFLAGS) \ +	$(LIBPLIST_CFLAGS) + +gnome_plist_editor_LDADD = \ +	-lpthread \ +	$(GLIB_LIBS) \ +	$(GTK_LIBS) \ +	$(LIBPLIST_LIBS) diff --git a/src/gnome-plist-editor.c b/src/gnome-plist-editor.c new file mode 100644 index 0000000..858480c --- /dev/null +++ b/src/gnome-plist-editor.c @@ -0,0 +1,377 @@ +/* + * gnome-plist-editor.c + * + * Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com> + *  + * The code contained in this file is free software; you can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + *   + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *   + * You should have received a copy of the GNU Lesser General Public + * License along with this code; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + *  + */ + +#include <config.h> + +#include <stdlib.h> + +#include <gtk/gtk.h> +#include <gio/gio.h> + +#include <plist/plist.h> +#include "plist-utils.h" + +static struct AppState { +	GtkWindow *main_window; +	GtkTreeStore *document_tree_store; +	GtkTreeView *document_tree_view; + +	plist_t root_node; +	gboolean is_binary; +} app; + +void main_window_destroy_cb(GtkWidget* widget, gpointer user_data) { +	if (app.document_tree_store) +		gtk_tree_store_clear(app.document_tree_store); + +	if (app.root_node) +		plist_free(app.root_node); + +	gtk_main_quit(); +} + +void update_document_tree_view(plist_t node, GtkTreeIter *parent) { +	GtkTreeStore *store = app.document_tree_store; +	GtkTreeIter iter; +	plist_t subnode = NULL; +	plist_t value_node = NULL; +	plist_type type; +	plist_type value_type; + +	gtk_tree_store_append(store, &iter, parent); +	gtk_tree_store_set(store, &iter, +		0, (gpointer)node, +		-1); + +	/* check for root */ +	if (parent == NULL) { +		value_node = node; +	} else { +		value_node = plist_get_next_sibling(node); +	} +	value_type = plist_get_node_type(value_node); + +	/* recurse through children */ +	for ( +		subnode = plist_get_first_child(value_node); +		subnode != NULL; +		subnode = plist_get_next_sibling(subnode) +	) { +		type = plist_get_node_type(subnode); +		if (type == PLIST_KEY) { +			update_document_tree_view(subnode, &iter); +		} +		if (value_type == PLIST_ARRAY && (type != PLIST_DICT && type != PLIST_ARRAY)) { +			update_document_tree_view(subnode, &iter); +		} +	} +} + +static void open_plist_file(const char *filename) { +	char *buffer = NULL; +	gsize size = 0; +	gsize bytes_read = 0; +	GFile *file = NULL; +	GFileInfo *fileinfo = NULL; +	GFileInputStream *filestream = NULL; +	GError *err = NULL; + +	file = g_file_new_for_path(filename); +	filestream = g_file_read(file, NULL, &err); +	if (!filestream) { +		fprintf(stderr, "ERROR: opening %s: %s\n", file, err->message); +		g_object_unref(file); +		goto leave; +	} + +	fileinfo = g_file_query_info(file, +		G_FILE_ATTRIBUTE_STANDARD_SIZE, +		G_FILE_QUERY_INFO_NONE, +		NULL, +		&err); + +	size = g_file_info_get_size(fileinfo); + +	/* read in the plist */ +	buffer = (char *)g_malloc(sizeof(char) * (size + 1)); +	g_input_stream_read_all(G_INPUT_STREAM(filestream), +		buffer, +		size, +		&bytes_read, +		NULL, +		&err); + +	if (memcmp(buffer, "bplist00", 8) == 0) { +		plist_from_bin(buffer, size, &app.root_node); +		app.is_binary = TRUE; +	} else { +		plist_from_xml(buffer, size, &app.root_node); +		app.is_binary = FALSE; +	} + +	gtk_tree_store_clear(app.document_tree_store); +	update_document_tree_view(app.root_node, NULL); +	gtk_tree_view_expand_all(app.document_tree_view); + +	g_free(buffer); + +leave: +	if (fileinfo) +		g_object_unref(fileinfo); +	if (filestream) +		g_object_unref(filestream); +	if (file) +		g_object_unref(file); +} + +void open_plist_cb(GtkWidget* item, gpointer user_data) { +	GtkWidget *dialog; +	GtkFileFilter *filter; + +	char *filename = NULL; + +	dialog = gtk_file_chooser_dialog_new ("Open Property List File", +		app.main_window, +		GTK_FILE_CHOOSER_ACTION_OPEN, +		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, +		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, +		NULL); + +	/* add default filter */ +	filter = gtk_file_filter_new(); +	gtk_file_filter_set_name(filter, "All Files"); +	gtk_file_filter_add_pattern(filter, "*"); +	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + +	/* add plist filter */ +	filter = gtk_file_filter_new(); +	gtk_file_filter_add_pattern(filter, "*.plist"); +	gtk_file_filter_set_name(filter, "Property List Files"); +	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); +	gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + +	if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { +		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); +		open_plist_file(filename); +	} + +	if (filename) +		g_free (filename); + +	gtk_widget_destroy (dialog); +} + +void about_menu_item_activate_cb(GtkMenuItem* item, gpointer user_data) { +	gtk_show_about_dialog(app.main_window, +		"program-name", "GNOME Property List Editor", +		"logo-icon-name", "text-editor", +		"website", "http://cgit.sukimashita.com/gnome-plist-editor.git/", +		"website-label", "GIT Source Code Repository", +		"version", PACKAGE_VERSION, +		NULL); +} + +typedef enum { +	COL_KEY, +	COL_TYPE, +	COL_VALUE, +	N_COLUMNS +} col_type_t; + +void plist_cell_data_function (GtkTreeViewColumn *col, +	GtkCellRenderer *renderer, +	GtkTreeModel *model, +	GtkTreeIter *iter, +	gpointer user_data) +{ +	col_type_t col_type; +	plist_t node; +	plist_t value_node; +	plist_t parent_node; +	plist_type value_type; +	char *text = NULL; + +	char *s = NULL; +	double d; +	uint8_t b; +	uint64_t u = 0; + +	col_type = (col_type_t)GPOINTER_TO_INT(user_data); + +	gtk_tree_model_get(model, iter, 0, &node, -1); + +	parent_node = plist_get_parent(node); + +	if (parent_node == NULL) { +		value_node = node; +	} +	else +	{ +		value_node = plist_get_next_sibling(node); +	} + +	if (plist_get_node_type(parent_node) == PLIST_ARRAY) { +		if ((value_type != PLIST_DICT) && (value_type != PLIST_ARRAY)) { +			value_node = node; +		} +	} +	value_type = plist_get_node_type(value_node); + +	switch(col_type) { +	case COL_KEY: +		if (plist_get_parent(node) == NULL) { +			text = "Root"; +		} +		else +		{ +			switch(plist_get_node_type(node)) { +			case PLIST_KEY: +				plist_get_key_val(node, &text); +				break; +			case PLIST_STRING: +				plist_get_string_val(node, &text); +				break; +			case PLIST_UINT: +				plist_get_uint_val(value_node, &u); +				text = g_strdup_printf("%llu", (long long)u); +				break; +			default: +				text = g_strdup_printf("Unhandled %d", plist_get_node_type(node)); +				break; +			} +		} +		break; +	case COL_TYPE: +		switch(value_type) { +		case PLIST_BOOLEAN: +			text = "Boolean"; +			break; +		case PLIST_UINT: +			text = "Number"; +			break; +		case PLIST_REAL: +			text = "Float"; +			break; +		case PLIST_STRING: +			text = "String"; +			break; +		case PLIST_DATA: +			text = "Data"; +			break; +		case PLIST_DATE: +			text = "Date"; +			break; +		case PLIST_ARRAY: +			text = "Array"; +			break; +		case PLIST_DICT: +			text = "Dictionary"; +			break; +		} +		break; +	case COL_VALUE: +		g_object_set(renderer, "sensitive", TRUE, NULL); +		switch(value_type) { +		case PLIST_BOOLEAN: +			plist_get_bool_val(value_node, &b); +			text = (b ? "true" : "false"); +			break; +		case PLIST_UINT: +			plist_get_uint_val(value_node, &u); +			text = g_strdup_printf("%llu", (long long)u); +			break; +		case PLIST_REAL: +			plist_get_real_val(value_node, &d); +			text = g_strdup_printf("%f", d); +			break; +		case PLIST_STRING: +			plist_get_string_val(value_node, &text); +			break; +		case PLIST_DATA: +			text = "FIXME: Parse Data"; +			break; +		case PLIST_DATE: +			text = "FIXME: Parse Dates"; +			break; +		case PLIST_ARRAY: +		case PLIST_DICT: +			text = g_strdup_printf("(%d items)", plist_node_get_item_count(value_node)); +			g_object_set(renderer, "sensitive", FALSE, NULL); +			break; +		default: +			break; +		} +		break; +	} + +	g_object_set(renderer, "text", text, NULL); +} + +void setup_tree_view(GtkBuilder *gtk_builder) { +	GtkTreeViewColumn *column; +	GtkCellRenderer *cell; + +	app.document_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(gtk_builder, "document_tree_view")); +	app.document_tree_store = GTK_TREE_STORE(gtk_builder_get_object(gtk_builder, "document_tree_store")); + +	/* key */ +	column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(gtk_builder, "treeviewcolumn1")); +	cell = GTK_CELL_RENDERER(gtk_builder_get_object(gtk_builder, "cellrenderertext1")); +	gtk_tree_view_column_set_cell_data_func(column, cell, plist_cell_data_function, GINT_TO_POINTER(COL_KEY), NULL); + +	/* type */ +	column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(gtk_builder, "treeviewcolumn2")); +	cell = GTK_CELL_RENDERER(gtk_builder_get_object(gtk_builder, "cellrenderercombo1")); +	gtk_tree_view_column_set_cell_data_func(column, cell, plist_cell_data_function, GINT_TO_POINTER(COL_TYPE), NULL); + +	/* value */ +	column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(gtk_builder, "treeviewcolumn3")); +	cell = GTK_CELL_RENDERER(gtk_builder_get_object(gtk_builder, "cellrenderertext2")); +	gtk_tree_view_column_set_cell_data_func(column, cell, plist_cell_data_function, GINT_TO_POINTER(COL_VALUE), NULL); +} + +int main(int argc, char **argv) { +	GtkBuilder *gtk_builder; + +	gtk_set_locale(); + +	/* Initialize the widget set */ +	gtk_init (&argc, &argv); + +	/* Create the main window */ +	gtk_builder = gtk_builder_new(); +	gtk_builder_add_from_file(gtk_builder, "gnome-plist-editor.ui", NULL); +	gtk_builder_connect_signals(gtk_builder, NULL); + +	app.main_window = GTK_WINDOW(gtk_builder_get_object(gtk_builder, "main_window")); +	setup_tree_view(gtk_builder); + +	g_object_unref(G_OBJECT(gtk_builder)); + +	/* Show the application window */ +	gtk_widget_show_all(GTK_WIDGET(app.main_window)); + +	/* Enter the main event loop, and wait for user interaction */ +	gtk_main (); + +	return 0; +} + diff --git a/src/gnome-plist-editor.ui b/src/gnome-plist-editor.ui new file mode 100644 index 0000000..e7e125d --- /dev/null +++ b/src/gnome-plist-editor.ui @@ -0,0 +1,353 @@ +<?xml version="1.0"?> +<interface> +  <requires lib="gtk+" version="2.16"/> +  <!-- interface-naming-policy project-wide --> +  <object class="GtkTreeStore" id="document_tree_store"> +    <columns> +      <!-- column-name node --> +      <column type="gpointer"/> +    </columns> +  </object> +  <object class="GtkListStore" id="plist_type_list_store"> +    <columns> +      <!-- column-name name --> +      <column type="gchararray"/> +    </columns> +    <data> +      <row> +        <col id="0" translatable="yes">Boolean</col> +      </row> +      <row> +        <col id="0" translatable="yes">Number</col> +      </row> +      <row> +        <col id="0" translatable="yes">Float</col> +      </row> +      <row> +        <col id="0" translatable="yes">String</col> +      </row> +      <row> +        <col id="0" translatable="yes">Array</col> +      </row> +      <row> +        <col id="0" translatable="yes">Dictionary</col> +      </row> +      <row> +        <col id="0" translatable="yes">Date</col> +      </row> +      <row> +        <col id="0" translatable="yes">Data</col> +      </row> +    </data> +  </object> +  <object class="GtkWindow" id="main_window"> +    <property name="title" translatable="yes">Property List Editor</property> +    <property name="window_position">center</property> +    <property name="default_width">450</property> +    <property name="default_height">350</property> +    <property name="icon_name">text-editor</property> +    <signal name="destroy" handler="main_window_destroy_cb"/> +    <child> +      <object class="GtkVBox" id="vbox1"> +        <property name="visible">True</property> +        <property name="orientation">vertical</property> +        <child> +          <object class="GtkMenuBar" id="menubar1"> +            <property name="visible">True</property> +            <child> +              <object class="GtkMenuItem" id="menuitem1"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">_File</property> +                <property name="use_underline">True</property> +                <child type="submenu"> +                  <object class="GtkMenu" id="menu1"> +                    <property name="visible">True</property> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem1"> +                        <property name="label">gtk-new</property> +                        <property name="visible">True</property> +                        <property name="sensitive">False</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="open_plist_menu_item"> +                        <property name="label">_Open...</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="image">image1</property> +                        <property name="use_stock">False</property> +                        <signal name="activate" handler="open_plist_cb"/> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem3"> +                        <property name="label">gtk-save</property> +                        <property name="visible">True</property> +                        <property name="sensitive">False</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem4"> +                        <property name="label">gtk-save-as</property> +                        <property name="visible">True</property> +                        <property name="sensitive">False</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkSeparatorMenuItem" id="separatormenuitem1"> +                        <property name="visible">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem5"> +                        <property name="label">gtk-quit</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                        <signal name="activate" handler="main_window_destroy_cb"/> +                      </object> +                    </child> +                  </object> +                </child> +              </object> +            </child> +            <child> +              <object class="GtkMenuItem" id="menuitem2"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">_Edit</property> +                <property name="use_underline">True</property> +                <child type="submenu"> +                  <object class="GtkMenu" id="menu2"> +                    <property name="visible">True</property> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem6"> +                        <property name="label">gtk-cut</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem7"> +                        <property name="label">gtk-copy</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem8"> +                        <property name="label">gtk-paste</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                    <child> +                      <object class="GtkImageMenuItem" id="imagemenuitem9"> +                        <property name="label">gtk-delete</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                      </object> +                    </child> +                  </object> +                </child> +              </object> +            </child> +            <child> +              <object class="GtkMenuItem" id="menuitem3"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">_View</property> +                <property name="use_underline">True</property> +              </object> +            </child> +            <child> +              <object class="GtkMenuItem" id="menuitem4"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">_Help</property> +                <property name="use_underline">True</property> +                <child type="submenu"> +                  <object class="GtkMenu" id="menu3"> +                    <property name="visible">True</property> +                    <child> +                      <object class="GtkImageMenuItem" id="about_menu_item"> +                        <property name="label">gtk-about</property> +                        <property name="visible">True</property> +                        <property name="use_underline">True</property> +                        <property name="use_stock">True</property> +                        <signal name="activate" handler="about_menu_item_activate_cb"/> +                      </object> +                    </child> +                  </object> +                </child> +              </object> +            </child> +          </object> +          <packing> +            <property name="expand">False</property> +            <property name="fill">False</property> +            <property name="position">0</property> +          </packing> +        </child> +        <child> +          <object class="GtkToolbar" id="toolbar1"> +            <property name="visible">True</property> +            <property name="toolbar_style">both</property> +            <child> +              <object class="GtkToolButton" id="new_plist_button"> +                <property name="visible">True</property> +                <property name="sensitive">False</property> +                <property name="label" translatable="yes">New</property> +                <property name="use_underline">True</property> +                <property name="stock_id">gtk-new</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +            <child> +              <object class="GtkToolButton" id="open_plist_button"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">Open...</property> +                <property name="use_underline">True</property> +                <property name="stock_id">gtk-open</property> +                <signal name="clicked" handler="open_plist_cb"/> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +            <child> +              <object class="GtkToolButton" id="save_plist_button"> +                <property name="visible">True</property> +                <property name="sensitive">False</property> +                <property name="label" translatable="yes">Save</property> +                <property name="use_underline">True</property> +                <property name="stock_id">gtk-save</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +            <child> +              <object class="GtkSeparatorToolItem" id="toolbutton1"> +                <property name="visible">True</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +            <child> +              <object class="GtkToolButton" id="add_sibling_button"> +                <property name="visible">True</property> +                <property name="sensitive">False</property> +                <property name="label" translatable="yes">Add Item</property> +                <property name="use_underline">True</property> +                <property name="icon_name">list-add</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +            <child> +              <object class="GtkToolButton" id="delete_item_button"> +                <property name="visible">True</property> +                <property name="sensitive">False</property> +                <property name="label" translatable="yes">Delete Item</property> +                <property name="use_underline">True</property> +                <property name="icon_name">list-remove</property> +              </object> +              <packing> +                <property name="expand">False</property> +                <property name="homogeneous">True</property> +              </packing> +            </child> +          </object> +          <packing> +            <property name="expand">False</property> +            <property name="fill">False</property> +            <property name="position">1</property> +          </packing> +        </child> +        <child> +          <object class="GtkScrolledWindow" id="scrolledwindow2"> +            <property name="visible">True</property> +            <property name="can_focus">True</property> +            <property name="hscrollbar_policy">never</property> +            <property name="vscrollbar_policy">automatic</property> +            <child> +              <object class="GtkTreeView" id="document_tree_view"> +                <property name="visible">True</property> +                <property name="can_focus">True</property> +                <property name="model">document_tree_store</property> +                <property name="headers_clickable">False</property> +                <property name="expander_column">treeviewcolumn1</property> +                <property name="rules_hint">True</property> +                <property name="search_column">8</property> +                <property name="enable_grid_lines">horizontal</property> +                <property name="tooltip_column">0</property> +                <child> +                  <object class="GtkTreeViewColumn" id="treeviewcolumn1"> +                    <property name="resizable">True</property> +                    <property name="min_width">150</property> +                    <property name="title">Key</property> +                    <child> +                      <object class="GtkCellRendererText" id="cellrenderertext1"/> +                    </child> +                  </object> +                </child> +                <child> +                  <object class="GtkTreeViewColumn" id="treeviewcolumn2"> +                    <property name="min_width">100</property> +                    <property name="title">Type</property> +                    <child> +                      <object class="GtkCellRendererCombo" id="cellrenderercombo1"> +                        <property name="editable">True</property> +                        <property name="model">plist_type_list_store</property> +                        <property name="text_column">0</property> +                      </object> +                      <attributes> +                        <attribute name="has-entry">0</attribute> +                      </attributes> +                    </child> +                  </object> +                </child> +                <child> +                  <object class="GtkTreeViewColumn" id="treeviewcolumn3"> +                    <property name="resizable">True</property> +                    <property name="title">Value</property> +                    <property name="expand">True</property> +                    <child> +                      <object class="GtkCellRendererText" id="cellrenderertext2"/> +                    </child> +                  </object> +                </child> +              </object> +            </child> +          </object> +          <packing> +            <property name="position">2</property> +          </packing> +        </child> +      </object> +    </child> +  </object> +  <object class="GtkImage" id="image1"> +    <property name="visible">True</property> +    <property name="stock">gtk-open</property> +    <property name="icon-size">1</property> +  </object> +  <object class="GtkTextBuffer" id="document_text_buffer"/> +</interface> diff --git a/src/plist-utils.c b/src/plist-utils.c new file mode 100644 index 0000000..fe63439 --- /dev/null +++ b/src/plist-utils.c @@ -0,0 +1,51 @@ +/* + * plist-utils.c + * + * Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com> + *  + * The code contained in this file is free software; you can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + *   + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *   + * You should have received a copy of the GNU Lesser General Public + * License along with this code; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + *  + */ + +#include <stdlib.h> + +#include "plist-utils.h" + +int plist_node_get_item_count(plist_t node) { +	plist_t child; +	plist_type type = PLIST_KEY; +	plist_type child_type; +	int count = 0; + +	type = plist_get_node_type(node); + +	child = plist_get_first_child(node); +	if (child == NULL) +		return count; + +	for(child; child != NULL; child = plist_get_next_sibling(child)) { +		if (type == PLIST_ARRAY) { +			child_type = plist_get_node_type(child); +			if ((child_type != PLIST_DICT) && (child_type != PLIST_ARRAY)) +				count++; +		} +		else if (plist_get_node_type(child) == PLIST_KEY) { +			count++; +		} +	} + +	return count; +} + diff --git a/src/plist-utils.h b/src/plist-utils.h new file mode 100644 index 0000000..0d55b14 --- /dev/null +++ b/src/plist-utils.h @@ -0,0 +1,29 @@ +/* + * plist-utils.h + * + * Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com> + *  + * The code contained in this file is free software; you can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + *   + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *   + * You should have received a copy of the GNU Lesser General Public + * License along with this code; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + *  + */ + +#ifndef _PLIST_UTILS_H +#define _PLIST_UTILS_H + +#include <plist/plist.h> + +int plist_node_get_item_count(plist_t node); + +#endif | 
