campo-sirio/ba/ba0100.cpp
guy db0a1c63c4 Milgiorato cambio ditta conseguente a cambio studio
git-svn-id: svn://10.65.10.50/branches/R_10_00@22948 c028cbd2-c16b-5b4b-a496-9718f37d4682
2014-05-16 12:59:16 +00:00

2438 lines
61 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <automask.h>
#include <controls.h>
#include <dongle.h>
#include <execp.h>
#include <recarray.h>
#include <relation.h>
#include <progind.h>
#include <sheet.h>
#include <toolfld.h>
#include <utility.h>
#include <urldefid.h>
#include <nditte.h>
#include <user.h>
#include "ba0.h"
#include "ba0101.h"
#include "ba0102.h"
#include "ba0103.h"
#include "ba0100.h"
#include "ba0100a.h"
#include "ba0400a.h"
#define MEN_FILE "bamenu.men"
#define PREFERRED_MENU M_STYLE
#define DLG_TREE 301
#define DLG_LIST 302
///////////////////////////////////////////////////////////
// TMenu_application declaration
///////////////////////////////////////////////////////////
class TMenu_application : public TSkeleton_application
{
TFilename _menuname;
TMenu _menu;
int _tree_view;
TString_array _preferred;
TMask* _mask;
protected: // TApplication
virtual bool user_create();
virtual bool destroy();
virtual bool menu(MENU_TAG m);
virtual long handler(WINDOW win, EVENT* ep);
virtual bool firm_change_enabled() const;
virtual void on_firm_change();
virtual bool test_assistance_year() const;
bool test_users_file() const;
bool ask_user_password(TString& utente);
protected:
void deconnect_user();
virtual void main_loop();
void test_temp();
int do_level();
// int do_tree(); // Deprecated
int do_explore();
int do_outlook();
int get_user_status(const char* usr) const;
bool set_user_status(const char* usr, int status) const;
bool check_user();
static bool menu_item_handler(TMask_field& f, KEY k);
static bool menu_find_handler(TMask_field& f, KEY k);
static bool tree_handler(TMask_field& f, KEY k);
static bool explore_handler(TMask_field& f, KEY k);
bool choose_colors();
bool choose_editors();
bool choose_study();
void load_preferences();
void save_preferences();
void update_preferred_tree();
void update_preferred();
void add_to_preferred();
void manage_preferred();
bool dongle_update_needed() const;
bool test_programs();
bool copy_setup(const TString& remote_path);
public:
TTree_field& tree_field() const;
void select_tree_current();
static bool tree_find_handler(TMask_field& f, KEY k);
static bool tree_shrink_handler(TMask_field& f, KEY k);
public:
void reload_images();
TMenu& main_menu() { return _menu; }
TMenu_application(const char* name);
};
inline TMenu_application& app()
{ return (TMenu_application&)main_app(); }
///////////////////////////////////////////////////////////
// Picture Mask
///////////////////////////////////////////////////////////
class TPicture_mask : public TMask
{
TSubmenu* _submenu;
TImage* _logo;
protected: // TMask
virtual void update();
virtual bool on_key(KEY k);
virtual void on_firm_change();
public:
virtual bool stop_run(KEY key);
void set_current(const TSubmenu& sm);
TPicture_mask(const char* name, int dx, int dy, const TSubmenu& sm, int x = -1, int y = -1);
virtual ~TPicture_mask();
};
bool TPicture_mask::stop_run(KEY key)
{
if (key == K_FORCE_CLOSE)
key = K_QUIT;
return TWindow::stop_run(key);
}
void TPicture_mask::update()
{
if (!ADVANCED_GRAPHICS)
return;
RCT client; xvt_vobj_get_client_rect(win(), &client);
RCT lgo = client, img = client;
const bool tree_view = id2pos(DLG_TREE) >= 0;
if (tree_view) // TreeView == 1
{
RCT tree; tfield(DLG_TREE).get_rect(tree);
lgo.left = tree.right; lgo.bottom /= 3;
img.left = tree.right; img.top = lgo.bottom; img.bottom = 2*lgo.bottom;
}
else
{
RCT but; field(101).get_rect(but);
lgo.right = but.left; lgo.bottom /= 2;
img.right = but.left; img.top = lgo.bottom;
}
if (_logo != NULL)
{
xvt_rect_inflate(&lgo, -CHARX, -CHARX);
_logo->draw(win(), lgo, 'C', 'T', '-');
}
const TImage& image = _submenu->image();
if (image.ok())
{
xvt_rect_inflate(&img, -CHARX, -CHARX);
image.draw(win(), img, 'C', 'C', '-');
}
}
bool TPicture_mask::on_key(KEY k)
{
switch (k)
{
case K_F3:
case K_F8:
set(DLG_USER, app().main_menu().last_search_string(), true);
return true;
default:
break;
}
return TMask::on_key(k);
}
void TPicture_mask::on_firm_change()
{
force_update();
}
void TPicture_mask::set_current(const TSubmenu& sm)
{
_submenu = (TSubmenu*)&sm;
}
TPicture_mask::TPicture_mask(const char* name, int dx, int dy,
const TSubmenu& submenu, int x, int y)
: TMask(name, 1, dx, dy, x, y), _submenu(NULL), _logo(NULL)
{
set_current(submenu);
//trova il logo corretto in base al producer
const TString& currlogo = get_logo();
_logo = new TImage(currlogo);
if (_logo->ok())
{
if (can_be_transparent(*_logo))
_logo->convert_transparent_color(MASK_BACK_COLOR);
}
else
{
delete _logo;
_logo = NULL;
}
}
TPicture_mask::~TPicture_mask()
{
if (_logo != NULL)
delete _logo;
}
///////////////////////////////////////////////////////////
// Color Mask
///////////////////////////////////////////////////////////
class TColor_mask : public TAutomask
{
class TPreview_panel : public TWindow
{
TColor_mask* _owner;
protected:
COLOR get_color_entry(const char* name) const;
virtual void update();
virtual PNT log2dev(long x, long y) const { PNT p = { short(ROWY*y), short(CHARX*x) }; return p; }
virtual void log2dev(const TRectangle& rctl, RCT& r) const
{
r.left = short(rctl.x*CHARX);
r.top = short(rctl.y*ROWY);
r.right = short(r.left + rctl.width()*CHARX);
r.bottom = short(r.top + rctl.height()*ROWY);
if (rctl.height() > 0)
r.bottom -= ROWY-CHARY;
}
public:
TPreview_panel(short x, short y, short dx, short dy, TColor_mask* owner);
} *_preview;
class TPreview_icons : public TWindow
{
TColor_mask* _owner;
protected:
virtual void update();
public:
TPreview_icons(short x, short y, short dx, short dy, TColor_mask* owner);
} *_icons;
int _cur_theme;
TAssoc_array _color;
protected: // TMask
virtual bool stop_run(KEY key) { return TWindow::stop_run(key); }
virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly);
TProp_field& colors_field() const;
TProp_field& options_field() const;
void colors2mask();
void mask2colors();
void options2mask();
void mask2options();
void enable_options();
protected:
COLOR get_color_entry(const char* c) const;
void set_color_entry(const char* name, COLOR col);
const TString& get_font_desc() const;
void set_font_desc(const TString& fd);
const char* cid2name(short cid) const;
COLOR cid2color(short cid) const;
COLOR cid2syscolor(short cid, const XVT_COLOR_COMPONENT* cc) const;
bool find_themes_ini(TFilename& ininame) const;
void load_themes();
bool apply_theme();
void save_colors(TConfig& colors);
public:
void save_colors();
TColor_mask();
};
COLOR TColor_mask::TPreview_panel::get_color_entry(const char* name) const
{ return _owner->get_color_entry(name); }
TColor_mask::TPreview_panel::TPreview_panel(short x, short y, short dx, short dy, TColor_mask* owner)
: _owner(owner)
{ create(x, y, dx, dy, "", 0, W_PLAIN, owner->page_win(0)); }
void TColor_mask::TPreview_panel::update()
{
COLOR p, b;
const int x = 0;
const int y = 0;
const int w = columns();
const int h = rows();
b = get_color_entry("MaskBack");
clear(b);
set_pen(p = get_color_entry("MaskLight"));
line(x+1, y, x+w-2, y);
line(x+1, y, x+1, y+h-1);
set_pen(p = get_color_entry("MaskDark"));
line(x+1, y+h-1, x+w-2, y+h-1);
line(x+w-2, y+h-1, x+w-2, y);
const TString& font_desc = _owner->get_font_desc();
if (font_desc.full())
{
XVT_FNTID fontid = xvt_font_create();
xvt_font_deserialize(fontid, font_desc);
xvt_dwin_set_font(win(), fontid);
xvt_font_destroy(fontid);
}
else
xvt_dwin_set_font(win(), xvtil_default_font());
set_opaque_text(false);
p = get_color_entry("Prompt");
b = get_color_entry("MaskBack");
set_color(p, b);
stringat(x+4, y+0, TR("Prompt"));
set_pen(p = get_color_entry("Normal"));
set_brush(b = get_color_entry("NormalBack"));
frame(x+3, y+1, x+w-3, y+2, 0);
set_color(p, b);
stringat(x+4, y+1, TR("Campo normale"));
set_pen(p = get_color_entry("Normal")); // Stesso inchiostro del normale
set_brush(b = get_color_entry("RequiredBack"));
frame(x+3, y+2, x+w-3, y+3, 0);
set_color(p, b);
stringat(x+4, y+2, TR("Campo obbligatorio"));
set_pen(p = get_color_entry("Focus"));
set_brush(b = get_color_entry("FocusBack"));
frame(x+3, y+3, x+w-3, y+4, 0);
set_color(p, b);
stringat(x+4, y+3, TR("Campo attivo"));
set_pen(p = get_color_entry("Disabled"));
set_brush(b = get_color_entry("DisabledBack"));
frame(x+3, y+4, x+w-3, y+5, 0);
set_color(p, b);
stringat(x+4, y+4, TR("Campo disabilitato"));
set_pen(p = get_color_entry("ButtonLight"));
set_brush(b = get_color_entry("ButtonBack"));
frame(x+3, y+5, x+w-3, y+6, 0);
set_color(get_color_entry("Normal"), b);
stringat(x+4, y+5, TR("Bottone normale"));
}
void TColor_mask::TPreview_icons::update()
{
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
clear(MASK_BACK_COLOR);
set_pen(MASK_DARK_COLOR);
xvt_dwin_draw_rect(win(), &rct);
const int s = _owner->get_int(218);
const int sz = 16 + s*8;
const int y = (rct.bottom - sz)/2;
int x = (rct.right - 3*sz)/2;
for (short id = 201; id <= 203; id++, x += sz)
xvt_dwin_draw_tool(win(), x, y, id, sz);
}
TColor_mask::TPreview_icons::TPreview_icons(short x, short y, short dx, short dy, TColor_mask* owner)
: _owner(owner)
{ create(x, y, dx, dy, "", 0, W_PLAIN, owner->page_win(1)); }
void TColor_mask::load_themes()
{
TList_field& fl = lfield(211);
TToken_string codes = fl.get_codes();
TToken_string values = fl.get_values();
const int default_items = 3; // Corrente, Tradizionale, Sistema
// Elimina tutti gli elementi non standard (oltre il terzo)
if (codes.items() > default_items)
{
for (int i = 0; i < 2; i++)
{
TToken_string& str = i == 0 ? codes : values;
int pos = 0;
for (int j = 0; j < default_items; j++)
pos = str.find(str.separator(), pos);
str.cut(pos);
}
}
int k = codes.items();
TFilename ininame; find_themes_ini(ininame);
TConfig default_themes(ininame);
TString_array pl;
default_themes.list_paragraphs(pl);
FOR_EACH_ARRAY_ROW(pl, i, row)
{
codes.add(k++);
values.add(row->left(15));
}
TConfig user_themes(CONFIG_GUI, "Colors");
user_themes.list_paragraphs(pl);
FOR_EACH_ARRAY_ROW(pl, j, raw)
{
if (raw->starts_with("Theme_"))
{
codes.add(k++);
values.add(raw->mid(6, 15));
}
}
if (k > default_items)
fl.replace_items(codes, values);
}
bool TColor_mask::find_themes_ini(TFilename& ininame) const
{
ininame = get_oem_info("Themes");
bool ok = ininame.full();
if (ok)
{
ininame.insert("setup/");
ok = ininame.exist();
if (!ok)
{
ininame = "res/themes.ini"; // Compatibility mode
ok = ininame.exist();
}
}
return ok;
}
void TColor_mask::colors2mask()
{
TProp_field& pg = colors_field();
pg.freeze(true);
FOR_EACH_ASSOC_STRING(_color, h, key, color)
{
const TFixed_string str(color);
if (str.find(',') > 0) // E' una proprieta' colore?
pg.set_property(key, color);
}
pg.freeze(false);
_preview->force_update();
}
void TColor_mask::mask2colors()
{
const TProp_field& pg = colors_field();
FOR_EACH_ASSOC_STRING(_color, h, key, color)
{
const TFixed_string str(color);
if (str.find(',') > 0) // E' una proprieta' colore?
{
const COLOR rgb = pg.get_color_property(key);
if (rgb != COLOR_INVALID)
set_color_entry(key, rgb);
}
}
_preview->force_update();
}
TProp_field& TColor_mask::colors_field() const
{ return (TProp_field&)field(212); }
TProp_field& TColor_mask::options_field() const
{ return (TProp_field&)field(213); }
bool TColor_mask::apply_theme()
{
bool applied = false;
const int theme = get_int(211);
if (theme > 2) // Normal theme
{
const TList_field& fl = lfield(211);
TToken_string values = fl.get_values();
TString name = values.get(theme);
TFilename thini; find_themes_ini(thini);
TConfig def_themes(thini, name);
TAssoc_array& def_colors = def_themes.list_variables();
name.insert("Theme_");
TConfig usr_themes(CONFIG_GUI, name);
TAssoc_array& usr_colors = usr_themes.list_variables();
TAssoc_array& colors = usr_colors.empty() ? def_colors : usr_colors;
if (!colors.empty())
{
_color = colors;
FOR_EACH_MASK_FIELD((*this), i, f)
{
const TFieldref* fr = f->field();
if (fr != NULL)
{
const TString* val = (const TString*)_color.objptr(fr->name());
if (val != NULL)
f->set(*val);
}
}
applied = true;
}
}
if (!applied)
{
switch (theme)
{
case 1: // Campo default colors
{
for (short bid = 101; bid <= 114; bid++)
{
const char* name = cid2name(bid);
const COLOR color = cid2color(bid);
set_color_entry(name, color);
}
set_font_desc("");
applied = true;
}
break;
case 2: // System colors
{
const XVT_COLOR_COMPONENT* cc = (XVT_COLOR_COMPONENT*)xvt_vobj_get_attr(NULL_WIN, ATTR_APP_CTL_COLORS);
for (short bid = 101; bid <= 114; bid++)
{
const char* name = cid2name(bid);
const COLOR color = cid2syscolor(bid, cc);
set_color_entry(name, color);
}
xvt_mem_free((DATA_PTR)cc);
XVT_FNTID defont = xvtil_default_font(false, false); // Legge il font standard
XVT_FNTID fontid = xvt_res_get_font(0); // Legge il font di sistema
xvt_font_set_size(fontid, xvt_font_get_size(defont)); // Forza l'altezza standard
TString256 fd; xvt_font_serialize(fontid, fd.get_buffer(), fd.size());
set_font_desc(fd);
xvt_font_destroy(fontid); // Rilascia il font di sistema
TProp_field& pf = options_field();
pf.set_property("Campi3D", true);
pf.set_property("NativeControls", true);
applied = true;
}
break;
default: // User defined settings
{
TConfig color(CONFIG_GUI, "Colors");
_color = color.list_variables();
}
break;
}
}
if (applied)
_cur_theme = theme;
colors2mask();
return applied;
}
bool TColor_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{
const short id = f.dlg();
bool ok = true;
switch (id)
{
case 211:
if (e == fe_init)
load_themes();
if (e == fe_modify && is_running())
{
const int new_theme = atoi(f.get());
if (new_theme != _cur_theme)
apply_theme();
}
break;
case DLG_OK:
if (e == fe_button)
{
stop_run(K_CTRL+'R');
return false;
}
break;
case DLG_SAVEREC:
if (e == fe_button)
{
stop_run(K_ENTER);
return false;
}
break;
case DLG_NEWREC:
if (e == fe_button)
{
TString80 name = user();
xvt_dm_post_string_prompt(TR("Nome del tema"), name.get_buffer(), 16);
if (name.full())
{
name.trim();
name.upper();
name.insert("Theme_");
{
TConfig ini(CONFIG_GUI, name);
save_colors(ini);
}
load_themes();
}
return false;
}
break;
case DLG_DELREC:
if (e == fe_button)
{
TList_field& themes = lfield(211);
const int pos = atoi(themes.get());
bool can_delete = pos > 2;
if (can_delete) // Tema non standard
{
TToken_string values = themes.get_values();
TString name = values.get(pos);
bool done = yesno_box(FR("Confermare la cancellazione del tema %s"), name.get_buffer());
if (done)
{
name.insert("Theme_");
TConfig ini(CONFIG_GUI, name);
if (ini.new_paragraph())
done = can_delete = false;
else
ini.remove_all();
}
if (done)
load_themes();
}
if (!can_delete)
error_box(TR("Tema non cancellabile"));
return false;
}
break;
case DLG_USER:
if (e == fe_button)
{
XVT_FNTID fontid = xvt_font_create();
TString256 fd = get_font_desc();
if (fd.full())
xvt_font_deserialize(fontid, fd);
else
xvt_font_copy(fontid, xvtil_default_font(), XVT_FA_ALL);
if (xvt_dm_post_font_sel(win(), fontid, NULL, 0))
{
xvt_font_serialize(fontid, fd.get_buffer(), fd.size());
set_font_desc(fd);
_preview->force_update();
}
xvt_font_destroy(fontid);
return false;
}
break;
case 212:
if (e == fe_init)
colors2mask(); else
if (e == fe_modify)
mask2colors();
break;
case 213:
if (e == fe_init)
options2mask(); else
if (e == fe_modify)
{
mask2options();
enable_options();
}
break;
case 218:
if (e == fe_init || e == fe_modify)
_icons->force_update();
break;
default:
break;
}
return ok;
}
void TColor_mask::enable_options()
{
TProp_field& pf = options_field();
pf.freeze(true);
const bool ag = pf.get_bool_property("AdvancedGraphics");
pf.enable_property("Campi3D", ag);
pf.enable_property("NativeControls", ag);
if (is_power_reseller())
pf.enable_property("AnimatedBoxes", ag);
else
pf.remove_property("AnimatedBoxes");
pf.freeze(false);
}
void TColor_mask::options2mask()
{
TProp_field& pf = options_field();
pf.freeze(true);
FOR_EACH_ASSOC_STRING(_color, obj, key, str) if (pf.has_property(key))
pf.set_property(key, str);
pf.freeze(false);
set(216, _color.get_int("TreeView"));
set(217, _color.get_int("InterLine"));
const int sz = _color.get_int("ToolSize");
set(218, (sz-16)/8);
enable_options();
}
void TColor_mask::mask2options()
{
TString4 val;
TProp_field& pf = options_field();
TVariant var;
FOR_EACH_ASSOC_STRING(_color, obj, key, str) if (pf.get_var_property(key, var))
{
if (var.is_bool())
{
val = var.as_bool() ? "X" : "";
_color.add(key, val, true);
}
}
val.cut(0) << get_int(216);
_color.add("TreeView", val, true);
val.cut(0) << get_int(217);
_color.add("InterLine", val, true);
val.cut(0) << (16+get_int(218)*8);
_color.add("ToolSize", val, true);
}
TColor_mask::TColor_mask()
: TAutomask("ba0200a"), _cur_theme(0)
{
TConfig color(CONFIG_GUI, "Colors");
_color = color.list_variables();
_preview = new TPreview_panel(1, 12, -1, -1, this);
_icons = new TPreview_icons(1, 14, -2, -1, this);
}
void TColor_mask::save_colors(TConfig& colors)
{
mask2options(); // Si assicura che venga trasferito anche ToolSize, che non e' nel TPropField
FOR_EACH_ASSOC_STRING(_color, obj, key, str)
colors.set(key, str);
}
void TColor_mask::save_colors()
{
TConfig colors(CONFIG_GUI, "Colors");
save_colors(colors);
TMenuitem::always_run_fullscreen(colors.get_bool("RunModal"));
}
const TString& TColor_mask::get_font_desc() const
{ return _color.get_str("FontDesc"); }
COLOR TColor_mask::get_color_entry(const char* name) const
{
COLOR c = COLOR_INVALID;
const TString& s = _color.get_str(name);
if (s.full())
{
TToken_string colore(s, ',');
const byte r = (byte)colore.get_int();
const byte g = (byte)colore.get_int();
const byte b = (byte)colore.get_int();
c = RGB2COLOR(r, g, b);
}
return c;
}
void TColor_mask::set_color_entry(const char* name, COLOR col)
{
TString* s = (TString*)_color.objptr(name);
if (s == NULL)
{
s = new TString(15);
_color.add(name, s);
}
s->format("%d,%d,%d", XVT_COLOR_GET_RED(col), XVT_COLOR_GET_GREEN(col), XVT_COLOR_GET_BLUE(col));
}
void TColor_mask::set_font_desc(const TString& fd)
{ _color.add("FontDesc", fd, true); }
const char* TColor_mask::cid2name(short cid) const
{
const int colors = 14;
const char* name[colors] = { "MaskBack", "MaskLight", "MaskDark",
"Normal", "NormalBack", "RequiredBack",
"Focus", "FocusBack",
"Disabled", "DisabledBack",
"ButtonBack", "ButtonLight", "ButtonDark",
"Prompt" };
const int i = cid < DLG_USER ? cid : cid - 101;
CHECK(i >= 0 && i < colors, "Invalid color id");
return name[i];
}
COLOR TColor_mask::cid2color(short cid) const
{
COLOR color[] = { XVT_MAKE_COLOR(201,194,188), COLOR_WHITE, COLOR_GRAY,
COLOR_BLACK, COLOR_WHITE, blend_colors(COLOR_WHITE, COLOR_YELLOW, 0.60),
COLOR_BLACK, COLOR_YELLOW,
COLOR_DKGRAY, COLOR_LTGRAY,
COLOR_LTGRAY, COLOR_WHITE, COLOR_GRAY,
COLOR_BLACK };
const int i = cid < DLG_USER ? cid : cid - 101;
CHECK(i >= 0 && i < 14, "Invalid color id");
return color[i];
}
COLOR TColor_mask::cid2syscolor(short cid, const XVT_COLOR_COMPONENT* cc) const
{
int entry[] = { XVT_COLOR_BACKGROUND, XVT_COLOR_BLEND, XVT_COLOR_BORDER,
XVT_COLOR_FOREGROUND, XVT_COLOR_BACKGROUND, XVT_COLOR_BACKGROUND,
XVT_COLOR_HIGHLIGHT, XVT_COLOR_SELECT,
XVT_COLOR_BLEND, XVT_COLOR_BORDER,
XVT_COLOR_BACKGROUND, XVT_COLOR_BLEND, XVT_COLOR_BORDER,
XVT_COLOR_FOREGROUND
};
const unsigned int component = entry[cid < DLG_USER ? cid : cid-101];
for (int i = 0; cc[i].type != XVT_COLOR_NULL; i++) if (cc[i].type == component)
{
switch (cid)
{
case 105: return COLOR_WHITE;
case 106: return blend_colors(cid2syscolor(105, cc), cid2syscolor(108, cc), 0.60);
default : return cc[i].color;
}
}
return COLOR_BLACK;
}
///////////////////////////////////////////////////////////
// Menu application
///////////////////////////////////////////////////////////
bool TMenu_application::test_assistance_year() const
{ return true; }
bool TMenu_application::menu_item_handler(TMask_field&f, KEY k)
{
if (k == K_SPACE)
{
app()._menu.select(f.dlg()-101);
f.set_focusdirty(false);
return f.mask().stop_run(K_AUTO_ENTER);
}
return true;
}
bool TMenu_application::menu_find_handler(TMask_field&f, KEY k)
{
if (k == K_TAB && f.focusdirty() && !f.empty())
{
const TString& v = f.get();
if (app()._menu.find_string(v))
{
f.set_focusdirty(false);
return f.mask().stop_run(K_F9);
}
else
{
beep();
return false;
}
}
return true;
}
int TMenu_application::do_level()
{
const TSubmenu& curr = _menu.current();
const int bwidth = 20;
TPicture_mask mask(curr.caption(), 0, 0, curr, 0, 0);
CHECK(_mask == NULL, "Two masks are better than one?");
_mask = &mask;
const int ampiezza = 51;
const int margin = (mask.columns()-80) / 2;
const int x = mask.columns() - ampiezza - margin;
int y = 1;
TString caption;
for (int i = 0; i < curr.items() && i < 16; i++, y++)
{
const TMenuitem& item = curr[i];
caption = item.caption();
if (item.is_submenu() && caption.right(3) != "...")
caption << "...";
mask.add_static(-1, 0, caption, x+4, y);
const short id = 100+y;
const int bmp = item.is_submenu() ? BMP_DIRDN: BMP_STOPREC;
mask.add_button(id, 0, "", x, y, 1, 1, "", bmp);
mask.set_handler(id, menu_item_handler);
if (item.disabled())
mask.disable(id);
}
mask.add_static(DLG_NULL, 0, PR("Cerca"), x, -4);
TEdit_field& ef = mask.add_string(DLG_USER, 0, "", x, -3, 50, "", ampiezza - 2);
ef.set_handler(menu_find_handler);
const int bottone = ampiezza / 3;
const int spazio = (ampiezza - bottone * 2) / 3;
const bool top = _menu.at_top();
mask.add_button(DLG_QUIT, 0, PR("Fine"), x + spazio, -1, bottone, 2);
if (!top)
mask.add_button(DLG_CANCEL, 0, PR("Menu precedente"), x + spazio * 2 + bottone, -1, bottone, 2);
mask.first_focus(101+_menu.selected());
const int k = mask.run();
int m = 0;
switch (k)
{
case K_ESC:
_menu.pop();
m = -1;
break;
case K_QUIT:
mask.reset();
m = -2;
break;
case K_F9:
case K_CTRL+'R':
m = 0;
break;
default:
m = _menu.selected() + 1; // Sempre > 0
break;
}
// Azzero solo ora altrimenti il menu normale crede di non poter fare il cambio ditta
_mask = NULL;
return m;
}
void TMenu_application::test_temp()
{
TFilename dir; dir.tempdir(); // Directory temporanea
dir.add("*");
TString_array files;
const int count = ::list_files(dir, files);
if (count > 0 && yesno_box(TR("Cancellare tutti i file temporanei in %s?"), dir.path()))
{
TProgress_monitor bar(count, TR("Cancellazione file temporanei"));
for (int i = count-1; i >= 0 && bar.add_status(); i--)
{
const char* e = files.row(i);
::remove(e);
}
}
}
HIDDEN bool pwd_handler(TMask_field& fld, KEY key)
{
if (key == K_F8)
{
TMask& m = fld.mask();
TString pwd;
TString usr = dongle().administrator(&pwd);
TLocalisamfile users(LF_USER);
users.put(USR_USERNAME, usr);
users.read();
pwd = decode(users.get(USR_PASSWORD));
m.set(F_USER, usr);
m.set(F_PASSWORD, pwd);
m.stop_run(K_ENTER);
}
return true;
}
HIDDEN bool user_mask_handler(TMask& mask, KEY key)
{
if (key == K_ENTER)
mask.stop_run(key);
return true;
}
void TMenu_application::reload_images()
{
_menu.reload_images();
}
bool TMenu_application::test_users_file() const
{
bool ok = prefix_valid();
if (ok)
{
TSystemisamfile users(LF_USER);
ok = users.open_ex() == NOERR;
if (ok)
users.close();
}
return ok;
}
bool TMenu_application::ask_user_password(TString& utente)
{
bool ok = false;
// Disabilita le voci di personalizzazione
enable_options_menu(false);
if (!test_users_file())
{
error_box(TR("Non e' possibile accedere al file degli utenti: necessita manutenzione"));
TExternal_app app("ba1 -0");
app.run(true, 1, false);
return ok; // False
}
TMask m("ba0100a");
m.set_handler(user_mask_handler);
if (is_power_station())
{
m.set_handler(F_USER, pwd_handler);
m.set_handler(F_PASSWORD, pwd_handler);
}
m.set(F_USER, utente);
m.first_focus(F_PASSWORD);
TEdit_field& e = m.efield(F_USER);
e.browse()->set_filter("ISGROUP!=\"X\"");
TLocalisamfile& users = e.browse()->cursor()->file();
TString pwd;
for (int i = 0; i < 3 && !ok; i++)
{
if (utente.not_empty() && utente != dongle().administrator())
{
m.set(F_USER, utente);
m.first_focus(F_PASSWORD);
}
if (m.run() == K_ESC)
break;
utente = m.get(F_USER);
TString pwd;
users.put(USR_USERNAME, utente);
if (users.read() == NOERR)
{
pwd = decode(users.get(USR_PASSWORD));
}
else
{
// Creo l'amministratore se necessario
users.zero();
if (utente == dongle().administrator(&pwd))
{
users.put(USR_USERNAME, utente);
users.put(USR_USERDESC, "Amministratore");
users.put(USR_PASSWORD, encode(pwd));
users.write();
}
else
utente.cut(0);
}
const TString& pass = m.get(F_PASSWORD);
ok = utente.full() && pwd == pass;
if (ok)
{
if (users.get_bool(USR_CONNECTED))
{
ok = yesno_box("%s\n%s",
TR("L'utente risulta essere gi<67> collegato"),
TR("Si desidera continuare ugualmente?"));
}
}
else
{
error_box(TR("Utente e/o password errata: fare attenzione alle maiuscole"));
m.reset(F_PASSWORD);
}
}
if (ok && users.curr().exist(USR_DATAPWD))
{
const long expiration = ini_get_int(CONFIG_STUDIO, "Main", "PasswordExpiration");
bool runba = expiration > 0;
while (runba)
{
runba = users.get(USR_PASSWORD).empty();
if (!runba)
{
const TDate oggi(TODAY);
const TDate datapwd = users.get_date(USR_DATAPWD);
if (datapwd.ok())
runba = expiration < (oggi-datapwd); // Password scaduta
else
{
// Scrivi la data se necessario
users.put(USR_DATAPWD, oggi);
users.rewrite();
}
}
if (runba)
{
warning_box(TR("E' necessario inserire una nuova password"));
user() = utente;
TExternal_app app("ba1 -3");
app.run();
users.reread();
}
}
}
// Abilita le voci di personalizzazione
enable_options_menu(true);
return ok;
}
// Testa stato utente: 0 inesistente; 1 = esiste; 2 connesso; 4 conversione in corso
// ATTENZIONE: non usare mai cache() in ba0!
int TMenu_application::get_user_status(const char* usr) const
{
CHECK(usr && *usr, "Utente nullo");
int status = 0;
if (test_users_file())
{
TLocalisamfile utonti(LF_USER);
utonti.put(USR_USERNAME, usr);
status = utonti.read() == NOERR;
if (status)
{
if (utonti.get_bool(USR_CONNECTED))
status |= 2;
if (dongle().administrator() == usr && utonti.get(USR_AUTSTR) == "CONVERTING")
status |= 4;
}
}
else
{
// Senza file aperti questo e' il massimo che posso fare
status = dongle().administrator() == usr;
}
return status;
}
bool TMenu_application::set_user_status(const char* usr, int status) const
{
CHECK(usr && *usr, "Utente nullo");
bool ok = false;
if (test_users_file())
{
TLocalisamfile utonti(LF_USER);
utonti.put(USR_USERNAME, usr);
if (utonti.read(_isequal, _lock) == NOERR)
{
utonti.put(USR_CONNECTED, status & 2 ? "X" : "");
ok = utonti.rewrite() == NOERR;
}
}
if (status & 2)
{
// Memorizza utente per riproporlo la prossima volta
TConfig campo_ini(CONFIG_INSTALL, "Main");
campo_ini.set("User", usr);
}
return ok;
}
bool TMenu_application::check_user()
{
bool ok = dongle().type() == _no_dongle;
if (!ok)
{
TString utente = user();
if (_mask == NULL) // Primo login della sessione;
{
TConfig campo_ini(CONFIG_INSTALL, "Main");
const bool use_system_user = campo_ini.get_bool("AutoLogin");
if (use_system_user && test_users_file())
ok = !cache().get(LF_USER, utente).empty();
}
if (!ok)
ok = ask_user_password(utente);
if (ok)
{
const TString& autstr = cache().get(LF_USER, dongle().administrator(), USR_AUTSTR);
if (autstr == "CONVERTING")
{
TString msg; msg << TR("E' in corso una conversione archivi") << ":\n";
if (utente == dongle().administrator())
{
msg << TR("Si desidera continuare ugualmente?");
ok = yesno_box(msg);
}
else
{
msg << TR("Accesso negato.");
ok = error_box(msg);
}
}
if (ok)
{
dongle().logout();
user() = utente;
ok = get_serial_number() >= 0;
if (!ok)
error_box(TR("Probabilmente <20> stato superato il numero massimo di utenti"));
}
if (ok)
set_user_status(utente, 3); // Esistente e connesso (1 | 2 = 3)
}
}
if (ok)
{
set_perms(); // Aggiorna permessi utente
customize_colors(); // Aggiorna set di colori
reload_images(); // Ritrasparentizza immagini e abilitazioni alberi
xvt_dwin_invalidate_rect(TASK_WIN, NULL); // Ridisegna sfondo
load_preferences(); // Aggiorna menu preferiti
test_temp(); // Cancella file temporanei
}
return ok;
}
HIDDEN int compare_version(const char* v1, int p1, const char* v2, int p2)
{
TString16 ver1(v1), ver2(v2);
ver1.trim();
if (ver1.len() == 4)
ver1.insert((v1[0] == '9') ? "19" : "20", 0);
ver2.trim();
if (ver2.len() == 4)
ver2.insert((v2[0] == '9') ? "19" : "20", 0);
int res = ver1.compare(ver2, -1, true);
if (res == 0)
res = p1 - p2;
return res;
}
static int get_module_version(TConfig& cfg, void* jolly)
{
const TString& p = cfg.get_paragraph();
if (p.len() == 2)
{
TAssoc_array& map = *(TAssoc_array*)jolly;
TToken_string* tok = new TToken_string(15);
*tok = cfg.get("Versione");
tok->add(cfg.get("Patch"));
map.add(p, tok);
}
return false;
}
bool TMenu_application::copy_setup(const TString& remote_path)
{
const TFixed_string local_setupdir("setup");
TFilename remote_setupdir = remote_path;
remote_setupdir.add(local_setupdir);
//controlla se esiste la directory;<3B> necessario in quanto se <20> una vecchia 4.0 potrebbe non esserci
bool ok = remote_setupdir.exist();
if (ok)
{
remote_setupdir.add("*.*");
TString_array ar;
list_files(remote_setupdir, ar);
if (!ar.empty())
{
make_dir(local_setupdir);
TFilename strsrc, strdst;
FOR_EACH_ARRAY_ROW (ar, i, row)
{
strsrc = *row;
const TFixed_string n = strsrc.name();
if (n.blank() || n.compare("Thumbs.db", -1, true) == 0)
continue;
strdst = local_setupdir;
strdst.add(n);
//se la copia dei files si inchioda esce
ok = fcopy(strsrc, strdst);
if (!ok)
break;
} //FOR_EACH_ARRAY...
} //if(!ar.empty...
} //if(remote_setupdir...
else
ok = cantread_box(remote_setupdir);
return ok;
}
bool TMenu_application::test_programs()
{
TToken_string dangerous;
int update_needed = 0;
const bool is_client = ini_get_int(CONFIG_INSTALL, "Main", "Type") == 3;
bool sy_needed = false;
TString msg = TR("I seguenti moduli devono essere aggiornati prima dell'utilizzo:\n");
if (is_client)
{
TConfig install("install.ini", "Main");
TFilename remote_name = install.get("DiskPath");
remote_name.add("install.ini");
if (remote_name.exist())
{
TProgind pi(3, TR("Controllo aggiornamento programmi"), false, true);
TConfig remote_install(remote_name, "Main");
remote_install.write_protect();
TAssoc_array my_modules, his_modules;
pi.addstatus(1);
install.for_each_paragraph(get_module_version, &my_modules);
pi.addstatus(1);
remote_install.for_each_paragraph(get_module_version, &his_modules);
pi.addstatus(1);
//giro su tutti i moduli che sono sul server
const TDongle& chiavetta = dongle();
FOR_EACH_ASSOC_STRING(his_modules, h, str_code, str_tok)
{
//per prima cosa controlla se deve aggiornare SY e/o BA
const TString4 code = str_code;
if (code == "sr")
continue; // Un client non pu<70> aggiornare il modulo server!
int module = 0;
if (code != "sy" && code != "ba")
module = chiavetta.module_name2code(code);
if (chiavetta.active(module) && chiavetta.shown(module))
{
//const TString4 code = dongle().module_code2name(module);
TToken_string* mytok = (TToken_string*)my_modules.objptr(code);
TToken_string* histok = (TToken_string*)his_modules.objptr(code);
const TString16 v1 = mytok ? mytok->get(0) : "";
const int p1 = mytok ? mytok->get_int() : 0;
const TString16 v2 = histok ? histok->get(0) : "";
const int p2 = histok ? histok->get_int() : 0;
if (!v1.blank() && compare_version(v1, p1, v2, p2) < 0)
{
// Non disabilitare mai il modulo base! Se non funzionasse qualcosa (vedi anno di assistenza)...
//...non lascierebbe funzionare nulla!!!!
if (module > 0)
dangerous.add(code);
else
{
if (code == "sy")
sy_needed = true;
}
if (msg.len() < 200)
{
TString name;
if (code == "sy")
name = TR("Sistema");
else
name = chiavetta.module_code2desc(module);
if (update_needed > 0)
msg << ", ";
msg << name;
}
else
{
if (msg.right(1) != ".")
msg << ",etc.";
}
update_needed++;
} //if (!v1.blank()...
} //if (chiavetta.active(module...
} //FOR_EACH_ASSOC_STR
} //if(remote_name.exist()...
if (update_needed > 0 && yesno_box(msg))
{
//copia il contenuto della setup del server nella setup del client
if (sy_needed)
{
if (copy_setup(remote_name.path()))
{
//mette il flag di installing
set_installing_flag();
//lancia setup in modalita' aggiornamento client e si suicida! (banzai!!)
TExternal_app app("setup\\SetCmpUp.exe -uc");
app.run(true, 0, false);
}
}
else //lancia l'installazione moduli alla vecchia maniera (e' una vecchia 4.0)
{
TExternal_app app("ba1 -6 /uADMIN");
app.run(true, 0, false);
}
//se lancia un'installazione->esce!!!
return false;
} //(if(update_needed>0...
} //if(is_client..
TString16 module;
TDate expires;
Tdninst dninst;
if (dninst.find_expiring(30, module, expires))
{
TString msg;
msg = TR("L'abilitazione ");
if (module == "*")
msg << TR(" di ") << dongle().product();
else
{
if (module.len() == 2)
msg << TR(" del modulo ") << module;
else
msg << TR(" del programma ") << module;
}
msg << TR(" scadr<64> il ") << expires << TR(":\nsi consiglia di contattare ")
<< dongle().reseller() << '.';
xvt_dm_popup_warning(msg);
}
_menu.set_dangerous_modules(dangerous);
return true;
}
bool TMenu_application::dongle_update_needed() const
{
bool ok = TApplication::test_assistance_year();
if (ok)
{
// Se sono una postazione client verifico l'aggiornamento di dninst.zip
if (xvt_sys_get_session_id() <= 0 && ini_get_int(CONFIG_INSTALL, "Main", "Type") == 3)
{
// Controlla se deve aggiornare il dninst.zip locale da quello del server
const char* const local_name = "setup/dninst.zip";
TFilename remote_name = ini_get_string(CONFIG_GENERAL, "Main", "DiskPath");
remote_name.add(local_name);
if (remote_name.exist())
{
const long remote_date = xvt_fsys_file_attr(remote_name, XVT_FILE_ATTR_MTIME);
const long local_date = xvt_fsys_file_attr(local_name, XVT_FILE_ATTR_MTIME);
if (remote_date > local_date)
::fcopy(remote_name, local_name);
}
}
Tdninst dninst; // file aggiornatissimo ormai ...
const int dninst_year = dninst.assist_year();
const int dongle_year = dongle().year_assist();
ok = dninst_year <= dongle_year;
}
return !ok;
}
bool TMenu_application::user_create()
{
disable_menu_item(M_FILE_PRINT); // Questa voce di menu non serve per ora
disable_menu_item(M_FILE_PREVIEW); // Figuriamoci questa
if (dongle().type() == _no_dongle)
{
if (!yesno_box(TR("ATTENZIONE\nQuesto programma <20> in versione dimostrativa.\n"
"Esso funzionera' con alcune limitazioni sulle registrazioni.\n"
"Si desidera proseguire?")))
return false;
}
else
{
if (dongle_update_needed())
{
TExternal_app app("ba1 -4");
app.run();
}
if (!check_user())
return false;
}
if (!test_programs())
return false;
if (!_menu.ok())
{
TWait_cursor hourglass;
TFilename menu = _menuname;
menu.ext("men");
_menu.read(menu);
update_preferred_tree();
}
return true;
}
void TMenu_application::deconnect_user()
{
if (get_user_status(user()) & 2) // Se e' connesso
set_user_status(user(), 1); // Sconnettilo
}
bool TMenu_application::destroy()
{
deconnect_user();
return true;
}
void TMenu_application::main_loop()
{
bool run = user_create();
while (run)
{
int m = 0;
switch (_tree_view)
{
// case 1: m = do_tree(); break;
case 2: m = do_explore(); break;
case 3: m = do_outlook(); break;
default: m = do_level(); break;
}
if (m > 0)
_menu.perform();
else
run = m >= -1;
if (installing()) //esce dal ciclo se ha lanciato una installazione moduli
break;
}
}
static bool _options_menu_enabled = false;
void enable_options_menu(bool on)
{
_options_menu_enabled = on;
const WINDOW tw = TASK_WIN;
xvt_menu_set_item_enabled(tw, M_FILE_NEW, on); // Cambio ditta
xvt_menu_set_item_enabled(tw, M_FILE_PG_SETUP, on); // Imposta Stampante
for (int i = 2; i <= 7; i++) // Menu opzioni
xvt_menu_set_item_enabled(tw, MENU_ITEM_ID(i), on);
xvt_menu_update(tw);
}
bool TMenu_application::choose_colors()
{
const KEY CTLR = K_CTRL+'R';
enable_options_menu(false);
bool update_needed = false;
KEY key = CTLR;
while (key == CTLR)
{
TColor_mask cm;
key = cm.run();
if (key == K_ENTER || key == CTLR) // Salva o Applica
{
_tree_view = cm.get_int(216); // Aggiorna stile menu
cm.save_colors(); // Aggiorna config
customize_colors(); // Aggiorna set di colori
reload_images(); // Aggiorna bitmaps del menu
// Ridisegna sfondo
TTemp_window tw(TASK_WIN);
tw.force_update();
update_needed = true;
}
}
// Provoca chiusura forzata del menu
if (update_needed && _mask != NULL)
_mask->stop_run(CTLR);
enable_options_menu(true);
return key == K_ENTER;
}
HIDDEN bool browse_file_handler(TMask_field& f, KEY k)
{
bool ok = true;
if (k == K_F9)
{
TFilename n = f.get(); n.ext("exe");
FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(n, &fs);
//DIRECTORY dir; xvt_fsys_get_dir(&dir);
const int err = xvt_dm_post_file_open(&fs, TR("Selezione programma"));
//xvt_fsys_set_dir(&dir);
if (err == FL_OK)
{
xvt_fsys_convert_fspec_to_str(&fs, n.get_buffer(), n.size());
f.set(n);
}
}
if (k == K_TAB && f.focusdirty())
{
TFilename infile(f.get());
if (infile.not_empty())
{
TFilename outfile;
if (!infile.search_in_path(outfile))
{
if (*infile.ext() == '\0')
infile.ext("exe");
if (!infile.search_in_path(outfile))
ok = error_box("Il programma %s non esiste!", (const char*)infile);
}
}
}
return ok;
}
HIDDEN bool link_notify(TSheet_field& s, int r, KEY k)
{
bool ok = true;
if (k == K_INS)
{
ok = s.items() < 29; // Accetta 29 righe al massimo
}
return ok;
}
bool TMenu_application::choose_editors()
{
enable_options_menu(false);
TConfig link(CONFIG_GUI, "Link");
TMask* msk = new TMask("ba0300a");
TMask& m = *msk;
TSheet_field& sheet = m.sfield(201);
sheet.set_notify(link_notify);
TMask& sm = sheet.sheet_mask();
sm.set_handler(102, browse_file_handler);
TAssoc_array& var = (TAssoc_array&)link.list_variables();
FOR_EACH_ASSOC_STRING(var, obj, key, str)
{
TToken_string& row = sheet.row(-1);
if (strlen(key) <= 3)
{
row = key;
row.lower();
row.add(str);
}
}
sheet.rows_array().sort();
if (m.run() == K_ENTER)
{
link.remove_all();
FOR_EACH_SHEET_ROW_BACK(sheet, r, row)
{
TString16 ext = row->get(0);
if (!ext.blank())
{
ext.lower();
TFilename prg = row->get();
link.set(ext, prg);
}
}
}
delete msk;
enable_options_menu(true);
return true;
}
HIDDEN int dir_sort(const TObject** d1, const TObject** d2)
{
const TString& s1 = (const TString&)**d1;
const TString& s2 = (const TString&)**d2;
return xvt_str_compare_ignoring_case(s1, s2);
}
class TStudy_mask : public TAutomask
{
bool is_valid_study(const char* path) const;
void list_studies(TString_array& s, bool count_firms) const;
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TStudy_mask();
};
bool TStudy_mask::is_valid_study(const char* path) const
{
TFilename n = path;
n.add("com/dir.gen");
//return n.find(' ') < 0 && n.exist();
return n.find(' ') < 0 && xvt_fsys_access(n, 0x2) == 0; // NO blanks and write permission
}
void TStudy_mask::list_studies(TString_array& sht, bool firms_count) const
{
TFilename str = firm2dir(-1);
for (int i = str.len()-2; i > 0; i--)
{
if (str[i] == '\\' || str[i] == '/')
{
str.cut(i);
break;
}
}
str.add("*");
SLIST dirs = xvt_fsys_list_files(DIR_TYPE, str, true);
for (SLIST_ELT e = xvt_slist_get_first(dirs); e; e = xvt_slist_get_next(dirs, e))
{
const char* f = xvt_slist_get(dirs, e, NULL);
if (is_valid_study(f))
{
if (firms_count)
{
str = f; str.add("?????A");
SLIST firms = xvt_fsys_list_files(DIR_TYPE, str, true);
const int nf = xvt_slist_count(firms);
xvt_slist_destroy(firms);
if (nf > 0)
{
TToken_string row = f;
row.add(nf);
sht.add(row);
}
}
else
sht.add(f);
}
}
xvt_slist_destroy(dirs);
}
bool TStudy_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case DLG_FINDREC:
if (e == fe_button)
send_key(K_F9, DLG_USER, &o);
break;
case DLG_USER:
if (e == fe_init)
o.set(firm2dir(-1));
if (e == fe_modify || e == fe_close)
{
TFilename s = o.get();
if (e == fe_modify && s.full() && !is_valid_study(s))
{
const TString name = s.name_only();
TString_array std; list_studies(std, false);
TString strBest;
double dBest = 0;
FOR_EACH_ARRAY_ROW(std, i, row)
{
const TFilename study = *row;
const TString& sn = study.name_only();
const double score = xvt_str_fuzzy_compare_ignoring_case(name, sn);
if (score > dBest)
{
strBest = study;
dBest = score;
}
}
if (dBest > 0.75)
o.set(s = strBest);
}
if (!is_valid_study(s))
return error_box("%s %s", (const char*)s, TR("non <20> uno studio valido!"));
}
if (e == fe_button)
{
TArray_sheet sht(-1, -1, 78, 20, TR("Scelta studio"), HR("Studio@70|Ditte"));
list_studies(sht.rows_array(), true);
sht.rows_array().TArray::sort(dir_sort);
if (sht.run() == K_ENTER)
o.set(sht.row(-1).get(0)); // -1 = selected row
}
break;
default:
break;
}
return true;
}
TStudy_mask::TStudy_mask() : TAutomask(TR("Scelta studio"), 1, 60, 3)
{
add_button_tool(DLG_OK, "", TOOL_OK);
add_button_tool(DLG_FINDREC, TR("Ricerca"), TOOL_FINDREC);
add_button_tool(DLG_NULL, "", 0);
add_button_tool(DLG_HELP, TR("Help"), TOOL_HELP);
add_button_tool(DLG_NULL, "", 0);
add_button_tool(DLG_CANCEL, "", TOOL_CANCEL);
add_string(DLG_USER, 0, "", 1, 1, 260, "B", 56);
set_handlers();
}
bool TMenu_application::choose_study()
{
// Disbilita le voci di personalizzazione
enable_options_menu(false);
TStudy_mask m;
bool ok = m.run() == K_ENTER;
if (ok)
{
long ditta = prefix().get_codditta();
if (ditta > 0)
ini_set_int(CONFIG_STUDIO, "Main", "Firm", ditta);
deconnect_user();
prefix().set_studio(m.get(DLG_USER));
ok = check_user();
if (ok)
{
ditta = ini_get_int(CONFIG_STUDIO, "Main", "Firm", 0);
_menu.set_firm(ditta);
_mask->stop_run(K_F9); // Ricarica maschera
}
else
{
dispatch_e_menu(M_FILE_QUIT); // Termina applicazione gracefully
}
}
// Abilita le voci di personalizzazione
enable_options_menu(true);
return ok;
}
long TMenu_application::handler(WINDOW win, EVENT* ep)
{
long ret = TApplication::handler(win, ep);
if (_mask != NULL)
{
switch (ep->type)
{
case E_FONT: // Sono cambiate le opzioni di visualizzazione
_mask->stop_run(K_CTRL + 'R');
break;
case E_PROCESS: // Notifica nascita e morte processi
if (_tree_view == 3)
{
TOutlook_mask& m = (TOutlook_mask&)*_mask;
m.handler(m.win(), ep);
}
break;
case E_SIZE:
if (_tree_view == 3)
{
WINDOW winm = _mask->win();
RCT rctw; xvt_vobj_get_client_rect(win, &rctw);
RCT rctm; xvt_vobj_get_client_rect(winm, &rctm);
if (rctm.right != rctw.right || rctm.bottom != rctw.bottom)
{
xvt_vobj_move(winm, &rctw);
_mask->force_update();
}
}
break;
default:
break;
}
}
return ret;
}
///////////////////////////////////////////////////////////
// Tree view implementation
///////////////////////////////////////////////////////////
bool TMenu_application::tree_handler(TMask_field& f, KEY k)
{
if (k == K_CTRL + K_SPACE)
{
TTree_field& tf = (TTree_field&)f;
TMenu_tree& mt = *(TMenu_tree*)tf.tree();
const TMenuitem& mi = mt.curr_item();
mi.perform();
if (mi.is_submenu())
{
TPicture_mask& pm = (TPicture_mask&)f.mask();
if (mt.expanded())
{
TMenu& menu = mt.curr_submenu().menu();
pm.set_current(menu.current());
}
pm.force_update();
}
}
return true;
}
TTree_field& TMenu_application::tree_field() const
{
CHECK(_tree_view > 0, "No menu tree");
return _mask->tfield(_tree_view == 3 ? 101 : 301);
}
void TMenu_application::select_tree_current()
{
TTree_field& tf = tree_field();
synchronize_tree_field(tf);
tf.set_focus();
}
bool TMenu_application::tree_find_handler(TMask_field&f, KEY k)
{
if (k == K_TAB && f.focusdirty() && !f.empty())
{
const TString& v = f.get();
TTree_field& tf = app().tree_field();
TMenu_tree& mt = *(TMenu_tree*)tf.tree();
if (mt.find_string(v))
app().select_tree_current();
else
beep();
}
return true;
}
bool TMenu_application::tree_shrink_handler(TMask_field&f, KEY k)
{
if (k == K_SPACE)
{
TTree_field& tf = app().tree_field();
TMenu_tree& mt = (TMenu_tree&)*tf.tree();
mt.shrink_all();
mt.goto_root();
app().select_tree_current();
}
return true;
}
void TMenu_application::update_preferred()
{
MENU_ITEM* mm = xvt_menu_get_tree(TASK_WIN);
MENU_ITEM* mi;
for (mi = mm; mi != NULL && mi->tag != 0 && mi->tag != PREFERRED_MENU; mi++);
if (mi == NULL || mi->tag <= 0 || mi->child == NULL)
{
NFCHECK("Can't find Preferiti Menu");
return;
}
const int prefs = min(_preferred.items(), 24);
int i;
MENU_ITEM* pm = (MENU_ITEM*)xvt_mem_zalloc((prefs+4)*sizeof(MENU_ITEM));
memcpy(pm, mi->child, 3*sizeof(MENU_ITEM));
for (i = 0; i < 2; i++)
{
const char* src = mi->child[i].text;
pm[i].text = xvt_str_duplicate(src);
}
xvt_res_free_menu_tree(mi->child);
mi->child = pm;
for (i = -1; i < prefs; i++)
{
MENU_ITEM& m = pm[i+3];
if (i >= 0)
{
m.tag = MENU_ITEM_ID(50+i);
m.enabled = true;
const char* src = _preferred.row(i).get(0);
m.text = xvt_str_duplicate(src);
}
else
{
m.tag = -1;
m.separator = true;
}
}
xvt_menu_set_tree(TASK_WIN, mm);
xvt_menu_update(TASK_WIN);
xvt_res_free_menu_tree(mm);
update_preferred_tree();
}
void TMenu_application::update_preferred_tree()
{
TSubmenu* pref = _menu.find("MENU_PREFERITI");
if (pref != NULL)
{
TToken_string node(16, '.');
pref->destroy_items();
FOR_EACH_ARRAY_ROW(_preferred, i, row)
{
int slash = row->rfind('/');
if (slash < 0)
slash = row->rfind(row->separator());
node = row->mid(slash+1);
if (node.items() == 2)
{
const char* sub = node.get(0);
TSubmenu* sm = _menu.find(sub);
if (sm != NULL)
{
const int num = node.get_int(1);
if (num >= 0 && num < sm->items())
pref->add(new TMenuitem(sm->item(num)));
}
}
}
if (_tree_view == 3 && _mask != NULL)
{
TMask_field& ol = _mask->field(102);
ol.set_focusdirty(false);
ol.on_hit(); // fe_init
}
}
}
void TMenu_application::load_preferences()
{
TConfig cfg(CONFIG_GUI, "ba0");
_preferred.destroy();
for (int i = 0; ; i++)
{
TToken_string row = cfg.get("Preferred", NULL, i);
if (row.empty_items())
break;
_preferred.add(row);
}
update_preferred();
cfg.set_paragraph("Colors");
TMenuitem::always_run_fullscreen(cfg.get_bool("RunModal"));
_tree_view = cfg.get_int("TreeView", NULL, -1, 3);
}
void TMenu_application::save_preferences()
{
TConfig cfg(CONFIG_GUI, "ba0");
int i;
for (i = 0; i < _preferred.items(); i++)
cfg.set("Preferred", _preferred.row(i), NULL, true, i);
cfg.set("Preferred", "", NULL, true, i);
}
void TMenu_application::add_to_preferred()
{
if (_mask == NULL) // Succede durante il login!
return;
const int max_pref = 32; // Massimo numero di preferiti
if (_preferred.items() < max_pref)
{
TToken_string tok;
switch (_tree_view)
{
case 0:
{
const TMask_field& butt = _mask->focus_field();
const int index = butt.dlg() - 101;
if (index >= 0 && index < max_pref)
{
_menu.select(index);
tok = _menu.curr_item().caption();
tok.add(_menu.current().name());
tok << '.' << index;
}
}
break;
case 2:
{
TMenulist_field& mf = (TMenulist_field&)_mask->field(DLG_LIST);
mf.curr_item(tok);
}
break;
default:
{
TTree_field& tf = tree_field();
tf.goto_selected();
if (tf.tree()->has_father()) // Aggiunge solo nodi NON radice
{
tf.tree()->get_description(tok);
TString id; tf.tree()->curr_id(id);
tok.add(id);
}
else
error_box(TR("Non <20> possibile aggiungere voci di primo livello"));
}
break;
}
if (tok.full() && tok.find("MENU_PREFERITI")<0 && _preferred.find(tok)<0)
{
_preferred.add(tok);
save_preferences();
update_preferred();
}
}
else
error_box(TR("Non <20> possibile memorizzare pi<70> di %d preferenze"), _preferred.items());
}
class TPreferred_mask : public TAutomask
{
protected:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TPreferred_mask() : TAutomask("ba0400a") { }
};
bool TPreferred_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_PREF_SHEET:
switch (e)
{
case se_query_add:
return false;
case se_enter:
enable(F_PREF_UP, jolly > 0);
enable(F_PREF_DN, jolly < ((TSheet_field&)o).items()-1);
break;
default:
break;
}
break;
case F_PREF_UP:
if (e == fe_button)
{
TSheet_field& sf = sfield(F_PREF_SHEET);
const int r = sf.selected();
if (r > 0)
{
sf.rows_array().swap(r, r-1);
sf.select(r-1);
sf.force_update();
}
}
break;
case F_PREF_DN:
if (e == fe_button)
{
TSheet_field& sf = sfield(F_PREF_SHEET);
const int r = sf.selected();
if (r < sf.items()-1)
{
sf.rows_array().swap(r, r+1);
sf.select(r+1);
sf.force_update();
}
}
break;
case DLG_DELREC:
if (e == fe_button && jolly == 0) // Main delete button pressed
{
TSheet_field& sf = sfield(F_PREF_SHEET);
const int r = sf.selected();
if (r >= 0)
sf.destroy(r);
return false;
}
break;
default:
break;
}
return true;
}
void TMenu_application::manage_preferred()
{
TPreferred_mask* m = new TPreferred_mask;
TSheet_field& sf = m->sfield(F_PREF_SHEET);
sf.rows_array() = _preferred;
sf.force_update();
if (m->run() == K_ENTER)
{
_preferred = sf.rows_array();
save_preferences();
update_preferred();
}
delete m;
}
/* Deprecated
int TMenu_application::do_tree()
{
_menu.jumpto_root();
const TSubmenu& curr = _menu.current();
TPicture_mask mask(curr.caption(), 0, 0, curr, 0, 0);
CHECK(_mask == NULL, "Two masks are better than one?");
_mask = &mask;
const int margin = (mask.columns()-80) / 2;
const int twidth = mask.columns() - 51;
const int bwidth = (mask.columns() - twidth - 8);
TMenu_tree tree(_menu);
TTree_field& tree_fld = mask.add_tree(DLG_TREE, 0, 0, 0, twidth, -1);
tree_fld.set_tree(&tree);
tree_fld.set_handler(tree_handler);
const int inizio = twidth - margin + 2;
const int ampiezza = mask.columns() - inizio - margin;
const int bottone = ampiezza / 3;
const int spazio = (ampiezza - 2 * bottone) / 3;
mask.add_static(DLG_NULL, 0, PR("Cerca"), inizio + 2, -4);
TEdit_field& ef = mask.add_string(DLG_USER, 0, "", inizio + 2, -3, 50, "", ampiezza - 4);
ef.set_handler(tree_find_handler);
TButton_field& mf = mask.add_button(201, 0, PR("Menu Principale"), inizio + spazio * 2 + bottone, -1, bottone, 2);
mf.set_handler(tree_shrink_handler);
mask.add_button(DLG_QUIT, 0, PR("Fine"), inizio + spazio, -1, bottone, 2);
mask.first_focus(DLG_TREE);
KEY key = mask.run();
_mask = NULL;
return key == K_QUIT ? -2 : 0;
}
*/
int TMenu_application::do_explore()
{
CHECK(_mask == NULL, "Two masks are better than one?");
_menu.jumpto_root();
TExplorer_mask mask(_menu);
_mask = &mask;
KEY key = mask.run();
_mask = NULL;
return key == K_QUIT ? -2 : 0;
}
int TMenu_application::do_outlook()
{
CHECK(_mask == NULL, "Two masks are better than one?");
TOutlook_mask mask(_menu);
_mask = &mask;
KEY key = mask.run();
_mask = NULL;
return key == K_QUIT ? -2 : 0;
}
bool TMenu_application::firm_change_enabled() const
{
bool yes = _mask != NULL || _tree_view == 0; // Impedisci il cambio ditta durante il login
if (yes)
yes &= _options_menu_enabled;
return yes;
}
void TMenu_application::on_firm_change()
{
TConfig cfgs(CONFIG_STUDIO, "Main"); // Forza creazione STUDIO.INI copiandolo eventulamente da PRASSIS.INI
TConfig cfgd(CONFIG_DITTA, "ba"); // Forza creazione DITTA.INI copiandolo eventulamente da PRASSID.INI
}
bool TMenu_application::menu(MENU_TAG mt)
{
bool ok = true;
switch (mt)
{
case BAR_ITEM_ID(1): main_loop(); ok = false; break;
case MENU_ITEM_ID(2): choose_colors(); break;
case MENU_ITEM_ID(3): choose_editors(); break;
case MENU_ITEM_ID(4): choose_study(); break;
case MENU_ITEM_ID(5): add_to_preferred(); break;
case MENU_ITEM_ID(6): manage_preferred(); break;
case MENU_ITEM_ID(7):
if (check_user())
_mask->stop_run(K_CTRL + 'R'); // Ricarica maschera
break;
default:
if (mt >= MENU_ITEM_ID(50) && mt < MENU_ITEM_ID(50+_preferred.items()))
{
bool ok = false;
const int index = mt - MENU_ITEM_ID(50);
TToken_string node(_preferred.row(index).get(1), '/');
if (_tree_view != 0)
{
TMenu_tree& met = *(TMenu_tree*)tree_field().tree();
ok = node.items() == 1 ? met.find_leaf(node) : met.goto_node(node);
if (ok)
{
select_tree_current();
if (met.curr_item().is_program())
tree_field().on_key(K_CTRL+K_SPACE); // Esegue subito il programma
}
}
else
{
TToken_string mi(node.get(-2), '.');
const char* sub = mi.get(0);
TSubmenu* sm = _menu.find(sub);
if (sm && _menu.jumpto(sm))
{
ok = true;
_menu.select(mi.get_int());
_mask->stop_run(K_CTRL + 'R');
}
}
if (!ok)
beep();
}
break;
}
return ok;
}
TMenu_application::TMenu_application(const char* name)
: _menuname(name), _mask(NULL), _tree_view(3)
{ }
int ba0100(int argc, char** argv)
{
if (xvt_vobj_get_attr(NULL_WIN, ATTR_APPL_ALREADY_RUNNING))
return warning_box(TR("Il menu principale <20> gi<67> in esecuzione!"));
TApplication::check_parameters(argc, argv);
TString& u = user();
if (u.blank())
{
TConfig campo_ini(CONFIG_INSTALL, "Main");
const bool su = campo_ini.get_bool("AutoLogin");
if (su) // usa utente di windows
{
xvt_sys_get_user_name(u.get_buffer(), u.size()+1);
u.upper();
if (u.compare("Administrator", -1, true) == 0) // Converti amministratore
u = dongle().administrator();
}
if (u.blank())
u = campo_ini.get("User"); // Ultimo utente usato
if (u.blank())
u = dongle().administrator(); // Usa amministratore come extrema ratio
}
TFilename menu = (argc < 2) ? MEN_FILE : argv[1];
bool ok = menu.custom_path();
if (!ok && argc >= 2)
{
menu = MEN_FILE;
ok = menu.custom_path();
}
if (ok)
{
TMenu_application *ma = new TMenu_application(menu);
ma->run(argc, argv, TR("Menu Principale"));
delete ma;
}
else
cantread_box(menu);
return 0;
}