campo-sirio/ba/ba8200.cpp
guy 763796dce1 Patch level : 2.1 nopatch
Files correlati     : ba8.exe
Ricompilazione Demo : [ ]
Commento            :

Corretta generazione clausola WHERE


git-svn-id: svn://10.65.10.50/trunk@11953 c028cbd2-c16b-5b4b-a496-9718f37d4682
2004-04-09 09:46:46 +00:00

1211 lines
28 KiB
C++
Executable File

#include <xi.h>
#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <extcdecl.h>
#include <prefix.h>
#include <progind.h>
#include <relation.h>
#include <sheet.h>
#include <tree.h>
#include <utility.h>
#include <xml.h>
#include "../sqlite/sqlite.h"
#include "ba8200.h"
#include "ba8201.h"
///////////////////////////////////////////////////////////
// TRelation_node & TRelation_tree
///////////////////////////////////////////////////////////
// Informazioni relative ad un nodo della relazione:
class TRelation_node : public TObject
{
const TRelation_node* _father; // Puntatore all'eventuale padre
int _logicnum; // Numero logico
TString16 _name, _alias; // Nome ed Alias
TString_array _join_fields; // Elenco dei campi di join
public:
bool description(TString& str) const;
int num() const { return _logicnum; }
const TString& name() const { return _name; }
const TString& alias() const { return _alias; }
const TString& id() const { return _alias.not_empty() ? _alias : _name; }
const TRelation_node* father() const { return _father; }
void set_num(int num);
void set_alias(const char* alias) { _alias = alias; }
TString_array& join() { return _join_fields; }
TRelation_node(const TRelation_node* father, int ln, const char* alias);
virtual ~TRelation_node() {}
};
bool TRelation_node::description(TString& str) const
{
const bool ok = _logicnum >= LF_USER;
if (ok)
{
const FileDes& fd = prefix().get_filedes(_logicnum);
str = _name;
if (_alias.not_empty())
str << " ALIAS " << _alias;
str << " (" << fd.Des << ')';
}
return ok;
}
void TRelation_node::set_num(int num)
{
_logicnum = num;
const FileDes& fd = prefix().get_filedes(_logicnum);
const TFilename name = fd.SysName;
_name = name.name(); _name.upper();
}
TRelation_node::TRelation_node(const TRelation_node* father, int ln, const char* alias)
: _father(father)
{
set_num(ln);
set_alias(alias);
}
// Albero di una relazione
class TRelation_tree : public TObject_tree
{
protected:
virtual bool get_description(TString& str) const;
public:
bool find_id(const TString& id);
};
bool TRelation_tree::get_description(TString& str) const
{
const TRelation_node* rn = (const TRelation_node*)curr_node();
if (rn != NULL)
return rn->description(str);
return false;
}
static bool find_id_callback(TTree& tree, void* jolly, word flags)
{
const TRelation_node* n = (const TRelation_node*)tree.curr_node();
if (n != NULL)
{
const TString& id = *(const TString*)jolly;
return n->id() == id;
}
return false;
}
bool TRelation_tree::find_id(const TString& id)
{
bool ok = goto_root();
if (ok)
{
scan_depth_first(find_id_callback, (void*)&id);
const TRelation_node* n = (const TRelation_node*)curr_node();
ok = n != NULL && n->id() == id;
}
return ok;
}
///////////////////////////////////////////////////////////
// TTable_mask
///////////////////////////////////////////////////////////
// Maschera per inserire/editare un nodo dell'albero
class TTable_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
protected:
int name2num(const TString& name) const;
int father_logicnum() const;
const char* find_linked_field(int logicnum, const RecFieldDes& fd) const;
public:
int son_logicnum() const;
void mask2node(TRelation_node& node);
TTable_mask();
~TTable_mask();
};
// Converte un nome di tabella nel suo numero loigico
int TTable_mask::name2num(const TString& name) const
{
int num = 0;
if (name.not_empty())
{
TList_sheet& sht = *efield(F_SON).sheet();
TString_array& arr = sht.rows_array();
FOR_EACH_ARRAY_ROW(arr, i, row)
{
if (name == row->get(0))
{
num = row->get_int(1);
break;
}
}
}
return num;
}
int TTable_mask::father_logicnum() const
{
return name2num(get(F_FATHER));
}
int TTable_mask::son_logicnum() const
{
return name2num(get(F_SON));
}
// Dato il numero logico di una tabella ed un campo (di un'altra tabella)
// cerca il campo piu' simile all'interno del tracciato record
const char* TTable_mask::find_linked_field(int logicnum, const RecFieldDes& fd) const
{
const RecDes& rd = prefix().get_recdes(logicnum);
int nBest = -1;
double dBest = 0.0;
for (int i = 0; i < rd.NFields; i++)
{
const RecFieldDes& field = rd.Fd[i];
if (field.TypeF == fd.TypeF && field.Len == fd.Len)
{
const double fuzzy = xvt_str_fuzzy_compare(field.Name, fd.Name);
if (fuzzy > dBest)
{
nBest = i;
dBest = fuzzy;
if (dBest == 1.0)
break;
}
}
}
return nBest >= 0 ? rd.Fd[nBest].Name : "";
}
bool TTable_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_SON:
if (e == fe_modify)
{
const int logicnum = son_logicnum();
const int fathernum = father_logicnum();
TSheet_field& sheet = sfield(F_SHEET);
sheet.destroy();
if (logicnum >= LF_USER && fathernum >= LF_USER)
{
const RecDes& rd = prefix().get_recdes(logicnum);
const KeyDes& kd = rd.Ky[0];
TToken_string tok;
for (int j = 0; j < kd.NkFields; j++)
{
const int n = kd.FieldSeq[j] % MaxFields;
tok = rd.Fd[n].Name;
tok.add(find_linked_field(fathernum, rd.Fd[n]));
sheet.rows_array().add(tok);
}
}
sheet.force_update();
}
break;
case F_SHEET:
if (e == se_query_add || e == se_query_del)
return false;
break;
default:
break;
}
return true;
}
// Trasferisce le informazioni dalla maschera ad un nodo della tabella
void TTable_mask::mask2node(TRelation_node& son)
{
son.set_num(son_logicnum());
son.set_alias(get(F_SON_ALIAS));
if (son.father() != NULL)
{
TString_array& join = son.join();
join.destroy();
TSheet_field& sheet = sfield(F_SHEET);
FOR_EACH_SHEET_ROW(sheet, i, row)
{
TToken_string* newrow = new TToken_string(50, '=');
newrow->add(row->get(0));
newrow->add(row->get());
join.add(newrow);
}
}
}
TTable_mask::TTable_mask() : TAutomask("ba8200b")
{
FileDes dir;
CGetFile(LF_DIR, &dir, _nolock, NORDIR);
const int nfiles = (int)dir.EOD;
TList_sheet& sht = *efield(F_SON).sheet();
TToken_string tt(80);
TFilename n;
for (int logic = LF_USER; logic < nfiles; logic++)
{
const FileDes& fd = prefix().get_filedes(logic);
n = fd.SysName; n = n.name(); n.upper();
tt = n;
tt.add(logic);
tt.add(fd.Des);
sht.rows_array().add(tt);
}
sht.rows_array().sort();
}
TTable_mask::~TTable_mask()
{ }
///////////////////////////////////////////////////////////
// TQuery_mask
///////////////////////////////////////////////////////////
// Maschera principale della costruzione della query
class TQuery_mask : public TAutomask
{
TRelation_tree _tree; // Albero della relazione
int _curr_num; // Numero del file corrente
bool _dragster; // Operazione di trascinamento in corso
TFilename _curr_query;// Nome completo della query in editazione
bool _is_dirty; // Maschera cambiata dall'ultimo caricamento
protected:
virtual void handler(WINDOW win, EVENT* ep);
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
protected:
bool add_file_to_tree();
void add_field_to_sheet(bool update = true);
void add_asterisk_to_sheet();
bool edit_file_in_tree();
static int sort_fields(const TObject** r1, const TObject** r2);
void fill_fields();
void enable_sql_button();
void enable_field_buttons();
void move_curr_field(int dir);
void tree2sql(TString& from, TString& where);
void sheet2sql();
void edit_query();
bool select_query();
bool load_tables_tree(TXmlItem& tables);
bool load_fields_sheet(TXmlItem& fields);
void global_reset();
bool save_tables_tree(TXmlItem& xml);
bool save_fields_sheet(TXmlItem& xml);
void save_as(TRecordsetExportFormat fmt);
public:
bool load_query();
bool save_query();
bool save_if_needed();
bool delete_query();
bool get_qry_path(TFilename& path) const;
TRelation_node* curr_node();
TQuery_mask();
};
// Nodo corrente dell'albero
TRelation_node* TQuery_mask::curr_node()
{
TTree_field& tf = tfield(F_TABLES);
tf.goto_selected();
TRelation_node* n = (TRelation_node*)_tree.curr_node();
return n;
}
// Aggiunge interattivamente un nodo all'albero
bool TQuery_mask::add_file_to_tree()
{
TTable_mask msk;
const TRelation_node* father = curr_node();
if (father != NULL)
{
msk.set(F_FATHER, father->name());
msk.set(F_FATHER_ALIAS, father->alias());
}
msk.disable(DLG_DELREC);
bool ok = msk.run() == K_ENTER;
if (ok)
{
TRelation_node* son = new TRelation_node(father, msk.son_logicnum(), msk.get(F_SON_ALIAS));
msk.mask2node(*son);
_tree.add_son(son);
_tree.expand_all();
tfield(F_TABLES).win().force_update();
_curr_num = son->num();
fill_fields();
}
return ok;
}
// Modifica interattivamente il nodo corrente dell'albero
bool TQuery_mask::edit_file_in_tree()
{
TRelation_node* son = curr_node();
if (son == NULL)
return false;
const TRelation_node* father = NULL;
if (_tree.goto_father())
father = (const TRelation_node*)_tree.curr_node();
TTable_mask msk;
if (father != NULL)
{
msk.set(F_FATHER, father->name());
msk.set(F_FATHER_ALIAS, father->alias());
TString_array& arr = son->join();
FOR_EACH_ARRAY_ROW(arr, i, row)
{
TToken_string& newrow = msk.sfield(F_SHEET).row(-1);
FOR_EACH_TOKEN((*row), tok)
{
TToken_string str(tok, '.');
str.strip_spaces();
if (str.items() > 1)
newrow.add(str.get(1));
else
newrow.add(str);
}
}
}
msk.set(F_SON, son->name());
msk.set(F_SON_ALIAS, son->alias());
bool update = true;
switch (msk.run())
{
case K_ENTER:
msk.mask2node(*son);
break;
case K_DEL:
if (curr_node() != NULL)
{
_tree.kill_node();
_tree.goto_root();
}
break;
default:
update = false;
break;
}
if (update)
{
TTree_field& tf = tfield(F_TABLES);
tf.win().force_update();
_curr_num = 0;
if (tf.select_current())
{
const TRelation_node* curr = curr_node();
if (curr != NULL)
_curr_num = curr->num();
}
fill_fields();
}
return update; // ????
}
// Ordina per importanza i campi di un tracciato record
int TQuery_mask::sort_fields(const TObject** r1, const TObject** r2)
{
TToken_string& s1 = (TToken_string&)**r1;
TToken_string& s2 = (TToken_string&)**r2;
const int w1 = s1.get_int(4);
const int w2 = s2.get_int(4);
int cmp = w2-w1;
if (cmp == 0)
cmp = strcmp(s1.get(0), s2.get(0));
return cmp;
}
// Riempie la lista dei campi del file corrente
void TQuery_mask::fill_fields()
{
TSheet_field& sht = sfield(F_FIELDS);
sht.destroy();
if (_curr_num >= LF_USER)
{
TRelation rel(_curr_num);
TRelation_description reldes(rel);
const RecDes& rd = prefix().get_recdes(_curr_num);
for (int i = 0; i < rd.NFields; i++)
{
TToken_string& row = sht.row(-1);
const RecFieldDes& fd = rd.Fd[i];
row = fd.Name;
row.add(fd.Len);
int weight = 0;
for (int k = 0; k < rd.NKeys; k++)
{
const KeyDes& kd = rd.Ky[k];
for (int j = 0; j < kd.NkFields; j++)
{
const int n = kd.FieldSeq[j] % MaxFields;
if (n == i)
{
if (weight == 0)
{
weight = (rd.NKeys-k)*100 + kd.NkFields-j;
row.add(k+1);
}
else
row << ' ' << (k+1);
}
}
}
row.add(reldes.get_field_description(fd.Name), 3);
row.add(weight, 4);
}
sht.rows_array().TArray::sort(sort_fields);
}
sht.force_update();
enable_field_buttons();
}
// Aggiunge il campo selezionato nello spredasheet F_FIELDS allo spreadsheet F_SHEET
void TQuery_mask::add_field_to_sheet(bool update)
{
const TRelation_node* n = curr_node();
if (n != NULL)
{
TSheet_field& sf = sfield(F_FIELDS);
const int r = sf.selected();
if (r >= 0)
{
TToken_string& rowsel = sf.row(r);
TSheet_field& ff = sfield(F_SHEET);
TToken_string& row = ff.row(-1);
row = n->id();
row.add(rowsel.get(0));
_is_dirty = true;
if (update)
{
ff.force_update();
enable_sql_button();
}
}
}
}
// Aggiunge tutte le colonne allo sheet
void TQuery_mask::add_asterisk_to_sheet()
{
const TRelation_node* n = curr_node();
if (n != NULL)
{
TSheet_field& sf = sfield(F_FIELDS);
const int nLast = sf.items()-1;
for (int i = 0; i <= nLast; i++)
{
sf.select(i);
add_field_to_sheet(i == nLast);
}
sf.select(0);
}
}
// Decide se attivare o meno il bottone SQL
void TQuery_mask::enable_sql_button()
{
const TSheet_field& s = sfield(F_SHEET);
enable(F_GENSQL, s.items() > 0);
}
// Decide se attivare o meno i bottoni di aggiunta campi
void TQuery_mask::enable_field_buttons()
{
const TSheet_field& sf = sfield(F_FIELDS);
const bool ok = sf.items() > 0;
enable(-1, ok);
}
void TQuery_mask::move_curr_field(int dir)
{
TSheet_field& s = sfield(F_SHEET);
const int sel = s.selected();
if (sel >= 0 && sel < s.items())
{
const int des = sel+dir;
if (des >= 0 && des < s.items())
{
s.rows_array().swap(sel, des);
s.select(des);
s.force_update();
}
}
}
static bool sql_tree_handler(TTree& tree, void* jolly, word flags)
{
TRelation_node* rn = (TRelation_node*)tree.curr_node();
TPointer_array& arr = *(TPointer_array*)jolly;
TToken_string& from = *(TToken_string*)arr.objptr(0);
TString& where = *(TString*)arr.objptr(1);
TString_array& join = rn->join();
TString str;
if (from.get_pos(rn->id()) < 0)
{
from.add(rn->id());
FOR_EACH_ARRAY_ROW(join, i, row)
{
if (where.find(*row) < 0)
{
if (where.not_empty())
where << "AND";
where << '(' << rn->id() << '.' << row->get(0) << '=';
str = row->get();
if (isalpha(str[0]))
where << rn->father()->id() << '.';
where << str << ')';
}
}
}
return false; // Don't stop search
}
// Riempie una stringa SQL con la relazione tra le tabelle
void TQuery_mask::tree2sql(TString& from, TString& where)
{
if (_tree.goto_root())
{
TPointer_array a;
a.add(&from);
a.add(&where);
_tree.scan_depth_first(sql_tree_handler, &a);
}
}
inline bool tok_get_bool(TToken_string& tok, int pos)
{
const char* str = tok.get(pos);
return str && *str > ' ';
}
// Genera una query SQL a partire dallo spreadsheet F_SHEET
void TQuery_mask::sheet2sql()
{
const TSheet_field& sheet = sfield(F_SHEET);
TToken_string select(50, ',');
_tree.goto_root();
const bool multiple = _tree.has_son();
TToken_string from(50, ','), groupby(50, ','), orderby(50, ',');
TString where;
TString field;
FOR_EACH_SHEET_ROW(sheet, i, row)
{
field = row->get(1);
if (!field.blank() && !tok_get_bool(*row, 2)) // Campo valido e visibile
{
if (multiple)
{
field.insert(".");
field.insert(row->get(0)); // Table name
}
select.add(field); // Column name only
if (tok_get_bool(*row, 3)) // Sort
orderby.add(field);
if (tok_get_bool(*row, 4)) // Group
groupby.add(field);
}
}
tree2sql(from, where);
TString sql;
sql << "SELECT " << select << '\n';
sql << "FROM " << from << '\n';
sql << "WHERE " << where << '\n';
if (groupby.not_empty())
sql << "GROUP BY " << groupby << '\n';
if (orderby.not_empty())
sql << "ORDER BY " << orderby << '\n';
sql << ";";
set(F_SQL, sql, true);
}
static int select_callback(void* jolly, int argc, char** value, char** field)
{
TArray_sheet* sht = (TArray_sheet*)jolly;
TToken_string row;
for (int i = 0; i < argc; i++)
row.add(value[i], i);
sht->add(row);
return SQLITE_OK;
}
void TQuery_mask::edit_query()
{
TSQL_recordset qry(get(F_SQL));
if (qry.columns() > 0)
{
TRecordset_sheet sht(qry);
sht.run();
}
else
warning_box(TR("Nessuna riga risultato"));
}
void TQuery_mask::save_as(TRecordsetExportFormat fmt)
{
xvt_fsys_save_dir();
TFilename path; path.tempdir();
const char* ext = "txt";
switch (fmt)
{
case fmt_html: ext = "html"; break;
case fmt_silk: ext = "xls"; break;
default: break;
}
FILE_SPEC fs;
xvt_fsys_convert_str_to_dir(path, &fs.dir);
strcpy(fs.type, ext);
strcpy(fs.name, get(F_CODICE));
strcpy(fs.creator, "AGA");
const bool good = xvt_dm_post_file_save(&fs, TR("Esportazione")) == FL_OK;
xvt_fsys_restore_dir();
if (good)
{
xvt_fsys_convert_dir_to_str(&fs.dir, path.get_buffer(), path.size());
path.add(fs.name);
TSQL_recordset qry(get(F_SQL));
bool ok = qry.items() > 0;
if (ok)
{
ok = qry.save_as(path, fmt);
if (ok)
xvt_sys_goto_url(path, "open");
}
}
}
bool TQuery_mask::get_qry_path(TFilename& path) const
{
const TString& name = get(F_CODICE);
const bool ok = name.not_empty();
if (ok)
{
path = firm2dir(-1);
path.add("custom");
if (!path.exist())
xvt_fsys_mkdir(path);
path.add(name);
path.ext("qry");
}
return ok;
}
bool TQuery_mask::select_query()
{
TFilename path;
const bool ok = select_custom_file(path, "qry");
if (ok)
{
path = path.name(); path.ext("");
set(F_CODICE, path);
}
return ok;
}
static bool xml_save_tree_handler(TTree& tree, void* jolly, word flags)
{
TXmlItem* rel = (TXmlItem*)jolly;
TRelation_node& node = (TRelation_node&)*tree.curr_node();
TXmlItem& son = rel->AddChild("table");
TString4 num; num << node.num();
son.SetAttr("Num", num);
son.SetAttr("Name", node.name());
if (node.alias().not_empty())
son.SetAttr("Alias", node.alias());
if (node.father() != NULL)
{
son.SetAttr("Father", node.father()->id());
FOR_EACH_ARRAY_ROW(node.join(), i, row)
{
if (i > 0)
son << "AND";
son << "(" << *row << ")";
}
}
return false;
}
bool TQuery_mask::save_tables_tree(TXmlItem& xml)
{
const bool ok = _tree.goto_root();
if (ok)
{
TXmlItem& rel = xml.AddChild("tables");
_tree.scan_depth_first(xml_save_tree_handler, &rel);
}
return ok;
}
bool TQuery_mask::save_fields_sheet(TXmlItem& xml)
{
TSheet_field& sf = sfield(F_SHEET);
const bool ok = sf.items() > 0;
if (ok)
{
TXmlItem& fields = xml.AddChild("fields");
FOR_EACH_SHEET_ROW(sf, i, row)
{
TXmlItem& field = fields.AddChild("field");
field.SetAttr("Table", row->get(0));
field.SetAttr("Name", row->get(1));
field.SetAttr("Hidden", tok_get_bool(*row,2));
field.SetAttr("Sort", tok_get_bool(*row,3));
field.SetAttr("Group", tok_get_bool(*row,4));
const char* str = row->get(5);
if (str && *str > ' ')
field.SetAttr("Expr", str);
}
}
return ok;
}
bool TQuery_mask::save_query()
{
bool ok = _curr_query.not_empty();
if (!ok)
ok = get_qry_path(_curr_query);
if (!ok)
return field(F_CODICE).on_key(K_ENTER); // Segnala errore
char name[_MAX_FNAME];
xvt_fsys_parse_pathname (_curr_query, NULL, NULL, name, NULL, NULL);
ok = *name > ' ';
if (ok)
{
TXmlItem xml;
xml.SetTag("query");
xml.SetAttr("Name", name);
xml.AddChild("description") << get(F_DESCR);
save_tables_tree(xml);
save_fields_sheet(xml);
xml.AddChild("sql") << get(F_SQL);
xml.Save(_curr_query);
_is_dirty = false;
}
return ok;
}
bool TQuery_mask::save_if_needed()
{
if (!_is_dirty)
return true;
if (!yesno_box(TR("Si desidera registrare la query?")))
return false;
return save_query();
}
///////////////////////////////////////////////////////////
// Caricamento da file xml
///////////////////////////////////////////////////////////
// Carica l'albero della relazione
bool TQuery_mask::load_tables_tree(TXmlItem& tables)
{
for (int i = 0; i < tables.GetChildren(); i++)
{
const TXmlItem& table = *tables.GetChild(i);
const int num = atoi(table.GetAttr("Num"));
if (num >= LF_USER)
{
_tree.find_id(table.GetAttr("Father"));
const TRelation_node* father = (const TRelation_node*)_tree.curr_node();
TRelation_node* son = new TRelation_node(father, num, table.GetAttr("Alias"));
if (father != NULL)
{
TString expr; table.GetEnclosedText(expr);
int i = expr.find('(');
while (i >= 0)
{
const int j = expr.find(')', i+1);
TToken_string* eq = new TToken_string(expr.sub(i+1, j), '=');
son->join().add(eq);
i = expr.find('(', j+1);
}
}
_tree.add_son(son);
}
}
const bool ok = _tree.goto_root();
if (ok)
{
const TRelation_node* rn = (TRelation_node*)_tree.curr_node();
_curr_num = rn->num();
fill_fields();
_tree.expand_all();
tfield(F_TABLES).win().force_update();
}
enable_field_buttons();
return ok;
}
// Carica l'elenco dei campi (o colonne)
bool TQuery_mask::load_fields_sheet(TXmlItem& xml)
{
TSheet_field& sheet = sfield(F_SHEET);
TXmlItem* fields = xml.FindFirst("fields");
const bool ok = fields != NULL;
if (ok)
{
for (int i = 0; i < fields->GetChildren(); i++)
{
const TXmlItem& field = *fields->GetChild(i);
TToken_string& row = sheet.row(-1);
row.add(field.GetAttr("Table"),0);
row.add(field.GetAttr("Name"),1);
row.add(field.GetBoolAttr("Hidden") ? "X" : "",2);
row.add(field.GetBoolAttr("Sort") ? "X" : "",3);
row.add(field.GetBoolAttr("Group") ? "X" : "",4);
row.add(field.GetAttr("Expr"),5);
}
sheet.force_update();
}
enable_sql_button();
return ok;
}
// Azzera tutto, ma proprio tutto
void TQuery_mask::global_reset()
{
if (_tree.goto_root())
{
_tree.kill_node();
TTree_field& tf = tfield(F_TABLES);
tf.select_current();
tf.win().force_update();
}
reset();
}
// Caica l'intera query
bool TQuery_mask::load_query()
{
TFilename path; get_qry_path(path);
bool ok = path.exist();
if (ok)
{
TXmlItem xml;
ok = xml.Load(path);
if (ok)
{
_curr_query = path;
global_reset();
path = path.name(); path.ext("");
set(F_CODICE, path);
const TXmlItem* desc = xml.FindFirst("description");
if (desc != NULL)
{
TString str; desc->GetEnclosedText(str);
set(F_DESCR, str);
}
TXmlItem* tables = xml.FindFirst("tables");
if (tables != NULL)
load_tables_tree(*tables);
load_fields_sheet(xml);
const TXmlItem* sql = xml.FindFirst("sql");
if (sql != NULL)
{
TString str; sql->GetEnclosedText(str);
set(F_SQL, str, true); // Aggiorna anche stato bottoni di esportazione
field(F_SQL).set_dirty(false); // Evita falsi allarmi di registrazione
}
_is_dirty = false; // Resetta definitivamente il dirty
}
}
return ok;
}
bool TQuery_mask::delete_query()
{
TFilename path; get_qry_path(path);
const bool ok = yesno_box(FR("Si desidera eliminare il file %s"), (const char*)path);
if (ok)
{
::remove(path);
global_reset();
}
return ok;
}
// Gestione eventi standard
bool TQuery_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_CODICE:
if (e == fe_button)
{
if (select_query())
e = fe_modify;
}
if (e == fe_modify)
{
save_if_needed();
load_query();
}
break;
case F_TABLES:
if (e == fe_modify)
{
const TRelation_node* rn = (TRelation_node*)_tree.curr_node();
if (rn && rn->num() != _curr_num)
{
_curr_num = rn->num();
fill_fields();
}
}
break;
case F_FIELDS:
if (e == se_query_modify || e == se_query_add || e == se_query_del)
return false;
enable_field_buttons();
break;
case F_ADDFILE:
if (e == fe_button)
add_file_to_tree();
break;
case F_EDITFILE:
if (e == fe_button)
edit_file_in_tree();
break;
case DLG_USER:
if (e == fe_button)
add_field_to_sheet();
break;
case F_ASTERISK:
if (e == fe_button)
add_asterisk_to_sheet();
break;
case F_GENSQL:
if (e == fe_button)
{
sheet2sql();
next_page(1001);
}
break;
case F_EDITQUERY:
if (e == fe_button)
edit_query();
break;
case F_SQL:
if (e == fe_init || e == fe_modify)
{
enable(-2, !o.empty());
_is_dirty = e == fe_modify;
}
break;
case F_EXPORT_HTML:
if (e == fe_button)
save_as(fmt_html);
break;
case F_EXPORT_EXCEL:
if (e == fe_button)
save_as(fmt_silk);
break;
case F_EXPORT_TXT:
if (e == fe_button)
save_as(fmt_text);
break;
case F_EXPORT_CAMPO:
if (e == fe_button)
save_as(fmt_campo);
break;
case F_SHEET:
enable_sql_button();
break;
case F_MOVEUP:
if (e == fe_button)
move_curr_field(-1);
break;
case F_MOVEDN:
if (e == fe_button)
move_curr_field(+1);
break;
case DLG_NEWREC:
if (e == fe_button)
{
save_if_needed();
global_reset();
}
break;
case DLG_FINDREC:
if (e == fe_button)
send_key(K_F9, F_CODICE);
case DLG_SAVEREC:
if (e == fe_button)
{
get_qry_path(_curr_query);
save_query();
}
break;
case DLG_DELREC:
if (e == fe_button && jolly == 0) // Elimina della Toolbar
{
delete_query();
return false; // Do not exit!
}
break;
case DLG_QUIT:
save_if_needed();
break;
default:
break;
}
return true;
}
// Gestione eventi di trascinamento
void TQuery_mask::handler(WINDOW wnd, EVENT* ep)
{
switch (ep->type)
{
case E_MOUSE_DOWN:
if (ep->v.mouse.button == 0 && wnd == win(0))
{
const TSheet_field& sf = sfield(F_FIELDS);
RCT rct; sf.get_rect(rct);
_dragster = xvt_rect_has_point(&rct, ep->v.mouse.where) != 0;
}
else
_dragster = false;
if (_dragster)
{
XinCursor hand = xi_get_pref(XI_PREF_HAND_CURSOR_RID);
xvt_win_set_cursor(wnd, (CURSOR)hand);
}
else
xvt_win_set_cursor(wnd, CURSOR_ARROW);
break;
case E_MOUSE_UP:
if (ep->v.mouse.button == 0 && _dragster)
{
TSheet_field& ff = sfield(F_SHEET);
RCT rct; ff.get_rect(rct);
if (xvt_rect_has_point(&rct, ep->v.mouse.where))
add_field_to_sheet();
xvt_win_set_cursor(wnd, CURSOR_ARROW);
}
_dragster = false;
break;
default:
break;
}
TAutomask::handler(wnd, ep);
}
TQuery_mask::TQuery_mask() : TAutomask("ba8200a"), _curr_num(0), _is_dirty(false)
{
RCT rcts, rctf, rctt;
TSheet_field& sheet = sfield(F_SHEET);
sheet.get_rect(rcts);
// Allarga a dritta lo spreadsheet coi noi dei campi
TSheet_field& fields = sfield(F_FIELDS);
fields.get_rect(rctf);
rctf.right = rcts.right;
fields.set_rect(rctf);
// Allarga a mancina l'albero della relazione
TTree_field& trf = tfield(F_TABLES);
trf.get_rect(rctt);
rctt.top -= 4;
rctt.left = rcts.left+4;
rctt.right -= 32; // Toglie scrollbar
rctt.bottom = rctf.bottom - 32;
trf.set_rect(rctt);
trf.set_tree(&_tree); // Associa l'albero al campo della maschera
}
///////////////////////////////////////////////////////////
// TSQL_recordset_app
///////////////////////////////////////////////////////////
class TSQL_recordset_app : public TSkeleton_application
{
public:
virtual void main_loop();
};
void TSQL_recordset_app::main_loop()
{
TQuery_mask* msk = new TQuery_mask;
msk->run();
delete msk;
}
int ba8200(int argc, char* argv[])
{
TSQL_recordset_app app;
app.run(argc, argv, TR("Query Generator"));
return 0;
}