view src/iklist.cpp @ 2:c0f76f8e67fa draft v1.0

ver 1.0.0 release (add 2 items, time-limit@2022-09-30. & bug fix.)
author pyon <pyon@macmini>
date Sat, 28 Aug 2021 09:56:40 +0900
parents 520044113ef0
children d3e201c48ff8
line wrap: on
line source

// Filename   : iklist.cpp
// Last Change: 2021-08-27 金 14:20:56.
//
#include <wx/textfile.h>
#include <wx/utils.h>
#include <wx/dir.h>
#include <wx/filefn.h>
#include <wx/wfstream.h>
#include <wx/txtstrm.h>
#include <wx/fs_zip.h>
#include <wx/filesys.h>
#include <wx/datetime.h>
#include <wx/msgdlg.h>
#include <wx/fileconf.h>

#include "iklist.h"

///////////////////////////////////////////////////////////////////////////

MainFrame::MainFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) 
	: wxFrame(parent, id, title, pos, size, style)
{
	// Check Limit Date
	wxDateTime today = wxDateTime::Today();
	wxDateTime limit(30, wxDateTime::Month::Sep, 2022);
	if (today.IsLaterThan(limit)) {
		wxMessageBox(wxT("使用期限が過ぎています."));
		Close();
	}

	CreateControls();
	LoadConfig();
	m_statusBar->SetStatusText(wxString::Format(wxT(" Welcome to I.K.List - version %s"), m_version), 0);

	// Connect Events
	m_searchCtrl->Connect(wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN, wxCommandEventHandler(MainFrame::OnCancel), NULL, this);
	m_searchCtrl->Connect(wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN, wxCommandEventHandler(MainFrame::OnSearch), NULL, this);
	m_searchCtrl->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MainFrame::OnText), NULL, this);
	m_searchCtrl->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MainFrame::OnSearch), NULL, this);
	m_textCtrl->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MainFrame::OnTextEnter), NULL, this);
	m_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::OnClick), NULL, this);
	m_choiceCity->Connect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(MainFrame::OnCityChoice), NULL, this);
	m_choiceKind->Connect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(MainFrame::OnKindChoice), NULL, this);
	m_dataViewListCtrl->Connect(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler(MainFrame::OnListItemActivated), NULL, this);
}

MainFrame::~MainFrame()
{
	// Clean TempFile
	wxString tmpdir, filename;
	wxGetEnv(wxT("TEMP"), &tmpdir);
	wxDir dir(tmpdir);
	dir.IsOpened();
	bool cont = dir.GetFirst(&filename, wxT("iklist-*"), wxDIR_FILES);
	while (cont) {
		wxString file = tmpdir + wxFILE_SEP_PATH + filename;
		if (wxFileName::IsFileWritable(file))
			wxRemoveFile(file);
		cont = dir.GetNext(&filename);
	}

	// Disconnect Events
	m_searchCtrl->Disconnect(wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN, wxCommandEventHandler(MainFrame::OnCancel), NULL, this);
	m_searchCtrl->Disconnect(wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN, wxCommandEventHandler(MainFrame::OnSearch), NULL, this);
	m_searchCtrl->Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MainFrame::OnText), NULL, this);
	m_searchCtrl->Disconnect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MainFrame::OnSearch), NULL, this);
	m_choiceCity->Disconnect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(MainFrame::OnCityChoice), NULL, this);
	m_choiceKind->Disconnect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(MainFrame::OnKindChoice), NULL, this);
	m_dataViewListCtrl->Disconnect(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler(MainFrame::OnListItemActivated), NULL, this);
}

// Event Handlers
void MainFrame::OnSearch(wxCommandEvent& WXUNUSED(event))
{
	SetList();
}

void MainFrame::OnCancel(wxCommandEvent& WXUNUSED(event))
{
	m_searchCtrl->Clear();
	SetList();
}

void MainFrame::OnText(wxCommandEvent& WXUNUSED(event))
{
	SetList();
}

void MainFrame::OnTextEnter(wxCommandEvent& WXUNUSED(event))
{
	CheckPassword();
}

