// frmSearch.cpp - Search form.
//
// (c) 2012-2017 Xestia Software Development.
//
// This file is part of Xestia Address Book.
//
// Xestia Address Book 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, version 3 of the license.
//
// Xestia Address Book 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 Xestia Address Book. If not, see
#include "frmSearch.h"
#define SEARCHSETTINGS_MAX 15
DEFINE_EVENT_TYPE(SE_ADDSEARCHSETTING);
DEFINE_EVENT_TYPE(SE_REMOVESEARCHSETTING);
DEFINE_EVENT_TYPE(SE_RELOADACCOUNTS);
DEFINE_EVENT_TYPE(SE_ADDRESULT);
DEFINE_EVENT_TYPE(SE_SBUPDATE);
DEFINE_EVENT_TYPE(SE_SEARCHFINISHED);
DEFINE_EVENT_TYPE(SE_UPDATERESULT);
DEFINE_EVENT_TYPE(SE_DELETERESULT);
DEFINE_EVENT_TYPE(SE_OPENCONTACT);
DEFINE_EVENT_TYPE(SE_EDITCONTACT);
DEFINE_EVENT_TYPE(SE_REVEALCONTACT);
BEGIN_EVENT_TABLE(frmSearch, wxFrame)
EVT_COMMAND(wxID_ANY, SE_ADDSEARCHSETTING, frmSearch::AddSearchSetting)
EVT_COMMAND(wxID_ANY, SE_REMOVESEARCHSETTING, frmSearch::RemoveSearchSetting)
EVT_COMMAND(wxID_ANY, SE_RELOADACCOUNTS, frmSearch::ReloadAccountList)
EVT_COMMAND(wxID_ANY, SE_ADDRESULT, frmSearch::AddResult)
EVT_COMMAND(wxID_ANY, SE_SBUPDATE, frmSearch::SearchBarUpdate)
EVT_COMMAND(wxID_ANY, SE_SEARCHFINISHED, frmSearch::SearchFinished)
EVT_COMMAND(wxID_ANY, SE_UPDATERESULT, frmSearch::UpdateResult)
EVT_COMMAND(wxID_ANY, SE_DELETERESULT, frmSearch::DeleteResult)
EVT_COMMAND(wxID_ANY, SE_OPENCONTACT, frmSearch::OpenContact)
EVT_COMMAND(wxID_ANY, SE_EDITCONTACT, frmSearch::EditContact)
EVT_COMMAND(wxID_ANY, SE_REVEALCONTACT, frmSearch::RevealContact)
END_EVENT_TABLE()
frmSearch::frmSearch( wxWindow* parent )
:
frmSearchADT( parent )
{
// Setup the application icon.
wxMemoryInputStream istream(bigimgs_searchicon_png, sizeof(bigimgs_searchicon_png));
wxImage bigimgs_searchiconi(istream, wxBITMAP_TYPE_PNG);
wxBitmap searchiconbmp(bigimgs_searchiconi, -1);
wxIcon searchicon;
searchicon.CopyFromBitmap(searchiconbmp);
this->SetIcon(searchicon);
// Setup the search window.
XABSearchPanel *InitPanel = new XABSearchPanel( tabSearch );
InitPanel->EnableButtons(TRUE, FALSE);
InitPanel->SetupPointers(this);
InitPanel->SetupInteger(ScrollGen);
szrSearch->Add(InitPanel, 1, wxEXPAND, 0);
szrSearch->Fit(tabSearch);
SearchFrames.insert(std::make_pair(ScrollGen, InitPanel));
ScrollGen++;
// Get the list of accounts and mark them as true.
wxString preffilename = GetUserPrefDir();
XABPreferences preferences(preffilename);
wxString AccDir;
wxString AccDirFull;
wxString AccDirFullSfx;
for (int i = 0; i < preferences.accounts.GetCount(); i++){
AccDir = preferences.accounts.GetAccountDirectory(i);
AccDirFull = preferences.accounts.GetAccountDirectory(i);
AccDirFull.Trim();
AccDirFull.Append(wxT("."));
AccDirFullSfx.Append(preferences.accounts.GetAccountType(i));
AccDirFullSfx.LowerCase();
AccDirFullSfx.Trim();
AccDirFull.Append(AccDirFullSfx);
SearchAccountsPaths.insert(std::make_pair(AccDir, AccDirFull));
SearchAccounts.insert(std::make_pair(AccDir, TRUE));
SearchAccountsNames.insert(std::make_pair(AccDir,
preferences.accounts.GetAccountName(i)));
AccDirFull.clear();
AccDirFullSfx.clear();
AccDir.clear();
}
// Setup the columns.
wxListItem item;
item.SetId(0);
item.SetText(_("Name"));
item.SetWidth(228);
lstResults->InsertColumn(0, item);
item.SetId(1);
item.SetText(_("Nickname"));
item.SetWidth(128);
lstResults->InsertColumn(1, item);
item.SetId(2);
item.SetText(_("Account"));
item.SetWidth(128);
lstResults->InsertColumn(2, item);
}
void frmSearch::SelectAccounts( wxCommandEvent& event )
{
// Create the form and display as modal.
frmSearchAccounts *frameSAccount = new frmSearchAccounts ( this );
frameSAccount->LoadSearchAccounts(&SearchAccounts, &SearchAccountsNames);
frameSAccount->ShowModal();
delete frameSAccount;
frameSAccount = NULL;
}
void frmSearch::SearchContacts( wxCommandEvent& event )
{
// Check if any accounts has been selected.
bool AccountsFound = false;
for (std::map::iterator saiter = SearchAccounts.begin();
saiter != SearchAccounts.end(); saiter++){
if (saiter->second == true){
AccountsFound = true;
break;
}
}
if (AccountsFound == false){
wxMessageBox(_("No accounts have been selected to search contacts for."),
_("No accounts selected"),
wxOK|wxICON_ERROR);
return;
}
// Change the button to stop.
if (StopMode == FALSE){
// Clear the list of search results.
lstResults->DeleteAllItems();
SearchResultAccount.clear();
SearchResultFilename.clear();
// Button clicked on as 'Search'.
DisableAllSearchSettings(TRUE);
StopMode = TRUE;
btnSearch->SetLabel(_("Stop"));
// Spawn a thread so that searching can proceed
// without blocking the GUI (and allow the
// search to stop when needed).
std::thread SearchThread(&frmSearch::SearchContactsThread, this);
SearchThread.detach();
} else {
// Button clicked on as 'Stop'.
StopMode = FALSE;
btnSearch->SetLabel(_("Search"));
DisableAllSearchSettings(FALSE);
}
}
void frmSearch::ResetContacts( wxCommandEvent& event )
{
// Clear all the search settings.
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSearchPanel *XABSPPtr;
XABSPPtr = static_cast(iter->second);
szrSearch->Detach(XABSPPtr);
// Remove the frame from the memory and the list.
delete XABSPPtr;
XABSPPtr = NULL;
SearchFrames.erase(iter->first);
}
// Clear the list of search results.
lstResults->DeleteAllItems();
// Clear the account settings.
for (std::map::iterator iter = SearchAccounts.begin();
iter != SearchAccounts.end(); iter++){
iter->second = TRUE;
}
// Clear the status bar.
wxCommandEvent statusResetEvent (SE_SBUPDATE);
wxString *statusReset = new wxString(wxT(""));
statusResetEvent.SetClientData(statusReset);
wxPostEvent(this, statusResetEvent);
// Add a search settings with the default things.
ScrollGen = 0;
XABSearchPanel *NewPanel = new XABSearchPanel( tabSearch );
NewPanel->EnableButtons(TRUE, FALSE);
NewPanel->SetupPointers(this);
NewPanel->SetupInteger(ScrollGen);
szrSearch->Add(NewPanel, 1, wxEXPAND, 0);
szrSearch->Fit(tabSearch);
SearchFrames.insert(std::make_pair(ScrollGen, NewPanel));
ScrollGen++;
}
void frmSearch::AddSearchSetting( wxCommandEvent& event )
{
// Add a search setting frame to the list.
XABSearchPanel *NewPanel = new XABSearchPanel( tabSearch );
NewPanel->EnableButtons(TRUE, TRUE);
NewPanel->SetupPointers(this);
NewPanel->SetupInteger(ScrollGen);
szrSearch->Add(NewPanel, 1, wxEXPAND|wxGROW, 5);
szrSearch->FitInside(tabSearch);
szrSearch->Layout();
szrSearch->RecalcSizes();
tabSearch->Layout();
SearchFrames.insert(std::make_pair(ScrollGen, NewPanel));
ScrollGen++;
// Check if number of search settings is SEARCHSETTINGS_MAX (or over).
// If it is, disable the option of adding extra settings
// for all frames until one is removed.
XABSearchPanel *XABSPPtr;
if (SearchFrames.size() >= SEARCHSETTINGS_MAX){
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSPPtr = static_cast(iter->second);
XABSPPtr->EnableButtons(FALSE, TRUE);
}
} else if (SearchFrames.size() >= 2){
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSPPtr = static_cast(iter->second);
XABSPPtr->EnableButtons(TRUE, TRUE);
}
}
//tabSearch->SetScrollbar(wxVERTICAL, 32768, 25, 32768, false);
tabSearch->Update();
//tabSearch->ScrollToLine(tabSearch->GetLineCount());
}
void frmSearch::RemoveSearchSetting( wxCommandEvent& event )
{
// Remove a search setting frame from the list.
// Get the integer from the event.
std::map::iterator iter;
iter = SearchFrames.find(event.GetInt());
XABSearchPanel *XABSPPtr;
XABSPPtr = static_cast(iter->second);
szrSearch->Detach(XABSPPtr);
// Remove the frame from the memory and the list.
SearchFrames.erase(event.GetInt());
delete XABSPPtr;
XABSPPtr = NULL;
if (SearchFrames.size() < SEARCHSETTINGS_MAX && SearchFrames.size() > 1){
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSPPtr = static_cast(iter->second);
XABSPPtr->EnableButtons(TRUE, TRUE);
}
} else if (SearchFrames.size() == 1){
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSPPtr = static_cast(iter->second);
XABSPPtr->EnableButtons(TRUE, FALSE);
}
}
szrSearch->FitInside(tabSearch);
szrSearch->Layout();
szrSearch->RecalcSizes();
tabSearch->Layout();
}
void frmSearch::ReloadAccountList( wxCommandEvent& event ){
// Currently unimplemented.
}
void frmSearch::SearchBarUpdate( wxCommandEvent& event ){
// Update the status bar.
wxString *SBData = (wxString*)event.GetClientData();
stbBottom->SetStatusText(*SBData, 0);
delete SBData;
SBData = NULL;
}
void frmSearch::SearchFinished( wxCommandEvent& event ){
// Reset the search button and unlock the search
// panel buttons.
StopMode = FALSE;
btnSearch->SetLabel(_("Search"));
DisableAllSearchSettings(FALSE);
}
void frmSearch::DisableAllSearchSettings(bool Enable){
// Check if there is only one search value. If there is, only enable
// the add button if this is the case.
if (SearchFrames.size() == 1){
XABSearchPanel *XABSPPtr = static_cast(SearchFrames.begin()->second);
XABSPPtr->EnableButtons(TRUE, FALSE);
return;
}
// Check if there is SEARCHSETTINGS_MAX controls set or more, only
// enable the remove button if this is the case.
if (SearchFrames.size() >= SEARCHSETTINGS_MAX){
for (std::map::iterator siter = SearchFrames.begin();
siter != SearchFrames.end(); siter++){
XABSearchPanel *XABSPPtr = static_cast(SearchFrames.begin()->second);
XABSPPtr->EnableButtons(FALSE, TRUE);
}
return;
}
// More than one control, so process them.
for (std::map::iterator siter = SearchFrames.begin();
siter != SearchFrames.end(); siter++){
XABSearchPanel *XABSPPtr = static_cast(siter->second);
if (Enable == FALSE){
wxCommandEvent enboxes(XABSP_ENABLECONTROLS);
wxPostEvent(XABSPPtr, enboxes);
} else if (Enable == TRUE){
wxCommandEvent disboxes(XABSP_DISABLECONTROLS);
wxPostEvent(XABSPPtr, disboxes);
}
}
}
void frmSearch::CloseWindow( wxCloseEvent& event ){
// Hide the window so users don't panic
// whilst clearing up.
this->Hide();
// Clear up.
for (std::map::iterator iter = SearchFrames.begin();
iter != SearchFrames.end(); ++iter){
XABSearchPanel *XABSPPtr;
XABSPPtr = static_cast(iter->second);
szrSearch->Detach(XABSPPtr);
// Remove the frame from the memory and the list.
delete XABSPPtr;
XABSPPtr = NULL;
}
SearchFrames.clear();
// Close window.
if (SearchMode == false){
WindowData *WData = new WindowData;
WData->DataType = 2;
WData->WindowPointer = this;
WData->WindowID = SearchUID;
wxCommandEvent delevent(WINDOW_CLOSE);
delevent.SetClientData(WData);
wxPostEvent(GetParent(), delevent);
wxCommandEvent rs(CE_REMOVESEARCH);
wxPostEvent(this, rs);
WData = NULL;
}
this->Destroy();
}
void frmSearch::CloseWindow( wxCommandEvent& event ){
// Close this window.
this->Close();
}
void frmSearch::SetUID(int UID){
// Set the UID of the search window.
SearchUID = UID;
}
void frmSearch::SetSearchMode(bool SearchModeIn){
// Set the search mode of the window.
SearchMode = SearchModeIn;
if (SearchMode == TRUE){
mnuContactEdit->Enable(FALSE);
mnuContactReveal->Enable(FALSE);
wxFileSystem::AddHandler(new wxMemoryFSHandler);
wxImage ciicon_png;
wxMemoryInputStream ciptostream(icons_cipto_png, sizeof(icons_cipto_png));
ciicon_png.LoadFile(ciptostream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("cipto.png"), ciicon_png, wxBITMAP_TYPE_PNG);
wxMemoryInputStream cilogstream(icons_cilog_png, sizeof(icons_cilog_png));
ciicon_png.LoadFile(cilogstream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("cilog.png"), ciicon_png, wxBITMAP_TYPE_PNG);
wxMemoryInputStream cisndstream(icons_cisnd_png, sizeof(icons_cisnd_png));
ciicon_png.LoadFile(cisndstream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("cisnd.png"), ciicon_png, wxBITMAP_TYPE_PNG);
wxMemoryInputStream cikeystream(icons_cikey_png, sizeof(icons_cikey_png));
ciicon_png.LoadFile(cikeystream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("cikey.png"), ciicon_png, wxBITMAP_TYPE_PNG);
wxMemoryInputStream civenstream(icons_civen_png, sizeof(icons_civen_png));
ciicon_png.LoadFile(civenstream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("civen.png"), ciicon_png, wxBITMAP_TYPE_PNG);
wxMemoryInputStream ciextstream(icons_ciext_png, sizeof(icons_ciext_png));
ciicon_png.LoadFile(ciextstream, wxBITMAP_TYPE_PNG);
wxMemoryFSHandler::AddFile(wxT("ciext.png"), ciicon_png, wxBITMAP_TYPE_PNG);
} else {
mnuContactEdit->Enable(TRUE);
mnuContactReveal->Enable(TRUE);
}
}