Wtx ~ Wt Extension Library
WtxLib
FormModel_imp.h
1 /**************************************************************************
2 ###########################################################################
3 ##
4 ## $SHOWOFFDB_BEGIN_LICENSE$
5 ## Copyright (C) 2011 Lorimark Solutions, LLC and/or its subsidiary(-ies).
6 ## All rights reserved.
7 ## Contact: Lorimark Solutions, LLC (info@showoff-db.org)
8 ##
9 ## This file is part of the Showoff Database Application Framework.
10 ##
11 ## Commercial Usage
12 ## Licensees holding valid ShowoffDB Commercial licenses may use this file in
13 ## accordance with the ShowoffDB Commercial License Agreement provided with the
14 ## Software or, alternatively, in accordance with the terms contained in
15 ## a written agreement between you and Lorimark Solutions, LLC.
16 ##
17 ## GNU Lesser General Public License Usage
18 ## Alternatively, this file may be used under the terms of the GNU Lesser
19 ## General Public License version 2.1 as published by the Free Software
20 ## Foundation and appearing in the file LICENSE.LGPL included in the
21 ## packaging of this file. Please review the following information to
22 ## ensure the GNU Lesser General Public License version 2.1 requirements
23 ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ##
25 ## In addition, as a special exception, Lorimark Solutions, LLC gives
26 ## you certain additional rights. These rights are described in the
27 ## Lorimark Solutions, LLC ShowoffDB LGPL Exception version 1.0, included in
28 ## the file LGPL_EXCEPTION.txt in this package.
29 ##
30 ## GNU General Public License Usage
31 ## Alternatively, this file may be used under the terms of the GNU
32 ## General Public License version 3.0 as published by the Free Software
33 ## Foundation and appearing in the file LICENSE.GPL included in the
34 ## packaging of this file. Please review the following information to
35 ## ensure the GNU General Public License version 3.0 requirements will be
36 ## met: http://www.gnu.org/copyleft/gpl.html.
37 ##
38 ## If you have questions regarding the use of this file, please contact
39 ## Lorimark Solutions, LLC at info@showoff-db.org.
40 ## $SHOWOFFDB_END_LICENSE$
41 ##
42 #############################################################################
43 ****************************************************************************/
44 
45 template <class C>
46 FormModel<C>::~FormModel()
47 {
48 }
49 
50 template <class C>
51 Wt::Dbo::ptr<C> FormModel<C>::load( int id, Wt::Dbo::Session * s )
52 {
53  if( id == -1 )
54  return Wt::Dbo::ptr<C>();
55 
56  Wt::Dbo::Transaction t(*s);
57  return s-> load<C>(id);
58 }
59 
60 template <class C>
61 FormModel<C>::FormModel( int id, Wt::Dbo::Session * s )
62 : Wtx::FormModel( C::TableDef() ),
63  m_item( load(id,s) )
64 {
65 #ifdef FM_DEBUG_TRACE
66  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
67 #endif
68  read();
69 }
70 
71 template <class C>
72 FormModel<C>::FormModel( const Wt::Dbo::ptr<C> & itm )
73 : Wtx::FormModel( C::TableDef() ),
74  m_item(itm)
75 {
76 #ifdef FM_DEBUG_TRACE
77  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
78 #endif
79  read();
80 }
81 
82 template <class C>
83 std::string FormModel<C>::tableName() const
84 {
85 #ifdef FM_DEBUG_TRACE
86  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
87 #endif
88  return C::TableDef().tableName();
89 }
90 
91 template <class C>
92 int FormModel<C>::itemId() const
93 {
94 #ifdef FM_DEBUG_TRACE
95  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
96 #endif
97  return item().id();
98 }
99 
100 template <class C>
101 const Wt::Dbo::ptr<C> & FormModel<C>::item() const
102 {
103 #ifdef FM_DEBUG_TRACE
104  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
105 #endif
106  return m_item;
107 }
108 
109 template <class C>
110 Wt::Dbo::ptr<C> & FormModel<C>::item()
111 {
112 #ifdef FM_DEBUG_TRACE
113  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
114 #endif
115  return m_item;
116 }
117 
118 template <class C>
119 Wt::Dbo::Session * FormModel<C>::session() const
120 {
121 #ifdef FM_DEBUG_TRACE
122  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
123 #endif
124  return item().session();
125 }
126 
127 template <class C>
128 bool FormModel<C>::remove()
129 {
130 #ifdef FM_DEBUG_TRACE
131  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
132 #endif
133  if( itemId() != -1 )
134  {
135  Wt::Dbo::Transaction t(*session());
136  item().remove();
137  item().purge();
138  return true;
139  }
140 
141  return false;
142 }
143 
144 template <class C>
145 int FormModel<C>::read()
146 {
147 #ifdef FM_DEBUG_TRACE
148  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
149 #endif
150 
151  m_isReadMode = true;
152  Wt::Dbo::Transaction t(*session());
153  refresh();
154  return itemId();
155 }
156 
157 template <class C>
158 void FormModel<C>::refresh()
159 {
160 #ifdef FM_DEBUG_TRACE
161  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
162 #endif
163 
164  if( itemId() == -1 )
165  return;
166 
167  const_cast<C*>(item().get())-> persist(*this);
168  const_cast<C*>(item().get())-> postRead();
169 }
170 
171 template <class C>
172 std::unique_ptr<Wt::WWidget> FormModel<C>::createEditWidget( Wt::WFormModel::Field f ) const
173 {
174 #ifdef FM_DEBUG_TRACE
175  std::cout << __LINE__ << ":" << __FILE__ << " " << f << std::endl;
176 #endif
177  if( item() )
178  return item()-> createEditWidget( f );
179 
180  return std::make_unique<Wt::WLineEdit>();
181 }
182 
183 template <class C>
184 void FormModel<C>::staleRefresh()
185 {
186 #ifdef FM_DEBUG_TRACE
187  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
188 #endif
189  if( isStale() )
190  {
191  Wt::Dbo::Transaction t(*session());
192  item().reread();
193  read();
194  }
195 }
196 
197 template <class C>
198 bool FormModel<C>::isStale() const
199 {
200 #ifdef FM_DEBUG_TRACE
201  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
202 #endif
203  if( itemId() == -1 )
204  return false;
205 
206  return diskVersion() != itemVersion();
207 }
208 
209 template <class C>
210 int FormModel<C>::diskVersion() const
211 {
212 #ifdef FM_DEBUG_TRACE
213  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
214 #endif
215  if( !session() )
216  return -1;
217 
218  Wt::Dbo::Transaction t(*session());
219  int version = session()->
220  template query<int>("SELECT version FROM \"" + tableName() + "\"")
221  .where("id=?").bind( item().id() )
222  ;
223 
224  return version;
225 }
226 
227 template <class C>
228 int FormModel<C>::itemVersion() const
229 {
230 #ifdef FM_DEBUG_TRACE
231  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
232 #endif
233  return m_item.version();
234 }
235 
236 template <class C>
237 const Wt::WFormModel::Field FormModel<C>::field( const std::string & fieldName ) const
238 {
239 #ifdef FM_DEBUG_TRACE
240  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
241 #endif
242 #ifdef NEVER
243  std::string c = "if:";
244  std::string f = fieldName;
245  if( f.substr( 0, c.size() ) == c )
246  {
247  f = f.substr(c.size());
248  }
249 
250  for( unsigned int i=0; i< fields().size(); i++ )
251  if( fields()[i] == f )
252  return fields()[i];
253 #endif
254 
255  auto fieldDef = item()-> TableDef().fieldDef(fieldName);
256 
257  if( fieldDef )
258  return fieldDef-> fieldName();
259 
260 #ifdef NEVER
261 
270  std::cout << __FILE__ << " " << __LINE__ << " "
271  << "WARNING (possibly fatal): cannot find: " << tableName() << "::" << fieldName << " in fields array"
272  << std::endl
273  ;
274 #endif
275 
276  return 0;
277 }
278 
279 template <class C>
280 const Wt::cpp17::any & FormModel<C>::value( const std::string & fieldName ) const
281 {
282 #ifdef FM_DEBUG_TRACE
283  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
284 #endif
285  return Wtx::FormModel::value( field(fieldName) );
286 }
287 
288 template <class C>
289 const Wt::cpp17::any & FormModel<C>::value( const Wtx::Dbo::FieldDefBase & fieldDef ) const
290 {
291 #ifdef FM_DEBUG_TRACE
292  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
293 #endif
294  return Wtx::FormModel::value( fieldDef.fieldName() );
295 }
296 
297 template <class C>
298 int FormModel<C>::accept()
299 {
300 #ifdef FM_DEBUG_TRACE
301  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
302 #endif
303  /*
304  ** before writing to the item, check the version of the item
305  ** on disk before attempting to write out our item. If there
306  ** is a discrepancy then we cannot write out the item since it
307  ** will cause an exception fault.
308  **
309  */
310  if( isStale() )
311  {
312  std::cout << __FILE__ << " " << __LINE__ << " "
313  << " stale object: "
314  << "\"" << tableName() << "\" "
315  << "id=" << item().id() << " "
316  << "itemVersion=" << itemVersion() << " "
317  << "diskVersion=" << diskVersion() << " "
318  << std::endl
319  ;
320  exit(-1);
321  return itemId();
322  }
323 
324  {
325  m_isReadMode = false;
326  Wt::Dbo::Transaction t(*session());
327 
328  if( itemId() == -1 )
329  session()-> add( m_item );
330 
331  item().modify()-> persist(*this);
332  item().modify()-> preWrite();
333  }
334 
335  staleRefresh();
336 
337  return itemId();
338 }
339 
340 template <class C>
341 void FormModel<C>::reset ()
342 {
343 #ifdef FM_DEBUG_TRACE
344  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
345 #endif
346  Wtx::FormModel::reset();
347 }
348 
349 template <class C>
350 bool FormModel<C>::validate ()
351 {
352 #ifdef FM_DEBUG_TRACE
353  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
354 #endif
355  return Wtx::FormModel::validate();
356 }
357 
358 template <class C>
359 bool FormModel<C>::isVisible( Wt::WFormModel::Field field ) const
360 {
361 #ifdef FM_DEBUG_TRACE
362  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
363 #endif
364  return Wtx::FormModel::isVisible( field );
365 }
366 
367 template <class C>
368 bool FormModel<C>::isReadOnly( Wt::WFormModel::Field field ) const
369 {
370 #ifdef FM_DEBUG_TRACE
371  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
372 #endif
373  return Wtx::FormModel::isReadOnly( field );
374 }
375 
376 template <class C>
377 Wt::WString FormModel<C>::label( Wt::WFormModel::Field field ) const
378 {
379 #ifdef FM_DEBUG_TRACE
380  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
381 #endif
382  return Wtx::FormModel::label( field );
383 }
384 
385 template <class C>
386 void FormModel<C>::setValue( Wt::WFormModel::Field field, const Wt::cpp17::any &value )
387 {
388 #ifdef FM_DEBUG_TRACE
389  std::cout << __LINE__ << ":" << __FILE__ << " " << field << " " << Wt::asString(value) << std::endl;
390 #endif
391  Wtx::FormModel::setValue( field, value );
392 }
393 
394 template <class C>
395 const Wt::cpp17::any & FormModel<C>::value( Wt::WFormModel::Field field ) const
396 {
397 #ifdef FM_DEBUG_TRACE
398  std::cout << __LINE__ << ":" << __FILE__ << " " << field << std::endl;
399 #endif
400  return Wtx::FormModel::value( field );
401 }
402 
403 template <class C>
404 Wt::WString FormModel<C>::valueText( Wt::WFormModel::Field field ) const
405 {
406 #ifdef FM_DEBUG_TRACE
407  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
408 #endif
409  return Wtx::FormModel::valueText( field );
410 }
411 
412 template <class C>
413 void FormModel<C>::setValidator (Wt::WFormModel::Field field, const std::shared_ptr< Wt::WValidator > &validator )
414 {
415 #ifdef FM_DEBUG_TRACE
416  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
417 #endif
418  Wtx::FormModel::setValidator( field, validator );
419 }
420 
421 template <class C>
422 std::shared_ptr< Wt::WValidator > FormModel<C>::validator( Wt::WFormModel::Field field ) const
423 {
424 #ifdef FM_DEBUG_TRACE
425  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
426 #endif
427  return Wtx::FormModel::validator( field );
428 }
429 
430 template <class C>
431 bool FormModel<C>::validateField( Wt::WFormModel::Field field )
432 {
433 #ifdef FM_DEBUG_TRACE
434  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
435 #endif
436  return Wtx::FormModel::validateField( field );
437 }
438 
439 template <class C>
440 void FormModel<C>::setValidated (Wt::WFormModel::Field field, bool validated)
441 {
442 #ifdef FM_DEBUG_TRACE
443  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
444 #endif
445  Wtx::FormModel::setValidated( field, validated );
446 }
447 
448 template <class C>
449 bool FormModel<C>::isValidated (Wt::WFormModel::Field field) const
450 {
451 #ifdef FM_DEBUG_TRACE
452  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
453 #endif
454  return Wtx::FormModel::isValidated( field );
455 }
456 
457 template <class C>
458 void FormModel<C>::setValidation( Wt::WFormModel::Field field, const Wt::WValidator::Result &result )
459 {
460 #ifdef FM_DEBUG_TRACE
461  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
462 #endif
463  Wtx::FormModel::setValidation( field, result );
464 }
465 
466 template <class C>
467 template <typename T> void FormModel<C>::act( Wt::Dbo::FieldRef<T> ref )
468 {
469 #ifdef FM_DEBUG_TRACE
470  std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
471 #endif
472 #ifdef FM_DEBUG_ACTIVITY
473  std::cout << __FILE__ << " " << __LINE__ << " "
474  << "read=" << (m_isReadMode? std::string("true"):std::string("false")) << " "
475  << "id=" << itemId() << " "
476  << "name=" << ref.name() << " "
477  << "value=" << item()-> keyField().value() << " "
478  << field(ref.name()) << " "
479 // << ref.value() << " "
480  << "'" << Wt::asString( value( field( ref.name() ) ) ) << "' "
481  << std::endl
482  ;
483 #endif
484 
485  if( m_isReadMode )
486  {
487  setValue
488  (
489  field(ref.name()),
490  Wt::cpp17::any(ref.value())
491  );
492  }
493  else
494  {
495  /*
496  ** fields that are designated as 'showOnly' are absolutely
497  ** NOT written back to the back-end database. This is different
498  ** from fields that are designated as 'readOnly' in which case,
499  ** when the fields are shown they fields cannot be edited.
500  ** However, fields marked as 'readOnly' can be modified through
501  ** the model whereas fields marked as 'showOnly' cannot.
502  **
503  ** The fundamental principal here is that in some cases, when
504  ** showing a field value, the 'field-write-to-db' function
505  ** (this function you're looking at now) is writing bad data
506  ** to the back-end database. This became a problem with the
507  ** back-end database on field types WDateTime. Something about
508  ** the conversion from a front-end WLineEdit to a back-end
509  ** WDateTime was causing total failure of the database, since
510  ** after the write, the back-end database contained a date-time
511  ** value of '-infinity' and then not even the table-views would
512  ** load the data - it would just crash the system.
513  **
514  ** UPDATE: the issue with writing date fields back to the back-end
515  ** database had something to do with the locale conversion of
516  ** the WDateTime input field. The field was not honoring locale
517  ** whereas the back-end database was, and so there was a date
518  ** local/style formatting conflict causing crap data to be push
519  ** to the database. A bug report was submitted to Wt and they
520  ** fixed the library.
521  **
522  */
523 #ifndef NEVER
524 // if( !isShowOnly( fieldDef( field(ref.name()) ) ) )
525  {
526  ref.setValue
527  (
528  Wt::cpp17::any_cast<T>
529  (
530  Wt::convertAnyToAny
531  (
532  value
533  (
534  field
535  (
536  ref.name()
537  )
538  ),
539  typeid(T)
540  )
541  )
542  );
543  }
544 #else
545 // if( !isShowOnly( fieldDef( field(ref.name()) ) ) )
546  {
547  ref.setValue
548  (
549  value
550  (
551  field
552  (
553  ref.name()
554  )
555  )
556  );
557  }
558 #endif
559  }
560 
561 #ifdef FM_DEBUG_ACTIVITY
562  if( std::string(ref.name()) == "dateStart" || std::string(ref.name()) == "keyField" || std::string(ref.name()) == "cfyField" )
563  std::cout << __FILE__ << " " << __LINE__ << " "
564  << std::string( isReadMode? "read":"write" ) << " "
565  << ref.name() << " "
566  << "'" << Wt::asString( value( field( ref.name() ) ) ) << "' "
567  << "'" << Wt::asString( ref.value() ) << "' "
568  << std::endl
569  ;
570 
571  if( std::string(ref.name()) == "dateStart" )
572  {
573  Wt::WString s = Wt::asString( value( field( ref.name() ) ) );
574  std::cout << __FILE__ << " " << __LINE__ << " "
575  << Wt::WLocale::currentLocale().dateFormat().toUTF8() << " "
576  << s << " "
577  << Wt::WDate::fromString(s,Wt::WLocale::currentLocale().dateFormat()).toString()
578  << std::endl
579  ;
580 
581  }
582 #endif
583 
584 
585 } // endtemplate <typename T> void FormModel<C>::act( Wt::Dbo::FieldRef<T> ref )
586 
587 /*
588 ** process pointer values to other classes
589 **
590 */
591 template <class C>
592 template <typename T> void FormModel<C>::actPtr( const Wt::Dbo::PtrRef<T> & ref )
593 {
594  /*
595  ** in read mode we store the pointer value
596  ** in to the model
597  **
598  */
599  if( m_isReadMode )
600  {
601 #ifdef FM_DEBUG_ACTIVITY
602  std::cout << __FILE__ << " " << __LINE__ << " read: "
603  << "ref.type=" << ref.type()-> name() << " "
604  << "ref.name=" << ref.name() << " "
605  << "id=" << ref.id() << " "
606  << "value.type=" << value( field( ref.name() ) ).type().name() << " "
607  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
608  << std::endl
609  ;
610 #endif
611  setValue
612  (
613  field(ref.name()), ref.value()
614 // boost::any(ref.value())
615  );
616 
617 #ifdef FM_DEBUG_ACTIVITY
618  std::cout << __FILE__ << " " << __LINE__ << " read: "
619  << "ref.type=" << ref.type()-> name() << " "
620  << "ref.name=" << ref.name() << " "
621  << "id=" << ref.id() << " "
622  << "value.type=" << value( field( ref.name() ) ).type().name() << " "
623  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
624  << std::endl
625  ;
626 #endif
627 
628  }
629 
630  /*
631  ** in write mode, we have to determine if the stored
632  ** value is still in a pointer representation, or
633  ** if it was converted to a text value (which can happen).
634  ** If the original pointer was converted to a text
635  ** value then we need to convert it to an integer and then
636  ** use that integer to find the original item so that
637  ** we can assign the item properly.
638  **
639  */
640  else
641  {
642  Wt::Dbo::ptr<T> newPtr;
643 
644  if( value(field(ref.name())).type() == typeid(Wt::Dbo::ptr<T>) )
645  {
646  newPtr = Wt::cpp17::any_cast< Wt::Dbo::ptr<T> >
647  (
648  value
649  (
650  field
651  (
652  ref.name()
653  )
654  )
655  );
656  }
657 
658  if( value(field(ref.name())).type() == typeid(std::string) )
659  {
660  std::cout << __FILE__ << " " << __LINE__ << " converting from std::string " << std::endl;
661  }
662 
663  /*
664  ** BUGBUG: this function should be returning a value() type
665  ** from the model that is a Dbo::ptr<> and not a string, but
666  ** it will come back as a WString if the editor used to modify
667  ** the field value is a WTextEdit. If we split apart string
668  ** we can extricate the id() value embedded in it, but this is
669  ** risky at best, and should not be required at all. But,
670  ** it is important to use the correct editor for these field
671  ** values.
672  **
673  */
674  if( value(field(ref.name())).type() == typeid(Wt::WString) )
675  {
676  auto idv = Wt::asString( value( field( ref.name() ) ) ).toUTF8();
677 
678  if( idv != "[null]" )
679  {
680  auto v = Wtx::Core::split( idv, ':' );
681  int idVal = std::stoi(v.at(1));
682 
683  if( idVal != -1 )
684  newPtr = session()-> template load<T>(idVal);
685  }
686  }
687 
688 #ifdef FM_DEBUG_ACTIVITY
689  std::cout << __FILE__ << " " << __LINE__ << " write: "
690  << "ref.name=" << ref.name() << " "
691  << "value.typename=" << value( field( ref.name() ) ).type().name() << " "
692  << "value.type=" << value( field( ref.name() ) ).type().hash_code() << " "
693  << "typeid<T>=" << typeid(Wt::Dbo::ptr<T>).hash_code() << " "
694  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
695  << "newPtr=" << newPtr.id()
696  << std::endl
697  ;
698 #endif
699 
700  /*
701  ** update the original pointer object with the
702  ** new value. if the id value is -1 then the
703  ** ref.value() will be cleared to nothing, which
704  ** is what's supposed to happen.
705  **
706  */
707 // if( newPtr.id() != -1 )
708  {
709  ref.value() = newPtr;
710  }
711 
712  } // endif( ..write mode.. )
713 
714 } // endtemplate <typename T> void actPtr( const Wt::Dbo::PtrRef<T> & ptrRef )
715 
716 /*
717 ** process pointer values to other classes
718 **
719 */
720 template <class C>
721 template <typename T> void FormModel<C>::actWeakPtr( const Wt::Dbo::WeakPtrRef<T> & ref )
722 {
723 #ifdef NEVER
724  /*
725  ** in read mode we store the pointer value
726  ** in to the model
727  **
728  */
729  if( m_isReadMode )
730  {
731 #ifdef FM_DEBUG_ACTIVITY
732  std::cout << __FILE__ << " " << __LINE__ << " read: "
733  << "ref.type=" << ref.type()-> name() << " "
734  << "ref.name=" << ref.name() << " "
735  << "id=" << ref.id() << " "
736  << "value.type=" << value( field( ref.name() ) ).type().name() << " "
737  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
738  << std::endl
739  ;
740 #endif
741  setValue
742  (
743  field(ref.name()), ref.value()
744 // boost::any(ref.value())
745  );
746 
747 #ifdef FM_DEBUG_ACTIVITY
748  std::cout << __FILE__ << " " << __LINE__ << " read: "
749  << "ref.type=" << ref.type()-> name() << " "
750  << "ref.name=" << ref.name() << " "
751  << "id=" << ref.id() << " "
752  << "value.type=" << value( field( ref.name() ) ).type().name() << " "
753  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
754  << std::endl
755  ;
756 #endif
757 
758  }
759 
760  /*
761  ** in write mode, we have to determine if the stored
762  ** value is still in a pointer representation, or
763  ** if it was converted to a text value (which can happen).
764  ** If the original pointer was converted to a text
765  ** value then we need to convert it to an integer and then
766  ** use that integer to find the original item so that
767  ** we can assign the item properly.
768  **
769  */
770  else
771  {
772  Wt::Dbo::ptr<T> newPtr;
773 
774  if( value(field(ref.name())).type() == typeid(Wt::Dbo::ptr<T>) )
775  {
776  newPtr = Wt::cpp17::any_cast< Wt::Dbo::ptr<T> >
777  (
778  value
779  (
780  field
781  (
782  ref.name()
783  )
784  )
785  );
786  }
787 
788  if( value(field(ref.name())).type() == typeid(std::string) )
789  {
790  std::cout << __FILE__ << " " << __LINE__ << " converting from std::string " << std::endl;
791  }
792 
793  /*
794  ** BUGBUG: this function should be returning a value() type
795  ** from the model that is a Dbo::ptr<> and not a string, but
796  ** it will come back as a WString if the editor used to modify
797  ** the field value is a WTextEdit. If we split apart string
798  ** we can extricate the id() value embedded in it, but this is
799  ** risky at best, and should not be required at all. But,
800  ** it is important to use the correct editor for these field
801  ** values.
802  **
803  */
804  if( value(field(ref.name())).type() == typeid(Wt::WString) )
805  {
806  auto idv = Wt::asString( value( field( ref.name() ) ) ).toUTF8();
807 
808  if( idv != "[null]" )
809  {
810  int idVal = std::stoi( idv );
811 
812  if( idVal != -1 )
813  newPtr = session()-> template load<T>(idVal);
814  }
815  }
816 
817 #ifdef FM_DEBUG_ACTIVITY
818  std::cout << __FILE__ << " " << __LINE__ << " write: "
819  << "ref.name=" << ref.name() << " "
820  << "value.typename=" << value( field( ref.name() ) ).type().name() << " "
821  << "value.type=" << value( field( ref.name() ) ).type().hash_code() << " "
822  << "typeid<T>=" << typeid(Wt::Dbo::ptr<T>).hash_code() << " "
823  << "value=" << Wt::asString( value( field( ref.name() ) ) ) << " "
824  << "newPtr=" << newPtr.id()
825  << std::endl
826  ;
827 #endif
828 
829  /*
830  ** update the original pointer object with the
831  ** new value. if the id value is -1 then the
832  ** ref.value() will be cleared to nothing, which
833  ** is what's supposed to happen.
834  **
835  */
836 // if( newPtr.id() != -1 )
837  {
838  ref.value() = newPtr;
839  }
840 
841  } // endif( ..write mode.. )
842 #endif
843 
844 } // endtemplate <typename T> void actPtr( const Wt::Dbo::PtrRef<T> & ptrRef )
845 
846 template <class C>
847 template <typename T> void FormModel<C>::actCollection( const Wt::Dbo::CollectionRef<T> & ref )
848 {
849  (void)ref;
850 #ifdef STILL_WORKING_ON_THIS
851 #ifndef DEBUG_ACTIVITY
852  std::cout << __FILE__ << " " << __LINE__ << " "
853  << ref.value().size() << " "
854  << ref.joinName() << " "
855  << ref.joinId() << " "
856  << ref.literalJoinId() << " "
857  << (ref.type() == Wt::Dbo::RelationType::ManyToOne? std::string("mto"):std::string("mtm")) << " "
858  << ref.fkConstraints() << " "
859  << std::endl
860  ;
861 
862  for( auto item : ref.value() )
863  std::cout << __FILE__ << " " << __LINE__ << " "
864  << item.id() << " "
865  << std::endl
866  ;
867 #endif
868 
869  if( isReadMode )
870  {
871  /*
872  ** save all the ID numbers of all the items in this
873  ** collection.
874  **
875  */
876  std::cout << __FILE__ << ":" << __LINE__ << " " << ref.joinName() << std::endl;
877 // Wt::Dbo::collection<Wt::Dbo::ptr<T>> ids; // = new std::vector<int>();
878  std::vector<int> ids;
879  for( auto item : ref.value() )
880  ids.push_back( item.id() );
881 // m_collections[ref.joinName()] = ids;
882 
883  std::cout << __FILE__ << ":" << __LINE__ << " " << m_collections[ref.joinName()].size() << std::endl;
884 
885  setValue( field(ref.joinName()), boost::any(ids) );
886  }
887  else
888  {
889  }
890 #endif
891 
892 } // endtemplate <typename T> void actCollection( const Wt::Dbo::CollectionRef<T> & ref )
893 
894 
895 
896 
Wt::Dbo::ptr< Wtx::Crm::Activity::Item > add(const std::string &key, const Wt::WDate &date, Wtx::Dbo::Session &session)
Add an item to the lookup table.
Definition: Activity.cpp:28
Wtx::Dbo::Session * session()
Current Session.
virtual Wt::WString label(Wt::WFormModel::Field field) const
Get Field Label.
Definition: FormModel.cpp:137
witty extension library
Definition: Activity.h:51