ArnLib  4.0.x
Active Registry Network
ArnBasicItem.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2022 Michael Wiklund.
2 // All rights reserved.
3 // Contact: arnlib@wiklunden.se
4 //
5 // This file is part of the ArnLib - Active Registry Network.
6 // Parts of ArnLib depend on Qt and/or other libraries that have their own
7 // licenses. Usage of these other libraries is subject to their respective
8 // license agreements.
9 //
10 // GNU Lesser General Public License Usage
11 // This file may be used under the terms of the GNU Lesser General Public
12 // License version 2.1 as published by the Free Software Foundation and
13 // appearing in the file LICENSE_LGPL.txt included in the packaging of this
14 // file. In addition, as a special exception, you may use the rights described
15 // in the Nokia Qt LGPL Exception version 1.1, included in the file
16 // LGPL_EXCEPTION.txt in this package.
17 //
18 // GNU General Public License Usage
19 // Alternatively, this file may be used under the terms of the GNU General Public
20 // License version 3.0 as published by the Free Software Foundation and appearing
21 // in the file LICENSE_GPL.txt included in the packaging of this file.
22 //
23 // Other Usage
24 // Alternatively, this file may be used in accordance with the terms and conditions
25 // contained in a signed written agreement between you and Michael Wiklund.
26 //
27 // This program is distributed in the hope that it will be useful, but WITHOUT ANY
28 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
29 // PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
30 //
31 
32 #include "ArnInc/ArnBasicItem.hpp"
33 #include "private/ArnBasicItem_p.hpp"
34 #include "ArnInc/ArnM.hpp"
35 #include "ArnInc/ArnEvent.hpp"
36 #include "ArnInc/ArnLib.hpp"
37 #include "ArnLink.hpp"
38 #include <QDataStream>
39 #include <QThreadStorage>
40 #include <QCoreApplication>
41 #include <QThread>
42 #include <QDebug>
43 
44 
45 QAtomicInt ArnBasicItemPrivate::_idCount(1);
46 
47 
48 ArnBasicItemPrivate::ArnBasicItemPrivate()
49 {
50  _reference = arnNullptr;
51  _eventHandler = arnNullptr;
52  _pendingEvChain = arnNullptr;
53  _id = quint32(_idCount.fetchAndAddRelaxed(1));
54 
55  _useUncrossed = false;
56  _isStdEvHandler = true;
57  _isAssigning = false;
58  _ignoreSameValue = ArnM::defaultIgnoreSameValue();
59  _isOnlyEcho = true; // Nothing else yet ...
60 
61  _syncMode = quint8( Arn::ObjectSyncMode());
62  _mode = quint8( Arn::ObjectMode());
63  _heritage = ArnCoreItem::Heritage::None;
64  _syncModeLinkShare = true;
65 }
66 
67 
68 ArnBasicItemPrivate::~ArnBasicItemPrivate()
69 {
70 }
71 
72 
73 ArnBasicItemPrivate& ArnBasicItemPrivate::addHeritage( ArnCoreItem::Heritage heritage)
74 {
75  _heritage |= heritage;
76  return *this;
77 }
78 
79 
80 
81 
82 void ArnBasicItem::init()
83 {
84  Q_D(ArnBasicItem);
85 
86  _link = arnNullptr;
87  d->_eventHandler = getThreadEventHandler(); // The common event handler for this thread
89 }
90 
91 
93  : ArnCoreItem( *new ArnBasicItemPrivate)
94 {
95  init();
96 }
97 
98 
99 ArnBasicItem::ArnBasicItem( ArnBasicItemPrivate& dd)
100  : ArnCoreItem( dd)
101 {
102  init();
103 }
104 
105 
107 {
108  close();
109 }
110 
111 
112 void ArnBasicItem::setupOpenItem( bool isFolder)
113 {
114  Q_UNUSED(isFolder)
115  Q_D(ArnBasicItem);
116 
117  addMode( Arn::ObjectMode::fromInt( d->_mode)); // Transfer modes to the link
118 }
119 
120 
121 bool ArnBasicItem::openWithFlags( const QString& path, Arn::LinkFlags linkFlags)
122 {
123  Q_D(ArnBasicItem);
124 
125  if (_link)
126  close();
127 
128  Arn::ObjectSyncMode syncMode = d->_syncModeLinkShare ? Arn::ObjectSyncMode::fromInt( d->_syncMode)
129  : Arn::ObjectSyncMode();
130  _link = ArnM::link( path, linkFlags, syncMode);
131  if (!_link) return false;
132 
133  ArnEvRefChange ev(+1);
134  sendArnEventLink( &ev);
135  ArnM::changeRefCounter(+1);
136 
137  _link->subscribe( this);
138  setupOpenItem( _link->isFolder());
139 #ifdef ArnBasicItem_INCPATH
140  d->_path = path;
141 #endif
142 
143  return true;
144 }
145 
146 
147 bool ArnBasicItem::open( const QString& path)
148 {
149  return openWithFlags( path, Arn::LinkFlags::CreateAllowed);
150 }
151 
152 
154 {
155  Q_D(ArnBasicItem);
156 
157  if (!_link) return;
158 
159  _link->unsubscribe( this);
160  // Now this item will not get ArnEvent updates in its
161 
162  ArnEvRefChange ev(-1);
163  sendArnEventLink( &ev);
164  ArnM::changeRefCounter(-1);
165 
166  if (d->_pendingEvChain) {
167  d->_pendingEvChain->setTargetMutex( arnNullptr); // No mutex needed anymore
168  d->_pendingEvChain->inhibitPendingChain();
169  }
170 
171  _link->deref();
172  _link = arnNullptr;
173  d->_syncMode = Arn::ObjectSyncMode();
174  d->_mode = Arn::ObjectMode();
175 }
176 
177 
178 void ArnBasicItem::destroyLink( bool isGlobal)
179 {
180  ArnM::destroyLink( _link, isGlobal);
181 }
182 
183 
185 {
186  return _link != arnNullptr;
187 }
188 
189 
191 {
192  if (!_link) return false;
193 
194  return _link->isFolder();
195 }
196 
197 
199 {
200  if (!_link) return false;
201 
202  return _link->isProvider();
203 }
204 
205 
207 {
208  if (!_link) return Arn::DataType::Null;
209 
210  return _link->type();
211 }
212 
213 
215 {
216  if (!_link) return 0;
217 
218  return _link->linkId();
219 }
220 
221 
223 {
224  if (!_link) return -1;
225 
226  return qMax( _link->refCount(), 0);
227 }
228 
229 
230 void ArnBasicItem::addSyncMode( Arn::ObjectSyncMode syncMode, bool linkShare)
231 {
232  Q_D(ArnBasicItem);
233 
234  d->_syncModeLinkShare = linkShare;
235  d->_syncMode |= syncMode;
236  if (d->_syncModeLinkShare && _link) {
237  _link->addSyncMode( Arn::ObjectSyncMode::fromInt( d->_syncMode));
238  }
239 }
240 
241 
242 void ArnBasicItem::resetOnlyEcho()
243 {
244  Q_D(ArnBasicItem);
245 
246  d->_isOnlyEcho = true;
247 }
248 
249 
250 void ArnBasicItem::addIsOnlyEcho( quint32 sendId)
251 {
252  Q_D(ArnBasicItem);
253 
254  if (sendId != d->_id) // Originate from different Item, not an echo
255  d->_isOnlyEcho = false;
256 }
257 
258 
259 bool ArnBasicItem::isOnlyEcho() const
260 {
261  Q_D(const ArnBasicItem);
262 
263  return d->_isOnlyEcho;
264 }
265 
266 
267 quint32 ArnBasicItem::localUpdateCount() const
268 {
269  if (!_link) return 0;
270 
271  return _link->localUpdateCount();
272 }
273 
274 
275 uint ArnBasicItem::retireType()
276 {
277  return _link ? _link->retireType() : uint( ArnLink::RetireType::None);
278 }
279 
280 
282 {
283  Q_D(const ArnBasicItem);
284 
285  if (d->_syncModeLinkShare && _link) {
286  return _link->syncMode();
287  }
288  return Arn::ObjectSyncMode::fromInt( d->_syncMode);
289 }
290 
291 
293 {
294  Q_D(ArnBasicItem);
295 
296  d->_mode |= Arn::ObjectMode::BiDir;
297  if (!_link) return *this;
298 
299  if (_link->isBiDirMode()) return *this; // Already is bidirectional mode
300 
302  ArnLink* twinLink = ArnM::addTwin( _link->linkPath(), _link, syncMode());
303  twinLink->deref();
304 
305  return *this;
306 }
307 
308 
310 {
311  Q_D(const ArnBasicItem);
312 
313  if (!_link) return d->mode().is( Arn::ObjectMode::BiDir);
314 
315  return _link->isBiDirMode();
316 }
317 
318 
320 {
321  Q_D(ArnBasicItem);
322 
324  d->_ignoreSameValue = false;
325  if (!_link) return *this;
326 
327  if (_link->isPipeMode()) return *this; // Already is pipe mode
328 
330  ArnLink* twinLink = ArnM::addTwin( _link->linkPath(), _link, syncMode());
331  _link->setPipeMode( true);
332  twinLink->deref();
333 
334  return *this;
335 }
336 
337 
339 {
340  Q_D(const ArnBasicItem);
341 
342  if (!_link) return d->mode().is( Arn::ObjectMode::Pipe);
343 
344  return _link->isPipeMode();
345 }
346 
347 
349 {
350  Q_D(ArnBasicItem);
351 
352  d->_mode |= Arn::ObjectMode::Save;
353  if (!_link) return *this;
354 
355  _link->setSaveMode( true);
356  return *this;
357 }
358 
359 
361 {
362  Q_D(const ArnBasicItem);
363 
364  if (!_link) return d->mode().is( Arn::ObjectMode::Save);
365 
366  return _link->isSaveMode();
367 }
368 
369 
371 {
372  if (!_link) return;
373 
374  _link->setAtomicOpProvider( true);
375  return;
376 }
377 
378 
380 {
381  if (!_link) return false;
382 
383  return _link->isAtomicOpProvider();
384 }
385 
386 
388 {
389  if (_link) {
390  ArnM::errorLog( QString("Setting item/link as master"),
392  }
393  addSyncMode( Arn::ObjectSyncMode::Master, true);
394  return *this;
395 }
396 
397 
399 {
401 }
402 
403 
405 {
406  if (_link) {
407  ArnM::errorLog( QString("Setting item/link to autoDestroy"),
409  }
410  addSyncMode( Arn::ObjectSyncMode::AutoDestroy, true);
411  return *this;
412 }
413 
414 
416 {
418 }
419 
420 
422 {
423  Q_D(ArnBasicItem);
424 
425  d->_mode |= mode; // Just in case, transfer all modes
426 
427  if (mode.is( mode.Pipe)) {
428  setPipeMode();
429  }
430  else if (mode.is( mode.BiDir)) {
431  setBiDirMode();
432  }
433  if (mode.is( mode.Save)) {
434  setSaveMode();
435  }
436 }
437 
438 
440 {
441  return getMode( _link);
442 }
443 
444 
446 Arn::ObjectMode ArnBasicItem::getMode( ArnLink* link) const
447 {
448  Q_D(const ArnBasicItem);
449 
450  if (!link) return Arn::ObjectMode::fromInt( d->_mode);
451 
452  return link->getMode();
453 }
454 
455 
457 {
458  Q_D(ArnBasicItem);
459 
460  d->_ignoreSameValue = isPipeMode() ? false : isIgnore;
461 }
462 
463 
465 {
466  Q_D(const ArnBasicItem);
467 
468  return d->_ignoreSameValue;
469 }
470 
471 
472 QString ArnBasicItem::path( Arn::NameF nameF) const
473 {
474  if (!_link) return QString();
475 
476  return _link->linkPath( nameF);
477 }
478 
479 
480 QString ArnBasicItem::name( Arn::NameF nameF) const
481 {
482  if (!_link) return QString();
483 
484  return _link->linkName( nameF);
485 }
486 
487 
488 void ArnBasicItem::setReference( void* reference)
489 {
490  Q_D(ArnBasicItem);
491 
492  d->_reference = reference;
493 }
494 
495 
497 {
498  Q_D(const ArnBasicItem);
499 
500  return d->_reference;
501 }
502 
503 
505 {
506  Q_D(const ArnBasicItem);
507 
508  return d->_id;
509 }
510 
511 
512 void ArnBasicItem::arnImport( const QByteArray& data, int ignoreSame)
513 {
514  ArnLinkHandle handle;
515  arnImport( data, ignoreSame, handle);
516 }
517 
518 
519 void ArnBasicItem::arnImport( const QByteArray& data, int ignoreSame, ArnLinkHandle& handleData)
520 {
521  if (!data.isEmpty()) {
522  if (data.at(0) < 32) { // Assume Export-code
523  switch (Arn::ExportCode::fromInt( data.at(0))) {
524  case Arn::ExportCode::Variant: { // Legacy
525  QVariant value;
526  QDataStream stream( data);
527  stream.setVersion( DATASTREAM_VER);
528  quint8 dummy; // Will get Export-code
529  stream >> dummy >> value;
530  setValue( value, ignoreSame, handleData); // ArnLinkHandle not fully supported for QVariant
531  return;
532  }
534  int sepPos = data.indexOf(':', 1);
535  Q_ASSERT(sepPos > 0);
536 
537  QByteArray typeName( data.constData() + 1, sepPos - 1);
538  int type = QMetaType::type( typeName.constData());
539  if (!type) {
540  errorLog( QString("Import unknown text type:") + typeName.constData(),
542  return;
543  }
544  QVariant value( QString::fromUtf8( data.constData() + sepPos + 1,
545  data.size() - sepPos - 1));
546  if (!value.convert( QVariant::Type( type))) {
547  errorLog( QString("Can't' import data type:") + typeName.constData(),
549  return;
550  }
551 
552  setValue( value, ignoreSame, handleData); // ArnLinkHandle not fully supported for QVariant
553  return;
554  }
556  if ((data.size() < 3) || (data.at(2) != DATASTREAM_VER)) {
557  errorLog( QString("Import not same DataStream version"),
559  return;
560  }
561  int sepPos = data.indexOf(':', 3);
562  Q_ASSERT(sepPos > 0);
563 
564  QByteArray typeName( data.constData() + 3, sepPos - 3);
565  int type = QMetaType::type( typeName.constData());
566  if (!type) {
567  errorLog( QString("Import unknown binary type:") + typeName.constData(),
569  return;
570  }
571 #if QT_VERSION >= 0x050000
572  void* valData = QMetaType::create( type);
573 #else
574  void* valData = QMetaType::construct( type);
575 #endif
576  Q_ASSERT( valData);
577  QDataStream stream( data);
578  stream.setVersion( DATASTREAM_VER);
579  stream.skipRawData( sepPos + 1);
580 #if QT_VERSION >= 0x060000
581  QMetaType mt( type);
582  bool isOk = mt.load( stream, valData);
583 #else
584  bool isOk = QMetaType::load( stream, type, valData);
585 #endif
586  if (!isOk) {
587  errorLog( QString("Can't' import binary type:") + typeName.constData(),
589  QMetaType::destroy( type, valData);
590  return;
591  }
592 
593 #if QT_VERSION >= 0x060000
594  QVariant value( mt, valData);
595 #else
596  QVariant value( type, valData);
597 #endif
598  QMetaType::destroy( type, valData);
599 
600  setValue( value, ignoreSame, handleData); // ArnLinkHandle not fully supported for QVariant
601  return;
602  }
604  setValue( data.mid(1), ignoreSame, handleData);
605  return;
607  handleData.flags().set( ArnLinkHandle::Flags::Text);
608  setValue( data.mid(1), ignoreSame, handleData);
609  //setValue( QString::fromUtf8( data.constData() + 1, data.size() - 1),
610  // ignoreSame, handleData);
611  return;
612  default: // Not supported code
613  return;
614  }
615  }
616  }
617  // Normal printable data
618  handleData.flags().set( ArnLinkHandle::Flags::Text);
619  setValue( data, ignoreSame, handleData);
620 }
621 
622 
623 QByteArray ArnBasicItem::arnExport() const
624 {
625  if (!_link) return QByteArray();
626 
627  QByteArray retVal;
628  Arn::DataType arnType = _link->type();
629 
630  if (arnType == Arn::DataType::Variant) {
631  QVariant value = toVariant();
632  QByteArray typeName( value.typeName());
633  int type = QMetaType::type( typeName.constData());
634  if (!type) {
635  errorLog( QString("Export unknown type:") + typeName.constData(),
637  return QByteArray();
638  }
639 
640  if (value.canConvert( QVariant::String)) { // Textual Variant
641  retVal += char( Arn::ExportCode::VariantTxt);
642  retVal += typeName;
643  retVal += ':';
644  retVal += value.toString().toUtf8();
645  }
646  else { // Binary Variant
647  QDataStream stream( &retVal, QIODevice::WriteOnly);
648  stream.setVersion( DATASTREAM_VER);
649  stream << quint8( Arn::ExportCode::VariantBin);
650  stream << quint8(0); // Spare
651  stream << quint8( DATASTREAM_VER);
652  stream.writeRawData( typeName.constData(), typeName.size());
653  stream << quint8(':');
654  if (!QMetaType::save( stream, type, value.constData())) {
655  errorLog( QString("Can't export type:") + typeName,
657  return QByteArray();
658  }
659  }
660  }
661  else if (arnType == Arn::DataType::ByteArray) {
662  retVal = char( Arn::ExportCode::ByteArray) + toByteArray();
663  }
664  else { // Expect only normal printable (could also be \n etc)
665  retVal = toString().toUtf8();
666  if (!retVal.isEmpty()) {
667  if (retVal.at(0) < 32) { // Starting char conflicting with Export-code
668  retVal.insert( 0, char( Arn::ExportCode::String)); // Stuff String-code at pos 0
669  }
670  }
671  }
672 
673  return retVal;
674 }
675 
676 
677 QString ArnBasicItem::toString( bool* isOk) const
678 {
679  if (!_link) return QString();
680 
681  return _link->toString( isOk);
682 }
683 
684 
685 QByteArray ArnBasicItem::toByteArray( bool* isOk) const
686 {
687  if (!_link) return QByteArray();
688 
689  return _link->toByteArray( isOk);
690 }
691 
692 
693 QVariant ArnBasicItem::toVariant( bool* isOk) const
694 {
695  if (!_link) return QVariant();
696 
697  return _link->toVariant( isOk);
698 }
699 
700 
701 int ArnBasicItem::toInt( bool* isOk) const
702 {
703  if (!_link) return 0;
704 
705  return _link->toInt( isOk);
706 }
707 
708 
709 double ArnBasicItem::toDouble( bool* isOk) const
710 {
711  if (!_link) return 0.0;
712 
713  return _link->toReal( isOk);
714 }
715 
716 
717 ARNREAL ArnBasicItem::toReal( bool* isOk) const
718 {
719  if (!_link) return 0.0;
720 
721  return _link->toReal( isOk);
722 }
723 
724 
725 bool ArnBasicItem::toBool( bool* isOk) const
726 {
727  if (!_link) return false;
728 
729  return _link->toInt( isOk) != 0;
730 }
731 
732 
733 uint ArnBasicItem::toUInt( bool* isOk) const
734 {
735  if (!_link) return 0;
736 
737  return _link->toByteArray( isOk).toUInt( isOk);
738 }
739 
740 
741 qint64 ArnBasicItem::toInt64( bool* isOk) const
742 {
743  if (!_link) return 0;
744 
745  return _link->toByteArray( isOk).toLongLong( isOk);
746 }
747 
748 
749 quint64 ArnBasicItem::toUInt64( bool* isOk) const
750 {
751  if (!_link) return 0;
752 
753  return _link->toByteArray( isOk).toULongLong( isOk);
754 }
755 
756 
758 {
759  this->setValue( other);
760  return *this;
761 }
762 
763 
765 {
766  this->setValue( val);
767  return *this;
768 }
769 
770 
772 {
773  this->setValue( val);
774  return *this;
775 }
776 
777 
779 {
780  this->setValue( val);
781  return *this;
782 }
783 
784 
785 ArnBasicItem& ArnBasicItem::operator=( const QByteArray& val)
786 {
787  this->setValue( val);
788  return *this;
789 }
790 
791 
793 {
794  this->setValue( val);
795  return *this;
796 }
797 
798 
800 {
801  this->setValue( val);
802  return *this;
803 }
804 
805 
807 {
808  this->setValue( val);
809  return *this;
810 }
811 
812 
814 {
815  this->setValue( val);
816  return *this;
817 }
818 
819 
820 ArnBasicItem& ArnBasicItem::operator=( const QVariant& val)
821 {
822  this->setValue( val);
823  return *this;
824 }
825 
826 
828 {
829  this->addValue( val);
830  return *this;
831 }
832 
833 
835 {
836  this->addValue( val);
837  return *this;
838 }
839 
840 
841 void ArnBasicItem::setValue( const ArnBasicItem& other, int ignoreSame)
842 {
843  ArnLink *link = other._link;
844 
845  if (link) {
846  switch (link->type()) {
847  case Arn::DataType::Int:
848  this->setValue( link->toInt(), ignoreSame);
849  break;
850  case Arn::DataType::Real:
851  this->setValue( link->toReal(), ignoreSame);
852  break;
854  this->setValue( link->toString(), ignoreSame);
855  break;
857  this->setValue( link->toByteArray(), ignoreSame);
858  break;
860  this->setValue( link->toVariant(), ignoreSame);
861  break;
862  case Arn::DataType::Null:
863  //cerr << "Attempt to assign null value from "
864  // << other._link->linkPath() << " to "
865  // << this->_link->linkPath() << endl;
866  errorLog( QString("Assigning Null"),
868  break;
869  default:
870  // cerr << "Unknown type when assigning " << other._link->linkPath()
871  // << " to " << this->_link->linkPath() << endl;
872  errorLog( QString("Assigning unknown type"),
874  }
875  }
876  else {
877  errorLog( QString("Assigning"),
879  }
880 }
881 
882 
883 void ArnBasicItem::setValue( int value, int ignoreSame)
884 {
885  Q_D(ArnBasicItem);
886 
887  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
888  if (_link) {
889  if (isIgnoreSame) {
890  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
891  bool isOk;
892  if ((value == holderLink->toInt( &isOk)) && isOk) {
893  holderLink->setIgnoredValue();
894  return;
895  }
896  }
897  d->_isAssigning = true;
898  _link->setValue( value, d->_id, d->_useUncrossed);
899  d->_isAssigning = false;
900  }
901  else {
902  errorLog( QString("Assigning int:") + QString::number( value),
904  }
905 }
906 
907 
908 void ArnBasicItem::setValue( ARNREAL value, int ignoreSame)
909 {
910  Q_D(ArnBasicItem);
911 
912  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
913  if (_link) {
914  if (isIgnoreSame) {
915  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
916  bool isOk;
917  if ((value == holderLink->toReal( &isOk)) && isOk) {
918  holderLink->setIgnoredValue();
919  return;
920  }
921  }
922  d->_isAssigning = true;
923  _link->setValue( value, d->_id, d->_useUncrossed);
924  d->_isAssigning = false;
925  }
926  else {
927  errorLog( QString("Assigning ARNREAL:") + QString::number( value),
929  }
930 }
931 
932 
933 void ArnBasicItem::setValue( bool value, int ignoreSame)
934 {
935  Q_D(ArnBasicItem);
936 
937  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
938  if (_link) {
939  if (isIgnoreSame) {
940  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
941  bool isOk;
942  if ((value == (holderLink->toInt( &isOk) != 0)) && isOk) {
943  holderLink->setIgnoredValue();
944  return;
945  }
946  }
947  d->_isAssigning = true;
948  _link->setValue( value ? 1 : 0, d->_id, d->_useUncrossed);
949  d->_isAssigning = false;
950  }
951  else {
952  errorLog( QString("Assigning bool:") + QString::number( value),
954  }
955 }
956 
957 
958 void ArnBasicItem::setValue( const QString& value, int ignoreSame)
959 {
960  Q_D(ArnBasicItem);
961 
962  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
963  if (_link) {
964  if (isIgnoreSame) {
965  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
966  bool isOk;
967  if ((value == holderLink->toString( &isOk)) && isOk) {
968  holderLink->setIgnoredValue();
969  return;
970  }
971  }
972  d->_isAssigning = true;
973  _link->setValue( value, d->_id, d->_useUncrossed);
974  d->_isAssigning = false;
975  }
976  else {
977  errorLog( QString("Assigning string:") + value,
979  }
980 }
981 
982 
983 void ArnBasicItem::setValue( const QByteArray& value, int ignoreSame)
984 {
985  Q_D(ArnBasicItem);
986 
987  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
988  if (_link) {
989  if (isIgnoreSame) {
990  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
991  bool isOk;
992  if ((value == holderLink->toByteArray( &isOk)) && isOk) {
993  holderLink->setIgnoredValue();
994  return;
995  }
996  }
997  d->_isAssigning = true;
998  _link->setValue( value, d->_id, d->_useUncrossed);
999  d->_isAssigning = false;
1000  }
1001  else {
1002  errorLog( QString("Assigning bytearray:") + QString::fromUtf8( value.constData(), value.size()),
1004  }
1005 }
1006 
1007 
1008 void ArnBasicItem::setValue( const QVariant& value, int ignoreSame)
1009 {
1010  Q_D(ArnBasicItem);
1011 
1012  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
1013  if (_link) {
1014  if (isIgnoreSame) {
1015  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
1016  bool isOk;
1017  if ((value == holderLink->toVariant( &isOk)) && isOk) {
1018  holderLink->setIgnoredValue();
1019  return;
1020  }
1021  }
1022  d->_isAssigning = true;
1023  _link->setValue( value, d->_id, d->_useUncrossed);
1024  d->_isAssigning = false;
1025  }
1026  else {
1027  errorLog( QString("Assigning variant"),
1029  }
1030 }
1031 
1032 
1033 void ArnBasicItem::setValue( const char* value, int ignoreSame)
1034 {
1035  setValue( QString::fromUtf8( value), ignoreSame);
1036 }
1037 
1038 
1039 void ArnBasicItem::setValue( uint value, int ignoreSame)
1040 {
1041  if (_link) {
1042  setValue( QByteArray::number( value), ignoreSame);
1043  }
1044  else {
1045  errorLog( QString("Assigning uint:") + QString::number( value),
1047  }
1048 }
1049 
1050 
1051 void ArnBasicItem::setValue( qint64 value, int ignoreSame)
1052 {
1053  if (_link) {
1054  setValue( QByteArray::number( qlonglong( value)), ignoreSame);
1055  }
1056  else {
1057  errorLog( QString("Assigning int64:") + QString::number( qlonglong( value)),
1059  }
1060 }
1061 
1062 
1063 void ArnBasicItem::setValue( quint64 value, int ignoreSame)
1064 {
1065  if (_link) {
1066  setValue( QByteArray::number( qulonglong( value)), ignoreSame);
1067  }
1068  else {
1069  errorLog( QString("Assigning uint64:") + QString::number( qulonglong( value)),
1071  }
1072 }
1073 
1074 
1075 void ArnBasicItem::setBits( int mask, int value, int ignoreSame)
1076 {
1077  Q_D(ArnBasicItem);
1078 
1079  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0); // TODO: mw bidir
1080  if (_link) {
1081  if (isIgnoreSame) {
1082  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
1083  bool isOk;
1084  int oldValue = holderLink->toInt( &isOk);
1085  if ((((oldValue & ~mask) | (value & mask)) == oldValue) && isOk) {
1086  holderLink->setIgnoredValue();
1087  return;
1088  }
1089  }
1090  d->_isAssigning = true;
1091  _link->setBits( mask, value, d->_id, d->_useUncrossed);
1092  d->_isAssigning = false;
1093  }
1094  else {
1095  errorLog( QString("Op setBits: mask=") + QString::number( mask) +
1096  " value=" + QString::number( value), ArnError::ItemNotOpen);
1097  }
1098 }
1099 
1100 
1101 void ArnBasicItem::addValue( int value)
1102 {
1103  Q_D(ArnBasicItem);
1104 
1105  if (_link) {
1106  d->_isAssigning = true;
1107  _link->addValue( value, d->_id, d->_useUncrossed);
1108  d->_isAssigning = false;
1109  }
1110  else {
1111  errorLog( QString("Op addValue<int>: value=") + QString::number( value), ArnError::ItemNotOpen);
1112  }
1113 }
1114 
1115 
1117 {
1118  Q_D(ArnBasicItem);
1119 
1120  if (_link) {
1121  d->_isAssigning = true;
1122  _link->addValue( value, d->_id, d->_useUncrossed);
1123  d->_isAssigning = false;
1124  }
1125  else {
1126  errorLog( QString("Op addValue<real>: value=") + QString::number( value), ArnError::ItemNotOpen);
1127  }
1128 }
1129 
1130 
1131 QThread* ArnBasicItem::thread() const
1132 {
1133  Q_D(const ArnBasicItem);
1134 
1135  if (d->_eventHandler)
1136  return d->_eventHandler->thread();
1137  else
1138  return arnNullptr; // MW: Ok? or QThread::currentThread();
1139 }
1140 
1141 
1143 bool ArnBasicItem::sendArnEventLink( ArnEvent* ev)
1144 {
1145  if (!_link) return false;
1146 
1147  _link->sendArnEvent( ev);
1148  return true;
1149 }
1150 
1151 
1152 void ArnBasicItem::sendArnEventItem( ArnEvent* ev, bool isAlienThread, bool isLocked)
1153 {
1154  Q_D(ArnBasicItem);
1155 
1156  if (!ev) return; // No event ...
1157 
1158  ev->setTarget( this);
1159  if (isAlienThread) {
1160  QMutex* targetMutex = _link ? _link->getMutex() : arnNullptr;
1161  if (!isLocked) // Not locked yet, assign mutex for target locking
1162  ev->setTargetMutex( targetMutex);
1163 
1164  ev->setTargetPendingChain( &d->_pendingEvChain); //
1165 
1166  if (isLocked) // Already locked, mutex will be used from now on
1167  ev->setTargetMutex( targetMutex);
1168  }
1169 
1170  arnEvent( ev, isAlienThread);
1171 }
1172 
1173 
1174 void ArnBasicItem::arnEvent( QEvent* ev, bool isAlienThread)
1175 {
1176  // Selected ArnEvent handler is called. Default is internal handler.
1177  // Selected handler must finish with ArnBasicItemEventHandler::defaultEvent( ev).
1178  // Warning!!! This ArnBasicItem might get deleted (ev->target == arnNullptr).
1179 
1180  Q_D(ArnBasicItem);
1181 
1182  if (isAlienThread) {
1183  if (!d->_eventHandler) { // No handler
1184  delete ev;
1185  return;
1186  }
1187  QCoreApplication::postEvent( d->_eventHandler, ev);
1188  }
1189  else {
1190  if (d->_isStdEvHandler || !d->_eventHandler) {
1191  ArnBasicItemEventHandler::defaultEvent( ev); // Optimized direct call
1192  }
1193  else {
1194  d->_eventHandler->event( ev);
1195  }
1196  }
1197 }
1198 
1199 
1200 void ArnBasicItem::setEventHandler( QObject* eventHandler)
1201 {
1202  Q_D(ArnBasicItem);
1203 
1204  d->_eventHandler = eventHandler;
1205  d->_isStdEvHandler = false;
1206 }
1207 
1208 
1210 {
1211  Q_D(const ArnBasicItem);
1212 
1213  return d->_eventHandler;
1214 }
1215 
1216 
1217 void ArnBasicItem::setUncrossed( bool isUncrossed)
1218 {
1219  Q_D(ArnBasicItem);
1220 
1221  d->_useUncrossed = isUncrossed;
1222 }
1223 
1224 
1226 {
1227  Q_D(const ArnBasicItem);
1228 
1229  return d->_useUncrossed || !isBiDirMode();
1230 }
1231 
1232 
1234 {
1235  Q_D(const ArnBasicItem);
1236 
1237  return d->_isAssigning;
1238 }
1239 
1240 
1241 void ArnBasicItem::setForceKeep( bool fk)
1242 {
1243  setUncrossed( fk);
1244 }
1245 
1246 
1247 bool ArnBasicItem::isForceKeep() const
1248 {
1249  return isUncrossed();
1250 }
1251 
1252 
1253 void ArnBasicItem::setValue( const QByteArray& value, int ignoreSame, ArnLinkHandle& handleData)
1254 {
1255  Q_D(ArnBasicItem);
1256 
1257  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
1258  ArnLinkHandle::Flags& handleFlags = handleData.flags();
1259  QString valueTxt;
1260 
1261  if (handleFlags.is( handleFlags.Text))
1262  valueTxt = QString::fromUtf8( value.constData(), value.size());
1263 
1264  if (_link) {
1265  if (isIgnoreSame) {
1266  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
1267  bool isOk;
1268  if (handleFlags.is( handleFlags.Text)) {
1269  if ((valueTxt == holderLink->toString( &isOk)) && isOk) {
1270  holderLink->setIgnoredValue( handleData);
1271  return;
1272  }
1273  }
1274  else {
1275  if ((value == holderLink->toByteArray( &isOk)) && isOk) {
1276  holderLink->setIgnoredValue( handleData);
1277  return;
1278  }
1279  }
1280  }
1281  d->_isAssigning = true;
1282  if (handleFlags.is( handleFlags.Text)) {
1283  handleFlags.set( handleFlags.Text, false); // Text flag not needed anymore
1284  _link->setValue( valueTxt, d->_id, d->_useUncrossed, handleData);
1285  }
1286  else {
1287  _link->setValue( value, d->_id, d->_useUncrossed, handleData);
1288  }
1289  d->_isAssigning = false;
1290  }
1291  else {
1292  errorLog( QString("Assigning bytearray (ArnLinkHandle):") + QString::fromUtf8( value.constData(), value.size()),
1294  }
1295 }
1296 
1297 
1298 void ArnBasicItem::setValue( const QVariant& value, int ignoreSame, ArnLinkHandle& handleData)
1299 {
1300  Q_D(ArnBasicItem);
1301 
1302  bool isIgnoreSame = (ignoreSame < 0) ? isIgnoreSameValue() : (ignoreSame != 0);
1303  if (_link) {
1304  if (isIgnoreSame) {
1305  ArnLink* holderLink = _link->holderLink( d->_useUncrossed);
1306  bool isOk;
1307  if ((value == holderLink->toVariant( &isOk)) && isOk) {
1308  holderLink->setIgnoredValue( handleData);
1309  return;
1310  }
1311  }
1312  d->_isAssigning = true;
1313  _link->setValue( value, d->_id, d->_useUncrossed, handleData);
1314  d->_isAssigning = false;
1315  }
1316  else {
1317  errorLog( QString("Assigning variant (ArnLinkHandle):"),
1319  }
1320 }
1321 
1322 
1323 QStringList ArnBasicItem::childItemsMain() const
1324 {
1325  // This must be run in main thread as childs only can be deleted there
1326  return ArnM::itemsMain( _link);
1327 }
1328 
1329 
1330 void ArnBasicItem::errorLog( const QString& errText, ArnError err, void* reference) const
1331 {
1332  QString itemText;
1333  if (_link) {
1334  itemText = " Item:" + _link->linkPath();
1335  }
1336  ArnM::errorLog( errText + itemText, err, reference);
1337 }
1338 
1339 
1340 
1341 ArnBasicItemEventHandler* ArnBasicItem::getThreadEventHandler()
1342 {
1343  static QThreadStorage<ArnBasicItemEventHandler*> evHandlers;
1344 
1345  if (!evHandlers.hasLocalData())
1346  evHandlers.setLocalData( new ArnBasicItemEventHandler);
1347 
1348  return evHandlers.localData();
1349 }
1350 
1351 
1352 ArnBasicItemEventHandler::ArnBasicItemEventHandler( QObject* parent)
1353  : QObject( parent)
1354 {
1355 }
1356 
1357 
1358 ArnBasicItemEventHandler::~ArnBasicItemEventHandler()
1359 {
1360 }
1361 
1362 
1364 void ArnBasicItemEventHandler::defaultEvent( QEvent* ev)
1365 {
1366  int evIdx = ev->type() - ArnEvent::baseType();
1367  switch (evIdx) {
1369  {
1370  ArnEvModeChange* e = static_cast<ArnEvModeChange*>( ev);
1371  ArnBasicItem* target = static_cast<ArnBasicItem*>( e->target());
1372  if (!target) return; // No target, deleted/closed ...
1373 
1374  // qDebug() << "ArnBasicEvModeChange: path=" << e->path() << " mode=" << e->mode()
1375  // << " inItemPath=" << target->path();
1376  if (!target->isFolder()) {
1377  if (e->mode().is( Arn::ObjectMode::Pipe)) { // Pipe-mode never IgnoreSameValue
1378  target->setIgnoreSameValue(false);
1379  }
1380  }
1381  return;
1382  }
1384  {
1385  ArnEvRetired* e = static_cast<ArnEvRetired*>( ev);
1386  ArnBasicItem* target = static_cast<ArnBasicItem*>( e->target());
1387  if (!target) return; // No target, deleted/closed ...
1388 
1389  if (!e->isBelow()) {
1390  if (Arn::debugLinkDestroy) qDebug() << "BasicItem arnLinkDestroyed: path=" << target->path();
1391  target->close();
1392  e->setTarget( arnNullptr); // target is not available any more
1393  }
1394  return;
1395  }
1396  default:;
1397  }
1398 }
1399 
1400 
1401 void ArnBasicItemEventHandler::customEvent( QEvent* ev)
1402 {
1403  defaultEvent( ev);
1404 }
Data type of an Arn Data Object
Definition: Arn.hpp:74
bool isUncrossed() const
Get the Uncrossed state of an object.
virtual ~ArnBasicItem()
QString toString(bool *isOk=arnNullptr) const
static int baseType(int setVal=-1)
Definition: ArnEvent.cpp:62
void destroyLink(bool isGlobal=true)
Destroy the Arn Data Object
QThread * thread() const
Get the thread affinity of this ArnBasicItem.
void setValue(const ArnBasicItem &other, int ignoreSame=Arn::SameValue::DefaultAction)
ArnBasicItem & setPipeMode()
Set general mode as Pipe for this Arn Data Object
quint64 toUInt64(bool *isOk=arnNullptr) const
bool isMaster() const
Arn::ObjectSyncMode syncMode() const
bool toBool(bool *isOk=arnNullptr) const
bool open(const QString &path)
Open a handle to an Arn Data Object
void close()
Close the handle.
void setReference(void *reference)
Set an associated external reference.
ArnBasicItem & setSaveMode()
Set general mode as Save for this Arn Data Object
bool debugLinkDestroy
Definition: ArnLib.cpp:40
int refCount() const
Get the number of refs to this Arn Data Object
uint toUInt(bool *isOk=arnNullptr) const
Implies BiDir and all data is preserved as a stream.
Definition: Arn.hpp:128
void setIgnoreSameValue(bool isIgnore=true)
Set skipping of equal value.
void setUncrossed(bool isUncrossed=true)
Set a Bidirectional item as Uncrossed.
Core base class for the inherited ArnItem classes.
Definition: ArnCoreItem.hpp:56
Arn::ObjectMode getMode() const
Use with care, link must be "referenced" before use, otherwise it might have been deleted...
bool isAtomicOpProvider() const
int toInt(bool *isOk=arnNullptr) const
uint itemId() const
Get the id for this ArnItem.
bool isIgnoreSameValue() const
ARNREAL toReal(bool *isOk=arnNullptr) const
Arn::ObjectMode mode() const
Definition: ArnEvent.hpp:168
QByteArray toByteArray(bool *isOk=arnNullptr) const
void setAtomicOpProvider()
Set this Arn Data Object as Atomic Operator Provider
A two way object, typically for validation or pipe.
Definition: Arn.hpp:126
void addValue(int value)
AtomicOp adds an integer to an Arn Data Object
void * reference() const
Get the stored external reference.
void setBits(int mask, int value, int ignoreSame=Arn::SameValue::DefaultAction)
AtomicOp assign an integer to specified bits in an Arn Data Object
void arnImport(const QByteArray &data, int ignoreSame=Arn::SameValue::DefaultAction)
Import data to an Arn Data Object
ArnBasicItem & operator+=(int val)
QVariant toVariant(bool *isOk=arnNullptr) const
void setTargetPendingChain(ArnEvent **targetPendingChain=arnNullptr)
Definition: ArnEvent.cpp:144
Definition: Arn.cpp:43
Destroy this Arn Data Object when client (tcp/ip) closes.
Definition: Arn.hpp:149
bool isOpen() const
State of the handle.
QString path(Arn::NameF nameF=Arn::NameF::EmptyOk) const
Path of the Arn Data Object
ArnBasicItem & setBiDirMode()
Set general mode as Bidirectional for this Arn Data Object
void addMode(Arn::ObjectMode mode)
Add general mode settings for this Arn Data Object
Arn::DataType type() const
The type stored in the Arn Data Object
#define ARNREAL
Definition: Arn.hpp:44
bool isAutoDestroy() const
static bool defaultIgnoreSameValue()
Definition: ArnM.cpp:1068
ArnBasicItem()
Standard constructor of a closed handle.
bool isBelow() const
Definition: ArnEvent.hpp:213
ArnBasicItem & setAutoDestroy()
Set client session sync mode as AutoDestroy for this ArnItem.
double toDouble(bool *isOk=arnNullptr) const
bool isFolder() const
uint linkId() const
Get the id for this Arn Data Object
#define DATASTREAM_VER
Definition: Arn.hpp:39
qint64 toInt64(bool *isOk=arnNullptr) const
static void errorLog(QString errText, ArnError err=ArnError::Undef, void *reference=arnNullptr)
Definition: ArnM.cpp:1025
bool isSaveMode() const
static void destroyLink(const QString &path, bool isGlobal=true)
Destroy the Arn Data Object at path
Definition: ArnM.cpp:853
bool isBiDirMode() const
QString name(Arn::NameF nameF) const
Name of the Arn Data Object
void setTargetMutex(QMutex *targetMutex)
Definition: ArnEvent.cpp:161
void setTarget(void *target)
Definition: ArnEvent.cpp:138
Data is persistent and will be saved.
Definition: Arn.hpp:130
friend class ArnBasicItemEventHandler
QByteArray arnExport() const
ArnBasicItem & setMaster()
Set client session sync mode as Master for this ArnItem.
void * target() const
Definition: ArnEvent.hpp:116
ArnBasicItem & operator=(const ArnBasicItem &other)
QObject * eventHandler() const
Get the event handler of this ArnBasicItem.
bool isProvider() const
void setEventHandler(QObject *eventHandler)
Set event handler for this ArnBasicItem.
bool isPipeMode() const
Base class handle for an Arn Data Object.
The client is default generator of data.
Definition: Arn.hpp:147
bool isAssigning() const
Tells if this ArnItem is assigned right now.