1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Damien
3 	CALISTE, laboratoire L_Sim, (2016)
4 
5 	Adresse mèl :
6 	CALISTE, damien P caliste AT cea P fr.
7 
8 	Ce logiciel est un programme informatique servant à visualiser des
9 	structures atomiques dans un rendu pseudo-3D.
10 
11 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
12 	respectant les principes de diffusion des logiciels libres. Vous pouvez
13 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
14 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
15 	sur le site "http://www.cecill.info".
16 
17 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
18 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
19 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
20 */
21 
22 /*   LICENCE SUM UP
23 	Copyright CEA, contributors : Damien
24 	CALISTE, laboratoire L_Sim, (2016)
25 
26 	E-mail address:
27 	CALISTE, damien P caliste AT cea P fr.
28 
29 	This software is a computer program whose purpose is to visualize atomic
30 	configurations in 3D.
31 
32 	This software is governed by the CeCILL  license under French law and
33 	abiding by the rules of distribution of free software.  You can  use,
34 	modify and/ or redistribute the software under the terms of the CeCILL
35 	license as circulated by CEA, CNRS and INRIA at the following URL
36 	"http://www.cecill.info".
37 
38 	The fact that you are presently reading this means that you have had
39 	knowledge of the CeCILL license and that you accept its terms. You can
40 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
41 */
42 
43 #include "visu_dataatomic.h"
44 
45 #include "visu_basic.h"
46 
47 #include "loaders/atomic_ascii.h"
48 #include "loaders/atomic_d3.h"
49 #include "loaders/atomic_xyz.h"
50 #include "loaders/atomic_yaml.h"
51 
52 /**
53  * SECTION: visu_dataatomic
54  * @short_description: a class of nodes representing atomic data and
55  * providing associated loading methods.
56  *
57  * <para>This class provides #VisuDataLoader for atomic data representation.</para>
58  */
59 
60 enum
61   {
62     PROP_0,
63     PROP_FILE,
64     PROP_FORMAT,
65     N_PROP,
66     PROP_LABEL
67   };
68 static GParamSpec *_properties[N_PROP];
69 
70 struct _VisuDataAtomicPrivate
71 {
72   gchar *file;
73   VisuDataLoader *format;
74 };
75 
76 static GList *_atomicFormats = NULL;
_initAtomicFormats(void)77 static void _initAtomicFormats(void)
78 {
79   visu_data_atomic_class_addLoader(visu_data_loader_ascii_getStatic());
80   visu_data_atomic_class_addLoader(visu_data_loader_d3_getStatic());
81   visu_data_atomic_class_addLoader(visu_data_loader_xyz_getStatic());
82   if (visu_data_loader_yaml_getStatic())
83     visu_data_atomic_class_addLoader(visu_data_loader_yaml_getStatic());
84 }
85 
86 static void visu_data_atomic_finalize    (GObject* obj);
87 static void visu_data_atomic_get_property(GObject* obj, guint property_id,
88                                           GValue *value, GParamSpec *pspec);
89 static void visu_data_atomic_set_property(GObject* obj, guint property_id,
90                                           const GValue *value, GParamSpec *pspec);
91 static gboolean visu_data_atomic_load(VisuDataLoadable *self, guint iSet,
92                                       GCancellable *cancel, GError **error);
93 static const gchar* visu_data_atomic_getFilename(const VisuDataLoadable *self,
94                                                  guint fileType);
95 
G_DEFINE_TYPE_WITH_CODE(VisuDataAtomic,visu_data_atomic,VISU_TYPE_DATA_LOADABLE,G_ADD_PRIVATE (VisuDataAtomic))96 G_DEFINE_TYPE_WITH_CODE(VisuDataAtomic, visu_data_atomic, VISU_TYPE_DATA_LOADABLE,
97                         G_ADD_PRIVATE(VisuDataAtomic))
98 
99 static void visu_data_atomic_class_init(VisuDataAtomicClass *klass)
100 {
101   /* Connect the overloading methods. */
102   G_OBJECT_CLASS(klass)->finalize     = visu_data_atomic_finalize;
103   G_OBJECT_CLASS(klass)->get_property = visu_data_atomic_get_property;
104   G_OBJECT_CLASS(klass)->set_property = visu_data_atomic_set_property;
105   VISU_DATA_LOADABLE_CLASS(klass)->load = visu_data_atomic_load;
106   VISU_DATA_LOADABLE_CLASS(klass)->getFilename = visu_data_atomic_getFilename;
107 
108   g_object_class_override_property(G_OBJECT_CLASS(klass), PROP_LABEL, "label");
109 
110   /**
111    * VisuDataAtomic::atomic-filename:
112    *
113    * The path to the source filename.
114    *
115    * Since: 3.8
116    */
117   _properties[PROP_FILE] =
118     g_param_spec_string("atomic-filename", "Atomic filename", "source filename",
119                         (gchar*)0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
120   /**
121    * VisuDataAtomic::atomic-format:
122    *
123    * The format of the source filename, if known.
124    *
125    * Since: 3.8
126    */
127   _properties[PROP_FORMAT] =
128     g_param_spec_object("atomic-format", "Atomic format", "source format",
129                         VISU_TYPE_DATA_LOADER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
130   g_object_class_install_properties(G_OBJECT_CLASS(klass), N_PROP, _properties);
131 
132   _initAtomicFormats();
133 }
visu_data_atomic_init(VisuDataAtomic * obj)134 static void visu_data_atomic_init(VisuDataAtomic *obj)
135 {
136   obj->priv = visu_data_atomic_get_instance_private(obj);
137 
138   /* Private data. */
139   obj->priv->file    = (gchar*)0;
140   obj->priv->format  = (VisuDataLoader*)0;
141 }
visu_data_atomic_finalize(GObject * obj)142 static void visu_data_atomic_finalize(GObject* obj)
143 {
144   VisuDataAtomic *data;
145 
146   data = VISU_DATA_ATOMIC(obj);
147 
148   g_free(data->priv->file);
149 
150   /* Chain up to the parent class */
151   G_OBJECT_CLASS(visu_data_atomic_parent_class)->finalize(obj);
152 }
visu_data_atomic_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)153 static void visu_data_atomic_get_property(GObject* obj, guint property_id,
154                                           GValue *value, GParamSpec *pspec)
155 {
156   VisuDataAtomic *self = VISU_DATA_ATOMIC(obj);
157 
158   switch (property_id)
159     {
160     case PROP_LABEL:
161       g_value_take_string(value, g_path_get_basename(self->priv->file));
162       break;
163     case PROP_FILE:
164       g_value_set_string(value, self->priv->file);
165       break;
166     case PROP_FORMAT:
167       g_value_set_object(value, self->priv->format);
168       break;
169     default:
170       /* We don't have any other property... */
171       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
172       break;
173     }
174 }
visu_data_atomic_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)175 static void visu_data_atomic_set_property(GObject* obj, guint property_id,
176                                           const GValue *value, GParamSpec *pspec)
177 {
178   VisuDataAtomic *self = VISU_DATA_ATOMIC(obj);
179 
180   switch (property_id)
181     {
182     case PROP_FILE:
183       self->priv->file = tool_path_normalize(g_value_get_string(value));
184       break;
185     case PROP_FORMAT:
186       self->priv->format = g_value_get_object(value);
187       break;
188     default:
189       /* We don't have any other property... */
190       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
191       break;
192     }
193 }
194 
195 /**
196  * visu_data_atomic_new:
197  * @file: a filename.
198  * @format: (allow-none): a #VisuDataLoader format, if known.
199  *
200  * Creates a #VisuDataAtomic object and set @file to it.
201  *
202  * Since: 3.8
203  *
204  * Returns: a newly allocated #VisuDataAtomic object.
205  **/
visu_data_atomic_new(const gchar * file,VisuDataLoader * format)206 VisuDataAtomic* visu_data_atomic_new(const gchar *file, VisuDataLoader *format)
207 {
208   return g_object_new(VISU_TYPE_DATA_ATOMIC, "n-files", 1,
209                       "atomic-filename", file, "atomic-format", format, NULL);
210 }
211 
212 /**
213  * visu_data_atomic_class_addLoader:
214  * @loader: (transfer full): a #VisuDataLoader object.
215  *
216  * Add @loader to the list of #VisuDataLoader to be used when
217  * visu_data_loadable_load() is called.
218  *
219  * Since: 3.8
220  **/
visu_data_atomic_class_addLoader(VisuDataLoader * loader)221 void visu_data_atomic_class_addLoader(VisuDataLoader *loader)
222 {
223   if (g_list_find(_atomicFormats, loader))
224     return;
225 
226   g_return_if_fail(VISU_IS_DATA_LOADER(loader));
227   DBG_fprintf(stderr, "Data Atomic: adding a new loader '%s'.\n",
228               tool_file_format_getName(TOOL_FILE_FORMAT(loader)));
229   tool_file_format_setPropertiesFromCLI(TOOL_FILE_FORMAT(loader));
230   _atomicFormats = g_list_prepend(_atomicFormats, loader);
231   _atomicFormats = g_list_sort(_atomicFormats,
232                                (GCompareFunc)visu_data_loader_comparePriority);
233 }
234 
235 /**
236  * visu_data_atomic_class_getLoaders:
237  *
238  * Returns a list of available #VisuDataLoader.
239  *
240  * Since: 3.8
241  *
242  * Returns: (transfer none) (element-type VisuDataLoader): a list of
243  * #VisuDataLoader owned by V_Sim.
244  **/
visu_data_atomic_class_getLoaders(void)245 GList* visu_data_atomic_class_getLoaders(void)
246 {
247   return _atomicFormats;
248 }
249 /**
250  * visu_data_atomic_class_getFileDescription:
251  *
252  * Returns a translated string describing what is files loaded by
253  * #VisuDataAtomic objects.
254  *
255  * Since: 3.8
256  *
257  * Returns: a string owned by V_Sim.
258  **/
visu_data_atomic_class_getFileDescription(void)259 const gchar* visu_data_atomic_class_getFileDescription(void)
260 {
261   return _("Position files");
262 }
263 /**
264  * visu_data_atomic_class_finalize:
265  *
266  * Empty the list of known loaders.
267  *
268  * Since: 3.8
269  **/
visu_data_atomic_class_finalize(void)270 void visu_data_atomic_class_finalize(void)
271 {
272   g_list_free_full(_atomicFormats, (GDestroyNotify)g_object_unref);
273   _atomicFormats = (GList*)0;
274 }
275 
276 /**
277  * visu_data_atomic_getFile:
278  * @data: a #VisuDataAtomic object.
279  * @format: (out caller-allocates): a location to store a
280  * #VisuDataLoader object.
281  *
282  * Returns the file defined in @data and its associated @format, if any.
283  *
284  * Since: 3.8
285  *
286  * Returns: a string owned by V_Sim.
287  **/
visu_data_atomic_getFile(VisuDataAtomic * data,VisuDataLoader ** format)288 const gchar* visu_data_atomic_getFile(VisuDataAtomic *data, VisuDataLoader **format)
289 {
290   g_return_val_if_fail(VISU_IS_DATA_ATOMIC(data), (const gchar*)0);
291 
292   if (format)
293     *format = data->priv->format;
294   return data->priv->file;
295 }
visu_data_atomic_getFilename(const VisuDataLoadable * self,guint fileType)296 static const gchar* visu_data_atomic_getFilename(const VisuDataLoadable *self,
297                                                  guint fileType)
298 {
299   g_return_val_if_fail(fileType == 0, (const gchar*)0);
300 
301   return visu_data_atomic_getFile(VISU_DATA_ATOMIC(self), (VisuDataLoader**)0);
302 }
303 
_finalize(VisuDataAtomic * data,VisuDataLoader * loader)304 static gboolean _finalize(VisuDataAtomic *data, VisuDataLoader *loader)
305 {
306   VisuNodeArrayIter iter;
307   ToolUnits unit, preferedUnit;
308   VisuBox *box;
309 
310   /* We do a last check on population... in case. */
311   visu_node_array_iter_new(VISU_NODE_ARRAY(data), &iter);
312   g_return_val_if_fail(iter.nAllStoredNodes, FALSE);
313   DBG_fprintf(stderr, "Data Atomic: loading OK (%d nodes).\n", iter.nAllStoredNodes);
314 
315   /* Setup additional infos. */
316   box = visu_boxed_getBox(VISU_BOXED(data));
317   unit = visu_box_getUnit(box);
318   preferedUnit = visu_basic_getPreferedUnit();
319   if (preferedUnit != TOOL_UNITS_UNDEFINED &&
320       unit != TOOL_UNITS_UNDEFINED &&
321       unit != preferedUnit)
322     visu_box_setUnit(box, preferedUnit);
323 
324   visu_node_array_completeAdding(VISU_NODE_ARRAY(data));
325 
326   data->priv->format = loader;
327 
328   return TRUE;
329 }
330 
_abort(VisuDataAtomic * data)331 static gboolean _abort(VisuDataAtomic *data)
332 {
333   visu_node_array_completeAdding(VISU_NODE_ARRAY(data));
334 
335   return FALSE;
336 }
337 
visu_data_atomic_load(VisuDataLoadable * self,guint iSet,GCancellable * cancel,GError ** error)338 static gboolean visu_data_atomic_load(VisuDataLoadable *self, guint iSet,
339                                       GCancellable *cancel, GError **error)
340 {
341   VisuDataAtomic *data;
342   GList *lst;
343   VisuDataLoader *loader;
344 
345   g_return_val_if_fail(VISU_IS_DATA_ATOMIC(self), FALSE);
346 
347   data = VISU_DATA_ATOMIC(self);
348 
349   if (!visu_data_loadable_checkFile(self, 0, error))
350     return FALSE;
351 
352   visu_node_array_startAdding(VISU_NODE_ARRAY(self));
353   for (lst = _atomicFormats; lst; lst = g_list_next(lst))
354     {
355       loader = VISU_DATA_LOADER(lst->data);
356 
357       /* Each load may set error even if the format is not recognise
358 	 and loadOK is FALSE, then we need to free the error. */
359       g_clear_error(error);
360 
361       if (!data->priv->format || loader == data->priv->format)
362 	{
363 	  DBG_fprintf(stderr,"Data Atomic: testing '%s' with format: %s.\n",
364 		      data->priv->file, tool_file_format_getName(TOOL_FILE_FORMAT(loader)));
365 	  if (visu_data_loader_load(loader, self, 0, iSet, cancel, error))
366             return (*error) ? _abort(data) : _finalize(data, loader);
367           if (*error && (*error)->domain == G_FILE_ERROR)
368             return _abort(data);
369           if (*error && data->priv->format)
370             return _abort(data);
371         }
372     }
373   g_clear_error(error);
374   g_set_error(error, VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_UNKNOWN,
375               _("Impossible to load '%s', unrecognised format.\n"), data->priv->file);
376   return _abort(data);
377 }
378 
379 /**
380  * visu_data_atomic_loadAt:
381  * @data: a #VisuDataAtomic object.
382  * @filename: a filename.
383  * @iSet: an id.
384  * @cancel: a #GCancellable object.
385  * @error: an error location.
386  *
387  * Specific routine to load an atomic file that is not stored in the
388  * location declared at construction. This is only used for archive plug-in.
389  *
390  * Since: 3.8
391  *
392  * Returns: TRUE on success.
393  **/
visu_data_atomic_loadAt(VisuDataAtomic * data,const gchar * filename,guint iSet,GCancellable * cancel,GError ** error)394 gboolean visu_data_atomic_loadAt(VisuDataAtomic *data, const gchar *filename, guint iSet, GCancellable *cancel, GError **error)
395 {
396   gchar *old;
397   gboolean res;
398 
399   g_return_val_if_fail(VISU_IS_DATA_ATOMIC(data), FALSE);
400   old = data->priv->file;
401   data->priv->file = (gchar*)filename;
402   res = visu_data_atomic_load(VISU_DATA_LOADABLE(data), iSet, cancel, error);
403   data->priv->file = old;
404   return res;
405 }
406 
407 /**
408  * visu_data_atomic_getForces:
409  * @dataObj: a #VisuDataAtomic object.
410  * @create: a boolean.
411  *
412  * Retrieves the #VisuNodeValuesVector used to store forces for
413  * @dataObj, create it depending on @create if not exists.
414  *
415  * Since: 3.8
416  *
417  * Returns: (transfer none): a #VisuNodeValuesVector object, owned by V_Sim.
418  **/
visu_data_atomic_getForces(VisuDataAtomic * dataObj,gboolean create)419 VisuNodeValuesVector* visu_data_atomic_getForces(VisuDataAtomic *dataObj,
420                                                  gboolean create)
421 {
422   VisuNodeValuesVector *vect;
423 
424   if (!dataObj)
425     return (VisuNodeValuesVector*)0;
426 
427   vect = (VisuNodeValuesVector*)visu_data_getNodeProperties(VISU_DATA(dataObj),
428                                                             _("Forces"));
429   if (!vect && create)
430     {
431       vect = visu_node_values_vector_new(VISU_NODE_ARRAY(dataObj),
432                                          _("Forces"));
433       visu_node_values_setEditable(VISU_NODE_VALUES(vect), FALSE);
434       visu_data_addNodeProperties(VISU_DATA(dataObj), VISU_NODE_VALUES(vect));
435     }
436   return vect;
437 }
438