summaryrefslogtreecommitdiffstats
path: root/applications/rview/rviewQuery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'applications/rview/rviewQuery.cpp')
-rw-r--r--applications/rview/rviewQuery.cpp647
1 files changed, 647 insertions, 0 deletions
diff --git a/applications/rview/rviewQuery.cpp b/applications/rview/rviewQuery.cpp
new file mode 100644
index 0000000..eddbd7f
--- /dev/null
+++ b/applications/rview/rviewQuery.cpp
@@ -0,0 +1,647 @@
+/*
+* 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 <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+
+/**
+ * PURPOSE:
+ *
+ * rView query shell. Handles editing, loading, saving and execution
+ * of RasQL queries. Actual database accesses are performed through
+ * class rView's member functions.
+ *
+ * COMMENTS:
+ * None
+ */
+
+
+
+// Standard wxWindows preamble.
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+
+#include <wx/wxprec.h>
+
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+
+
+#include <string.h>
+#include <iostream.h>
+#include <ctype.h>
+
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#endif
+
+#include "raslib/rmdebug.hh"
+
+#include "rviewApp.hh"
+#include "rviewUtils.hh"
+//#include "rviewDb.hh"
+#include "rviewQuery.hh"
+#include "rviewPrefs.hh"
+
+
+
+
+const int rviewQuery::query_width = 500;
+const int rviewQuery::query_height = 300;
+const int rviewQuery::query_border = 8;
+const int rviewQuery::query_bottom = 50;
+const int rviewQuery::query_bwidth = 80;
+const int rviewQuery::query_bheight = 40;
+
+
+
+
+const char rviewQuery::query_extension[] = ".ql";
+const char rviewQuery::query_firstline[] = "-- rview-Query";
+
+
+
+// The Query window counter
+int rviewQuery::queryCounter = 0;
+
+
+// Lookup tables for fonts. These have to be sorted case-sensitively!
+const keyword_to_ident_c rviewQuery::fontNameTab[] = {
+ {wxDECORATIVE, "decorative"},
+ {wxDEFAULT, "default"},
+ {wxMODERN, "modern"},
+ {wxROMAN, "roman"},
+ {wxSCRIPT, "script"},
+ {wxSWISS, "swiss"},
+ {wxTELETYPE, "teletype"}
+};
+const keyword_to_ident_c rviewQuery::fontStyleTab[] = {
+ {wxITALIC, "italic"},
+ {wxSLANT, "slant"}
+};
+
+const keyword_to_ident_c rviewQuery::fontWeightTab[] = {
+ {wxBOLD, "bold"},
+ {wxLIGHT, "light"}
+};
+
+
+
+
+rviewQuery::rviewQuery(rviewDatabase *db, char *query) : rviewFrame(NULL, NULL, 0, 0, query_width, query_height)
+{
+ int w, h;
+ const char *b;
+ char *d;
+ char buffer[STRINGSIZE];
+ int fontSize, fontName, fontStyle, fontWeight;
+ const int fontNameSize = sizeof(fontNameTab) / sizeof(keyword_to_ident);
+ const int fontStyleSize = sizeof(fontStyleTab) / sizeof(keyword_to_ident);
+ const int fontWeightSize = sizeof(fontWeightTab) / sizeof(keyword_to_ident);
+
+ RMDBGENTER(3, RMDebug::module_applications, "rviewQuery", "rviewQuery()");
+
+ queryDb = db;
+ updateDisplay = NULL;
+
+ CreateStatusLine(1);
+
+ mbar = NULL;
+ for (w=0; w<3; w++) mbarMenus[w] = NULL;
+
+ if (::wxDirExists((char*)(prefs->queryPath.ptr())))
+ hotPath = prefs->queryPath;
+ else
+ hotPath = ".";
+
+ // Read font from prefs
+ b = prefs->queryFont;
+ fontSize = 12; fontName = wxDEFAULT; fontStyle = wxNORMAL; fontWeight = wxNORMAL;
+ while (*b != 0)
+ {
+ while ((*b == ' ') || (*b == ',')) b++;
+ if (*b == 0) break;
+ d = buffer;
+ while ((*b != ' ') && (*b != ',') && (*b != 0)) {*d++ = *b++;}
+ *d++ = 0;
+ w = atoi(buffer);
+ if (w != 0) fontSize = w;
+ else
+ {
+ if ((w = rviewLookupKeyword(buffer, fontNameTab, fontNameSize, FALSE)) >= 0)
+ fontName = w;
+ else if ((w = rviewLookupKeyword(buffer, fontStyleTab, fontStyleSize, FALSE)) >= 0)
+ fontStyle = w;
+ else if ((w = rviewLookupKeyword(buffer, fontWeightTab, fontWeightSize, FALSE)) >= 0)
+ fontWeight = w;
+ else
+ cerr << "Bad identifier in font string: " << buffer << endl;
+ }
+ }
+ //cout << "size " << fontSize << ", name " << fontName << ", style " << fontStyle << ", weight " << fontWeight << endl;
+
+ font = new wxFont(fontSize, fontName, fontStyle, fontWeight);
+ //font = ::wxTheFontList->FindOrCreateFont(fontSize, fontName, fontStyle, fontWeight);
+ //cout << "Font " << font->GetPointSize() << ',' << font->GetFamily() << ',' << font->GetStyle() << endl;
+
+ GetClientSize(&w, &h);
+
+ // Set identifier
+ qwindowID = queryCounter++;
+ updateID = -1; // no update object
+
+ w -= 2*query_border; h -= query_bottom;
+ twin = new wxTextWindow((wxWindow*)this, query_border, query_border, w, h - 2*query_border, wxBORDER | wxNATIVE_IMPL);
+
+ twin->SetFont(font);
+
+ panel = new wxPanel((wxWindow*)this, query_border, h, w, query_bottom);
+ butClear = new rviewButton(panel);
+ butExec = new rviewButton(panel);
+ butUpdt = new rviewButton(panel);
+
+ if (query != NULL)
+ {
+ twin->WriteText(query);
+ }
+
+ buildMenubar();
+
+ newDBState(rmanClientApp::theApp()->ReadDBState());
+
+ label();
+
+ OnSize(w, h);
+
+ Show(TRUE);
+}
+
+
+rviewQuery::~rviewQuery(void)
+{
+ // If an update window is open notify it.
+ if (updateDisplay != NULL)
+ {
+ updateDisplay->noLongerUpdate();
+ }
+}
+
+
+const char *rviewQuery::getFrameName(void) const
+{
+ return "rviewQuery";
+}
+
+rviewFrameType rviewQuery::getFrameType(void) const
+{
+ return rviewFrameTypeQuery;
+}
+
+
+void rviewQuery::OnSize(int w, int h)
+{
+ int x, y;
+
+ GetClientSize(&x, &y);
+ if ((frameWidth == x) && (frameHeight == y)) return;
+ frameWidth = x; frameHeight = y;
+
+ x -= 2*query_border; y -= query_bottom;
+ twin->SetSize(query_border, query_border, x, y - 2*query_border);
+
+ panel->SetSize(query_border, y, x, query_bottom);
+
+ y = (query_bottom - query_bheight) / 2;
+
+ x = (x - 3*query_bwidth) / 3;
+ butClear->SetSize(x/2, y, query_bwidth, query_bheight);
+ butExec->SetSize((3*x)/2 + query_bwidth, y, query_bwidth, query_bheight);
+ butUpdt->SetSize((5*x)/2 + 2*query_bwidth, y, query_bwidth, query_bheight);
+
+ // doesn't work, unfortunately
+ /*if (mbar != NULL)
+ {
+ int hw, hh;
+
+ mbar->GetSize(&x, &y);
+ mbarMenus[3]->GetSize(&hw, &hh);
+ mbarMenus[3]->SetSize(x-hw, (y-hh)/2, hw, hh);
+ }*/
+}
+
+
+void rviewQuery::OnMenuCommand(int id)
+{
+ // Load query from hotlist?
+ if ((id >= MENU_QUERY_HOTLIST) && (id < MENU_QUERY_HOTLIST + hotNumber))
+ {
+ char buffer[STRINGSIZE];
+
+ sprintf(buffer, "%s"DIR_SEPARATOR"%s%s", hotPath.ptr(), mbar->GetLabel(id), query_extension);
+ loadQuery(buffer);
+ return;
+ }
+
+ switch (id)
+ {
+ case MENU_QUERY_FILE_OPEN:
+ case MENU_QUERY_FILE_SAVE:
+ {
+ char *name, *aux;
+ char *prefDir = (char*)(hotPath.ptr());
+ char filter[16];
+
+ sprintf(filter, "*%s", query_extension);
+ if (::wxDirExists(prefDir)) name = prefDir; else name = ".";
+ name = ::wxFileSelector(lman->lookup((id == MENU_QUERY_FILE_OPEN) ? "titleQueryLoad" : "titleQuerySave"), name, NULL, NULL, filter, 0 , this);
+ if (name != NULL)
+ {
+ aux = ::wxFileNameFromPath(name);
+ if (strlen(aux) > 0)
+ {
+ if (id == MENU_QUERY_FILE_OPEN)
+ {
+ RMDBGONCE(3, RMDebug::module_applications, "rviewQuery", "loadQuery()");
+ loadQuery(name);
+ }
+ else
+ {
+ RMDBGONCE(3, RMDebug::module_applications, "rviewQuery", "saveQuery()");
+ saveQuery(name);
+ }
+ hotPath = ::wxPathOnly(name);
+ prefs->queryPath = hotPath;
+ prefs->markModified();
+ buildMenubar();
+ }
+ }
+ }
+ break;
+ case MENU_QUERY_FILE_EXIT: this->Close(TRUE); break;
+ case MENU_QUERY_EDIT_CUT: twin->Cut(); break;
+ case MENU_QUERY_EDIT_COPY: twin->Copy(); break;
+ case MENU_QUERY_EDIT_PASTE: twin->Paste(); break;
+ default: break;
+ }
+}
+
+
+
+void rviewQuery::buildMenubar(void)
+{
+ char pattern[STRINGSIZE], leaf[STRINGSIZE];
+ char *f;
+ char *qhots[MENU_QUERY_HOTRANGE];
+ int i;
+ wxMenu *hotList;
+
+ // Do we actually need to rebuild the menu?
+ if ((mbar != NULL) && (strcmp(hotPath, lastHotPath) == 0)) return;
+
+ // build hotlist menu
+ hotList = new wxMenu;
+ sprintf(pattern, "%s"DIR_SEPARATOR"*%s", hotPath.ptr(), query_extension);
+
+ // Sort the hotlist alphabetically
+ f = ::wxFindFirstFile(pattern); hotNumber = 0;
+ while (f && (hotNumber < MENU_QUERY_HOTRANGE))
+ {
+ strcpy(leaf, ::wxFileNameFromPath(f));
+ f = strstr(leaf, query_extension);
+ if (f != NULL) *f = '\0';
+ if ((qhots[hotNumber] = new char[strlen(leaf) + 1]) == NULL) break;
+ strcpy(qhots[hotNumber], leaf);
+ hotNumber++;
+ f = wxFindNextFile();
+ }
+
+ rviewQuicksortStrings(qhots, 0, hotNumber-1);
+
+ for (i=0; i<hotNumber; i++)
+ {
+ //cout << "Item " << i << ": " << qhots[i] << endl;
+ hotList->Append(MENU_QUERY_HOTLIST + i, qhots[i]);
+ delete [] qhots[i];
+ }
+
+ if (mbar == NULL)
+ {
+ mbarMenus[0] = new wxMenu;
+ mbarMenus[0]->Append(MENU_QUERY_FILE_OPEN, "");
+ mbarMenus[0]->Append(MENU_QUERY_FILE_SAVE, "");
+ mbarMenus[0]->Append(MENU_QUERY_FILE_EXIT, "");
+
+ mbarMenus[1] = new wxMenu;
+ mbarMenus[1]->Append(MENU_QUERY_EDIT_CUT, "");
+ mbarMenus[1]->Append(MENU_QUERY_EDIT_COPY, "");
+ mbarMenus[1]->Append(MENU_QUERY_EDIT_PASTE, "");
+
+ mbarMenus[2] = hotList;
+
+
+ mbar = new wxMenuBar;
+ sprintf(pattern, "&%s", lman->lookup("menQueryFile"));
+ mbar->Append(mbarMenus[0], pattern);
+ sprintf(pattern, "&%s", lman->lookup("menQueryEdit"));
+ mbar->Append(mbarMenus[1], pattern);
+ sprintf(pattern, "&%s", lman->lookup("menQueryHotlist"));
+ mbar->Append(mbarMenus[2], pattern);
+
+ SetMenuBar(mbar);
+ }
+ else
+ {
+ mbar->Delete(mbarMenus[2], 2);
+ sprintf(pattern, "&%s", lman->lookup("menQueryHotlist"));
+ mbar->Append(hotList, pattern);
+ delete mbarMenus[2];
+ mbarMenus[2] = hotList;
+ }
+}
+
+
+
+void rviewQuery::label(void)
+{
+ updateTitle();
+
+ mbar->SetLabel(MENU_QUERY_FILE_OPEN, lman->lookup("menQueryFileOpen"));
+ mbar->SetLabel(MENU_QUERY_FILE_SAVE, lman->lookup("menQueryFileSave"));
+ mbar->SetLabel(MENU_QUERY_FILE_EXIT, lman->lookup("menQueryFileClose"));
+ mbar->SetHelpString(MENU_QUERY_FILE_OPEN, lman->lookup("helpQueryFileOpen"));
+ mbar->SetHelpString(MENU_QUERY_FILE_SAVE, lman->lookup("helpQueryFileSave"));
+ mbar->SetHelpString(MENU_QUERY_FILE_EXIT, lman->lookup("helpQueryFileClose"));
+
+ mbar->SetLabel(MENU_QUERY_EDIT_CUT, lman->lookup("menQueryEditCut"));
+ mbar->SetLabel(MENU_QUERY_EDIT_COPY, lman->lookup("menQueryEditCopy"));
+ mbar->SetLabel(MENU_QUERY_EDIT_PASTE, lman->lookup("menQueryEditPaste"));
+ mbar->SetHelpString(MENU_QUERY_EDIT_CUT, lman->lookup("helpQueryEditCut"));
+ mbar->SetHelpString(MENU_QUERY_EDIT_COPY, lman->lookup("helpQueryEditCopy"));
+ mbar->SetHelpString(MENU_QUERY_EDIT_PASTE, lman->lookup("helpQueryEditPaste"));
+
+ mbar->SetLabelTop(0, lman->lookup("menQueryFile"));
+ mbar->SetLabelTop(1, lman->lookup("menQueryEdit"));
+ mbar->SetLabelTop(2, lman->lookup("menQueryHotlist"));
+
+ butClear->SetLabel(lman->lookup("textClear"));
+ butExec->SetLabel(lman->lookup("textExec"));
+ butUpdt->SetLabel(lman->lookup("textUpdt"));
+}
+
+
+void rviewQuery::updateTitle(void)
+{
+ if (updateID == -1)
+ {
+ SetTitle(lman->lookup("titleQuery"));
+ }
+ else
+ {
+ char buffer[STRINGSIZE];
+ sprintf(buffer, "%s q%dd%d", lman->lookup("titleQuery"), qwindowID, updateID);
+ SetTitle(buffer);
+ }
+}
+
+
+int rviewQuery::process(wxObject &obj, wxEvent &evt)
+{
+ int type = evt.GetEventType();
+
+ if (type == wxEVENT_TYPE_BUTTON_COMMAND)
+ {
+ if (&obj == (wxObject*)butClear)
+ {
+ twin->Clear();
+ return 1;
+ }
+ if (&obj == (wxObject*)butExec)
+ {
+ int numl = twin->GetNumberOfLines();
+ int i, totalLength = 1;
+ char *b, *query;
+
+ query = twin->GetContents();
+
+ // Execute query.
+ i = rmanClientApp::theApp()->executeQuery(query, (updateDisplay == NULL) ? NULL : &updateMddObj);
+ // Did it fail?
+ if (i == 0)
+ {
+ int line, column;
+
+ // Was it a query error?
+ if (queryDb->getErrorInfo(line, column) != 0)
+ {
+ long offset = twin->XYToPosition(column-1, line-1);
+
+ // query was big enough to hold the entore query, so it's definitely
+ // big enough to hold one line
+ twin->GetLineText(line-1, query);
+ b = query + column-1;
+ while ((*b != ' ') && (!iscntrl(*b))) b++;
+ twin->SetSelection(offset, offset + (long)(b - (query + column-1)));
+ }
+ }
+ delete [] query;
+ // Notify that we did something, not whether it was a success
+ return 1;
+ }
+ if (&obj == (wxObject*)butUpdt)
+ {
+ rviewDisplay *newDisplay;
+
+ // Don't set updateDisplay directly. We might have a valid update image and
+ // issued a cancel from the file selection box.
+ if ((newDisplay = (rviewDisplay*)rmanClientApp::theApp()->OpenFile(rviewDisplay::display_flag_update, &updateMddObj, FALSE)) != NULL)
+ {
+ if (updateDisplay != NULL)
+ {
+ updateDisplay->noLongerUpdate();
+ }
+ updateDisplay = newDisplay;
+ updateDisplay->setQueryWindow(qwindowID);
+ updateID = updateDisplay->getIdentifier();
+ updateTitle();
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+int rviewQuery::getIdentifier(void) const
+{
+ return qwindowID;
+}
+
+int rviewQuery::getQueryCounter(void) const
+{
+ return queryCounter;
+}
+
+
+
+int rviewQuery::userEvent(const user_event &ue)
+{
+ if ((ue.type == usr_db_opened) || (ue.type == usr_db_closed))
+ {
+ newDBState((ue.type == usr_db_opened));
+ return 1;
+ }
+ if ((updateDisplay != NULL) && (ue.type == usr_update_closed))
+ {
+ r_Ref<r_GMarray> *whichMdd = (r_Ref<r_GMarray>*)(ue.data);
+ if (*whichMdd == updateMddObj)
+ {
+ updateDisplay = NULL; updateID = -1;
+ updateTitle();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+void rviewQuery::newDBState(bool newState)
+{
+ butExec->Enable(newState);
+}
+
+
+bool rviewQuery::loadQuery(char *file)
+{
+ size_t length;
+ int idlength;
+ char *buffer, *b;
+ FILE *fp;
+
+ if ((fp = fopen(file, "rb")) == NULL)
+ {
+ char msg[STRINGSIZE];
+ sprintf(msg, "%s %s", lman->lookup("errorFileOpen"), file);
+ rviewErrorbox::reportError(msg, rviewQuery::getFrameName(), "loadQuery");
+ return FALSE;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ length = ftell(fp);
+ if ((buffer = new char[length+1]) == NULL)
+ {
+ rviewErrorbox::reportError(lman->lookup("errorMemory"), rviewQuery::getFrameName(), "loadQuery");
+ fclose(fp); return FALSE;
+ }
+ fseek(fp, 0, SEEK_SET);
+
+ b = buffer;
+ for (idlength=0; idlength<(int)length; idlength++)
+ {
+ int c;
+
+ if ((c = fgetc(fp)) == EOF) break;
+#ifdef __VISUALC__
+ if (c != '\r')
+#endif
+ *b++ = c;
+ }
+ *b++ = '\0';
+
+ if (idlength < (int)length)
+ {
+ char msg[STRINGSIZE];
+ sprintf(msg, "%s %s", lman->lookup("errorFileRead"), file);
+ rviewErrorbox::reportError(msg, rviewQuery::getFrameName(), "loadQuery");
+ fclose(fp);
+ return FALSE;
+ }
+
+ fclose(fp);
+
+ idlength = strlen("RasDaView-Query");
+ if (strncmp(buffer, "RasDaView-Query", idlength) != 0)
+ {
+ idlength = strlen(query_firstline);
+ if (strncmp(buffer,query_firstline, idlength) != 0) idlength = -1;
+ }
+ if (idlength < 0)
+ {
+ rviewErrorbox::reportError(lman->lookup("errorQueryFile"), rviewQuery::getFrameName(), "loadQuery");
+ delete [] buffer;
+ return FALSE;
+ }
+ twin->Clear();
+ twin->WriteText(buffer + idlength + 1);
+ delete [] buffer;
+ return TRUE;
+}
+
+
+bool rviewQuery::saveQuery(char *file)
+{
+ FILE *fp;
+ char *buffer, *b, *upper;
+
+ if ((fp = fopen(file, "wb")) == NULL)
+ {
+ char msg[STRINGSIZE];
+ sprintf(msg, "%s %s", lman->lookup("errorFileOpen"), file);
+ rviewErrorbox::reportError(msg, rviewQuery::getFrameName(), "saveQuery");
+ return FALSE;
+ }
+
+ fprintf(fp, query_firstline); fputc('\n', fp);
+ buffer = twin->GetContents();
+ b = buffer; upper = buffer + strlen(buffer);
+
+ while (b < upper)
+ {
+#ifdef __VISUALC__
+ if (*b != '\r')
+#endif
+ if (fputc(*b, fp) != *b) break;
+ b++;
+ }
+ if (b != upper)
+ {
+ char msg[STRINGSIZE];
+ sprintf(msg, "%s %s", lman->lookup("errorFileWrite"), file);
+ rviewErrorbox::reportError(msg, rviewQuery::getFrameName(), "saveQuery");
+ fclose(fp);
+ return FALSE;
+ }
+
+ fclose(fp);
+
+ delete [] buffer;
+
+ return TRUE;
+}