Files correlati : cg0.exe cg2.exe cg3.exe cg3700a.msk Ricompilazione Demo : [ ] Commento : CM20023 Se apro la ricerca sul tipo costo ricavo della riga Iva e poi dall'help richiamo le informazioni e do conferma, riaprendo la ricerca sul campo tipo costo ricavo l'applicazione va in errore. CM20024 Se i campi delle date sono di compilazione obbligatoria devono avere il colore giallo. CM20025 Richiamando gruppo conto appartenete ai costi appare il campo della sola descrizione del codice iva di compensazione. Ricordo che il campo del codice e della descrizione per la compensazione devono apparire solo nel caso in cui venga richiamato un sottoconto di tipo ricavo. CM20027 I totali attuali in presenza di movimenti provvisori non sono corretti in quanto non vengono inclusi. I movimenti appartengono tutti all'anno 2002. git-svn-id: svn://10.65.10.50/trunk@11112 c028cbd2-c16b-5b4b-a496-9718f37d4682
3016 lines
77 KiB
C++
Executable File
3016 lines
77 KiB
C++
Executable File
#include <xinclude.h>
|
|
|
|
#include <applicat.h>
|
|
#include <colors.h>
|
|
#include <controls.h>
|
|
#include <currency.h>
|
|
#include <execp.h>
|
|
#include <mailbox.h>
|
|
#include <progind.h>
|
|
#include <recarray.h>
|
|
#include <relation.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <varmask.h>
|
|
|
|
#include "cg3.h"
|
|
#include "cglib01.h"
|
|
#include "cg3600.h"
|
|
|
|
#include <causali.h>
|
|
#include <mov.h>
|
|
#include <pconti.h>
|
|
#include <rmov.h>
|
|
#include <saldi.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TList
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#ifdef USE_OBSOLETE_LIST
|
|
|
|
class TList : public TContainer
|
|
{
|
|
enum { MAX_SKIP = 8192 };
|
|
|
|
struct TList_object : public TObject
|
|
{
|
|
TObject* _obj;
|
|
TList_object* _next;
|
|
TList_object* _prev;
|
|
};
|
|
|
|
TList_object** _skip;
|
|
long _items, _current;
|
|
long _step, _last_skip;
|
|
|
|
protected:
|
|
// @cmember Ritorna un puntatore al primo oggetto del contenitore
|
|
virtual TObject* first_item( );
|
|
// @cmember Ritorna un puntatore all'ultimo oggetto del contenitore
|
|
virtual TObject* last_item( );
|
|
// @cmember Ritorna un puntatore all'oggetto successivo all'oggetto corrente
|
|
virtual TObject* succ_item( );
|
|
// @cmember Ritorna un puntatore all'oggetto che precede l'oggetto corrente
|
|
virtual TObject* pred_item( );
|
|
// @cmember Ritorna il numero di oggetti nel contenitore
|
|
virtual long objects( );
|
|
|
|
protected:
|
|
TList_object* detach_lstobj(long index);
|
|
TList_object* lstobjptr(long index) const;
|
|
|
|
public:
|
|
long items() const { return _items; }
|
|
|
|
TObject* objptr(long index) const;
|
|
|
|
TObject& obj(long index)
|
|
{ TObject* o = objptr(index); CHECK(o, "Null list item"); return *o; }
|
|
|
|
const TObject& obj(long index) const
|
|
{ const TObject* o = objptr(index); CHECK(o, "Null list item"); return *o; }
|
|
|
|
void destroy();
|
|
long insert(TObject* obj, long pos);
|
|
long append(TObject* obj, long pos = -1);
|
|
|
|
TObject* detach(long pos);
|
|
bool remove(long pos);
|
|
|
|
void change_step(long step); // Forza il passo per gli elementi
|
|
long choose_step(long expected_size); // Sceglie il passo per gli elemnti
|
|
|
|
TList(long expected_size = 128L);
|
|
virtual ~TList();
|
|
};
|
|
|
|
TList::TList(long expected_size)
|
|
: _items(0), _current(0)
|
|
{
|
|
_skip = new TList_object*[MAX_SKIP+1];
|
|
_skip[0] = NULL;
|
|
choose_step(expected_size);
|
|
}
|
|
|
|
TList::~TList()
|
|
{
|
|
destroy();
|
|
delete [] _skip;
|
|
}
|
|
|
|
long TList::objects( )
|
|
{
|
|
return _items;
|
|
}
|
|
|
|
TObject* TList::first_item()
|
|
{
|
|
return objptr(_current = 0);
|
|
}
|
|
|
|
TObject* TList::succ_item()
|
|
{
|
|
return objptr(++_current);
|
|
}
|
|
|
|
TObject* TList::pred_item()
|
|
{
|
|
return objptr(_current++);
|
|
}
|
|
|
|
TObject* TList::last_item()
|
|
{
|
|
return objptr(_current = _items-1);
|
|
}
|
|
|
|
void TList::destroy()
|
|
{
|
|
TList_object* head = _skip[0];
|
|
while (head)
|
|
{
|
|
TList_object* next = head->_next;
|
|
if (head->_obj)
|
|
delete head->_obj;
|
|
delete head;
|
|
head = next;
|
|
}
|
|
_items = _current = _last_skip = 0;
|
|
_skip[0] = NULL;
|
|
}
|
|
|
|
TList::TList_object* TList::lstobjptr(long index) const
|
|
{
|
|
TList_object* lstobj = NULL;
|
|
const ldiv_t p = ldiv(index, _step);
|
|
if (p.quot >= 0 && p.quot < _last_skip)
|
|
{
|
|
TList_object* lo = _skip[p.quot];
|
|
for (long s = p.rem; lo && s > 0; s--)
|
|
lo = lo->_next;
|
|
|
|
lstobj = lo;
|
|
}
|
|
return lstobj;
|
|
}
|
|
|
|
TObject* TList::objptr(long index) const
|
|
{
|
|
const TList_object* lo = lstobjptr(index);
|
|
return lo ? lo->_obj : NULL;
|
|
}
|
|
|
|
void TList::change_step(long step)
|
|
{
|
|
CHECKD(step > 0 && step <= 16384, "Bad list step ", step);
|
|
_step = step;
|
|
_last_skip = 0;
|
|
|
|
step = 0;
|
|
for (TList_object* lo = _skip[0]; lo; lo = lo->_next, step--)
|
|
{
|
|
if (step == 0)
|
|
{
|
|
CHECK(_last_skip < MAX_SKIP, "Too many items");
|
|
_skip[_last_skip++] = lo;
|
|
step = _step;
|
|
}
|
|
}
|
|
}
|
|
|
|
long TList::choose_step(long expected_size)
|
|
{
|
|
long step = expected_size / MAX_SKIP + 1;
|
|
if (step < 8)
|
|
step = 8;
|
|
change_step(step);
|
|
return step;
|
|
}
|
|
|
|
long TList::insert(TObject* obj, long index)
|
|
{
|
|
if (index < 0)
|
|
index = 0;
|
|
else
|
|
{
|
|
if (index > _items)
|
|
index = _items;
|
|
}
|
|
const long pred = index-1;
|
|
|
|
TList_object* newobj = new TList_object;
|
|
newobj->_obj = obj;
|
|
|
|
if (pred < 0)
|
|
{
|
|
newobj->_prev = NULL;
|
|
newobj->_next = _skip[0];
|
|
if (_skip[0])
|
|
_skip[0]->_prev = newobj;
|
|
}
|
|
else
|
|
{
|
|
TList_object* lo = lstobjptr(pred);
|
|
CHECK(lo, "NULL insertion point");
|
|
newobj->_next = lo->_next;
|
|
newobj->_prev = lo;
|
|
if (lo->_next)
|
|
lo->_next->_prev = newobj;
|
|
lo->_next = newobj;
|
|
}
|
|
_items++;
|
|
|
|
ldiv_t p = ldiv(index, _step);
|
|
if (p.rem == 0 && p.quot < MAX_SKIP) // Cambia il capolista
|
|
_skip[p.quot] = newobj;
|
|
|
|
for (long i = p.quot + 1; i < _last_skip; i++)
|
|
_skip[i] = _skip[i]->_prev; // Aggiorna capilista successivi
|
|
|
|
// Siamo andati oltre l'ultimo skip
|
|
const long s = (_items - 1) / _step + 1;
|
|
if (s > _last_skip)
|
|
{
|
|
if (s > MAX_SKIP)
|
|
change_step(_step+1);
|
|
else
|
|
{
|
|
if (_last_skip > 0)
|
|
{
|
|
TList_object* lo = _skip[_last_skip-1];
|
|
while (lo->_next != NULL)
|
|
lo = lo->_next;
|
|
_skip[_last_skip++] = lo;
|
|
_skip[_last_skip] = NULL;
|
|
}
|
|
else
|
|
_last_skip = 1;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
long TList::append(TObject* obj, long index)
|
|
{
|
|
if (index < 0 || index >= _items)
|
|
index = _items;
|
|
else
|
|
index++;
|
|
return insert(obj, index);
|
|
}
|
|
|
|
TList::TList_object* TList::detach_lstobj(long index)
|
|
{
|
|
TList_object* lo = lstobjptr(index);
|
|
if (lo)
|
|
{
|
|
if (lo->_prev)
|
|
lo->_prev->_next = lo->_next;
|
|
if (lo->_next)
|
|
lo->_next->_prev = lo->_prev;
|
|
ldiv_t res = ldiv(index, _step);
|
|
if (res.rem == 0)
|
|
_skip[res.quot] = lo->_next;
|
|
long p;
|
|
for (p = res.quot + 1; p < _last_skip; p++)
|
|
_skip[p] = _skip[p]->_next;
|
|
|
|
_items--;
|
|
|
|
p = (_items - 1) / _step + 1;
|
|
if (p < _last_skip)
|
|
{
|
|
_last_skip--;
|
|
_skip[_last_skip] = NULL;
|
|
}
|
|
}
|
|
|
|
return lo;
|
|
}
|
|
|
|
TObject* TList::detach(long index)
|
|
{
|
|
TList_object* lo = detach_lstobj(index);
|
|
TObject* obj;
|
|
if (lo)
|
|
{
|
|
obj = lo->_obj;
|
|
delete lo;
|
|
}
|
|
else
|
|
obj = NULL;
|
|
return obj;
|
|
}
|
|
|
|
bool TList::remove(long index)
|
|
{
|
|
TObject* o = detach(index);
|
|
if (o)
|
|
delete o;
|
|
return o != NULL;
|
|
}
|
|
|
|
#else
|
|
|
|
// Simpler and faster 32 bit implemetation
|
|
|
|
class TList : public TContainer
|
|
{
|
|
TArray _data;
|
|
|
|
protected:
|
|
// @cmember Ritorna un puntatore al primo oggetto del contenitore
|
|
virtual TObject* first_item( ) { return _data.first_item(); }
|
|
// @cmember Ritorna un puntatore all'ultimo oggetto del contenitore
|
|
virtual TObject* last_item( ) { return _data.last_item(); }
|
|
// @cmember Ritorna un puntatore all'oggetto successivo all'oggetto corrente
|
|
virtual TObject* succ_item( ) { return _data.succ_item(); }
|
|
// @cmember Ritorna un puntatore all'oggetto che precede l'oggetto corrente
|
|
virtual TObject* pred_item( ) { return _data.pred_item(); }
|
|
// @cmember Ritorna il numero di oggetti nel contenitore
|
|
virtual long objects( ) { return _data.objects(); }
|
|
|
|
public:
|
|
long items() const { return _data.items(); }
|
|
void destroy() { _data.destroy(); }
|
|
long insert(TObject* obj, long pos) { return _data.insert(obj, pos); }
|
|
long append(TObject* obj, long pos = -1);
|
|
bool remove(long pos) { _data.remove(pos, TRUE); return TRUE; }
|
|
|
|
const TObject& obj(long index) const
|
|
{ const TObject* o = _data.objptr(index); CHECK(o, "Null list item"); return *o; }
|
|
};
|
|
|
|
long TList::append(TObject* obj, long index)
|
|
{
|
|
if (index < 0 || index >= items())
|
|
index = items();
|
|
else
|
|
index++;
|
|
return insert(obj, index);
|
|
}
|
|
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TBalance
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TBalance : public TObject
|
|
{
|
|
TImporto _saldo_ini, _progr_dare, _progr_avere, _saldo_fin;
|
|
|
|
protected:
|
|
bool find(const TBill& b, int esercizio,
|
|
TImporto& si, TImporto& da, TImporto& av, TImporto& sf,
|
|
TImporto& pd, TImporto& pa) const;
|
|
int indicatore_bilancio(const TBill& b) const;
|
|
|
|
public:
|
|
void read(int g, int c, long s, int esercizio, bool ignora_movap, bool provvis);
|
|
void read(const TBill& b, int esercizio, bool ignora_movap, bool provvis);
|
|
void reread();
|
|
|
|
const TImporto& saldo_iniziale() const;
|
|
const real& progressivo_dare_iniziale() const;
|
|
const real& progressivo_avere_iniziale() const;
|
|
real progressivo_dare_finale() const;
|
|
real progressivo_avere_finale() const;
|
|
TImporto saldo_finale(bool chiusura = FALSE) const;
|
|
TImporto saldo_finale_chiusura() const;
|
|
|
|
TBalance();
|
|
TBalance(int g, int c, long s, int esercizio, bool ignora_movap, bool provvis);
|
|
TBalance(const TBill& b, int esercizio, bool ignora_movap, bool provvis);
|
|
virtual ~TBalance() { }
|
|
};
|
|
|
|
TBalance::TBalance()
|
|
{
|
|
}
|
|
|
|
TBalance::TBalance(int g, int c, long s, int esercizio, bool ignora_movap, bool provvis)
|
|
{
|
|
read(g, c, s, esercizio, ignora_movap, provvis);
|
|
}
|
|
|
|
TBalance::TBalance(const TBill& b, int esercizio, bool ignora_movap, bool provvis)
|
|
{
|
|
read(b, esercizio, ignora_movap, provvis);
|
|
}
|
|
|
|
bool TBalance::find(const TBill& b, int esercizio,
|
|
TImporto& si, TImporto& da, TImporto& av, TImporto& sf,
|
|
TImporto& pd, TImporto& pa) const
|
|
{
|
|
CHECK(b.sottoconto() > 0L, "Sottoconto mancante");
|
|
|
|
TString key(30);
|
|
key.format("%d||%d|%d|%ld", esercizio, b.gruppo(), b.conto(), b.sottoconto());
|
|
const TRectype & saldi = cache().get(LF_SALDI, key);
|
|
if (!saldi.empty())
|
|
{
|
|
si.set(saldi.get_char(SLD_FLAGSALINI), saldi.get_real(SLD_SALDO));
|
|
da.set('D', saldi.get_real(SLD_PDARE));
|
|
av.set('A', saldi.get_real(SLD_PAVERE));
|
|
sf.set(saldi.get_char(SLD_FLAGSALFIN), saldi.get_real(SLD_SALDOFIN));
|
|
pd.set('D', saldi.get_real(SLD_PDAREPRO));
|
|
pa.set('A', saldi.get_real(SLD_PAVEREPRO));
|
|
}
|
|
else
|
|
{
|
|
si.set('D', ZERO);
|
|
da = av = sf = pd = pa = si;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TBalance::read(int gruppo, int conto, long sottoconto, int esercizio, bool ignora_movap, bool provvis)
|
|
{
|
|
const TBill zio(gruppo, conto, sottoconto);
|
|
read(zio, esercizio, ignora_movap, provvis);
|
|
}
|
|
|
|
int TBalance::indicatore_bilancio(const TBill& b) const
|
|
{
|
|
TString16 str;
|
|
str.format("%d|%d", b.gruppo(), b.conto());
|
|
const int ib = atoi(cache().get(LF_PCON, str, PCN_INDBIL));
|
|
if (ib == 0)
|
|
NFCHECK("Impossibile stabilire l'indicatore di bilancio");
|
|
return ib;
|
|
}
|
|
|
|
void TBalance::read(const TBill& b, int esercizio, bool ignora_movap, bool provvis)
|
|
{
|
|
TImporto si, sf, pd, pa, prd, pra;
|
|
|
|
find(b, esercizio, si, pd, pa, sf, prd, pra);
|
|
if (provvis)
|
|
{
|
|
pd += prd;
|
|
pa += pra;
|
|
}
|
|
_saldo_ini = si;
|
|
_progr_dare = pd;
|
|
_progr_avere = pa;
|
|
_saldo_fin = sf;
|
|
|
|
if (_saldo_ini.is_zero())
|
|
{
|
|
const int indbil = indicatore_bilancio(b);
|
|
if (indbil == 1 || indbil == 2 || indbil == 5)
|
|
{
|
|
TEsercizi_contabili esercizi;
|
|
const int precedente = esercizi.pred(esercizio);
|
|
if (precedente > 0 && find(b, precedente, si, pd, pa, sf, prd, pra))
|
|
{
|
|
if (provvis)
|
|
{
|
|
pd += prd;
|
|
pa += pra;
|
|
}
|
|
_saldo_ini = si;
|
|
_saldo_ini += pd;
|
|
_saldo_ini += pa;
|
|
_saldo_ini += sf;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ignora_movap)
|
|
_saldo_ini.set('D', ZERO);
|
|
}
|
|
}
|
|
|
|
const TImporto& TBalance::saldo_iniziale() const
|
|
{ return _saldo_ini; }
|
|
|
|
const real& TBalance::progressivo_dare_iniziale() const
|
|
{
|
|
return _saldo_ini.sezione() == 'D' ? _saldo_ini.valore() : ZERO;
|
|
}
|
|
|
|
const real& TBalance::progressivo_avere_iniziale() const
|
|
{
|
|
return _saldo_ini.sezione() == 'A' ? _saldo_ini.valore() : ZERO;
|
|
}
|
|
|
|
real TBalance::progressivo_dare_finale() const
|
|
{
|
|
real pd = progressivo_dare_iniziale();
|
|
pd += _progr_dare.valore();
|
|
if (_saldo_fin.sezione() == 'D')
|
|
pd += _saldo_fin.valore();
|
|
return pd;
|
|
}
|
|
|
|
real TBalance::progressivo_avere_finale() const
|
|
{
|
|
real pa = progressivo_avere_iniziale();
|
|
pa += _progr_avere.valore();
|
|
if (_saldo_fin.sezione() == 'A')
|
|
pa += _saldo_fin.valore();
|
|
return pa;
|
|
}
|
|
|
|
TImporto TBalance::saldo_finale(bool chiusura) const
|
|
{
|
|
TImporto sf(_saldo_ini);
|
|
sf += _progr_dare;
|
|
sf += _progr_avere;
|
|
if (chiusura)
|
|
sf += _saldo_fin;
|
|
return sf;
|
|
}
|
|
|
|
TImporto TBalance::saldo_finale_chiusura() const
|
|
{
|
|
return saldo_finale(TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrino
|
|
///////////////////////////////////////////////////////////
|
|
|
|
enum tipo_riga_mastrino { riga_mastrino, riga_contropartita };
|
|
|
|
class TRiga_mastrino : public TObject
|
|
{
|
|
tipo_riga_mastrino _type; // Tipo della riga
|
|
TRecnotype _mov, _rmov; // Numero fisico di record movivento e riga movimento
|
|
real _dare, _avere; // Progressivi dare ed avere
|
|
TDate _data; // Data di registrazione (Ottimizzazione)
|
|
|
|
public:
|
|
tipo_riga_mastrino tipo() const { return _type; }
|
|
TRecnotype rmov() const { return _rmov; }
|
|
TRecnotype mov() const { return _mov; }
|
|
|
|
const TDate& data() const { return _data; }
|
|
const real& dare() const { return _dare; }
|
|
const real& avere() const { return _avere; }
|
|
TImporto saldo() const; // Dare-Avere normalizzato
|
|
|
|
TRiga_mastrino(tipo_riga_mastrino trig,
|
|
TRecnotype rmov, TRecnotype mov,
|
|
const real& d, const real& a,
|
|
const TDate& datareg);
|
|
virtual ~TRiga_mastrino() { }
|
|
};
|
|
|
|
TRiga_mastrino::TRiga_mastrino(tipo_riga_mastrino trig,
|
|
TRecnotype rmov, TRecnotype mov,
|
|
const real& d, const real& a,
|
|
const TDate& datareg)
|
|
: _type(trig), _rmov(rmov), _mov(mov),
|
|
_dare(d), _avere(a), _data(datareg)
|
|
{ }
|
|
|
|
TImporto TRiga_mastrino::saldo() const
|
|
{
|
|
TImporto imp('D', _dare - _avere);
|
|
imp.normalize();
|
|
return imp;
|
|
}
|
|
|
|
class TMastrino : public TObject
|
|
{
|
|
static long _instances;
|
|
static TCursor* _cur;
|
|
static TRelation* _rel;
|
|
static TLocalisamfile *_rmov; // File principale della relazione
|
|
static TLocalisamfile *_mov; // File secondario della relazione
|
|
|
|
TBill _conto; // Conto del mastrino
|
|
int _esercizio; // Esercizio di riferimento (eventualmente 0)
|
|
TDate _da_data, _a_data; // Date limite
|
|
TString _da_caus, _a_caus; // Causali limite
|
|
bool _provvis; // Includi provvisori
|
|
|
|
real _pdare_ini, _pavere_ini;
|
|
real _pdare_per, _pavere_per;
|
|
real _pdare_fin, _pavere_fin;
|
|
|
|
TList _riga; // Righe del mastrino
|
|
|
|
protected:
|
|
TCursor& cur() { return *_cur; }
|
|
TRelation& rel() { return *_rel; }
|
|
TLocalisamfile& rmov() { return *_rmov; }
|
|
TLocalisamfile& mov() { return *_mov; }
|
|
|
|
void position_rel(long n);
|
|
TRiga_mastrino& row(long n) const { return (TRiga_mastrino&)_riga.obj(n); }
|
|
|
|
public:
|
|
long items() const { return _riga.items(); }
|
|
|
|
void read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac, bool provvis);
|
|
void reread();
|
|
|
|
TRiga_mastrino& operator[](long n) const { return row(n); }
|
|
const TRectype& riga(long n);
|
|
const TRectype& testata(long n);
|
|
|
|
long first(tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long pred(long rec, tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long succ(long rec, tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long last(tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
|
|
void destroy() { _riga.destroy(); }
|
|
|
|
const real& progressivo_dare_iniziale() const { return _pdare_ini; }
|
|
const real& progressivo_avere_iniziale() const { return _pavere_ini; }
|
|
TImporto saldo_iniziale() const;
|
|
|
|
const real& progressivo_dare_finale() const { return _pdare_fin; }
|
|
const real& progressivo_avere_finale() const { return _pavere_fin; }
|
|
TImporto saldo_finale() const;
|
|
|
|
real progressivo_dare_periodo() const { return _pdare_ini + _pdare_per; }
|
|
real progressivo_avere_periodo() const { return _pavere_ini + _pavere_per; }
|
|
TImporto saldo_periodo() const;
|
|
|
|
int esercizio() const { return _esercizio; }
|
|
const TDate& inizio_periodo() const { return _da_data; }
|
|
const TDate& fine_periodo() const { return _a_data; }
|
|
void periodo(TDate& dd, TDate& ad) const { dd = _da_data; ad = _a_data; }
|
|
|
|
bool expandable(long rec) const;
|
|
bool expand(long rec);
|
|
bool collapse(long rec);
|
|
|
|
TMastrino();
|
|
virtual ~TMastrino();
|
|
};
|
|
|
|
long TMastrino::_instances = 0L;
|
|
TCursor* TMastrino::_cur = NULL;
|
|
TRelation* TMastrino::_rel = NULL;
|
|
TLocalisamfile* TMastrino::_rmov = NULL; // File principale della relazione
|
|
TLocalisamfile* TMastrino::_mov = NULL; // File secondario della relazione
|
|
|
|
|
|
TMastrino::TMastrino()
|
|
: _esercizio(0)
|
|
{
|
|
if (_instances == 0L)
|
|
{
|
|
_rel = new TRelation(LF_RMOV);
|
|
_rel->add(LF_MOV, "NUMREG==NUMREG");
|
|
_rmov = &_rel->lfile();
|
|
_mov = &_rel->lfile(LF_MOV);
|
|
}
|
|
_instances++;
|
|
}
|
|
|
|
TMastrino::~TMastrino()
|
|
{
|
|
_instances--;
|
|
if (_instances == 0L)
|
|
{
|
|
delete _cur; _cur = NULL;
|
|
delete _rel; _rel = NULL;
|
|
_rmov = _mov = NULL;
|
|
}
|
|
}
|
|
|
|
long TMastrino::succ(long rec, tipo_riga_mastrino tipo) const
|
|
{
|
|
if (rec < 0) rec = -1;
|
|
|
|
const long ul = items();
|
|
for (long i = rec+1; i < ul; i++)
|
|
{
|
|
if (row(i).tipo() == tipo)
|
|
break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
long TMastrino::pred(long rec, tipo_riga_mastrino tipo) const
|
|
{
|
|
if (rec > items()) rec = items();
|
|
for (long i = rec-1; i >= 0; i--)
|
|
{
|
|
if (row(i).tipo() == tipo)
|
|
break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
long TMastrino::first(tipo_riga_mastrino tipo) const
|
|
{
|
|
return succ(-1, tipo);
|
|
}
|
|
|
|
long TMastrino::last(tipo_riga_mastrino tipo) const
|
|
{
|
|
return pred(items(), tipo);
|
|
}
|
|
|
|
void TMastrino::read(const TBill& conto,
|
|
int ae, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac,
|
|
bool provvis)
|
|
{
|
|
TEsercizi_contabili esercizi;
|
|
|
|
_conto = conto;
|
|
_esercizio = ae;
|
|
|
|
_riga.destroy();
|
|
|
|
rmov().setkey(2);
|
|
TRectype& rmov_rec = rmov().curr();
|
|
TRectype& mov_rec = mov().curr();
|
|
|
|
if (ae <= 0)
|
|
{
|
|
if (dd.ok())
|
|
ae = esercizi.date2esc(dd);
|
|
else
|
|
ae = esercizi.date2esc(ad);
|
|
}
|
|
CHECKD(esercizi.exist(ae), "Anno di esercizio fantasioso: ", ae);
|
|
|
|
const TDate& inizio_esercizio = esercizi[ae].inizio();
|
|
_da_data = dd.ok() ? dd : inizio_esercizio;
|
|
_a_data = ad.ok() ? ad : esercizi[ae].fine();
|
|
|
|
const bool test_caus = !(dc.blank() && ac.blank());
|
|
_da_caus = dc;
|
|
_a_caus = ac.blank() ? "zzz" : ac; // Se vuota sceglie la massima causale
|
|
_provvis = provvis;
|
|
|
|
TDate max_data_reg = _a_data;
|
|
long num_giorni = _a_data - inizio_esercizio + 1;
|
|
if (_esercizio > 0)
|
|
{
|
|
const int succ = esercizi.next(ae);
|
|
if (succ > 0)
|
|
{
|
|
max_data_reg = esercizi[succ].fine();
|
|
num_giorni += 30;
|
|
}
|
|
else
|
|
max_data_reg = esercizi[ae].fine();
|
|
}
|
|
|
|
#ifdef USE_OBSOLETE_LIST
|
|
// Stima dimensione mastrino
|
|
_riga.choose_step(num_giorni);
|
|
#endif
|
|
|
|
// Valori dei saldi fino alla data di inizio stampa:
|
|
// Vengono inizializzati con i saldi iniziali dell'esercizio,
|
|
// poi verranno sommati gli importi dei movimenti che
|
|
// vanno dall'inizio dell'esercizio al giorno precedente
|
|
// la data di inizio stampa
|
|
|
|
TBalance saldo(_conto, ae, TRUE, provvis);
|
|
_pdare_ini = saldo.progressivo_dare_iniziale();
|
|
_pavere_ini = saldo.progressivo_avere_iniziale();
|
|
|
|
// Valori dei saldi finali:
|
|
// Comprendono i movimenti di apertura, chiusura ed i progressivi attuali
|
|
saldo.read(_conto, ae, FALSE, provvis);
|
|
_pdare_fin = saldo.progressivo_dare_finale();
|
|
_pavere_fin = saldo.progressivo_avere_finale();
|
|
|
|
// Valori dei saldi del perido in esame:
|
|
// Vengono inizializzati a zero e poi si incrementa man mano
|
|
// coi valori degli importi dei movimenti compresi nei
|
|
// limiti della stampa
|
|
_pdare_per = _pavere_per = ZERO;
|
|
|
|
const TRecfield rmov_datareg (rmov_rec, RMV_DATAREG);
|
|
const TRecfield rmov_numreg (rmov_rec, RMV_NUMREG);
|
|
const TRecfield rmov_gruppo (rmov_rec, RMV_GRUPPO);
|
|
const TRecfield rmov_conto (rmov_rec, RMV_CONTO);
|
|
const TRecfield rmov_sottoconto(rmov_rec, RMV_SOTTOCONTO);
|
|
const TRecfield rmov_sezione (rmov_rec, RMV_SEZIONE);
|
|
const TRecfield rmov_importo (rmov_rec, RMV_IMPORTO);
|
|
|
|
const TRecfield mov_datacomp (mov_rec, MOV_DATACOMP);
|
|
const TRecfield mov_provvis (mov_rec, MOV_PROVVIS);
|
|
const TRecfield mov_codcaus (mov_rec, MOV_CODCAUS);
|
|
|
|
#ifdef DBG
|
|
long num_rec = 0;
|
|
const clock_t clock_start = clock();
|
|
#endif
|
|
|
|
rmov_rec.zero();
|
|
conto.put(rmov_rec);
|
|
TRectype darow(rmov_rec), arow(rmov_rec);
|
|
darow.put(RMV_DATAREG, inizio_esercizio);
|
|
arow.put(RMV_DATAREG, max_data_reg);
|
|
TCursor cur(&rel(), "", 2, &darow, &arow);
|
|
const TRecnotype totrows = cur.items();
|
|
cur.freeze();
|
|
|
|
TString caption(80);
|
|
caption.format(FR("Caricamento mastrino %03d.%03d.%06ld"),
|
|
_conto.gruppo(), _conto.conto(), _conto.sottoconto());
|
|
TProgind pi(totrows, caption, FALSE, TRUE);
|
|
|
|
for (cur = 0L; cur.pos() < totrows; ++cur)
|
|
{
|
|
pi.addstatus(1);
|
|
#ifdef DBG
|
|
num_rec++;
|
|
if ((num_rec & 0x7F) == 0)
|
|
{
|
|
const double sec = (clock() - clock_start) / CLOCKS_PER_SEC;
|
|
if (sec > 0.0)
|
|
{
|
|
TString80 msg;
|
|
msg.format(FR("%ld records at %ld rec/sec"), num_rec, long(num_rec/sec));
|
|
pi.set_text(msg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Ignora eventualmente i movimenti provvisori
|
|
if (!_provvis)
|
|
{
|
|
const char is_provvis = *(const char*)mov_provvis;
|
|
if (is_provvis > ' ')
|
|
continue;
|
|
}
|
|
|
|
const TDate data_corrente = _esercizio <= 0 ? rmov_datareg : TDate((const char*)mov_datacomp);
|
|
if (data_corrente > _a_data)
|
|
continue;
|
|
|
|
const char sezione = *((const char*)rmov_sezione);
|
|
const real importo((const char*)rmov_importo);
|
|
|
|
if (data_corrente < _da_data)
|
|
{
|
|
if (data_corrente >= inizio_esercizio)
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_ini += importo;
|
|
else
|
|
_pavere_ini += importo;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_per += importo;
|
|
else
|
|
_pavere_per += importo;
|
|
|
|
// Controlla che la causale sia nei limiti
|
|
if (test_caus)
|
|
{
|
|
const bool ok = _da_caus <= mov_codcaus && _a_caus >= mov_codcaus;
|
|
if (!ok)
|
|
continue;
|
|
}
|
|
|
|
TRiga_mastrino* r = new TRiga_mastrino(riga_mastrino,
|
|
rmov().recno(), mov().recno(),
|
|
_pdare_per, _pavere_per, rmov_datareg);
|
|
_riga.append(r);
|
|
}
|
|
}
|
|
|
|
// Mi sposto all'inizio per far funzionare bene da subito il metodo riga(0)
|
|
mov().first();
|
|
rmov().first();
|
|
}
|
|
|
|
void TMastrino::reread()
|
|
{
|
|
read(_conto, _esercizio, _da_data, _a_data, _da_caus, _a_caus, _provvis);
|
|
}
|
|
|
|
void TMastrino::position_rel(long n)
|
|
{
|
|
const TRiga_mastrino& r = row(n);
|
|
if (rmov().recno() != r.rmov())
|
|
rmov().readat(r.rmov());
|
|
if (mov().recno() != r.mov())
|
|
mov().readat(r.mov());
|
|
}
|
|
|
|
const TRectype& TMastrino::riga(long n)
|
|
{
|
|
position_rel(n);
|
|
return rmov().curr();
|
|
}
|
|
|
|
const TRectype& TMastrino::testata(long n)
|
|
{
|
|
position_rel(n);
|
|
return mov().curr();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_iniziale() const
|
|
{
|
|
TImporto s('D', _pdare_ini - _pavere_ini);
|
|
return s.normalize();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_finale() const
|
|
{
|
|
TImporto s('D', _pdare_fin - _pavere_fin);
|
|
return s.normalize();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_periodo() const
|
|
{
|
|
TImporto s('D', progressivo_dare_periodo() - progressivo_avere_periodo());
|
|
return s.normalize();
|
|
}
|
|
|
|
bool TMastrino::expandable(long rec) const
|
|
{
|
|
bool e = FALSE;
|
|
if (rec >= 0 && rec < items())
|
|
{
|
|
if (row(rec).tipo() == riga_mastrino)
|
|
{
|
|
if (rec < items()-1)
|
|
e = row(rec+1).tipo() != riga_contropartita;
|
|
else
|
|
e = TRUE;
|
|
}
|
|
}
|
|
return e;
|
|
}
|
|
|
|
// Genera le righe di contropartita di una riga del mastrino
|
|
bool TMastrino::expand(long rec)
|
|
{
|
|
bool ok = expandable(rec);
|
|
if (ok)
|
|
{
|
|
const TRectype& head = testata(rec); // Testata movimento
|
|
const long numreg = head.get_long(RMV_NUMREG); // Numero di registrazione
|
|
const int numrig = riga(rec).get_int(RMV_NUMRIG); // Numero riga contabile
|
|
const TDate datareg = head.get(MOV_DATAREG); // Data di registrazione
|
|
|
|
rmov().setkey(1); // Usa chiave NUMREG+NUMRIG
|
|
TRectype& curr = rmov().curr(); // Record corrente
|
|
|
|
const TRecfield rnumreg (curr, RMV_NUMREG); // Numero di registrazione corrente
|
|
const TRecfield rnumrig (curr, RMV_NUMRIG); // Numero di riga corrente
|
|
const TRecfield rsezione(curr, RMV_SEZIONE); // Sezione Dare/Avere
|
|
const TRecfield rimporto(curr, RMV_IMPORTO); // Importo della riga
|
|
|
|
int err = NOERR;
|
|
if (numrig != 1) // Se non e' gia' posizionato grazie a riga(rec)
|
|
{
|
|
curr.zero(); // Azzera record corrente
|
|
curr.put(RMV_NUMREG, numreg); // Inizializza la chiave parziale
|
|
err = rmov().read(_isgteq); // Cerca la prima riga del movimento
|
|
}
|
|
for (; err == NOERR; err = rmov().next()) // Scandisce righe movimento
|
|
{
|
|
if (numreg != (long)rnumreg) // Controlla validita' numero
|
|
break;
|
|
|
|
if (numrig != (int)rnumrig) // Ignora la riga gia' presente
|
|
{
|
|
real dare, avere; // Costruisce importo della riga
|
|
if (*(const char*)rsezione == 'D')
|
|
dare = rimporto;
|
|
else
|
|
avere = rimporto;
|
|
// Aggiunge una riga di contropartita al mastrino
|
|
TRiga_mastrino* r = new TRiga_mastrino(riga_contropartita,
|
|
rmov().recno(), mov().recno(),
|
|
dare, avere, datareg);
|
|
_riga.append(r, rec++);
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// Elimina le righe di contropartita di una riga del mastrino
|
|
bool TMastrino::collapse(long rec)
|
|
{
|
|
bool ok = TRUE; // Posso eliminare?
|
|
if (row(rec).tipo() != riga_mastrino) // Se non sono su una riga mastrino ...
|
|
rec = pred(rec, riga_mastrino); // ... mi sposto sulla precedente riga mastrino
|
|
else
|
|
ok = !expandable(rec); // Controlla che sia possibile
|
|
|
|
if (ok) // Posso effetivamente procedere
|
|
{
|
|
rec++; // Elimino ogni riga contropartita successiva
|
|
while (rec < items() && row(rec).tipo() != riga_mastrino)
|
|
_riga.remove(rec);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_control
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGrid_control;
|
|
|
|
|
|
class TGrid_cell : public TFixed_string
|
|
{
|
|
XI_EVENT* _xiev;
|
|
|
|
public:
|
|
TString& set(const char* txt);
|
|
TString& set(long num);
|
|
void set_icon(int id);
|
|
void show_button(bool on = TRUE);
|
|
void hide_button() { show_button(FALSE); }
|
|
void set_back_color(COLOR col);
|
|
void set_fore_color(COLOR col);
|
|
void set_colors(COLOR back, COLOR fore);
|
|
|
|
short get_column() const { return _xiev->v.cell_request.col_nbr; }
|
|
|
|
TString& operator = (const char* str) { return set(str); }
|
|
TString& operator = (const TString& str) { return set(str); }
|
|
|
|
TGrid_cell(XI_EVENT* xiev);
|
|
virtual ~TGrid_cell() { }
|
|
};
|
|
|
|
class TGrid_field : public TOperable_field
|
|
{
|
|
protected: // TMask_field
|
|
virtual void create(WINDOW parent);
|
|
virtual void parse_head(TScanner& scanner);
|
|
virtual bool parse_item(TScanner& scanner);
|
|
virtual word class_id() const;
|
|
|
|
TGrid_control& grid() const { return (TGrid_control&)*_ctl; }
|
|
|
|
public:
|
|
virtual bool handler(XI_EVENT* xiev);
|
|
virtual long items() const;
|
|
virtual void cell_request(long rec, short id, TGrid_cell& cell);
|
|
|
|
virtual bool on_record(long rec) { return TRUE; }
|
|
virtual bool off_record(long rec) { return TRUE; }
|
|
virtual bool on_resize_column(short cid, int new_size) { return TRUE; }
|
|
virtual void on_dbl_cell(long rec, short id) { }
|
|
virtual void on_grid_button() { }
|
|
virtual void on_record_button(long rec) { }
|
|
virtual void on_cell_button(long rec, short cid) { }
|
|
|
|
long selected() const;
|
|
void update(long n = -1);
|
|
int visible_rows() const;
|
|
bool select(long rec);
|
|
|
|
void reset_columns_order();
|
|
void save_columns_order() const;
|
|
|
|
TGrid_field(TMask* m);
|
|
virtual ~TGrid_field() { }
|
|
};
|
|
|
|
class TGrid_control : public TControl
|
|
{
|
|
enum grid_control_constants { MAX_COL = 128 };
|
|
|
|
long _cur_rec;
|
|
bool _read_only;
|
|
|
|
// @cmember:(INTERNAL) Tipo di ogni colonna
|
|
byte _type[MAX_COL];
|
|
|
|
TGrid_field* _grid;
|
|
|
|
int _default_width[MAX_COL];
|
|
int _columns_order;
|
|
|
|
protected: // TControl
|
|
//@cmember Gestisce gli eventi delle celle
|
|
virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
|
|
|
|
//@cmember Chiama gli handlers opportuni per verificare il cambio record
|
|
bool try_to_select(long rec) const;
|
|
|
|
protected:
|
|
//@cmember Ritorna il numero totale di righe
|
|
long items() const { return _grid->items(); }
|
|
|
|
//@cmember Converte un record nella eventuale riga corrispondente a video
|
|
int rec2row(long rec) const;
|
|
|
|
//@cmember Converte una riga a video nell'eventuale record corrispondente
|
|
long row2rec(int row) const;
|
|
|
|
//@cmember Converte un indice di colonna nel corrispondente id
|
|
short int col2cid(int pos) const;
|
|
|
|
void update_selection(XI_EVENT* xiev);
|
|
|
|
void set_columns_order(TToken_string* order);
|
|
|
|
XI_OBJ* find_column(short cid) const;
|
|
XI_OBJ* find_column(const char* head) const;
|
|
|
|
public:
|
|
long selected() const { return _cur_rec; }
|
|
bool select(long n);
|
|
|
|
int visible_rows() const;
|
|
|
|
byte& column_type(int c) { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; }
|
|
|
|
void update(long n = -1);
|
|
bool is_visible(long rec) const;
|
|
|
|
void load_columns_order();
|
|
void save_columns_order() const;
|
|
void reset_columns_order() { set_columns_order(NULL); }
|
|
|
|
TGrid_control(WINDOW parent, short cid,
|
|
short x, short y, short dx, short dy,
|
|
const char* flags, const char* head,
|
|
TGrid_field* owner);
|
|
virtual ~TGrid_control() {}
|
|
};
|
|
|
|
|
|
TGrid_control::TGrid_control(
|
|
WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet
|
|
short cid, // @parm Identificatore
|
|
short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet
|
|
short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet
|
|
short dx, // @parm Larghezza (in caratteri) dello spreasheet
|
|
short dy, // @parm Lunghezza (in caratteri) dello spreasheet
|
|
const char* flags, // @parm Flags di abilitazione
|
|
const char* head, // @parm Titolo delle colonne
|
|
TGrid_field* owner)
|
|
: _grid(owner), _cur_rec(-1), _columns_order(0)
|
|
{
|
|
_read_only = FALSE;
|
|
bool auto_num = FALSE;
|
|
bool multi_line = FALSE;
|
|
int lines_in_cell = 1;
|
|
|
|
for (const char* f = flags; *f; f++)
|
|
{
|
|
switch(*f)
|
|
{
|
|
case 'A':
|
|
auto_num = TRUE;
|
|
break;
|
|
case 'D':
|
|
_read_only = TRUE;
|
|
break;
|
|
case 'M':
|
|
multi_line = TRUE;
|
|
lines_in_cell = (int)xi_get_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL);
|
|
break;
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
if (multi_line)
|
|
lines_in_cell = *f - '0';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
const int NUMBER_WIDTH = auto_num ? 7 : 1;
|
|
short v_width[MAX_COL];
|
|
short m_width[MAX_COL];
|
|
int fixed_columns = 1; // Number of fixed columns
|
|
int lines_in_header = 1; // Number of header lines
|
|
|
|
// Calcolo larghezza massima tabella
|
|
TToken_string header(head);
|
|
TToken_string new_header(256);
|
|
int i = 0;
|
|
int f_width = NUMBER_WIDTH; // Stima larghezza colonne fisse
|
|
int max_width = f_width; // Stima larghezza della colonna piu' grande
|
|
|
|
for (const char* h = header.get(); h; h = header.get(), i++)
|
|
{
|
|
CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i);
|
|
_type[i] = ' ';
|
|
|
|
TFixed_string testa(esc(h));
|
|
const bool multiple = testa.find('\n') > 0;
|
|
if (multiple)
|
|
lines_in_header = 2;
|
|
|
|
const int at = testa.find('@');
|
|
int v = testa.len(); // Video width
|
|
if (at >= 0)
|
|
{
|
|
const TString& wi = testa.mid(at+1);
|
|
const int video = atoi(wi);
|
|
if (video > 0) v = video;
|
|
if (wi.find('F') >= 0)
|
|
{
|
|
fixed_columns = i+2;
|
|
f_width += v+1;
|
|
}
|
|
if (wi.find('R') >= 0)
|
|
_type[i] = 'R';
|
|
|
|
testa.cut(at);
|
|
}
|
|
|
|
v++;
|
|
// memory width of column
|
|
m_width[i] = v * lines_in_cell;
|
|
if (v > 64) v = 64;
|
|
v_width[i] = v;
|
|
if (v_width[i] > max_width)
|
|
max_width = v_width[i];
|
|
new_header.add(testa);
|
|
}
|
|
|
|
// Calcola rettangolo massimo per lo sheet
|
|
RCT rct; coord2rct(parent, x, y, dx, dy, rct);
|
|
rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar
|
|
|
|
// Controlla se ci sono troppe colonne fisse
|
|
if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right)
|
|
fixed_columns = 1;
|
|
|
|
XI_OBJ* itf = get_interface(parent);
|
|
|
|
long list_attr = XI_ATR_ENABLED | XI_ATR_VISIBLE;
|
|
// if (_read_only) list_attr |= XI_ATR_NAVIGATE;
|
|
|
|
XI_OBJ_DEF* listdef = xi_add_list_def(NULL, cid,
|
|
rct.top, rct.left, rct.bottom-rct.top,
|
|
list_attr,
|
|
NORMAL_COLOR, NORMAL_BACK_COLOR, // normal
|
|
DISABLED_COLOR, DISABLED_BACK_COLOR, // disabled
|
|
FOCUS_COLOR, // active
|
|
0);
|
|
|
|
listdef->app_data = (long)this;
|
|
|
|
XI_LIST_DEF* l = listdef->v.list;
|
|
#ifdef XI_R4
|
|
l->min_heading_height = xi_button_calc_height_font(xi_get_system_font()) * lines_in_header;
|
|
#else
|
|
l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()) * lines_in_header;
|
|
#endif
|
|
l->sizable_columns = TRUE;
|
|
l->movable_columns = TRUE;
|
|
l->fixed_columns = fixed_columns;
|
|
l->max_lines_in_cell = lines_in_cell;
|
|
l->scroll_bar = TRUE;
|
|
l->scroll_bar_button = TRUE;
|
|
l->white_space_color = MASK_DARK_COLOR;
|
|
l->rule_color = MASK_DARK_COLOR;
|
|
|
|
if (_read_only)
|
|
{
|
|
l->single_select = TRUE;
|
|
}
|
|
else
|
|
{
|
|
l->active_back_color = FOCUS_BACK_COLOR;
|
|
}
|
|
|
|
// Definizione della prima colonna (numero di riga)
|
|
const long attr = XI_ATR_VISIBLE | XI_ATR_RJUST | XI_ATR_SELECTABLE;
|
|
XI_OBJ_DEF* coldef = xi_add_column_def(listdef, FIRST_FIELD+1000-1, attr, 0,
|
|
NUMBER_WIDTH * XI_FU_MULTIPLE, NUMBER_WIDTH , "");
|
|
|
|
coldef->app_data = (long)this;
|
|
XI_COLUMN_DEF* cd = coldef->v.column;
|
|
cd->heading_platform = TRUE;
|
|
cd->column_platform = TRUE;
|
|
|
|
for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++)
|
|
{
|
|
long attr = XI_ATR_VISIBLE | XI_ATR_ENABLED | XI_ATR_AUTOSCROLL;
|
|
if (_read_only)
|
|
attr |= XI_ATR_READONLY | XI_ATR_SELECTABLE;
|
|
if (_type[i] == 'R')
|
|
attr |= XI_ATR_RJUST;
|
|
coldef = xi_add_column_def(listdef, FIRST_FIELD+i+1000, attr, i+1,
|
|
v_width[i] * XI_FU_MULTIPLE, m_width[i], (char*)h);
|
|
|
|
coldef->app_data = (long)this;
|
|
cd = coldef->v.column;
|
|
cd->heading_platform = TRUE;
|
|
cd->center_heading = TRUE;
|
|
if (multi_line)
|
|
cd->wrap_text = _type[i] != 'R';
|
|
}
|
|
|
|
RCT rd; xi_get_def_rect(listdef, (XinRect*)&rd);
|
|
if ((rd.right - rd.left) > (rct.right - rct.left))
|
|
l->width = rct.right - rct.left;
|
|
|
|
_obj = xi_create(itf, listdef); // Create the whole thing!
|
|
xi_dequeue(); // Flush events in XOL
|
|
xi_tree_free(listdef); // Free definitions
|
|
|
|
CHECKD(_obj, "Can't create list control ", cid);
|
|
update_tab_cid();
|
|
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
RCT rct; xi_get_rect(column[i], (XinRect*)&rct);
|
|
_default_width[i] = rct.right - rct.left;
|
|
}
|
|
}
|
|
|
|
// Converts a record number in the correspondig row number
|
|
int TGrid_control::rec2row(long record) const
|
|
{
|
|
int rows;
|
|
const long* rec = xi_get_list_info(_obj, &rows);
|
|
int r = rows > 0 ? int(record - rec[0]) : -1;
|
|
if (r < 0 || r >= rows)
|
|
r = -1;
|
|
return r;
|
|
}
|
|
|
|
// Converts a row number in the correspondig record number
|
|
long TGrid_control::row2rec(int row) const
|
|
{
|
|
CHECK(row >= 0, "Negative grid row?");
|
|
|
|
int rows;
|
|
const long* handle = xi_get_list_info(_obj, &rows);
|
|
|
|
long rec;
|
|
if (rows > 0)
|
|
{
|
|
if (row >= rows)
|
|
rec = handle[rows-1] + row - rows + 1;
|
|
else
|
|
rec = handle[row];
|
|
}
|
|
else
|
|
rec = -1;
|
|
|
|
if (rec < 0 || rec >= items())
|
|
rec = -1;
|
|
|
|
return rec;
|
|
}
|
|
|
|
int TGrid_control::visible_rows() const
|
|
{
|
|
return xi_get_visible_rows(_obj, NULL, NULL);
|
|
}
|
|
|
|
bool TGrid_control::is_visible(long rec) const
|
|
{
|
|
int first, last;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
|
|
int rows;
|
|
const long* handle = xi_get_list_info(_obj, &rows);
|
|
|
|
bool yes = rec >= handle[first] && rec <= handle[last];
|
|
return yes;
|
|
}
|
|
|
|
|
|
void TGrid_control::update(long n)
|
|
{
|
|
if (n >= 0)
|
|
{
|
|
const int riga = rec2row(n);
|
|
if (riga >= 0)
|
|
{
|
|
XI_OBJ row;
|
|
XI_MAKE_ROW(&row, _obj, riga);
|
|
xi_cell_request(&row);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int num = 0;
|
|
const long* handle = xi_get_list_info(_obj, &num);
|
|
|
|
bool scroll_first = items() == 0;
|
|
if (!scroll_first)
|
|
{
|
|
int first = 0, last = 0;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
n = handle[first];
|
|
scroll_first = n > items();
|
|
}
|
|
|
|
if (scroll_first)
|
|
xi_scroll(_obj, XI_SCROLL_FIRST);
|
|
else
|
|
xi_scroll_rec(_obj, n, NORMAL_COLOR, XI_ATR_ENABLED, 0);
|
|
}
|
|
}
|
|
|
|
bool TGrid_control::select(long rec)
|
|
{
|
|
bool ok, sel;
|
|
if (rec >= 0)
|
|
{
|
|
ok = try_to_select(rec);
|
|
sel = ok;
|
|
}
|
|
else
|
|
{
|
|
ok = _cur_rec >= 0 && _cur_rec < items() && _grid->off_record(_cur_rec);
|
|
sel = FALSE;
|
|
}
|
|
|
|
if (ok)
|
|
{
|
|
if (sel)
|
|
{
|
|
int first, last;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
// Controllo che la nuova riga sia completamente visibile
|
|
const int next_row = rec2row(rec);
|
|
if (next_row >= first && next_row <= last)
|
|
{
|
|
if (_read_only)
|
|
{
|
|
XI_OBJ riga; XI_MAKE_ROW(&riga, _obj, next_row);
|
|
long attr = xi_get_attrib(&riga);
|
|
attr |= XI_ATR_SELECTED;
|
|
xi_set_attrib(&riga, attr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long attr = XI_ATR_ENABLED;
|
|
if (_read_only)
|
|
attr |= XI_ATR_SELECTED;
|
|
xi_scroll_rec(_obj, rec, NORMAL_COLOR, attr, 0);
|
|
}
|
|
|
|
if (!_read_only)
|
|
{
|
|
const int next_row = rec2row(rec);
|
|
XI_OBJ cella; XI_MAKE_CELL(&cella, _obj, next_row, 1);
|
|
xi_set_focus(&cella);
|
|
}
|
|
} // end if (sel)
|
|
|
|
// Deseleziona record precedente se ancora visibile
|
|
if (_read_only)
|
|
{
|
|
const int cur_row = rec2row(_cur_rec);
|
|
if (cur_row >= 0)
|
|
{
|
|
XI_OBJ riga; XI_MAKE_ROW(&riga, _obj, cur_row);
|
|
long attr = xi_get_attrib(&riga);
|
|
attr &= ~XI_ATR_SELECTED;
|
|
xi_set_attrib(&riga, attr);
|
|
}
|
|
xi_dequeue();
|
|
}
|
|
|
|
if (rec < 0 || rec >= items())
|
|
rec = -1;
|
|
_cur_rec = rec;
|
|
} // end if (ok)
|
|
|
|
return ok;
|
|
}
|
|
|
|
short TGrid_control::col2cid(int pos) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
CHECKD(pos >= 0 && pos < num, "Bad column ", pos);
|
|
const short cid = column[pos]->cid - 1000;
|
|
return cid;
|
|
}
|
|
|
|
bool TGrid_control::try_to_select(long rec) const
|
|
{
|
|
bool ok = rec >= 0 && rec < items();
|
|
if (ok && rec != _cur_rec)
|
|
{
|
|
if (_cur_rec >= 0 && _cur_rec < items())
|
|
ok = _grid->off_record(_cur_rec);
|
|
if (ok)
|
|
ok = _grid->on_record(rec);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TGrid_control::update_selection(XI_EVENT* xiev)
|
|
{
|
|
const bool is_curr = xiev->v.rec_request.data_rec == _cur_rec;
|
|
if (_read_only)
|
|
{
|
|
/*
|
|
if (is_curr)
|
|
xiev->v.rec_request.attrib |= XI_ATR_SELECTED;
|
|
else
|
|
xiev->v.rec_request.attrib &= ~XI_ATR_SELECTED;
|
|
*/
|
|
}
|
|
else
|
|
xiev->v.rec_request.has_focus = is_curr;
|
|
}
|
|
|
|
// Certified 75%
|
|
bool TGrid_control::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|
{
|
|
BOOLEAN& refused = xiev->refused;
|
|
|
|
const bool handled = _grid->handler(xiev);
|
|
if (handled)
|
|
return !refused;
|
|
|
|
switch (xiev->type)
|
|
{
|
|
case XIE_GET_FIRST:
|
|
if (items() > 0L)
|
|
{
|
|
long n = items() * (long)xiev->v.rec_request.percent / 100L;
|
|
if (n < 0L) n = 0L;
|
|
xiev->v.rec_request.data_rec = n;
|
|
update_selection(xiev);
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
break;
|
|
case XIE_GET_LAST:
|
|
xiev->v.rec_request.data_rec = items()-1;
|
|
update_selection(xiev);
|
|
break;
|
|
case XIE_GET_PREV:
|
|
case XIE_GET_NEXT:
|
|
{
|
|
const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ;
|
|
if (n >= 0 && n < items())
|
|
{
|
|
xiev->v.rec_request.data_rec = n;
|
|
update_selection(xiev);
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
break;
|
|
case XIE_GET_PERCENT:
|
|
{
|
|
const long rec = xiev->v.get_percent.record;
|
|
long n = items(); if (n <= 0) n = 1;
|
|
xiev->v.get_percent.percent = short(rec * 100L / n);
|
|
}
|
|
break;
|
|
case XIE_COL_MOVE:
|
|
// Rifiuta di spostare una colonna nelle o dalle colonne fisse
|
|
if (xiev->v.column.in_fixed ||
|
|
xiev->v.column.col_nbr < xi_get_fixed_columns(xiev->v.column.list))
|
|
refused = TRUE;
|
|
else
|
|
_columns_order = 1;
|
|
break;
|
|
case XIE_COL_SIZE:
|
|
{
|
|
const short cid = col2cid(xiev->v.column.col_nbr);
|
|
if (_grid->on_resize_column(cid, xiev->v.column.new_col_width))
|
|
_columns_order = 1;
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
break;
|
|
case XIE_SELECT:
|
|
if (xiev->v.select.xi_obj->type == XIT_ROW) // Considero solo le righe
|
|
{
|
|
if (xiev->v.select.selected) // Sto selezionando
|
|
{
|
|
const long rec = row2rec(xiev->v.select.xi_obj->v.row_data.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
if (xiev->v.select.column == 0)
|
|
{
|
|
#ifndef XI_R4
|
|
_cur_rec = rec; // Assegno subito il record corrente
|
|
_grid->on_record_button(rec);
|
|
#endif
|
|
if (_read_only)
|
|
refused = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (_read_only && rec == _cur_rec)
|
|
{
|
|
const short cid = col2cid(xiev->v.select.column);
|
|
_grid->on_dbl_cell(rec, cid);
|
|
refused = TRUE;
|
|
}
|
|
_cur_rec = rec; // Assegno solo ora il record corrente
|
|
}
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case XIE_CELL_REQUEST:
|
|
{
|
|
const long& rec = xiev->v.cell_request.rec;
|
|
if (rec >= 0 && rec < items())
|
|
{
|
|
TGrid_cell cell(xiev);
|
|
const short cid = col2cid(cell.get_column());
|
|
if (cid >= FIRST_FIELD)
|
|
{
|
|
_grid->cell_request(rec, cid, cell);
|
|
}
|
|
else
|
|
{
|
|
if (cell.size() > 2)
|
|
{
|
|
cell.set(rec+1);
|
|
// Setto il colore del testo altrimenti verrebbe grigio:
|
|
// non uso la set_color perche' ignora NORMAL_COLOR
|
|
xiev->v.cell_request.color = NORMAL_COLOR;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
refused = TRUE; // Ogni tanto succede
|
|
}
|
|
break;
|
|
case XIE_ON_ROW:
|
|
{ // Qui ci passa solo se non e' _read_only
|
|
const long rec = row2rec(xiev->v.xi_obj->v.row);
|
|
if (rec >= 0)
|
|
{
|
|
if (_grid->on_record(rec))
|
|
_cur_rec = rec;
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
else
|
|
{
|
|
NFCHECK("You are entering an invalid row: %d", xiev->v.xi_obj->v.row);
|
|
refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case XIE_OFF_ROW:
|
|
// Qui ci passa solo se non e' _read_only
|
|
if (_cur_rec >= 0 && _cur_rec < items())
|
|
refused = !_grid->off_record(_cur_rec);
|
|
break;
|
|
case XIE_ON_CELL:
|
|
break;
|
|
case XIE_DBL_CELL:
|
|
{
|
|
const long rec = row2rec(xiev->v.xi_obj->v.cell.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
const short cid = col2cid(xiev->v.xi_obj->v.cell.column);
|
|
_grid->on_dbl_cell(rec, cid);
|
|
}
|
|
}
|
|
break;
|
|
case XIE_BUTTON:
|
|
if (xiev->v.xi_obj->type == XIT_LIST)
|
|
{
|
|
_grid->on_grid_button();
|
|
}
|
|
else
|
|
{
|
|
const XI_CELL_DATA& cell = xiev->v.xi_obj->v.cell;
|
|
const long rec = row2rec(cell.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
const short cid = col2cid(cell.column);
|
|
_grid->on_cell_button(rec, cid);
|
|
}
|
|
else
|
|
NFCHECK("You are clicking an invalid cell: %d", cell.row);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return !refused;
|
|
}
|
|
|
|
XI_OBJ* TGrid_control::find_column(short cid) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
for (int i = num-1; i >= 0; i--)
|
|
{
|
|
if (column[i]->cid == cid)
|
|
break;
|
|
}
|
|
return i >= 0 ? column[i] : NULL;
|
|
}
|
|
|
|
XI_OBJ* TGrid_control::find_column(const char* head) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
|
|
TString80 text;
|
|
for (int i = num-1; i >= 0; i--)
|
|
{
|
|
xi_get_text(column[i], text.get_buffer(), text.size());
|
|
if (text == head)
|
|
break;
|
|
}
|
|
return i >= 0 ? column[i] : NULL;
|
|
}
|
|
|
|
void TGrid_control::set_columns_order(TToken_string* order)
|
|
{
|
|
XI_OBJ* itf = get_interface();
|
|
XI_OBJ* focus = xi_get_focus(itf);
|
|
xi_set_focus(itf);
|
|
|
|
int num_cols;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num_cols);
|
|
|
|
// Costante da sottrarre nella xi_column_set_pixel_width altrimenti la somma due volte!
|
|
const int offset = 2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
const int fixed = xi_get_fixed_columns(_obj);
|
|
if (fixed > 1)
|
|
xi_set_fixed_columns(_obj, 1);
|
|
|
|
if (order == NULL)
|
|
{
|
|
for (int index = 1; index < num_cols; index++)
|
|
{
|
|
const short cid = FIRST_FIELD + 1000 + index - 1;
|
|
XI_OBJ* col = find_column(cid);
|
|
if (col)
|
|
{
|
|
xi_move_column(col, index);
|
|
RCT rct; xi_get_rect(col, (XinRect*)&rct);
|
|
if (_default_width[index] != rct.right - rct.left)
|
|
xi_column_set_pixel_width(col, _default_width[index]-offset);
|
|
}
|
|
}
|
|
_columns_order = 0x3;
|
|
}
|
|
else
|
|
{
|
|
TToken_string col(8, ',');
|
|
int pos = 0;
|
|
for (col = order->get(0); !col.blank(); col = order->get(), pos++)
|
|
{
|
|
const char* head = esc(col.get(0));
|
|
const int width = col.get_int();
|
|
XI_OBJ* column = find_column(head);
|
|
if (column) // Controlla che esista ancora
|
|
{
|
|
if (pos > 0 && pos < num_cols)
|
|
xi_move_column(column, pos); // Sposta la colonna se possibile
|
|
if (width > XI_FU_MULTIPLE) // Se ha una larghezza valida
|
|
xi_column_set_pixel_width(column, width - offset);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fixed > 1)
|
|
xi_set_fixed_columns(_obj, fixed);
|
|
|
|
if (focus)
|
|
xi_set_focus(focus);
|
|
}
|
|
|
|
HIDDEN TFilename& field2parag(const TMask_field& f, TFilename& name)
|
|
{
|
|
const TMask& m = f.mask();
|
|
name = m.source_file();
|
|
name.ext(""); // Nome della maschera senza estensione
|
|
const int index = m.number();
|
|
CHECKD(index >= 0 && index <= 8, "Bad mask index:", index);
|
|
if (index > 0) // Aggiunge l'eventuale numero di sotto-maschera
|
|
name << '(' << index << ')';
|
|
return name;
|
|
}
|
|
|
|
void TGrid_control::load_columns_order()
|
|
{
|
|
TFilename parag; field2parag(*_grid, parag);
|
|
TConfig config(CONFIG_USER, parag);
|
|
TToken_string order = config.get("Browse", NULL, id());
|
|
if (order.empty_items())
|
|
config.remove("Browse", id());
|
|
else
|
|
set_columns_order(&order);
|
|
_columns_order = 0;
|
|
}
|
|
|
|
void TGrid_control::save_columns_order() const
|
|
{
|
|
if (_columns_order)
|
|
{
|
|
TFilename parag; field2parag(*_grid, parag);
|
|
TConfig config(CONFIG_USER, parag); // Apre il file di configurazione
|
|
|
|
TToken_string order(127); // Nuovo ordine delle colonne
|
|
if (_columns_order == 1) // Se vale 3 devo solo resettare
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
TString80 head;
|
|
for (int i = 0; i < num; i++) // Scorre tutte le colonne
|
|
{
|
|
xi_get_text(column[i], head.get_buffer(), head.size());
|
|
const int acapo = head.find('\n');
|
|
if (acapo > 0)
|
|
{
|
|
head[acapo] = '\\';
|
|
head.insert("n", acapo+1);
|
|
}
|
|
order.add(head);
|
|
RCT rct; xi_get_rect(column[i], (XinRect*)&rct);
|
|
order << ',' << rct.right - rct.left;
|
|
}
|
|
config.set("Browse", order, NULL, TRUE, id());
|
|
}
|
|
else
|
|
config.remove("Browse", id());
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_cell
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TGrid_cell::TGrid_cell(XI_EVENT* xiev)
|
|
: TFixed_string(xiev->v.cell_request.s, xiev->v.cell_request.len),
|
|
_xiev(xiev)
|
|
{ }
|
|
|
|
|
|
// Setta il testo di una cella (Mai piu' testo troppo lungo!)
|
|
// Se c'e' gia' un'icona la elimina
|
|
TString& TGrid_cell::set(const char* txt)
|
|
{
|
|
strncpy(txt, size());
|
|
if (not_empty())
|
|
{
|
|
int& icon = _xiev->v.cell_request.icon_rid;
|
|
if (icon)
|
|
icon = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
TString& TGrid_cell::set(long num)
|
|
{
|
|
char buff[16];
|
|
sprintf(buff, "%ld", num);
|
|
return set(buff);
|
|
}
|
|
|
|
// Setta l'icona di una cella
|
|
// Se c'e' gia' un testo lo elimina
|
|
void TGrid_cell::set_icon(int id)
|
|
{
|
|
_xiev->v.cell_request.icon_rid = id;
|
|
if (id)
|
|
_xiev->v.cell_request.s[0] = '\0';
|
|
}
|
|
|
|
void TGrid_cell::show_button(bool on)
|
|
{
|
|
_xiev->v.cell_request.button = on;
|
|
_xiev->v.cell_request.button_on_focus = on;
|
|
}
|
|
|
|
void TGrid_cell::set_back_color(COLOR col)
|
|
{
|
|
if (col != NORMAL_BACK_COLOR)
|
|
_xiev->v.cell_request.back_color = col;
|
|
}
|
|
|
|
void TGrid_cell::set_fore_color(COLOR col)
|
|
{
|
|
if (col != NORMAL_COLOR)
|
|
_xiev->v.cell_request.color = col;
|
|
}
|
|
|
|
void TGrid_cell::set_colors(COLOR back, COLOR fore)
|
|
{
|
|
if (back != NORMAL_BACK_COLOR)
|
|
_xiev->v.cell_request.back_color = back;
|
|
if (fore != NORMAL_COLOR)
|
|
_xiev->v.cell_request.color = fore;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TGrid_field::TGrid_field(TMask* m)
|
|
: TOperable_field(m)
|
|
{ }
|
|
|
|
word TGrid_field::class_id() const
|
|
{
|
|
return CLASS_GRID_FIELD;
|
|
}
|
|
|
|
void TGrid_field::update(long n)
|
|
{ grid().update(n); }
|
|
|
|
void TGrid_field::parse_head(TScanner& scanner)
|
|
{
|
|
_ctl_data._width = scanner.integer();
|
|
_ctl_data._height = scanner.integer();
|
|
if (_ctl_data._height == 0)
|
|
_ctl_data._height = -1;
|
|
}
|
|
|
|
void TGrid_field::create(WINDOW parent)
|
|
{
|
|
_ctl = new TGrid_control(parent, dlg(),
|
|
_ctl_data._x, _ctl_data._y,
|
|
_ctl_data._width, _ctl_data._height,
|
|
_ctl_data._flags, _ctl_data._park,
|
|
this);
|
|
grid().load_columns_order();
|
|
}
|
|
|
|
bool TGrid_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "IT")
|
|
{
|
|
_ctl_data._park.add(scanner.string());
|
|
return TRUE;
|
|
}
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
|
|
bool TGrid_field::handler(XI_EVENT* xiev)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
long TGrid_field::items() const
|
|
{
|
|
return 100000L;
|
|
}
|
|
|
|
int TGrid_field::visible_rows() const
|
|
{
|
|
return grid().visible_rows();
|
|
}
|
|
|
|
void TGrid_field::cell_request(long rec, short id, TGrid_cell& cell)
|
|
{
|
|
cell.set("Cell");
|
|
}
|
|
|
|
long TGrid_field::selected() const
|
|
{ return grid().selected(); }
|
|
|
|
bool TGrid_field::select(long rec)
|
|
{ return grid().select(rec); }
|
|
|
|
void TGrid_field::reset_columns_order()
|
|
{
|
|
grid().reset_columns_order();
|
|
}
|
|
|
|
void TGrid_field::save_columns_order() const
|
|
{
|
|
grid().save_columns_order();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Da qui in poi e' tutta roba specializzata del programma
|
|
///////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Maschere per colori
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TRow_mask : public TMask
|
|
{
|
|
public:
|
|
virtual void update();
|
|
|
|
TRow_mask();
|
|
virtual ~TRow_mask() { }
|
|
};
|
|
|
|
class TColor_mask : public TVariable_mask
|
|
{
|
|
static TRow_mask* _sheet_mask;
|
|
static TMask* get_mask(int, TMask&) { return _sheet_mask; }
|
|
|
|
COLOR _mas_back, _mas_fore;
|
|
COLOR _con_back, _con_fore;
|
|
|
|
protected:
|
|
static bool color_handler(TMask_field& f, KEY k);
|
|
static bool reset_handler(TMask_field& f, KEY k);
|
|
|
|
void type2colors(char tipo, COLOR& back, COLOR& fore) const;
|
|
|
|
public:
|
|
void get_cur_colors(COLOR& back, COLOR& fore) const;
|
|
void set_cur_colors(COLOR back, COLOR fore);
|
|
|
|
void get_colors(COLOR& mb, COLOR& mf, COLOR& cb, COLOR& cf) const;
|
|
|
|
TColor_mask(COLOR mb, COLOR mf, COLOR cb, COLOR cf);
|
|
virtual ~TColor_mask();
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TRow_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TRow_mask* TColor_mask::_sheet_mask = NULL;
|
|
|
|
TRow_mask::TRow_mask()
|
|
: TMask("cg2100k", 1)
|
|
{
|
|
}
|
|
|
|
void TRow_mask::update()
|
|
{
|
|
TSheet_field* s = get_sheet();
|
|
TColor_mask& m = (TColor_mask&)s->mask();
|
|
COLOR back, fore;
|
|
m.get_cur_colors(back, fore);
|
|
|
|
_pixmap = TRUE;
|
|
set_pen(COLOR_BLACK);
|
|
|
|
RCT rct; field(100).get_rect(rct);
|
|
set_brush(back);
|
|
frame(rct.left, 2*rct.top - rct.bottom - CHARY/2, rct.right, rct.top - CHARY/2, 0);
|
|
|
|
field(99).get_rect(rct);
|
|
set_brush(fore);
|
|
frame(rct.left, 2*rct.top - rct.bottom - CHARY/2, rct.right, rct.top - CHARY/2, 0);
|
|
|
|
_pixmap = FALSE;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TColor_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
void TColor_mask::type2colors(char tipo, COLOR& back, COLOR& fore) const
|
|
{
|
|
if (toupper(tipo) == 'M')
|
|
{
|
|
back = _mas_back;
|
|
fore = _mas_fore;
|
|
}
|
|
else
|
|
{
|
|
back = _con_back;
|
|
fore = _con_fore;
|
|
}
|
|
}
|
|
|
|
void TColor_mask::get_cur_colors(COLOR& back, COLOR& fore) const
|
|
{
|
|
TSheet_field& s = (TSheet_field&)fld(0);
|
|
TToken_string& row = s.row(s.selected());
|
|
const char tipo = row[5];
|
|
type2colors(tipo, back, fore);
|
|
}
|
|
|
|
void TColor_mask::set_cur_colors(COLOR back, COLOR fore)
|
|
{
|
|
TSheet_field& s = (TSheet_field&)fld(0);
|
|
const int cur = s.selected();
|
|
TToken_string& row = s.row(cur);
|
|
const char tipo = toupper(row[5]);
|
|
if (tipo == 'M')
|
|
{
|
|
_mas_back = back;
|
|
_mas_fore = fore;
|
|
}
|
|
else
|
|
{
|
|
_con_back = back;
|
|
_con_fore = fore;
|
|
}
|
|
s.set_back_and_fore_color(back, fore, cur);
|
|
s.force_update(cur);
|
|
}
|
|
|
|
bool TColor_mask::color_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TMask& m = f.mask();
|
|
TColor_mask& cm = (TColor_mask&)m.get_sheet()->mask();
|
|
|
|
COLOR back, fore;
|
|
cm.get_cur_colors(back, fore);
|
|
const bool use_back = f.dlg() == 100;
|
|
|
|
const COLOR col = choose_color(use_back ? back : fore, m.win());
|
|
if (col != COLOR_INVALID)
|
|
{
|
|
if (use_back)
|
|
back = col;
|
|
else
|
|
fore = col;
|
|
cm.set_cur_colors(back, fore);
|
|
cm._sheet_mask->update();
|
|
m.set_focus();
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TColor_mask::reset_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE && f.yesno_box(TR("Si desidera azzerare tutti i colori?")))
|
|
{
|
|
TColor_mask& m = (TColor_mask&) f.mask();
|
|
|
|
m._mas_back = NORMAL_BACK_COLOR;
|
|
m._mas_fore = NORMAL_COLOR;
|
|
m._con_back = NORMAL_BACK_COLOR;
|
|
m._con_fore = NORMAL_COLOR;
|
|
TSheet_field& s = (TSheet_field&)f.mask().field(101);
|
|
s.set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, -1);
|
|
s.force_update();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TColor_mask::get_colors(COLOR& mb, COLOR& mf, COLOR& cb, COLOR& cf) const
|
|
{
|
|
mb = _mas_back;
|
|
mf = _mas_fore;
|
|
cb = _con_back;
|
|
cf = _con_fore;
|
|
}
|
|
|
|
TColor_mask::TColor_mask(COLOR mb, COLOR mf, COLOR cb, COLOR cf)
|
|
: TVariable_mask("cg2100k"),
|
|
_mas_back(mb), _mas_fore(mf), _con_back(cb), _con_fore(cf)
|
|
{
|
|
set_handler(102, reset_handler);
|
|
set_caption("Colori delle righe mastrini");
|
|
CHECK(_sheet_mask == NULL, "One color at time, please");
|
|
_sheet_mask = new TRow_mask;
|
|
_sheet_mask->set_handler(99, color_handler);
|
|
_sheet_mask->set_handler(100, color_handler);
|
|
|
|
TVariable_sheet_field& s = (TVariable_sheet_field&)fld(0);
|
|
s.set_getmask(get_mask);
|
|
|
|
const char* const tipi = "MC";
|
|
int row = 0;
|
|
for (const char* c = tipi; *c; c++)
|
|
{
|
|
COLOR back, fore;
|
|
type2colors(*c, back, fore);
|
|
TToken_string& riga = s.row(-1);
|
|
riga << TR("Riga ") << (*c == 'M' ? TR("mastrino") : TR("contropartita"));
|
|
s.set_back_and_fore_color(back, fore, row++);
|
|
}
|
|
}
|
|
|
|
TColor_mask::~TColor_mask()
|
|
{
|
|
delete _sheet_mask;
|
|
_sheet_mask = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrini_grid
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TMastrini_grid : public TGrid_field
|
|
{
|
|
TMastrino _mastrino;
|
|
|
|
TDecoder _causali;
|
|
TEsercizi_contabili _esercizi;
|
|
|
|
COLOR _mas_back, _mas_fore;
|
|
COLOR _con_back, _con_fore;
|
|
|
|
protected: // TGrid_field
|
|
virtual bool on_record(long rec);
|
|
virtual void cell_request(long rec, short id, TGrid_cell& cell);
|
|
virtual void on_grid_button();
|
|
virtual bool on_resize_column(short id, int new_size);
|
|
|
|
void update_mask() const;
|
|
|
|
public:
|
|
virtual void on_dbl_cell(long rec, short id);
|
|
virtual void on_record_button(long rec);
|
|
virtual long items() const { return _mastrino.items(); }
|
|
|
|
void destroy();
|
|
void read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac, bool provv);
|
|
void reread();
|
|
|
|
TMastrino& mastrino() { return _mastrino; }
|
|
|
|
void save_colors();
|
|
void load_colors();
|
|
void set_colors();
|
|
|
|
TMastrini_grid(TMask* m);
|
|
virtual ~TMastrini_grid() { }
|
|
};
|
|
|
|
TMastrini_grid::TMastrini_grid(TMask* m)
|
|
: TGrid_field(m), _causali(LF_CAUSALI, CAU_DESCR)
|
|
{
|
|
load_colors();
|
|
}
|
|
|
|
void TMastrini_grid::destroy()
|
|
{
|
|
_mastrino.destroy();
|
|
grid().select(-1);
|
|
}
|
|
|
|
HIDDEN const char* real2string(const real& r)
|
|
{
|
|
TCurrency cur(r);
|
|
return cur.string(TRUE);
|
|
}
|
|
|
|
HIDDEN void set_imp(TMask_field& f, const TImporto& imp)
|
|
{
|
|
if (!imp.is_zero())
|
|
{
|
|
TString80 str;
|
|
str.format("%s %c", real2string(imp.valore()), imp.sezione());
|
|
f.set(str);
|
|
}
|
|
else
|
|
f.reset();
|
|
}
|
|
|
|
void TMastrini_grid::cell_request(long rec, short id, TGrid_cell& cell)
|
|
{
|
|
const TRiga_mastrino& riga = _mastrino[rec];
|
|
|
|
switch (id)
|
|
{
|
|
case 101:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell = riga.data().string();
|
|
cell << ' ' << mov.get(MOV_DATADOC);
|
|
}
|
|
break;
|
|
case 102:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
const int anno = _esercizi.date2esc(riga.data());
|
|
const int eser = mov.get_int(MOV_ANNOES);
|
|
TString8 str;
|
|
if (anno != eser)
|
|
str = "C"; // Di competenza vecchia
|
|
if (mov.get(MOV_PROVVIS).not_empty())
|
|
{
|
|
if (str.not_empty())
|
|
str << '/';
|
|
str << 'P';
|
|
}
|
|
cell = str;
|
|
}
|
|
break;
|
|
case 103:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell.set(_causali.decode(mov.get(MOV_CODCAUS)));
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.format("%03d.%03d.%06ld",
|
|
rmov.get_int(RMV_GRUPPO),
|
|
rmov.get_int(RMV_CONTO),
|
|
rmov.get_long(RMV_SOTTOCONTO));
|
|
}
|
|
break;
|
|
case 104:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.set(rmov.get(RMV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell.set(mov.get(MOV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
TBill uncle(rmov,TRUE);
|
|
cell.set(uncle.descrizione());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.set(rmov.get(RMV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
const TBill conto(rmov);
|
|
cell.set(conto.descrizione());
|
|
}
|
|
}
|
|
break;
|
|
case 105:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
const char sez = rmov.get_char(RMV_SEZIONE);
|
|
if (sez == 'D')
|
|
cell = real2string(rmov.get_real(RMV_IMPORTO));
|
|
}
|
|
break;
|
|
case 106:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
const char sez = rmov.get_char(RMV_SEZIONE);
|
|
if (sez == 'A')
|
|
cell = real2string(rmov.get_real(RMV_IMPORTO));
|
|
}
|
|
break;
|
|
case 107:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell = mov.get(MOV_NUMDOC); cell.left_just(7);
|
|
cell << ' ' << mov.get(MOV_PROTIVA);
|
|
}
|
|
break;
|
|
case 108:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell = real2string(rmov.get_real(RMV_IMPORTO));
|
|
cell << ' ' << rmov.get(RMV_SEZIONE);
|
|
}
|
|
break;
|
|
case 109:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const long next_row = _mastrino.succ(rec, riga_mastrino);
|
|
bool stampa = next_row >= _mastrino.items();
|
|
if (!stampa)
|
|
{
|
|
const TDate& data = _mastrino[next_row].data();
|
|
stampa = riga.data() != data;
|
|
}
|
|
if (stampa)
|
|
{
|
|
TImporto imp = riga.saldo();
|
|
imp += _mastrino.saldo_iniziale();
|
|
imp.normalize();
|
|
cell = real2string(imp.valore());
|
|
cell << ' ' << imp.sezione();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (riga.tipo() == riga_mastrino)
|
|
cell.set_colors(_mas_back, _mas_fore);
|
|
else
|
|
cell.set_colors(_con_back, _con_fore);
|
|
}
|
|
|
|
bool TMastrini_grid::on_record(long rec)
|
|
{
|
|
if (_mastrino[rec].tipo() != riga_mastrino)
|
|
rec = _mastrino.pred(rec, riga_mastrino);
|
|
|
|
TRiga_mastrino& riga = _mastrino[rec];
|
|
TMask& gm = mask();
|
|
set_imp(gm.field(F_TOTRIG_SAL), riga.saldo());
|
|
gm.set(F_TOTRIG_DAR, riga.dare());
|
|
gm.set(F_TOTRIG_AVE, riga.avere());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TMastrini_grid::on_dbl_cell(long rec, short id)
|
|
{
|
|
if (rec >= 0 && rec < items())
|
|
{
|
|
if (_mastrino.expandable(rec))
|
|
_mastrino.expand(rec);
|
|
else
|
|
_mastrino.collapse(rec);
|
|
update();
|
|
}
|
|
}
|
|
|
|
void TMastrini_grid::on_grid_button()
|
|
{
|
|
const long total = _mastrino.items();
|
|
if (total > 0)
|
|
{
|
|
TProgind* pi = NULL;
|
|
|
|
if (total > 50)
|
|
pi = new TProgind(total, TR("Aggiornamento contropartite ..."), FALSE, TRUE, 48);
|
|
else
|
|
begin_wait();
|
|
|
|
// Cerca l'ultima contropartita
|
|
const long last_con = _mastrino.last(riga_contropartita);
|
|
// Se non esistono contropartite devo espandere le righe
|
|
const bool expand = last_con < 0;
|
|
|
|
#ifdef DBG
|
|
const clock_t clock_start = clock();
|
|
#endif
|
|
|
|
if (expand)
|
|
{
|
|
long step = 0;
|
|
for (long n = _mastrino.first(riga_mastrino);
|
|
n < _mastrino.items(); n = _mastrino.succ(n, riga_mastrino))
|
|
{
|
|
if (_mastrino.expandable(n))
|
|
_mastrino.expand(n);
|
|
if (pi)
|
|
{
|
|
pi->setstatus(++step);
|
|
#ifdef DBG
|
|
if ((step & 0x7F) == 0)
|
|
{
|
|
const double sec = (clock() - clock_start) / CLOCKS_PER_SEC;
|
|
if (sec > 0.0)
|
|
{
|
|
TString80 msg;
|
|
msg.format(FR("%ld records at %ld rec/sec"), step, long(step/sec));
|
|
pi->set_text(msg);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long n = last_con; n > 0; n = _mastrino.pred(n, riga_contropartita))
|
|
{
|
|
_mastrino.collapse(n);
|
|
if (pi)
|
|
pi->setstatus(total - n + 1);
|
|
}
|
|
}
|
|
|
|
if (pi)
|
|
delete pi;
|
|
else
|
|
end_wait();
|
|
|
|
update();
|
|
}
|
|
}
|
|
|
|
void TMastrini_grid::on_record_button(long rec)
|
|
{
|
|
TWait_cursor hourglass;
|
|
|
|
const TRectype& testata = _mastrino.testata(rec);
|
|
TString text;
|
|
text << "1|" << testata.get(MOV_NUMREG);
|
|
|
|
const char* const appname = "cg2 -0";
|
|
TMessage pn(appname, MSG_LN, text);
|
|
pn.send();
|
|
|
|
TExternal_app a(appname);
|
|
a.run();
|
|
mask().set_focus();
|
|
|
|
TMailbox mail;
|
|
if (mail.next_s(MSG_LN) != NULL)
|
|
{
|
|
if (yesno_box(TR("Si desidera aggiornare il mastrino?")))
|
|
reread();
|
|
}
|
|
}
|
|
|
|
// Posso ridimensionare solo le descrizioni, le altre devono rimanere fisse per
|
|
// non perdere la formattazione su due righe
|
|
bool TMastrini_grid::on_resize_column(short cid, int new_size)
|
|
{
|
|
return cid == 103 || cid == 104;
|
|
}
|
|
|
|
|
|
void TMastrini_grid::read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac, bool provv)
|
|
{
|
|
destroy();
|
|
_mastrino.read(conto, annoes, dd, ad, dc, ac, provv);
|
|
update();
|
|
update_mask();
|
|
}
|
|
|
|
void TMastrini_grid::reread()
|
|
{
|
|
destroy();
|
|
_mastrino.reread();
|
|
update();
|
|
update_mask();
|
|
}
|
|
|
|
void TMastrini_grid::update_mask() const
|
|
{
|
|
TMask& gm = mask();
|
|
|
|
gm.set(F_ESERCIZIO, _mastrino.esercizio());
|
|
gm.set(F_DADATA, _mastrino.inizio_periodo());
|
|
gm.set(F_ADATA, _mastrino.fine_periodo());
|
|
|
|
set_imp(gm.field(F_TOTPRO_SAL), _mastrino.saldo_iniziale());
|
|
gm.set(F_TOTPRO_DAR, _mastrino.progressivo_dare_iniziale());
|
|
gm.set(F_TOTPRO_AVE, _mastrino.progressivo_avere_iniziale());
|
|
|
|
gm.reset(F_TOTRIG_SAL);
|
|
gm.reset(F_TOTRIG_DAR);
|
|
gm.reset(F_TOTRIG_AVE);
|
|
|
|
set_imp(gm.field(F_TOTPER_SAL), _mastrino.saldo_periodo());
|
|
gm.set(F_TOTPER_DAR, _mastrino.progressivo_dare_periodo());
|
|
gm.set(F_TOTPER_AVE, _mastrino.progressivo_avere_periodo());
|
|
|
|
set_imp(gm.field(F_TOTATT_SAL), _mastrino.saldo_finale());
|
|
gm.set(F_TOTATT_DAR, _mastrino.progressivo_dare_finale());
|
|
gm.set(F_TOTATT_AVE, _mastrino.progressivo_avere_finale());
|
|
|
|
gm.enable(DLG_LINK, _mastrino.items() > 0);
|
|
}
|
|
|
|
void TMastrini_grid::load_colors()
|
|
{
|
|
TConfig conf(CONFIG_USER, "cg3600b");
|
|
_mas_back = conf.get_color("ColorMB", NULL, -1, FOCUS_BACK_COLOR);
|
|
_mas_fore = conf.get_color("ColorMF", NULL, -1, FOCUS_COLOR);
|
|
_con_back = conf.get_color("ColorCB", NULL, -1, NORMAL_BACK_COLOR);
|
|
_con_fore = conf.get_color("ColorCF", NULL, -1, NORMAL_COLOR);
|
|
}
|
|
|
|
void TMastrini_grid::save_colors()
|
|
{
|
|
TConfig conf(CONFIG_USER, "cg3600b");
|
|
conf.set_color("ColorMB", _mas_back);
|
|
conf.set_color("ColorMF", _mas_fore);
|
|
conf.set_color("ColorCB", _con_back);
|
|
conf.set_color("ColorCF", _con_fore);
|
|
}
|
|
|
|
void TMastrini_grid::set_colors()
|
|
{
|
|
TColor_mask m(_mas_back, _mas_fore, _con_back, _con_fore);
|
|
if (m.run() == K_ENTER)
|
|
{
|
|
m.get_colors(_mas_back, _mas_fore, _con_back, _con_fore);
|
|
save_colors();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGrid_mask : public TMask
|
|
{
|
|
TMastrini_grid* _grid;
|
|
|
|
protected: // TMask
|
|
virtual TMask_field* parse_field(TScanner& sc);
|
|
virtual bool on_key(KEY k);
|
|
virtual void handler(WINDOW win, EVENT* ep);
|
|
|
|
static bool link_handler(TMask_field& f, KEY k);
|
|
|
|
public:
|
|
TMastrini_grid& grid() { CHECK(_grid, "What's grid?"); return *_grid; }
|
|
|
|
TGrid_mask();
|
|
virtual ~TGrid_mask() { }
|
|
};
|
|
|
|
TGrid_mask::TGrid_mask()
|
|
: _grid(NULL)
|
|
{
|
|
read_mask("cg3600b", 0, 0);
|
|
set_handler(DLG_LINK, link_handler);
|
|
}
|
|
|
|
TMask_field* TGrid_mask::parse_field(TScanner& sc)
|
|
{
|
|
TMask_field* f;
|
|
if (sc.key() == "SP")
|
|
f = _grid = new TMastrini_grid(this);
|
|
else
|
|
f = TMask::parse_field(sc);
|
|
return f;
|
|
}
|
|
|
|
bool TGrid_mask::link_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TGrid_mask& gm = (TGrid_mask&)f.mask();
|
|
TMastrini_grid& grid = gm.grid();
|
|
const long rec = grid.selected();
|
|
if (rec >= 0 && rec < grid.items())
|
|
grid.on_record_button(rec);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TGrid_mask::on_key(KEY k)
|
|
{
|
|
long rec = grid().selected();
|
|
switch (k)
|
|
{
|
|
case K_LHOME:
|
|
rec = 0;
|
|
break;
|
|
case K_PREV:
|
|
rec -= _grid->visible_rows();
|
|
if (rec < 0) rec = 0;
|
|
break;
|
|
case K_UP:
|
|
if (rec > 0)
|
|
rec--;
|
|
break;
|
|
case K_DOWN:
|
|
if (rec < _grid->items()-1)
|
|
rec++;
|
|
break;
|
|
case K_NEXT:
|
|
rec += _grid->visible_rows();
|
|
if (rec >= _grid->items())
|
|
rec = _grid->items()-1;
|
|
break;
|
|
case K_LEND:
|
|
rec = _grid->items()-1;
|
|
break;
|
|
case K_ENTER:
|
|
case K_CTRL+'+':
|
|
case K_CTRL+'-':
|
|
if (focus_field().dlg() == _grid->dlg())
|
|
_grid->on_dbl_cell(rec, DLG_USER);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (rec != grid().selected())
|
|
{
|
|
grid().select(rec);
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask::on_key(k);
|
|
}
|
|
|
|
void TGrid_mask::handler(WINDOW win, EVENT* ep)
|
|
{
|
|
static TGrid_field* _last_grid = NULL;
|
|
|
|
if (ep->type == E_MOUSE_DOWN && ep->v.mouse.button == 1)
|
|
{
|
|
_last_grid = NULL;
|
|
|
|
RCT rct; _grid->get_rect(rct);
|
|
if (xvt_rect_has_point(&rct, ep->v.mouse.where))
|
|
_last_grid = _grid;
|
|
|
|
if (_last_grid)
|
|
{
|
|
TGrid_field& sht = (TGrid_field&)*_last_grid;
|
|
#if (XVT_PTK_VERSION_MAJOR > 4) || (XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50)
|
|
MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
|
|
if (menu)
|
|
{
|
|
const PNT& p = ep->v.mouse.where;
|
|
RCT cr; xvt_vobj_get_client_rect(win, &cr);
|
|
XVT_POPUP_ALIGNMENT pa = XVT_POPUP_CENTER;
|
|
if (p.h < cr.right / 3)
|
|
pa = XVT_POPUP_LEFT_ALIGN;
|
|
else
|
|
if (p.h > 2 * cr.right / 3)
|
|
pa = XVT_POPUP_RIGHT_ALIGN;
|
|
|
|
xvt_menu_popup(menu->child, win, p, pa, NULL);
|
|
xvt_res_free_menu_tree(menu);
|
|
}
|
|
#else
|
|
ASK_RESPONSE r = xvt_dm_post_ask(TR("Annulla"), TR("Ripristina"), TR("Salva"),
|
|
TR("Ordinamento delle colonne"));
|
|
if (r == RESP_2)
|
|
sht.reset_columns_order();
|
|
if (r == RESP_2 || r == RESP_3)
|
|
sht.save_columns_order();
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
if (ep->type == E_COMMAND)
|
|
{
|
|
if (_last_grid)
|
|
{
|
|
switch (ep->v.cmd.tag)
|
|
{
|
|
case M_EDIT_UNDO:
|
|
_last_grid->reset_columns_order();
|
|
case M_EDIT_COPY:
|
|
_last_grid->save_columns_order();
|
|
break;
|
|
case M_EDIT_SEARCH:
|
|
_last_grid->on_key(K_F11);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
TMask::handler(win, ep);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TQuery_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TQuery_mask : public TMask
|
|
{
|
|
protected:
|
|
static bool esercizio_handler(TMask_field& f, KEY k);
|
|
static bool data_handler(TMask_field& f, KEY k);
|
|
static bool find_handler(TMask_field& f, KEY k);
|
|
|
|
public:
|
|
void do_query(TGrid_mask& gm);
|
|
|
|
TQuery_mask();
|
|
virtual ~TQuery_mask() { }
|
|
};
|
|
|
|
TQuery_mask::TQuery_mask()
|
|
: TMask("cg3600a")
|
|
{
|
|
set_handler(F_ESERCIZIO, esercizio_handler);
|
|
set_handler(F_DADATA, data_handler);
|
|
set_handler(F_ADATA, data_handler);
|
|
set_handler(DLG_FINDREC, find_handler);
|
|
}
|
|
|
|
bool TQuery_mask::esercizio_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_TAB && f.focusdirty())
|
|
{
|
|
TEsercizi_contabili esc;
|
|
const int anno = atoi(f.get());
|
|
if (esc.exist(anno))
|
|
{
|
|
TMask& m = f.mask();
|
|
TDate dd = m.get(F_DADATA);
|
|
if (esc.date2esc(dd) != anno)
|
|
m.set(F_DADATA, esc[anno].inizio());
|
|
dd = m.get(F_ADATA);
|
|
if (esc.date2esc(dd) != anno)
|
|
m.set(F_ADATA, esc[anno].fine());
|
|
}
|
|
else
|
|
{
|
|
if (anno > 0)
|
|
return error_box(FR("Esercizio inesistente: %d"), anno);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TQuery_mask::data_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = TRUE;
|
|
if (k == K_ENTER)
|
|
{
|
|
const TQuery_mask& qm = (const TQuery_mask&)f.mask();
|
|
const TEsercizi_contabili esercizi;
|
|
int codice_esercizio = qm.get_int(F_ESERCIZIO);
|
|
|
|
if (codice_esercizio == 0)
|
|
{
|
|
const short id_altra_data = f.dlg() == F_DADATA ? F_ADATA : F_DADATA;
|
|
const TDate d = qm.get(id_altra_data);
|
|
if (d.ok())
|
|
codice_esercizio = esercizi.date2esc(d);
|
|
}
|
|
|
|
if (f.empty())
|
|
{
|
|
if (codice_esercizio == 0)
|
|
return error_box(TR("E' necessario specificare almeno una data."));
|
|
return TRUE;
|
|
}
|
|
|
|
const TDate d = f.get();
|
|
const int esercizio = esercizi.date2esc(d);
|
|
if (codice_esercizio != 0)
|
|
{
|
|
if (esercizio != codice_esercizio)
|
|
ok = error_box(FR("La data deve appartenere all'esercizio %d"), codice_esercizio);
|
|
}
|
|
else
|
|
{
|
|
if (esercizio == 0)
|
|
ok = error_box(TR("La data deve appartenere ad un esercizio contabile"));
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TQuery_mask::find_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
const TQuery_mask& qm = (const TQuery_mask&)f.mask();
|
|
short id;
|
|
switch (qm.get(F_TIPO)[0])
|
|
{
|
|
case 'C': id = F_CLIENTE; break;
|
|
case 'F': id = F_FORNITORE; break;
|
|
default : id = F_SOTTOCONTO; break;
|
|
}
|
|
qm.field(id).on_key(K_F9);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TQuery_mask::do_query(TGrid_mask& gm)
|
|
{
|
|
const char t = get(F_TIPO)[0];
|
|
const int g = get_int(F_GRUPPO);
|
|
const int c = get_int(F_CONTO);
|
|
const long s = get_long((t <= ' ') ? F_SOTTOCONTO : ((t == 'C') ? F_CLIENTE : F_FORNITORE));
|
|
const TBill conto(g, c, s, t);
|
|
|
|
const int annoes = get_int(F_ESERCIZIO);
|
|
const TDate da_data(get(F_DADATA));
|
|
const TDate a_data(get(F_ADATA));
|
|
|
|
const TString& da_caus = get(F_DACAUSALE);
|
|
const TString& a_caus = get(F_ACAUSALE);
|
|
|
|
const bool provv = get_bool(F_PROVVIS);
|
|
|
|
conto.set(gm, F_GRUPPO, F_CONTO, F_SOTTOCONTO, 0, F_DESSOTTOC);
|
|
|
|
gm.grid().read(conto, annoes, da_data, a_data, da_caus, a_caus, provv);
|
|
|
|
gm.run();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrini_video
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TMastrini_video : public TApplication
|
|
{
|
|
TQuery_mask* _qm;
|
|
TGrid_mask* _gm;
|
|
|
|
TArray _file;
|
|
|
|
protected:
|
|
virtual bool create();
|
|
virtual bool destroy();
|
|
virtual bool menu(MENU_TAG);
|
|
virtual void on_firm_change();
|
|
|
|
public:
|
|
|
|
};
|
|
|
|
bool TMastrini_video::create()
|
|
{
|
|
xvt_statbar_set("", TRUE);
|
|
|
|
open_files(LF_RMOV, LF_MOV, LF_CAUSALI, 0);
|
|
open_files(LF_SALDI, LF_PCON, 0);
|
|
|
|
_qm = new TQuery_mask;
|
|
_gm = new TGrid_mask;
|
|
|
|
dispatch_e_menu(BAR_ITEM(1));
|
|
return TRUE;
|
|
}
|
|
|
|
bool TMastrini_video::destroy()
|
|
{
|
|
delete _gm;
|
|
delete _qm;
|
|
|
|
_file.destroy();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TMastrini_video::on_firm_change()
|
|
{
|
|
TEsercizi_contabili::update();
|
|
}
|
|
|
|
bool TMastrini_video::menu(MENU_TAG mt)
|
|
{
|
|
if (mt == BAR_ITEM(1))
|
|
{
|
|
TQuery_mask& qm = *_qm;
|
|
|
|
const TEsercizi_contabili esercizi;
|
|
const int codice_ultimo_esercizio = esercizi.last();
|
|
if (codice_ultimo_esercizio > 0)
|
|
{
|
|
const TEsercizio& esercizio = esercizi.esercizio(codice_ultimo_esercizio);
|
|
qm.set(F_ESERCIZIO, codice_ultimo_esercizio);
|
|
qm.set(F_DADATA, esercizio.inizio());
|
|
qm.set(F_ADATA, esercizio.fine());
|
|
}
|
|
|
|
KEY key = 0;
|
|
while (key != K_QUIT)
|
|
{
|
|
qm.reset(F_SOTTOCONTO); // Azzera sottoconto
|
|
qm.reset(F_CLIENTE); // Azzera cliente
|
|
qm.reset(F_FORNITORE); // Azzera fornitore
|
|
qm.reset(-5); // Azzera causali
|
|
|
|
key = qm.run();
|
|
switch (key)
|
|
{
|
|
case K_ENTER:
|
|
disable_menu_item(M_FONT);
|
|
qm.do_query(*_gm);
|
|
enable_menu_item(M_FONT);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
_gm->grid().set_colors();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Main
|
|
///////////////////////////////////////////////////////////
|
|
|
|
int cg3600(int argc, char* argv[])
|
|
{
|
|
TMastrini_video mv;
|
|
mv.run(argc, argv, TR("Mastrini"));
|
|
return 0;
|
|
}
|
|
|
|
|