void MainFrame::OnClick(wxCommandEvent& WXUNUSED(event))
{
	CheckPassword();
}

void MainFrame::OnCityChoice(wxCommandEvent& WXUNUSED(event))
{
	SetList();
}

void MainFrame::OnKindChoice(wxCommandEvent& WXUNUSED(event))
{
	SetList();
}

void MainFrame::OnListItemActivated(wxDataViewEvent& WXUNUSED(event))
{
	int n = m_dataViewListCtrl->GetSelectedRow();
	wxString index = m_dataViewListCtrl->GetTextValue(n, 0);
	wxString pdf = MakePDF(index);

	wxString cmd = wxT("cmd /c start ") + pdf;
	wxArrayString output, error;
	wxExecute(cmd, output, error, wxEXEC_ASYNC|wxEXEC_HIDE_CONSOLE);
}

// Functions
void MainFrame::SetList()
{
	wxString text = m_searchCtrl->GetValue();
	wxString city = m_choiceCity->GetString(m_choiceCity->GetSelection());
	wxString kind = m_choiceKind->GetString(m_choiceKind->GetSelection());

	m_dataViewListCtrl->DeleteAllItems();
	wxVector<wxVariant> data;
	unsigned int n = 0;
    for (int i = 0; i < m_data.GetCount(); i++) {
		wxArrayString str = wxSplit(m_data[i], ':');

		data.push_back(wxVariant(wxString::Format(wxT("%04d"), i + 1)));	// ID
		data.push_back(wxVariant(str[0]));	// Name
		data.push_back(wxVariant(str[1]));	// City
		data.push_back(wxVariant(str[2]));	// Kind

		bool matched = true;
		if (!text.IsEmpty() &&  str[0].Find(text) == wxNOT_FOUND) matched =false;
		if (!city.IsEmpty() && !str[1].IsSameAs(city))            matched =false;
		if (!kind.IsEmpty() && !str[2].IsSameAs(kind))            matched =false;

		if (!m_inarea && str.GetCount() == 4 && str[3].IsSameAs(wxT("*"))) matched =false;

		if (matched) {
			m_dataViewListCtrl->AppendItem(data);
			n++;
		}

		data.clear();
    }
	//m_dataViewListCtrl->SetScrollPos(wxVERTICAL, 0, true);
	m_dataViewListCtrl->Scroll(0, 0);
	m_statusBar->SetStatusText(wxString::Format(wxT(" %d found."), n), 0);
}
#include <wx/sstream.h>
wxString MainFrame::MakePDF(wxString index)
{
	wxString tmpdir;
	wxGetEnv(wxT("TEMP"), &tmpdir);
	wxString pdf = tmpdir + "/iklist-" + index + ".pdf";
	if (wxFile::Exists(pdf)) return pdf;

	wxStringInputStream si0(wxT("%PDF"));

	wxString file;
	file = SearchFile(wxT("data/03"), index);
	wxFileInputStream si1(file);
	file = SearchFile(wxT("data/04"), index);
	wxFileInputStream si2(file);
	file = SearchFile(wxT("data/08"), index);
	wxFileInputStream si3(file);

	wxFileOutputStream so(pdf);
	so << si0;
	so << si1 << si2 << si3;	// use chunk buffer to copy if file is big.

	return pdf;
}

wxString MainFrame::SearchFile(wxString directory, wxString index)
{
	wxDir dir(directory);
	if (!dir.IsOpened())
		return wxEmptyString;

	wxString filename;
	bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES);
	while (cont) {
		if (filename.Mid(8, 4).IsSameAs(index, false)) 
			break;
		cont = dir.GetNext(&filename);
	}
	return directory + wxT("/") + filename;
}

