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