GnuCashew ~ Web Application compatible with GnuCash sql data files.
GCW
Loading...
Searching...
No Matches
MainWidget.cpp
Go to the documentation of this file.
1#line 2 "src/Gui/MainWidget.cpp"
2
3#include <random>
4
5#include <Wt/WDialog.h>
6#include <Wt/WComboBox.h>
7#include <Wt/WPushButton.h>
8#include <Wt/WVBoxLayout.h>
9#include <Wt/Json/Serializer.h>
10
11#ifdef STATUS_BAR_CLOCK
12#include <Wt/WTimer.h>
13#endif
14
15#include "../define.h"
16#include "../GnuCashew.h"
17#include "../Eng/TransactionManager.h"
18#include "MainWidget.h"
20#include "LanguagePicker.h"
21
23: public Wt::WPushButton
24{
25 public:
26
27 PushButton( const Wt::WString & _text )
28 : Wt::WPushButton( _text )
29 {
30 setStyleClass( "btn-xs" );
31 setAttributeValue( "style", "margin-left:3px;margin-right:3px" );
32 }
33
34};
35
38{
39 addStyleClass( "MainWidget" );
40
41 auto lw = setLayout( std::make_unique< Wt::WVBoxLayout >() );
42 lw-> setSpacing( 0 );
43
44 m_navBar = lw-> addWidget( std::make_unique< Wt::WNavigationBar >() );
45 m_navBar-> addStyleClass( "NavBar" );
46
47 m_toolBar = lw-> addWidget( std::make_unique< Wt::WToolBar >() );
48 m_toolBar-> addStyleClass( "ToolBar" );
49
50 m_centralWidget = lw-> addWidget( std::make_unique< GCW::Gui::CentralWidget >(), 1 );
51
52 m_statusBar = lw-> addWidget( std::make_unique< Wt::WContainerWidget >() );
53 m_statusBar-> addStyleClass( "StatusBar" );
54
55#ifdef STATUS_BAR_CLOCK
56 auto timer = addChild( std::make_unique< Wt::WTimer >() );
57 timer-> setInterval( std::chrono::seconds(1) );
58 timer-> timeout().connect( this, &MainWidget::do_statusBarUpdate );
59 timer-> start();
60#endif
61
62} // endGCW::MainWidget::MainWidget()
63
64auto
66load()-> void
67{
69
70 /*
71 ** Set up the navbar
72 */
73 auto link = Wt::WLink( TR8("gcw_gui.doxygen_link") );
74 link.setTarget( Wt::LinkTarget::NewWindow );
75 navBar()-> setResponsive( true );
76 navBar()-> addStyleClass( "navbar-light bg-light" );
77 navBar()-> setTitle( "GCW", link );
78
79 /*
80 ** install the main menu
81 */
82 {
83 auto w_ = std::make_unique< GCW::Gui::MainMenu >( this );
84 m_mainMenu = w_.get();
85 navBar()-> addMenu( std::move( w_ ) );
86 }
87
88 /*
89 ** install the site language selector
90 */
91 navBar()-> addWidget( std::make_unique< LanguagePicker >(), Wt::AlignmentFlag::Right );
92
93 /*
94 ** plop all the buttons down
95 */
96 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.save" ) ) );
97 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.close" ) ) );
98 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.newInvoice" ) ) );
99 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.open" ) ) );
100
101 {
102 auto b = std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.edit" ) );
103 auto e = b.get();
104 toolBar()-> addButton( std::move(b) );
105 e-> clicked().connect( [=](){ openSelectedAccount(); });
106 }
107
108 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.new" ) ) );
109 toolBar()-> addButton( std::make_unique< PushButton >( TR( "gcw.MainWidget.tb.delete" ) ) );
110
111#ifdef ENABLE_DEV
112 {
113 auto b = std::make_unique< PushButton >( "devtest" );
114 auto e = b.get();
115 toolBar()-> addButton( std::move(b) );
116 e-> clicked().connect( [=](){ test(); });
117 }
118#endif
119
120#ifdef STATUS_BAR_CLOCK
121 statusBar()-> addNew< Wt::WText >( "status bar" );
122 m_clock = statusBar()-> addNew< Wt::WText >();
123 m_clock-> setAttributeValue( "style", "float:right;" );
124#endif
125
126} // endload()-> void
127
128auto
130do_statusBarUpdate()-> void
131{
132#ifdef STATUS_BAR_CLOCK
133 m_clock-> setText( Wt::WDateTime::currentDateTime().addSecs( -1*60*60*5 ).toString() );
134#endif
135
136} // enddo_statusBarUpdate()-> void
137
138
139auto
141open_properties()-> void
142{
143 if( !GCW::app()-> gnucashew_session().isOpen() )
144 return;
145
146 auto dialog = addChild( std::make_unique< Wt::WDialog >( TR( "gcw.PropertiesWidget.titleBar" ) ) );
147 dialog-> rejectWhenEscapePressed( true );
148 dialog-> contents()-> addNew< GCW::Gui::FilePropertiesWidget >();
149 dialog-> show();
150 dialog->
151 finished().connect( [=]()
152 {
153 removeChild( dialog );
154 });
155
156} // endopen_properties()
157
158auto
160open_aboutWidget()-> void
161{
162 auto templt = std::make_unique< Wt::WTemplate >( TR( "gcw.AboutWidget.about" ) );
163 templt-> bindString( "version", "none" );
164 templt-> bindString( "buildid", "none" );
165 templt-> bindString( "finance", "none (yet)" );
166
167 auto dialog = addChild( std::make_unique< Wt::WDialog >( TR( "gcw.AboutWidget.titleBar" ) ) );
168 dialog-> rejectWhenEscapePressed( true );
169 dialog-> contents()-> addWidget( std::move( templt ) );
170 dialog-> show();
171 dialog->
172 finished().connect( [=]()
173 {
174 removeChild( dialog );
175 });
176
177} // endopen_properties()
178
179auto
181openSelectedAccount()-> void
182{
183 centralWidget()-> activateAccountsTreeView();
184 centralWidget()-> accountsTreeView()-> editSelectedAccount();
185
186} // endopenSelectedAccount()
187
188auto
190setBasicLedger()-> void
191{
192 std::cout << __FILE__ << ":" << __LINE__ << " " << std::endl;
193
194}
195
196auto
198setAutosplit()-> void
199{
200 std::cout << __FILE__ << ":" << __LINE__ << " " << std::endl;
201
202}
203
204auto
206setTransaction()-> void
207{
208 std::cout << __FILE__ << ":" << __LINE__ << " " << std::endl;
209
210}
211
212auto
214setDoubleLine()-> void
215{
216 if( auto accountRegister = centralWidget()-> currentAccountRegister() )
217 {
218 auto doubleLine = m_mainMenu-> menuItem( TR( "gcw.MainWidget.mu.view.doubleline" ) );
219
220 accountRegister-> setDoubleLine( doubleLine-> isChecked() );
221 }
222
223} // endsetDoubleLine()-> void
224
225namespace {
226
227auto randomNumber( int _min, int _max )-> int
228{
229 static std::random_device rd; // Non-deterministic seed
230 static std::mt19937 gen( rd() ); // Mersenne Twister RNG
231
232 std::uniform_int_distribution<> dist( _min, _max ); // inclusive range
233
234 auto retVal = dist( gen );
235
236 return retVal;
237
238} // endauto randomNumber( int _min, int _max )-> int
239
240auto
241test_tableview()-> void
242{
243 auto model = std::make_shared< Wt::WStandardItemModel >();
244 for( int row = 0; row< 3; row++ )
245 {
246 std::vector< std::unique_ptr< Wt::WStandardItem > > rowset;
247 for( int col = 0; col< 3; col++ )
248 {
249 auto item = std::make_unique< Wt::WStandardItem >( Wt::WString("row{1} col{2}").arg( row ).arg( col) );
250 rowset.push_back( std::move( item ) );
251 }
252
253 model-> appendRow( std::move( rowset ) );
254 }
255
256 auto tableView = std::make_unique< Wt::WTableView >();
257 tableView-> setSelectionBehavior ( Wt::SelectionBehavior::Items );
258// tableView-> setSelectionBehavior ( Wt::SelectionBehavior::Rows );
259// tableView-> setSelectionMode ( Wt::SelectionMode::Single );
260 tableView-> setSelectionMode ( Wt::SelectionMode::Extended );
261 tableView-> setColumnResizeEnabled ( false );
262 tableView-> setAlternatingRowColors ( true );
263 tableView-> setModel ( model );
264
265 auto pbgo = std::make_unique< Wt::WPushButton >( "go" );
266 pbgo.get()->
267 clicked().connect( [=]()
268 {
269 std::cout << __FILE__ << ":" << __LINE__ << " " << std::endl;
270
271 int row = 99;
272 std::vector< std::unique_ptr< Wt::WStandardItem > > rowset;
273 for( int col = 0; col< 3; col++ )
274 {
275 auto item = std::make_unique< Wt::WStandardItem >( Wt::WString("row{1} col{2}").arg( row ).arg( col) );
276 rowset.push_back( std::move( item ) );
277 }
278
279 model-> insertRow( 2, std::move( rowset ) );
280
281 });
282
283
284 Wt::WDialog dialog( "test" );
285 dialog.contents()-> addWidget( std::move( pbgo ) );
286 dialog.contents()-> addWidget( std::move( tableView ) );
287 dialog.rejectWhenEscapePressed( true );
288 dialog.setResizable( true );
289 dialog.setMinimumSize( 600, 300 );
290 dialog.setClosable( true );
291 dialog.exec();
292
293} // endtest_tableview()-> void
294
295/*
296** this loads random transactions in to the database. It focuses
297** on the checking account as the primary account, and has a
298** handful of other accounts that it generates random transactions
299** for. It also adds transactions as deposits.
300*/
301auto
302load_random_transactions()
303{
304 std::map< std::string, std::vector< std::string > > expenses = {
305 { "Expenses:Medical Expenses",
306 {
307 "Copay for doctor visit",
308 "Prescription refill – CVS",
309 "Dental cleaning – Dr. Smith",
310 "Urgent care visit – weekend",
311 "Eye exam – optometrist",
312 "Physical therapy session",
313 "Lab tests – Quest Diagnostics",
314 "Over-the-counter medication",
315 "Hospital parking fee",
316 "Flu shot – Walgreens"
317 }},
318 { "Expenses:Laundry/Dry Cleaning",
319 {
320 "Dry cleaning suit – Cleaners Plus",
321 "Wash & fold service",
322 "Shirt pressing – Express Cleaners",
323 "Comforter dry cleaned",
324 "Stain removal – silk blouse",
325 "Laundry card refill",
326 "Pickup & delivery laundry",
327 "Uniform cleaning",
328 "Curtain dry cleaning",
329 "Weekly laundry service"
330 }},
331 { "Expenses:Groceries",
332 {
333 "Weekly grocery run – Walmart",
334 "Produce market – fresh veggies",
335 "Milk and bread – local store",
336 "Bulk items – Costco",
337 "Organic produce – Whole Foods",
338 "Meat & seafood purchase",
339 "Baking supplies – holiday",
340 "Frozen goods – Aldi",
341 "Snacks and beverages",
342 "Pet food – grocery aisle"
343 }},
344 { "Expenses:Cable",
345 {
346 "Monthly cable bill – Spectrum",
347 "Sports channel add-on",
348 "Premium movie package",
349 "DVR upgrade fee",
350 "Service technician visit",
351 "Late payment fee",
352 "Internet & cable bundle",
353 "Pay-per-view boxing event",
354 "Channel upgrade request",
355 "Equipment rental fee"
356 }},
357 { "Expenses:Taxes:Other Tax",
358 {
359 "Local occupancy tax",
360 "Vehicle registration tax",
361 "Luxury goods tax",
362 "Parking permit tax",
363 "Short-term rental tax",
364 "City environmental fee",
365 "Import duty – online order",
366 "Special assessment tax",
367 "Utility usage surcharge",
368 "Tourism tax"
369 }},
370 { "Expenses:Computer",
371 {
372 "New laptop purchase",
373 "External hard drive – backup",
374 "Software subscription – Adobe",
375 "Keyboard & mouse combo",
376 "Replacement charger",
377 "RAM upgrade",
378 "Anti-virus renewal",
379 "Laptop repair service",
380 "Cloud storage subscription",
381 "Graphics card upgrade"
382 }},
383 { "Expenses:Phone",
384 {
385 "Monthly mobile bill – Verizon",
386 "New phone case",
387 "Data overage charge",
388 "International calling plan",
389 "Screen protector purchase",
390 "Device insurance premium",
391 "Phone upgrade fee",
392 "SIM card replacement",
393 "Voicemail-to-text add-on",
394 "Mobile hotspot charge"
395 }},
396 { "Expenses:Books",
397 {
398 "Textbook purchase – college",
399 "E-book download – Kindle",
400 "Magazine subscription",
401 "Used books – thrift store",
402 "Study guide – exam prep",
403 "Children’s storybook",
404 "Hardcover bestseller",
405 "Travel guidebook",
406 "Audio book subscription",
407 "Book club order"
408 }},
409 { "Expenses:Insurance:Health Insurance",
410 {
411 "Monthly premium – Blue Cross",
412 "Policy renewal fee",
413 "Dependent coverage add-on",
414 "COBRA payment",
415 "Out-of-network reimbursement",
416 "Health plan deductible payment",
417 "Policy admin charge",
418 "Wellness program fee",
419 "Health savings account contribution",
420 "Employer premium adjustment"
421 }},
422 { "Expenses:Supplies",
423 {
424 "Office paper & pens",
425 "Printer ink cartridges",
426 "Cleaning supplies – janitorial",
427 "Packaging tape – shipping",
428 "Storage bins purchase",
429 "Paper towels & tissues",
430 "Refill for whiteboard markers",
431 "Safety gloves & masks",
432 "Breakroom coffee supplies",
433 "Stationery order"
434 }},
435 { "Expenses:Taxes:Social Security",
436 {
437 "Social security tax withholding",
438 "Additional SS tax adjustment",
439 "Employer SS contribution",
440 "Self-employment SS tax",
441 "Catch-up SS payment",
442 "Late SS filing fee",
443 "SS estimated tax",
444 "Overpayment refund offset",
445 "Correction to SS tax",
446 "Supplemental SS fee"
447 }},
448 { "Expenses:Entertainment:Recreation",
449 {
450 "Movie tickets – Friday night",
451 "Bowling alley fee",
452 "Zoo admission",
453 "Amusement park day pass",
454 "Concert ticket – local band",
455 "Game rental – board games",
456 "Streaming movie rental",
457 "Mini golf outing",
458 "Escape room experience",
459 "Comedy club cover charge"
460 }},
461 { "Expenses:Online Services",
462 {
463 "Cloud backup subscription",
464 "Website hosting fee",
465 "Domain renewal – personal site",
466 "Streaming service – Netflix",
467 "VPN annual plan",
468 "Stock photo download",
469 "Music subscription – Spotify",
470 "Online course enrollment",
471 "Web app premium upgrade",
472 "Paid newsletter subscription"
473 }},
474 { "Expenses:Taxes:State/Province",
475 {
476 "State income tax payment",
477 "Quarterly state estimated tax",
478 "State tax penalty",
479 "State tax refund offset",
480 "State franchise tax",
481 "State use tax – online order",
482 "State excise tax",
483 "State annual filing fee",
484 "State surtax adjustment",
485 "State environmental surcharge"
486 }},
487 { "Expenses:Insurance:Life Insurance",
488 {
489 "Term life premium – annual",
490 "Whole life policy contribution",
491 "Beneficiary change fee",
492 "Policy loan interest payment",
493 "Cash value withdrawal fee",
494 "Additional rider premium",
495 "Coverage renewal",
496 "Life insurance underwriting fee",
497 "Group life policy payment",
498 "Late policy premium fee"
499 }},
500 { "Expenses:Auto:Fuel",
501 {
502 "Gas fill-up – Shell",
503 "Diesel purchase – truck",
504 "Premium fuel – road trip",
505 "Gasoline – self-service",
506 "Fuel for rental car",
507 "Prepaid gas card load",
508 "Gas station coffee & snack",
509 "Topping off tank – holiday",
510 "Discount fuel club purchase",
511 "Fleet vehicle refueling"
512 }}
513 };
514
515// Assets:Current Assets:Checking Account
516// Income:Salary
517
518 auto pb_expense = std::make_unique< Wt::WPushButton >( "load random expenses" );
519 pb_expense.get()->
520 clicked().connect( [=]()
521 {
523
524 auto account1 = GCW::Dbo::Accounts::byFullName( "Assets:Current Assets:Checking Account" );
525 std::cout << __FILE__ << ":" << __LINE__
526 << " " << account1
527 << " " << expenses.size()
528 << " " << account1-> name()
529 << std::endl;
530
531 for( auto expense : expenses )
532 {
533 auto account2 = GCW::Dbo::Accounts::byFullName( expense.first );
534
535 std::cout << __FILE__ << ":" << __LINE__
536 << " " << account2
537 << " " << expense.second.size()
538 << " " << expense.first
539 << std::endl;
540
541 for( auto second : expense.second )
542 {
543 GCW_NUMERIC value( float( 1234.0 / randomNumber( 1, 99 ) ) );
544
545 auto number = randomNumber( 0, 9 );
546
547 transMan
549 (
550 account1-> guid(),
551 account2-> guid(),
552 Wt::WDate::currentDate().addDays( randomNumber( 0, 365) ),
553 -value,
554 expense.second.at( number )
555 );
556
557 } // endfor( auto second : expense.second )
558
559 } // endfor( auto expense : expenses )
560
561 });
562
563 auto pb_income = std::make_unique< Wt::WPushButton >( "load random income" );
564 pb_income.get()->
565 clicked().connect( [=]()
566 {
568
569 auto account1 = GCW::Dbo::Accounts::byFullName( "Assets:Current Assets:Checking Account" );
570 std::cout << __FILE__ << ":" << __LINE__
571 << " " << account1
572 << " " << expenses.size()
573 << " " << account1-> name()
574 << std::endl;
575
576 auto account2 = GCW::Dbo::Accounts::byFullName( "Income:Salary" );
577
578 for( int i=0; i< 12; i++ )
579 {
580 GCW_NUMERIC value( randomNumber( 1000, 2000 ) );
581
582 transMan
584 (
585 account1-> guid(),
586 account2-> guid(),
587 Wt::WDate::currentDate().addDays( 60 + 28 * i + randomNumber( -5, 5 ) ),
588 value,
589 "Income"
590 );
591
592 } // endfor( auto expense : expenses )
593
594 });
595
596 Wt::WDialog dialog( "random transactions" );
597 dialog.contents()-> addWidget( std::move( pb_expense ) );
598 dialog.contents()-> addWidget( std::make_unique< Wt::WBreak >() );
599 dialog.contents()-> addWidget( std::move( pb_income ) );
600 dialog.rejectWhenEscapePressed( true );
601 dialog.setClosable( true );
602 dialog.exec();
603
604} // endload_random_transactions()
605
606} // endnamespace {
607
608auto
610test()-> void
611{
612 test_tableview();
613// load_random_transactions();
614
615} // endtest()
616
617
618
619
620
621
622
623
auto newTransaction(const std::string &_accountGuid1, const std::string &_accountGuid2, const Wt::WDate &_date=Wt::WDate::currentDate(), GCW_NUMERIC _value=GCW_NUMERIC(0), const std::string &_description="") -> void
New Transaction.
Wt::WToolBar * m_toolBar
Definition MainWidget.h:72
auto setTransaction() -> void
auto open_aboutWidget() -> void
auto test() -> void
auto openSelectedAccount() -> void
auto open_properties() -> void
auto setDoubleLine() -> void
auto setBasicLedger() -> void
auto do_statusBarUpdate() -> void
CentralWidget * m_centralWidget
Definition MainWidget.h:74
Wt::WContainerWidget * m_statusBar
Definition MainWidget.h:73
auto setAutosplit() -> void
Wt::WNavigationBar * m_navBar
Definition MainWidget.h:70
auto load() -> void
PushButton(const Wt::WString &_text)
Widget * addNew(Args &&...args)
void setLayout(std::unique_ptr< WLayout > layout)
virtual void addWidget(std::unique_ptr< WWidget > widget)
static WDateTime currentDateTime()
static WDate currentDate()
virtual void load() override
void addChild(std::unique_ptr< WObject > child)
virtual void setAttributeValue(const std::string &name, const WString &value) override
virtual void setStyleClass(const WString &styleClass) override
virtual void addStyleClass(const WString &styleClass, bool force=false) override
#define TR8(X)
Definition define.h:18
#define TR(X)
Definition define.h:17
#define GCW_NUMERIC
Internal Numeric Type.
Definition gcwglobal.h:40
const Wt::WFormModel::Field name
const Wt::WFormModel::Field guid
endGCW::Dbo::Accounts::s_accountDefs
auto byFullName(const std::string &_fullName) -> Item::Ptr
Load Account by 'full name' with ':' account separator.
App * app()
Definition App.cpp:75