#pragma once /************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2024 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "meos_util.h" #include "oDataContainer.h" #include "oBase.h" #include "Table.h"" class RelativeTimeFormatter : public oDataDefiner { string name; public: RelativeTimeFormatter(const char* n) : name(n) {} const wstring& formatData(const oBase* obj) const override { int t = obj->getDCI().getInt(name); if (t <= 0) return makeDash(L"-"); return obj->getEvent()->getAbsTime(t); } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { int t = obj->getEvent()->getRelativeTime(input); obj->getDI().setInt(name.c_str(), t); output = formatData(obj); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), false, true); } }; class AbsoluteTimeFormatter : public oDataDefiner { string name; public: AbsoluteTimeFormatter(const char* n) : name(n) {} const wstring& formatData(const oBase* obj) const override { int t = obj->getDCI().getInt(name); return formatTime(t); } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { int t = convertAbsoluteTimeMS(input); if (t == NOTIME) t = 0; obj->getDI().setInt(name.c_str(), t); output = formatData(obj); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), false, true); } }; class PayMethodFormatter : public oDataDefiner { mutable vector< pair > modes; mutable map setCodes; mutable long rev; public: PayMethodFormatter() : rev(-1) {} void prepare(oEvent* oe) const override { oe->getPayModes(modes); for (size_t i = 0; i < modes.size(); i++) { setCodes[canonizeName(modes[i].first.c_str())] = modes[i].second; } } const wstring& formatData(const oBase* ob) const override { if (ob->getEvent()->getRevision() != rev) prepare(ob->getEvent()); int p = ob->getDCI().getInt("Paid"); if (p == 0) return lang.tl("Faktura"); else { int pm = ob->getDCI().getInt("PayMode"); for (size_t i = 0; i < modes.size(); i++) { if (modes[i].second == pm) return modes[i].first; } return _EmptyWString; } } pair setData(oBase* ob, const wstring& input, wstring& output, int inputId) const override { auto res = setCodes.find(canonizeName(input.c_str())); if (res != setCodes.end()) { ob->getDI().setInt("PayMode", res->second); } output = formatData(ob); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), true, true); } }; class StartGroupFormatter : public oDataDefiner { mutable long rev = -1; mutable map sgmap; mutable wstring out; int static getGroup(const oBase* ob) { const oRunner* r = dynamic_cast(ob); int sg = 0; if (r) sg = r->getStartGroup(false); else { const oClub* c = dynamic_cast(ob); if (c) sg = c->getStartGroup(); } return sg; } public: StartGroupFormatter() {} void prepare(oEvent* oe) const override { auto& sg = oe->getStartGroups(true); for (auto& g : sg) { int t = g.second.firstStart; sgmap[g.first] = oe->getAbsTimeHM(t); } } const wstring& formatData(const oBase* ob) const override { if (ob->getEvent()->getRevision() != rev) prepare(ob->getEvent()); int sg = getGroup(ob); if (sg > 0) { auto res = sgmap.find(sg); if (res != sgmap.end()) out = itow(sg) + L" (" + res->second + L")"; else out = itow(sg) + L" (??)"; return out; } else return _EmptyWString; } pair setData(oBase* ob, const wstring& input, wstring& output, int inputId) const override { int g = inputId; if (inputId <= 0 && !input.empty()) { vector sIn; split(input, L" ", sIn); for (wstring& in : sIn) { int num = _wtoi(in.c_str()); if (in.find_first_of(':') != input.npos) { int t = ob->getEvent()->convertAbsoluteTime(input); if (t > 0) { for (auto& sg : ob->getEvent()->getStartGroups(false)) { if (sg.second.firstStart == t) { g = sg.first; break; } } } } else if (sgmap.count(num)) { g = num; break; } } } oRunner* r = dynamic_cast(ob); if (r) { r->setStartGroup(g); } else { oClub* c = dynamic_cast(ob); if (c) c->setStartGroup(g); } output = formatData(ob); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), true, false); } // Return the desired cell type CellType getCellType() const { return CellType::cellSelection; } void fillInput(const oBase* obj, vector>& out, size_t& selected) const final { if (obj->getEvent()->getRevision() != rev) prepare(obj->getEvent()); int sg = getGroup(obj); out.emplace_back(_EmptyWString, 0); selected = 0; for (auto& v : sgmap) { out.emplace_back(v.second, v.first); if (sg == v.first) selected = sg; } } }; class DataHider : public oDataDefiner { public: const wstring& formatData(const oBase* obj) const override { return _EmptyWString; } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return -1; } }; class DataBoolean : public oDataDefiner { string attrib; public: DataBoolean(const string& attrib) : attrib(attrib) {} const wstring& formatData(const oBase* obj) const override { int v = obj->getDCI().getInt(attrib); return lang.tl(v ? "true[boolean]" : "false[boolean]"); } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { bool v = compareStringIgnoreCase(L"true", input) == 0 || _wtoi64(input.c_str()) > 0; if (!v) { const wstring& T = lang.tl("true[boolean]"); v = compareStringIgnoreCase(T, input) == 0; } obj->getDI().setInt(attrib.c_str(), v); output = formatData(obj); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), true, true); } }; class ResultModuleFormatter : public oDataDefiner { public: const wstring& formatData(const oBase* obj) const override { return obj->getDCI().getString("Result"); } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { string tag(input.begin(), input.end()); dynamic_cast(*obj).setResultModule(tag); output = formatData(obj); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { return table->addColumn(description, max(minWidth, 90), false, true); } }; class SplitPrintListFormatter : public oDataDefiner { public: const wstring& formatData(const oBase* obj) const override { wstring listId = obj->getDCI().getString("SplitPrint"); if (listId.empty()) { return lang.tl("Standard"); } try { const MetaListContainer& lc = obj->getEvent()->getListContainer(); EStdListType type = lc.getCodeFromUnqiueId(gdioutput::narrow(listId)); const MetaList& ml = lc.getList(type); return ml.getListName(); } catch (meosException&) { return _EmptyWString; } } void fillInput(const oBase* obj, vector>& out, size_t& selected) const { oEvent* oe = obj->getEvent(); oe->getListContainer().getLists(out, false, false, false, true); out.insert(out.begin(), make_pair(lang.tl("Standard"), -10)); wstring listId = obj->getDCI().getString("SplitPrint"); EStdListType type = oe->getListContainer().getCodeFromUnqiueId(gdioutput::narrow(listId)); if (type == EStdListType::EStdNone) selected = -10; else { for (auto& t : out) { if (type == oe->getListContainer().getType(t.second)) { selected = t.second; break; } } } } CellType getCellType() const final { return CellType::cellSelection; } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { if (inputId == -10) obj->getDI().setString("SplitPrint", L""); else { EStdListType type = obj->getEvent()->getListContainer().getType(inputId); string id = obj->getEvent()->getListContainer().getUniqueId(type); obj->getDI().setString("SplitPrint", gdioutput::widen(id)); } output = formatData(obj); return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { oEvent* oe = table->getEvent(); vector> out; oe->getListContainer().getLists(out, false, false, false, true); for (auto& t : out) { minWidth = max(minWidth, t.first.size() * 6); } return table->addColumn(description, max(minWidth, 90), false, true); } }; class AnnotationFormatter : public oDataDefiner { mutable int numChar = 12; public: const wstring& formatData(const oBase* obj) const override { const wstring& ws = obj->getDCI().getString("Annotation"); if (ws.empty()) return ws; int pos = ws.find_first_of('@'); if (pos != wstring::npos) return limitText(ws.substr(pos + 1), numChar); return limitText(ws, numChar); } bool canEdit() const override { return false; } pair setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override { return make_pair(0, false); } int addTableColumn(Table* table, const string& description, int minWidth) const override { numChar = minWidth / 5; return table->addColumn(description, max(minWidth, 90), false, true); } };