Lingoes界面上的‘语言’字串可以选择不同的语言,这样导致其窗口的‘标题’不同,因此对于不同‘语言’界面的Lngoes还需要使用不同的字串传给FindWndow。这个开始还真没注意。
另一个问题,当前没有找到好的HTML Parser,于是打算采用直接分解‘text’的方式获得结果。这样做会使结果的处理非常的‘受限’,比如如果选择了多个词典,text方式处理起来就非常麻烦了。因此当前就先采用‘text’方式,处理一个默认字典先。
今天发现
wxSQLite3好用,和其封装MySQL++类似,又能迎合wxWidgets的类型,用起来比较顺手。今天的主要动作也是集中在LingosHook本地数据库的设计和访问接口的实现上,应该说写好了,就差合并使用了,这个明天再说吧。
wxSQLite3相关代码如下,记录一下,下次再用wxSQLite3就有参考了。第一次用,有错误再说吧,嘿嘿~
#include <vector>
#include "wx/wx.h"
#include "wx/wxsqlite3.h"
class CDBAccess
{
public:
static const wxString TABLENAME_WORD;
static const wxString TABLENAME_DICTIONARY;
static const wxString TABLENAME_RESULT;
static const wxString WORDCLASS_NOUN;
public:
enum WordClass { WC_UNKNOWN = -1, WC_NOUN = 0 };
typedef std::pair<int, wxString> TResultPair;//wordclass + result
typedef std::vector<TResultPair> TResultVector;
typedef std::pair<wxString, TResultVector> TRecordPair;//dictionary+result vector
typedef std::vector<TRecordPair> TRecordVector;
typedef struct _RecordData_t
{
wxString m_strWord;
wxString m_strSymbol;
TRecordVector m_vctResult;
wxString m_strHTML;
} TRecordData;
public:
CDBAccess();
virtual ~CDBAccess();
int Init(const wxString& dbfile);
int Insert(const TRecordData& record);
int Remove(const wxString& word);
int Search(TRecordData& record);
protected:
int InitTables();
void Close();
int InsertWordTable(const TRecordData& record, wxLongLong& id);
int InsertDictTable(const wxString& dict, wxLongLong& id);
int InsertResultTable(const wxLongLong& wordid, const wxLongLong& dictid, const TResultPair& result);
WordClass GetWordClass(const wxString& type) const;
int RemoveWordTable(const wxString& word, wxLongLong& id);
int RemoveResultTable(const wxLongLong& wordid);
int SearchWordTable(TRecordData& record, wxLongLong& id);
int SearchResultTable(const wxLongLong& wordid, TRecordData& record);
const wxString SearchDictTable(const wxLongLong& dictid);
protected:
wxString _strDBFile;
wxSQLite3Database _DB;
};#include <map>
#include "wx/wx.h"
#include "DBAccess.h"
const wxString CDBAccess::TABLENAME_WORD = _("WordTable");
const wxString CDBAccess::TABLENAME_DICTIONARY = _("DictionaryTable");
const wxString CDBAccess::TABLENAME_RESULT = _("ResultTable");
const wxString CDBAccess::WORDCLASS_NOUN = _("n.");
CDBAccess::CDBAccess()
{
}
CDBAccess::~CDBAccess()
{
Close();
}
int CDBAccess::Init(const wxString &dbfile)
{
try
{
Close();
_DB.Open(dbfile);
if(InitTables() != 0)
return -1;
}
catch(const wxSQLite3Exception& e)
{
return -1;
}
return 0;
}
int CDBAccess::InitTables()
{
try
{
const char* wordtable = "CREATE TABLE IF NOT EXISTS WordTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Word VARCHAR(32) UNIQUE,Symbol VARCHAR(64),HTML TEXT,UpdateTime DATE)";
_DB.ExecuteUpdate(wordtable);
const char* dicttable = "CREATE TABLE IF NOT EXISTS DictionaryTable (ID INTEGER PRIMARY KEY AUTOINCREMENT,Title VARCHAR(64),UpdateTime DATE)";
_DB.ExecuteUpdate(dicttable);
const char* resulttable = "CREATE TABLE IF NOT EXISTS ResultTable (WordID INTEGER,DictID INTEGER,ClassID INTEGER,Result VARCHAR(255))";
_DB.ExecuteUpdate(resulttable);
}
catch(const wxSQLite3Exception& e)
{
return -1;
}
return 0;
}
void CDBAccess::Close()
{
if(_DB.IsOpen())
_DB.Close();
}
int CDBAccess::Insert(const CDBAccess::TRecordData &record)
{
try
{
_DB.Begin();
wxLongLong wordid = 0;
InsertWordTable(record, wordid);
for(TRecordVector::const_iterator it = record.m_vctResult.begin(); it != record.m_vctResult.end(); ++ it)
{
wxLongLong dictid = 0;
InsertDictTable(it->first, dictid);
for(TResultVector::const_iterator i = it->second.begin(); i != it->second.end(); ++ i)
{
InsertResultTable(wordid, dictid, *i);
}
}
_DB.Commit();
}
catch(const wxSQLite3Exception& e)
{
_DB.Rollback();
return -1;
}
return 0;
}
int CDBAccess::InsertWordTable(const CDBAccess::TRecordData &record, wxLongLong &id)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
query.Bind(1, record.m_strWord);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
if(!res.Eof())
{
id = res.GetInt64(0);
}
else
{
wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO WordTable VALUES(NULL, ?, ?, ?, DATETIME('NOW', 'LOCALTIME'))");
query.Bind(1, record.m_strWord);
query.Bind(2, record.m_strSymbol);
query.Bind(3, record.m_strHTML);
query.ExecuteUpdate();
id = _DB.GetLastRowId();
}
return 0;
}
int CDBAccess::InsertDictTable(const wxString& dict, wxLongLong &id)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM DictionaryTable WHERE Title = ?");
query.Bind(1, dict);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
throw wxSQLite3Exception(255, _("SELECT ROWID of DictTable FAILED."));
if(!res.Eof())
{
id = res.GetInt64(0);
}
else
{
wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO DictionaryTable VALUES(NULL, ?, DATETIME('NOW', 'LOCALTIME'))");
query.Bind(1, dict);
query.ExecuteUpdate();
id = _DB.GetLastRowId();
}
return 0;
}
int CDBAccess::InsertResultTable(const wxLongLong &wordid, const wxLongLong &dictid, const TResultPair& result)
{
// WordClass type = GetWordClass(result.first);
wxSQLite3Statement query = _DB.PrepareStatement("INSERT INTO ResultTable VALUES(?, ?, ?, ?)");
query.Bind(1, wordid);
query.Bind(2, dictid);
query.Bind(3, result.first);
query.Bind(4, result.second);
query.ExecuteUpdate();
return 0;
}
CDBAccess::WordClass CDBAccess::GetWordClass(const wxString &type) const
{
if(type == WORDCLASS_NOUN)
return WC_NOUN;
else
return WC_UNKNOWN;
}
int CDBAccess::Remove(const wxString &word)
{
try
{
_DB.Begin();
wxLongLong wordid = 0;
RemoveWordTable(word, wordid);
RemoveResultTable(wordid);
_DB.Commit();
}
catch(const wxSQLite3Exception& e)
{
_DB.Rollback();
return -1;
}
return 0;
}
int CDBAccess::RemoveWordTable(const wxString &word, wxLongLong &id)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID FROM WordTable WHERE Word = ?");
query.Bind(1, word);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
if(!res.Eof())
{
id = res.GetInt64(0);
wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM WordTable WHERE ID = ?");
query.Bind(1, id);
query.ExecuteUpdate();
}
else
{
throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
}
return 0;
}
int CDBAccess::RemoveResultTable(const wxLongLong &wordid)
{
wxSQLite3Statement query = _DB.PrepareStatement("DELETE FROM ResultTable WHERE WordID = ?");
query.Bind(1, wordid);
query.ExecuteUpdate();
return 0;
}
int CDBAccess::Search(CDBAccess::TRecordData &record)
{
try
{
wxLongLong wordid = 0;
SearchWordTable(record, wordid);
SearchResultTable(wordid, record);
}
catch(const wxSQLite3Exception& e)
{
return -1;
}
return 0;
}
int CDBAccess::SearchWordTable(TRecordData& record, wxLongLong &id)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT ROWID,Symbol FROM WordTable WHERE Word = ?");
query.Bind(1, record.m_strWord);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
throw wxSQLite3Exception(255, _("SELECT ROWID of WordTable FAILED."));
if(!res.Eof())
{
id = res.GetInt64(0);
record.m_strSymbol = res.GetAsString(1);
}
else
{
throw wxSQLite3Exception(254, _("SELECT WordTable FAILED."));
}
return 0;
}
int CDBAccess::SearchResultTable(const wxLongLong& wordid, CDBAccess::TRecordData& record)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT DictID, ClassID, Result FROM ResultTable WHERE wordid = ?");
query.Bind(1, wordid);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
throw wxSQLite3Exception(255, _("SELECT ROWID of ResultTable FAILED."));
std::map<wxLongLong, TResultVector> mapResult;
res.NextRow();//add
while(!res.Eof())
{
wxLongLong dictid = res.GetInt64(0);
std::map<wxLongLong, TResultVector>::iterator it = mapResult.find(dictid);
if(it == mapResult.end())
it = mapResult.insert(std::make_pair(dictid, TResultVector())).first;
it->second.push_back(std::make_pair(res.GetInt(1), res.GetAsString(2)));
res.NextRow();
}
for(std::map<wxLongLong, TResultVector>::const_iterator it = mapResult.begin(); it != mapResult.end(); ++ it)
{
wxString dict = SearchDictTable(it->first);
record.m_vctResult.push_back(std::make_pair(dict, it->second));
}
return 0;
}
const wxString CDBAccess::SearchDictTable(const wxLongLong &dictid)
{
wxSQLite3Statement query = _DB.PrepareStatement("SELECT Title FROM DictionaryTable WHERE ID = ?");
query.Bind(1, dictid);
wxSQLite3ResultSet res = query.ExecuteQuery();
if(!res.IsOk())
return _("FAILED.");
if(res.Eof())
return _("Unknown.");
return res.GetAsString(0);
}