#include #include #include #include #include #include #include #include #include #include #include #include #include "ba8300.h" #include "ba8301.h" #include /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // TReport_sheet /////////////////////////////////////////////////////////// class TReport_sheet : public TSheet { TReport_section& _section; protected: virtual long get_items() const { return _section.items(); } virtual void get_row(long r, TToken_string& row); public: virtual KEY run(); int selection(int& first, int& last) const; TReport_sheet(TReport_section& sec); }; void TReport_sheet::get_row(long r, TToken_string& row) { const TReport_field& rf = (const TReport_field&)_section[r]; const TRectangle& rect = rf.get_rect(); row.cut(0); row.add(checked(r) ? "X" : " "); row.add(rf.type_name()); row.add(rf.id()); row.add(num2str(rect.top())); row.add(num2str(rect.left())); row.add(num2str(rect.width())); row.add(num2str(rect.height())); if (rf.field().not_empty()) row.add(rf.field()); else row.add(rf.picture()); } int TReport_sheet::selection(int& first, int& last) const { int tot = 0; first = items()+1; last = -1; FOR_EACH_ARRAY_ITEM_BACK(_section, i, o) { const TReport_field& rf = *(const TReport_field*)o; if (rf.selected()) { if (i < first) first = i; if (i > last) last = i; tot++; } } return tot; } KEY TReport_sheet::run() { int first = -1; uncheck(-1); FOR_EACH_ARRAY_ITEM(_section, i, o) { const TReport_field& rf = *(const TReport_field*)o; if (rf.selected()) { check(i); if (first < 0) first = i; } } if (first > 0) select(first); const KEY k = TSheet::run(); if (k != K_ESC) { FOR_EACH_ARRAY_ITEM(_section, i, o) { TReport_field& rf = *(TReport_field*)o; rf.select(checked(i)); } } return k; } TReport_sheet::TReport_sheet(TReport_section& sec) : TSheet(-1, -1, -2, -4, "Campi", "@1|Tipo@10|ID@4R|Riga@R|Col.@R|Larg.@R|Alt.@R|Testo@50", 0xE), _section(sec) { } /////////////////////////////////////////////////////////// // TSection_properties_mask /////////////////////////////////////////////////////////// class TSection_properties_mask : public TReport_base_mask { protected: virtual void update(); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void set_num(short id, long num); short get_num(short id) const; void vedo_non_vedo(); void set_section(const TReport_section& rs); public: void get_section(TReport_section& rs) const; TSection_properties_mask(TReport_section& rs); }; void TSection_properties_mask::update() { for (int i = 0; i < 2; i++) { TMask_field& fld = field(i == 0 ? F_FGCOLOR : F_BGCOLOR); if (fld.active() && fld.parent() == win()) { RCT rctfld; fld.get_rect(rctfld); const int x = rctfld.right / CHARX + 1; const int y = rctfld.top / ROWY + 1; RCT& rct = resize_rect(x, y, -3, 1, W_PLAIN, win()); rct.top = rctfld.top; rct.bottom = rctfld.bottom; xi_draw_3d_rect((XinWindow)win(), (XinRect*)&rct, TRUE, 2, MASK_LIGHT_COLOR, i == 0 ? _fgcolor : _bgcolor, MASK_DARK_COLOR); } } TReport_base_mask::update(); } void TSection_properties_mask::set_num(short id, long num) { set(id, num2str(num)); } short TSection_properties_mask::get_num(short id) const { return str2num(get(id)); } void TSection_properties_mask::vedo_non_vedo() { const char type = get(F_TYPE)[0]; const int level = get_int(F_LEVEL); const bool can_pos = (type != 'H' && level == 0) || (type == 'F' && level == 1); show(F_X, can_pos); show(F_Y, can_pos); show(F_CONDITION, /*type == 'B' &&*/ level > 0 && level < 10); show(F_GROUP_BY, type == 'H' && level > 1 && level < 10); show(F_SQL, type == 'B' && level > 10); show(F_KEEP_WITH_NEXT, level > 1 && type == 'H'); show(F_CAN_BREAK, level > 0 && type == 'B'); show(F_HIDE_IF_NEEDED, level == 0 && type != 'B'); show(F_REPEAT, level > 1 && type == 'H'); bool can_delete = false; if (level > 1) { if (level > 10) can_delete = _report.find_section('B', level+1) == NULL; else can_delete = true; } enable(DLG_DELREC, can_delete); } bool TSection_properties_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_TYPE: case F_LEVEL: if (e == fe_modify) vedo_non_vedo(); break; case F_DX: case F_DY: if (e == fe_modify) { const int num = get_num(o.dlg()); set_num(o.dlg(), num); // Reformat } break; default: break; } return TReport_base_mask::on_field_event(o, e, jolly); } void TSection_properties_mask::set_section(const TReport_section& rs) { char s[2] = { rs.type(), '\0' }; set(F_TYPE, s); set(F_LEVEL, rs.level()); vedo_non_vedo(); if (field(F_X).active()) { set_num(F_X, rs.pos().x); set_num(F_Y, rs.pos().y); } set_num(F_DX, rs.width()); set_num(F_DY, rs.height()); set(F_CONDITION, rs.condition()); set(F_GROUP_BY, rs.grouped_by()); if (rs.recordset() != NULL) set(F_SQL, rs.recordset()->query_text()); else reset(F_SQL); set(F_HIDE_IF_NEEDED, rs.hidden_if_needed()); set(F_HIDDEN, rs.hidden()); set(F_PAGE_BREAK, rs.page_break()); set(F_KEEP_WITH_NEXT, rs.keep_with_next()); set(F_CAN_BREAK, rs.can_be_broken()); set(F_REPEAT, rs.repeat_on_page()); set(F_DISABLED, rs.deactivated()); set(F_BORDER, rs.border()); set(F_PATTERN, rs.pattern()); set_num(F_RADIUS, rs.radius()); _fgcolor = rs.fore_color(); _bgcolor = rs.back_color(); set_font_info(rs.font()); set(F_PRESCRIPT, rs.prescript()); set(F_POSTSCRIPT, rs.postscript()); } void TSection_properties_mask::get_section(TReport_section& rs) const { if (field(F_X).active()) { const TPoint pos(get_num(F_X), get_num(F_Y)); rs.set_pos(pos); } rs.set_width(get_num(F_DX)); rs.set_height(get_num(F_DY)); rs.show(!get_bool(F_HIDDEN)); rs.activate(!get_bool(F_DISABLED)); rs.set_condition(get(F_CONDITION)); rs.group_by(get(F_GROUP_BY)); rs.set_recordset(get(F_SQL)); rs.hide_if_needed(get_bool(F_HIDE_IF_NEEDED)); rs.force_page_break(get_bool(F_PAGE_BREAK)); rs.keep_with_next(get_bool(F_KEEP_WITH_NEXT)); rs.can_break(get_bool(F_CAN_BREAK)); rs.set_repeat_on_page(get_bool(F_REPEAT)); rs.set_pattern((PAT_STYLE)get_int(F_PATTERN)); rs.set_border(get_int(F_BORDER)); rs.set_radius(get_num(F_RADIUS)); rs.set_fore_color(_fgcolor); rs.set_back_color(_bgcolor); TReport_font f; if (get_font_info(f)) rs.set_font(f); rs.set_prescript(get(F_PRESCRIPT)); rs.set_postscript(get(F_POSTSCRIPT)); } TSection_properties_mask::TSection_properties_mask(TReport_section& rs) : TReport_base_mask("ba8300c", rs.report()) { set_section(rs); } /////////////////////////////////////////////////////////// // TReport_properties_mask /////////////////////////////////////////////////////////// class TReport_properties_mask : public TReport_base_mask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void set_report(const TReport& r); public: void get_report(TReport& r) const; TReport_properties_mask(TReport& rep) : TReport_base_mask("ba8300d", rep) { set_report(rep); } }; bool TReport_properties_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { return TReport_base_mask::on_field_event(o, e, jolly); } void TReport_properties_mask::set_report(const TReport& r) { set(F_FONT_AUTO, r.use_printer_font()); set(F_ORIENTATION, r.orientation()); set(F_DX, r.user_defined_cpi()); set(F_DY, r.lpi()); set_font_info(r.font()); set(F_CLASS, r.get_class()); set(F_COMMAND, r.command_line()); set(F_INCLUDE, ((TReport&)r).get_libraries()); set(F_PRESCRIPT, r.prescript()); set(F_POSTSCRIPT, r.postscript()); sfield(F_PARAMS).rows_array() = r.params(); sfield(F_LINK).rows_array() = r.allegates(); } void TReport_properties_mask::get_report(TReport& r) const { const bool af = get_bool(F_FONT_AUTO); r.set_use_printer_font(af); if (!af) { r.set_cpi(get_int(F_DX)); r.set_lpi(get_int(F_DY)); TReport_font f; if (get_font_info(f)) r.set_font(f); } r.set_orientation(get_int(F_ORIENTATION)); r.set_class(get(F_CLASS)); r.set_command_line(get(F_COMMAND)); const TString& oldlib = r.get_libraries(); if (oldlib != get(F_INCLUDE)) { r.set_libraries(get(F_INCLUDE)); r.include_libraries(); // reload } r.set_prescript(get(F_PRESCRIPT)); r.set_postscript(get(F_POSTSCRIPT)); r.set_params(sfield(F_PARAMS).rows_array()); r.set_allegates(sfield(F_LINK).rows_array()); } /////////////////////////////////////////////////////////// // TReport_mask /////////////////////////////////////////////////////////// class TReport_mask : public TAutomask { TReport _report; TReport_section* _curr_section; TReport_tree _tree; TFilename _curr_report; bool _is_dirty; protected: virtual TMask_field* parse_field(TScanner& scanner); virtual void notify_focus_field(short id); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); protected: bool select_query(); bool select_report(); void select_section(); void update_report() const; TReport_section& curr_section(); void add_field(); void edit_field(TReport_field& rf); void fields_properties(); bool add_section(); void section_properties(); void report_properties(); bool enumerate_bodies(int level, TToken_string& code, TToken_string& desc) const; bool get_rep_path(TFilename& path) const; void set_num_attr(TXmlItem& item, const char* attr, short num, short def = 0) const; void set_col_attr(TXmlItem& item, const char* attr, COLOR col, COLOR def) const; public: void on_print(); bool save_report(); bool save_if_needed(); void global_reset(); bool delete_report(); bool load_report(); TReport_tree& sections() { return _tree; } TReport_mask(); }; TMask_field* TReport_mask::parse_field(TScanner& scanner) { if (scanner.token().starts_with("RE")) return new TReport_drawer(this); return TAutomask::parse_field(scanner); } /* bool TReport_mask::select_report() { TFilename path; const bool ok = select_custom_file(path, "rep"); if (ok) { path = path.name(); path.ext(""); set(F_CODICE, path); } return ok; } */ bool TReport_mask::select_query() { TFilename path; bool ok = select_custom_file(path, "qry"); if (ok) { TXmlItem item; item.Load(path); const TXmlItem* sql = item.FindFirst("sql"); ok = sql != NULL; if (ok) { TString str; sql->GetEnclosedText(str); set(F_SQL, str, true); } } return ok; } bool TReport_mask::get_rep_path(TFilename& path) const { const TString& name = get(F_CODICE); const bool ok = name.not_empty(); if (ok) { path = name; if (!path.is_absolute_path()) { path = firm2dir(-1); path.add("custom"); if (!path.exist()) xvt_fsys_mkdir(path); path.add(name); path.ext("rep"); if (!path.exist() && is_power_station()) path = name; } path.ext("rep"); } return ok; } bool TReport_mask::save_report() { bool ok = _curr_report.not_empty(); if (!ok) ok = get_rep_path(_curr_report); if (!ok) return field(F_CODICE).on_key(K_ENTER); // Segnala errore _report.set_description(get(F_DESCR)); _report.set_recordset(get(F_SQL)); if (is_power_station()) { FILE_SPEC fsp; memset(&fsp, 0, sizeof(fsp)); xvt_fsys_convert_str_to_dir(_curr_report.path(), &fsp.dir); strcpy(fsp.type, _curr_report.ext()); _curr_report.ext(""); strcpy(fsp.name, _curr_report.name()); strcpy(fsp.creator, "CAMPO"); ok = xvt_dm_post_file_save(&fsp, TR("Nome report")) == FL_OK; if (ok) { xvt_fsys_convert_dir_to_str(&fsp.dir, _curr_report.get_buffer(), _curr_report.size()); _curr_report.add(fsp.name); } } if (ok) { ok = _report.save(_curr_report); if (ok) _is_dirty = false; } return ok; } bool TReport_mask::save_if_needed() { if (!_is_dirty) return true; if (!yesno_box(TR("Si desidera registrare il report?"))) return false; return save_report(); } void TReport_mask::global_reset() { _report.destroy(); reset(); update_report(); } bool TReport_mask::load_report() { TFilename path; get_rep_path(path); bool ok = path.exist(); if (ok) { _curr_report = path; global_reset(); ok = _report.load(path); if (ok) { path = path.name(); path.ext(""); set(F_CODICE, path); const TRecordset* rs = _report.recordset(); if (rs != NULL) set(F_SQL, rs->query_text(), true); set(F_DESCR, _report.description()); field(F_SQL).set_dirty(false); _is_dirty = false; TTree_field& sections = tfield(F_SECTIONS); _tree.goto_node('B', 1); sections.select_current(); select_section(); } } return ok; } bool TReport_mask::delete_report() { TFilename path; get_rep_path(path); const bool ok = path.exist() && yesno_box(FR("Si desidera eliminare il file '%s'"), (const char*)path); if (ok) { ::remove(path); global_reset(); } return ok; } void TReport_mask::on_print() { const TString& app = _report.command_line(); if (app.not_empty() && yesno_box(FR("Si desidera stampare utilizzando '%s'"), (const char*)app)) { TExternal_app a(app); a.run(); } else { #ifdef DBG TFilename tmp; tmp.tempdir(); tmp.add("ba8300.txt"); TReport_book book(tmp); #else TReport_book book; #endif book.add(_report); book.print_or_preview(); } } TReport_section& TReport_mask::curr_section() { return *_curr_section; } void TReport_mask::select_section() { TTree_field& tf = tfield(F_SECTIONS); tf.select_current(); _curr_section = &_tree.curr_section(); TReport_drawer& rd = (TReport_drawer&)field(F_REPORT); rd.set_report_section(*_curr_section); const char type = _curr_section->type(); const int level = _curr_section->level(); char htype = 'H'; int hlevel = level; switch (type) { case 'H': { if (level <= 1) hlevel = 1-level; else { if (level < 10) { if (_report.find_section('H', level-1)) hlevel = level-1; } else htype = 'B'; } } break; case 'B': if (level >= 1) { if (level < 10) { hlevel = _report.find_max_level('H'); if (hlevel <= 1) hlevel = 0; } } else hlevel = 0; break; case 'F': if (level > 1) { if (level > 10) htype = 'B'; else { if (_report.find_section('F', level-1)) hlevel = level-1; } } else hlevel = 1-level; break; default: break; } TReport_drawer& rdh = (TReport_drawer&)field(F_REPORTH); rdh.set_report_section(_report.section(htype, hlevel)); update_report(); } void TReport_mask::update_report() const { TTree_field& tf = tfield(F_SECTIONS); tf.win().force_update(); TReport_drawer& rdh = (TReport_drawer&)field(F_REPORTH); rdh.win().force_update(); TReport_drawer& rd = (TReport_drawer&)field(F_REPORT); rd.win().force_update(); } void TReport_mask::add_field() { TReport_section& rs = curr_section(); TReport_field* rf = new TReport_field(&rs); rf->set_type('S'); rf->set_pos(0, rs.compute_size().y+100); TReport_field_mask m(*rf); m.disable(DLG_DELREC); if (m.run() == K_ENTER) { m.get_field(*rf); rs.add(rf); update_report(); } else delete rf; } void TReport_mask::edit_field(TReport_field& rf) { TReport_section& rs = rf.section(); TReport_field_mask m(rf); const KEY key = m.run(); switch(key) { case K_ENTER: m.get_field(rf); break; case K_DEL: { for (int i = rs.last(); i >= 0; i--) if (rs.objptr(i) == &rf) { rs.destroy(i, true); break; } } break; default: break; } if (key != K_ESC) { _is_dirty = true; rs.sort(); update_report(); } } void TReport_mask::fields_properties() { TReport_section& rs = curr_section(); TReport_sheet sheet(rs); int first, last; int selected = sheet.selection(first, last); if (selected == 1) { TReport_field& rf = rs.field(first); edit_field(rf); return; } KEY key = K_ENTER; while (key != K_ESC) { key = sheet.run(); selected = sheet.selection(first, last); if (selected == 0 && (key == K_ENTER || key == K_DEL)) { first = last = sheet.selected(); selected = 1; sheet.check(first); } switch (key) { case K_INS: add_field(); break; case K_ENTER: { for (int i = first; i <= last; i++) if (sheet.checked(i)) { TReport_field& rf = rs.field(i); edit_field(rf); } } break; case K_DEL: if (selected > 0 && yesno_box(FR("Comfermare la cancellazione di %d elementi"), selected)) { for (int i = last; i >= first; i--) if (sheet.checked(i)) rs.destroy(i, true); } break; default: break; } update_report(); } } bool TReport_mask::enumerate_bodies(int level, TToken_string& code, TToken_string& desc) const { TReport_section* rs = _report.find_section('B', level); if (rs != NULL) { TString str; str.format("B%d", level); code.add(str); describe_section('B', level, str); str.trim(); desc.add(str); enumerate_bodies(level*10+1, code, desc); // Figlio enumerate_bodies(level+1, code, desc); // Fratello } return rs != NULL; } bool TReport_mask::add_section() { TMask m("ba8300e"); TToken_string code, desc; enumerate_bodies(1, code, desc); TList_field& list = (TList_field&)m.field(102); list.replace_items(code, desc); if (m.run() == K_ENTER) { char type = m.get(101)[0]; int level = 0; if (type == 'S') { type = 'B'; const int father = atoi(m.get(102).mid(1)); if (father < 100000L) { int i; for (i = 1; i <= 9; i++) // Cerca l'ultimo figlio del nodo padre { level = father*10+i; if (_report.find_section(type, level) == NULL) break; } if (i > 9) level = 0; } } else { if (type == 'H') { const int hl = _report.find_max_level('H'); const int fl = _report.find_max_level('F'); level = max(hl, fl) + 1; } else level = _report.find_max_level('B')+1; if (level > 9) level = 0; } if (level > 0) { _tree.goto_node(type, level); tfield(F_SECTIONS).select_current(); _curr_section = &_report.section(type, level); section_properties(); } else error_box(TR("Livello non ammesso")); } return false; } void TReport_mask::section_properties() { TReport_section& rs = curr_section(); TSection_properties_mask m(rs); switch (m.run()) { case K_ENTER: m.get_section(rs); _tree.goto_node(rs.type(), rs.level()); _is_dirty = true; break; case K_DEL: if (yesno_box(TR("Confermare l'eliminazione della sezione"))) { const char t = rs.type(); const int l = rs.level(); rs.report().kill_section(t, l); _tree.goto_node(t, l-1); _is_dirty = true; } break; default: break; } if (_is_dirty) select_section(); } void TReport_mask::report_properties() { TReport_properties_mask m(_report); if (m.run() == K_ENTER) { m.get_report(_report); _is_dirty = true; update_report(); } } void TReport_mask::notify_focus_field(short id) { TAutomask::notify_focus_field(id); if (id == F_REPORTH || id == F_REPORT) { TReport_drawer& rd = (TReport_drawer&)field(id); _curr_section = &rd.curr_section(); } } bool TReport_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODICE: if (e == fe_init) { if (main_app().argc() >= 3) { set(F_CODICE, main_app().argv(2)); load_report(); } } if (e == fe_modify) { save_if_needed(); load_report(); } break; case F_SECTIONS: if (e == fe_init || e == fe_modify) { select_section(); const TReport_section& rs = _tree.curr_section(); const bool ok = strchr("HBF", rs.type()) != NULL; enable(-1, ok); } break; case F_FLD_ADD: if (e == fe_button && o.active()) add_field(); break; case F_FLD_PROPERTIES: if (e == fe_button && o.active()) fields_properties(); break; case F_SEC_ADD: if (e == fe_button && o.active()) add_section(); break; case F_SEC_PROPERTIES: if (e == fe_button && o.active()) section_properties(); break; case F_REP_PROPERTIES: if (e == fe_button) report_properties(); break; case F_SQL: if (e == fe_init || e == fe_modify) enable(F_SHOW_QRY, !o.empty()); break; case F_NEW_QRY: if (e == fe_button) { TExternal_app q("ba8 -1"); q.run(); } break; case F_IMPORT_QRY: if (e == fe_button) select_query(); break; case F_SHOW_QRY: if (e == fe_button) { const TString& sql = get(F_SQL); TRecordset* rex = create_recordset(sql); if (rex != NULL) { if (rex->items() > 0) { TRecordset_sheet sht(*rex); sht.run(); } else { if (sql.find("SELECT ") >= 0) warning_box(TR("Nessuna riga risultato")); } delete rex; } } break; case DLG_PRINT: if (e == fe_button) { on_print(); return false; } break; case DLG_NEWREC: if (e == fe_button) { save_if_needed(); global_reset(); } break; case DLG_FINDREC: if (e == fe_button) send_key(K_F9, F_CODICE); case DLG_SAVEREC: if (e == fe_button) { get_rep_path(_curr_report); save_report(); } break; case DLG_DELREC: if (e == fe_button && jolly == 0) // Elimina della Toolbar { delete_report(); return false; // Do not exit! } break; case DLG_QUIT: save_if_needed(); break; default: break; } return true; } TReport_mask::TReport_mask() : _tree(_report), _is_dirty(false) { read_mask("ba8300a", 0, -1); set_handlers(); TTree_field& albero = tfield(F_SECTIONS); RCT rct_sec; albero.get_rect(rct_sec); const short sec[2] = { F_REPORT, F_REPORTH }; for (int s = 0; s < 2; s++) { TReport_drawer& rd = (TReport_drawer&)field(sec[s]); RCT rct_rep; rd.get_rect(rct_rep); rct_rep.left = rct_sec.right+ROWY; rct_rep.right -= ROWY; rct_rep.bottom -= ROWY; rd.set_rect(rct_rep); switch (s) { case 1 : rd.set_report_section(_report.section('H', 0)); break; default: _curr_section = &_report.section('B', 1); rd.set_report_section(*_curr_section); break; } } _tree.goto_node('B', 1); const int ih = _tree.image_height(); if (ih > CHARY) albero.set_row_height(ih); albero.set_tree(&_tree); _tree.goto_root(); _tree.expand_all(); } /////////////////////////////////////////////////////////// // TReporter_app /////////////////////////////////////////////////////////// class TReporter_app : public TSkeleton_application { TReport_mask* _msk; protected: virtual bool create(); virtual void main_loop(); virtual bool destroy(); virtual void print(); public: TReporter_app() : _msk(NULL) { } }; void TReporter_app::print() { if (_msk != NULL) _msk->on_print(); } bool TReporter_app::create() { if (!has_module(RSAUT)) return error_box(TR("Modulo non autorizzato")); _msk = new TReport_mask; xvt_sys_sleep(500); return TSkeleton_application::create(); } bool TReporter_app::destroy() { if (_msk != NULL) { delete _msk; _msk = NULL; } return true; } void TReporter_app::main_loop() { _msk->run(); } int ba8300(int argc, char* argv[]) { TReporter_app app; app.run(argc, argv, TR("Report Generator")); return 0; }