void BudgetWindow::RefreshBudgetGrid(void) { fIncomeGrid.MakeEmpty(); fSpendingGrid.MakeEmpty(); CppSQLite3Query query = gDatabase.DBQuery("select category,amount,period from " "budgetlist order by category", "BudgetWindow::RefreshCategories"); while(!query.eof()) { BString cat = DeescapeIllegalCharacters(query.getStringField(0)); Fixed amount; amount.SetPremultiplied(query.getInt64Field(1)); BudgetPeriod period = (BudgetPeriod)query.getIntField(2); ReportGrid *grid = (amount.IsPositive()) ? &fIncomeGrid : &fSpendingGrid; int32 index = grid->CountItems(); grid->AddItem(); grid->SetRowTitle(index, cat.String()); Fixed f(amount.AbsoluteValue()); switch(period) { case BUDGET_QUARTERLY: { f /= 3; Fixed qamt(amount); qamt *= 4; grid->SetValue(12,index,qamt); break; } case BUDGET_ANNUALLY: { f /=12; grid->SetValue(12,index,amount); break; } default: { Fixed mamt(f); mamt *= 12; grid->SetValue(12,index,mamt); break; } } for(int32 i=0; i<12; i++) grid->SetValue(i,index,f); query.nextRow(); } }
void BudgetWindow::RefreshCategories(void) { fCategoryList->Clear(); fIncomeRow = new BRow(); fCategoryList->AddRow(fIncomeRow); fSpendingRow = new BRow(); fCategoryList->AddRow(fSpendingRow); fIncomeRow->SetField(new BStringField(TRANSLATE("Income")),0); fSpendingRow->SetField(new BStringField(TRANSLATE("Spending")),0); CppSQLite3Query query = gDatabase.DBQuery("select category,amount,period,isexpense from " "budgetlist order by category", "BudgetWindow::RefreshCategories"); float maxwidth=fCategoryList->StringWidth("Category"); while(!query.eof()) { BString cat = DeescapeIllegalCharacters(query.getStringField(0)); Fixed amount; amount.SetPremultiplied(query.getInt64Field(1)); BudgetPeriod period = (BudgetPeriod)query.getIntField(2); BRow *row = new BRow(); if(query.getIntField(3)==0) fCategoryList->AddRow(row,fIncomeRow); else fCategoryList->AddRow(row,fSpendingRow); row->SetField(new BStringField(cat.String()),0); BString amountstr; gDefaultLocale.CurrencyToString(amount.AbsoluteValue(),amountstr); amountstr.Truncate(amountstr.FindFirst(gDefaultLocale.CurrencyDecimal())); amountstr.RemoveFirst(gDefaultLocale.CurrencySymbol()); row->SetField(new BStringField(amountstr.String()),1); float tempwidth = fCategoryList->StringWidth(cat.String()); maxwidth = MAX(tempwidth,maxwidth); row->SetField(new BStringField(BudgetPeriodToString(period).String()),2); query.nextRow(); } fCategoryList->ColumnAt(0)->SetWidth(maxwidth+30); fCategoryList->ExpandOrCollapse(fIncomeRow,true); fCategoryList->ExpandOrCollapse(fSpendingRow,true); }
void BudgetWindow::GenerateBudget(const bool &zero) { // Generate a budget based on the last year's transactions ReportGrid income(1,0), spending(1,0); gDatabase.DBCommand("delete from budgetlist", "BudgetWindow::GenerateBudget:empty budget"); CppSQLite3Query query; query = gDatabase.DBQuery("select * from categorylist order by name", "BudgetWindow::GenerateBudget:get categories"); if(query.eof()) return; float maxwidth=fCategoryList->StringWidth(TRANSLATE("Category")); while(!query.eof()) { BString catname = DeescapeIllegalCharacters(query.getStringField(0)); if(catname.ICompare(TRANSLATE("Transfer"))==0) { query.nextRow(); continue; } bool isexpense = !query.getIntField(1); if(isexpense) { spending.AddItem(); spending.SetRowTitle(spending.CountItems()-1,catname.String()); } else { income.AddItem(); income.SetRowTitle(income.CountItems()-1,catname.String()); } float tempwidth = fCategoryList->StringWidth(catname.String()); maxwidth = MAX(maxwidth,tempwidth); query.nextRow(); } query.finalize(); // Now that we have the list of categories, query for transactions for each // account from each category BString querystring; Fixed cattotal; for(int32 i=0; i<income.CountItems(); i++) { querystring = ""; cattotal = 0; if(!zero) { for(int32 j=0; j<gDatabase.CountAccounts(); j++) { Account *acc = gDatabase.AccountAt(j); querystring = "select sum(amount) from account_" ; querystring << acc->GetID() << " where category = '" << EscapeIllegalCharacters(income.RowTitle(i)) << "' and date > " << DecrementDateByYear(GetCurrentDate()) << ";"; query = gDatabase.DBQuery(querystring.String(), "BudgetWindow::GenerateBudget:get category"); cattotal.AddPremultiplied(query.getInt64Field(0)); query.finalize(); } cattotal /= 12; cattotal.Round(); } income.SetValue(0,i,cattotal); gDatabase.AddBudgetEntry(BudgetEntry(income.RowTitle(i),cattotal,BUDGET_MONTHLY,false)); } for(int32 i=0; i<spending.CountItems(); i++) { querystring = ""; cattotal = 0; if(!zero) { for(int32 j=0; j<gDatabase.CountAccounts(); j++) { Account *acc = gDatabase.AccountAt(j); querystring = "select sum(amount) from account_" ; querystring << acc->GetID() << " where category = '" << EscapeIllegalCharacters(spending.RowTitle(i)) << "';"; query = gDatabase.DBQuery(querystring.String(), "BudgetWindow::GenerateBudget:get category"); cattotal.AddPremultiplied(query.getInt64Field(0)); query.finalize(); } cattotal /= 12; cattotal.Round(); } spending.SetValue(0,i,cattotal); gDatabase.AddBudgetEntry(BudgetEntry(spending.RowTitle(i),cattotal,BUDGET_MONTHLY,true)); } }
status_t LoadRules(const char *path, BObjectList<FilerRule> *ruleList) { BEntry entry("/boot/home/config/settings/FilerRules"); if (!entry.Exists()) return B_OK; CppSQLite3DB db; db.open("/boot/home/config/settings/FilerRules"); // Because this particular build of sqlite3 does not support multithreading // because of lack of pthreads support, we need to do this in a slightly different order CppSQLite3Query query; query = DBQuery(db,"select name from RuleList order by ruleid;","PrefsWindow::LoadRules"); BString command; while (!query.eof()) { BString rulename = query.getStringField((int)0); FilerRule *rule = new FilerRule; rule->SetDescription(DeescapeIllegalCharacters(rulename.String()).String()); ruleList->AddItem(rule); query.nextRow(); } query.finalize(); for (int32 i = 0; i < ruleList->CountItems(); i++) { FilerRule *rule = ruleList->ItemAt(i); if (!rule) continue; BString rulename(EscapeIllegalCharacters(rule->GetDescription())); // Now comes the fun(?) part: loading the tests and actions. Joy. :/ command = "select * from "; command << rulename << " where entrytype = 'test';"; query = DBQuery(db,command.String(),"PrefsWindow::LoadRules"); while (!query.eof()) { BString classname = DeescapeIllegalCharacters(query.getStringField(1)); BMessage *test = new BMessage; test->AddString("name",classname); if (classname.ICompare("Attribute") == 0) { test->AddString("mimetype",DeescapeIllegalCharacters(query.getStringField(4))); test->AddString("typename",DeescapeIllegalCharacters(query.getStringField(5))); test->AddString("attrname",DeescapeIllegalCharacters(query.getStringField(6))); } test->AddString("mode",DeescapeIllegalCharacters(query.getStringField(2)).String()); test->AddString("value",DeescapeIllegalCharacters(query.getStringField(3)).String()); rule->AddTest(test); query.nextRow(); } query.finalize(); command = "select * from "; command << rulename << " where entrytype = 'action';"; query = DBQuery(db,command.String(),"PrefsWindow::LoadRules"); while (!query.eof()) { BMessage *action = new BMessage; action->AddString("name",DeescapeIllegalCharacters(query.getStringField(1))); action->AddString("value",DeescapeIllegalCharacters(query.getStringField(3))); rule->AddAction(action); query.nextRow(); } query.finalize(); } db.close(); return B_OK; }
RecipeEditor::RecipeEditor(const BRect &frame, const BMessenger &msgr, const int32 &number, const char *category) : BWindow(frame,"Add Recipe",B_FLOATING_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS), fMessenger(msgr), fNumber(number), fCategory(category) { AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); AddShortcut('Q', B_COMMAND_KEY, new BMessage(M_QUIT_APP)); BView *back = new BView(Bounds(),"back",B_FOLLOW_ALL, B_WILL_DRAW); back->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); AddChild(back); fCategories = new BMenu("Categories"); CppSQLite3Query query = DBQuery("select category from categories order by category;", "RecipeEditor:get categories"); while(!query.eof()) { BString cat(DeescapeIllegalCharacters(query.getStringField(0))); BMessage *menumsg = new BMessage(M_CATEGORY_CHANGED); menumsg->AddString("name",cat); fCategories->AddItem(new BMenuItem(cat.String(),menumsg)); query.nextRow(); } fCategories->SetRadioMode(true); fCategories->SetLabelFromMarked(true); if(fCategories->CountItems()>0) fCategories->ItemAt(0)->SetMarked(true); BRect r(10,10,10 + fCategories->MaxContentWidth(),11); BMenuField *field = new BMenuField(r,"field","Category",fCategories, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP); back->AddChild(field); field->ResizeToPreferred(); r = field->Frame(); if(category) { BMenuItem *marked = fCategories->FindItem(category); if(marked) marked->SetMarked(true); } else { BMenuItem *marked = fCategories->ItemAt(0L); if(marked) marked->SetMarked(true); } r.OffsetBy(0,r.Height() + 10); fNameBox = new AutoTextControl(r,"namebox","Name: ",NULL,NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW | B_PULSE_NEEDED | B_NAVIGABLE | B_NAVIGABLE_JUMP); fNameBox->SetEscapeCancel(true); fNameBox->SetDivider(be_plain_font->StringWidth("Name ") + 5); back->AddChild(fNameBox); fNameBox->ResizeToPreferred(); r = fNameBox->Frame(); r.right = Bounds().right - 10; fNameBox->ResizeTo(r.Width(), r.Height()); r.OffsetBy(0,r.Height() + 10); BStringView *label = new BStringView(r,"inglabel","Ingredients:"); back->AddChild(label); r.OffsetBy(0,r.Height() + 10); r.bottom = r.top + 100; r.right -= B_V_SCROLL_BAR_WIDTH; BRect textrect = r.OffsetToCopy(0,0); textrect.InsetBy(10,10); fIngredientBox = new BTextView(r, "ingredients", textrect, B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED | B_NAVIGABLE | B_NAVIGABLE_JUMP); fIngredientBox->SetDoesUndo(true); BScrollView *ingredscroll = new BScrollView("ingredients_scroller",fIngredientBox, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,0,false, true); back->AddChild(ingredscroll); r = ingredscroll->Frame(); label = new BStringView(BRect(10,10,11,11),"dirlabel","Directions:"); label->ResizeToPreferred(); label->MoveTo(10, r.bottom + 10); back->AddChild(label); r.OffsetBy(0,r.Height() + 20 + label->Frame().Height()); r.right -= B_V_SCROLL_BAR_WIDTH; textrect = r.OffsetToCopy(0,0); textrect.InsetBy(10,10); fDirectionsBox = new BTextView(r, "directions", textrect, B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED | B_NAVIGABLE | B_NAVIGABLE_JUMP); fDirectionsBox->SetDoesUndo(true); BScrollView *dirscroll = new BScrollView("directions_scroller",fDirectionsBox, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,0,false, true); back->AddChild(dirscroll); fOK = new BButton(BRect(10,10,11,11),"ok","Cancel", new BMessage(M_ADD_RECIPE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW); fOK->ResizeToPreferred(); fOK->SetLabel("OK"); fOK->MoveTo(Bounds().right - fOK->Bounds().Width() - 10, Bounds().bottom - fOK->Bounds().Height() - 10); r = fOK->Frame(); back->AddChild(fOK); r.OffsetBy(-r.Width() - 10, 0); fCancel = new BButton(r,"cancel","Cancel",new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW); back->AddChild(fCancel); field->MakeFocus(true); ResizeTo(Bounds().Width(), fDirectionsBox->Parent()->Frame().bottom + 20 + fOK->Bounds().Height()); dirscroll->SetResizingMode(B_FOLLOW_ALL); // This is the part that's different for editing a recipe as opposed to // just adding one to the database if(number >= 0 && category) { SetTitle("Edit Recipe"); BString name, ingredients, directions; if(GetRecipe(number,category,name,ingredients,directions)) { BMenuItem *item = fCategories->FindItem(category); if(item) item->SetMarked(true); fNameBox->SetText(name.String()); fIngredientBox->SetText(ingredients.String()); fDirectionsBox->SetText(directions.String()); fOK->SetMessage(new BMessage(M_EDIT_RECIPE)); } } AddShortcut(B_ENTER, B_COMMAND_KEY, new BMessage(fOK->Command())); }
CatBrowser::CatBrowser(const BRect &frame, const BMessenger &msgr, const char *category, bool editmode) : BWindow(frame,"Recipe Browser",B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS), fMessenger(msgr), fCategoryCount(-1), fCurrentPage(-1), fEditMode(editmode) { AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); AddShortcut('Q', B_COMMAND_KEY, new BMessage(M_QUIT_APP)); BView *back = new BView(Bounds(),"back",B_FOLLOW_ALL, B_WILL_DRAW); back->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); AddChild(back); fCategories = new BMenu("Categories"); CppSQLite3Query query = DBQuery("select category from categories order by category;", "FindWindow:get categories"); while(!query.eof()) { BString cat(DeescapeIllegalCharacters(query.getStringField(0))); fCategories->AddItem(new BMenuItem(cat.String(),new BMessage(M_SET_CATEGORY))); query.nextRow(); } fCategories->SetRadioMode(true); fCategories->SetLabelFromMarked(true); if(fCategories->CountItems()>0) fCategories->ItemAt(0)->SetMarked(true); BRect r(10,10,10 + fCategories->MaxContentWidth(),11); BMenuField *field = new BMenuField(r,"field","Category",fCategories); back->AddChild(field); field->ResizeToPreferred(); r = field->Frame(); BMenuItem *marked = fCategories->FindItem(category); if(marked) marked->SetMarked(true); r.OffsetBy(0,r.Height() + 10); r.right = Bounds().right - 10 - B_V_SCROLL_BAR_WIDTH; r.bottom = Bounds().bottom - 10; fList = new BListView(r, "newlist", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL); fList->SetInvocationMessage(new BMessage(M_SET_RECIPE)); BScrollView *newscroll = new BScrollView("newscroll",fList, B_FOLLOW_ALL, 0, false, true); back->AddChild(newscroll); fBack = new BButton(BRect(10,10,11,11),"back","Back", new BMessage(M_RESULTS_BACK), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW); fBack->ResizeToPreferred(); fBack->ResizeTo(be_plain_font->StringWidth("Back") + 15,fBack->Frame().Height()); fBack->MoveTo(10,Bounds().bottom - fBack->Bounds().Height() - 10); r = fBack->Frame(); back->AddChild(fBack); fBack->SetEnabled(false); r.OffsetBy(r.Width() + 5, 0); fNext = new BButton(r,"next","Next", new BMessage(M_RESULTS_NEXT), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW); back->AddChild(fNext); fNext->SetEnabled(false); fClose = new BButton(BRect(10,10,11,11),"close","View Recipe", new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW); fClose->ResizeToPreferred(); fClose->SetLabel("Close"); fClose->MoveTo(Bounds().right - fClose->Bounds().Width() - 10,r.top); r = fClose->Frame(); fClose->MakeDefault(true); r.OffsetBy(-r.Width() - 10, 0); fOpen = new BButton(r,"openrecipe","View Recipe",new BMessage(M_SET_RECIPE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW); back->AddChild(fOpen); back->AddChild(fClose); fList->MakeFocus(true); r = fList->Parent()->Frame(); r.bottom = fClose->Frame().top - 10; fList->Parent()->ResizeTo(r.Width(),r.Height()); float controlwidth = (fBack->Frame().Width() * 2) + (fOpen->Frame().Width() * 2) + 65; if( Frame().Width() < controlwidth ) ResizeTo(controlwidth, Frame().Height()); if(fEditMode) { // This hidden mode (Command-Click on the browser menu item) is for doing // massive edits on the database fList->SetListType(B_MULTIPLE_SELECTION_LIST); fList->SetSelectionMessage(new BMessage(M_SET_RECIPE)); BMenu *editmenu = new BMenu("Edit"); editmenu->AddItem(new BMenuItem("Mass Recategorize",new BMessage(M_SHOW_RECAT))); editmenu->AddItem(new BMenuItem("Delete Recipe",new BMessage(M_DELETE_RECIPE))); r.Set(10,10,10 + be_plain_font->StringWidth("Edit") + 25,11); r.OffsetTo(Bounds().right - 10 - r.Width(), 10); BMenuField *editfield = new BMenuField(r,"editfield","Edit",editmenu, B_FOLLOW_RIGHT | B_FOLLOW_TOP); editfield->SetDivider(0); back->AddChild(editfield); fSortString = " order by number "; } PostMessage(M_SET_CATEGORY); }
void CatBrowser::RunQuery(void) { BString esccat(EscapeIllegalCharacters(fCategory.String())); if(fCategory.CountChars() < 1) return; fList->DeselectAll(); for(int32 i = 0; i < fList->CountItems(); i++) { RecipeItem *item = (RecipeItem*)fList->ItemAt(i); delete item; } fList->MakeEmpty(); if(!fCategoryCount) return; int32 itemcount = fEditMode ? EDIT_MODE_RECIPE_COUNT : BROWSE_MODE_RECIPE_COUNT; BString command; CppSQLite3Query query; if(fCurrentPage >= 0) { QueryPage *page = (QueryPage*)fPageList.ItemAt(fCurrentPage); QueryPage *lastpage = NULL; if(!page) return; command = "select * from "; if(page->init) { command << esccat << " where (number >= " << page->start << ") and (number <= " << page->end << ") " << fSortString << ";"; } else { lastpage = (QueryPage*)fPageList.ItemAt(fCurrentPage - 1); command << esccat << " where number >= " << (lastpage->end + 1) << fSortString << ";"; } query = DBQuery(command.String(), "CatBrowser:get category"); RecipeItem *ritem = NULL; for(int32 i = 0; i < itemcount; i++) { if(query.eof()) break; BString string = query.getStringField(1); ritem = new RecipeItem(DeescapeIllegalCharacters(string.String()).String(), esccat.String(), query.getIntField(0)); fList->AddItem(ritem); query.nextRow(); } if(lastpage && ritem) { page->start = lastpage->end + 1; page->end = ritem->fNumber; page->init = true; } } else { command = "select * from "; command << esccat << " where number >= 0 " << fSortString << ";"; query = DBQuery(command.String(), "CatBrowser:get category"); RecipeItem *ritem = NULL; for(int32 i = 0; i < itemcount; i++) { if(query.eof()) break; BString string = query.getStringField(1); ritem = new RecipeItem(DeescapeIllegalCharacters(string.String()).String(), esccat.String(), query.getIntField(0)); fList->AddItem(ritem); query.nextRow(); } if(ritem) { fCurrentPage = 0; QueryPage *page = (QueryPage*)fPageList.ItemAt(fCurrentPage); page->start = 0; page->end = ritem->fNumber; page->init = true; } } fList->Select(0L); fList->MakeFocus(true); }