/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
/
/**
* PURPOSE:
*
* rView main application (class rView) and main frame (class rviewMainFrame).
* The main application includes the database object which has to be accessed
* through rView-member functions.
*
* COMMENTS:
* none
*/
#ifdef __GNUG__
#pragma implementation
#endif
// changed in wxWindows 2.4.2:
//#include "wx_prec.h"
#include
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include
#include
#include
#include
#include
#include "labelManager.hh"
#ifdef EARLY_TEMPLATE
#define __EXECUTABLE__
#endif
#include "raslib/rminit.hh"
#include "raslib/rmdebug.hh"
#include "rviewApp.hh"
#include "rviewDb.hh"
#include "rviewPrefs.hh"
//#include "rviewQuery.hh"
#include "rviewIO.hh"
#include "rviewDModes.hh"
#include "rviewOSection.hh"
/*
* Class for the lookup of scaled images, used internally only
*/
class rviewLookScaleDialog: public rviewFrame
{
public:
rviewLookScaleDialog(rmanClientApp *parentApp, const char *name, double scale);
~rviewLookScaleDialog(void);
void label(void);
int process(wxObject &obj, wxEvent &evt);
void OnSize(int w, int h);
// constants
static const int lkscale_border;
static const int lkscale_theight;
static const int lkscale_bwidth;
static const int lkscale_bheight;
static const int lkscale_width;
static const int lkscale_height;
protected:
wxPanel *panel;
rviewText *collName;
rviewText *scaleString;
rviewButton *okBut;
rviewButton *cancelBut;
rmanClientApp *parent;
};
const int rviewLookScaleDialog::lkscale_border = 8;
const int rviewLookScaleDialog::lkscale_theight = 50;
const int rviewLookScaleDialog::lkscale_bwidth = 50;
const int rviewLookScaleDialog::lkscale_bheight = 30;
const int rviewLookScaleDialog::lkscale_width = 300;
const int rviewLookScaleDialog::lkscale_height = 2*rviewLookScaleDialog::lkscale_border + 2*rviewLookScaleDialog::lkscale_theight + rview_window_extra_height;
rviewLookScaleDialog::rviewLookScaleDialog(rmanClientApp *parentApp, const char *name, double scale) : rviewFrame(NULL, lman->lookup("titleLookScaleColl"), -1, -1, lkscale_width, lkscale_height)
{
panel = new wxPanel(this, 0, 0, lkscale_width, lkscale_height);
panel->SetLabelPosition(wxVERTICAL);
collName = new rviewText(panel, name);
scaleString = new rviewText(panel, scale);
okBut = new rviewButton(panel);
cancelBut = new rviewButton(panel);
parent = parentApp;
label();
frameWidth=-1;
frameHeight=-1;
OnSize(lkscale_width, lkscale_height);
OnSize(lkscale_width, lkscale_height);
Show(TRUE);
}
rviewLookScaleDialog::~rviewLookScaleDialog(void)
{
}
void rviewLookScaleDialog::OnSize(int w, int h)
{
int x, y, aux, boff;
GetClientSize(&x, &y);
panel->SetSize(0, 0, x, y);
aux = x - 3*lkscale_border - lkscale_bwidth;
collName->SetSize(lkscale_border, lkscale_border, aux, lkscale_theight);
scaleString->SetSize(lkscale_border, lkscale_border + lkscale_theight, aux, lkscale_theight);
aux += 2*lkscale_border;
boff = lkscale_border + lkscale_theight - lkscale_bheight;
okBut->SetSize(aux, boff, lkscale_bwidth, lkscale_bheight);
cancelBut->SetSize(aux, boff + lkscale_theight, lkscale_bwidth, lkscale_bheight);
}
void rviewLookScaleDialog::label(void)
{
SetTitle(lman->lookup("titleLookScaleColl"));
collName->SetLabel(lman->lookup("lkScaleName"));
scaleString->SetLabel(lman->lookup("lkScaleScale"));
okBut->SetLabel(lman->lookup("textOK"));
cancelBut->SetLabel(lman->lookup("textCancel"));
}
int rviewLookScaleDialog::process(wxObject &obj, wxEvent &evt)
{
int type = evt.GetEventType();
int readAndClose=0;
if (type == wxEVENT_TYPE_TEXT_ENTER_COMMAND)
readAndClose = 1;
else if (type == wxEVENT_TYPE_BUTTON_COMMAND)
{
if (&obj == (wxObject*)okBut)
readAndClose = 1;
else if (&obj == (wxObject*)cancelBut)
{
parent->LookupScaledCollection(NULL, 0.0);
Close(TRUE);
return 1;
}
}
if (readAndClose != 0)
{
double scale;
char *b, *rest;
b = scaleString->GetValue();
scale = strtod(b, &rest);
if (b == rest)
{
cerr << "Bad scaling parameter..." << endl;
}
else
{
parent->LookupScaledCollection(collName->GetValue(), scale);
Close(TRUE);
}
return -1;
}
return 0;
}
//#define DUMMY_MDD_OBJECT r_UShort
//FILE *logfile; // WIN32 debug!!!
// Emergency exit signal handler
void rmanAbort(int code)
{
char *sig;
// First things first
rmanClientApp::theApp()->Shutdown();
switch (code)
{
case SIGINT: sig = "SIGINT"; break;
case SIGABRT: sig = "SIGABRT"; break;
case SIGSEGV: sig = "SIGSEGV"; break;
case SIGFPE: sig = "SIGFPE"; break;
#ifndef __VISUALC__
case SIGBUS: sig = "SIGBUS"; break;
#endif
default: sig = "SIG?"; break;
}
cerr << "Aborted " << code << " (" << sig << " )" << endl;
//fprintf(logfile, "Aborted (%s)\n", sig);
exit(-1);
}
/*
* A RasDaMan client application using wxWindows. This can be used as base class
* to other RasDaMan apps as well.
*/
rmanClientApp *rmanClientApp::theclientapp = NULL;
const char *rmanClientApp::vffFileName = "vff-file";
rmanClientApp::rmanClientApp(const char *homevar, const char *prefsname, const char *labelname)
{
char *rvh;
char *b;
#ifdef __VISUALC__
char *d;
#endif
char labels[STRINGSIZE];
theclientapp = this;
//logfile = fopen("rview.log", "w");
rvh = getenv(homevar);
// labels.txt is looked for in $RVIEWHOME or failing that .
if (rvh == NULL)
sprintf(homeDir, ".");
else
sprintf(homeDir, "%s", rvh);
sprintf(labels, "%s"DIR_SEPARATOR"%s", homeDir, labelname);
lman = new labelManager(labels);
frameManager = new rviewFrameMgr();
rviewInitCharacterTables();
strcpy(prefsFileLeafname, prefsname);
// Preferences are looked for in $HOME, ., $RVIEWHOME
#ifdef __VISUALC__
if (((b = getenv("HOMEDRIVE")) != NULL) && ((d = getenv("HOMEPATH")) != NULL))
sprintf(prefsFile, "%s%s", b, d);
#else
if ((b = getenv("HOME")) != NULL)
sprintf(prefsFile, "%s", b);
#endif
else
strcpy(prefsFile, ".");
// always save prefs to $HOME/.rviewrc
sprintf(prefsSaveFile, "%s"DIR_SEPARATOR"%s", prefsFile, prefsname);
if (!findPreferencesOnPath(prefsFile))
{
strcpy(prefsFile, ".");
if (!findPreferencesOnPath(prefsFile) && (rvh != NULL))
{
strcpy(prefsFile, homeDir);
findPreferencesOnPath(prefsFile);
}
}
if (prefsFile[0] == 0)
{
cerr << "Couldn't find any preferences files." << endl;
cout << "New prefs will be written to " << prefsSaveFile << endl;
}
prefs = new rviewPrefs(prefsFile);
// Install signal handlers (open databases are ANNOYING!)
signal(SIGILL, (void(*)(int))rmanAbort);
signal(SIGINT, (void(*)(int))rmanAbort);
#if !defined(RMANDEBUG)
signal(SIGABRT, (void(*)(int))rmanAbort);
signal(SIGSEGV, (void(*)(int))rmanAbort);
#endif
signal(SIGFPE, (void(*)(int))rmanAbort);
#ifndef __VISUALC__
signal(SIGBUS, (void(*)(int))rmanAbort);
#endif
}
rmanClientApp::~rmanClientApp(void)
{
delete lman; lman = NULL;
delete frameManager; frameManager = NULL;
theclientapp = NULL;
rviewIO::terminate();
//prefs->save(prefsSaveFile);
//fclose(logfile);
}
bool rmanClientApp::findPreferencesOnPath(char *path)
{
sprintf(path + strlen(path), DIR_SEPARATOR"%s", prefsFileLeafname);
if (::wxFileExists(path)) return TRUE;
path[0] = 0; return FALSE;
}
int rmanClientApp::SavePreferences(void) const
{
return prefs->save(prefsSaveFile);
}
rmanClientApp *rmanClientApp::theApp(void)
{
return theclientapp;
}
bool rmanClientApp::ReadDBState(void)
{
return database.isOpen();
}
/*
* Called when something crashes.
*/
void rmanClientApp::Shutdown(void)
{
if (database.isOpen())
{
database.close();
}
}
int rmanClientApp::OpenServer(const char *srvname, int srvport, const char *dbname,
const char *usrname, const char *usrpassword)
{
if (database.isOpen())
return -1;
RMDBGONCE(3, RMDebug::module_applications, "rviewApp", "OpenServer( " << srvname << ", " << dbname << "," << usrname << "," << usrpassword << " )" );
if (database.open(srvname, srvport, dbname, usrname, usrpassword) != 0)
{
user_event ue;
ue.type = usr_db_opened;
if (frameManager != NULL)
frameManager->broadcastUserEvent(ue);
return 0;
}
return -1;
}
int rmanClientApp::CloseServer(void)
{
if (!database.isOpen())
return -1;
user_event ue;
database.close();
ue.type = usr_db_closed;
if (frameManager != NULL)
frameManager->broadcastUserEvent(ue);
RMDBGONCE(3, RMDebug::module_applications, "rviewApp", "CloseServer() Database closed." );
return 0;
}
rviewFrame *rmanClientApp::OpenFile(unsigned int flags, r_Ref *newMddObj, bool resultwin)
{
char *s;
char *prefPath = (char*)(prefs->filePath.ptr());
s = wxFileSelector(lman->lookup("loadFile"), (::wxDirExists(prefPath)) ? prefPath : NULL , NULL, NULL, "*");
if (s)
{
int status;
r_Ref mddPtr;
RMDBGONCE(3, RMDebug::module_applications, "rviewApp", "OpenFile(...) " << s );
prefs->filePath = ::wxPathOnly(s);
prefs->markModified();
// load TIFF
if (rviewIO::isTIFF(s))
{
status = rviewIO::loadTIFF(s, mddPtr, prefs->vffParams.ptr());
if (status == RVIEW_IO_OK)
{
rviewDisplay *newImage;
mdd_frame mddObj;
// receiver makes a copy.
mddObj.mdd = mddPtr; mddObj.flags = 0;
newImage = new rviewFlatImage(&mddObj, flags | rviewDisplay::display_flag_standalone);
if (newMddObj != NULL) *newMddObj = mddPtr;
if (newImage->openViewer() != 0)
{
delete newImage; newImage = NULL;
}
return newImage;
}
}
// load VFF -- whether this is supported is sorted out in rviewIO.cpp
else if (rviewIO::isVFF(s))
{
status = rviewIO::loadVFF(s, mddPtr, prefs->vffParams.ptr());
if (status == RVIEW_IO_OK)
{
if (resultwin)
{
// load in results window
rviewResult *result;
const char *file = ::wxFileNameFromPath(s);
collection_desc *cdesc = new collection_desc;
cdesc->collName = new char[strlen(file)+1];
strcpy(cdesc->collName, file);
cdesc->collType = new char[strlen(mddPtr->get_type_name())+1];
strcpy(cdesc->collType, mddPtr->get_type_name());
cdesc->collInfo = new char[strlen(vffFileName)+1];
strcpy(cdesc->collInfo, vffFileName);
cdesc->number = 1;
cdesc->mddObjs = new mdd_frame[1];
cdesc->strObjs = NULL;
cdesc->mddObjs[0].mdd = mddPtr;
cdesc->mddObjs[0].flags = 0;
result = new rviewResult(cdesc);
return result;
}
else
{
// load in default viewer
rviewDisplay *newImage;
mdd_frame mddObj;
mddObj.mdd = mddPtr; mddObj.flags = 0;
newImage = new rviewVolumeImage(&mddObj, flags | rviewDisplay::display_flag_standalone);
if (newMddObj != NULL) *newMddObj = mddPtr;
if (newImage->openViewer() != 0)
{
delete newImage; newImage = NULL;
}
return newImage;
}
}
}
}
return (rviewFrame*)NULL;
}
int rmanClientApp::LookupCollection(void)
{
collection_desc *desc;
char *name;
name = ::wxGetTextFromUser(lman->lookup("promptEnterColl"), lman->lookup("titleCollLook"), (char*)(prefs->lastColl.ptr()));
if (name == NULL) return 0;
if ((desc = new collection_desc) == NULL)
{
cerr << lman->lookup("errorMemory") << endl;
return 0;
}
memset(desc, 0, sizeof(collection_desc));
if ((desc->collName = new char [strlen(name) + 1]) == NULL)
{
cerr << lman->lookup("errorMemory") << endl;
delete desc;
return 0;
}
strcpy(desc->collName, name);
prefs->lastColl = name;
prefs->markModified();
RMDBGENTER(3, RMDebug::module_applications, "rviewApp", "LookupCollection() " << desc->collName );
#ifdef DUMMY_MDD_OBJECT
desc->number = 1;
r_Minterval iv(3);
iv << r_Sinterval(r_Range(0),r_Range(300)) << r_Sinterval(r_Range(200),r_Range(400)) << r_Sinterval(r_Range(10), r_Range(12));
desc->mddObjs = new mdd_frame[1];
desc->mddObjs[0].mdd = (r_Ref ) new r_Marray(iv);
desc->collType = new char[16]; strcpy(desc->collType, "r_UShort");
r_Ref < r_Marray < DUMMY_MDD_OBJECT > > mddPtr = (r_Ref < r_Marray < DUMMY_MDD_OBJECT > >) desc->mddObjs[0].mdd;
mddPtr->set_type_by_name("UShortImage");
r_Point point(3);
cout << mddPtr->spatial_domain() << endl;
for (point[0]=0; point[0]<=300; point[0]++)
for (point[1]=200; point[1]<=400; point[1]++)
for (point[2]=10; point[2]<=12; point[2]++)
(*mddPtr)[point] = ((DUMMY_MDD_OBJECT)(point[0] + point[1] + point[2])) << (8*(sizeof(DUMMY_MDD_OBJECT) - 1));
if (1)
#else
if (database.lookupCollection(desc) != 0)
#endif
{
RMDBGEXIT(3, RMDebug::module_applications, "rviewApp", "LookupCollection() OK." );
/*for (int i=0; inumber; i++)
{
cout << "Object #" << i << ": " << desc->mddArrays[i]->spatial_domain() << endl;
}*/
rviewResult *result = new rviewResult(desc);
return 1;
}
else
{
rviewDeleteCollection(desc);
}
RMDBGEXIT(3, RMDebug::module_applications, "rviewApp", "LookupCollection() FAILED." );
return 0;
}
int rmanClientApp::LookupScaledCollection(void)
{
rviewLookScaleDialog *lsd = new rviewLookScaleDialog(this, (char*)(prefs->lastScColl.ptr()), prefs->imgScale);
return 0;
}
int rmanClientApp::LookupScaledCollection(const char *name, double scale)
{
if (name != NULL)
{
collection_desc *desc;
RMDBGENTER(3, RMDebug::module_applications, "rviewApp", "LookupScaledCollection( " << name << " at scale " << scale << " )");
prefs->imgScale = scale;
if ((desc = new collection_desc) == NULL)
{
cerr << lman->lookup("errorMemory") << endl;
return 0;
}
memset(desc, 0, sizeof(collection_desc));
if ((desc->collName = new char [strlen(name) + 1]) == NULL)
{
cerr << lman->lookup("errorMemory") << endl;
delete desc;
return 0;
}
strcpy(desc->collName, name);
prefs->lastScColl = name;
prefs->markModified();
r_Fast_Base_Scale *scaler;
if ((scaler = database.lookupScaledObject(desc, scale)) != NULL)
{
// don't call in standalone mode, viewer sorts it out itself.
rviewScaledImage *image = new rviewScaledImage(desc, scaler);
if (image->openViewer() != 0)
{
image->Close(TRUE);
RMDBGEXIT(3, RMDebug::module_applications, "rviewApp", "LookupScalledCollection() FAILED" );
return 0;
}
RMDBGEXIT(3, RMDebug::module_applications, "rviewApp", "LookupScalledCollection() OK" );
return 1;
}
else
{
rviewDeleteCollection(desc);
}
}
RMDBGEXIT(3, RMDebug::module_applications, "rviewApp", "LookupScalledCollection() FAILED" );
return 0;
}
int rmanClientApp::LookupOrthosection(void)
{
char *name;
name = ::wxGetTextFromUser(lman->lookup("promptEnterOrtho"), lman->lookup("titleOrthoLook"), (char*)(prefs->lastOrthoColl.ptr()));
if ((name != NULL) && (strlen(name) != 0))
{
char buffer[STRINGSIZE];
const char *d = name;
char *b = buffer;
const double *lp = NULL;
double loid;
// search the collection name for a trailing ,
while ((*d != '\0') && (*d != ','))
{
*b++ = *d++;
}
while ((b > buffer) && (isspace((unsigned int)(b[-1])))) b--;
*b++ = '\0';
if (*d == ',')
{
loid = atof(d+1);
lp = &loid;
}
return LookupOrthosection(buffer, lp);
}
return -1;
}
int rmanClientApp::LookupOrthosection(const char *collname, const double *loid)
{
rviewOSectionPartImage *newImage = rviewOSectionPartImage::createViewer(collname, loid);
if (newImage == NULL)
{
rviewErrorbox::reportError(lman->lookup("errorOrthoViewer"), "rmanClientApp", "LookupOrthosection");
return -1;
}
prefs->lastOrthoColl = collname;
return 0;
}
int rmanClientApp::CreateCollection(void)
{
char *name;
name = ::wxGetTextFromUser(lman->lookup("promptEnterColl"), lman->lookup("titleCollCrt"), (char*)(prefs->lastOrthoColl.ptr()));
if (name != NULL)
{
char buffer[STRINGSIZE];
strncpy(buffer, name, STRINGSIZE);
return database.createCollection(buffer, rbt_none);
}
return 0;
}
int rmanClientApp::DeleteCollection(void)
{
char *name;
char buffer[STRINGSIZE];
name = ::wxGetTextFromUser(lman->lookup("promptEnterColl"), lman->lookup("titleCollDel"), (char*)(prefs->lastColl.ptr()));
if (name != NULL)
{
strncpy(buffer, name, STRINGSIZE);
return database.deleteCollection(buffer);
}
return 0;
}
int rmanClientApp::insertMDD(r_Ref srcMdd, char *collName, r_Minterval *domain)
{
char useName[STRINGSIZE];
char *title;
int status;
if (domain == NULL)
title = lman->lookup("titleInsertMdd");
else
title = lman->lookup("titleInsertMddPro");
if (collName == NULL)
{
title = ::wxGetTextFromUser(lman->lookup("promptEnterColl"), title, (char*)(prefs->lastColl.ptr()));
if (title == NULL) return 0;
strncpy(useName, title, STRINGSIZE);
}
else
strncpy(useName, collName, STRINGSIZE);
if ((status = database.insertObject(useName, srcMdd, domain)) != 0)
{
prefs->lastColl = useName;
prefs->markModified();
}
return status;
}
collection_desc *rmanClientApp::executeQuerySync(char *query, r_Ref *updateMdd, bool showProgress)
{
collection_desc *desc;
if ((desc = new collection_desc) == NULL)
{
cerr << lman->lookup("errorMemory") << endl;
return NULL;
}
desc->number = 0;
if (database.executeQuery(desc, query, updateMdd, showProgress) == 0)
{
delete desc;
return NULL;
}
// no result?
if (desc->number > 0)
{
char qcollName[] = "";
desc->collName = new char[strlen(qcollName)+1];
strcpy(desc->collName, qcollName);
}
else
{
delete desc;
return NULL;
}
return desc;
}
int rmanClientApp::executeQuery(char *query, r_Ref *updateMdd)
{
collection_desc *desc;
if ((desc = executeQuerySync(query, updateMdd)) != NULL)
{
if (desc->mddObjs != NULL)
{
rviewResult *qresult = new rviewResult(desc);
}
else
{
rviewStringSet *qresult = new rviewStringSet(desc);
// rviewStringSet doesn't need the descriptor data after the
// constructor, so we can just delete it right away
rviewDeleteCollection(desc);
}
return 1;
}
return 0;
}
int rmanClientApp::getMinterval(r_Minterval &dom, const char *collname, const double *loid)
{
return database.getMinterval(dom, collname, loid);
}