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> 8 #include <Wt/WMessageBox.h> 10 #include <Wtx/Core/Core.h> 11 #include <Wtx/Util/Util.h> 12 #include <Wtx/PopupMessage.h> 14 template <
class C,
class D>
16 :
Wt::WContainerWidget(),
30 template <
class C,
class D>
32 :
Wt::WContainerWidget(),
35 auto tv = std::make_unique<Wtx::Dbo::TableView<C>>( viewDefName, s );
36 m_tableView = tv.get();
40 m_lw-> addWidget( std::move(tv),1 );
49 template <
class C,
class D>
51 :
Wt::WContainerWidget(),
54 auto tv = std::make_unique< Wtx::Dbo::TableView<C> >( viewDef, s );
55 m_tableView = tv.get();
59 m_lw-> addWidget( std::move(tv), 1 );
61 m_tableView-> clicked().connect(
this, &TableViewManager<C,D>::on_clicked );
62 m_tableView-> doubleClicked().connect(
this, &TableViewManager<C,D>::on_doubleClicked );
71 template <
class C,
class D>
73 :
Wt::WContainerWidget(),
76 auto tv = std::make_unique<Wtx::Dbo::TableView<C>>( viewDefName, viewDef, s );
77 m_tableView = tv.get();
81 lw()-> addWidget( std::move(tv), 1 );
93 template <
class C,
class D>
96 auto u_lw = std::make_unique<Wt::WVBoxLayout>();
98 setLayout( std::move(u_lw) );
101 lw()-> setContentsMargins( 0,0,0,0 );
104 auto u_cw = std::make_unique<Wt::WContainerWidget>();
105 m_toolBar = u_cw.get();
106 lw()-> addWidget( std::move(u_cw) );
110 auto u_cw = std::make_unique<Wt::WContainerWidget>();
111 m_buttonBar = u_cw.get();
115 if( tableView()-> viewDef().m_def.allowAdd )
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 );
121 m_pbAdd-> setObjectName(
"tvAdd-" + tableView()-> viewDef().m_def.title );
124 if( tableView()-> viewDef().m_def.allowChange )
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 );
130 m_pbEdit-> setObjectName(
"tvEdit-" + tableView()-> viewDef().m_def.title );
133 if( tableView()-> viewDef().m_def.allowDelete )
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 );
139 m_pbDelete-> setObjectName(
"tvDelete-" + tableView()-> viewDef().m_def.title );
142 if( tableView()-> viewDef().m_def.allowExport )
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 );
148 m_pbExport-> setObjectName(
"tvExport-" + tableView()-> viewDef().m_def.title );
151 if( tableView()-> viewDef().m_def.allowPrint )
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 );
157 m_pbPrint-> setObjectName(
"tvPrint-" + tableView()-> viewDef().m_def.title );
160 if( tableView()-> viewDef().m_def.additional !=
"" )
162 for(
auto add : Wtx::Core::split( tableView()-> viewDef().m_def.additional,
',' ) )
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 );
169 pb-> clicked().connect( [=]()
171 m_additionalClicked.emit( pb-> text().toUTF8() );
178 lw()-> addWidget( std::move(u_cw) );
184 auto u_cw = std::make_unique<Wt::WContainerWidget>();
185 u_cw-> addNew<Wt::WPushButton>(
"filter");
187 lw()-> addWidget( std::move(u_cw) );
193 template <
class C,
class D>
199 m_pbAdd-> setEnabled( !value );
202 m_pbEdit-> setEnabled( !value );
205 m_pbDelete-> setEnabled( !value );
208 m_pbExport-> setEnabled( !value );
211 m_pbPrint-> setEnabled( !value );
215 template <
class C,
class D>
218 m_dialogWidth = width;
219 m_dialogHeight = height;
222 template <
class C,
class D>
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,
" ",
"") );
232 if( tableView()-> viewDef().m_def.hideSearch )
233 searchWidget()-> setHidden(
true);
238 lw()-> addWidget( std::move(u_searchWidget) );
241 if( tableView()-> viewDef().m_def.showFooter )
243 auto u_footerWidget = std::make_unique<FooterWidget>();
244 m_footerWidget = u_footerWidget.get();
245 lw()-> addWidget( std::move(u_footerWidget) );
248 if( tableView()-> viewDef().m_def.showPrevNext )
250 auto u_prevNextWidget = std::make_unique< PrevNextWidget >();
251 m_prevNextWidget = u_prevNextWidget.get();
252 lw()-> addWidget( std::move(u_prevNextWidget) );
254 auto _move = [=](
int row )
256 auto newIndex = tableView()-> model()-> index( row, 0 );
258 tableView()-> select( newIndex );
259 tableView()-> scrollTo( newIndex );
261 m_prevNextWidget-> setRow( row, tableView()-> model()-> rowCount() );
263 on_clicked( newIndex, Wt::WMouseEvent() );
267 m_prevNextWidget-> m_top->
268 clicked().connect( [=]()
270 if( tableView()-> selectedIndexes().size() == 0 )
277 m_prevNextWidget-> m_prev->
278 clicked().connect( [=]()
280 if( tableView()-> selectedIndexes().size() == 0 )
283 auto index = *(tableView()-> selectedIndexes().begin());
285 if( index.row() == 0 )
288 _move( index.row()-1 );
292 m_prevNextWidget-> m_next->
293 clicked().connect( [=]()
295 if( tableView()-> selectedIndexes().size() == 0 )
298 auto index = *(tableView()-> selectedIndexes().begin());
300 if( index.row() == tableView()-> model()-> rowCount() )
303 _move( index.row()+1 );
307 m_prevNextWidget-> m_bottom->
308 clicked().connect( [=]()
310 if( tableView()-> selectedIndexes().size() == 0 )
313 _move( tableView()-> model()-> rowCount()-1 );
323 template <
class C,
class D>
326 Wt::Dbo::ptr<C> item;
329 Wt::Dbo::Transaction t(*
session());
330 item =
session()->
template addNew<C>(
"new item");
334 Wt::Dbo::Transaction t(*
session());
335 item.modify()-> keyField().setValue( Wt::WString(
"new item {1}").arg( item.id() ).toUTF8() );
338 tableView()-> refresh();
340 m_addClicked.emit( item );
344 template <
class C,
class D>
348 if( m_tableView-> model()-> rowCount() == 1 )
350 m_editClicked.emit( tableView()-> model()-> stableResultRow( 0 ) );
352 auto index = tableView()-> model()-> index( 0, 0 );
359 if( m_tableView-> selectedIndexes().size() != 1 )
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");
375 auto index = *m_tableView-> selectedIndexes().begin();
376 m_editClicked.emit( tableView()-> model()-> stableResultRow( index.row() ) );
383 template <
class C,
class D>
387 if( m_tableView-> selectedIndexes().size() != 1 )
389 std::string message = tableView()-> viewDef().m_def.deleteMessage;
392 message =
"You must select an item to delete";
394 Wtx::PopupMessage::show( message );
399 m_tableView-> item( *m_tableView-> selectedIndexes().begin() );
401 if( m_deleteClicked.isConnected() )
403 m_deleteClicked.emit( selectedItem );
410 Wt::WString(
"Are you sure you want to delete item<br /> '{1}'?")
411 .arg( m_tableView-> item( *m_tableView-> selectedIndexes().begin() )-> keyField().value() )
415 if( Wt::WMessageBox::show(
"Alert", message, Wt::StandardButton::Yes | Wt::StandardButton::No ) != Wt::StandardButton::Yes )
419 for(
auto index : m_tableView-> selectedIndexes() )
421 auto item = m_tableView-> item( index );
423 Wt::Dbo::Transaction t(*
session());
428 m_tableView-> refresh();
432 template <
class C,
class D>
434 : m_autohide(autohide)
436 auto u_lw = std::make_unique<Wt::WHBoxLayout>();
438 setLayout( std::move(u_lw) );
440 lw()-> addWidget( std::move( std::make_unique<Wt::WText>(
"Search:" ) ) );
442 auto u_filter = std::make_unique<Wt::WLineEdit>();
443 m_filter = u_filter.get();
444 lw()-> addWidget( std::move(u_filter), 1 );
452 template <
class C,
class D>
455 auto templt = addNew<Wt::WTemplate>
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>" 464 auto u_rowCounts = std::make_unique<Wt::WText>();
465 m_rowCounts = u_rowCounts.get();
466 templt-> bindWidget(
"left", std::move(u_rowCounts) );
473 auto u_center = std::make_unique<Wt::WText>(
"");
474 m_center = u_center.get();
475 templt-> bindWidget(
"center", std::move(u_center) );
477 auto u_right = std::make_unique<Wt::WText>(
"");
478 m_right = u_right.get();
479 templt-> bindWidget(
"right", std::move(u_right) );
485 template <
class C,
class D>
488 m_queryRowCount = filtered;
489 m_totalRowCount = total;
493 template <
class C,
class D>
496 m_queryRowCount = value;
500 template <
class C,
class D>
503 m_totalRowCount = value;
507 template <
class C,
class D>
510 if( m_totalRowCount > 0 )
515 Wt::WString(
"{1} of {2}")
516 .arg( m_queryRowCount )
517 .arg( m_totalRowCount )
525 Wt::WString(
"{1} items")
526 .arg( m_queryRowCount )
535 template <
class C,
class D>
538 auto _addNew = [=](
const char * text )
540 auto pb = addNew< Wt::WPushButton >( text );
541 pb-> addStyleClass(
"btn-success" );
542 pb-> addStyleClass(
"btn-xs" );
547 m_top = _addNew(
"<<" );
548 m_prev = _addNew(
"<" );
549 m_text = addNew< Wt::WText >(
" " );
550 m_next = _addNew(
">" );
551 m_bottom = _addNew(
">>" );
555 template <
class C,
class D>
561 Wt::WString(
" {1} of {2} " )
577 template <
class C,
class D>
583 template <
class C,
class D>
590 template <
class C,
class D>
595 if( !tableView()-> viewDef().m_def.allowSearch )
598 searchWidget()-> setFilter( keyEvent.text() );
600 if( keyEvent.text() ==
"" )
602 m_tableView-> setQuery();
607 template <
class C,
class D>
610 std::cout << __FILE__ <<
":" << __LINE__ <<
" " << tableView()-> viewDef().m_def.title << std::endl;
614 template <
class C,
class D>
617 return m_tableView-> filter();
620 template <
class C,
class D>
626 m_filter-> setFocus(
true);
628 m_filter-> setText( value );
630 if( value ==
"" && m_autohide )
634 template <
class C,
class D>
638 m_filter-> enterPressed().emit();
642 template <
class C,
class D>
645 m_filter-> setToolTip( value );
649 template <
class C,
class D>
652 if( searchWidget()-> m_filter-> text() ==
"" && tableView()-> viewDef().m_def.hideSearch )
653 searchWidget()-> setHidden(
true);
655 m_tableView-> setQuery( searchWidget()-> m_filter-> text().toUTF8() );
657 if( tableView()-> viewDef().m_def.hideSearch )
658 m_tableView-> setFocus(
true);
661 template <
class C,
class D>
664 m_tableView-> setQuery( searchWidget()-> m_filter-> text().toUTF8() );
669 template <
class C,
class D>
681 m_footerWidget-> setRowCount( tableView()-> queryRowCount(), tableView()-> totalRowCount() );
689 template <
class C,
class D>
692 if( !index.isValid() )
695 if( m_prevNextWidget )
697 m_prevNextWidget-> setRow( index.row(), tableView()-> model()-> rowCount() );
702 Wt::WApplication::instance()-> processEvents();
708 stableResultRow( index.row() )
713 template <
class C,
class D>
716 if( !detail-> beforeUpdate() )
719 detail-> updateModel();
721 if( !detail-> afterUpdate() )
724 if( !detail-> beforeAccept() )
727 detail-> formModel()-> accept();
729 if( !detail-> afterAccept() )
732 if( detail-> refreshTableOnSave() )
734 tableView()-> refresh();
738 m_itemSaved.emit( detail-> formModel()-> item() );
743 template <
class C,
class D>
748 template <
class C,
class D>
751 return openDetail( tableView()-> model()-> stableResultRow( index.row() ) );
755 template <
class C,
class D>
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");
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) );
774 m_buttonTemplt =
dynamic_cast<Wt::WTemplate*
>(dialog-> contents()-> addNew<Wt::WTemplate>
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 />" 787 auto detail = dialog-> contents()-> addNew<D>( item );
791 auto u_buttonTemplt = std::make_unique<Wt::WTemplate>
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 />" 803 m_buttonTemplt = u_buttonTemplt.get();
804 lw-> addWidget( std::move(u_buttonTemplt) );
806 auto u_detail = std::make_unique<D>( item );
807 auto detail = u_detail.get();
808 lw-> addWidget( std::move(u_detail) );
812 detail-> doSave().connect( [=]()
817 detail-> doClose().connect( [=]()
822 detail-> doDeleteItem().connect( [=](
bool noask )
824 on_delete_clicked( noask );
828 if( detail-> allowChange()
829 || tableView()-> viewDef().m_def.allowChange )
831 auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>(
"submit",
"submit");
832 button-> setObjectName(
"dlg-submit" );
836 if( doSave( detail ) )
843 m_buttonTemplt-> bindEmpty(
"submit");
847 if( detail-> allowChange()
848 || tableView()-> viewDef().m_def.allowChange )
850 auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>(
"close",
"close");
851 button-> setObjectName(
"dlg-close" );
860 m_buttonTemplt-> bindEmpty(
"close");
863 if( detail-> allowDelete()
867 auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>(
"delete",
"delete");
868 button-> setObjectName(
"dlg-delete" );
877 m_buttonTemplt-> bindEmpty(
"delete");
880 if( detail-> allowPrint()
881 || tableView()-> viewDef().m_def.allowPrint )
883 auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>(
"print",
"print");
884 button-> setObjectName(
"dlg-print" );
893 m_buttonTemplt-> bindEmpty(
"print");
896 if( detail-> allowUnlock()
897 || tableView()-> viewDef().m_def.allowUnlock )
899 auto button = m_buttonTemplt-> bindNew<Wt::WPushButton>(
"unlock",
"unlock");
900 button-> setObjectName(
"dlg-unlock" );
909 m_buttonTemplt-> bindEmpty(
"unlock");
912 m_buttonTemplt-> bindEmpty(
"toolbar" );
914 auto _doAdditional = [=](
const std::string & additionals )
916 auto adds = Wtx::Core::split( additionals,
',' );
917 if( adds.size() == 1 )
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" );
925 clicked().connect( [=]()
927 detail-> onAdditional( adds.at(0) );
932 auto cwAdditional = m_buttonTemplt-> bindNew<Wt::WContainerWidget>(
"additional");
933 cwAdditional-> setMargin(
"10px" );
934 for(
auto a : Wtx::Core::split( additionals,
',' ) )
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( [=]()
943 detail-> onAdditional( a );
950 _doAdditional( detail-> additional() );
954 if( detail-> additional() !=
"" 955 || tableView()-> viewDef().m_def.additional !=
"" )
957 m_buttonTemplt-> bindNew<Wt::WPushButton>(
"additional", detail-> additional() )->
958 clicked().connect( [=]()
960 detail-> onAdditional();
965 m_buttonTemplt-> bindEmpty(
"additional" );
969 dialog-> setWindowTitle
971 Wt::WString(
"{1}:{2}")
973 .arg( detail-> templateName() )
977 finished().connect( [=]( Wt::DialogCode code )
979 removeChild( dialog );
988 template <
class C,
class D>
991 m_doubleClicked.emit( tableView()-> model()-> stableResultRow( index.row() ) );
997 template <
class C,
class D>
1000 m_exportClicked.emit( tableView()-> queryValue() );
1003 template <
class C,
class D>
1006 m_printClicked.emit( tableView()-> filter() );
1009 template <
class C,
class D>
1015 template <
class C,
class D>
1018 std::cout << __FILE__ <<
":" << __LINE__ <<
" on_unlock" << std::endl;
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.
Wtx::Dbo::Session * session()
Current Session.
std::string replace(const std::string &string, const std::string &before, const std::string &after)
Replace a String.