diff --git a/include/msksheet.cpp b/include/msksheet.cpp index f8f6befad..1c90b32a2 100755 --- a/include/msksheet.cpp +++ b/include/msksheet.cpp @@ -11,7 +11,7 @@ extern "C" #include #include #include - +#include /////////////////////////////////////////////////////////// // TSpreadsheet /////////////////////////////////////////////////////////// @@ -30,6 +30,9 @@ class TSpreadsheet : public TControl friend class TSheet_field; // @access:(INTERNAL) Private Member + // @cmember:(INTERNAL) costanti + enum {NUMBER_WIDTH=3}; + enum {MAX_COL=48}; // @cmember:(INTERNAL) Array di TToken_strings contenenti le righe TString_array _str; @@ -78,7 +81,7 @@ class TSpreadsheet : public TControl // @cmember:(INTERNAL) Numero della riga a cui saltare appena possibile int _selection_posted; // @cmember:(INTERNAL) Dimensioni delle colonne - int _default_width[32]; // 32 = MAX_COLS + int _default_width[MAX_COL]; // @cmember:(INTERNAL) Bisogna salvare l'ordien delle colonne bool _save_columns_order; @@ -294,8 +297,6 @@ TSpreadsheet::TSpreadsheet( _row_dirty(FALSE), _cell_dirty(FALSE), _check_enabled(TRUE), _needs_update(-1), _selection_posted(-1), _save_columns_order(FALSE) { - const int NUMBER_WIDTH = 3; - const int MAX_COL = 32; int m_width[MAX_COL], v_width[MAX_COL]; int fixed_columns = 1; // Number of fixed columns @@ -1268,17 +1269,19 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev) _check_enabled = TRUE; // Re-enable checks } break; - case K_CTRL + '-': + case K_CTRL + '-': // ********* delete line { - if (owner().mask().id2pos(DLG_DELREC) && notify(_cur_rec, K_DEL)) - { + //if (owner().mask().id2pos(DLG_DELREC)>=0 && notify(_cur_rec, K_DEL)) + if (sheet_mask().id2pos(DLG_DELREC)>=0 && sheet_mask().field(DLG_DELREC).enabled() && notify(_cur_rec, K_DEL)) + { int rec = _cur_rec; _row_dirty = FALSE; destroy(rec); if (rec < items()) str2mask(rec); notify(rec, K_CTRL+K_DEL); // Notifica l'avvenuta cancellazione - if (rec >= items()) + set_dirty(); + if (rec >= items()) rec = items() - 1; if (rec >= 0) select(rec, FALSE); @@ -1286,7 +1289,7 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev) refused = TRUE; } break; - case K_CTRL+'+': + case K_CTRL + '+': // ********* insert line if (test_focus_change()) { insert(-1, TRUE, TRUE); @@ -2023,6 +2026,7 @@ KEY TSpreadsheet::edit(int n) if (n < items()) str2mask(n); notify(n, K_CTRL+K_DEL); // Notifica l'avvenuta cancellazione + set_dirty(); } } else @@ -2040,9 +2044,12 @@ KEY TSpreadsheet::edit(int n) // TSheet_field /////////////////////////////////////////////////////////// + // Certified 100% TSheet_field::TSheet_field(TMask* m) - : TOperable_field(m), _append(TRUE) + : TLoadable_field(m), _append(TRUE), + _enable_autoload(FALSE),_sheetfile(NULL),_linee_rec(NULL),_external_record(FALSE), + _userput(NULL),_userget(NULL) { } @@ -2058,6 +2065,11 @@ bool TSheet_field::is_kind_of(word cid) const // Certified 100% TSheet_field::~TSheet_field() { + if (_sheetfile!=NULL) + delete _sheetfile; + if (_linee_rec!=NULL && !_external_record) + delete _linee_rec; + } // Certified 100% @@ -2094,17 +2106,85 @@ void TSheet_field::parse_head(TScanner& scanner) } -// Certified 100% +// Certified: ...under debug... bool TSheet_field::parse_item(TScanner& scanner) { - if (scanner.key() == "IT") + if (scanner.key() == "IT") // ITEM { _ctl_data._park.add(scanner.string()); return TRUE; } + + if (scanner.key() == "FL") // FLAGS + { + _enable_autoload=scanner.string()=="A"; + return TRUE; + } + if (scanner.key() == "US") // USE + { + int key = 1; + + const int logicnum = scanner.integer(); + + if (logicnum > 0) + { + TDir d; d.get(logicnum); + if (fexist(d.filename())) // Controlla l'esistenza del file + { + _sheetfile = new TLocalisamfile(logicnum); + TString s = scanner.pop(); + + // cerca l'indicazione del campo di numerazione + if (s == "KE") + { + s = scanner.pop(); + _linee_rec= new TRecord_array(logicnum, s);// alloca i record + } + else + { + NFCHECK("Manca la definizione del campo di autonumerazione nel campo %d", + (int)dlg()); + } + + } + } + return TRUE; + } + + if (scanner.key() == "IN") // input (definisce la chiave) + { + parse_input(scanner); + return TRUE; + } + return TMask_field::parse_item(scanner); } +void TSheet_field::parse_input(TScanner& scanner) +{ + + const char* s = scanner.pop(); + _file_k_names.add(s); + + s = scanner.pop(); + if (*s == '"') // Constant string + { + scanner.push(); + TString& str = scanner.line(); + _file_k_ids.add(str); + + } + else // Field on the mask + { + CHECKS(_file_k_ids.get_pos(s) < 0, "Duplicate input field ", s); + _file_k_ids.add(s); + if (scanner.popkey() == "SE") _file_k_ids << '@'; // Special FILTERing field + else scanner.push(); + } +} + + + // Certified 100% void TSheet_field::create(WINDOW parent) { @@ -2393,7 +2473,7 @@ void TSheet_field::exchange(bool show_value, const real& nuo) if (vec != nuo) { - TBit_array valuta(32); + TBit_array valuta(TSpreadsheet::MAX_COL); int i = 0; for (int f = FIRST_FIELD; ;f++, i++) { @@ -2571,3 +2651,130 @@ void TSheet_field::check_row(int n) } +// Certified: ...under debug.. +void TSheet_field::set_lines_record(TRecord_array & r_a) +{ + if (_linee_rec && !_external_record) + delete _linee_rec; + _linee_rec= & r_a; + _external_record=TRUE; // il record attuale è esterno... +} + +// Certified: ...under debug.. +TRectype * TSheet_field::putkey(const TRelation& r) +{ + if (_sheetfile) { + // ******* + // costruisce la chiave per il record array + _sheetfile->zero(); + _file_k_names.restart(); + _file_k_ids.restart(); + TString dbfieldname; + while ((dbfieldname=_file_k_names.get())!="") { + TMask_field & f= mask().field(atoi(_file_k_ids.get())); + ((TLoadable_field&)f).autoload(r); + _sheetfile->put(dbfieldname, f.get()); + } + return &_sheetfile->curr(); + } + return NULL; +} + +// Certified: ...under debug.. +bool TSheet_field::autoload_line(int i,TRectype & rec) +{ + TToken_string &row= this->row(i-1); + + row = ""; + // riempie le colonne dello sheet i cui campi hanno attributo "FIELD" + for (int f=FIRST_FIELD; f<=_last_column_id; f++) { + TFieldref const *dbfield=sheet_mask().field(f).field(); + if (dbfield) { + row.add(dbfield->read(rec),cid2index(f)); + } + // completa l'operazione con le funzioni definite dall'utente + } + if (_userget) + _userget(*this,i); + check_row(i-1); + return TRUE; +} + +// Certified: ...under debug.. +bool TSheet_field::autosave_line(int i,TRectype & rec) +{ + for (int f=FIRST_FIELD; f<=_last_column_id; f++) { + TFieldref const *dbfield=sheet_mask().field(f).field(); + if (dbfield) + dbfield->write(cell(i-1,cid2index(f)),rec); + } + // completa l'operazione con le funzioni definite dall'utente + if (_userput) + _userput(*this,i); + return FALSE; +} + +// Certified: ...under debug.. +bool TSheet_field::autoload(const TRelation& rel) +{ + if (_enable_autoload) + { + CHECK(_linee_rec !=NULL, "Iu ev forgotten tu declare de Record array for de scit"); + // ******* + // trasferisce le linee dal record array allo sheet + destroy(); // cancella lo sheet + const int last_line = _linee_rec->last_row(); + for (int i= 1; i <= last_line; i++) + { + autoload_line(i,_linee_rec->row(i, TRUE)); + } + + return(0); + } + return _enable_autoload; +} + +// Certified: ...under debug.. +bool TSheet_field::autosave(TRelation& rel) +{ + if (_enable_autoload) + { + CHECK(_linee_rec !=NULL, "Iu ev forgotten tu declare de Record array for de scit"); + _linee_rec->destroy_rows(); + if (_sheetfile) + { + // trasferisce dal file locale + if (mask().insert_mode()) { + // rinumera la chiave + _file_k_names.restart(); + _file_k_ids.restart(); + TString dbfieldname; + while ((dbfieldname=_file_k_names.get())!="") { + TMask_field & f= mask().field(atoi(_file_k_ids.get())); + _linee_rec->renum_key(dbfieldname, f.get()); + } + } + } + // ******* + // trasferisce le linee dallo sheet al record array + for (int i= 1; i <= items(); i++) + { + autosave_line(i,_linee_rec->row(i, TRUE)); + } + } + return _enable_autoload; +} + + +// Certified: ...under debug.. +void TSheet_field::set_userget(SHEET_USERGETPUT handler) +{ + _userget = handler; +} + +// Certified: ...under debug.. +void TSheet_field::set_userput(SHEET_USERGETPUT handler) +{ + _userput = handler; +} + diff --git a/include/msksheet.h b/include/msksheet.h index 3b638d4c1..34f3e4917 100755 --- a/include/msksheet.h +++ b/include/msksheet.h @@ -5,6 +5,18 @@ #include #endif +#ifndef __ISAM_H +#include +#endif + +#ifndef __RECARRAY_H +#include +#endif + +#ifndef __RELATION_H +#include +#endif + #define FIRST_FIELD 101 #define K_ROWEDIT ( K_CTRL + 'I' ) @@ -16,12 +28,15 @@ class TSheet_field; // @type SPREADSHEET_NOTIFY | Prototipo funzione che gestisce l'ingresso, l'uscita e la modifica da una riga dello sheet typedef bool (*SPREADSHEET_NOTIFY)(TSheet_field& s, int r, KEY k); +// @type SHEET_USERGETPUT| Prototipo funzione utente che gestisce il caricamento/salvataggio dei dati dello sheet +typedef void (*SHEET_USERGETPUT)(TSheet_field &fld_righe, int item); + // @doc EXTERNAL // @class TSheet_field | Classe per la gestione dei campi di uno spreadsheet // // @base public | TMask_field -class TSheet_field : public TOperable_field +class TSheet_field : public TLoadable_field { // @author:(INTERNAL) Guido @@ -31,7 +46,24 @@ class TSheet_field : public TOperable_field // @access:(INTERNAL) Private Member // @cmember:(INTERNAL) Indica se aggiungere a fondo dello spreadsheet o nella riga in cui ti trovi - bool _append; + bool _append; + + // @cmember:(INTERNAL) Flag di autoload + bool _enable_autoload; + // @cmember:(INTERNAL) Campi di input sulla maschera (key field names) + TToken_string _file_k_names; + // @cmember:(INTERNAL) Campi di input sulla maschera (key field ids) + TToken_string _file_k_ids; + // @cmember:(INTERNAL) file delle righe + TLocalisamfile * _sheetfile; + // @cmember:(INTERNAL) record array delle righe + TRecord_array *_linee_rec; + // @cmember:(INTERNAL) indicatore di record array gestito esternamente + bool _external_record; + // @cmember:(INTERNAL) funzioni utente per get tra record (array) e array righe + SHEET_USERGETPUT _userput; + // @cmember:(INTERNAL) funzioni utente per put tra righe e record (array) + SHEET_USERGETPUT _userget; // @access Protected Member protected: @@ -50,7 +82,9 @@ protected: virtual void parse_head(TScanner& scanner); // @cmember Legge gli item dello spreadsheet da