void MainFrame::LoadConfig()
{
	wxFileSystem::AddHandler(new wxZipFSHandler);
	wxFileSystem* fs = new wxFileSystem;
	wxString archive = wxT("iklist.lib");

	// Load Password
	wxString pwfn = wxT("p8wypswd5c0x");
	wxFSFile* pwfile = fs->OpenFile(archive + wxT("#zip:") + pwfn);
	wxString buf;
	if (pwfile) {
		wxInputStream *zstream = pwfile->GetStream();
		wxTextInputStream tstream(*zstream);
		buf = tstream.ReadLine();
		delete pwfile;
	}
	for (int i = 0; i < buf.Len(); i++) {	// XOR 17
		m_pswd += wxString::Format(wxT("%c"), buf[i].GetValue() ^ 17); 
	}

	pwfn = wxT("_p8wypswd5c0x");
	wxFSFile* gpwfile = fs->OpenFile(archive + wxT("#zip:") + pwfn);
	if (gpwfile) {
		wxInputStream *zstream = gpwfile->GetStream();
		wxTextInputStream tstream(*zstream);
		buf = tstream.ReadLine();
		delete gpwfile;
	}
	for (int i = 0; i < buf.Len(); i++) {	// XOR 17
		m_gpswd += wxString::Format(wxT("%c"), buf[i].GetValue() ^ 17); 
	}

	// Load List
	wxString listfn = wxT("q534list8mor");
	wxFSFile* listfile = fs->OpenFile(archive + wxT("#zip:") + listfn);
	if (listfile) {
		wxInputStream *zstream = listfile->GetStream();
		wxTextInputStream tstream(*zstream);
		for (int i = 0; i < 543; i++) {	//#########################
		//while (!zstream->Eof()) {
			m_data.Add(tstream.ReadLine());
		}
		delete listfile;
	}
	
	// Load config
    wxString conf_file = wxGetCwd() + wxFILE_SEP_PATH + wxT("app.conf");
    wxFileConfig* conf = new wxFileConfig(wxT("MyApp"), wxT("T.Mutoh"), conf_file, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
    conf->SetPath(wxT("/Misc"));
    conf->Read(wxT("version"), &m_version);
	delete conf;

	// Set Filter
	wxArrayString filter = GetChoiceArray(1);
	for (int i = 0; i < filter.GetCount(); i++) {
		m_choiceCity->Append(filter[i]);
	}
	m_choiceCity->SetSelection(0);

	filter = GetChoiceArray(2);
	for (int i = 0; i < filter.GetCount(); i++) {
		m_choiceKind->Append(filter[i]);
	}
	m_choiceKind->SetSelection(0);

	delete fs;
}

wxArrayString MainFrame::GetChoiceArray(int n)
{
	wxArrayString filter;
	filter.Add(wxEmptyString);
	for (int i = 0; i < m_data.GetCount(); i++) {
		wxArrayString str = wxSplit(m_data[i], ':');
		bool seen;
		for (int j = 0; j < filter.GetCount(); j++) {
			if (filter[j].IsSameAs(str[n])) {
				seen = true;
				break;
			} else {
				seen = false;
			}
		}
		if (!seen) filter.Add(str[n]);
	}
	return filter;
}

void MainFrame::CheckPassword()
{
	m_inarea = false;
	if (m_textCtrl->GetValue().IsSameAs(m_pswd, true)) {
		m_inarea = true;
	} else if (m_textCtrl->GetValue().IsSameAs(m_gpswd, true)) {
		//;
	} else {
		m_textCtrl->SetBackgroundColour(wxColour(255, 160, 160));
		m_textCtrl->SelectAll();
		return;
	}
	m_staticTextWord->SetLabel(wxT("キーワード:"));

	m_textCtrl->Disconnect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(MainFrame::OnTextEnter), NULL, this);
	m_button->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::OnClick), NULL, this);
	m_textCtrl->Destroy();
	m_button->Destroy();
	m_searchCtrl->Show();
	this->Layout();

	SetList();
}

