meos-2024/code/datadefiners.h

378 lines
12 KiB
C++

#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 <http://www.gnu.org/licenses/>.
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<int, bool> 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<int, bool> 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<wstring, size_t> > modes;
mutable map<wstring, int> 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<int, bool> 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<int, wstring> sgmap;
mutable wstring out;
int static getGroup(const oBase* ob) {
const oRunner* r = dynamic_cast<const oRunner*>(ob);
int sg = 0;
if (r)
sg = r->getStartGroup(false);
else {
const oClub* c = dynamic_cast<const oClub*>(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<int, bool> setData(oBase* ob, const wstring& input, wstring& output, int inputId) const override {
int g = inputId;
if (inputId <= 0 && !input.empty()) {
vector<wstring> 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<oRunner*>(ob);
if (r) {
r->setStartGroup(g);
}
else {
oClub* c = dynamic_cast<oClub*>(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<pair<wstring, size_t>>& 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<int, bool> 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<int, bool> 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<int, bool> setData(oBase* obj, const wstring& input, wstring& output, int inputId) const override {
string tag(input.begin(), input.end());
dynamic_cast<oClass&>(*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<pair<wstring, size_t>>& 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<int, bool> 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<pair<wstring, size_t>> out;
oe->getListContainer().getLists(out, false, false, false, true);
for (auto& t : out) {
minWidth = max<int>(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<int, bool> 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);
}
};