virtual bool parse_item(TScanner& scanner); - // @cmember Crea lo spreadsheet + // @cmember Legge gli input (campi chiave) dello spreadsheet da

+ void parse_input(TScanner& scanner); + // @cmember Crea lo spreadsheet virtual void create(WINDOW parent); // @cmember Setta il focus sul campo @@ -67,11 +101,35 @@ public: // @cmember Gestisce la pressione del tasto (TRUE se la gestione ha avuto successo) virtual bool on_key(KEY k); - // @cmember Ritorna una riga dello spreadsheet + virtual bool is_sheet() const { return TRUE; } + + // @cmember Legge automaticamente la linea dal record array assegnato + virtual bool autoload_line(int i,TRectype & rec); + // @cmember Salva automaticamente la linea nel record array assegnato + virtual bool autosave_line(int i,TRectype & rec); + + // @cmember Legge automaticamente lo sheet dal record array assegnato + virtual bool autoload(const TRelation& r); + // @cmember Salva automaticamente lo sheet nel record array assegnato + virtual bool autosave(TRelation& r) ; + // @cmember setta la funzione utente che Legge i campi dello sheet + void set_userget(SHEET_USERGETPUT handler); + // @cmember setta la funzione utente che scrive i campi dello sheet + void set_userput(SHEET_USERGETPUT handler); + // @cmember carica le chiavi del record array dello sheet + TRectype * putkey(const TRelation& r); + // @cmember restituisce il record array assegnato allo sheet + TRecord_array * record() const {return _linee_rec;} + // @cmember Imposta un record array esterno che contiene le righe dello sheet + void set_lines_record(TRecord_array &); + // @cmember Ritorna se il record assegnato è gestito esternamente (read/write/remove) + bool external_record() const {return _external_record;} + + // @cmember Ritorna una riga dello spreadsheet TToken_string& row(int n); // @cmember Ritorna un array con tutte le righe dello spreadsheet TString_array& rows_array() const; - // @cmember Ritrna l'elemento

-esimo della riga

+ // @cmember Ritorna l'elemento

-esimo della riga

const char* cell(int r, int c) { return row(r).get(c); } @@ -153,7 +211,7 @@ public: // @cmember Setta il member

con il valore di

void set_append(bool on = TRUE) { _append = on;} - // @cmember Ritorna il valore del mebro

+ // @cmember Ritorna il valore del membro

bool append() const { return _append;} // @cmember Funzione eseguita dopo ogni insert @@ -162,6 +220,7 @@ public: // @cmember Esegue Tutti i check iniziali sulla riga

void check_row(int n); + // @cmember Costruttore TSheet_field(TMask* m); // @cmember Distruttore