void MainFrame::CreateControls()
{
    this->SetIcon(wxIcon(wxT("sample")));
	this->SetSizeHints(wxDefaultSize, wxDefaultSize);
	this->SetBackgroundColour(wxColour(130, 170, 210));

	wxBoxSizer* bSizerTop = new wxBoxSizer(wxVERTICAL);

	//--
	wxBoxSizer* bSizerWord = new wxBoxSizer(wxHORIZONTAL);

	m_staticTextWord = new wxStaticText(this, wxID_ANY, wxT("パスワード:"), wxDefaultPosition, wxDefaultSize, 0);
	bSizerWord->Add(m_staticTextWord, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	m_textCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, -1), wxTE_PASSWORD|wxTE_PROCESS_ENTER);
	bSizerWord->Add(m_textCtrl, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
	m_textCtrl->SetFocus();

	m_button = new wxButton(this, wxID_ANY, wxT("OK"), wxDefaultPosition, wxSize(60, -1), 0);
	bSizerWord->Add(m_button, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	m_searchCtrl = new wxSearchCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, -1), 0);
	#ifndef __WXMAC__
	m_searchCtrl->ShowSearchButton(true);
	#endif
	m_searchCtrl->ShowCancelButton(true);
	bSizerWord->Add(m_searchCtrl, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	bSizerTop->Add(bSizerWord, 0, wxEXPAND, 5);

	//--
	wxBoxSizer* bSizerFilter = new wxBoxSizer(wxHORIZONTAL);

	m_staticTextFilter = new wxStaticText(this, wxID_ANY, wxT("フィルター:"), wxDefaultPosition, wxDefaultSize, 0);
	bSizerFilter->Add(m_staticTextFilter, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	m_staticTextCity = new wxStaticText(this, wxID_ANY, wxT("市町村"), wxDefaultPosition, wxDefaultSize, 0);
	bSizerFilter->Add(m_staticTextCity, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	wxArrayString m_choiceCityChoices;
	m_choiceCity = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceCityChoices, 0);
	m_choiceCity->SetSelection(0);
	m_choiceCity->SetBackgroundColour(wxColour(220, 255, 255));
	bSizerFilter->Add(m_choiceCity, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	m_staticTextKind = new wxStaticText(this, wxID_ANY, wxT("区分"), wxDefaultPosition, wxDefaultSize, 0);
	bSizerFilter->Add(m_staticTextKind, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	wxArrayString m_choiceKindChoices;
	m_choiceKind = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceKindChoices, 0);
	m_choiceKind->SetSelection(0);
	m_choiceKind->SetBackgroundColour(wxColour(220, 255, 255));
	bSizerFilter->Add(m_choiceKind, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

	bSizerTop->Add(bSizerFilter, 0, wxEXPAND, 5);

	//--
	m_dataViewListCtrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_SINGLE|wxDV_VERT_RULES|wxDV_ROW_LINES);
	m_dataViewListColumnID = m_dataViewListCtrl->AppendTextColumn(wxT("ID"),       wxDATAVIEW_CELL_INERT,  40, static_cast<wxAlignment>(wxALIGN_CENTER), wxDATAVIEW_COL_RESIZABLE|wxDATAVIEW_COL_SORTABLE);
	m_dataViewListColumnName = m_dataViewListCtrl->AppendTextColumn(wxT(" 名称"), wxDATAVIEW_CELL_INERT, 280, static_cast<wxAlignment>(wxALIGN_LEFT),   wxDATAVIEW_COL_RESIZABLE|wxDATAVIEW_COL_SORTABLE);
	m_dataViewListColumnCity = m_dataViewListCtrl->AppendTextColumn(wxT("市町村"), wxDATAVIEW_CELL_INERT,  -1, static_cast<wxAlignment>(wxALIGN_CENTER), wxDATAVIEW_COL_RESIZABLE|wxDATAVIEW_COL_SORTABLE);
	m_dataViewListColumnKind = m_dataViewListCtrl->AppendTextColumn(wxT(" 区分"), wxDATAVIEW_CELL_INERT,  -1, static_cast<wxAlignment>(wxALIGN_LEFT),   wxDATAVIEW_COL_RESIZABLE|wxDATAVIEW_COL_SORTABLE);
	bSizerTop->Add(m_dataViewListCtrl, 1, wxALL|wxEXPAND, 5);

	this->SetSizer(bSizerTop);
	this->Layout();
	m_statusBar = this->CreateStatusBar(1, wxSTB_SIZEGRIP, wxID_ANY);
	m_statusBar->SetBackgroundColour(wxColour(130, 170, 210));

	this->Centre(wxBOTH);
	m_searchCtrl->Hide();
}