diff --git a/Makefile b/Makefile index 02f2763..7ebf1ee 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ SRCS = \ src/Database.cpp \ src/DateBox.cpp \ src/DStringList.cpp \ + src/FilterView.cpp \ src/Fixed.cpp \ src/HelpButton.cpp \ src/Import.cpp \ diff --git a/src/FilterView.cpp b/src/FilterView.cpp new file mode 100644 index 0000000..5f254fb --- /dev/null +++ b/src/FilterView.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FilterView.h" +#include "RegisterView.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "FilterView" + + +FilterView::FilterView(const char* name, int32 flags) + : BView(name, flags | B_FRAME_EVENTS), + fMessenger(NULL) +{ + BMenu* fPeriodMenu = new BMenu("timeperiod"); + // Important: keep the order according to filter_period_field in RegisterView.h + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("All transactions"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("This month"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("Last month"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("This quarter"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("Last quarter"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("This year"), new BMessage(M_FILTER_CHANGED))); + fPeriodMenu->AddItem(new BMenuItem(B_TRANSLATE("Last year"), new BMessage(M_FILTER_CHANGED))); + + fPeriodMenu->SetLabelFromMarked(true); + fPeriodMenu->SetRadioMode(true); + fPeriodMenu->ItemAt(0L)->SetMarked(true); + + BMenuField* periodField = new BMenuField("periodfield", B_TRANSLATE("Period:"), fPeriodMenu); + + float maxwidth = 0; + for (int32 i = 0; i < fPeriodMenu->CountItems(); i++) { + BMenuItem* item = fPeriodMenu->ItemAt(i); + float labelwidth = StringWidth(item->Label()); + maxwidth = MAX(labelwidth, maxwidth); + } + fPeriodMenu->SetExplicitSize(BSize(maxwidth + 20, B_SIZE_UNSET)); + + BString label(B_TRANSLATE_CONTEXT("Payee", "CommonTerms")); + label << ":"; + fPayee = new BTextControl("payee", label, NULL, new BMessage(M_FILTER_CHANGED)); + + label = B_TRANSLATE_CONTEXT("Category", "CommonTerms"); + label << ":"; + fCategory = new BTextControl("category", label, NULL, new BMessage(M_FILTER_CHANGED)); + + label = B_TRANSLATE_CONTEXT("Memo", "CommonTerms"); + label << ":"; + fMemo = new BTextControl("memo", label, NULL, new BMessage(M_FILTER_CHANGED)); + + fCompareMenu = new BMenu(""); + fCompareMenu->AddItem(new BMenuItem("≦", new BMessage(M_FILTER_CHANGED))); + fCompareMenu->AddItem(new BMenuItem("=", new BMessage(M_FILTER_CHANGED))); + fCompareMenu->AddItem(new BMenuItem("≧", new BMessage(M_FILTER_CHANGED))); + + fCompareMenu->SetLabelFromMarked(true); + fCompareMenu->SetRadioMode(true); + fCompareMenu->ItemAt(0L)->SetMarked(true); + + BMenuField* compareField = new BMenuField("compareField", "", fCompareMenu); + compareField->SetExplicitSize(BSize(StringWidth("≦") * 2, B_SIZE_UNSET)); + + label = B_TRANSLATE_CONTEXT("Amount", "CommonTerms"); + label << ":"; + fAmount = new BTextControl("amount", label, NULL, new BMessage(M_FILTER_CHANGED)); + + fClear = new BButton("clearbutton", B_TRANSLATE("Clear"), new BMessage(M_CLEAR_FILTER)); + fFilter = new BButton("startbutton", B_TRANSLATE("Filter"), new BMessage(M_START_FILTER)); + + // clang-format off + BView* amountWidget = new BView("amountWidget", B_WILL_DRAW); + BLayoutBuilder::Group<>(amountWidget, B_HORIZONTAL, -2) + .Add(compareField) + .Add(fAmount->CreateTextViewLayoutItem()) + .End(); + + BLayoutBuilder::Group<>(this, B_VERTICAL, 0) + .SetInsets(0) + .AddGrid(0.0, B_USE_SMALL_SPACING) + .Add(periodField->CreateLabelLayoutItem(), 0, 0) + .Add(periodField->CreateMenuBarLayoutItem(), 1, 0) + .Add(fPayee->CreateLabelLayoutItem(), 0, 1) + .Add(fPayee->CreateTextViewLayoutItem(), 1, 1) + .Add(fCategory->CreateLabelLayoutItem(), 0, 2) + .Add(fCategory->CreateTextViewLayoutItem(), 1, 2) + .Add(fMemo->CreateLabelLayoutItem(), 0, 3) + .Add(fMemo->CreateTextViewLayoutItem(),1, 3) + .Add(new BStringView("amountlabel", label), 0, 4) + .Add(amountWidget, 1, 4) + .End() + .AddStrut(B_USE_BIG_SPACING) + .AddGroup(B_HORIZONTAL) + .Add(fClear) + .Add(fFilter) + .End() + .End(); + // clang-format on +} + + +FilterView::~FilterView(void) +{ +} + + +void +FilterView::AttachedToWindow(void) +{ + if (fPeriodMenu->LockLooper()) { + fPeriodMenu->SetTargetForItems(this); + fPeriodMenu->UnlockLooper(); + } + fCompareMenu->SetTargetForItems(this); + fPayee->SetTarget(this); + fCategory->SetTarget(this); + fMemo->SetTarget(this); + fAmount->SetTarget(this); + fClear->SetTarget(this); + fFilter->SetTarget(this); +} + + +void +FilterView::MessageReceived(BMessage* msg) +{ + int32 start; + BString string; + switch (msg->what) { + case M_START_FILTER: + case M_FILTER_CHANGED: + { + BMessage filterMsg(M_FILTER); + filterMsg.AddString("payee", fPayee->Text()); + filterMsg.AddString("category", fCategory->Text()); + filterMsg.AddString("memo", fMemo->Text()); + filterMsg.AddString("amount", fAmount->Text()); + filterMsg.AddInt32("moreless", fCompareMenu->FindMarkedIndex()); + filterMsg.AddInt32("period", fPeriodMenu->FindMarkedIndex()); + + fMessenger->SendMessage(&filterMsg); + break; + } + case M_CLEAR_FILTER: + { + fPayee->SetText(""); + fCategory->SetText(""); + fMemo->SetText(""); + fAmount->SetText(""); + fCompareMenu->ItemAt(0L)->SetMarked(true); + if (fPeriodMenu->LockLooper()) { + fPeriodMenu->ItemAt(0L)->SetMarked(true); + fPeriodMenu->UnlockLooper(); + } + break; + } + default: + { + BView::MessageReceived(msg); + } + } +} + + +void +FilterView::MakeEmpty(void) +{ + fPeriodMenu->ItemAt(0L)->SetMarked(true); + fPayee->SetText(""); + fCategory->SetText(""); + fMemo->SetText(""); + fCompareMenu->ItemAt(0L)->SetMarked(true); + fAmount->SetText(""); + +} diff --git a/src/FilterView.h b/src/FilterView.h new file mode 100644 index 0000000..01e0510 --- /dev/null +++ b/src/FilterView.h @@ -0,0 +1,45 @@ +#ifndef FILTERVIEW_H +#define FILTERVIEW_H + +#include +#include +#include +#include + + +enum { + M_FILTER_CHANGED = 'flch', + M_CLEAR_FILTER = 'clar', + M_START_FILTER = 'strt', +}; + + +class FilterView : public BView { +public: + FilterView(const char* name, int32 flags); + ~FilterView(void); + + void AttachedToWindow(void); + void MessageReceived(BMessage* msg); + + void SetMessenger(BMessenger* msgr) { fMessenger = msgr; }; + +private: + void MakeEmpty(void); + + BMenu* fPeriodMenu; + BMenu* fCompareMenu; + + BTextControl* fPayee; + BTextControl* fCategory; + BTextControl* fMemo; + BTextControl* fAmount; + + BButton* fClear; + BButton* fFilter; + + BMessenger* fMessenger; +}; + + +#endif diff --git a/src/RegisterView.cpp b/src/RegisterView.cpp index db1eded..952c890 100644 --- a/src/RegisterView.cpp +++ b/src/RegisterView.cpp @@ -10,6 +10,7 @@ #include "AccountListItem.h" #include "CheckView.h" #include "Database.h" +#include "FilterView.h" #include "MainWindow.h" #include "QuickTrackerItem.h" @@ -18,17 +19,12 @@ #define B_TRANSLATION_CONTEXT "RegisterView" -enum { - M_SELECT_ACCOUNT = 'slac', - M_SELECT_CURRENT -}; - RegisterView::RegisterView(const char* name, int32 flags) : BView(name, flags | B_FRAME_EVENTS) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); - float width = GetAccountViewWidth(); + // Accounts BStringView* accountLabel = new BStringView("accountlabel", B_TRANSLATE("Accounts")); accountLabel->SetFont(be_bold_font); accountLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); @@ -37,11 +33,11 @@ RegisterView::RegisterView(const char* name, int32 flags) fAccountView = new BListView("accountview", B_SINGLE_SELECTION_LIST); fAccountView->SetSelectionMessage(new BMessage(M_SELECT_ACCOUNT)); fAccountView->SetInvocationMessage(new BMessage(M_SHOW_ACCOUNT_SETTINGS)); - fAccountView->SetExplicitSize(BSize(GetAccountViewWidth(), B_SIZE_UNSET)); fAccountScroller = new BScrollView("accountscroll", fAccountView, 0, false, true); fAccountScroller->SetViewColor(ViewColor()); + // Checkview fCheckView = new CheckView("checkview", B_WILL_DRAW); gDatabase.AddObserver(fCheckView); @@ -51,6 +47,7 @@ RegisterView::RegisterView(const char* name, int32 flags) acc->AddObserver(this); } + // Transactions list BStringView* transactionlabel = new BStringView("transactionlabel", B_TRANSLATE("Transactions")); transactionlabel->SetFont(be_bold_font); @@ -60,11 +57,23 @@ RegisterView::RegisterView(const char* name, int32 flags) gDatabase.AddObserver(fTransactionView); gDatabase.AddObserver(this); + // Filter + BBox* filterBox = new BBox("filterbox"); + filterBox->SetLabel(B_TRANSLATE("Filter")); + fFilterView = new FilterView("filterview", B_WILL_DRAW); + + // QuickTracker BBox* qtBox = new BBox("qtbox"); qtBox->SetLabel(B_TRANSLATE("QuickTracker")); QTNetWorthItem* qtItem = new QTNetWorthItem("networth"); // clang-format off + BLayoutBuilder::Group<>(filterBox, B_VERTICAL, 0) + .SetInsets(B_USE_DEFAULT_SPACING, B_USE_BIG_SPACING, + B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) + .Add(fFilterView) + .End(); + BLayoutBuilder::Group<>(qtBox, B_VERTICAL, 0) .SetInsets(B_USE_DEFAULT_SPACING, B_USE_BIG_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) @@ -79,6 +88,8 @@ RegisterView::RegisterView(const char* name, int32 flags) .Add(accountLabel) .Add(fAccountScroller, 2) .AddStrut(B_USE_DEFAULT_SPACING) + .Add(filterBox) + .AddStrut(B_USE_DEFAULT_SPACING) .Add(qtBox) .End() .AddGroup(B_VERTICAL, 0) @@ -97,6 +108,7 @@ void RegisterView::AttachedToWindow(void) { fAccountView->SetTarget(this); + fFilterView->SetMessenger(new BMessenger(this)); // If the selection done is before being attached to the window, the message is // never received. @@ -133,6 +145,11 @@ RegisterView::MessageReceived(BMessage* msg) Window()->PostMessage(M_SHOW_ACCOUNT_SETTINGS); break; } + case M_FILTER: + { + msg->PrintToStream(); + break; + } default: { BView::MessageReceived(msg); @@ -178,10 +195,6 @@ RegisterView::HandleNotify(const uint64& value, const BMessage* msg) } fCheckView->SetFieldsEnabled(!acc->IsClosed()); } - - // Adjust the AccountView width every time there is a change - fAccountView->SetExplicitSize(BSize(GetAccountViewWidth(), B_SIZE_UNSET)); - fAccountView->Relayout(); } else if (value & WATCH_TRANSACTION) { if (value & WATCH_CREATE || value & WATCH_DELETE || value & WATCH_CHANGE) fAccountView->Invalidate(); @@ -204,19 +217,3 @@ RegisterView::SelectAccount(const int32& index) fAccountView->Select(index); } - -float -RegisterView::GetAccountViewWidth() -{ - // Min width is the fixed width of QuickTracker - float width = be_plain_font->StringWidth(B_TRANSLATE("Balance")) - + be_plain_font->StringWidth(": $99,999,999.00"); - - for (int32 i = 0; i < gDatabase.CountAccounts(); i++) { - Account* acc = gDatabase.AccountAt(i); - - float namewidth = be_bold_font->StringWidth(acc->Name()) + B_V_SCROLL_BAR_WIDTH + 10; - width = (namewidth > width) ? namewidth : width; - } - return width; -} \ No newline at end of file diff --git a/src/RegisterView.h b/src/RegisterView.h index 604f218..7cbff91 100644 --- a/src/RegisterView.h +++ b/src/RegisterView.h @@ -8,8 +8,25 @@ #include "TransactionView.h" class CheckView; +class FilterView; + +enum { + M_SHOW_ACCOUNT_SETTINGS = 'acst', + M_SELECT_ACCOUNT = 'slac', + M_SELECT_CURRENT = 'slcu', + M_FILTER = 'filt', +}; + +typedef enum { + ALL_TRANSACTIONS = 0, + THIS_MONTH, + LAST_MONTH, + THIS_QUARTER, + LAST_QUARTER, + THIS_YEAR, + LAST_YEAR +} filter_period_field; -#define M_SHOW_ACCOUNT_SETTINGS 'acst' class RegisterView : public BView, public Observer { public: @@ -29,9 +46,8 @@ class RegisterView : public BView, public Observer { bool SelectLastTransaction(void) { return fTransactionView->SelectLast(); } private: - float GetAccountViewWidth(void); - CheckView* fCheckView; + FilterView* fFilterView; BListView* fAccountView; BScrollView* fAccountScroller; TransactionView* fTransactionView;