2012-04-13 15:14:01 +00:00
|
|
|
|
#include "wxinc.h"
|
|
|
|
|
#include "incstr.h"
|
|
|
|
|
|
|
|
|
|
#include "agasys.h"
|
|
|
|
|
#include "xvt.h"
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Unzip support
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#include <wx/dir.h>
|
|
|
|
|
#include <wx/progdlg.h>
|
|
|
|
|
#include <wx/wfstream.h>
|
|
|
|
|
#include <wx/zipstrm.h>
|
|
|
|
|
|
|
|
|
|
static unsigned int aga_getziplist(const char* zipfile, wxArrayString& aFiles)
|
|
|
|
|
{
|
|
|
|
|
wxFFileInputStream fin(zipfile);
|
|
|
|
|
wxZipInputStream zip(fin);
|
|
|
|
|
for (wxZipEntry* z = zip.GetNextEntry(); z; z = zip.GetNextEntry())
|
|
|
|
|
{
|
|
|
|
|
const wxString str = z->GetInternalName();
|
|
|
|
|
aFiles.Add(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return aFiles.GetCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool aga_unzip(const char* zipfile, const char* destdir)
|
|
|
|
|
{
|
|
|
|
|
wxArrayString aFiles;
|
|
|
|
|
const unsigned int files = aga_getziplist(zipfile, aFiles);
|
|
|
|
|
|
|
|
|
|
wxProgressDialog pi("Unzip", "", files, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
|
|
|
|
|
pi.SetSize(480, 120);
|
|
|
|
|
pi.Center();
|
|
|
|
|
|
|
|
|
|
for (unsigned int f = 0; f < files; f++)
|
|
|
|
|
{
|
|
|
|
|
const wxString& strFileName = aFiles[f];
|
|
|
|
|
if (!pi.Update(f, strFileName))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (wxEndsWithPathSeparator(strFileName) || strFileName.Find('.') < 0) // Is dir name
|
|
|
|
|
{
|
|
|
|
|
wxString strOutDir = destdir;
|
|
|
|
|
if (!wxEndsWithPathSeparator(strOutDir))
|
|
|
|
|
strOutDir += wxFILE_SEP_PATH;
|
|
|
|
|
strOutDir += strFileName;
|
2014-09-22 13:47:58 +00:00
|
|
|
|
xvt_fsys_mkdir(strOutDir);
|
2012-04-13 15:14:01 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
wxFFileInputStream file(zipfile);
|
|
|
|
|
wxZipInputStream fin(file);
|
2012-04-10 07:53:46 +00:00
|
|
|
|
|
|
|
|
|
wxZipEntry* entry = NULL;
|
|
|
|
|
do entry = fin.GetNextEntry();
|
|
|
|
|
while (entry && entry->GetInternalName() != strFileName);
|
|
|
|
|
if (entry == NULL || !fin.OpenEntry(*entry))
|
|
|
|
|
continue;
|
2012-04-13 15:14:01 +00:00
|
|
|
|
|
|
|
|
|
wxString strOutFile = destdir;
|
|
|
|
|
if (!wxEndsWithPathSeparator(strOutFile) && !wxIsPathSeparator(strFileName[0]))
|
|
|
|
|
strOutFile += wxFILE_SEP_PATH;
|
|
|
|
|
strOutFile += strFileName;
|
|
|
|
|
|
|
|
|
|
wxString strPath;
|
|
|
|
|
::wxSplitPath(strOutFile, &strPath, NULL, NULL);
|
2014-09-22 13:47:58 +00:00
|
|
|
|
xvt_fsys_mkdir(strPath);
|
2012-04-13 15:14:01 +00:00
|
|
|
|
|
|
|
|
|
wxFileOutputStream fout(strOutFile);
|
|
|
|
|
fout.Write(fin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return files > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Zip support
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static void AddFileToZip(const wxString& strPrefix, const wxString& strFile,
|
|
|
|
|
wxZipOutputStream& zip)
|
|
|
|
|
{
|
|
|
|
|
if (!wxFileExists(strFile))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
wxString strPath, strName, strExt;
|
|
|
|
|
wxSplitPath(strFile, &strPath, &strName, &strExt);
|
|
|
|
|
|
|
|
|
|
wxString strRelName;
|
|
|
|
|
strRelName = strPath.Mid(strPrefix.Length());
|
|
|
|
|
if (!strRelName.IsEmpty())
|
|
|
|
|
strRelName += '/';
|
|
|
|
|
strRelName += strName;
|
|
|
|
|
strRelName += '.';
|
|
|
|
|
strRelName += strExt;
|
|
|
|
|
|
|
|
|
|
zip.PutNextEntry(strRelName);
|
|
|
|
|
wxFileInputStream fin(strFile);
|
|
|
|
|
zip.Write(fin); // Scrivo file compresso
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool AddFilesToZip(const wxString& strBase, wxArrayString& aFiles, const char* zipfile)
|
|
|
|
|
{
|
|
|
|
|
wxFFileOutputStream out(zipfile);
|
|
|
|
|
wxZipOutputStream zip(out);
|
|
|
|
|
|
|
|
|
|
const size_t nFiles = aFiles.GetCount();
|
|
|
|
|
wxProgressDialog pi("Zip", "", nFiles, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
|
|
|
|
|
pi.SetSize(480, 120);
|
|
|
|
|
pi.Center();
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < nFiles; i++)
|
|
|
|
|
{
|
|
|
|
|
const wxString& str = aFiles[i];
|
|
|
|
|
if (!pi.Update(i, str))
|
|
|
|
|
break;
|
|
|
|
|
AddFileToZip(strBase, str, zip);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool aga_zip(const char* srcfiles, const char* zipfile)
|
|
|
|
|
{
|
|
|
|
|
wxString strBase, strMask, strExt;
|
|
|
|
|
wxSplitPath(srcfiles, &strBase, &strMask, &strExt);
|
|
|
|
|
strMask += '.';
|
|
|
|
|
strMask += strExt;
|
|
|
|
|
|
|
|
|
|
wxArrayString aFiles;
|
|
|
|
|
wxDir::GetAllFiles(strBase, &aFiles, strMask);
|
|
|
|
|
|
|
|
|
|
return AddFilesToZip(strBase, aFiles, zipfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool aga_zip_filelist(const char* filelist, const char* zipfile)
|
|
|
|
|
{
|
|
|
|
|
wxArrayString aFiles;
|
|
|
|
|
ifstream fin(filelist);
|
|
|
|
|
while (!fin.eof())
|
|
|
|
|
{
|
|
|
|
|
char name[_MAX_PATH];
|
|
|
|
|
fin.getline(name, sizeof(name));
|
|
|
|
|
if (*name)
|
|
|
|
|
aFiles.Add(name);
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return AddFilesToZip("", aFiles, zipfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// DDE
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#ifdef __WXMSW__
|
|
|
|
|
#include <wx/dde.h>
|
|
|
|
|
#define wxAgaClient wxDDEClient
|
|
|
|
|
#define wxAgaConnection wxDDEConnection
|
|
|
|
|
#else
|
|
|
|
|
// Forse inutile: forse gia' fatto da wxWidgets
|
|
|
|
|
#include <wx/sckipc.h>
|
|
|
|
|
#define wxAgaClient wxTCPClient
|
|
|
|
|
#define wxAgaConnection wxTCPConnection
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static wxAgaClient* _net_client = NULL;
|
|
|
|
|
static unsigned long _net_conns = 0;
|
|
|
|
|
|
|
|
|
|
unsigned long aga_dde_connect(const char* host, const char* service, const char* topic)
|
|
|
|
|
{
|
|
|
|
|
if (_net_client == NULL)
|
|
|
|
|
{
|
|
|
|
|
_net_client = new wxAgaClient;
|
|
|
|
|
_net_conns = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxConnectionBase* conn = _net_client->MakeConnection(host, service, topic);
|
|
|
|
|
if (conn != NULL)
|
|
|
|
|
_net_conns++;
|
|
|
|
|
|
|
|
|
|
return (unsigned long)conn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool aga_dde_execute(unsigned long connection, const char* msg)
|
|
|
|
|
{
|
|
|
|
|
bool ok = false;
|
|
|
|
|
if (connection != 0)
|
|
|
|
|
{
|
|
|
|
|
wxAgaConnection* conn = (wxAgaConnection*)connection;
|
|
|
|
|
ok = conn->Execute((char*)msg, -1);
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool aga_dde_terminate(unsigned long connection)
|
|
|
|
|
{
|
|
|
|
|
bool ok = false;
|
|
|
|
|
if (connection != 0 && _net_client != NULL)
|
|
|
|
|
{
|
|
|
|
|
wxAgaConnection* conn = (wxAgaConnection*)connection;
|
|
|
|
|
ok = conn->Disconnect();
|
|
|
|
|
if (ok && _net_conns > 0)
|
|
|
|
|
{
|
|
|
|
|
_net_conns--;
|
|
|
|
|
if (_net_conns == 0)
|
|
|
|
|
{
|
|
|
|
|
delete _net_client;
|
|
|
|
|
_net_client = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-22 13:47:58 +00:00
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Multi file operations
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/* Solo da Vista in poi...
|
|
|
|
|
#include <Shobjidl.h>
|
|
|
|
|
#include <ShlGUID.h>
|
|
|
|
|
|
|
|
|
|
static IFileOperation* CreatePFO()
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
|
|
|
|
if (!SUCCEEDED(hr))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
IFileOperation *pfo = NULL;
|
|
|
|
|
hr = ::CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
|
|
|
|
|
if (!SUCCEEDED(hr))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
pfo->SetOperationFlags(FOF_NOCONFIRMATION);
|
|
|
|
|
|
|
|
|
|
return pfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DeleteIUnknown(IUnknown* iu)
|
|
|
|
|
{
|
|
|
|
|
if (iu)
|
|
|
|
|
{
|
|
|
|
|
iu->Release();
|
|
|
|
|
iu = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int xvt_fsys_files_remove(const char* src, SLIST names)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
int nDone = 0;
|
|
|
|
|
IFileOperation *pfo = CreatePFO();
|
|
|
|
|
if (!pfo)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
HRESULT hr = 0;
|
|
|
|
|
|
|
|
|
|
if (xvt_slist_count(names) == 0)
|
|
|
|
|
{
|
|
|
|
|
wxString n = src;
|
|
|
|
|
wxWritableWCharBuffer wcb = n.wchar_str();
|
|
|
|
|
IShellItem* psiFolder = NULL;
|
|
|
|
|
hr = ::SHCreateItemFromParsingName(wcb, NULL, IID_PPV_ARGS(&psiFolder));
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
{
|
|
|
|
|
IEnumShellItems* pEnum = NULL;
|
|
|
|
|
hr = psiFolder->BindToHandler(NULL, BHID_EnumItems, IID_IEnumShellItems, (void**)&pEnum);
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
{
|
|
|
|
|
hr = pfo->DeleteItems(pEnum);
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
nDone++;
|
|
|
|
|
DeleteIUnknown(pEnum);
|
|
|
|
|
}
|
|
|
|
|
DeleteIUnknown(psiFolder);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (SLIST_ELT e = xvt_slist_get_first(names); e; e = xvt_slist_get_next(names, e))
|
|
|
|
|
{
|
|
|
|
|
wxFileName n = xvt_slist_get(names, e, NULL);
|
|
|
|
|
if (!n.IsAbsolute())
|
|
|
|
|
n.PrependDir(src);
|
|
|
|
|
wxWritableWCharBuffer wcb = n.GetFullPath().wchar_str();
|
|
|
|
|
IShellItem* psiItem = NULL;
|
|
|
|
|
hr = ::SHCreateItemFromParsingName(wcb, NULL, IID_PPV_ARGS(&psiItem));
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
{
|
|
|
|
|
hr = pfo->DeleteItem(psiItem, NULL);
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
nDone++;
|
|
|
|
|
DeleteIUnknown(psiItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hr = pfo->PerformOperations();
|
|
|
|
|
DeleteIUnknown(pfo);
|
|
|
|
|
return SUCCEEDED(hr) ? nDone : -1;
|
|
|
|
|
*/
|
|
|
|
|
return -1; // Not implemented yet
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int xvt_fsys_files_copy(const char* src, SLIST names, const char* dst)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int xvt_fsys_files_move(const char* src, SLIST names, const char* dst)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-13 15:14:01 +00:00
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// TProgressIndicator
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class TProgressIndicator : public wxDialog
|
|
|
|
|
{
|
|
|
|
|
enum { MAX_GAUGES = 16 };
|
|
|
|
|
wxGauge* m_pGauge[MAX_GAUGES];
|
|
|
|
|
wxStaticText* m_pPassed;
|
|
|
|
|
wxStaticText* m_pResidual;
|
|
|
|
|
wxStaticText* m_pEstimated;
|
|
|
|
|
wxStopWatch m_chrono;
|
|
|
|
|
long m_nNextUpdate;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
DECLARE_EVENT_TABLE();
|
|
|
|
|
|
|
|
|
|
void Init(wxString msg, int nGauges, bool bCancellable);
|
|
|
|
|
wxString msec2str(long ms) const;
|
|
|
|
|
long Elapsed() const { return m_chrono.Time(); }
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
void SetRange(int nRange, int nGauge = 0);
|
|
|
|
|
bool SetProgress(int nPos, int nGauge = 0);
|
|
|
|
|
void SetMessage(wxString msg);
|
|
|
|
|
|
|
|
|
|
TProgressIndicator(wxString msg, bool bCancellable, int nGauges);
|
|
|
|
|
TProgressIndicator(size_t nRange, wxString msg, bool bCancellable);
|
|
|
|
|
virtual ~TProgressIndicator();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
BEGIN_EVENT_TABLE(TProgressIndicator, wxDialog)
|
|
|
|
|
// EVT_MENU(wxID_CANCEL, TProgressIndicator::OnCancel)
|
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
|
|
|
|
|
wxString TProgressIndicator::msec2str(long ms) const
|
|
|
|
|
{
|
|
|
|
|
int s = ms/1000;
|
|
|
|
|
const int h = s / 3600;
|
|
|
|
|
s -= h*3600;
|
|
|
|
|
const int m = s / 60;
|
|
|
|
|
s -= m*60;
|
|
|
|
|
return wxString::Format(wxT("%02d:%02d:%02d"), h, m, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TProgressIndicator::SetRange(int nRange, int nGauge)
|
|
|
|
|
{
|
|
|
|
|
wxASSERT(nRange >= 0 && nGauge >= 0 && nGauge < MAX_GAUGES);
|
|
|
|
|
m_pGauge[nGauge]->SetRange(nRange);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TProgressIndicator::SetProgress(int nPos, int nGauge)
|
|
|
|
|
{
|
|
|
|
|
if (!IsShown())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
wxASSERT(nPos >= 0 && nGauge >= 0 && nGauge < MAX_GAUGES);
|
|
|
|
|
m_pGauge[nGauge]->SetValue(nPos);
|
|
|
|
|
|
|
|
|
|
const long elap = Elapsed();
|
|
|
|
|
if (elap > m_nNextUpdate)
|
|
|
|
|
{
|
|
|
|
|
m_nNextUpdate = elap+CLOCKS_PER_SEC;
|
|
|
|
|
m_pPassed->SetLabel(msec2str(elap));
|
|
|
|
|
|
|
|
|
|
wxLongLong_t nTotValue = 0, nTotRange = 0;
|
|
|
|
|
for (int i = 0; i < MAX_GAUGES && m_pGauge[i]; i++)
|
|
|
|
|
{
|
|
|
|
|
const int nValue = m_pGauge[i]->GetValue();
|
|
|
|
|
const int nRange = m_pGauge[i]->GetRange();
|
|
|
|
|
if (nValue < nRange) // Escludi dal calcolo i processi gi<67> terminati
|
|
|
|
|
{
|
|
|
|
|
nTotValue += nValue;
|
|
|
|
|
nTotRange += nRange;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (nTotValue > 0)
|
|
|
|
|
{
|
|
|
|
|
const long est = long(elap * nTotRange / nTotValue);
|
|
|
|
|
m_pEstimated->SetLabel(msec2str(est));
|
|
|
|
|
m_pResidual->SetLabel(msec2str(est-elap));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxYield();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TProgressIndicator::SetMessage(wxString msg)
|
|
|
|
|
{ SetLabel(msg); }
|
|
|
|
|
|
|
|
|
|
void TProgressIndicator::Init(wxString msg, int nGauges, bool bCancellable)
|
|
|
|
|
{
|
|
|
|
|
const int nGap = 4;
|
|
|
|
|
wxBoxSizer* pTopSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
|
SetSizer(pTopSizer);
|
|
|
|
|
|
|
|
|
|
memset(m_pGauge, 0, sizeof(m_pGauge));
|
|
|
|
|
for (int i = 0; i < nGauges; i++)
|
|
|
|
|
{
|
|
|
|
|
m_pGauge[i] = new wxGauge(this, 1001+i, 100, wxDefaultPosition, wxSize(400, -1));
|
|
|
|
|
pTopSizer->Add(m_pGauge[i], 0, wxALL, nGap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxGridSizer* pTimersSizer = new wxGridSizer(1, 3, nGap, nGap);
|
|
|
|
|
pTopSizer->Add(pTimersSizer, 0, wxEXPAND);
|
|
|
|
|
|
|
|
|
|
wxStaticBoxSizer* pPassed = new wxStaticBoxSizer(wxVERTICAL, this, _("Elapsed Time"));
|
|
|
|
|
pTimersSizer->Add(pPassed, 0, wxEXPAND);
|
|
|
|
|
m_pPassed = new wxStaticText(this, 1101, wxT("00:00:00"));
|
|
|
|
|
pPassed->Add(m_pPassed, 0, wxALL|wxALIGN_CENTER, 0);
|
|
|
|
|
|
|
|
|
|
wxStaticBoxSizer* pResidual = new wxStaticBoxSizer(wxVERTICAL, this, _("Residual Time"));
|
|
|
|
|
pTimersSizer->Add(pResidual, 0, wxEXPAND);
|
|
|
|
|
m_pResidual = new wxStaticText(this, 1102, wxT("00:00:00"));
|
|
|
|
|
pResidual->Add(m_pResidual, 0, wxALL|wxALIGN_CENTER, 0);
|
|
|
|
|
|
|
|
|
|
wxStaticBoxSizer* pEstimated = new wxStaticBoxSizer(wxVERTICAL, this, _("Estimated Time"));
|
|
|
|
|
pTimersSizer->Add(pEstimated, 0, wxEXPAND);
|
|
|
|
|
m_pEstimated = new wxStaticText(this, 1103, wxT("00:00:00"));
|
|
|
|
|
pEstimated->Add(m_pEstimated, 0, wxALL|wxALIGN_CENTER, 0);
|
|
|
|
|
|
|
|
|
|
wxButton* pCancel = NULL;
|
|
|
|
|
if (bCancellable)
|
|
|
|
|
{
|
|
|
|
|
pCancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
|
|
|
|
|
pTopSizer->Add(pCancel, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, nGap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pTopSizer->SetSizeHints(this);
|
|
|
|
|
|
|
|
|
|
SetMessage(msg);
|
|
|
|
|
|
|
|
|
|
Show();
|
|
|
|
|
Enable();
|
|
|
|
|
Update();
|
|
|
|
|
|
|
|
|
|
m_nNextUpdate = 0;
|
|
|
|
|
m_chrono.Start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TProgressIndicator::TProgressIndicator(size_t nRange, wxString msg, bool bCancellable)
|
|
|
|
|
: wxDialog(NULL, wxID_ANY, msg)
|
|
|
|
|
{
|
|
|
|
|
Init(msg, 1, bCancellable);
|
|
|
|
|
SetRange(nRange, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TProgressIndicator::TProgressIndicator(wxString msg, bool bCancellable, int nGauges)
|
|
|
|
|
: wxDialog(NULL, wxID_ANY, msg)
|
|
|
|
|
{
|
|
|
|
|
Init(msg, nGauges, bCancellable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TProgressIndicator::~TProgressIndicator()
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Multiprocess
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class TWorker : public wxThread
|
|
|
|
|
{
|
|
|
|
|
XVT_MULTITHREAD_CALLBACK m_pFunc;
|
|
|
|
|
void* m_pCaller;
|
|
|
|
|
void* m_pData;
|
|
|
|
|
int m_nFirst, m_nLast, m_nTotal;
|
|
|
|
|
TProgressIndicator* m_pi;
|
|
|
|
|
int m_nGauge;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual ExitCode Entry();
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TWorker(XVT_MULTITHREAD_CALLBACK func, void* pCaller, void* pData,
|
|
|
|
|
int nFirst, int nLast, int nTotal, TProgressIndicator* pi, int nGauge);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
wxThread::ExitCode TWorker::Entry()
|
|
|
|
|
{
|
|
|
|
|
ExitCode ec = 0;
|
|
|
|
|
if (m_pi != NULL)
|
|
|
|
|
{
|
|
|
|
|
m_pi->SetRange(m_nLast-m_nFirst, m_nGauge);
|
|
|
|
|
for (int i = m_nFirst; i < m_nLast && ec == 0; i++)
|
|
|
|
|
{
|
|
|
|
|
ec = (ExitCode)m_pFunc(m_pCaller, m_pData, i, m_nTotal);
|
|
|
|
|
if (!m_pi->SetProgress(i-m_nFirst+1, m_nGauge))
|
|
|
|
|
ec = ExitCode(-1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = m_nFirst; i < m_nLast && ec == 0; i++)
|
|
|
|
|
ec = (ExitCode)m_pFunc(m_pCaller, m_pData, i, m_nTotal);
|
|
|
|
|
}
|
|
|
|
|
return ec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TWorker::TWorker(XVT_MULTITHREAD_CALLBACK func, void* pCaller, void* pData,
|
|
|
|
|
int nFirst, int nLast, int nTotal, TProgressIndicator* pi, int nGauge)
|
|
|
|
|
: wxThread(wxTHREAD_JOINABLE), m_pFunc(func), m_pCaller(pCaller), m_pData(pData),
|
|
|
|
|
m_nFirst(nFirst), m_nLast(nLast), m_nTotal(nTotal), m_pi(pi), m_nGauge(nGauge)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// SetPriority(WXTHREAD_MIN_PRIORITY);
|
|
|
|
|
Create();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN xvt_sys_multithread(XVT_MULTITHREAD_CALLBACK pFunc, void* pCaller, void* pData,
|
|
|
|
|
int tot, const char* msg)
|
|
|
|
|
{
|
|
|
|
|
const int MAX_WORKERS = 16;
|
|
|
|
|
|
|
|
|
|
// Bilanciamento automatico
|
|
|
|
|
int nWorkers = wxThread::GetCPUCount();
|
|
|
|
|
if (nWorkers <= 0)
|
|
|
|
|
nWorkers = 1;
|
|
|
|
|
if (nWorkers > tot)
|
|
|
|
|
nWorkers = tot;
|
|
|
|
|
if (nWorkers > MAX_WORKERS)
|
|
|
|
|
nWorkers = MAX_WORKERS;
|
|
|
|
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
if (nWorkers > 1)
|
|
|
|
|
{
|
|
|
|
|
TProgressIndicator* pi = NULL;
|
|
|
|
|
if (msg && *msg)
|
|
|
|
|
pi = new TProgressIndicator(msg, tot > nWorkers, nWorkers);
|
|
|
|
|
|
|
|
|
|
TWorker* worker[MAX_WORKERS]; memset(worker, 0, sizeof(worker));
|
|
|
|
|
|
|
|
|
|
int nFirst, nLast = 0, w;
|
|
|
|
|
for (w = 0; w < nWorkers; w++)
|
|
|
|
|
{
|
|
|
|
|
nFirst = nLast;
|
|
|
|
|
nLast = tot*(w+1)/nWorkers;
|
|
|
|
|
worker[w] = new TWorker(pFunc, pCaller, pData, nFirst, nLast, tot, pi, w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (w = 0; w < nWorkers; w++)
|
|
|
|
|
worker[w]->Run();
|
|
|
|
|
|
|
|
|
|
if (pi != NULL)
|
|
|
|
|
pi->Refresh();
|
|
|
|
|
|
|
|
|
|
for (w = 0; w < nWorkers; w++)
|
|
|
|
|
{
|
|
|
|
|
const wxThread::ExitCode r = worker[w]->Wait();
|
|
|
|
|
if (ret == 0 && r != 0)
|
|
|
|
|
ret = int(r);
|
|
|
|
|
delete worker[w];
|
|
|
|
|
worker[w] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pi != NULL)
|
|
|
|
|
delete pi;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (msg && *msg)
|
|
|
|
|
{
|
|
|
|
|
TProgressIndicator pi(size_t(tot), msg, tot > nWorkers);
|
|
|
|
|
for (int i = 0; i < tot && ret == 0; i++)
|
|
|
|
|
{
|
|
|
|
|
ret = pFunc(pCaller, pData, i, tot);
|
|
|
|
|
if (!pi.SetProgress(i+1))
|
|
|
|
|
ret = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < tot && ret == 0; i++)
|
|
|
|
|
ret = pFunc(pCaller, pData, i, tot);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|