Wtx ~ Wt Extension Library
WtxLib
TableViewManager_imp.h
1 
2 #include <Wt/WDialog.h>
3 #include <Wt/WApplication.h>
4 #include <Wt/WVBoxLayout.h>
5 #include <Wt/WPushButton.h>
6 #include <Wt/WTemplate.h>
7 #include <Wt/WText.h>
8 #include <Wt/WMessageBox.h>
9 
10 #include <Wtx/Core/Core.h>
11 #include <Wtx/Util/Util.h>
12 #include <Wtx/PopupMessage.h>
13 
14 template <class C, class D>
16 : Wt::WContainerWidget(),
17  m_session(s)
18 {
19  initHead();
20 
21 // auto tv = std::make_unique<Wtx::Dbo::TableView<C>>( s );
22 // m_tableView = tv.get();
23 
24 // m_lw-> addWidget( std::move(tv) );
25 //
26  initFoot();
27 
28 }
29 
30 template <class C, class D>
31 Wtx::Dbo::TableViewManager<C,D>::TableViewManager( const std::string & viewDefName, Wtx::Dbo::Session * s )
32 : Wt::WContainerWidget(),
33  m_session(s)
34 {
35  auto tv = std::make_unique<Wtx::Dbo::TableView<C>>( viewDefName, s );
36  m_tableView = tv.get();
37 
38  initHead();
39 
40  m_lw-> addWidget( std::move(tv),1 );
41 
42 // if( !tableView()-> viewDef().m_def.hideSearch )
43  m_tableView-> keyPressed().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_keyPressed );
44 
45  initFoot();
46 
47 }
48 
49 template <class C, class D>
51 : Wt::WContainerWidget(),
52  m_session(s)
53 {
54  auto tv = std::make_unique< Wtx::Dbo::TableView<C> >( viewDef, s );
55  m_tableView = tv.get();
56 
57  initHead();
58 
59  m_lw-> addWidget( std::move(tv), 1 );
60 
61  m_tableView-> clicked().connect( this, &TableViewManager<C,D>::on_clicked );
62  m_tableView-> doubleClicked().connect( this, &TableViewManager<C,D>::on_doubleClicked );
63 
64 // if( !tableView()-> viewDef().m_def.hideSearch )
65  m_tableView-> keyPressed().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_keyPressed );
66 
67  initFoot();
68 
69 }
70 
71 template <class C, class D>
72 Wtx::Dbo::TableViewManager<C,D>::TableViewManager( const std::string & viewDefName, const Wtx::TableViewDef::ViewDef & viewDef, Wtx::Dbo::Session * s )
73 : Wt::WContainerWidget(),
74  m_session(s)
75 {
76  auto tv = std::make_unique<Wtx::Dbo::TableView<C>>( viewDefName, viewDef, s );
77  m_tableView = tv.get();
78 
79  initHead();
80 
81  lw()-> addWidget( std::move(tv), 1 );
82 
83 // if( !tableView()-> viewDef().m_def.hideSearch )
84  {
85  m_tableView-> keyPressed ().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_keyPressed );
86  m_tableView-> keyWentDown ().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_keyWentDown );
87  }
88 
89  initFoot();
90 
91 }
92 
93 template <class C, class D>
95 {
96  auto u_lw = std::make_unique<Wt::WVBoxLayout>();
97  m_lw = u_lw.get();
98  setLayout( std::move(u_lw) );
99 
100 // lw()-> setContentsMargins( 0,23,0,23 );
101  lw()-> setContentsMargins( 0,0,0,0 );
102 
103  {
104  auto u_cw = std::make_unique<Wt::WContainerWidget>();
105  m_toolBar = u_cw.get();
106  lw()-> addWidget( std::move(u_cw) );
107  }
108 
109  {
110  auto u_cw = std::make_unique<Wt::WContainerWidget>();
111  m_buttonBar = u_cw.get();
112 
113  if( tableView() )
114  {
115  if( tableView()-> viewDef().m_def.allowAdd )
116  {
117  m_pbAdd = u_cw-> addNew<Wt::WPushButton>( Wt::WString::tr("Wtx.add") );
118  m_pbAdd-> addStyleClass("btn-success btn-xs");
119  m_pbAdd-> setMargin( "10px", Wt::Side::Right );
120  m_pbAdd-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_add_clicked );
121  m_pbAdd-> setObjectName( "tvAdd-" + tableView()-> viewDef().m_def.title );
122  }
123 
124  if( tableView()-> viewDef().m_def.allowChange )
125  {
126  m_pbEdit = u_cw-> addNew<Wt::WPushButton>( Wt::WString::tr("Wtx.edit") );
127  m_pbEdit-> addStyleClass("btn-success btn-xs");
128  m_pbEdit-> setMargin( "10px", Wt::Side::Right );
129  m_pbEdit-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_edit_clicked );
130  m_pbEdit-> setObjectName( "tvEdit-" + tableView()-> viewDef().m_def.title );
131  }
132 
133  if( tableView()-> viewDef().m_def.allowDelete )
134  {
135  m_pbDelete = u_cw-> addNew<Wt::WPushButton>( Wt::WString::tr("Wtx.delete") );
136  m_pbDelete-> addStyleClass("btn-success btn-xs");
137  m_pbDelete-> setMargin( "10px", Wt::Side::Right );
138  m_pbDelete-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::do_on_delete_clicked );
139  m_pbDelete-> setObjectName( "tvDelete-" + tableView()-> viewDef().m_def.title );
140  }
141 
142  if( tableView()-> viewDef().m_def.allowExport )
143  {
144  m_pbExport = u_cw-> addNew<Wt::WPushButton>( Wt::WString::tr("Wtx.export") );
145  m_pbExport-> addStyleClass("btn-success btn-xs");
146  m_pbExport-> setMargin( "10px", Wt::Side::Right );
147  m_pbExport-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_export_clicked );
148  m_pbExport-> setObjectName( "tvExport-" + tableView()-> viewDef().m_def.title );
149  }
150 
151  if( tableView()-> viewDef().m_def.allowPrint )
152  {
153  m_pbPrint = u_cw-> addNew<Wt::WPushButton>( Wt::WString::tr("Wtx.print") );
154  m_pbPrint-> addStyleClass("btn-success btn-xs");
155  m_pbPrint-> setMargin( "10px", Wt::Side::Right );
156  m_pbPrint-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_print_clicked );
157  m_pbPrint-> setObjectName( "tvPrint-" + tableView()-> viewDef().m_def.title );
158  }
159 
160  if( tableView()-> viewDef().m_def.additional != "" )
161  {
162  for( auto add : Wtx::Core::split( tableView()-> viewDef().m_def.additional, ',' ) )
163  {
164  auto pb = u_cw-> addNew<Wt::WPushButton>( add );
165  pb-> addStyleClass("btn-success btn-xs");
166  pb-> setMargin( "10px", Wt::Side::Right );
167  pb-> setObjectName( "tvAdditional-" + add );
168 // pb-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_additional_clicked );
169  pb-> clicked().connect( [=]()
170  {
171  m_additionalClicked.emit( pb-> text().toUTF8() );
172  });
173  }
174  }
175 
176  }
177 
178  lw()-> addWidget( std::move(u_cw) );
179 
180  }
181 
182 #ifdef NEVER
183  {
184  auto u_cw = std::make_unique<Wt::WContainerWidget>();
185  u_cw-> addNew<Wt::WPushButton>("filter");
186 // u_cw-> clicked().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_filter_clicked );
187  lw()-> addWidget( std::move(u_cw) );
188  }
189 #endif
190 
191 }
192 
193 template <class C, class D>
195 {
196  m_readOnly = value;
197 
198  if( m_pbAdd )
199  m_pbAdd-> setEnabled( !value );
200 
201  if( m_pbEdit )
202  m_pbEdit-> setEnabled( !value );
203 
204  if( m_pbDelete )
205  m_pbDelete-> setEnabled( !value );
206 
207  if( m_pbExport )
208  m_pbExport-> setEnabled( !value );
209 
210  if( m_pbPrint )
211  m_pbPrint-> setEnabled( !value );
212 
213 }
214 
215 template <class C, class D>
216 void Wtx::Dbo::TableViewManager<C,D>::setDialogSize( Wt::WLength width, Wt::WLength height )
217 {
218  m_dialogWidth = width;
219  m_dialogHeight = height;
220 }
221 
222 template <class C, class D>
224 {
225 
226 // if( tableView()-> viewDef().m_def.allowSearch )
227  {
228  auto u_searchWidget = std::make_unique<SearchWidget>( tableView()-> viewDef().m_def.hideSearch );
229  m_searchWidget = u_searchWidget.get();
230  m_searchWidget-> setObjectName( "tvSearchWidget-" + Wtx::replace( tableView()-> viewDef().m_def.title, " ", "") );
231 
232  if( tableView()-> viewDef().m_def.hideSearch )
233  searchWidget()-> setHidden(true);
234 
235  searchWidget()-> m_filter-> enterPressed().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_filterEntered );
236  searchWidget()-> m_filter-> blurred().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_filterEntered );
237  searchWidget()-> m_filter-> textInput().connect( this, &Wtx::Dbo::TableViewManager<C,D>::on_filterTyped );
238  lw()-> addWidget( std::move(u_searchWidget) );
239  }
240 
241  if( tableView()-> viewDef().m_def.showFooter )
242  {
243  auto u_footerWidget = std::make_unique<FooterWidget>();
244  m_footerWidget = u_footerWidget.get();
245  lw()-> addWidget( std::move(u_footerWidget) );
246  }
247 
248  if( tableView()-> viewDef().m_def.showPrevNext )
249  {
250  auto u_prevNextWidget = std::make_unique< PrevNextWidget >();
251  m_prevNextWidget = u_prevNextWidget.get();
252  lw()-> addWidget( std::move(u_prevNextWidget) );
253 
254  auto _move = [=]( int row )
255  {
256  auto newIndex = tableView()-> model()-> index( row, 0 );
257 
258  tableView()-> select( newIndex );
259  tableView()-> scrollTo( newIndex );
260 
261  m_prevNextWidget-> setRow( row, tableView()-> model()-> rowCount() );
262 
263  on_clicked( newIndex, Wt::WMouseEvent() );
264 
265  };
266 
267  m_prevNextWidget-> m_top->
268  clicked().connect( [=]()
269  {
270  if( tableView()-> selectedIndexes().size() == 0 )
271  return;
272 
273  _move( 0 );
274 
275  });
276 
277  m_prevNextWidget-> m_prev->
278  clicked().connect( [=]()
279  {
280  if( tableView()-> selectedIndexes().size() == 0 )
281  return;
282 
283  auto index = *(tableView()-> selectedIndexes().begin());
284 
285  if( index.row() == 0 )
286  return;
287 
288  _move( index.row()-1 );
289 
290  });
291 
292  m_prevNextWidget-> m_next->
293  clicked().connect( [=]()
294  {
295  if( tableView()-> selectedIndexes().size() == 0 )
296  return;
297 
298  auto index = *(tableView()-> selectedIndexes().begin());
299 
300  if( index.row() == tableView()-> model()-> rowCount() )
301  return;
302 
303  _move( index.row()+1 );
304 
305  });
306 
307  m_prevNextWidget-> m_bottom->
308  clicked().connect( [=]()
309  {
310  if( tableView()-> selectedIndexes().size() == 0 )
311  return;
312 
313  _move( tableView()-> model()-> rowCount()-1 );
314 
315  });
316 
317 
318  }
319 
320  updateFooter();
321 }
322 
323 template <class C, class D>
325 {
326  Wt::Dbo::ptr<C> item;
327 
328  {
329  Wt::Dbo::Transaction t(*session());
330  item = session()-> template addNew<C>("new item");
331  }
332 
333  {
334  Wt::Dbo::Transaction t(*session());
335  item.modify()-> keyField().setValue( Wt::WString("new item {1}").arg( item.id() ).toUTF8() );
336  }
337 
338  tableView()-> refresh();
339 
340  m_addClicked.emit( item );
341 
342 } // endvoid Wtx::Dbo::TableViewManager<C,D>::on_add_clicked()
343 
344 template <class C, class D>
346 {
347 
348  if( m_tableView-> model()-> rowCount() == 1 )
349  {
350  m_editClicked.emit( tableView()-> model()-> stableResultRow( 0 ) );
351 
352  auto index = tableView()-> model()-> index( 0, 0 );
353  if( m_openDetail )
354  openDetail( index );
355 
356  return;
357  }
358 
359  if( m_tableView-> selectedIndexes().size() != 1 )
360  {
361  auto dialog = addChild( std::make_unique<Wt::WDialog>("alert") );
362  dialog-> setClosable(true);
363  dialog-> rejectWhenEscapePressed(true);
364  dialog-> setResizable(false);
365  dialog-> setMinimumSize( m_dialogWidth, m_dialogHeight );
366  dialog-> setMaximumSize( m_dialogWidth, m_dialogHeight );
367  dialog-> resize( m_dialogWidth, m_dialogHeight );
368  dialog-> addStyleClass("detail-form");
369  dialog-> contents()-> addNew<Wt::WText>("You must select an item to edit");
370  dialog-> show();
371 
372  return;
373  }
374 
375  auto index = *m_tableView-> selectedIndexes().begin();
376  m_editClicked.emit( tableView()-> model()-> stableResultRow( index.row() ) );
377 
378  if( m_openDetail )
379  openDetail( index );
380 
381 }
382 
383 template <class C, class D>
385 {
386 
387  if( m_tableView-> selectedIndexes().size() != 1 )
388  {
389  std::string message = tableView()-> viewDef().m_def.deleteMessage;
390 
391  if( message == "" )
392  message = "You must select an item to delete";
393 
394  Wtx::PopupMessage::show( message );
395  return;
396  }
397 
398  auto selectedItem =
399  m_tableView-> item( *m_tableView-> selectedIndexes().begin() );
400 
401  if( m_deleteClicked.isConnected() )
402  {
403  m_deleteClicked.emit( selectedItem );
404  return;
405  }
406 
407  if( !noask )
408  {
409  auto message =
410  Wt::WString("Are you sure you want to delete item<br /> '{1}'?")
411  .arg( m_tableView-> item( *m_tableView-> selectedIndexes().begin() )-> keyField().value() )
412  .toUTF8()
413  ;
414 
415  if( Wt::WMessageBox::show( "Alert", message, Wt::StandardButton::Yes | Wt::StandardButton::No ) != Wt::StandardButton::Yes )
416  return;
417  }
418 
419  for( auto index : m_tableView-> selectedIndexes() )
420  {
421  auto item = m_tableView-> item( index );
422 
423  Wt::Dbo::Transaction t(*session());
424  item.remove();
425 
426  } // endfor( auto index : m_tableView-> selectedIndexes() )
427 
428  m_tableView-> refresh();
429 
430 } // endvoid Wtx::Dbo::TableViewManager<C,D>::on_delete_clicked()
431 
432 template <class C, class D>
434 : m_autohide(autohide)
435 {
436  auto u_lw = std::make_unique<Wt::WHBoxLayout>();
437  m_lw = u_lw.get();
438  setLayout( std::move(u_lw) );
439 
440  lw()-> addWidget( std::move( std::make_unique<Wt::WText>( "Search:" ) ) );
441 
442  auto u_filter = std::make_unique<Wt::WLineEdit>();
443  m_filter = u_filter.get();
444  lw()-> addWidget( std::move(u_filter), 1 );
445 
446 // lw()-> addWidget( std::move( std::make_unique<Wt::WPushButton>("clear") ), 1 );
447 
448 } // endWtx::Dbo::TableViewManager<C,D>::SearchWidget::SearchWidget()
449 
450 
451 
452 template <class C, class D>
454 {
455  auto templt = addNew<Wt::WTemplate>
456  (
457  "<div>"
458  " <div style=\"float:left; width:200px;\"> ${left} </div>"
459  " <div style=\"margin:0 auto; width:200px;\"> ${center} </div>"
460  " <div style=\"float:right; width:200px;\"> ${right} </div>"
461  "</div>"
462  );
463 
464  auto u_rowCounts = std::make_unique<Wt::WText>();
465  m_rowCounts = u_rowCounts.get();
466  templt-> bindWidget( "left", std::move(u_rowCounts) );
467 
468 /*
469 ** BUGBUG: the following two do not lay out properly. they
470 ** should be all on one line.
471 **
472 */
473  auto u_center = std::make_unique<Wt::WText>("");
474  m_center = u_center.get();
475  templt-> bindWidget( "center", std::move(u_center) );
476 
477  auto u_right = std::make_unique<Wt::WText>("");
478  m_right = u_right.get();
479  templt-> bindWidget( "right", std::move(u_right) );
480 
481 // m_rowCounts = templt-> bindNew<Wt::WText>("left");
482  updateWidgets();
483 }
484 
485 template <class C, class D>
487 {
488  m_queryRowCount = filtered;
489  m_totalRowCount = total;
490  updateWidgets();
491 }
492 
493 template <class C, class D>
495 {
496  m_queryRowCount = value;
497  updateWidgets();
498 }
499 
500 template <class C, class D>
502 {
503  m_totalRowCount = value;
504  updateWidgets();
505 }
506 
507 template <class C, class D>
509 {
510  if( m_totalRowCount > 0 )
511  {
512  m_rowCounts->
513  setText
514  (
515  Wt::WString("{1} of {2}")
516  .arg( m_queryRowCount )
517  .arg( m_totalRowCount )
518  );
519  }
520  else
521  {
522  m_rowCounts->
523  setText
524  (
525  Wt::WString("{1} items")
526  .arg( m_queryRowCount )
527  );
528  }
529 }
530 
531 
532 
533 
534 
535 template <class C, class D>
537 {
538  auto _addNew = [=]( const char * text )
539  {
540  auto pb = addNew< Wt::WPushButton >( text );
541  pb-> addStyleClass( "btn-success" );
542  pb-> addStyleClass( "btn-xs" );
543 
544  return pb;
545  };
546 
547  m_top = _addNew( "<<" );
548  m_prev = _addNew( "<" );
549  m_text = addNew< Wt::WText >( " " );
550  m_next = _addNew( ">" );
551  m_bottom = _addNew( ">>" );
552 
553 }
554 
555 template <class C, class D>
557 {
558  m_text->
559  setText
560  (
561  Wt::WString( " {1} of {2} " )
562  .arg( row )
563  .arg( rowCount )
564  );
565 }
566 
567 
568 
569 
570 
571 
572 
573 
574 
575 
576 
577 template <class C, class D>
578 Wt::WContainerWidget * Wtx::Dbo::TableViewManager<C,D>::toolBar()
579 {
580  return m_toolBar;
581 }
582 
583 template <class C, class D>
584 Wt::WContainerWidget * Wtx::Dbo::TableViewManager<C,D>::buttonBar()
585 {
586  return m_buttonBar;
587 }
588 
589 
590 template <class C, class D>
591 void Wtx::Dbo::TableViewManager<C,D>::on_keyPressed( Wt::WKeyEvent keyEvent )
592 {
593 // std::cout << __FILE__ << ":" << __LINE__ << " " << tableView()-> viewDef().m_def.title << std::endl;
594 
595  if( !tableView()-> viewDef().m_def.allowSearch )
596  return;
597 
598  searchWidget()-> setFilter( keyEvent.text() );
599 
600  if( keyEvent.text() == "" )
601  {
602  m_tableView-> setQuery();
603  updateFooter();
604  }
605 }
606 
607 template <class C, class D>
608 void Wtx::Dbo::TableViewManager<C,D>::on_keyWentDown( Wt::WKeyEvent keyEvent )
609 {
610  std::cout << __FILE__ << ":" << __LINE__ << " " << tableView()-> viewDef().m_def.title << std::endl;
611 
612 }
613 
614 template <class C, class D>
615 const std::string & Wtx::Dbo::TableViewManager<C,D>::filter() const
616 {
617  return m_tableView-> filter();
618 }
619 
620 template <class C, class D>
621 void Wtx::Dbo::TableViewManager<C,D>::SearchWidget::setFilter( const Wt::WString & value )
622 {
623  setHidden( false );
624 
625  if( !m_autohide );
626  m_filter-> setFocus(true);
627 
628  m_filter-> setText( /* m_filter-> text() + */ value );
629 
630  if( value == "" && m_autohide )
631  setHidden( true );
632 }
633 
634 template <class C, class D>
635 void Wtx::Dbo::TableViewManager<C,D>::SearchWidget::setSearch( const Wt::WString & value )
636 {
637  setFilter( value );
638  m_filter-> enterPressed().emit();
639 // on_filterEntered();
640 }
641 
642 template <class C, class D>
643 void Wtx::Dbo::TableViewManager<C,D>::SearchWidget::setToolTip( const Wt::WString & value )
644 {
645  m_filter-> setToolTip( value );
646 }
647 
648 
649 template <class C, class D>
651 {
652  if( searchWidget()-> m_filter-> text() == "" && tableView()-> viewDef().m_def.hideSearch )
653  searchWidget()-> setHidden(true);
654 
655  m_tableView-> setQuery( searchWidget()-> m_filter-> text().toUTF8() );
656 
657  if( tableView()-> viewDef().m_def.hideSearch )
658  m_tableView-> setFocus(true);
659 }
660 
661 template <class C, class D>
663 {
664  m_tableView-> setQuery( searchWidget()-> m_filter-> text().toUTF8() );
665  updateFooter();
666 }
667 
668 
669 template <class C, class D>
671 {
672 // std::cout << __FILE__ << ":" << __LINE__ << " "
673 // << searchWidget()-> m_filter-> text() << " "
674 // << tableView()-> queryRowCount() << " "
675 // << tableView()-> totalRowCount() << " "
676 // << std::endl
677 // ;
678 
679  if( m_footerWidget )
680  {
681  m_footerWidget-> setRowCount( tableView()-> queryRowCount(), tableView()-> totalRowCount() );
682  }
683 
684 }
685 
686 
687 
688 
689 template <class C, class D>
690 void Wtx::Dbo::TableViewManager<C,D>::on_clicked( Wt::WModelIndex index, Wt::WMouseEvent event )
691 {
692  if( !index.isValid() )
693  return;
694 
695  if( m_prevNextWidget )
696  {
697  m_prevNextWidget-> setRow( index.row(), tableView()-> model()-> rowCount() );
698  }
699 
700 // tableView()-> select( index );
701 
702  Wt::WApplication::instance()-> processEvents();
703 
704  m_itemClicked.emit
705  (
706  tableView()->
707  model()->
708  stableResultRow( index.row() )
709  );
710 
711 }
712 
713 template <class C, class D>
715 {
716  if( !detail-> beforeUpdate() )
717  return false;
718 
719  detail-> updateModel();
720 
721  if( !detail-> afterUpdate() )
722  return false;
723 
724  if( !detail-> beforeAccept() )
725  return false;
726 
727  detail-> formModel()-> accept();
728 
729  if( !detail-> afterAccept() )
730  return false;
731 
732  if( detail-> refreshTableOnSave() )
733  {
734  tableView()-> refresh();
735 // tableView()-> refreshSelected();
736  }
737 
738  m_itemSaved.emit( detail-> formModel()-> item() );
739 
740  return true;
741 }
742 
743 template <class C, class D>
745 {
746 }
747 
748 template <class C, class D>
749 D * Wtx::Dbo::TableViewManager<C,D>::openDetail( Wt::WModelIndex index )
750 {
751  return openDetail( tableView()-> model()-> stableResultRow( index.row() ) );
752 
753 }
754 
755 template <class C, class D>
756 D * Wtx::Dbo::TableViewManager<C,D>::openDetail( typename C::Ptr item )
757 {
758  auto dialog = addChild( std::make_unique<Wt::WDialog>("Edit") );
759  dialog-> setClosable(true);
760  dialog-> rejectWhenEscapePressed(true);
761  dialog-> setResizable(false);
762  dialog-> setMinimumSize( m_dialogWidth, m_dialogHeight );
763  dialog-> setMaximumSize( m_dialogWidth, m_dialogHeight );
764  dialog-> resize( m_dialogWidth, m_dialogHeight );
765  dialog-> addStyleClass("detail-form");
766 
767  auto u_lw = std::make_unique<Wt::WVBoxLayout>();
768  auto lw = u_lw.get();
769  dialog-> contents()-> setOverflow( Wt::Overflow::Auto );
770  dialog-> contents()-> setLayout( std::move(u_lw) );
771 
772 #ifdef NO_LAYOUT
773 
774  m_buttonTemplt = dynamic_cast<Wt::WTemplate*>(dialog-> contents()-> addNew<Wt::WTemplate>
775  (
776  "<div>"
777  " ${submit class=\"btn-success btn-xs\"}"
778  " ${close class=\"btn-danger btn-xs\"}"
779  " ${delete class=\"btn-success btn-xs\"}"
780  " ${print class=\"btn-success btn-xs\"}"
781  " ${unlock class=\"btn-success btn-xs\"}"
782  " ${additional}<br />"
783  " ${toolbar}"
784  "</div>"
785  ));
786 
787  auto detail = dialog-> contents()-> addNew<D>( item );
788 
789 #else
790 
791  auto u_buttonTemplt = std::make_unique<Wt::WTemplate>
792  (
793  "<div>"
794  " ${submit class=\"btn-success btn-xs\"}"
795  " ${close class=\"btn-danger btn-xs\"}"
796  " ${delete class=\"btn-success btn-xs\"}"
797  " ${print class=\"btn-success btn-xs\"}"
798  " ${unlock class=\"btn-success btn-xs\"}"
799  " ${additional}<br />"
800  " ${toolbar}"
801  "</div>"
802  );
803  m_buttonTemplt = u_buttonTemplt.get();
804  lw-> addWidget( std::move(u_buttonTemplt) );
805 
806  auto u_detail = std::make_unique<D>( item );
807  auto detail = u_detail.get();
808  lw-> addWidget( std::move(u_detail) );
809 
810 #endif
811 
812  detail-> doSave().connect( [=]()
813  {
814  doSave( detail );
815  });
816 
817  detail-> doClose().connect( [=]()
818  {
819  dialog-> accept();
820  });
821 
822  detail-> doDeleteItem().connect( [=]( bool noask )
823  {
824  on_delete_clicked( noask );
825  dialog-> accept();
826  });
827 
828  if( detail-> allowChange()
829  || tableView()-> viewDef().m_def.allowChange )
830  {
831  auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>("submit","submit");
832  button-> setObjectName( "dlg-submit" );
833  button-> clicked()
834  .connect( [=]()
835  {
836  if( doSave( detail ) )
837  dialog-> accept();
838 
839  });
840  }
841  else
842  {
843  m_buttonTemplt-> bindEmpty("submit");
844  }
845 
846 
847  if( detail-> allowChange()
848  || tableView()-> viewDef().m_def.allowChange )
849  {
850  auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>("close","close");
851  button-> setObjectName( "dlg-close" );
852  button-> clicked()
853  .connect( [=]()
854  {
855  dialog-> reject();
856  });
857  }
858  else
859  {
860  m_buttonTemplt-> bindEmpty("close");
861  }
862 
863  if( detail-> allowDelete()
864 // || tableView()-> viewDef().m_def.allowDelete
865  )
866  {
867  auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>("delete","delete");
868  button-> setObjectName( "dlg-delete" );
869  button-> clicked()
870  .connect( [=]()
871  {
872  detail-> onDelete();
873  });
874  }
875  else
876  {
877  m_buttonTemplt-> bindEmpty("delete");
878  }
879 
880  if( detail-> allowPrint()
881  || tableView()-> viewDef().m_def.allowPrint )
882  {
883  auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>("print","print");
884  button-> setObjectName( "dlg-print" );
885  button-> clicked()
886  .connect( [=]()
887  {
888  detail-> onPrint();
889  });
890  }
891  else
892  {
893  m_buttonTemplt-> bindEmpty("print");
894  }
895 
896  if( detail-> allowUnlock()
897  || tableView()-> viewDef().m_def.allowUnlock )
898  {
899  auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>("unlock","unlock");
900  button-> setObjectName( "dlg-unlock" );
901  button-> clicked()
902  .connect( [=]()
903  {
904  detail-> onUnlock();
905  });
906  }
907  else
908  {
909  m_buttonTemplt-> bindEmpty("unlock");
910  }
911 
912  m_buttonTemplt-> bindEmpty( "toolbar" );
913 
914  auto _doAdditional = [=]( const std::string & additionals )
915  {
916  auto adds = Wtx::Core::split( additionals, ',' );
917  if( adds.size() == 1 )
918  {
919  auto pb = m_buttonTemplt-> bindNew<Wt::WPushButton>( "additional", adds.at(0) );
920  pb-> setObjectName( "dlg-" + adds.at(0) );
921  pb-> setMargin( "5px", Wt::Side::Left | Wt::Side::Right );
922  pb-> addStyleClass( "btn-success" );
923  pb-> addStyleClass( "btn-xs" );
924  pb->
925  clicked().connect( [=]()
926  {
927  detail-> onAdditional( adds.at(0) );
928  });
929  return;
930  }
931 
932  auto cwAdditional = m_buttonTemplt-> bindNew<Wt::WContainerWidget>("additional");
933  cwAdditional-> setMargin( "10px" );
934  for( auto a : Wtx::Core::split( additionals, ',' ) )
935  {
936  auto pb = cwAdditional-> addNew<Wt::WPushButton>(a);
937  pb-> setObjectName( "dlg-" + a );
938  pb-> setMargin( "5px", Wt::Side::Left | Wt::Side::Right );
939  pb-> addStyleClass( "btn-success" );
940  pb-> addStyleClass( "btn-xs" );
941  pb-> clicked().connect( [=]()
942  {
943  detail-> onAdditional( a );
944  });
945  }
946 
947  };
948 
949 
950  _doAdditional( detail-> additional() );
951 // BUGBUG _doAdditional( tableView()-> viewDef().m_def.additional );
952 
953 #ifdef NEVER
954  if( detail-> additional() != ""
955  || tableView()-> viewDef().m_def.additional != "" )
956  {
957  m_buttonTemplt-> bindNew<Wt::WPushButton>( "additional", detail-> additional() )->
958  clicked().connect( [=]()
959  {
960  detail-> onAdditional();
961  });
962  }
963  else
964  {
965  m_buttonTemplt-> bindEmpty( "additional" );
966  }
967 #endif
968 
969  dialog-> setWindowTitle
970  (
971  Wt::WString("{1}:{2}")
972  .arg( item.id() )
973  .arg( detail-> templateName() )
974  );
975 
976  dialog->
977  finished().connect( [=]( Wt::DialogCode code )
978  {
979  removeChild( dialog );
980  });
981 
982  dialog-> show();
983 
984  return detail;
985 
986 } // endD * Wtx::Dbo::TableViewManager<C,D>::openDetail( typename C::Ptr item )
987 
988 template <class C, class D>
989 void Wtx::Dbo::TableViewManager<C,D>::on_doubleClicked( Wt::WModelIndex index, Wt::WMouseEvent event )
990 {
991  m_doubleClicked.emit( tableView()-> model()-> stableResultRow( index.row() ) );
992 
993  if( m_openDetail )
994  openDetail( index );
995 }
996 
997 template <class C, class D>
999 {
1000  m_exportClicked.emit( tableView()-> queryValue() );
1001 }
1002 
1003 template <class C, class D>
1005 {
1006  m_printClicked.emit( tableView()-> filter() );
1007 }
1008 
1009 template <class C, class D>
1011 {
1012 // m_additionalClicked.emit();
1013 }
1014 
1015 template <class C, class D>
1017 {
1018  std::cout << __FILE__ << ":" << __LINE__ << " on_unlock" << std::endl;
1019 }
1020 
1021 
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.
Table View Definition.
Definition: TableViewDef.h:171
std::string replace(const std::string &string, const std::string &before, const std::string &after)
Replace a String.
Definition: Util.cpp:480