1 /* Dia -- a diagram creation/manipulation program
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * Property system for dia objects/shapes.
5  * Copyright (C) 2000 James Henstridge
6  * Copyright (C) 2001 Cyrille Chepelov
7  * Major restructuration done in August 2001 by C. Chepelov
8  *
9  * proplist.c: Property list handling routines.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include "properties.h"
31 #include "propinternals.h"
32 #include "dia_xml.h"
33 #include "diaerror.h"
34 
35 /* ------------------------------------------------------------------------- */
36 /* Construction of a list of properties from a filtered list of descriptors. */
37 /* This is a little halfway between properties and property descriptor       */
38 /* lists...                                                                  */
pdtpp_true(const PropDescription * pdesc)39 gboolean pdtpp_true(const PropDescription *pdesc)
40 { return TRUE; }
pdtpp_synthetic(const PropDescription * pdesc)41 gboolean pdtpp_synthetic(const PropDescription *pdesc)
42 { return TRUE; }
pdtpp_from_object(const PropDescription * pdesc)43 gboolean pdtpp_from_object(const PropDescription *pdesc)
44 { return TRUE; }
pdtpp_is_visible(const PropDescription * pdesc)45 gboolean pdtpp_is_visible(const PropDescription *pdesc)
46 { return (pdesc->flags & PROP_FLAG_VISIBLE) != 0; }
pdtpp_is_visible_no_standard(const PropDescription * pdesc)47 gboolean pdtpp_is_visible_no_standard(const PropDescription *pdesc)
48 { return (pdesc->flags & PROP_FLAG_VISIBLE) != 0 &&
49          (pdesc->flags & PROP_FLAG_STANDARD) == 0; }
pdtpp_is_not_visible(const PropDescription * pdesc)50 gboolean pdtpp_is_not_visible(const PropDescription *pdesc)
51 { return (pdesc->flags & PROP_FLAG_VISIBLE) == 0; }
pdtpp_do_save(const PropDescription * pdesc)52 gboolean pdtpp_do_save(const PropDescription *pdesc)
53 { return (pdesc->flags & (PROP_FLAG_DONT_SAVE|PROP_FLAG_LOAD_ONLY)) == 0; }
pdtpp_do_save_no_standard(const PropDescription * pdesc)54 gboolean pdtpp_do_save_no_standard(const PropDescription *pdesc)
55 { return (pdesc->flags & (PROP_FLAG_DONT_SAVE|PROP_FLAG_LOAD_ONLY|PROP_FLAG_STANDARD)) == 0; }
pdtpp_do_load(const PropDescription * pdesc)56 gboolean pdtpp_do_load(const PropDescription *pdesc)
57 { return (((pdesc->flags & PROP_FLAG_DONT_SAVE) == 0) ||
58             ((pdesc->flags & PROP_FLAG_LOAD_ONLY) != 0)); }
pdtpp_defaults(const PropDescription * pdesc)59 gboolean pdtpp_defaults(const PropDescription *pdesc)
60 { return (pdesc->flags & PROP_FLAG_NO_DEFAULTS) == 0; }
pdtpp_do_not_save(const PropDescription * pdesc)61 gboolean pdtpp_do_not_save(const PropDescription *pdesc)
62 { return (pdesc->flags & PROP_FLAG_DONT_SAVE) != 0; }
63 
64 GPtrArray *
prop_list_from_descs(const PropDescription * plist,PropDescToPropPredicate pred)65 prop_list_from_descs(const PropDescription *plist,
66                      PropDescToPropPredicate pred)
67 {
68   GPtrArray *ret;
69   guint count = 0, i;
70 
71   prop_desc_list_calculate_quarks((PropDescription *)plist);
72 
73   for (i = 0; plist[i].name != NULL; i++)
74     if (pred(&plist[i])) count++;
75 
76   ret = g_ptr_array_new();
77   g_ptr_array_set_size(ret,count);
78 
79   count = 0;
80   for (i = 0; plist[i].name != NULL; i++) {
81 #if 0
82       g_message("about to append property %s/%s to list"
83               "predicate is %s %d %d",plist[i].type,plist[i].name,
84               pred(&plist[i])?"TRUE":"FALSE",
85               plist[i].flags,plist[i].flags & PROP_FLAG_DONT_SAVE);
86 #endif
87     if (pred(&plist[i])) {
88       Property *prop = plist[i].ops->new_prop(&plist[i],pred);
89       g_ptr_array_index(ret,count++) = prop;
90     }
91   }
92 
93   return ret;
94 }
95 
96 void
prop_list_free(GPtrArray * plist)97 prop_list_free(GPtrArray *plist)
98 {
99   int i;
100   if (!plist) return;
101 
102   for (i = 0; i < plist->len; i++) {
103     Property *prop = g_ptr_array_index(plist,i);
104     prop->ops->free(prop);
105   }
106   g_ptr_array_free(plist,TRUE);
107 }
108 
109 /* copies the whole property structure, including the data. */
110 GPtrArray *
prop_list_copy(GPtrArray * src)111 prop_list_copy(GPtrArray *src)
112 {
113   int i;
114   GPtrArray *dest;
115 
116   dest = g_ptr_array_new();
117   g_ptr_array_set_size(dest, src->len);
118 
119   for (i=0; i < src->len; i++) {
120     Property *psrc = g_ptr_array_index(src,i);
121     Property *pdest = pdest = psrc->ops->copy(psrc);
122     g_ptr_array_index(dest,i) = pdest;
123   }
124   return dest;
125 }
126 
127 /* copies the whole property structure, excluding the data. */
128 GPtrArray *
prop_list_copy_empty(GPtrArray * plist)129 prop_list_copy_empty(GPtrArray *plist)
130 {
131   int i;
132   GPtrArray *dest;
133 
134   dest = g_ptr_array_new();
135   g_ptr_array_set_size(dest, plist->len);
136 
137   for (i=0; i < plist->len; i++) {
138     Property *psrc = g_ptr_array_index(plist,i);
139     Property *pdest = psrc->ops->new_prop(psrc->descr,psrc->reason);
140     g_ptr_array_index(dest,i) = pdest;
141   }
142   return dest;
143 }
144 
145 gboolean
prop_list_load(GPtrArray * props,DataNode data,GError ** err)146 prop_list_load(GPtrArray *props, DataNode data, GError **err)
147 {
148   int i;
149   gboolean ret = TRUE;
150 
151   for (i = 0; i < props->len; i++) {
152     Property *prop = g_ptr_array_index(props,i);
153     AttributeNode attr = object_find_attribute(data, prop->name);
154     DataNode data = attr ? attribute_first_data(attr) : NULL;
155     if ((!attr || !data) && prop->descr->flags & PROP_FLAG_OPTIONAL) {
156       prop->experience |= PXP_NOTSET;
157       continue;
158     }
159     if ((!attr) || (!data)) {
160       if (err && !*err)
161 	*err = g_error_new (DIA_ERROR,
162                             DIA_ERROR_FORMAT,
163 			    _("No attribute '%s' (%p) or no data(%p) in this attribute"),
164 			    prop->name,attr,data);
165       prop->experience |= PXP_NOTSET;
166       ret = FALSE;
167       continue;
168     }
169     prop->ops->load(prop,attr,data);
170   }
171   return ret;
172 }
173 
174 void
prop_list_save(GPtrArray * props,DataNode data)175 prop_list_save(GPtrArray *props, DataNode data)
176 {
177   int i;
178   for (i = 0; i < props->len; i++) {
179     Property *prop = g_ptr_array_index(props,i);
180     AttributeNode attr = new_attribute(data,prop->name);
181     prop->ops->save(prop,attr);
182   }
183 }
184 
185 Property *
find_prop_by_name(const GPtrArray * props,const gchar * name)186 find_prop_by_name(const GPtrArray *props, const gchar *name)
187 {
188   int i;
189   GQuark prop_quark = g_quark_from_string(name);
190 
191   for (i = 0; i < props->len; i++) {
192     Property *prop = g_ptr_array_index(props,i);
193     if (prop->name_quark == prop_quark) return prop;
194   }
195   return NULL;
196 }
197 
198 Property *
find_prop_by_name_and_type(const GPtrArray * props,const gchar * name,PropertyType type)199 find_prop_by_name_and_type(const GPtrArray *props, const gchar *name,
200                            PropertyType type)
201 {
202   Property *ret = find_prop_by_name(props,name);
203   GQuark type_quark = g_quark_from_string(type);
204   if (!ret) return NULL;
205   if (type_quark != ret->type_quark) return NULL;
206   return ret;
207 }
208 
209 void
prop_list_add_list(GPtrArray * props,const GPtrArray * ptoadd)210 prop_list_add_list (GPtrArray *props, const GPtrArray *ptoadd)
211 {
212   guint i;
213   for (i = 0 ; i < ptoadd->len; i++) {
214     Property *prop = g_ptr_array_index(ptoadd,i);
215 
216     g_ptr_array_add(props,prop->ops->copy(prop));
217   }
218 }
219 
220 GPtrArray *
prop_list_from_single(Property * prop)221 prop_list_from_single(Property *prop) {
222   GPtrArray *plist = g_ptr_array_new();
223   g_ptr_array_add(plist,prop);
224   return plist;
225 }
226