[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
klfpobj.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * file klfpobj.cpp
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist at bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id: klfpobj.cpp 991 2017-01-04 09:15:43Z phfaist $ */
23 
24 #include <QtDebug>
25 #include <QByteArray>
26 #include <QDataStream>
27 #include <QTextStream>
28 
29 #include "klfpobj.h"
30 
31 
33 {
34 }
36 {
37 }
38 
40 {
41 }
43 {
44 }
45 
46 
47 
48 // -----------------------------
49 
50 
52 {
54  QStringList pnames = propertyNameList();
55  foreach (QString pname, pnames) {
56  data[pname] = property(pname);
57  }
58  return data;
59 }
60 
62 {
64  klfDbg("data="<<data) ;
65  bool allok = true;
66  for (QVariantMap::const_iterator it = data.begin(); it != data.end(); ++it) {
67  bool ok = setProperty(it.key(), it.value());
68  if (!ok) {
69  allok = false;
70  qWarning()<<KLF_FUNC_NAME<<": Can't set property "<<it.key()<<" to "<<it.value();
71  }
72  }
73  return allok;
74 }
75 
76 
77 // --------
78 
80 {
81  return stream << e.specification() << qint32(e.value());
82 }
84 {
85  QByteArray s;
86  qint32 x;
87  stream >> s >> x;
88  e.setSpecification(s);
89  e.setValue(x);
90  return stream;
91 }
92 
93 
94 // -------
95 
96 
97 
98 
100  : pPropNameSpace(propNameSpace)
101 {
102  // ensure the property name space exists
103  if (!pRegisteredProperties.contains(propNameSpace))
104  pRegisteredProperties[propNameSpace] = QMap<QString,int>();
105  if (!pRegisteredPropertiesMaxId.contains(propNameSpace))
106  pRegisteredPropertiesMaxId[propNameSpace] = -1;
107 }
108 
110 {
111 }
112 
113 
115 {
116  int propId = propertyIdForName(propname);
117  if (propId < 0) {
118  qWarning("%s[%s](): Property `%s' not registered.", KLF_FUNC_NAME, qPrintable(pPropNameSpace),
119  qPrintable(propname));
120  return QVariant();
121  }
122  return property(propId);
123 }
125 {
126  if (propId >= 0 && propId < pProperties.size()) {
127  // all ok, return property (possibly an empty QVariant() if prop not set)
128  return pProperties[propId];
129  }
130  if (propId < 0) {
131  qWarning("%s[%s](%d): invalid property ID.", KLF_FUNC_NAME, qPrintable(pPropNameSpace),
132  propId);
133  return QVariant();
134  }
135  // property not set (or property not registered)
136  return QVariant();
137 }
138 
139 QVariant KLFPropertizedObject::property(const QString& propname, const QVariant& defaultValue) const
140 {
141  int propId = propertyIdForName(propname);
142  if (propId < 0) {
143  return defaultValue;
144  }
145  QVariant value = property(propId);
146  if (value.isValid())
147  return value;
148  return defaultValue;
149 }
150 
152 {
153  return property(propName, QVariant()).isValid();
154 }
155 
157 {
158  if (!propertyIdRegistered(propId))
159  return false;
160 
161  return hasPropertyValue(propertyNameForId(propId));
162 }
163 
164 
166  const QVariant& )
167 {
168  // do nothing. Subclasses may implement thier own behavior.
169 }
170 
171 bool KLFPropertizedObject::doSetProperty(const QString& propname, const QVariant& value)
172 {
173  if ( ! propertyNameRegistered(propname) ) {
174  qWarning("%s[%s](): Property `%s' not registered.", KLF_FUNC_NAME, qPrintable(pPropNameSpace),
175  qPrintable(propname));
176  return false;
177  }
178  return doSetProperty(propertyIdForName(propname), value);
179 }
181 {
182  if (propId >= 0 && propId < pProperties.size()) {
183  // all ok, set this property
184  QVariant oldvalue = pProperties[propId];
185  pProperties[propId] = value;
186  propertyValueChanged(propId, oldvalue, value);
187  return true;
188  }
189  if (propId < 0) {
190  qWarning("%s[%s](id=%d): invalid property ID.", KLF_FUNC_NAME, qPrintable(pPropNameSpace),
191  propId);
192  return false;
193  }
194  // maybe our properties array needs resize for properties that could have been
195  // registered after last access
196  int maxId = propertyMaxId();
197  if (propId <= maxId) {
198  pProperties.resize(maxId + 1);
199  }
200  if (propId < 0 || propId >= pProperties.size() ||
201  ! propertyIdRegistered(propId) ) {
202  qWarning("%s[%s](id=%d): invalid property id.", KLF_FUNC_NAME, qPrintable(pPropNameSpace),
203  propId);
204  return false;
205  }
206  QVariant oldvalue = pProperties[propId];
207  pProperties[propId] = value;
208  propertyValueChanged(propId, oldvalue, value);
209  return true;
210 }
211 int KLFPropertizedObject::doLoadProperty(const QString& propname, const QVariant& value)
212 {
213  klfDbg("propname="<<propname<<" value="<<value) ;
214  int propId = propertyIdForName(propname);
215  if ( propId < 0 ) {
216  // register property
217  propId = registerProperty(propname);
218  if (propId < 0)
219  return -1;
220  }
221  doSetProperty(propId, value);
222  return propId;
223 }
224 
226 {
227  QList<int> idList;
228  int k;
229  // walk vector and a fill a QList of all set properties' ID
230  for (k = 0; k < pProperties.size(); ++k) {
231  if (pProperties[k].isValid())
232  idList << k;
233  }
234  return idList;
235 }
236 
238 {
239  QStringList propSetList;
240  int k;
241  // walk vector and a fill a QStringList of all set properties.
242  for (k = 0; k < pProperties.size(); ++k) {
243  if (pProperties[k].isValid())
244  propSetList << propertyNameForId(k);
245  }
246  return propSetList;
247 }
248 
249 
250 
251 
253 {
254  QList<int> propertyList = propertyIdList();
255  QMap<QString,QVariant> properties;
256  int k;
257  // walk all properties and insert them into list
258  for (k = 0; k < propertyList.size(); ++k) {
259  properties[propertyNameForId(propertyList[k])] = property(propertyList[k]);
260  }
261  return properties;
262 }
263 
264 bool KLFPropertizedObject::setProperty(const QString& propname, const QVariant& value)
265 {
266  return doLoadProperty(propname, value) >= 0;
267 }
268 
270 {
271  KLF_ASSERT_CONDITION(propertyIdRegistered(propId), "Property ID="<<propId<<" is not registered!",
272  return false; ) ;
273 
274  return setProperty(propertyNameForId(propId), value);
275 }
276 
277 
279 {
281  klfDbg("propValues="<<propValues) ;
282 
283  bool allok = true;
284  QStringList propKeys = propValues.keys();
285  int k;
286  for (k = 0; k < propKeys.size(); ++k) {
287  // bypass check, set property anyway
288  bool ok = (doLoadProperty(propKeys[k], propValues[propKeys[k]]) >= 0);
289  if (!ok) {
290  allok = false;
291  qWarning()<<KLF_FUNC_NAME<<": Failed to load property "<<propKeys[k]<<" with value "<<propValues[propKeys[k]];
292  }
293  }
294  return allok;
295 }
296 
297 
299 {
300  QByteArray data;
301  {
302  QDataStream stream(&data, QIODevice::WriteOnly);
303  stream << *this;
304  // force close of buffer in destroying stream
305  }
306  return data;
307 }
308 
310 {
311  QDataStream stream(data);
312  stream >> *this;
313 }
314 
315 /*
316 QVariant KLFPropertizedObject::parsePropertyValue(int propId, const QString& strvalue)
317 {
318  KLF_ASSERT_CONDITION(propertyIdRegistered(propId), "Property ID="<<propId<<" is not registered!",
319  return QVariant(); ) ;
320 
321  return parsePropertyValue(propertyNameForId(propId), strvalue);
322 }
323 
324 QVariant KLFPropertizedObject::parsePropertyValue(const QString& / *propName* /, const QString& / *strvalue* /)
325 {
326  return QVariant();
327 }
328 */
329 
330 
331 
332 
333 
334 QString KLFPropertizedObject::toString(uint toStringFlags) const
335 {
336  QString s;
337 
338  int k;
339  QList<int> props;
340  bool html = (toStringFlags & ToStringUseHtml);
341  bool quote = (toStringFlags & ToStringQuoteValues);
342  bool allprops = (toStringFlags & ToStringAllProperties);
343  bool usehtmldiv = (toStringFlags & ToStringUseHtmlDiv);
344 
345  if (allprops)
346  props = registeredPropertyIdList();
347  else
348  props = propertyIdList();
349 
350  if (html) {
351  if (usehtmldiv) {
352  s = QString("<div class=\"klfpobj_entry\">\n<div class=\"klfpobj_name\">%2</div>\n")
353  .arg(pPropNameSpace.toHtmlEscaped());
354  } else {
355  s = QString("<table class=\"klfpobj_tentry\">\n"
356  "<tr colspan=\"2\" class=\"klfpobj_tname\"><th>%1</th></tr>\n")
357  .arg(pPropNameSpace.toHtmlEscaped());
358  }
359  } else {
360  s = QString("%1\n").arg(pPropNameSpace);
361  }
362 
363  for (k = 0; k < props.size(); ++k) {
364  QString pname = propertyNameForId(props[k]);
365  QVariant vval = property(props[k]);
366  bool isnull = !vval.isValid();
367  bool canstring = vval.canConvert(QVariant::String);
368  QString value = vval.toString();
369  if (html) {
370  if (usehtmldiv)
371  s += QString("<div class=\"klfpobj_prop_%1\"><div class=\"klfpobj_propname\">%2</div>: "
372  "<div class=\"klfpobj_propvalue\">%3</div></div>\n")
373  .arg(pname, pname, value.toHtmlEscaped());
374  else
375  s += QString(" <tr class=\"klfpobj_tprop_%1\"><td class=\"klfpobj_tpropname\">%2</td>"
376  "<td class=\"klfpobj_tpropvalue\">%3</td></tr>\n")
377  .arg(pname, pname, value.toHtmlEscaped());
378  } else {
379  if (quote) {
380  if (!isnull && canstring) {
381  value.replace("\\", "\\\\");
382  value.replace("\"", "\\\"");
383  value = '"' + value + '"';
384  } else if (!isnull) {
385  value = QString("[%1]").arg(vval.typeName());
386  } else {
387  // true null
388  value = "NULL";
389  }
390  }
391  s += QString("%1: %2\n").arg(propertyNameForId(props[k]), value);
392  }
393  }
394  s += "\n";
395  if (html) {
396  if (usehtmldiv) {
397  s += "</div>\n";
398  } else {
399  s += "</table>\n";
400  }
401  }
402 
403  return s;
404 }
405 
406 
407 
409 {
410  return propertyMaxId(pPropNameSpace);
411 }
413 {
414  return propertyIdRegistered(pPropNameSpace, propId);
415 }
417 {
418  return propertyNameRegistered(pPropNameSpace, propertyName);
419 }
421 {
422  return propertyIdForName(pPropNameSpace, propName);
423 }
425 {
426  return propertyNameForId(pPropNameSpace, id);
427 }
429 {
430  return registeredPropertyNameList(pPropNameSpace);
431 }
433 {
434  return registeredPropertyIdList(pPropNameSpace);
435 }
437 {
438  return registeredProperties(pPropNameSpace);
439 }
440 
441 // ---- PROTECTED ----
442 
444 {
445  registerBuiltInProperty(pPropNameSpace, propId, name);
446 }
448 {
449  return registerProperty(pPropNameSpace, propName);
450 }
451 
452 // ---- STATIC PROTECTED ----
453 
455  const QString& name)
456 {
457  internalRegisterProperty(pnamespace, name, propId);
458 }
459 int KLFPropertizedObject::registerProperty(const QString& propNameSpace, const QString& propName)
460 {
461  return internalRegisterProperty(propNameSpace, propName, -1);
462 }
464 {
465  if ( ! pRegisteredPropertiesMaxId.contains(propNameSpace) ) {
466  qWarning("%s(): property name space `%s' does not exist!", KLF_FUNC_NAME,
467  qPrintable(propNameSpace));
468  return -1;
469  }
470  return pRegisteredPropertiesMaxId[propNameSpace];
471 }
473 {
474  return ( ! propertyNameForId(propNameSpace, propId).isNull() ) ;
475 }
477  const QString& propertyName)
478 {
479  return (propertyIdForName(propNameSpace, propertyName) != -1) ;
480 }
481 int KLFPropertizedObject::propertyIdForName(const QString& propNameSpace, const QString& name)
482 {
483  if ( ! pRegisteredProperties.contains(propNameSpace) ) {
484  qWarning("%s: property name space `%s' does not exist!", KLF_FUNC_NAME,
485  qPrintable(propNameSpace));
486  return -1;
487  }
488  QMap<QString, int> propList = pRegisteredProperties[propNameSpace];
489  if ( ! propList.contains(name) )
490  return -1;
491  return propList.value(name);
492 }
494 {
495  if ( ! pRegisteredProperties.contains(propNameSpace) ) {
496  qWarning("%s: property name space `%s' does not exist!", KLF_FUNC_NAME,
497  qPrintable(propNameSpace));
498  return QString();
499  }
500  QMap<QString, int> propList = pRegisteredProperties[propNameSpace];
501  QList<QString> keyList = propList.keys(propId);
502  if (keyList.isEmpty())
503  return QString();
504  if (keyList.size() > 1) {
505  qWarning("%s: What's going on?? property Id=%d not unique in prop name space `%s'.",
506  KLF_FUNC_NAME, propId, qPrintable(propNameSpace));
507  }
508  return keyList[0];
509 }
511 {
512  if ( ! pRegisteredProperties.contains(propNameSpace) ) {
513  qWarning("%s: property name space `%s' does not exist!", KLF_FUNC_NAME,
514  qPrintable(propNameSpace));
515  return QStringList();
516  }
517 
518  return pRegisteredProperties[propNameSpace].keys();
519 }
521 {
522  if ( ! pRegisteredProperties.contains(propNameSpace) ) {
523  qWarning("%s: property name space `%s' does not exist!", KLF_FUNC_NAME,
524  qPrintable(propNameSpace));
525  return QList<int>();
526  }
527 
528  return pRegisteredProperties[propNameSpace].values();
529 }
530 
532 {
533  if ( ! pRegisteredProperties.contains(propNameSpace) ) {
534  qWarning("%s: property name space `%s' does not exist!", KLF_FUNC_NAME,
535  qPrintable(propNameSpace));
536  return QMap<QString, int>();
537  }
538  return pRegisteredProperties[propNameSpace];
539 }
540 
541 
542 // ---- PRIVATE ----
543 
544 QMap<QString, QMap<QString, int> > KLFPropertizedObject::pRegisteredProperties =
546 
547 QMap<QString, int> KLFPropertizedObject::pRegisteredPropertiesMaxId = QMap<QString,int>();
548 
549 
550 int KLFPropertizedObject::internalRegisterProperty(const QString& propNameSpace,
551  const QString& propName,
552  int propId)
553 {
555  klfDbg("propNameSpace = " << propNameSpace << ", propName = " << propName << ", propId = " << propId) ;
556 
557  const QMap<QString, int> propList = pRegisteredProperties[propNameSpace];
558  int propMaxId = -1;
559  if (pRegisteredPropertiesMaxId.contains(propNameSpace)) {
560  propMaxId = pRegisteredPropertiesMaxId[propNameSpace];
561  }
562  if (propId == -1) {
563  // propMaxId is maximum ID already used, so +1 gives a free ID.
564  propId = propMaxId + 1;
565  // and update propMaxId to account for the new propId...
566  propMaxId = propId;
567  } else {
568  // used the fixed propId. Update propMaxId if necessary.
569  if (propId > propMaxId) {
570  propMaxId = propId;
571  }
572  }
573  if ( propList.keys(propId).size() > 0 ) {
574  QString oldPropName = propList.keys(propId).at(0);
575  if (propName == oldPropName) {
576  return propId; // already registered, return that property ID
577  }
578  qWarning("%s[%s]: Property ID `%d' is already registered with conflicting names!\n"
579  "\told name is `%s', new is `%s'",
580  KLF_FUNC_NAME, qPrintable(propNameSpace), propId, qPrintable(oldPropName),
581  qPrintable(propName));
582  return -1;
583  }
584  // make sure property name is valid and unique
585  if (propName.isEmpty()) {
586  qWarning("%s[%s]: Cannot Register a property with empty name!", KLF_FUNC_NAME,
587  qPrintable(propNameSpace));
588  return -1;
589  }
590  if (propList.contains(propName)) {
591  qWarning("%s[%s]: Property `%s' already registered.", KLF_FUNC_NAME, qPrintable(propNameSpace),
592  qPrintable(propName));
593  return -1;
594  }
595  // name and ID are valid and unique.
596  // finally insert the property into list of known properties.
597  pRegisteredProperties[propNameSpace][propName] = propId;
598  // propMaxId was updated according to the new ID earlier in this function.
599  pRegisteredPropertiesMaxId[propNameSpace] = propMaxId;
600  return propId;
601 }
602 
603 
605 {
606  if (a.pPropNameSpace != b.pPropNameSpace)
607  return false;
608  QList<int> propIds = a.registeredPropertyIdList();
609  int k;
610  for (k = 0; k < propIds.size(); ++k)
611  if (a.property(propIds[k]) != b.property(propIds[k]))
612  return false;
613 
614  return true;
615 }
616 
617 
618 
620 {
621  stream << allProperties();
622  return stream;
623 }
625 {
627  stream >> props;
628  setAllProperties(props);
629  return stream;
630 }
632 {
633  return obj.streamInto(stream);
634 }
636 {
637  return obj.streamFrom(stream);
638 }
639 
640 
642 {
643  return stream << obj.toString();
644 }
645 
646 
647 
649 {
650  stream << obj.allProperties();
651  return stream;
652 }
653 
654 
655 
bool canConvert(int targetTypeId) const
virtual bool setAllProperties(const QMap< QString, QVariant > &propValues)
Initializes properties to given values.
Definition: klfpobj.cpp:278
virtual ~KLFPropertizedObject()
Definition: klfpobj.cpp:109
bool contains(const Key &key) const
KLF_EXPORT QDataStream & operator<<(QDataStream &stream, const KLFEnumType &e)
Definition: klfpobj.cpp:79
QList< T > values() const
Encapsulates output in an HTML <table> and escapes strings.
Definition: klfpobj.h:458
KLF_EXPORT QDataStream & operator>>(QDataStream &stream, KLFEnumType &e)
Definition: klfpobj.cpp:83
QStringList propertyNameList() const
A list of properties that have been set.
Definition: klfpobj.cpp:237
QStringList registeredPropertyNameList() const
See the corresponding protected static method.
Definition: klfpobj.cpp:428
QDataStream & streamFrom(QDataStream &stream)
Explicit function name for the simple "operator>>".
Definition: klfpobj.cpp:624
#define klfDbg(streamableItems)
print debug stream items
KLFPropertizedObject(const QString &propertyNameSpace)
Definition: klfpobj.cpp:99
#define KLF_DEBUG_BLOCK(msg)
Utility to debug the execution of a block.
void setAllPropertiesFromByteArray(const QByteArray &data)
Loads all properties saved by allPropertiesToByteArray()
Definition: klfpobj.cpp:309
void setValue(int v)
Definition: klfpobj.h:176
int value() const
Definition: klfpobj.h:172
QByteArray allPropertiesToByteArray() const
Saves all the properties in binary form.
Definition: klfpobj.cpp:298
virtual bool setProperty(const QString &pname, const QVariant &value)=0
Assign a value to a property.
void registerBuiltInProperty(int propId, const QString &propName) const
Definition: klfpobj.cpp:443
virtual QVariant property(const QString &propName) const
Definition: klfpobj.cpp:114
QDataStream & streamInto(QDataStream &stream) const
Explicit function name for the simple "operator<<".
Definition: klfpobj.cpp:619
virtual void propertyValueChanged(int propId, const QVariant &oldValue, const QVariant &newValue)
Definition: klfpobj.cpp:165
A class that holds properties.
Definition: klfpobj.h:277
virtual QMap< QString, QVariant > allProperties() const
Convenience function to retrieve all properties.
Definition: klfpobj.cpp:51
int size() const
QList< Key > keys() const
Ensures that non-html output is machine parsable.
Definition: klfpobj.h:460
QMap< QString, QVariant > allProperties() const
Returns all properties that have been set.
Definition: klfpobj.cpp:252
friend bool operator==(const KLFPropertizedObject &a, const KLFPropertizedObject &b)
Definition: klfpobj.cpp:604
void resize(int size)
#define KLF_EXPORT
Definition: klfdefs.h:41
virtual QStringList propertyNameList() const =0
Queries what property are (or can be) set.
virtual QVariant property(const QString &propName) const =0
get a property&#39;s value
virtual ~KLFSpecifyableType()
Definition: klfpobj.cpp:42
QList< int > propertyIdList() const
A list of properties that have been set.
Definition: klfpobj.cpp:225
bool isEmpty() const
int registerProperty(const QString &propertyName) const
Definition: klfpobj.cpp:447
bool isEmpty() const
virtual bool setProperty(const QString &propname, const QVariant &value)
Sets the given property to the given value.
Definition: klfpobj.cpp:264
iterator end()
virtual bool doSetProperty(const QString &propname, const QVariant &value)
Definition: klfpobj.cpp:171
iterator begin()
QString propertyNameForId(int propId) const
See the corresponding protected static method.
Definition: klfpobj.cpp:424
QList< int > registeredPropertyIdList() const
See the corresponding protected static method.
Definition: klfpobj.cpp:432
QString toHtmlEscaped() const
#define KLF_FUNC_NAME
virtual bool hasPropertyValue(const QString &propName) const
Tests if a property was set.
Definition: klfpobj.cpp:151
bool propertyNameRegistered(const QString &propertyName) const
See the corresponding protected static method.
Definition: klfpobj.cpp:416
QString & replace(int position, int n, QChar after)
virtual int doLoadProperty(const QString &propname, const QVariant &value)
Definition: klfpobj.cpp:211
int propertyMaxId() const
See the corresponding protected static method.
Definition: klfpobj.cpp:408
const char * typeName() const
bool isValid() const
bool setSpecification(const QByteArray &data)
Definition: klfpobj.h:205
virtual bool setAllProperties(const QMap< QString, QVariant > &data)
Convenience function to load a set of property values.
Definition: klfpobj.cpp:61
int propertyIdForName(const QString &propertyName) const
See the corresponding protected static method.
Definition: klfpobj.cpp:420
#define KLF_ASSERT_CONDITION(expr, msg, failaction)
Asserting Conditions (NON-FATAL)
QMap< QString, int > registeredProperties() const
See the corresponding protected static method.
Definition: klfpobj.cpp:436
Include also all non-explicitely-set properties.
Definition: klfpobj.h:461
virtual QString toString(uint toStringFlags=0) const
Formats the property contents in a (human and/or parsable) string.
Definition: klfpobj.cpp:334
virtual ~KLFAbstractPropertizedObject()
Definition: klfpobj.cpp:35
int size() const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
QString toString() const
int propId
Definition: klfdatautil.cpp:96
bool propertyIdRegistered(int propId) const
See the corresponding protected static method.
Definition: klfpobj.cpp:412
Uses <div> with CSS classes instead of a table (HTML only)
Definition: klfpobj.h:459
QByteArray specification() const
Definition: klfpobj.h:200
const T value(const Key &key, const T &defaultValue) const

Generated by doxygen 1.8.13