/* Meganekko Copyright (C) 2008 Alex Yatskov This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "Pch.h" #include "DialogCardManager.h" #include "FlashCardManager.h" BEGIN_EVENT_TABLE(DialogCardManager, wxDialog) EVT_MENU(ID_MENU_CARD_ADD, DialogCardManager::OnMenuCardAdd) EVT_MENU(ID_MENU_CARD_REMOVE, DialogCardManager::OnMenuCardRemove) EVT_MENU(ID_MENU_CARD_ENABLE, DialogCardManager::OnMenuCardEnable) EVT_BUTTON(XRCID("buttonAdd"), DialogCardManager::OnMenuCardAdd) EVT_BUTTON(XRCID("buttonRemove"), DialogCardManager::OnMenuCardRemove) EVT_LISTBOX(XRCID("checkListCards"), DialogCardManager::OnCheckListCardsIndexChanged) EVT_CHECKLISTBOX(XRCID("checkListCards"), DialogCardManager::OnCheckListCardsChecked) EVT_TEXT_ENTER(XRCID("textFilter"), DialogCardManager::OnCardSummaryChanged) EVT_TEXT(XRCID("textQuestion"), DialogCardManager::OnCardTextChanged) EVT_TEXT(XRCID("textAnswer"), DialogCardManager::OnCardTextChanged) EVT_CHOICE(XRCID("choiceSearch"), DialogCardManager::OnCardSummaryChanged) EVT_CHOICE(XRCID("choiceSort"), DialogCardManager::OnCardSummaryChanged) EVT_NOTEBOOK_PAGE_CHANGING(XRCID("notebookCard"), DialogCardManager::OnNotebookCardPageChanged) END_EVENT_TABLE() DialogCardManager::DialogCardManager(wxWindow* parent, FlashCardManager* manager) : m_manager(manager), m_textQuestion(NULL), m_htmlQuestion(NULL), m_textAnswer(NULL), m_htmlAnswer(NULL), m_textFilter(NULL), m_choiceSearch(NULL), m_choiceSort(NULL), m_listCards(NULL), m_notebookCard(NULL), m_staticDeck(NULL), m_staticRemembered(NULL), m_staticForgotten(NULL), m_staticBungled(NULL), m_staticAdded(NULL), m_staticReviewPrevious(NULL), m_staticReviewNext(NULL) { wxXmlResource::Get()->LoadDialog(this, parent, wxT("DialogCardManager")); const FlashCardOptions& options = m_manager->GetOptions(); m_textQuestion = XRCCTRL(*this, "textQuestion", wxTextCtrl); m_htmlQuestion = XRCCTRL(*this, "htmlQuestion", wxHtmlWindow); m_textAnswer = XRCCTRL(*this, "textAnswer", wxTextCtrl); m_htmlAnswer = XRCCTRL(*this, "htmlAnswer", wxHtmlWindow); m_textFilter = XRCCTRL(*this, "textFilter", wxTextCtrl); m_choiceSearch = XRCCTRL(*this, "choiceSearch", wxChoice); m_choiceSort = XRCCTRL(*this, "choiceSort", wxChoice); m_listCards = XRCCTRL(*this, "checkListCards", wxCheckListBox); m_notebookCard = XRCCTRL(*this, "notebookCard", wxNotebook); m_staticDeck = XRCCTRL(*this, "staticDeck", wxStaticText); m_staticRemembered = XRCCTRL(*this, "staticCountRemembered", wxStaticText); m_staticForgotten = XRCCTRL(*this, "staticCountForgotten", wxStaticText); m_staticBungled = XRCCTRL(*this, "staticCountBungled", wxStaticText); m_staticAdded = XRCCTRL(*this, "staticTimeAdded", wxStaticText); m_staticReviewPrevious = XRCCTRL(*this, "staticTimeReviewPrevious", wxStaticText); m_staticReviewNext = XRCCTRL(*this, "staticTimeReviewNext", wxStaticText); m_htmlQuestion->SetFonts(options.fontNameNormal, options.fontNameFixed, options.fontSizes); m_htmlAnswer->SetFonts(options.fontNameNormal, options.fontNameFixed, options.fontSizes); m_listCards->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(DialogCardManager::OnCheckListCardsKeyDown), NULL, this); m_listCards->Connect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(DialogCardManager::OnCheckListCardsContextMenu), NULL, this); m_textFilter->SetFocus(); SetSize(800, 600); UpdateCards(); } void DialogCardManager::OnMenuCardAdd(wxCommandEvent& event) { AddCard(); } void DialogCardManager::OnMenuCardRemove(wxCommandEvent& event) { RemoveCard(); } void DialogCardManager::OnMenuCardEnable(wxCommandEvent& event) { wxArrayInt selections; m_listCards->GetSelections(selections); const bool checked = IsSelectionChecked(); for (unsigned i = 0; i < selections.Count(); ++i) { m_listCards->Check(selections[i], !checked); } } void DialogCardManager::OnNotebookCardPageChanged(wxNotebookEvent& event) { if (m_htmlQuestion != NULL && m_htmlAnswer != NULL) { m_htmlQuestion->SetPage(m_textQuestion->GetValue()); m_htmlAnswer->SetPage(m_textAnswer->GetValue()); } } void DialogCardManager::OnCheckListCardsIndexChanged(wxCommandEvent& event) { UpdateCard(); } void DialogCardManager::OnCheckListCardsChecked(wxCommandEvent& event) { const int selection = event.GetSelection(); FlashCard* const card = m_cardMap.find(selection)->second; card->Enable(m_listCards->IsChecked(selection)); } void DialogCardManager::OnCheckListCardsContextMenu(wxContextMenuEvent& event) { wxArrayInt selections; const int selectedCount = m_listCards->GetSelections(selections); wxMenu* const menu = new wxMenu(); menu->Append(ID_MENU_CARD_ADD, wxT("&Add new card")); if (selectedCount > 0) { menu->Append(ID_MENU_CARD_REMOVE, wxT("&Remove card(s)")); menu->AppendSeparator(); menu->AppendCheckItem(ID_MENU_CARD_ENABLE, wxT("&Enable card(s)"))->Check(IsSelectionChecked()); } PopupMenu(menu); delete menu; } void DialogCardManager::OnCheckListCardsKeyDown(wxKeyEvent& event) { switch (event.GetKeyCode()) { case WXK_DELETE: RemoveCard(); break; case WXK_INSERT: AddCard(); break; default: event.Skip(); break; } } void DialogCardManager::OnCardSummaryChanged(wxCommandEvent& event) { UpdateCards(); } void DialogCardManager::UpdateCards() { const wxString filterText = m_textFilter->GetValue().Strip().Lower(); const FilterMode filterMode = static_cast(m_choiceSearch->GetSelection()); const DeckSortType sortType = static_cast(m_choiceSort->GetSelection()); std::vector cards; m_manager->EnumerateCards(&cards, static_cast(-1), true, true, sortType); m_cardMap.clear(); std::vector states; wxArrayString questions; int index = 0; for (std::vector::const_iterator iter = cards.begin(); iter != cards.end(); ++iter) { FlashCard* const card = *iter; const wxString question = card->GetQuestion(); const wxString answer = card->GetAnswer(); if (!filterText.IsEmpty()) { const wxString questionTemp = question.Strip().Lower(); const wxString answerTemp = answer.Strip().Lower(); const bool filtered = (filterMode == FILTER_MODE_QUESTION && questionTemp.Find(filterText) == wxNOT_FOUND) || (filterMode == FILTER_MODE_ANSWER && answerTemp.Find(filterText) == wxNOT_FOUND); if (filtered) { continue; } } states.push_back(card->GetEnabled()); questions.Add(question); m_cardMap.insert(std::make_pair(index++, card)); } m_listCards->SetSelection(wxNOT_FOUND); m_listCards->Set(questions); for (size_t i = 0; i < states.size(); ++i) { m_listCards->Check(i, states[i]); } if (m_listCards->GetCount() > 0) { m_listCards->Select(0); } UpdateCard(); } void DialogCardManager::UpdateCard() { wxArrayInt selections; const bool canDisplaySelection = m_listCards->GetSelections(selections) == 1; m_notebookCard->Enable(canDisplaySelection); const wxString unspecified = wxT("-"); wxString question = wxEmptyString; wxString answer = wxEmptyString; wxString deck = unspecified; wxString countRemembered = unspecified; wxString countForgotten = unspecified; wxString countBungled = unspecified; wxString timeAdded = unspecified; wxString timeReviewPrevious = unspecified; wxString timeReviewNext = unspecified; if (canDisplaySelection) { const FlashCard* const card = m_cardMap.find(selections[0])->second; question = card->GetQuestion(); answer = card->GetAnswer(); deck = wxString::FromAscii(DeckTypeToString(card->GetDeck()).c_str()); countRemembered = wxString::Format(wxT("%d"), card->GetCountRemembered()); countForgotten = wxString::Format(wxT("%d"), card->GetCountForgotten()); countBungled = wxString::Format(wxT("%d"), card->GetCountBungled()); timeAdded = TimeToStringRel(card->GetTimeAdded()); if (card->GetDeck() != DECK_TYPE_UNTESTED) { timeReviewPrevious = TimeToStringRel(card->GetTimeReviewPrevious()); } if (card->GetDeck() == DECK_TYPE_EXPIRED || card->GetDeck() == DECK_TYPE_PENDING) { timeReviewNext = TimeToStringRel(card->GetTimeReviewNext()); } } m_textQuestion->ChangeValue(question); m_htmlQuestion->SetPage(question); m_textAnswer->ChangeValue(answer); m_htmlAnswer->SetPage(answer); m_staticDeck->SetLabel(deck); m_staticRemembered->SetLabel(countRemembered); m_staticForgotten->SetLabel(countForgotten); m_staticBungled->SetLabel(countBungled); m_staticAdded->SetLabel(timeAdded); m_staticReviewPrevious->SetLabel(timeReviewPrevious); m_staticReviewNext->SetLabel(timeReviewNext); } void DialogCardManager::AddCard() { FlashCard* const card = m_manager->AddCard(wxEmptyString, wxEmptyString, true); m_listCards->Append(card->GetQuestion()); const int selectionIndex = m_listCards->GetCount() - 1; m_listCards->Check(selectionIndex, card->GetEnabled()); m_listCards->SetSelection(wxNOT_FOUND); m_listCards->SetSelection(selectionIndex); m_cardMap.insert(std::make_pair(selectionIndex, card)); m_notebookCard->SetSelection(1); m_textQuestion->SetFocus(); UpdateCard(); } void DialogCardManager::RemoveCard() { wxArrayInt selections; m_listCards->GetSelections(selections); const bool remove = selections.Count() > 0 && wxMessageBox(wxT("Are you sure you want to remove the selected card(s)?"), wxT("Meganekko"), wxYES_NO) == wxYES; if (remove) { for (unsigned i = 0; i < selections.Count(); ++i) { m_manager->RemoveCard(m_cardMap.find(selections[i])->second); } UpdateCards(); } } void DialogCardManager::OnCardTextChanged(wxCommandEvent& event) { wxArrayInt selections; if (m_listCards->GetSelections(selections) == 1) { const int selection = selections[0]; FlashCard* const card = m_cardMap.find(selection)->second; card->SetQuestion(m_textQuestion->GetValue().c_str()); card->SetAnswer(m_textAnswer->GetValue().c_str()); m_listCards->SetString(selection, card->GetQuestion()); m_listCards->Check(selection, card->GetEnabled()); } } bool DialogCardManager::IsSelectionChecked() const { wxArrayInt selections; m_listCards->GetSelections(selections); unsigned checked = 0; for (unsigned i = 0; i < selections.GetCount(); ++i) { if (m_listCards->IsChecked(selections[i])) { ++checked; } } return checked == selections.GetCount() || checked > selections.GetCount() / 2; }