Wtx ~ Wt Extension Library
WtxLib
Widget.cpp
1 
2 #include <Wt/WStandardItemModel.h>
3 #include <Wt/WCalendar.h>
4 #include <Wt/WHBoxLayout.h>
5 #include <Wt/WPushButton.h>
6 #include <Wt/WComboBox.h>
7 #include <Wt/WStackedWidget.h>
8 #include <Wt/WTemplate.h>
9 
10 #include "Widget.h"
11 
12 #define COUT_(X) std::cout << __FILE__ << "::" << __LINE__ << " " << X << std::endl;
13 #define COUT_LINE COUT_("");
14 
15 
16 Wtx::Web::Calendar::Widget::ToolBar::ToolBar()
17 {
18  addStyleClass("form-inline"); // this makes everything on one line
19  auto templt = addNew<Wt::WTemplate>( Wt::WString::tr( "Wtx.Calendar.toolBar" ) );
20 
21  m_pbNew = templt-> bindNew<Wt::WPushButton>( "new", Wt::WString::tr("Wtx.Calendar.Widget.new") );
22  m_pbToday = templt-> bindNew<Wt::WPushButton>( "today", Wt::WString::tr("Wtx.Calendar.Widget.today") );
23  m_pbPrev = templt-> bindNew<Wt::WPushButton>( "previous", Wt::WString::tr("Wtx.Calendar.Widget.previous") );
24  m_pbNext = templt-> bindNew<Wt::WPushButton>( "next", Wt::WString::tr("Wtx.Calendar.Widget.next") );
25  m_pbFind = templt-> bindNew<Wt::WPushButton>( "find", Wt::WString::tr("Wtx.Calendar.Widget.find") );
26  m_cbView = templt-> bindNew<Wt::WComboBox>( "view" );
27  m_pbSett = templt-> bindNew<Wt::WPushButton>( "settings", Wt::WString::tr("Wtx.Calendar.Widget.settings") );
28 
29  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.day" ) );
30  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.week" ) );
31  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.month" ) );
32  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.year" ) );
33  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.schedule" ) );
34  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.4-days" ) );
35  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.5-days" ) );
36  m_cbView-> addItem( Wt::WString::tr( "Wtx.Calendar.Widget.View.table" ) );
37 
38  m_date = templt-> bindNew<Wt::WText>( "date" );
39 
40 }
41 
42 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbNew() const
43 {
44  return m_pbNew;
45 }
46 
47 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbToday() const
48 {
49  return m_pbToday;
50 }
51 
52 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbPrev() const
53 {
54  return m_pbPrev;
55 }
56 
57 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbNext() const
58 {
59  return m_pbNext;
60 }
61 
62 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbFind() const
63 {
64  return m_pbFind;
65 }
66 
67 Wt::WComboBox * Wtx::Web::Calendar::Widget::ToolBar::cbView() const
68 {
69  return m_cbView;
70 }
71 
72 Wt::WPushButton * Wtx::Web::Calendar::Widget::ToolBar::pbSett() const
73 {
74  return m_pbSett;
75 }
76 
77 
78 Wtx::Web::Calendar::Widget::SideBar::SideBar( int firstDayOfWeek )
79 {
80  m_calendar = addNew<Wt::WCalendar>();
81  m_calendar-> addStyleClass( "calendarPicker" );
82  m_calendar-> setSelectionMode( Wt::SelectionMode::Single );
83  m_calendar-> setFirstDayOfWeek( firstDayOfWeek );
84 }
85 
86 Wt::WCalendar * Wtx::Web::Calendar::Widget::SideBar::calendar() const
87 {
88  return m_calendar;
89 }
90 
91 int range( int value, int minimum, int maximum )
92 {
93  if( value < minimum )
94  value = minimum;
95 
96  if( value > maximum )
97  value = maximum;
98 
99  return value;
100 }
101 
103 : m_database( database )
104 {
105  /*
106  ** make sure the requested first-day-of-week is properly limited.
107  ** the possible values are:
108  **
109  ** 1=mon
110  ** 2=tue
111  ** 3=wed
112  ** 4=thu
113  ** 5=fri
114  ** 6=sat
115  ** 7=sun
116  **
117  */
118  firstDayOfWeek = range( firstDayOfWeek, 1, 7 );
119 
120  m_selectedDate = Wt::WDate::currentDate();
121 
122  auto u_lw = std::make_unique<Wt::WHBoxLayout>();
123  auto lw = u_lw.get();
124  setLayout( std::move(u_lw) );
125 
126  auto u_sideBar = std::make_unique<Wtx::Web::Calendar::Widget::SideBar>( firstDayOfWeek );
127  m_sideBar = u_sideBar.get();
128  lw-> addWidget( std::move( u_sideBar ) );
129  m_sideBar-> calendar()-> clicked().connect( [=]( /* Wt::WDate & date */ )
130  {
131  if( m_sideBar-> calendar()-> selection().size() > 0 )
132  {
133  setSelectedDate( *(m_sideBar-> calendar()-> selection().begin()) );
134  }
135  });
136 
137  auto u_templt = std::make_unique<Wt::WTemplate>( Wt::WString::tr( "Wtx.Calendar.widget" ) );
138  auto m_templt = u_templt.get();
139 
140  lw-> addWidget( std::move(u_templt), 1 );
141 
142  m_toolBar = m_templt-> bindNew<ToolBar>( "toolBar" );
143 
144  m_toolBar-> pbNew()-> clicked().connect( [=]()
145  {
146  m_itemNew.emit( selectedDate() );
147  });
148 
149  m_toolBar-> pbToday()-> clicked().connect( [=]()
150  {
151  setSelectedDate( Wt::WDate::currentDate() );
152  });
153 
154  m_toolBar-> pbPrev()-> clicked().connect( [=]()
155  {
156  selectPrevious();
157  });
158 
159  m_toolBar-> pbNext()-> clicked().connect( [=]()
160  {
161  selectNext();
162  });
163 
164  m_toolBar-> cbView()-> activated().connect( [=]( int value )
165  {
166  setView( value );
167  });
168 
169  m_stack = m_templt-> bindNew<Wt::WStackedWidget>( "stack" );
170 
171  auto u_dayView = std::make_unique<Wtx::Web::Calendar::DayView>(firstDayOfWeek,this);
172  m_dayView = u_dayView.get();
173  m_stack-> addWidget( std::move(u_dayView) );
174 
175  auto u_weekView = std::make_unique<Wtx::Web::Calendar::WeekView>(firstDayOfWeek,this);
176  m_weekView = u_weekView.get();
177  m_stack-> addWidget( std::move(u_weekView) );
178 
179  auto u_monthView = std::make_unique<Wtx::Web::Calendar::MonthView>(firstDayOfWeek,this);
180  m_monthView = u_monthView.get();
181  m_stack-> addWidget( std::move(u_monthView) );
182  m_monthView-> clicked().connect( [=]( Wt::WDate date )
183  {
184  setSelectedDate( date );
185  });
186  m_monthView-> itemClicked().connect( [=]( Wt::WModelIndex index )
187  {
188  m_itemClicked.emit( index );
189  });
190  m_monthView-> itemDoubleClicked().connect( [=]( Wt::WModelIndex index )
191  {
192  m_itemDoubleClicked.emit( index );
193  });
194 
195  auto u_yearView = std::make_unique<Wtx::Web::Calendar::YearView>(firstDayOfWeek,this);
196  m_yearView = u_yearView.get();
197  m_stack-> addWidget( std::move(u_yearView) );
198 
199  auto u_scheduleView = std::make_unique<Wt::WText>("schedule");
200  m_stack-> addWidget( std::move(u_scheduleView) );
201 
202  auto u_fourDaysView = std::make_unique<Wt::WText>("4-days");
203  m_stack-> addWidget( std::move(u_fourDaysView) );
204 
205  auto u_fiveDaysView = std::make_unique<Wt::WText>("5-days");
206  m_stack-> addWidget( std::move(u_fiveDaysView) );
207 
208  auto u_tableView = std::make_unique<Wt::WText>("Table");
209  m_stack-> addWidget( std::move(u_tableView) );
210 
211  setView( MONTH );
212 
213  std::map< Wt::WDate, std::string > holidays =
214  {
215  { Wt::WDate( 2018, 5, 5 ), "Cinco de Mayo" },
216  { Wt::WDate( 2018, 5, 10 ), "Ascension Day" },
217  { Wt::WDate( 2018, 5, 13 ), "Mother's Day" },
218  { Wt::WDate( 2018, 5, 21 ), "Victoria Day (Canada)" },
219  { Wt::WDate( 2018, 5, 28 ), "Memorial Day (USA)" }
220  };
221 
222  for( auto calendarDay : monthView()-> dayWidgets() )
223  {
224  auto holidayItem = holidays.find( calendarDay-> date() );
225  if( holidayItem != holidays.end() )
226  {
227  calendarDay-> header()-> setText( holidayItem-> second );
228  }
229  }
230 
231  std::map< Wt::WDate, std::string > moon =
232  {
233  { Wt::WDate( 2018, 5, 7 ), "Last Quarter Moon" },
234  { Wt::WDate( 2018, 5, 15 ), "New Moon" },
235  { Wt::WDate( 2018, 5, 21 ), "New Quarter Moon" },
236  { Wt::WDate( 2018, 5, 29 ), "Full Moon" }
237  };
238 
239  for( auto calendarDay : monthView()-> dayWidgets() )
240  {
241  auto moonItem = moon.find( calendarDay-> date() );
242  if( moonItem != moon.end() )
243  {
244  calendarDay-> footer()-> setText( moonItem-> second );
245  }
246  }
247 
248  updateView();
249 
250 } // endWtx::Web::Calendar::Widget::Widget()
251 
252 void Wtx::Web::Calendar::Widget::setView( int value )
253 {
254  m_toolBar-> cbView()-> setCurrentIndex( value );
255  m_stack-> setCurrentIndex( value );
256 }
257 
258 int Wtx::Web::Calendar::Widget::view() const
259 {
260  return m_toolBar-> cbView()-> currentIndex();
261 }
262 
263 
264 const Wt::WDate & Wtx::Web::Calendar::Widget::selectedDate() const
265 {
266  return m_selectedDate;
267 }
268 
269 Wtx::Web::Calendar::YearView * Wtx::Web::Calendar::Widget::yearView() const
270 {
271  return m_yearView;
272 }
273 
274 Wtx::Web::Calendar::MonthView * Wtx::Web::Calendar::Widget::monthView() const
275 {
276  return m_monthView;
277 }
278 
279 Wtx::Web::Calendar::WeekView * Wtx::Web::Calendar::Widget::weekView() const
280 {
281  return m_weekView;
282 }
283 
284 Wtx::Web::Calendar::DayView * Wtx::Web::Calendar::Widget::dayView() const
285 {
286  return m_dayView;
287 }
288 
289 Wtx::Web::Calendar::Widget::ToolBar * Wtx::Web::Calendar::Widget::toolBar() const
290 {
291  return m_toolBar;
292 }
293 
294 Wtx::Web::Calendar::Widget::SideBar * Wtx::Web::Calendar::Widget::sideBar() const
295 {
296  return m_sideBar;
297 }
298 
299 void Wtx::Web::Calendar::Widget::selectPrevious()
300 {
301  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.year" ) )
302  {
303  setSelectedDate( selectedDate().addMonths(-12) );
304  }
305 
306  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.month" ) )
307  {
308  setSelectedDate( selectedDate().addMonths(-1) );
309  }
310 
311  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.week" ) )
312  {
313  setSelectedDate( selectedDate().addDays(-7) );
314  }
315 
316  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.day" ) )
317  {
318  setSelectedDate( selectedDate().addDays(-1) );
319  }
320 
321 }
322 
323 void Wtx::Web::Calendar::Widget::selectNext()
324 {
325  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.year" ) )
326  {
327  setSelectedDate( selectedDate().addMonths(12) );
328  }
329 
330  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.month" ) )
331  {
332  setSelectedDate( selectedDate().addMonths(1) );
333  }
334 
335  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.week" ) )
336  {
337  setSelectedDate( selectedDate().addDays(7) );
338  }
339 
340  if( toolBar()-> cbView()-> currentText() == Wt::WString::tr( "Wtx.Calendar.Widget.View.day" ) )
341  {
342  setSelectedDate( selectedDate().addDays(1) );
343  }
344 
345 }
346 
347 void Wtx::Web::Calendar::Widget::updateView()
348 {
349  m_modelMaps.clear();
350  setSelectedDate( selectedDate() );
351 }
352 
353 void Wtx::Web::Calendar::Widget::setSelectedDate( const Wt::WDate & date )
354 {
355  m_selectedDate = date;
356  m_sideBar-> calendar()-> browseTo( date );
357  m_sideBar-> calendar()-> select( date );
358  yearView()-> setSelectedDate( date );
359  monthView()-> setSelectedDate( date );
360  weekView()-> setSelectedDate( date );
361  dayView()-> setSelectedDate( date );
362 }
363 
364 Wt::Signal<Wt::WDate> & Wtx::Web::Calendar::Widget::itemNew()
365 {
366  return m_itemNew;
367 }
368 
369 Wt::Signal<Wt::WModelIndex> & Wtx::Web::Calendar::Widget::itemClicked()
370 {
371  return m_itemClicked;
372 }
373 
374 Wt::Signal<Wt::WModelIndex> & Wtx::Web::Calendar::Widget::itemDoubleClicked()
375 {
376  return m_itemDoubleClicked;
377 }
378 
385 std::shared_ptr<Wt::WAbstractItemModel> Wtx::Web::Calendar::Widget::getModel( const Wt::WDate & date, const std::vector<std::string> & fList )
386 {
387  /*
388  ** First, try to pull the model from the model cache.
389  ** We may have already generated this model for this date,
390  ** so we can just reuse it to save time.
391  **
392  */
393  auto retVal = m_modelMaps[date];
394 
395  /*
396  ** If we did-not get a model from the cache, then
397  ** we're going to have to construct it.
398  **
399  */
400  if( !retVal )
401  {
402  /*
403  ** Generate a field-list. The field-list always begins with
404  ** the 'id' of the item.
405  **
406  */
407  std::vector<std::string> fieldList = fList;
408  fieldList.insert( fieldList.begin(), "id" );
409 
410  retVal = std::make_shared<Wt::WStandardItemModel>();
411  retVal-> insertColumns( 0, fieldList.size()+2 );
412  retVal-> setHeaderData( 1, Wt::Orientation::Horizontal, "source" );
413  for( int i=0; i< fieldList.size(); i++ )
414  retVal-> setHeaderData( i+1, Wt::Orientation::Horizontal, fieldList.at(i) );
415 
416  for( auto modelProvider : m_database.modelProviders() )
417  {
418  auto model = modelProvider-> getModel( date, fieldList );
419 
420  auto _column = [=]( const Wt::cpp17::any & fieldName )
421  {
422  for( int i=0; i< model-> columnCount(); i++ )
423  if( Wt::asString( model-> headerData( i ) ) == Wt::asString( fieldName ) )
424  return i;
425 
426  return -1;
427  };
428 
429  int row = retVal-> rowCount();
430  retVal-> insertRows( row, model-> rowCount() );
431 
432  for( int i=0; i< model-> rowCount(); i++, row++ )
433  {
434  retVal-> setData( row, 0, modelProvider-> name() );
435  for( int j=0; j< retVal-> columnCount(); j++ )
436  {
437  int column=_column( retVal-> headerData(j) );
438  if( column != -1 )
439  {
440  retVal-> setData( row, j, model-> data( i, column ) );
441  }
442  }
443  }
444  }
445 
446  m_modelMaps[date] = retVal;
447  }
448 
449  return retVal;
450 }
451 
452 #ifdef NEVER
453 Wtx::Web::Calendar::Widget::ToolBar * Wtx::Web::Calendar::Widget::toolBar() const
454 {
455  return m_toolBar;
456 }
457 
458 Wtx::Web::Calendar::Widget::SideBar * Wtx::Web::Calendar::Widget::sideBar() const
459 {
460  return m_sideBar;
461 }
462 #endif
463 
std::shared_ptr< Wt::WAbstractItemModel > getModel(const Wt::WDate &date, const std::vector< std::string > &fieldList)
Get a Model by Date.
Definition: Widget.cpp:385
Calendar Day Widget.
Definition: DayView.h:65
Widget(int firstDayOfWeek, Database &database)
ctor
Definition: Widget.cpp:102