From 62fe686c7ff816464b9b309933030ea88e27338f Mon Sep 17 00:00:00 2001 From: Frederic Cervenansky Date: Thu, 27 Aug 2009 11:47:02 +0000 Subject: [PATCH] creation of an interface to manage DB descriptor files --- src2/CppSQLite3.cpp | 4500 +++++++++++++------- src2/CppSQLite3.h | 927 ++-- src2/creaImageIOGimmick.cpp | 1 - src2/creaImageIOGimmickReaderDialog.cpp | 4 +- src2/creaImageIOWxCustomizeConfigPanel.cpp | 4 - src2/creaImageIOWxDescriptorPanel.cpp | 782 ++++ src2/creaImageIOWxDescriptorPanel.h | 154 + src2/creaImageIOWxGimmickView.cpp | 106 +- src2/creaImageIOWxViewer.cpp | 2 +- 9 files changed, 4600 insertions(+), 1880 deletions(-) create mode 100644 src2/creaImageIOWxDescriptorPanel.cpp create mode 100644 src2/creaImageIOWxDescriptorPanel.h diff --git a/src2/CppSQLite3.cpp b/src2/CppSQLite3.cpp index 3d074d5..cf58159 100644 --- a/src2/CppSQLite3.cpp +++ b/src2/CppSQLite3.cpp @@ -1,1500 +1,3000 @@ -//////////////////////////////////////////////////////////////////////////////// -// CppSQLite3 - A C++ wrapper around the SQLite3 embedded database library. -// -// Copyright (c) 2004 Rob Groves. All Rights Reserved. rob.groves@btinternet.com -// -// Permission to use, copy, modify, and distribute this software and its -// documentation for any purpose, without fee, and without a written -// agreement, is hereby granted, provided that the above copyright notice, -// this paragraph and the following two paragraphs appear in all copies, -// modifications, and distributions. -// -// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, -// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST -// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, -// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF -// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION -// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -// -// V3.0 03/08/2004 -Initial Version for sqlite3 -// -// V3.1 16/09/2004 -Implemented getXXXXField using sqlite3 functions -// -Added CppSQLiteDB3::tableExists() -//////////////////////////////////////////////////////////////////////////////// -#include "CppSQLite3.h" -#include - - -// Named constant for passing to CppSQLite3Exception when passing it a string -// that cannot be deleted. -static const bool DONT_DELETE_MSG=false; - -//////////////////////////////////////////////////////////////////////////////// -// Prototypes for SQLite functions not included in SQLite DLL, but copied below -// from SQLite encode.c -//////////////////////////////////////////////////////////////////////////////// -int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out); -int sqlite3_decode_binary(const unsigned char *in, unsigned char *out); - -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Exception::CppSQLite3Exception(const int nErrCode, - const char* szErrMess, - bool bDeleteMsg/*=true*/) : - mnErrCode(nErrCode) -{ - mpszErrMess = sqlite3_mprintf("%s[%d]: %s", - errorCodeAsString(nErrCode), - nErrCode, - szErrMess ? szErrMess : ""); - /* - if (bDeleteMsg && szErrMess) - { - sqlite3_free(szErrMess); - } - */ -} - -CppSQLite3Exception::CppSQLite3Exception(const int nErrCode, - char* szErrMess, - bool bDeleteMsg/*=true*/) : - mnErrCode(nErrCode) -{ - mpszErrMess = sqlite3_mprintf("%s[%d]: %s", - errorCodeAsString(nErrCode), - nErrCode, - szErrMess ? szErrMess : ""); - - if (bDeleteMsg && szErrMess) - { - sqlite3_free(szErrMess); - } -} - -CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) : - mnErrCode(e.mnErrCode) -{ - mpszErrMess = 0; - if (e.mpszErrMess) - { - mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess); - } -} - - -const char* CppSQLite3Exception::errorCodeAsString(int nErrCode) -{ - switch (nErrCode) - { - case SQLITE_OK : return "SQLITE_OK"; - case SQLITE_ERROR : return "SQLITE_ERROR"; - case SQLITE_INTERNAL : return "SQLITE_INTERNAL"; - case SQLITE_PERM : return "SQLITE_PERM"; - case SQLITE_ABORT : return "SQLITE_ABORT"; - case SQLITE_BUSY : return "SQLITE_BUSY"; - case SQLITE_LOCKED : return "SQLITE_LOCKED"; - case SQLITE_NOMEM : return "SQLITE_NOMEM"; - case SQLITE_READONLY : return "SQLITE_READONLY"; - case SQLITE_INTERRUPT : return "SQLITE_INTERRUPT"; - case SQLITE_IOERR : return "SQLITE_IOERR"; - case SQLITE_CORRUPT : return "SQLITE_CORRUPT"; - case SQLITE_NOTFOUND : return "SQLITE_NOTFOUND"; - case SQLITE_FULL : return "SQLITE_FULL"; - case SQLITE_CANTOPEN : return "SQLITE_CANTOPEN"; - case SQLITE_PROTOCOL : return "SQLITE_PROTOCOL"; - case SQLITE_EMPTY : return "SQLITE_EMPTY"; - case SQLITE_SCHEMA : return "SQLITE_SCHEMA"; - case SQLITE_TOOBIG : return "SQLITE_TOOBIG"; - case SQLITE_CONSTRAINT : return "SQLITE_CONSTRAINT"; - case SQLITE_MISMATCH : return "SQLITE_MISMATCH"; - case SQLITE_MISUSE : return "SQLITE_MISUSE"; - case SQLITE_NOLFS : return "SQLITE_NOLFS"; - case SQLITE_AUTH : return "SQLITE_AUTH"; - case SQLITE_FORMAT : return "SQLITE_FORMAT"; - case SQLITE_RANGE : return "SQLITE_RANGE"; - case SQLITE_ROW : return "SQLITE_ROW"; - case SQLITE_DONE : return "SQLITE_DONE"; - case CPPSQLITE_ERROR : return "CPPSQLITE_ERROR"; - default: return "UNKNOWN_ERROR"; - } -} - - -CppSQLite3Exception::~CppSQLite3Exception() -{ - if (mpszErrMess) - { - sqlite3_free(mpszErrMess); - mpszErrMess = 0; - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Buffer::CppSQLite3Buffer() -{ - mpBuf = 0; -} - - -CppSQLite3Buffer::~CppSQLite3Buffer() -{ - clear(); -} - - -void CppSQLite3Buffer::clear() -{ - if (mpBuf) - { - sqlite3_free(mpBuf); - mpBuf = 0; - } - -} - - -const char* CppSQLite3Buffer::format(const char* szFormat, ...) -{ - clear(); - va_list va; - va_start(va, szFormat); - mpBuf = sqlite3_vmprintf(szFormat, va); - va_end(va); - return mpBuf; -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Binary::CppSQLite3Binary() : - mpBuf(0), - mnBinaryLen(0), - mnBufferLen(0), - mnEncodedLen(0), - mbEncoded(false) -{ -} - - -CppSQLite3Binary::~CppSQLite3Binary() -{ - clear(); -} - - -void CppSQLite3Binary::setBinary(const unsigned char* pBuf, int nLen) -{ - mpBuf = allocBuffer(nLen); - memcpy(mpBuf, pBuf, nLen); -} - - -void CppSQLite3Binary::setEncoded(const unsigned char* pBuf) -{ - clear(); - - mnEncodedLen = strlen((const char*)pBuf); - mnBufferLen = mnEncodedLen + 1; // Allow for NULL terminator - - mpBuf = (unsigned char*)malloc(mnBufferLen); - - if (!mpBuf) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Cannot allocate memory", - DONT_DELETE_MSG); - } - - memcpy(mpBuf, pBuf, mnBufferLen); - mbEncoded = true; -} - - -const unsigned char* CppSQLite3Binary::getEncoded() -{ - if (!mbEncoded) - { - unsigned char* ptmp = (unsigned char*)malloc(mnBinaryLen); - memcpy(ptmp, mpBuf, mnBinaryLen); - mnEncodedLen = sqlite3_encode_binary(ptmp, mnBinaryLen, mpBuf); - free(ptmp); - mbEncoded = true; - } - - return mpBuf; -} - - -const unsigned char* CppSQLite3Binary::getBinary() -{ - if (mbEncoded) - { - // in/out buffers can be the same - mnBinaryLen = sqlite3_decode_binary(mpBuf, mpBuf); - - if (mnBinaryLen == -1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Cannot decode binary", - DONT_DELETE_MSG); - } - - mbEncoded = false; - } - - return mpBuf; -} - - -int CppSQLite3Binary::getBinaryLength() -{ - getBinary(); - return mnBinaryLen; -} - - -unsigned char* CppSQLite3Binary::allocBuffer(int nLen) -{ - clear(); - - // Allow extra space for encoded binary as per comments in - // SQLite encode.c See bottom of this file for implementation - // of SQLite functions use 3 instead of 2 just to be sure ;-) - mnBinaryLen = nLen; - mnBufferLen = 3 + (257*nLen)/254; - - mpBuf = (unsigned char*)malloc(mnBufferLen); - - if (!mpBuf) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Cannot allocate memory", - DONT_DELETE_MSG); - } - - mbEncoded = false; - - return mpBuf; -} - - -void CppSQLite3Binary::clear() -{ - if (mpBuf) - { - mnBinaryLen = 0; - mnBufferLen = 0; - free(mpBuf); - mpBuf = 0; - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Query::CppSQLite3Query() -{ - mpVM = 0; - mbEof = true; - mnCols = 0; - mbOwnVM = false; -} - - -CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query& rQuery) -{ - mpVM = rQuery.mpVM; - // Only one object can own the VM - const_cast(rQuery).mpVM = 0; - mbEof = rQuery.mbEof; - mnCols = rQuery.mnCols; - mbOwnVM = rQuery.mbOwnVM; -} - - -CppSQLite3Query::CppSQLite3Query(sqlite3* pDB, - sqlite3_stmt* pVM, - bool bEof, - bool bOwnVM/*=true*/) -{ - mpDB = pDB; - mpVM = pVM; - mbEof = bEof; - mnCols = sqlite3_column_count(mpVM); - mbOwnVM = bOwnVM; -} - - -CppSQLite3Query::~CppSQLite3Query() -{ - try - { - finalize(); - } - catch (...) - { - } -} - - -CppSQLite3Query& CppSQLite3Query::operator=(const CppSQLite3Query& rQuery) -{ - try - { - finalize(); - } - catch (...) - { - } - mpVM = rQuery.mpVM; - // Only one object can own the VM - const_cast(rQuery).mpVM = 0; - mbEof = rQuery.mbEof; - mnCols = rQuery.mnCols; - mbOwnVM = rQuery.mbOwnVM; - return *this; -} - - -int CppSQLite3Query::numFields() -{ - checkVM(); - return mnCols; -} - - -const char* CppSQLite3Query::fieldValue(int nField) -{ - checkVM(); - - if (nField < 0 || nField > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - return (const char*)sqlite3_column_text(mpVM, nField); -} - - -const char* CppSQLite3Query::fieldValue(const char* szField) -{ - int nField = fieldIndex(szField); - return (const char*)sqlite3_column_text(mpVM, nField); -} - - -int CppSQLite3Query::getIntField(int nField, int nNullValue/*=0*/) -{ - if (fieldDataType(nField) == SQLITE_NULL) - { - return nNullValue; - } - else - { - return sqlite3_column_int(mpVM, nField); - } -} - - -int CppSQLite3Query::getIntField(const char* szField, int nNullValue/*=0*/) -{ - int nField = fieldIndex(szField); - return getIntField(nField, nNullValue); -} - - -double CppSQLite3Query::getFloatField(int nField, double fNullValue/*=0.0*/) -{ - if (fieldDataType(nField) == SQLITE_NULL) - { - return fNullValue; - } - else - { - return sqlite3_column_double(mpVM, nField); - } -} - - -double CppSQLite3Query::getFloatField(const char* szField, double fNullValue/*=0.0*/) -{ - int nField = fieldIndex(szField); - return getFloatField(nField, fNullValue); -} - - -const char* CppSQLite3Query::getStringField(int nField, const char* szNullValue/*=""*/) -{ - if (fieldDataType(nField) == SQLITE_NULL) - { - return szNullValue; - } - else - { - return (const char*)sqlite3_column_text(mpVM, nField); - } -} - - -const char* CppSQLite3Query::getStringField(const char* szField, const char* szNullValue/*=""*/) -{ - int nField = fieldIndex(szField); - return getStringField(nField, szNullValue); -} - - -const unsigned char* CppSQLite3Query::getBlobField(int nField, int& nLen) -{ - checkVM(); - - if (nField < 0 || nField > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - nLen = sqlite3_column_bytes(mpVM, nField); - return (const unsigned char*)sqlite3_column_blob(mpVM, nField); -} - - -const unsigned char* CppSQLite3Query::getBlobField(const char* szField, int& nLen) -{ - int nField = fieldIndex(szField); - return getBlobField(nField, nLen); -} - - -bool CppSQLite3Query::fieldIsNull(int nField) -{ - return (fieldDataType(nField) == SQLITE_NULL); -} - - -bool CppSQLite3Query::fieldIsNull(const char* szField) -{ - int nField = fieldIndex(szField); - return (fieldDataType(nField) == SQLITE_NULL); -} - - -int CppSQLite3Query::fieldIndex(const char* szField) -{ - checkVM(); - - if (szField) - { - for (int nField = 0; nField < mnCols; nField++) - { - const char* szTemp = sqlite3_column_name(mpVM, nField); - - if (strcmp(szField, szTemp) == 0) - { - return nField; - } - } - } - - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field name requested", - DONT_DELETE_MSG); -} - - -const char* CppSQLite3Query::fieldName(int nCol) -{ - checkVM(); - - if (nCol < 0 || nCol > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - return sqlite3_column_name(mpVM, nCol); -} - - -const char* CppSQLite3Query::fieldDeclType(int nCol) -{ - checkVM(); - - if (nCol < 0 || nCol > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - return sqlite3_column_decltype(mpVM, nCol); -} - - -int CppSQLite3Query::fieldDataType(int nCol) -{ - checkVM(); - - if (nCol < 0 || nCol > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - return sqlite3_column_type(mpVM, nCol); -} - - -bool CppSQLite3Query::eof() -{ - checkVM(); - return mbEof; -} - - -void CppSQLite3Query::nextRow() -{ - checkVM(); - - int nRet = sqlite3_step(mpVM); - - if (nRet == SQLITE_DONE) - { - // no rows - mbEof = true; - } - else if (nRet == SQLITE_ROW) - { - // more rows, nothing to do - } - else - { - nRet = sqlite3_finalize(mpVM); - mpVM = 0; - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, - (char*)szError, - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Query::finalize() -{ - if (mpVM && mbOwnVM) - { - int nRet = sqlite3_finalize(mpVM); - mpVM = 0; - if (nRet != SQLITE_OK) - { - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } - } -} - - -void CppSQLite3Query::checkVM() -{ - if (mpVM == 0) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Null Virtual Machine pointer", - DONT_DELETE_MSG); - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Table::CppSQLite3Table() -{ - mpaszResults = 0; - mnRows = 0; - mnCols = 0; - mnCurrentRow = 0; -} - - -CppSQLite3Table::CppSQLite3Table(const CppSQLite3Table& rTable) -{ - mpaszResults = rTable.mpaszResults; - // Only one object can own the results - const_cast(rTable).mpaszResults = 0; - mnRows = rTable.mnRows; - mnCols = rTable.mnCols; - mnCurrentRow = rTable.mnCurrentRow; -} - - -CppSQLite3Table::CppSQLite3Table(char** paszResults, int nRows, int nCols) -{ - mpaszResults = paszResults; - mnRows = nRows; - mnCols = nCols; - mnCurrentRow = 0; -} - - -CppSQLite3Table::~CppSQLite3Table() -{ - try - { - finalize(); - } - catch (...) - { - } -} - - -CppSQLite3Table& CppSQLite3Table::operator=(const CppSQLite3Table& rTable) -{ - try - { - finalize(); - } - catch (...) - { - } - mpaszResults = rTable.mpaszResults; - // Only one object can own the results - const_cast(rTable).mpaszResults = 0; - mnRows = rTable.mnRows; - mnCols = rTable.mnCols; - mnCurrentRow = rTable.mnCurrentRow; - return *this; -} - - -void CppSQLite3Table::finalize() -{ - if (mpaszResults) - { - sqlite3_free_table(mpaszResults); - mpaszResults = 0; - } -} - - -int CppSQLite3Table::numFields() -{ - checkResults(); - return mnCols; -} - - -int CppSQLite3Table::numRows() -{ - checkResults(); - return mnRows; -} - - -const char* CppSQLite3Table::fieldValue(int nField) -{ - checkResults(); - - if (nField < 0 || nField > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - int nIndex = (mnCurrentRow*mnCols) + mnCols + nField; - return mpaszResults[nIndex]; -} - - -const char* CppSQLite3Table::fieldValue(const char* szField) -{ - checkResults(); - - if (szField) - { - for (int nField = 0; nField < mnCols; nField++) - { - if (strcmp(szField, mpaszResults[nField]) == 0) - { - int nIndex = (mnCurrentRow*mnCols) + mnCols + nField; - return mpaszResults[nIndex]; - } - } - } - - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field name requested", - DONT_DELETE_MSG); -} - - -int CppSQLite3Table::getIntField(int nField, int nNullValue/*=0*/) -{ - if (fieldIsNull(nField)) - { - return nNullValue; - } - else - { - return atoi(fieldValue(nField)); - } -} - - -int CppSQLite3Table::getIntField(const char* szField, int nNullValue/*=0*/) -{ - if (fieldIsNull(szField)) - { - return nNullValue; - } - else - { - return atoi(fieldValue(szField)); - } -} - - -double CppSQLite3Table::getFloatField(int nField, double fNullValue/*=0.0*/) -{ - if (fieldIsNull(nField)) - { - return fNullValue; - } - else - { - return atof(fieldValue(nField)); - } -} - - -double CppSQLite3Table::getFloatField(const char* szField, double fNullValue/*=0.0*/) -{ - if (fieldIsNull(szField)) - { - return fNullValue; - } - else - { - return atof(fieldValue(szField)); - } -} - - -const char* CppSQLite3Table::getStringField(int nField, const char* szNullValue/*=""*/) -{ - if (fieldIsNull(nField)) - { - return szNullValue; - } - else - { - return fieldValue(nField); - } -} - - -const char* CppSQLite3Table::getStringField(const char* szField, const char* szNullValue/*=""*/) -{ - if (fieldIsNull(szField)) - { - return szNullValue; - } - else - { - return fieldValue(szField); - } -} - - -bool CppSQLite3Table::fieldIsNull(int nField) -{ - checkResults(); - return (fieldValue(nField) == 0); -} - - -bool CppSQLite3Table::fieldIsNull(const char* szField) -{ - checkResults(); - return (fieldValue(szField) == 0); -} - - -const char* CppSQLite3Table::fieldName(int nCol) -{ - checkResults(); - - if (nCol < 0 || nCol > mnCols-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid field index requested", - DONT_DELETE_MSG); - } - - return mpaszResults[nCol]; -} - - -void CppSQLite3Table::setRow(int nRow) -{ - checkResults(); - - if (nRow < 0 || nRow > mnRows-1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid row index requested", - DONT_DELETE_MSG); - } - - mnCurrentRow = nRow; -} - - -void CppSQLite3Table::checkResults() -{ - if (mpaszResults == 0) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Null Results pointer", - DONT_DELETE_MSG); - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3Statement::CppSQLite3Statement() -{ - mpDB = 0; - mpVM = 0; -} - - -CppSQLite3Statement::CppSQLite3Statement(const CppSQLite3Statement& rStatement) -{ - mpDB = rStatement.mpDB; - mpVM = rStatement.mpVM; - // Only one object can own VM - const_cast(rStatement).mpVM = 0; -} - - -CppSQLite3Statement::CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM) -{ - mpDB = pDB; - mpVM = pVM; -} - - -CppSQLite3Statement::~CppSQLite3Statement() -{ - try - { - finalize(); - } - catch (...) - { - } -} - - -CppSQLite3Statement& CppSQLite3Statement::operator=(const CppSQLite3Statement& rStatement) -{ - mpDB = rStatement.mpDB; - mpVM = rStatement.mpVM; - // Only one object can own VM - const_cast(rStatement).mpVM = 0; - return *this; -} - - -int CppSQLite3Statement::execDML() -{ - checkDB(); - checkVM(); - - const char* szError=0; - - int nRet = sqlite3_step(mpVM); - - if (nRet == SQLITE_DONE) - { - int nRowsChanged = sqlite3_changes(mpDB); - - nRet = sqlite3_reset(mpVM); - - if (nRet != SQLITE_OK) - { - szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } - - return nRowsChanged; - } - else - { - nRet = sqlite3_reset(mpVM); - szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } -} - - -CppSQLite3Query CppSQLite3Statement::execQuery() -{ - checkDB(); - checkVM(); - - int nRet = sqlite3_step(mpVM); - - if (nRet == SQLITE_DONE) - { - // no rows - return CppSQLite3Query(mpDB, mpVM, true/*eof*/, false); - } - else if (nRet == SQLITE_ROW) - { - // at least 1 row - return CppSQLite3Query(mpDB, mpVM, false/*eof*/, false); - } - else - { - nRet = sqlite3_reset(mpVM); - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::bind(int nParam, const char* szValue) -{ - checkVM(); - int nRes = sqlite3_bind_text(mpVM, nParam, szValue, -1, SQLITE_TRANSIENT); - - if (nRes != SQLITE_OK) - { - throw CppSQLite3Exception(nRes, - "Error binding string param", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::bind(int nParam, const int nValue) -{ - checkVM(); - int nRes = sqlite3_bind_int(mpVM, nParam, nValue); - - if (nRes != SQLITE_OK) - { - throw CppSQLite3Exception(nRes, - "Error binding int param", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::bind(int nParam, const double dValue) -{ - checkVM(); - int nRes = sqlite3_bind_double(mpVM, nParam, dValue); - - if (nRes != SQLITE_OK) - { - throw CppSQLite3Exception(nRes, - "Error binding double param", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::bind(int nParam, const unsigned char* blobValue, int nLen) -{ - checkVM(); - int nRes = sqlite3_bind_blob(mpVM, nParam, - (const void*)blobValue, nLen, SQLITE_TRANSIENT); - - if (nRes != SQLITE_OK) - { - throw CppSQLite3Exception(nRes, - "Error binding blob param", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::bindNull(int nParam) -{ - checkVM(); - int nRes = sqlite3_bind_null(mpVM, nParam); - - if (nRes != SQLITE_OK) - { - throw CppSQLite3Exception(nRes, - "Error binding NULL param", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::reset() -{ - if (mpVM) - { - int nRet = sqlite3_reset(mpVM); - - if (nRet != SQLITE_OK) - { - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } - } -} - - -void CppSQLite3Statement::finalize() -{ - if (mpVM) - { - int nRet = sqlite3_finalize(mpVM); - mpVM = 0; - - if (nRet != SQLITE_OK) - { - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } - } -} - - -void CppSQLite3Statement::checkDB() -{ - if (mpDB == 0) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Database not open", - DONT_DELETE_MSG); - } -} - - -void CppSQLite3Statement::checkVM() -{ - if (mpVM == 0) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Null Virtual Machine pointer", - DONT_DELETE_MSG); - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -CppSQLite3DB::CppSQLite3DB() -{ - mpDB = 0; - mnBusyTimeoutMs = 60000; // 60 seconds -} - - -CppSQLite3DB::CppSQLite3DB(const CppSQLite3DB& db) -{ - mpDB = db.mpDB; - mnBusyTimeoutMs = 60000; // 60 seconds -} - - -CppSQLite3DB::~CppSQLite3DB() -{ - close(); -} - - -CppSQLite3DB& CppSQLite3DB::operator=(const CppSQLite3DB& db) -{ - mpDB = db.mpDB; - mnBusyTimeoutMs = 60000; // 60 seconds - return *this; -} - - -void CppSQLite3DB::open(const char* szFile) -{ - int nRet = sqlite3_open(szFile, &mpDB); - - if (nRet != SQLITE_OK) - { - const char* szError = sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } - - setBusyTimeout(mnBusyTimeoutMs); -} - - -void CppSQLite3DB::close() -{ - if (mpDB) - { - sqlite3_close(mpDB); - mpDB = 0; - } -} - - -CppSQLite3Statement CppSQLite3DB::compileStatement(const char* szSQL) -{ - checkDB(); - - sqlite3_stmt* pVM = compile(szSQL); - return CppSQLite3Statement(mpDB, pVM); -} - - -bool CppSQLite3DB::tableExists(const char* szTable) -{ - char szSQL[128]; - sprintf(szSQL, - "select count(*) from sqlite_master where type='table' and name='%s'", - szTable); - int nRet = execScalar(szSQL); - return (nRet > 0); -} - - -int CppSQLite3DB::execDML(const char* szSQL) -{ - checkDB(); - - char* szError=0; - - int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError); - - if (nRet == SQLITE_OK) - { - return sqlite3_changes(mpDB); - } - else - { - throw CppSQLite3Exception(nRet, szError); - } -} - - -CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL) -{ - checkDB(); - - sqlite3_stmt* pVM = compile(szSQL); - - int nRet = sqlite3_step(pVM); - - if (nRet == SQLITE_DONE) - { - // no rows - return CppSQLite3Query(mpDB, pVM, true/*eof*/); - } - else if (nRet == SQLITE_ROW) - { - // at least 1 row - return CppSQLite3Query(mpDB, pVM, false/*eof*/); - } - else - { - nRet = sqlite3_finalize(pVM); - const char* szError= sqlite3_errmsg(mpDB); - throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); - } -} - - -int CppSQLite3DB::execScalar(const char* szSQL) -{ - CppSQLite3Query q = execQuery(szSQL); - - if (q.eof() || q.numFields() < 1) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Invalid scalar query", - DONT_DELETE_MSG); - } - - return atoi(q.fieldValue(0)); -} - - -CppSQLite3Table CppSQLite3DB::getTable(const char* szSQL) -{ - checkDB(); - - char* szError=0; - char** paszResults=0; - int nRet; - int nRows(0); - int nCols(0); - - nRet = sqlite3_get_table(mpDB, szSQL, &paszResults, &nRows, &nCols, &szError); - - if (nRet == SQLITE_OK) - { - return CppSQLite3Table(paszResults, nRows, nCols); - } - else - { - throw CppSQLite3Exception(nRet, szError); - } -} - - -sqlite_int64 CppSQLite3DB::lastRowId() -{ - return sqlite3_last_insert_rowid(mpDB); -} - - -void CppSQLite3DB::setBusyTimeout(int nMillisecs) -{ - mnBusyTimeoutMs = nMillisecs; - sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs); -} - - -void CppSQLite3DB::checkDB() -{ - if (!mpDB) - { - throw CppSQLite3Exception(CPPSQLITE_ERROR, - "Database not open", - DONT_DELETE_MSG); - } -} - - -sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL) -{ - checkDB(); - - char* szError=0; - const char* szTail=0; - sqlite3_stmt* pVM; - - int nRet = sqlite3_prepare(mpDB, szSQL, -1, &pVM, &szTail); - - if (nRet != SQLITE_OK) - { - throw CppSQLite3Exception(nRet, szError); - } - - return pVM; -} - - -//////////////////////////////////////////////////////////////////////////////// -// SQLite encode.c reproduced here, containing implementation notes and source -// for sqlite3_encode_binary() and sqlite3_decode_binary() -//////////////////////////////////////////////////////////////////////////////// - -/* -** 2002 April 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains helper routines used to translate binary data into -** a null-terminated string (suitable for use in SQLite) and back again. -** These are convenience routines for use by people who want to store binary -** data in an SQLite database. The code in this file is not used by any other -** part of the SQLite library. -** -** $Id: CppSQLite3.cpp,v 1.1 2009/02/09 10:09:33 guigues Exp $ -*/ - -/* -** How This Encoder Works -** -** The output is allowed to contain any character except 0x27 (') and -** 0x00. This is accomplished by using an escape character to encode -** 0x27 and 0x00 as a two-byte sequence. The escape character is always -** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The -** 0x27 character is encoded as the two byte sequence 0x01 0x03. Finally, -** the escape character itself is encoded as the two-character sequence -** 0x01 0x02. -** -** To summarize, the encoder works by using an escape sequences as follows: -** -** 0x00 -> 0x01 0x01 -** 0x01 -> 0x01 0x02 -** 0x27 -> 0x01 0x03 -** -** If that were all the encoder did, it would work, but in certain cases -** it could double the size of the encoded string. For example, to -** encode a string of 100 0x27 characters would require 100 instances of -** the 0x01 0x03 escape sequence resulting in a 200-character output. -** We would prefer to keep the size of the encoded string smaller than -** this. -** -** To minimize the encoding size, we first add a fixed offset value to each -** byte in the sequence. The addition is modulo 256. (That is to say, if -** the sum of the original character value and the offset exceeds 256, then -** the higher order bits are truncated.) The offset is chosen to minimize -** the number of characters in the string that need to be escaped. For -** example, in the case above where the string was composed of 100 0x27 -** characters, the offset might be 0x01. Each of the 0x27 characters would -** then be converted into an 0x28 character which would not need to be -** escaped at all and so the 100 character input string would be converted -** into just 100 characters of output. Actually 101 characters of output - -** we have to record the offset used as the first byte in the sequence so -** that the string can be decoded. Since the offset value is stored as -** part of the output string and the output string is not allowed to contain -** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27. -** -** Here, then, are the encoding steps: -** -** (1) Choose an offset value and make it the first character of -** output. -** -** (2) Copy each input character into the output buffer, one by -** one, adding the offset value as you copy. -** -** (3) If the value of an input character plus offset is 0x00, replace -** that one character by the two-character sequence 0x01 0x01. -** If the sum is 0x01, replace it with 0x01 0x02. If the sum -** is 0x27, replace it with 0x01 0x03. -** -** (4) Put a 0x00 terminator at the end of the output. -** -** Decoding is obvious: -** -** (5) Copy encoded characters except the first into the decode -** buffer. Set the first encoded character aside for use as -** the offset in step 7 below. -** -** (6) Convert each 0x01 0x01 sequence into a single character 0x00. -** Convert 0x01 0x02 into 0x01. Convert 0x01 0x03 into 0x27. -** -** (7) Subtract the offset value that was the first character of -** the encoded buffer from all characters in the output buffer. -** -** The only tricky part is step (1) - how to compute an offset value to -** minimize the size of the output buffer. This is accomplished by testing -** all offset values and picking the one that results in the fewest number -** of escapes. To do that, we first scan the entire input and count the -** number of occurances of each character value in the input. Suppose -** the number of 0x00 characters is N(0), the number of occurances of 0x01 -** is N(1), and so forth up to the number of occurances of 0xff is N(255). -** An offset of 0 is not allowed so we don't have to test it. The number -** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number -** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth. -** In this way we find the offset that gives the minimum number of escapes, -** and thus minimizes the length of the output string. -*/ - -/* -** Encode a binary buffer "in" of size n bytes so that it contains -** no instances of characters '\'' or '\000'. The output is -** null-terminated and can be used as a string value in an INSERT -** or UPDATE statement. Use sqlite3_decode_binary() to convert the -** string back into its original binary. -** -** The result is written into a preallocated output buffer "out". -** "out" must be able to hold at least 2 +(257*n)/254 bytes. -** In other words, the output will be expanded by as much as 3 -** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. -** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) -** -** The return value is the number of characters in the encoded -** string, excluding the "\000" terminator. -*/ -int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out){ - int i, j, e, m; - int cnt[256]; - if( n<=0 ){ - out[0] = 'x'; - out[1] = 0; - return 1; - } - memset(cnt, 0, sizeof(cnt)); - for(i=n-1; i>=0; i--){ cnt[in[i]]++; } - m = n; - for(i=1; i<256; i++){ - int sum; - if( i=='\'' ) continue; - sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff]; - if( sum + + + + + +// Named constant for passing to CppSQLite3Exception when passing it a string + +// that cannot be deleted. + +static const bool DONT_DELETE_MSG=false; + + + +//////////////////////////////////////////////////////////////////////////////// + +// Prototypes for SQLite functions not included in SQLite DLL, but copied below + +// from SQLite encode.c + +//////////////////////////////////////////////////////////////////////////////// + +int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out); + +int sqlite3_decode_binary(const unsigned char *in, unsigned char *out); + + + +//////////////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Exception::CppSQLite3Exception(const int nErrCode, + + const char* szErrMess, + + bool bDeleteMsg/*=true*/) : + + mnErrCode(nErrCode) + +{ + + mpszErrMess = sqlite3_mprintf("%s[%d]: %s", + + errorCodeAsString(nErrCode), + + nErrCode, + + szErrMess ? szErrMess : ""); + + /* + + if (bDeleteMsg && szErrMess) + + { + + sqlite3_free(szErrMess); + + } + + */ + +} + + + +CppSQLite3Exception::CppSQLite3Exception(const int nErrCode, + + char* szErrMess, + + bool bDeleteMsg/*=true*/) : + + mnErrCode(nErrCode) + +{ + + mpszErrMess = sqlite3_mprintf("%s[%d]: %s", + + errorCodeAsString(nErrCode), + + nErrCode, + + szErrMess ? szErrMess : ""); + + + + if (bDeleteMsg && szErrMess) + + { + + sqlite3_free(szErrMess); + + } + +} + + + +CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) : + + mnErrCode(e.mnErrCode) + +{ + + mpszErrMess = 0; + + if (e.mpszErrMess) + + { + + mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess); + + } + +} + + + + + +const char* CppSQLite3Exception::errorCodeAsString(int nErrCode) + +{ + + switch (nErrCode) + + { + + case SQLITE_OK : return "SQLITE_OK"; + + case SQLITE_ERROR : return "SQLITE_ERROR"; + + case SQLITE_INTERNAL : return "SQLITE_INTERNAL"; + + case SQLITE_PERM : return "SQLITE_PERM"; + + case SQLITE_ABORT : return "SQLITE_ABORT"; + + case SQLITE_BUSY : return "SQLITE_BUSY"; + + case SQLITE_LOCKED : return "SQLITE_LOCKED"; + + case SQLITE_NOMEM : return "SQLITE_NOMEM"; + + case SQLITE_READONLY : return "SQLITE_READONLY"; + + case SQLITE_INTERRUPT : return "SQLITE_INTERRUPT"; + + case SQLITE_IOERR : return "SQLITE_IOERR"; + + case SQLITE_CORRUPT : return "SQLITE_CORRUPT"; + + case SQLITE_NOTFOUND : return "SQLITE_NOTFOUND"; + + case SQLITE_FULL : return "SQLITE_FULL"; + + case SQLITE_CANTOPEN : return "SQLITE_CANTOPEN"; + + case SQLITE_PROTOCOL : return "SQLITE_PROTOCOL"; + + case SQLITE_EMPTY : return "SQLITE_EMPTY"; + + case SQLITE_SCHEMA : return "SQLITE_SCHEMA"; + + case SQLITE_TOOBIG : return "SQLITE_TOOBIG"; + + case SQLITE_CONSTRAINT : return "SQLITE_CONSTRAINT"; + + case SQLITE_MISMATCH : return "SQLITE_MISMATCH"; + + case SQLITE_MISUSE : return "SQLITE_MISUSE"; + + case SQLITE_NOLFS : return "SQLITE_NOLFS"; + + case SQLITE_AUTH : return "SQLITE_AUTH"; + + case SQLITE_FORMAT : return "SQLITE_FORMAT"; + + case SQLITE_RANGE : return "SQLITE_RANGE"; + + case SQLITE_ROW : return "SQLITE_ROW"; + + case SQLITE_DONE : return "SQLITE_DONE"; + + case CPPSQLITE_ERROR : return "CPPSQLITE_ERROR"; + + default: return "UNKNOWN_ERROR"; + + } + +} + + + + + +CppSQLite3Exception::~CppSQLite3Exception() + +{ + + if (mpszErrMess) + + { + + sqlite3_free(mpszErrMess); + + mpszErrMess = 0; + + } + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Buffer::CppSQLite3Buffer() + +{ + + mpBuf = 0; + +} + + + + + +CppSQLite3Buffer::~CppSQLite3Buffer() + +{ + + clear(); + +} + + + + + +void CppSQLite3Buffer::clear() + +{ + + if (mpBuf) + + { + + sqlite3_free(mpBuf); + + mpBuf = 0; + + } + + + +} + + + + + +const char* CppSQLite3Buffer::format(const char* szFormat, ...) + +{ + + clear(); + + va_list va; + + va_start(va, szFormat); + + mpBuf = sqlite3_vmprintf(szFormat, va); + + va_end(va); + + return mpBuf; + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Binary::CppSQLite3Binary() : + + mpBuf(0), + + mnBinaryLen(0), + + mnBufferLen(0), + + mnEncodedLen(0), + + mbEncoded(false) + +{ + +} + + + + + +CppSQLite3Binary::~CppSQLite3Binary() + +{ + + clear(); + +} + + + + + +void CppSQLite3Binary::setBinary(const unsigned char* pBuf, int nLen) + +{ + + mpBuf = allocBuffer(nLen); + + memcpy(mpBuf, pBuf, nLen); + +} + + + + + +void CppSQLite3Binary::setEncoded(const unsigned char* pBuf) + +{ + + clear(); + + + + mnEncodedLen = strlen((const char*)pBuf); + + mnBufferLen = mnEncodedLen + 1; // Allow for NULL terminator + + + + mpBuf = (unsigned char*)malloc(mnBufferLen); + + + + if (!mpBuf) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Cannot allocate memory", + + DONT_DELETE_MSG); + + } + + + + memcpy(mpBuf, pBuf, mnBufferLen); + + mbEncoded = true; + +} + + + + + +const unsigned char* CppSQLite3Binary::getEncoded() + +{ + + if (!mbEncoded) + + { + + unsigned char* ptmp = (unsigned char*)malloc(mnBinaryLen); + + memcpy(ptmp, mpBuf, mnBinaryLen); + + mnEncodedLen = sqlite3_encode_binary(ptmp, mnBinaryLen, mpBuf); + + free(ptmp); + + mbEncoded = true; + + } + + + + return mpBuf; + +} + + + + + +const unsigned char* CppSQLite3Binary::getBinary() + +{ + + if (mbEncoded) + + { + + // in/out buffers can be the same + + mnBinaryLen = sqlite3_decode_binary(mpBuf, mpBuf); + + + + if (mnBinaryLen == -1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Cannot decode binary", + + DONT_DELETE_MSG); + + } + + + + mbEncoded = false; + + } + + + + return mpBuf; + +} + + + + + +int CppSQLite3Binary::getBinaryLength() + +{ + + getBinary(); + + return mnBinaryLen; + +} + + + + + +unsigned char* CppSQLite3Binary::allocBuffer(int nLen) + +{ + + clear(); + + + + // Allow extra space for encoded binary as per comments in + + // SQLite encode.c See bottom of this file for implementation + + // of SQLite functions use 3 instead of 2 just to be sure ;-) + + mnBinaryLen = nLen; + + mnBufferLen = 3 + (257*nLen)/254; + + + + mpBuf = (unsigned char*)malloc(mnBufferLen); + + + + if (!mpBuf) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Cannot allocate memory", + + DONT_DELETE_MSG); + + } + + + + mbEncoded = false; + + + + return mpBuf; + +} + + + + + +void CppSQLite3Binary::clear() + +{ + + if (mpBuf) + + { + + mnBinaryLen = 0; + + mnBufferLen = 0; + + free(mpBuf); + + mpBuf = 0; + + } + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Query::CppSQLite3Query() + +{ + + mpVM = 0; + + mbEof = true; + + mnCols = 0; + + mbOwnVM = false; + +} + + + + + +CppSQLite3Query::CppSQLite3Query(const CppSQLite3Query& rQuery) + +{ + + mpVM = rQuery.mpVM; + + // Only one object can own the VM + + const_cast(rQuery).mpVM = 0; + + mbEof = rQuery.mbEof; + + mnCols = rQuery.mnCols; + + mbOwnVM = rQuery.mbOwnVM; + +} + + + + + +CppSQLite3Query::CppSQLite3Query(sqlite3* pDB, + + sqlite3_stmt* pVM, + + bool bEof, + + bool bOwnVM/*=true*/) + +{ + + mpDB = pDB; + + mpVM = pVM; + + mbEof = bEof; + + mnCols = sqlite3_column_count(mpVM); + + mbOwnVM = bOwnVM; + +} + + + + + +CppSQLite3Query::~CppSQLite3Query() + +{ + + try + + { + + finalize(); + + } + + catch (...) + + { + + } + +} + + + + + +CppSQLite3Query& CppSQLite3Query::operator=(const CppSQLite3Query& rQuery) + +{ + + try + + { + + finalize(); + + } + + catch (...) + + { + + } + + mpVM = rQuery.mpVM; + + // Only one object can own the VM + + const_cast(rQuery).mpVM = 0; + + mbEof = rQuery.mbEof; + + mnCols = rQuery.mnCols; + + mbOwnVM = rQuery.mbOwnVM; + + return *this; + +} + + + + + +int CppSQLite3Query::numFields() + +{ + + checkVM(); + + return mnCols; + +} + + + + + +const char* CppSQLite3Query::fieldValue(int nField) + +{ + + checkVM(); + + + + if (nField < 0 || nField > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + return (const char*)sqlite3_column_text(mpVM, nField); + +} + + + + + +const char* CppSQLite3Query::fieldValue(const char* szField) + +{ + + int nField = fieldIndex(szField); + + return (const char*)sqlite3_column_text(mpVM, nField); + +} + + + + + +int CppSQLite3Query::getIntField(int nField, int nNullValue/*=0*/) + +{ + + if (fieldDataType(nField) == SQLITE_NULL) + + { + + return nNullValue; + + } + + else + + { + + return sqlite3_column_int(mpVM, nField); + + } + +} + + + + + +int CppSQLite3Query::getIntField(const char* szField, int nNullValue/*=0*/) + +{ + + int nField = fieldIndex(szField); + + return getIntField(nField, nNullValue); + +} + + + + + +double CppSQLite3Query::getFloatField(int nField, double fNullValue/*=0.0*/) + +{ + + if (fieldDataType(nField) == SQLITE_NULL) + + { + + return fNullValue; + + } + + else + + { + + return sqlite3_column_double(mpVM, nField); + + } + +} + + + + + +double CppSQLite3Query::getFloatField(const char* szField, double fNullValue/*=0.0*/) + +{ + + int nField = fieldIndex(szField); + + return getFloatField(nField, fNullValue); + +} + + + + + +const char* CppSQLite3Query::getStringField(int nField, const char* szNullValue/*=""*/) + +{ + + if (fieldDataType(nField) == SQLITE_NULL) + + { + + return szNullValue; + + } + + else + + { + + return (const char*)sqlite3_column_text(mpVM, nField); + + } + +} + + + + + +const char* CppSQLite3Query::getStringField(const char* szField, const char* szNullValue/*=""*/) + +{ + + int nField = fieldIndex(szField); + + return getStringField(nField, szNullValue); + +} + + + + + +const unsigned char* CppSQLite3Query::getBlobField(int nField, int& nLen) + +{ + + checkVM(); + + + + if (nField < 0 || nField > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + nLen = sqlite3_column_bytes(mpVM, nField); + + return (const unsigned char*)sqlite3_column_blob(mpVM, nField); + +} + + + + + +const unsigned char* CppSQLite3Query::getBlobField(const char* szField, int& nLen) + +{ + + int nField = fieldIndex(szField); + + return getBlobField(nField, nLen); + +} + + + + + +bool CppSQLite3Query::fieldIsNull(int nField) + +{ + + return (fieldDataType(nField) == SQLITE_NULL); + +} + + + + + +bool CppSQLite3Query::fieldIsNull(const char* szField) + +{ + + int nField = fieldIndex(szField); + + return (fieldDataType(nField) == SQLITE_NULL); + +} + + + + + +int CppSQLite3Query::fieldIndex(const char* szField) + +{ + + checkVM(); + + + + if (szField) + + { + + for (int nField = 0; nField < mnCols; nField++) + + { + + const char* szTemp = sqlite3_column_name(mpVM, nField); + + + + if (strcmp(szField, szTemp) == 0) + + { + + return nField; + + } + + } + + } + + + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field name requested", + + DONT_DELETE_MSG); + +} + + + + + +const char* CppSQLite3Query::fieldName(int nCol) + +{ + + checkVM(); + + + + if (nCol < 0 || nCol > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + return sqlite3_column_name(mpVM, nCol); + +} + + + + + +const char* CppSQLite3Query::fieldDeclType(int nCol) + +{ + + checkVM(); + + + + if (nCol < 0 || nCol > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + return sqlite3_column_decltype(mpVM, nCol); + +} + + + + + +int CppSQLite3Query::fieldDataType(int nCol) + +{ + + checkVM(); + + + + if (nCol < 0 || nCol > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + return sqlite3_column_type(mpVM, nCol); + +} + + + + + +bool CppSQLite3Query::eof() + +{ + + checkVM(); + + return mbEof; + +} + + + + + +void CppSQLite3Query::nextRow() + +{ + + checkVM(); + + + + int nRet = sqlite3_step(mpVM); + + + + if (nRet == SQLITE_DONE) + + { + + // no rows + + mbEof = true; + + } + + else if (nRet == SQLITE_ROW) + + { + + // more rows, nothing to do + + } + + else + + { + + nRet = sqlite3_finalize(mpVM); + + mpVM = 0; + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, + + (char*)szError, + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Query::finalize() + +{ + + if (mpVM && mbOwnVM) + + { + + int nRet = sqlite3_finalize(mpVM); + + mpVM = 0; + + if (nRet != SQLITE_OK) + + { + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + + } + +} + + + + + +void CppSQLite3Query::checkVM() + +{ + + if (mpVM == 0) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Null Virtual Machine pointer", + + DONT_DELETE_MSG); + + } + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Table::CppSQLite3Table() + +{ + + mpaszResults = 0; + + mnRows = 0; + + mnCols = 0; + + mnCurrentRow = 0; + +} + + + + + +CppSQLite3Table::CppSQLite3Table(const CppSQLite3Table& rTable) + +{ + + mpaszResults = rTable.mpaszResults; + + // Only one object can own the results + + const_cast(rTable).mpaszResults = 0; + + mnRows = rTable.mnRows; + + mnCols = rTable.mnCols; + + mnCurrentRow = rTable.mnCurrentRow; + +} + + + + + +CppSQLite3Table::CppSQLite3Table(char** paszResults, int nRows, int nCols) + +{ + + mpaszResults = paszResults; + + mnRows = nRows; + + mnCols = nCols; + + mnCurrentRow = 0; + +} + + + + + +CppSQLite3Table::~CppSQLite3Table() + +{ + + try + + { + + finalize(); + + } + + catch (...) + + { + + } + +} + + + + + +CppSQLite3Table& CppSQLite3Table::operator=(const CppSQLite3Table& rTable) + +{ + + try + + { + + finalize(); + + } + + catch (...) + + { + + } + + mpaszResults = rTable.mpaszResults; + + // Only one object can own the results + + const_cast(rTable).mpaszResults = 0; + + mnRows = rTable.mnRows; + + mnCols = rTable.mnCols; + + mnCurrentRow = rTable.mnCurrentRow; + + return *this; + +} + + + + + +void CppSQLite3Table::finalize() + +{ + + if (mpaszResults) + + { + + sqlite3_free_table(mpaszResults); + + mpaszResults = 0; + + } + +} + + + + + +int CppSQLite3Table::numFields() + +{ + + checkResults(); + + return mnCols; + +} + + + + + +int CppSQLite3Table::numRows() + +{ + + checkResults(); + + return mnRows; + +} + + + + + +const char* CppSQLite3Table::fieldValue(int nField) + +{ + + checkResults(); + + + + if (nField < 0 || nField > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + int nIndex = (mnCurrentRow*mnCols) + mnCols + nField; + + return mpaszResults[nIndex]; + +} + + + + + +const char* CppSQLite3Table::fieldValue(const char* szField) + +{ + + checkResults(); + + + + if (szField) + + { + + for (int nField = 0; nField < mnCols; nField++) + + { + + if (strcmp(szField, mpaszResults[nField]) == 0) + + { + + int nIndex = (mnCurrentRow*mnCols) + mnCols + nField; + + return mpaszResults[nIndex]; + + } + + } + + } + + + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field name requested", + + DONT_DELETE_MSG); + +} + + + + + +int CppSQLite3Table::getIntField(int nField, int nNullValue/*=0*/) + +{ + + if (fieldIsNull(nField)) + + { + + return nNullValue; + + } + + else + + { + + return atoi(fieldValue(nField)); + + } + +} + + + + + +int CppSQLite3Table::getIntField(const char* szField, int nNullValue/*=0*/) + +{ + + if (fieldIsNull(szField)) + + { + + return nNullValue; + + } + + else + + { + + return atoi(fieldValue(szField)); + + } + +} + + + + + +double CppSQLite3Table::getFloatField(int nField, double fNullValue/*=0.0*/) + +{ + + if (fieldIsNull(nField)) + + { + + return fNullValue; + + } + + else + + { + + return atof(fieldValue(nField)); + + } + +} + + + + + +double CppSQLite3Table::getFloatField(const char* szField, double fNullValue/*=0.0*/) + +{ + + if (fieldIsNull(szField)) + + { + + return fNullValue; + + } + + else + + { + + return atof(fieldValue(szField)); + + } + +} + + + + + +const char* CppSQLite3Table::getStringField(int nField, const char* szNullValue/*=""*/) + +{ + + if (fieldIsNull(nField)) + + { + + return szNullValue; + + } + + else + + { + + return fieldValue(nField); + + } + +} + + + + + +const char* CppSQLite3Table::getStringField(const char* szField, const char* szNullValue/*=""*/) + +{ + + if (fieldIsNull(szField)) + + { + + return szNullValue; + + } + + else + + { + + return fieldValue(szField); + + } + +} + + + + + +bool CppSQLite3Table::fieldIsNull(int nField) + +{ + + checkResults(); + + return (fieldValue(nField) == 0); + +} + + + + + +bool CppSQLite3Table::fieldIsNull(const char* szField) + +{ + + checkResults(); + + return (fieldValue(szField) == 0); + +} + + + + + +const char* CppSQLite3Table::fieldName(int nCol) + +{ + + checkResults(); + + + + if (nCol < 0 || nCol > mnCols-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid field index requested", + + DONT_DELETE_MSG); + + } + + + + return mpaszResults[nCol]; + +} + + + + + +void CppSQLite3Table::setRow(int nRow) + +{ + + checkResults(); + + + + if (nRow < 0 || nRow > mnRows-1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid row index requested", + + DONT_DELETE_MSG); + + } + + + + mnCurrentRow = nRow; + +} + + + + + +void CppSQLite3Table::checkResults() + +{ + + if (mpaszResults == 0) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Null Results pointer", + + DONT_DELETE_MSG); + + } + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3Statement::CppSQLite3Statement() + +{ + + mpDB = 0; + + mpVM = 0; + +} + + + + + +CppSQLite3Statement::CppSQLite3Statement(const CppSQLite3Statement& rStatement) + +{ + + mpDB = rStatement.mpDB; + + mpVM = rStatement.mpVM; + + // Only one object can own VM + + const_cast(rStatement).mpVM = 0; + +} + + + + + +CppSQLite3Statement::CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM) + +{ + + mpDB = pDB; + + mpVM = pVM; + +} + + + + + +CppSQLite3Statement::~CppSQLite3Statement() + +{ + + try + + { + + finalize(); + + } + + catch (...) + + { + + } + +} + + + + + +CppSQLite3Statement& CppSQLite3Statement::operator=(const CppSQLite3Statement& rStatement) + +{ + + mpDB = rStatement.mpDB; + + mpVM = rStatement.mpVM; + + // Only one object can own VM + + const_cast(rStatement).mpVM = 0; + + return *this; + +} + + + + + +int CppSQLite3Statement::execDML() + +{ + + checkDB(); + + checkVM(); + + + + const char* szError=0; + + + + int nRet = sqlite3_step(mpVM); + + + + if (nRet == SQLITE_DONE) + + { + + int nRowsChanged = sqlite3_changes(mpDB); + + + + nRet = sqlite3_reset(mpVM); + + + + if (nRet != SQLITE_OK) + + { + + szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + + + + return nRowsChanged; + + } + + else + + { + + nRet = sqlite3_reset(mpVM); + + szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + +} + + + + + +CppSQLite3Query CppSQLite3Statement::execQuery() + +{ + + checkDB(); + + checkVM(); + + + + int nRet = sqlite3_step(mpVM); + + + + if (nRet == SQLITE_DONE) + + { + + // no rows + + return CppSQLite3Query(mpDB, mpVM, true/*eof*/, false); + + } + + else if (nRet == SQLITE_ROW) + + { + + // at least 1 row + + return CppSQLite3Query(mpDB, mpVM, false/*eof*/, false); + + } + + else + + { + + nRet = sqlite3_reset(mpVM); + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::bind(int nParam, const char* szValue) + +{ + + checkVM(); + + int nRes = sqlite3_bind_text(mpVM, nParam, szValue, -1, SQLITE_TRANSIENT); + + + + if (nRes != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRes, + + "Error binding string param", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::bind(int nParam, const int nValue) + +{ + + checkVM(); + + int nRes = sqlite3_bind_int(mpVM, nParam, nValue); + + + + if (nRes != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRes, + + "Error binding int param", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::bind(int nParam, const double dValue) + +{ + + checkVM(); + + int nRes = sqlite3_bind_double(mpVM, nParam, dValue); + + + + if (nRes != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRes, + + "Error binding double param", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::bind(int nParam, const unsigned char* blobValue, int nLen) + +{ + + checkVM(); + + int nRes = sqlite3_bind_blob(mpVM, nParam, + + (const void*)blobValue, nLen, SQLITE_TRANSIENT); + + + + if (nRes != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRes, + + "Error binding blob param", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::bindNull(int nParam) + +{ + + checkVM(); + + int nRes = sqlite3_bind_null(mpVM, nParam); + + + + if (nRes != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRes, + + "Error binding NULL param", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::reset() + +{ + + if (mpVM) + + { + + int nRet = sqlite3_reset(mpVM); + + + + if (nRet != SQLITE_OK) + + { + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + + } + +} + + + + + +void CppSQLite3Statement::finalize() + +{ + + if (mpVM) + + { + + int nRet = sqlite3_finalize(mpVM); + + mpVM = 0; + + + + if (nRet != SQLITE_OK) + + { + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + + } + +} + + + + + +void CppSQLite3Statement::checkDB() + +{ + + if (mpDB == 0) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Database not open", + + DONT_DELETE_MSG); + + } + +} + + + + + +void CppSQLite3Statement::checkVM() + +{ + + if (mpVM == 0) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Null Virtual Machine pointer", + + DONT_DELETE_MSG); + + } + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + + + +CppSQLite3DB::CppSQLite3DB() + +{ + + mpDB = 0; + + mnBusyTimeoutMs = 60000; // 60 seconds + +} + + + + + +CppSQLite3DB::CppSQLite3DB(const CppSQLite3DB& db) + +{ + + mpDB = db.mpDB; + + mnBusyTimeoutMs = 60000; // 60 seconds + +} + + + + + +CppSQLite3DB::~CppSQLite3DB() + +{ + + close(); + +} + + + + + +CppSQLite3DB& CppSQLite3DB::operator=(const CppSQLite3DB& db) + +{ + + mpDB = db.mpDB; + + mnBusyTimeoutMs = 60000; // 60 seconds + + return *this; + +} + + + + + +void CppSQLite3DB::open(const char* szFile) + +{ + + int nRet = sqlite3_open(szFile, &mpDB); + + + + if (nRet != SQLITE_OK) + + { + + const char* szError = sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + + + + setBusyTimeout(mnBusyTimeoutMs); + +} + + + + + +void CppSQLite3DB::close() + +{ + + if (mpDB) + + { + + sqlite3_close(mpDB); + + mpDB = 0; + + } + +} + + + + + +CppSQLite3Statement CppSQLite3DB::compileStatement(const char* szSQL) + +{ + + checkDB(); + + + + sqlite3_stmt* pVM = compile(szSQL); + + return CppSQLite3Statement(mpDB, pVM); + +} + + + + + +bool CppSQLite3DB::tableExists(const char* szTable) + +{ + + char szSQL[128]; + + sprintf(szSQL, + + "select count(*) from sqlite_master where type='table' and name='%s'", + + szTable); + + int nRet = execScalar(szSQL); + + return (nRet > 0); + +} + + + + + +int CppSQLite3DB::execDML(const char* szSQL) + +{ + + checkDB(); + + + + char* szError=0; + + + + int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError); + + + + if (nRet == SQLITE_OK) + + { + + return sqlite3_changes(mpDB); + + } + + else + + { + + throw CppSQLite3Exception(nRet, szError); + + } + +} + + + + + +CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL) + +{ + + checkDB(); + + + + sqlite3_stmt* pVM = compile(szSQL); + + + + int nRet = sqlite3_step(pVM); + + + + if (nRet == SQLITE_DONE) + + { + + // no rows + + return CppSQLite3Query(mpDB, pVM, true/*eof*/); + + } + + else if (nRet == SQLITE_ROW) + + { + + // at least 1 row + + return CppSQLite3Query(mpDB, pVM, false/*eof*/); + + } + + else + + { + + nRet = sqlite3_finalize(pVM); + + const char* szError= sqlite3_errmsg(mpDB); + + throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG); + + } + +} + + + + + +int CppSQLite3DB::execScalar(const char* szSQL) + +{ + + CppSQLite3Query q = execQuery(szSQL); + + + + if (q.eof() || q.numFields() < 1) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Invalid scalar query", + + DONT_DELETE_MSG); + + } + + + + return atoi(q.fieldValue(0)); + +} + + + + + +CppSQLite3Table CppSQLite3DB::getTable(const char* szSQL) + +{ + + checkDB(); + + + + char* szError=0; + + char** paszResults=0; + + int nRet; + + int nRows(0); + + int nCols(0); + + + + nRet = sqlite3_get_table(mpDB, szSQL, &paszResults, &nRows, &nCols, &szError); + + + + if (nRet == SQLITE_OK) + + { + + return CppSQLite3Table(paszResults, nRows, nCols); + + } + + else + + { + + throw CppSQLite3Exception(nRet, szError); + + } + +} + + + + + +sqlite_int64 CppSQLite3DB::lastRowId() + +{ + + return sqlite3_last_insert_rowid(mpDB); + +} + + + + + +void CppSQLite3DB::setBusyTimeout(int nMillisecs) + +{ + + mnBusyTimeoutMs = nMillisecs; + + sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs); + +} + + + + + +void CppSQLite3DB::checkDB() + +{ + + if (!mpDB) + + { + + throw CppSQLite3Exception(CPPSQLITE_ERROR, + + "Database not open", + + DONT_DELETE_MSG); + + } + +} + + + + + +sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL) + +{ + + checkDB(); + + + + char* szError=0; + + const char* szTail=0; + + sqlite3_stmt* pVM; + + + + int nRet = sqlite3_prepare(mpDB, szSQL, -1, &pVM, &szTail); + + + + if (nRet != SQLITE_OK) + + { + + throw CppSQLite3Exception(nRet, szError); + + } + + + + return pVM; + +} + + + + + +//////////////////////////////////////////////////////////////////////////////// + +// SQLite encode.c reproduced here, containing implementation notes and source + +// for sqlite3_encode_binary() and sqlite3_decode_binary() + +//////////////////////////////////////////////////////////////////////////////// + + + +/* + +** 2002 April 25 + +** + +** The author disclaims copyright to this source code. In place of + +** a legal notice, here is a blessing: + +** + +** May you do good and not evil. + +** May you find forgiveness for yourself and forgive others. + +** May you share freely, never taking more than you give. + +** + +************************************************************************* + +** This file contains helper routines used to translate binary data into + +** a null-terminated string (suitable for use in SQLite) and back again. + +** These are convenience routines for use by people who want to store binary + +** data in an SQLite database. The code in this file is not used by any other + +** part of the SQLite library. + +** + +** $Id: CppSQLite3.cpp,v 1.2 2009/08/27 11:47:02 cervenansky Exp $ + +*/ + + + +/* + +** How This Encoder Works + +** + +** The output is allowed to contain any character except 0x27 (') and + +** 0x00. This is accomplished by using an escape character to encode + +** 0x27 and 0x00 as a two-byte sequence. The escape character is always + +** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The + +** 0x27 character is encoded as the two byte sequence 0x01 0x03. Finally, + +** the escape character itself is encoded as the two-character sequence + +** 0x01 0x02. + +** + +** To summarize, the encoder works by using an escape sequences as follows: + +** + +** 0x00 -> 0x01 0x01 + +** 0x01 -> 0x01 0x02 + +** 0x27 -> 0x01 0x03 + +** + +** If that were all the encoder did, it would work, but in certain cases + +** it could double the size of the encoded string. For example, to + +** encode a string of 100 0x27 characters would require 100 instances of + +** the 0x01 0x03 escape sequence resulting in a 200-character output. + +** We would prefer to keep the size of the encoded string smaller than + +** this. + +** + +** To minimize the encoding size, we first add a fixed offset value to each + +** byte in the sequence. The addition is modulo 256. (That is to say, if + +** the sum of the original character value and the offset exceeds 256, then + +** the higher order bits are truncated.) The offset is chosen to minimize + +** the number of characters in the string that need to be escaped. For + +** example, in the case above where the string was composed of 100 0x27 + +** characters, the offset might be 0x01. Each of the 0x27 characters would + +** then be converted into an 0x28 character which would not need to be + +** escaped at all and so the 100 character input string would be converted + +** into just 100 characters of output. Actually 101 characters of output - + +** we have to record the offset used as the first byte in the sequence so + +** that the string can be decoded. Since the offset value is stored as + +** part of the output string and the output string is not allowed to contain + +** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27. + +** + +** Here, then, are the encoding steps: + +** + +** (1) Choose an offset value and make it the first character of + +** output. + +** + +** (2) Copy each input character into the output buffer, one by + +** one, adding the offset value as you copy. + +** + +** (3) If the value of an input character plus offset is 0x00, replace + +** that one character by the two-character sequence 0x01 0x01. + +** If the sum is 0x01, replace it with 0x01 0x02. If the sum + +** is 0x27, replace it with 0x01 0x03. + +** + +** (4) Put a 0x00 terminator at the end of the output. + +** + +** Decoding is obvious: + +** + +** (5) Copy encoded characters except the first into the decode + +** buffer. Set the first encoded character aside for use as + +** the offset in step 7 below. + +** + +** (6) Convert each 0x01 0x01 sequence into a single character 0x00. + +** Convert 0x01 0x02 into 0x01. Convert 0x01 0x03 into 0x27. + +** + +** (7) Subtract the offset value that was the first character of + +** the encoded buffer from all characters in the output buffer. + +** + +** The only tricky part is step (1) - how to compute an offset value to + +** minimize the size of the output buffer. This is accomplished by testing + +** all offset values and picking the one that results in the fewest number + +** of escapes. To do that, we first scan the entire input and count the + +** number of occurances of each character value in the input. Suppose + +** the number of 0x00 characters is N(0), the number of occurances of 0x01 + +** is N(1), and so forth up to the number of occurances of 0xff is N(255). + +** An offset of 0 is not allowed so we don't have to test it. The number + +** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number + +** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth. + +** In this way we find the offset that gives the minimum number of escapes, + +** and thus minimizes the length of the output string. + +*/ + + + +/* + +** Encode a binary buffer "in" of size n bytes so that it contains + +** no instances of characters '\'' or '\000'. The output is + +** null-terminated and can be used as a string value in an INSERT + +** or UPDATE statement. Use sqlite3_decode_binary() to convert the + +** string back into its original binary. + +** + +** The result is written into a preallocated output buffer "out". + +** "out" must be able to hold at least 2 +(257*n)/254 bytes. + +** In other words, the output will be expanded by as much as 3 + +** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. + +** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) + +** + +** The return value is the number of characters in the encoded + +** string, excluding the "\000" terminator. + +*/ + +int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out){ + + int i, j, e, m; + + int cnt[256]; + + if( n<=0 ){ + + out[0] = 'x'; + + out[1] = 0; + + return 1; + + } + + memset(cnt, 0, sizeof(cnt)); + + for(i=n-1; i>=0; i--){ cnt[in[i]]++; } + + m = n; + + for(i=1; i<256; i++){ + + int sum; + + if( i=='\'' ) continue; + + sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff]; + + if( sum -#include - -#define CPPSQLITE_ERROR 1000 - -class CppSQLite3Exception -{ -public: - - CppSQLite3Exception(const int nErrCode, - char* szErrMess, - bool bDeleteMsg=true); - CppSQLite3Exception(const int nErrCode, - const char* szErrMess, - bool bDeleteMsg=true); - - CppSQLite3Exception(const CppSQLite3Exception& e); - - virtual ~CppSQLite3Exception(); - - const int errorCode() { return mnErrCode; } - - const char* errorMessage() { return mpszErrMess; } - - static const char* errorCodeAsString(int nErrCode); - -private: - - int mnErrCode; - char* mpszErrMess; -}; - - -class CppSQLite3Buffer -{ -public: - - CppSQLite3Buffer(); - - ~CppSQLite3Buffer(); - - const char* format(const char* szFormat, ...); - - operator const char*() { return mpBuf; } - - void clear(); - -private: - - char* mpBuf; -}; - - -class CppSQLite3Binary -{ -public: - - CppSQLite3Binary(); - - ~CppSQLite3Binary(); - - void setBinary(const unsigned char* pBuf, int nLen); - void setEncoded(const unsigned char* pBuf); - - const unsigned char* getEncoded(); - const unsigned char* getBinary(); - - int getBinaryLength(); - - unsigned char* allocBuffer(int nLen); - - void clear(); - -private: - - unsigned char* mpBuf; - int mnBinaryLen; - int mnBufferLen; - int mnEncodedLen; - bool mbEncoded; -}; - - -class CppSQLite3Query -{ -public: - - CppSQLite3Query(); - - CppSQLite3Query(const CppSQLite3Query& rQuery); - - CppSQLite3Query(sqlite3* pDB, - sqlite3_stmt* pVM, - bool bEof, - bool bOwnVM=true); - - CppSQLite3Query& operator=(const CppSQLite3Query& rQuery); - - virtual ~CppSQLite3Query(); - - int numFields(); - - int fieldIndex(const char* szField); - const char* fieldName(int nCol); - - const char* fieldDeclType(int nCol); - int fieldDataType(int nCol); - - const char* fieldValue(int nField); - const char* fieldValue(const char* szField); - - int getIntField(int nField, int nNullValue=0); - int getIntField(const char* szField, int nNullValue=0); - - double getFloatField(int nField, double fNullValue=0.0); - double getFloatField(const char* szField, double fNullValue=0.0); - - const char* getStringField(int nField, const char* szNullValue=""); - const char* getStringField(const char* szField, const char* szNullValue=""); - - const unsigned char* getBlobField(int nField, int& nLen); - const unsigned char* getBlobField(const char* szField, int& nLen); - - bool fieldIsNull(int nField); - bool fieldIsNull(const char* szField); - - bool eof(); - - void nextRow(); - - void finalize(); - -private: - - void checkVM(); - - sqlite3* mpDB; - sqlite3_stmt* mpVM; - bool mbEof; - int mnCols; - bool mbOwnVM; -}; - - -class CppSQLite3Table -{ -public: - - CppSQLite3Table(); - - CppSQLite3Table(const CppSQLite3Table& rTable); - - CppSQLite3Table(char** paszResults, int nRows, int nCols); - - virtual ~CppSQLite3Table(); - - CppSQLite3Table& operator=(const CppSQLite3Table& rTable); - - int numFields(); - - int numRows(); - - const char* fieldName(int nCol); - - const char* fieldValue(int nField); - const char* fieldValue(const char* szField); - - int getIntField(int nField, int nNullValue=0); - int getIntField(const char* szField, int nNullValue=0); - - double getFloatField(int nField, double fNullValue=0.0); - double getFloatField(const char* szField, double fNullValue=0.0); - - const char* getStringField(int nField, const char* szNullValue=""); - const char* getStringField(const char* szField, const char* szNullValue=""); - - bool fieldIsNull(int nField); - bool fieldIsNull(const char* szField); - - void setRow(int nRow); - - void finalize(); - -private: - - void checkResults(); - - int mnCols; - int mnRows; - int mnCurrentRow; - char** mpaszResults; -}; - - -class CppSQLite3Statement -{ -public: - - CppSQLite3Statement(); - - CppSQLite3Statement(const CppSQLite3Statement& rStatement); - - CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM); - - virtual ~CppSQLite3Statement(); - - CppSQLite3Statement& operator=(const CppSQLite3Statement& rStatement); - - int execDML(); - - CppSQLite3Query execQuery(); - - void bind(int nParam, const char* szValue); - void bind(int nParam, const int nValue); - void bind(int nParam, const double dwValue); - void bind(int nParam, const unsigned char* blobValue, int nLen); - void bindNull(int nParam); - - void reset(); - - void finalize(); - -private: - - void checkDB(); - void checkVM(); - - sqlite3* mpDB; - sqlite3_stmt* mpVM; -}; - - -class CppSQLite3DB -{ -public: - - CppSQLite3DB(); - - virtual ~CppSQLite3DB(); - - void open(const char* szFile); - - void close(); - - bool tableExists(const char* szTable); - - int execDML(const char* szSQL); - - CppSQLite3Query execQuery(const char* szSQL); - - int execScalar(const char* szSQL); - - CppSQLite3Table getTable(const char* szSQL); - - CppSQLite3Statement compileStatement(const char* szSQL); - - sqlite_int64 lastRowId(); - - void interrupt() { sqlite3_interrupt(mpDB); } - - void setBusyTimeout(int nMillisecs); - - static const char* SQLiteVersion() { return SQLITE_VERSION; } - -private: - - CppSQLite3DB(const CppSQLite3DB& db); - CppSQLite3DB& operator=(const CppSQLite3DB& db); - - sqlite3_stmt* compile(const char* szSQL); - - void checkDB(); - - sqlite3* mpDB; - int mnBusyTimeoutMs; -}; - -#endif +//////////////////////////////////////////////////////////////////////////////// + +// CppSQLite3 - A C++ wrapper around the SQLite3 embedded database library. + +// + +// Copyright (c) 2004 Rob Groves. All Rights Reserved. rob.groves@btinternet.com + +// + +// Permission to use, copy, modify, and distribute this software and its + +// documentation for any purpose, without fee, and without a written + +// agreement, is hereby granted, provided that the above copyright notice, + +// this paragraph and the following two paragraphs appear in all copies, + +// modifications, and distributions. + +// + +// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, + +// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST + +// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, + +// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// + +// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + +// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF + +// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION + +// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +// + +// V3.0 03/08/2004 -Initial Version for sqlite3 + +// + +// V3.1 16/09/2004 -Implemented getXXXXField using sqlite3 functions + +// -Added CppSQLiteDB3::tableExists() + +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _CppSQLite3_H_ + +#define _CppSQLite3_H_ + + + +#include "sqlite3.h" + +#include + +#include + + + +#define CPPSQLITE_ERROR 1000 + + + +class CppSQLite3Exception + +{ + +public: + + + + CppSQLite3Exception(const int nErrCode, + + char* szErrMess, + + bool bDeleteMsg=true); + + CppSQLite3Exception(const int nErrCode, + + const char* szErrMess, + + bool bDeleteMsg=true); + + + + CppSQLite3Exception(const CppSQLite3Exception& e); + + + + virtual ~CppSQLite3Exception(); + + + + const int errorCode() { return mnErrCode; } + + + + const char* errorMessage() { return mpszErrMess; } + + + + static const char* errorCodeAsString(int nErrCode); + + + +private: + + + + int mnErrCode; + + char* mpszErrMess; + +}; + + + + + +class CppSQLite3Buffer + +{ + +public: + + + + CppSQLite3Buffer(); + + + + ~CppSQLite3Buffer(); + + + + const char* format(const char* szFormat, ...); + + + + operator const char*() { return mpBuf; } + + + + void clear(); + + + +private: + + + + char* mpBuf; + +}; + + + + + +class CppSQLite3Binary + +{ + +public: + + + + CppSQLite3Binary(); + + + + ~CppSQLite3Binary(); + + + + void setBinary(const unsigned char* pBuf, int nLen); + + void setEncoded(const unsigned char* pBuf); + + + + const unsigned char* getEncoded(); + + const unsigned char* getBinary(); + + + + int getBinaryLength(); + + + + unsigned char* allocBuffer(int nLen); + + + + void clear(); + + + +private: + + + + unsigned char* mpBuf; + + int mnBinaryLen; + + int mnBufferLen; + + int mnEncodedLen; + + bool mbEncoded; + +}; + + + + + +class CppSQLite3Query + +{ + +public: + + + + CppSQLite3Query(); + + + + CppSQLite3Query(const CppSQLite3Query& rQuery); + + + + CppSQLite3Query(sqlite3* pDB, + + sqlite3_stmt* pVM, + + bool bEof, + + bool bOwnVM=true); + + + + CppSQLite3Query& operator=(const CppSQLite3Query& rQuery); + + + + virtual ~CppSQLite3Query(); + + + + int numFields(); + + + + int fieldIndex(const char* szField); + + const char* fieldName(int nCol); + + + + const char* fieldDeclType(int nCol); + + int fieldDataType(int nCol); + + + + const char* fieldValue(int nField); + + const char* fieldValue(const char* szField); + + + + int getIntField(int nField, int nNullValue=0); + + int getIntField(const char* szField, int nNullValue=0); + + + + double getFloatField(int nField, double fNullValue=0.0); + + double getFloatField(const char* szField, double fNullValue=0.0); + + + + const char* getStringField(int nField, const char* szNullValue=""); + + const char* getStringField(const char* szField, const char* szNullValue=""); + + + + const unsigned char* getBlobField(int nField, int& nLen); + + const unsigned char* getBlobField(const char* szField, int& nLen); + + + + bool fieldIsNull(int nField); + + bool fieldIsNull(const char* szField); + + + + bool eof(); + + + + void nextRow(); + + + + void finalize(); + + + +private: + + + + void checkVM(); + + + + sqlite3* mpDB; + + sqlite3_stmt* mpVM; + + bool mbEof; + + int mnCols; + + bool mbOwnVM; + +}; + + + + + +class CppSQLite3Table + +{ + +public: + + + + CppSQLite3Table(); + + + + CppSQLite3Table(const CppSQLite3Table& rTable); + + + + CppSQLite3Table(char** paszResults, int nRows, int nCols); + + + + virtual ~CppSQLite3Table(); + + + + CppSQLite3Table& operator=(const CppSQLite3Table& rTable); + + + + int numFields(); + + + + int numRows(); + + + + const char* fieldName(int nCol); + + + + const char* fieldValue(int nField); + + const char* fieldValue(const char* szField); + + + + int getIntField(int nField, int nNullValue=0); + + int getIntField(const char* szField, int nNullValue=0); + + + + double getFloatField(int nField, double fNullValue=0.0); + + double getFloatField(const char* szField, double fNullValue=0.0); + + + + const char* getStringField(int nField, const char* szNullValue=""); + + const char* getStringField(const char* szField, const char* szNullValue=""); + + + + bool fieldIsNull(int nField); + + bool fieldIsNull(const char* szField); + + + + void setRow(int nRow); + + + + void finalize(); + + + +private: + + + + void checkResults(); + + + + int mnCols; + + int mnRows; + + int mnCurrentRow; + + char** mpaszResults; + +}; + + + + + +class CppSQLite3Statement + +{ + +public: + + + + CppSQLite3Statement(); + + + + CppSQLite3Statement(const CppSQLite3Statement& rStatement); + + + + CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM); + + + + virtual ~CppSQLite3Statement(); + + + + CppSQLite3Statement& operator=(const CppSQLite3Statement& rStatement); + + + + int execDML(); + + + + CppSQLite3Query execQuery(); + + + + void bind(int nParam, const char* szValue); + + void bind(int nParam, const int nValue); + + void bind(int nParam, const double dwValue); + + void bind(int nParam, const unsigned char* blobValue, int nLen); + + void bindNull(int nParam); + + + + void reset(); + + + + void finalize(); + + + +private: + + + + void checkDB(); + + void checkVM(); + + + + sqlite3* mpDB; + + sqlite3_stmt* mpVM; + +}; + + + + + +class CppSQLite3DB + +{ + +public: + + + + CppSQLite3DB(); + + + + virtual ~CppSQLite3DB(); + + + + void open(const char* szFile); + + + + void close(); + + + + bool tableExists(const char* szTable); + + + + int execDML(const char* szSQL); + + + + CppSQLite3Query execQuery(const char* szSQL); + + + + int execScalar(const char* szSQL); + + + + CppSQLite3Table getTable(const char* szSQL); + + + + CppSQLite3Statement compileStatement(const char* szSQL); + + + + sqlite_int64 lastRowId(); + + + + void interrupt() { sqlite3_interrupt(mpDB); } + + + + void setBusyTimeout(int nMillisecs); + + + + static const char* SQLiteVersion() { return SQLITE_VERSION; } + + + +private: + + + + CppSQLite3DB(const CppSQLite3DB& db); + + CppSQLite3DB& operator=(const CppSQLite3DB& db); + + + + sqlite3_stmt* compile(const char* szSQL); + + + + void checkDB(); + + + + sqlite3* mpDB; + + int mnBusyTimeoutMs; + +}; + + + +#endif + diff --git a/src2/creaImageIOGimmick.cpp b/src2/creaImageIOGimmick.cpp index de6b11d..9f12380 100644 --- a/src2/creaImageIOGimmick.cpp +++ b/src2/creaImageIOGimmick.cpp @@ -91,7 +91,6 @@ namespace creaImageIO } } - /////////////////////////////////////////////////////////////////////////// // create a DB from a attributes descriptor file for medical images // // @param i_name : DB name // diff --git a/src2/creaImageIOGimmickReaderDialog.cpp b/src2/creaImageIOGimmickReaderDialog.cpp index d8c52e1..d890f70 100644 --- a/src2/creaImageIOGimmickReaderDialog.cpp +++ b/src2/creaImageIOGimmickReaderDialog.cpp @@ -1,6 +1,6 @@ #include #include -#include + namespace creaImageIO { @@ -16,7 +16,7 @@ namespace creaImageIO int image_out_dim, int nb_threads) { - BlockScopeWxApp app; + creaImageIO::WxGimmickReaderDialog w(0, -1, diff --git a/src2/creaImageIOWxCustomizeConfigPanel.cpp b/src2/creaImageIOWxCustomizeConfigPanel.cpp index 7ca2f23..f237eaf 100644 --- a/src2/creaImageIOWxCustomizeConfigPanel.cpp +++ b/src2/creaImageIOWxCustomizeConfigPanel.cpp @@ -42,10 +42,6 @@ namespace creaImageIO wxButton *save = new wxButton(this,wxID_ANY,_T("Save Changes"), wxPoint(5,130) ); Connect( save->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxCustomizeConfigPanel::OnSaveConfig ); - - //topsizer->Add( mView,1,wxGROW,0); - -// SetSizer( topsizer ); Layout(); } diff --git a/src2/creaImageIOWxDescriptorPanel.cpp b/src2/creaImageIOWxDescriptorPanel.cpp new file mode 100644 index 0000000..f37554b --- /dev/null +++ b/src2/creaImageIOWxDescriptorPanel.cpp @@ -0,0 +1,782 @@ +#include "creaImageIOWxDescriptorPanel.h" +#include +#include +#include + + +namespace creaImageIO +{ + // CTor + +WxDescriptorPanel::WxDescriptorPanel(wxWindow *parent) + : wxDialog(parent, -1,_T("Descriptor Creation"), wxDefaultPosition, wxSize(550,550)) +{ + + + GimmickDebugMessage(1,"WxDescriptorPanel::WxDescriptorPanel" + <GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnNew ); + + wxButton *LoadDescriptor = new wxButton(this, -1,_T("Load a descriptor"), wxPoint(150,7) ); + Connect( LoadDescriptor->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnLoad ); + + wxStaticLine *line1 = new wxStaticLine(this, -1, wxPoint(5,40), wxSize(540,2)); + + // LEVEL + wxStaticText * LevelText=new wxStaticText(this,-1,_T(" Level: "), wxPoint(5,50)); + LevelCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("patient"), wxPoint(50,50), wxSize(50,25)); + wxButton *addLevel = new wxButton(this, ID_LEVEL_ADD,_T("add a level"), wxPoint(150,50) ); + Connect( addLevel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddLevel ); + + wxStaticLine *line2 = new wxStaticLine(this, -1, wxPoint(5,75), wxSize(540,2)); + + // ATTRIBUTES + + wxStaticText * GR=new wxStaticText(this,-1,_T(" DICOM Group: "), wxPoint(5,110)); + GRCtrl=new wxTextCtrl(this, ID_GR_CTRL,_T("0x0010"), wxPoint(82,110), wxSize(50,25)); + Connect( GRCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute ); + + wxStaticText * EL=new wxStaticText(this,-1,_T(" DICOM Element: "), wxPoint(140,110)); + ELCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T("0x0010"), wxPoint(230,110), wxSize(50,25)); + Connect( ELCtrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED , (wxObjectEventFunction) &WxDescriptorPanel::OnDicomAttribute ); + + + wxString choices[3]; + choices[0] = "Unknow Attribute"; + std::map::iterator it_att =ownatt.begin(); + for(int i = 1; it_att != ownatt.end(); it_att++, i++) + { + choices[i] = crea::std2wx(it_att->second); + } + + + AttributeCombo = new wxComboBox(this, ID_ATTRIBUTE_CTRL,_T(""),wxPoint(300,110), wxSize(120,25),3,choices, wxCB_READONLY); + AttributeCombo->SetSelection(0); + + + wxButton *addAttribute = new wxButton(this, ID_ATTRIBUTE_ADD,_T("add an attribute"), wxPoint(440,110) ); + Connect( addAttribute->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnAddAttribute ); + + wxStaticLine *line3 = new wxStaticLine(this, -1, wxPoint(5,140), wxSize(540,2)); + + // RESULT + + ResultCtrl=new wxTextCtrl(this, ID_EL_CTRL,_T(""), wxPoint(5,150), wxSize(250,310), wxTE_READONLY| wxMac | wxTE_MULTILINE | wxTE_RICH ); + wxButton *RemoveCtrl = new wxButton(this, ID_REMOVE_ADD,_T("Remove an entry"), wxPoint(280,200) ); + Connect( RemoveCtrl->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnRemove ); + + wxStaticLine *line4 = new wxStaticLine(this, -1, wxPoint(5,470), wxSize(540,2)); + // VALIDATION BUTTON + wxButton *Ok = new wxButton(this, -1,_T("OK"), wxPoint(10,480) ); + Connect( Ok->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnOK ); + + wxButton *Apply = new wxButton(this, -1,_T("APPLY"), wxPoint(150,480) ); + Connect( Apply->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxObjectEventFunction) &WxDescriptorPanel::OnApply ); + + wxButton *Cancel = new wxButton(this, wxID_CANCEL,_T("CANCEL"), wxPoint(250,480) ); +// Connect( Cancel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED , (wxCloseEvent) &wxWindow::Close ); + + Layout(); + CreateDescriptor(0); + } + + /// Destructor + WxDescriptorPanel::~WxDescriptorPanel() + { + GimmickDebugMessage(1,"WxCustomizeConfigPanel::~WxCustomizeConfigPanel" + <GetSelection() == 0) + { + name_att = "D" + GRCtrl->GetValue() + "_" + ELCtrl->GetValue(); + } + else + { wxString wd = AttributeCombo->GetValue(); + std::string st = crea::wx2std(wd); + name_att = OwnAttribute(st); + } + onAddAttribute(crea::wx2std(AttributeCombo->GetValue()), name_att); + } + ////////////////////////////////////////////////////////// + // add an attribute // + // @param att : attribute // + // @param name_att : 's name // + // @param level : level to add the attribute // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::onAddAttribute( const std::string &att, const std::string &name_att,std::string level ) + { + if(lv == 0) + { + wxMessageBox(_T("Need a level first!"),crea::std2wx("WARNING"),wxOK,this); + } + else + { + if( !att.empty() ) + { + // Find Name of level + if(level.empty()) + { + level = findLevel(); + } + + if (!addAtribute(level, name_att)) + { + wxMessageBox(_T("Attribute already used in this level"),crea::std2wx("WARNING"),wxOK,this); + } + else + { + ResultCtrl->SetInsertionPoint(InsertPt); + for (int i = 1; i<=lv;i++) + { + ResultCtrl->WriteText(" "); + } + ResultCtrl->WriteText("| - "); + ResultCtrl->WriteText(att); + wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle()); + ResultAttr.SetTextColour(*wxWHITE); + ResultCtrl->SetDefaultStyle(ResultAttr); + std::string text = " "; + ResultCtrl->WriteText(" " + name_att); + ResultAttr.SetTextColour(*wxBLACK); + ResultCtrl->SetDefaultStyle(ResultAttr); + ResultCtrl->WriteText("\n"); + } + InsertPt = ResultCtrl->GetInsertionPoint(); + } + } + } + + ////////////////////////////////////////////////////////// + // add a level // + // @param event : Wxevent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnAddLevel(wxCommandEvent& event) + { + if( !LevelCtrl->GetValue().IsEmpty() ) + { + onAddLevel(crea::wx2std(LevelCtrl->GetValue())); + } + } + + ////////////////////////////////////////////////////////// + // add a level // + // @param level : level's name // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::onAddLevel(const std::string &level) + { + if(addLevel(crea::wx2std(level))) + { + wxMessageBox(_T("Level already used"),crea::std2wx(("WARNING")),wxOK,this); + return; + } + + lv++; + ResultCtrl->SetInsertionPoint(InsertPt); + for (int i = 1; iWriteText(" "); + } + if(lv>1) + { ResultCtrl->WriteText("| \n"); + for (int i = 1; iWriteText(" "); + } + ResultCtrl->WriteText("|_"); + } + + wxTextAttr ResultAttr(ResultCtrl->GetDefaultStyle()); + ResultAttr.SetTextColour(*wxRED); + ResultCtrl->SetDefaultStyle(ResultAttr); + ResultCtrl->WriteText(level); + ResultAttr.SetTextColour(*wxBLACK); + ResultCtrl->SetDefaultStyle(ResultAttr); + ResultCtrl->WriteText("\n"); + InsertPt = ResultCtrl->GetInsertionPoint(); + + } + + ////////////////////////////////////////////////////////// + // Find a DICOM attribute from group and element values // + // @param event : Wxevent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnDicomAttribute(wxCommandEvent& event) + { + int i = 0; + if(!GRCtrl->GetValue().IsEmpty() && !ELCtrl->GetValue().IsEmpty() + && GRCtrl->GetValue().Len() == 6 && ELCtrl->GetValue().Len() == 6 && AttributeCombo->GetSelection() == 0) + { + + std::string gr = crea::wx2std(GRCtrl->GetValue()); + std::string el = crea::wx2std(ELCtrl->GetValue()); + std::stringstream val; + + unsigned short group; + unsigned short element; + val << std::dec << gr ; + val >> std::hex >> group; + val.clear(); + val << std::dec << el ; + val >> std::hex >> element; + + // Retrieve the name from gdcm dict + GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element); + // AttributeCombo->Clear(); + if(entry) + { + AttributeCombo->Delete(0); + AttributeCombo->Insert(crea::std2wx(entry->GetName()), 0); + } + else + { + AttributeCombo->Delete(0); + AttributeCombo->Insert(_T("Unknown Attribute"),0); + } + AttributeCombo->SetSelection(0); + + } + + } + + + ////////////////////////////////////////////////////////// + // determine values for own attributes // + // @param name : attribute's name // + // @param key : indicates key map or not // + // @return : - // + ////////////////////////////////////////////////// + std::string WxDescriptorPanel::OwnAttribute(const std::string name) + { + std::string result; + + std::map::iterator it_att = ownatt.begin(); + for(; it_att != ownatt.end(); it_att++) + { + if(it_att->second == name) + { + result = it_att->first.c_str(); + break; + } + } + return result; + } + + ////////////////////////////////////////////////////////// + // Find a level in function of position in Return Ctrl // + // @param - : // + // @return : - // + ////////////////////////////////////////////////// + std::string WxDescriptorPanel::findLevel() + { + long column; + long line; + + ResultCtrl->PositionToXY( ResultCtrl->GetInsertionPoint(),&column, &line); + std::string tx(crea::wx2std(ResultCtrl->GetRange(0, ResultCtrl->XYToPosition(0,line+1))).c_str()); + std::string::size_type level_pos_start = tx.rfind("|_"); + if(level_pos_start == -1) + { + level_pos_start = 0; + } + else + { + level_pos_start += 2; + } + + std::string::size_type level_pos_end = tx.find_first_of("\n",level_pos_start); + return tx.substr(level_pos_start,level_pos_end - level_pos_start); + } + + ////////////////////////////////////////////////////// + // Remove an item // + // @param event : Wxevent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnRemove(wxCommandEvent& event) + { + long line; + long column; + long pos_start; + long pos_end; + + pos_start = ResultCtrl->GetInsertionPoint(); + ResultCtrl->PositionToXY( pos_start,&column, &line); + if (line == 0) + { + std::string name("root"); + RemoveLevel(name); + ResultCtrl->Clear(); + lv = 0; + } + else + { + wxString text = ResultCtrl->GetLineText(line); + if ( text.Find("|_") == -1) + { + std::string level = findLevel(); + // find GR and EL values to remove + std::string tx = crea::wx2std(text); + std::string::size_type EL_start_pos = tx.find_last_of(" "); + RemoveAttribute(level, tx.substr(EL_start_pos+1,tx.size() - EL_start_pos)); + ResultCtrl->Remove( ResultCtrl->XYToPosition(0,line), ResultCtrl->XYToPosition(0,line+1)); + } + else + { + RemoveLevel(crea::wx2std(text.AfterFirst('_'))); + lv = text.Find("|")/3; + pos_start= ResultCtrl->XYToPosition(0,line-1); + ResultCtrl->SetInsertionPointEnd(); + pos_end = ResultCtrl->GetInsertionPoint(); + ResultCtrl->Remove(pos_start, pos_end); + } + } + + } + ////////////////////////////////////////////////////// + // create a descriptor structure // + // @param name : level's name to add // + // @return : boolean result // + ////////////////////////////////////////////////// + void WxDescriptorPanel::CreateDescriptor(int type) + { + if(type == 0) // First initialization + { + outDscp.clear(); + outDscp += ""; + outDscp += "\n"; + outDscp += "root"; + outDscp += "\n"; + outDscp += "O Name Name 4"; + outDscp += "\n"; + } + if(type == 1) + { + if(lv > 1) + { + outDscp += "O NumberOfChildren "; + outDscp += crea::wx2std(LevelCtrl->GetValue()); + outDscp += "s"; + outDscp += "\n"; + } + outDscp += ""; + outDscp += "\n"; + outDscp += crea::wx2std(LevelCtrl->GetValue()); + outDscp += "\n"; + + } + if(type == 2) + { + outDscp += "D"; + outDscp += " "; + outDscp += crea::wx2std(GRCtrl->GetValue()); + outDscp += " "; + outDscp += crea::wx2std(ELCtrl->GetValue()); + outDscp += " "; + outDscp += "3"; + outDscp += "\n"; + } + + + } + + + ////////////////////////////////////////////////////// + // add a level // + // @param name : level's name to add // + // @return : boolean result // + ////////////////////////////////////////////////// + bool WxDescriptorPanel::addLevel(const std::string &name) + { + bool bfound = false; + std::map >::iterator it_tree = DscpTree.begin(); + for (;it_tree != DscpTree.end(); it_tree++) + { + if(it_tree->first == name) + { + bfound = true; + break; + } + } + if(!bfound) + { + lvlist[lv] = name; + std::vector branch; + DscpTree[name] = branch; + } + return bfound; + } + + ////////////////////////////////////////////////////// + // remove a level // + // @param name : level's name to remove // + // @return : boolean result // + ////////////////////////////////////////////////// + bool WxDescriptorPanel::RemoveLevel(const std::string &name) + { + bool bresult = false; + std::map::iterator it_list= lvlist.begin(); + for(; it_list != lvlist.end(); it_list++) + { + if(it_list->second == name) + { + break; + } + } + std::map::iterator it_list2 = it_list; + for(;it_list != lvlist.end(); it_list++) + { + std::map >::iterator it_tree = DscpTree.begin(); + for (;it_tree != DscpTree.end(); it_tree++) + { + if(it_tree->first == name) + { + DscpTree.erase(it_tree); + break; + } + } + } + lvlist.erase(it_list2, lvlist.end()); + return bresult; + } + + + ////////////////////////////////////////////////////// + // add an attribute in a level // + // @param level : level's name to add attribute // + // @param name : attribute's name // + // @return : boolean result // + ////////////////////////////////////////////////// + bool WxDescriptorPanel::addAtribute(const std::string &level, const std::string &name) + { + bool bresult = true; + std::map >::iterator it_tree = DscpTree.begin(); + for (;it_tree != DscpTree.end(); it_tree++) + { + if (it_tree->first.c_str() == level) + { + std::vector::iterator it_branch = it_tree->second.begin(); + for(;it_branch != it_tree->second.end(); it_branch++) + { + if(it_branch->c_str() == name) + { + bresult = false; + } + } + if(bresult) + { + it_tree->second.push_back(name); + break; + } + } + } + return bresult; + } + + ////////////////////////////////////////////////////// + // remove an attribute from a level // + // @param level : level's name to remove attribute // + // @param name : attribute's name // + // @return : boolean result // + ////////////////////////////////////////////////// + bool WxDescriptorPanel::RemoveAttribute(const std::string &level, const std::string &name) + { + bool bresult = false; + std::map >::iterator it_tree = DscpTree.begin(); + for (;it_tree != DscpTree.end(); it_tree++) + { + if(it_tree->first == level) + { + std::vector::iterator it_branch = it_tree->second.begin(); + cout << it_tree->second.size(); + for(;it_branch != it_tree->second.end(); it_branch++) + { + if(it_branch->c_str() == name) + { + bresult = true; + it_tree->second.erase(it_branch); + break; + } + } + } + } + return bresult; + } + + ////////////////////////////////////////////////// + // create a new descriptor // + // @param event : WxEvent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnNew(wxCommandEvent &Event) + { + LevelCtrl->SetValue(_T("patient")); + ResultCtrl->Clear(); + DscpTree.clear(); + lv = 0; + } + + ////////////////////////////////////////////////// + // Load a descriptor file // + // @param event : WxEvent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnLoad(wxCommandEvent &Event) + { + long style = wxOPEN | wxFILE_MUST_EXIST; + LevelCtrl->SetValue(_T("patient")); + ResultCtrl->Clear(); + DscpTree.clear(); + lv = 0; + + std::string wc("*.dscp"); + wxFileDialog* FD = new wxFileDialog( 0, + _T("Select file"), + _T(""), + _T(""), + crea::std2wx(wc), + style, + wxDefaultPosition); + if (FD->ShowModal()==wxID_OK) + { + loadDescriptor(crea::wx2std(FD->GetPath()).c_str()); + } + + } + + ////////////////////////////////////////////////// + // Save a descriptor // + // @param event : WxEvent // + // @return : - // + ////////////////////////////////////////////////// + void WxDescriptorPanel::OnOK(wxCommandEvent &Event) + { + saveDescriptor(); + wxWindow::Close(); + } + + ///////////////////////////////////////////////////// + // Save a descriptor and apply it (create a new DB// + // @param event : WxEvent // + // @return : - // + ///////////////////////////////////////////////////// + void WxDescriptorPanel::OnApply(wxCommandEvent &Event) + { + m_DscpFile = saveDescriptor(); + wxWindow::Close(); + SetReturnCode(ID_DSCP_APPLY); + } + + const std::string WxDescriptorPanel::saveDescriptor() + { + std::string file = ""; + long style = wxSAVE; + std::string wc("*.dscp"); + wxFileDialog* FD = new wxFileDialog( 0, + _T("Select file"), + _T(""), + _T(""), + crea::std2wx(wc), + style, + wxDefaultPosition); + + + if (FD->ShowModal()==wxID_OK) + { + createDescriptorFile(); + file = crea::wx2std(FD->GetPath()).c_str(); + std::ofstream ofs(file.c_str()); + ofs.clear(); + ofs << outDscp; + ofs.close(); + } + return file.c_str(); + } + + /////////////////////////////////////////////////////// + // Cancel action // + // @param event : WxEvent // + // @return : - // + /////////////////////////////////////////////////////// + + void WxDescriptorPanel::OnCancel(wxCommandEvent& event) + { + } + + /////////////////////////////////////////////////////// + // create a descriptor file // + // @param - : // + // @return : - // + /////////////////////////////////////////////////////// + void WxDescriptorPanel::createDescriptorFile() + { + + outDscp.clear(); + outDscp += ""; + outDscp += "\n"; + outDscp += "Root"; + outDscp += "\n"; + outDscp += "O Name Name 4"; + outDscp += "\n"; + std::map >::iterator it_tree = DscpTree.begin(); + std::map::iterator it_lv_nb = lvlist.begin(); + std::map::iterator it_lv = lvlist.begin(); + it_lv_nb++; + for (;it_lv != lvlist.end(); it_lv++, it_lv_nb++) + { + outDscp +=""; + outDscp += "\n"; + outDscp += it_lv->second.c_str(); + outDscp += "\n"; + if(it_lv_nb != lvlist.end()) + { + outDscp += "O NumberOfChildren "; + outDscp += it_lv_nb->second.c_str(); + outDscp += "s"; + outDscp += "\n"; + } + std::vector::iterator it_branch = DscpTree[it_lv->second.c_str()].begin(); + for(;it_branch != DscpTree[it_lv->second.c_str()].end(); it_branch++) + { + std::string att = it_branch->c_str(); + if(att[0] == 'D' && att[7] == '_' && att.size() == 14) + { + outDscp += "D "; + outDscp += att.substr(1,6) + " "; // GR + outDscp += att.substr(8,6) + " ";// EL + outDscp += "3"; + outDscp += "\n"; + } + else + { + outDscp += "O "; + outDscp += it_branch->c_str(); + outDscp += " "; + outDscp += ownatt[att]; + outDscp += " "; + outDscp += "2"; + outDscp += "\n"; + } + } + + } + } + + + /////////////////////////////////////////////////////// + // load a descriptor // + // @param i_name : file name to load // + // @return : - // + ///////////////////////////////////////////////////// + void WxDescriptorPanel::loadDescriptor(const std::string i_name) + { + std::ifstream i_file(i_name.c_str()); + std::stringstream buffer; + buffer << i_file.rdbuf(); + std::string line; + std::string level; + + bool bname; + int ilevel = -1; + + + while(std::getline(buffer, line)) + { + if(line =="") + { //increment levels. + ilevel++; + bname = true; + } + else if(bname) + { + // For each level, a name to describe it + level = line; + if(ilevel>0) + { + onAddLevel(level); + } + bname = false; + } + else + { + // split line to find all tags + std::vector descriptors; + std::string separator = " "; + std::string::size_type last_pos = line.find_first_not_of(separator); + //find first separator + std::string::size_type pos = line.find_first_of(separator, last_pos); + while(std::string::npos != pos || std::string::npos != last_pos) + { + descriptors.push_back(line.substr(last_pos, pos - last_pos)); + last_pos = line.find_first_not_of(separator, pos); + pos = line.find_first_of(separator, last_pos); + } + + // By default, the last tag is at zero and not recorded but if take in count + unsigned int flag = 0; + if(descriptors.size() == 4) + { + std::stringstream val; + val << std::dec << descriptors[3]; + val>> flag; + } + + // if Dicom tag, use "group" and "element" descriptor + if(descriptors[0] == "D") + { std::stringstream val, val2; + unsigned short group; + unsigned short element; + val << std::dec << descriptors[1] ; + val >> std::hex >> group; + val2 << std::dec << descriptors[2]; + val2 >> std::hex >> element; + std::string compose = "D"; + compose += descriptors[1]; + compose += "_"; + compose += descriptors[2]; + GDCM_NAME_SPACE::DictEntry* entry = GDCM_NAME_SPACE::Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, element); + if(ilevel>0) + { + onAddAttribute( entry->GetName(),compose, level); + } + } + else // "O" means if user's own tag. + { + boost::algorithm::replace_all(descriptors[2],"_"," "); + if(ilevel>0 && descriptors[1] != "NumberOfChildren" ) + { + onAddAttribute( descriptors[2].c_str(),descriptors[1].c_str(), level); + } + } + } + } + } + +//====================================================================== + +//====================================================================== + +} // EO namespace creaImageIO + + diff --git a/src2/creaImageIOWxDescriptorPanel.h b/src2/creaImageIOWxDescriptorPanel.h new file mode 100644 index 0000000..2f95e81 --- /dev/null +++ b/src2/creaImageIOWxDescriptorPanel.h @@ -0,0 +1,154 @@ +#ifndef __creaImageIOWxDescriptorPanel_h_INCLUDED__ +#define __creaImageIOWxDescriptorPanel_h_INCLUDED__ + +#ifdef USE_WXWIDGETS +#include +#include +#include +#include +#include +#include +#include + + +#define ID_DESCRIPTOR 1500 +#define ID_LEVEL_CTRL ID_DESCRIPTOR+1 +#define ID_LEVEL_ADD ID_DESCRIPTOR+2 +#define ID_GR_CTRL ID_DESCRIPTOR+3 +#define ID_EL_CTRL ID_DESCRIPTOR+4 +#define ID_NAME_CTRL ID_DESCRIPTOR+5 +#define ID_ATTRIBUTE_CTRL ID_DESCRIPTOR+6 +#define ID_ATTRIBUTE_ADD ID_DESCRIPTOR+7 +#define ID_REMOVE_ADD ID_DESCRIPTOR+8 +#define ID_DSCP_APPLY ID_DESCRIPTOR+9 + +namespace creaImageIO +{ + + /** + * \ingroup GUI + */ + //===================================================================== + //===================================================================== + /// Gimmick DB are based on descriptors with a tree structure . + /// Ecah level contains attributes (DICOM or other) to identify data + /// WxDescriptorPanel allows creation, modification and save of descriptors. + /// + + class WxDescriptorPanel : public wxDialog + { + public: + WxDescriptorPanel(); + WxDescriptorPanel(wxWindow *parent); + ~WxDescriptorPanel(); + + // Get file to load Descriptor + const std::string& GetDescriptor(){ return m_DscpFile;} + + private : + + // WxControls + wxTextCtrl *LevelCtrl; //TextCtrl to enter level's name + wxTextCtrl *GRCtrl; // TextCtrl to enter DICOM Group value + wxTextCtrl *ELCtrl; // TextCtrl to enter DICOM element value + wxTextCtrl *ResultCtrl; //TextCtrl to visualize Descriptor + wxComboBox *AttributeCombo; // Combox to choose Attribute values + + /// Add an attribute (DICOM or own) + void OnAddAttribute(wxCommandEvent& event); + + /// Add an attribute (DICOM or own) + void onAddAttribute( const std::string &att, const std::string &name_att, std::string level = ""); + + /// Add a Level + void OnAddLevel(wxCommandEvent& event); + + /// Add a Level + void onAddLevel(const std::string &level); + + /// Find a DICOM attribute from group and element values + void OnDicomAttribute(wxCommandEvent& event); + + /// Remove a value (level or attribute) + void OnRemove(wxCommandEvent& event); + + /// Create a new descriptor + void OnNew(wxCommandEvent& event); + + /// Load an exsitant descriptor + void OnLoad(wxCommandEvent& event); + + /// Save a descriptor + void OnOK(wxCommandEvent& event); + + /// Save a descriptor and use it + void OnApply(wxCommandEvent& event); + + /// Cancel + void OnCancel(wxCommandEvent& event); + + /// Create a descriptor structure + void CreateDescriptor(int type); + + /// add a level + bool addLevel(const std::string &name); + + /// add an attribute + bool addAtribute(const std::string &level, const std::string &name); + + /// remove an attribute + bool RemoveAttribute(const std::string &level, const std::string &name); + + /// remove a level + bool RemoveLevel(const std::string &name); + + /// Create a descriptor file + void createDescriptorFile(); + + /// load a descriptor file + void loadDescriptor(const std::string i_name); + + /// find a level'name + std::string findLevel(); + + /// determine values for own attributes + std::string OwnAttribute(const std::string name); + + /// save a descriptor in a file + const std::string saveDescriptor(); + + /// number of level + int lv; + + /// Insert point in result control + long InsertPt; + + /// Output file for Descriptor + std::string m_DscpFile; + + /// Output Descriptor + std::string outDscp; + + // Vector of attributes + std::vector VLevel; + + // map of level, attributes + std::map > DscpTree; + + // map of own application attributes + std::map ownatt; + + // List of added level + std::map lvlist; + + }; // class WxDescriptorPanel + //===================================================================== + + +} // EO namespace creaImageIO + + +#endif // USE_WIDGETS +// EOF +#endif + diff --git a/src2/creaImageIOWxGimmickView.cpp b/src2/creaImageIOWxGimmickView.cpp index c3e2b07..522b054 100644 --- a/src2/creaImageIOWxGimmickView.cpp +++ b/src2/creaImageIOWxGimmickView.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace crea; // Icons @@ -36,15 +37,15 @@ namespace creaImageIO // The ids of the different tools enum { - TOOL_CREATEDB_ID = 1, - TOOL_ADDFILES_ID = 2, - TOOL_ADDDIR_ID = 3, - TOOL_ADDDATABASE_ID = 4, - TOOL_REMOVE_ID = 5, - TOOL_SYNCHRONIZE_ID = 6, - TOOL_HELP_ID = 7, - TOOL_SETTINGS_ID = 8, - TOOL_TOOLS_ID = 9 + TOOL_ADDFILES_ID = 1, + TOOL_ADDDIR_ID = 2, + TOOL_ADDDATABASE_ID = 3, + TOOL_REMOVE_ID = 4, + TOOL_SYNCHRONIZE_ID = 5, + TOOL_HELP_ID = 6, + TOOL_SETTINGS_ID = 7, + TOOL_TOOLS_ID = 8, + TOOL_CREATEDB_ID = 9, }; //====================================================================== @@ -204,12 +205,7 @@ namespace creaImageIO mToolBar = new wxToolBar(this,-1,wxDefaultPosition,wxDefaultSize, style); - mToolAddFile = mToolBar->AddTool( TOOL_CREATEDB_ID, - _T("Create database"), - mIcon->GetBitmap(Icon_create_database), - _T("Create DB from an Attributes Descriptor file") - ); - mToolAddFile = mToolBar->AddTool( TOOL_ADDFILES_ID, + mToolAddFile = mToolBar->AddTool( TOOL_ADDFILES_ID, _T("Add file(s)"), mIcon->GetBitmap(Icon_page_down), _T("Add one or more file to database") @@ -249,6 +245,12 @@ namespace creaImageIO mIcon->GetBitmap(Icon_tools), _T("Applies tools to images") ); + mToolAddFile = mToolBar->AddTool( TOOL_CREATEDB_ID, + _T("Create database"), + mIcon->GetBitmap(Icon_create_database), + _T("Create DB from an Attributes Descriptor file") + ); + //const wxBitmap& bitmap1, const wxString& shortHelpString = "", wxItemKind kind = wxITEM_NORMAL) mToolBar->Realize(); @@ -783,7 +785,8 @@ namespace creaImageIO { mViewer->StopPlayer(); - wxDialog* dial = new wxDialog (this,-1,_T("Tools"),wxDefaultPosition, wxSize(300,250)); + + wxDialog* dial = new wxDialog (this,-1,_T("Tools"),wxDefaultPosition, wxSize(550,350)); wxSizer* buttonsSizer = dial->CreateSeparatedButtonSizer(wxOK|wxCANCEL); wxNotebook* nb= new wxNotebook(dial, -1, wxDefaultPosition, wxDefaultSize, 0); @@ -797,6 +800,7 @@ namespace creaImageIO WxGimmickTools * gimmickTools = new WxGimmickTools(nb, mCurrentDirectory); nb->AddPage( gimmickTools, _T("Bruker Image Reader") ); #endif + dial->SetSizer(dialSizer, true); dial->Layout(); @@ -1027,21 +1031,6 @@ namespace creaImageIO mess << "Files\tscanned\t: " << p.GetNumberScannedFiles() << "\n"; mess << "Files\thandled\t: " << p.GetNumberHandledFiles() << "\n\n"; mess << "Files\tadded \t: " << p.GetNumberAddedFiles() << "\n\n"; - - /* char times[500]; - sprintf(times,"Time to parse dir \t\t: %ld ms \t%d°/o\nTime to read files info \t: %ld ms \t%d°/o\nTime to update structs \t: %ld ms \t%d°/o\nTime to update database \t: %ld ms \t%d°/o\nTotal time \t\t\t: %ld ms", - summary.parse_time, - (int)( summary.parse_time*100./summary.total_time), - summary.file_scan_time, - (int)(summary.file_scan_time*100./summary.total_time), - summary.update_structs_time, - (int)(summary.update_structs_time*100./summary.total_time), - summary.update_database_time, - (int)(summary.update_database_time*100./summary.total_time), - summary.total_time ); - - mess << times; - */ wxMessageBox(std2wx(mess.str()),_T("Addition result"),wxOK,this); } @@ -1092,38 +1081,29 @@ namespace creaImageIO void WxGimmickView::OnCreateDB(wxCommandEvent& event) { - //Select DB - long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST; - std::string wc("*.txt"); - wxFileDialog* FD = new wxFileDialog( 0, - _T("Select file"), - _T(""), - _T(""), - crea::std2wx(wc), - style, - wxDefaultPosition); - - if (FD->ShowModal()==wxID_OK) - { - wxBusyCursor busy; - wxArrayString afile; - FD->GetPaths(afile); - //get name of DB (file name) - std::string file = crea::wx2std(afile[0]); - size_t pos = file.find_last_of("\\"); - std::string name = file.substr(pos+1); - std::string directory = file.substr(0,pos); - pos = name.find_last_of("."); - name = name.substr(0,pos); - //get directory to store DB - directory += "\\" + name + ".sqlite3"; - //create createDB - mGimmick->createDB(name, file,directory); - //create TreeHandler - mGimmick->addDB(name, directory); - //create TreeView - CreateSingleTreeView(name); - } + WxDescriptorPanel * DescriptorPan = new WxDescriptorPanel(this); + DescriptorPan->Layout(); + if ( DescriptorPan->ShowModal() == ID_DSCP_APPLY) + { + wxBusyCursor busy; + std::string file(DescriptorPan->GetDescriptor()); + if (!file.empty()) + { + size_t pos = file.find_last_of("\\"); + std::string name = file.substr(pos+1); + std::string directory = file.substr(0,pos); + pos = name.find_last_of("."); + name = name.substr(0,pos); + //get directory to store DB + directory += "\\" + name + ".sqlite3"; + //create createDB + mGimmick->createDB(name, file,directory); + //create TreeHandler + mGimmick->addDB(name, directory); + //create TreeView + CreateSingleTreeView(name); + } + } } //================================================= diff --git a/src2/creaImageIOWxViewer.cpp b/src2/creaImageIOWxViewer.cpp index 193fedb..cf9f13c 100644 --- a/src2/creaImageIOWxViewer.cpp +++ b/src2/creaImageIOWxViewer.cpp @@ -5,7 +5,7 @@ #include #include #include - +#include #include #include #include -- 2.45.0