meganekko/FrameMeganekko.cpp

395 lines
12 KiB
C++
Raw Normal View History

2014-10-23 07:57:27 +00:00
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "Pch.h"
#include "FrameMeganekko.h"
#include "DialogCardManager.h"
#include "DialogCard.h"
#include "DialogAbout.h"
#include "DialogOptions.h"
BEGIN_EVENT_TABLE(FrameMeganekko, wxFrame)
EVT_MENU(XRCID("menuFileNew"), FrameMeganekko::OnMenuFileNew)
EVT_MENU(XRCID("menuFileOpen"), FrameMeganekko::OnMenuFileOpen)
EVT_MENU(XRCID("menuFileSave"), FrameMeganekko::OnMenuFileSave)
EVT_MENU(XRCID("menuFileSaveAs"), FrameMeganekko::OnMenuFileSaveAs)
EVT_MENU(XRCID("menuFileExit"), FrameMeganekko::OnMenuFileExit)
EVT_MENU(XRCID("menuToolsCardsManage"), FrameMeganekko::OnMenuToolsCardsManage)
EVT_MENU(XRCID("menuToolsCardsExpire"), FrameMeganekko::OnMenuToolsCardsExpire)
EVT_MENU(XRCID("menuToolsOptions"), FrameMeganekko::OnMenuToolsOptions)
EVT_MENU(XRCID("menuToolsReviewSequential"), FrameMeganekko::OnMenuToolsReviewSequential)
EVT_MENU(XRCID("menuToolsReviewStudy"), FrameMeganekko::OnMenuToolsReviewStudy)
EVT_MENU(XRCID("menuHelpHomepage"), FrameMeganekko::OnMenuHelpHomepage)
EVT_MENU(XRCID("menuHelpAbout"), FrameMeganekko::OnMenuHelpAbout)
EVT_BUTTON(XRCID("buttonExpired"), FrameMeganekko::OnButtonExpired)
EVT_BUTTON(XRCID("buttonFailed"), FrameMeganekko::OnButtonFailed)
EVT_BUTTON(XRCID("buttonUntested"), FrameMeganekko::OnButtonUntested)
EVT_BUTTON(XRCID("buttonPending"), FrameMeganekko::OnButtonPending)
EVT_CLOSE(FrameMeganekko::OnClose)
END_EVENT_TABLE()
FrameMeganekko::FrameMeganekko(const wxString& filename) :
m_gaugeExpired(NULL),
m_gaugeFailed(NULL),
m_gaugeUntested(NULL),
m_gaugePending(NULL),
m_buttonExpired(NULL),
m_buttonFailed(NULL),
m_buttonUntested(NULL),
m_buttonPending(NULL)
{
wxXmlResource::Get()->LoadFrame(this, NULL, wxT("FrameMeganekko"));
SetSize(wxSize(640, 480));
m_gaugeExpired = XRCCTRL(*this, "gaugeExpired", wxGauge);
m_gaugeFailed = XRCCTRL(*this, "gaugeFailed", wxGauge);
m_gaugeUntested = XRCCTRL(*this, "gaugeUntested", wxGauge);
m_gaugePending = XRCCTRL(*this, "gaugePending", wxGauge);
m_buttonExpired = XRCCTRL(*this, "buttonExpired", wxButton);
m_buttonFailed = XRCCTRL(*this, "buttonFailed", wxButton);
m_buttonUntested = XRCCTRL(*this, "buttonUntested", wxButton);
m_buttonPending = XRCCTRL(*this, "buttonPending", wxButton);
if (!filename.IsEmpty())
{
OpenDecks(filename);
}
UpdateDecks();
}
void FrameMeganekko::OnMenuFileNew(wxCommandEvent& event)
{
if (!SavePromptBail())
{
NewDecks();
}
}
void FrameMeganekko::OnMenuFileOpen(wxCommandEvent& event)
{
if (SavePromptBail())
{
return;
}
wxString filename = wxFileSelector(
wxT("Choose a deck file to open"),
wxEmptyString,
wxEmptyString,
wxT("mnko"),
wxT("Meganekko files|*.mnko"),
wxOPEN,
this
);
if (filename.IsEmpty())
{
return;
}
#ifdef wxGTK
// is this a bug in gtk wx? the default_extension doesn't appear to do anything
// so for now just explicitly provide an extension if one isn't specified
wxFileName temp(filename);
if (temp.GetExt().IsEmpty())
{
temp.SetExt(wxT("mnko"));
filename = temp.GetFullPath();
}
#endif
OpenDecks(filename);
}
void FrameMeganekko::OnMenuFileSave(wxCommandEvent& event)
{
SaveDecks();
}
void FrameMeganekko::OnMenuFileSaveAs(wxCommandEvent& event)
{
SaveDecksAs();
}
void FrameMeganekko::OnMenuFileExit(wxCommandEvent&)
{
Close(true);
}
void FrameMeganekko::OnMenuToolsCardsManage(wxCommandEvent& event)
{
DialogCardManager* const dialog = new DialogCardManager(this, &m_manager);
dialog->ShowModal();
UpdateDecks();
}
void FrameMeganekko::OnMenuToolsCardsExpire(wxCommandEvent& event)
{
const int count = m_manager.ExpireCards();
if (count == 0)
{
wxMessageBox(wxT("There are no newly expired cards"), wxT("Meganekko"), wxOK | wxICON_INFORMATION, this);
}
else
{
wxMessageBox(wxString::Format(wxT("There are %d newly expired cards"), count), wxT("Meganekko"), wxOK | wxICON_INFORMATION, this);
UpdateDecks();
}
}
void FrameMeganekko::OnMenuToolsOptions(wxCommandEvent& event)
{
DialogOptions* const dialog = new DialogOptions(this, &m_manager);
dialog->ShowModal();
UpdateDecks();
}
void FrameMeganekko::OnMenuToolsReviewSequential(wxCommandEvent& event)
{
std::vector<FlashCard*> cards;
m_manager.EnumerateCards(&cards, static_cast<unsigned>(-1) & ~BIT(DECK_TYPE_FAILED), true, false, DECK_SORT_TYPE_TIME_REVIEW_PREVIOUS);
if (cards.size() > 0)
{
DialogCard* const dialog = new DialogCard(this, BIT(DialogCard::CARD_CTRL_QUIZ), cards, m_manager.GetOptions());
dialog->ShowModal();
UpdateDecks();
}
}
void FrameMeganekko::OnMenuToolsReviewStudy(wxCommandEvent& event)
{
std::vector<FlashCard*> cards;
m_manager.EnumerateCards(&cards, static_cast<unsigned>(-1), false, true, DECK_SORT_TYPE_TIME_ADDED);
if (cards.size() > 0)
{
const unsigned controls = BIT(DialogCard::CARD_CTRL_ENABLED) | BIT(DialogCard::CARD_CTRL_NAVIGATE);
DialogCard* const dialog = new DialogCard(this, controls, cards, m_manager.GetOptions());
dialog->ShowModal();
UpdateDecks();
}
}
void FrameMeganekko::OnMenuHelpHomepage(wxCommandEvent& event)
{
wxLaunchDefaultBrowser(wxT("http://foosoft.net/meganekko"));
}
void FrameMeganekko::OnMenuHelpAbout(wxCommandEvent& event)
{
DialogAbout* const dialog = new DialogAbout(this);
dialog->ShowModal();
}
void FrameMeganekko::OnButtonExpired(wxCommandEvent& event)
{
UseDeck(DECK_TYPE_EXPIRED);
}
void FrameMeganekko::OnButtonFailed(wxCommandEvent& event)
{
UseDeck(DECK_TYPE_FAILED);
}
void FrameMeganekko::OnButtonUntested(wxCommandEvent& event)
{
UseDeck(DECK_TYPE_UNTESTED);
}
void FrameMeganekko::OnButtonPending(wxCommandEvent& event)
{
UseDeck(DECK_TYPE_PENDING);
}
void FrameMeganekko::OnClose(wxCloseEvent& event)
{
if (event.CanVeto() && SavePromptBail())
{
event.Veto();
}
else
{
Destroy();
}
}
bool FrameMeganekko::UseDeck(DeckType type)
{
unsigned controls = BIT(DialogCard::CARD_CTRL_QUIZ);
if (type == DECK_TYPE_FAILED)
{
controls = BIT(DialogCard::CARD_CTRL_LEARNED) | BIT(DialogCard::CARD_CTRL_NAVIGATE);
}
std::vector<FlashCard*> cards;
m_manager.EnumerateCards(&cards, BIT(type), true, false, DECK_SORT_TYPE_SHUFFLE);
if (cards.size() > 0)
{
DialogCard* const dialog = new DialogCard(this, controls, cards, m_manager.GetOptions());
dialog->ShowModal();
UpdateDecks();
}
return cards.size() > 0;
}
bool FrameMeganekko::SaveDecksAs()
{
wxString filename = wxFileSelector(
wxT("Choose a deck file to save"),
wxEmptyString,
wxEmptyString,
wxT("mnko"),
wxT("Meganekko files|*.mnko"),
wxSAVE,
this
);
if (filename.IsEmpty())
{
return false;
}
m_filename = filename;
#ifdef wxGTK
// is this a bug in gtk wx? the default_extension doesn't appear to do anything
// so for now just explicitly provide an extension if one isn't specified
wxFileName temp(m_filename);
if (temp.GetExt().IsEmpty())
{
temp.SetExt(wxT("mnko"));
m_filename = temp.GetFullPath();
}
#endif
return SaveDecks(m_filename);
}
bool FrameMeganekko::SaveDecks()
{
return m_filename.IsEmpty() ? SaveDecksAs() : SaveDecks(m_filename);
}
bool FrameMeganekko::SaveDecks(const wxString& filename)
{
if (!m_manager.Save(filename.c_str()))
{
wxMessageBox(wxString::Format(wxT("Cannot save deck %s"), filename.c_str()), wxT("Meganekko"), wxOK | wxICON_ERROR, this);
return false;
}
m_filename = filename;
UpdateDecks();
return true;
}
bool FrameMeganekko::OpenDecks(const wxString& filename)
{
if (!m_manager.Open(filename.c_str()))
{
wxMessageBox(wxString::Format(wxT("Cannot open deck %s"), filename.c_str()), wxT("Meganekko"), wxOK | wxICON_ERROR, this);
return false;
}
m_filename = filename;
UpdateDecks();
return true;
}
bool FrameMeganekko::NewDecks()
{
m_manager.Close();
m_filename.Clear();
UpdateDecks();
return true;
}
void FrameMeganekko::UpdateDecks()
{
const wxString title = wxString::Format(
wxT("Meganekko - %s %c"),
m_filename.IsEmpty() ? wxT("Untitled") : m_filename.c_str(),
m_manager.IsModified() ? '*' : ' '
);
SetTitle(title);
const int expired = m_manager.GetDeckSize(DECK_TYPE_EXPIRED, false);
const int failed = m_manager.GetDeckSize(DECK_TYPE_FAILED, false);
const int untested = m_manager.GetDeckSize(DECK_TYPE_UNTESTED, false);
const int pending = m_manager.GetDeckSize(DECK_TYPE_PENDING, false);
const int total = expired + failed + untested + pending;
float percentExpired = 0;
float percentFailed = 0;
float percentUntested = 0;
float percentPending = 0;
if (total > 0)
{
percentExpired = 100.0f * static_cast<float>(expired) / static_cast<float>(total);
percentFailed = 100.0f * static_cast<float>(failed) / static_cast<float>(total);
percentUntested = 100.0f * static_cast<float>(untested) / static_cast<float>(total);
percentPending = 100.0f * static_cast<float>(pending) / static_cast<float>(total);
}
m_gaugeExpired->SetValue(static_cast<int>(percentExpired));
m_gaugeExpired->SetToolTip(wxString::Format(wxT("%.2f%%"), percentExpired));
m_buttonExpired->SetLabel(wxString::Format(wxT("&Expired (%d)"), expired));
m_buttonExpired->Enable(expired > 0);
m_gaugeFailed->SetValue(static_cast<int>(percentFailed));
m_gaugeFailed->SetToolTip(wxString::Format(wxT("%.2f%%"), percentFailed));
m_buttonFailed->SetLabel(wxString::Format(wxT("F&ailed (%d)"), failed));
m_buttonFailed->Enable(failed > 0);
m_gaugeUntested->SetValue(static_cast<int>(percentUntested));
m_gaugeUntested->SetToolTip(wxString::Format(wxT("%.2f%%"), percentUntested));
m_buttonUntested->SetLabel(wxString::Format(wxT("&Untested (%d)"), untested));
m_buttonUntested->Enable(untested > 0);
m_gaugePending->SetValue(static_cast<int>(percentPending));
m_gaugePending->SetToolTip(wxString::Format(wxT("%.2f%%"), percentPending));
m_buttonPending->SetLabel(wxString::Format(wxT("&Pending (%d)"), pending));
m_buttonPending->Enable(pending > 0);
}
bool FrameMeganekko::SavePromptBail()
{
if (!m_manager.IsModified())
{
return false;
}
const int result = m_manager.GetOptions().autoSave ? wxYES : wxMessageBox(
wxT("The flash card database has been modified, do you want to save?"),
wxT("Meganekko"),
wxYES_NO | wxCANCEL | wxICON_QUESTION,
this
);
if (result == wxNO || (result == wxYES && SaveDecks()))
{
return false;
}
return true;
}