MeOS version 3.9.1399 Beta
This commit is contained in:
parent
0adbb266e9
commit
032a39ab1e
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -34,6 +34,9 @@
|
|||||||
#include "Printer.h"
|
#include "Printer.h"
|
||||||
#include "oListInfo.h"
|
#include "oListInfo.h"
|
||||||
#include "meosexception.h"
|
#include "meosexception.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
extern Image image;
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -139,10 +142,11 @@ public:
|
|||||||
|
|
||||||
template<typename T, typename TI>
|
template<typename T, typename TI>
|
||||||
void HTMLWriter::formatTL(ostream &fout,
|
void HTMLWriter::formatTL(ostream &fout,
|
||||||
const map<pair<gdiFonts, string>, pair<string, string>> &styles,
|
ImageWriter& imageWriter,
|
||||||
const T &tl,
|
const map<pair<gdiFonts, string>, pair<string, string>> &styles,
|
||||||
double &yscale, double &xscale,
|
const T &tl,
|
||||||
int &offsetY, int &offsetX) {
|
double &yscale, double &xscale,
|
||||||
|
int &offsetY, int &offsetX) {
|
||||||
|
|
||||||
|
|
||||||
auto itt = tl.begin();
|
auto itt = tl.begin();
|
||||||
@ -158,6 +162,14 @@ void HTMLWriter::formatTL(ostream &fout,
|
|||||||
string yp = itos(int(yscale*TI::y(ctr_it)) + offsetY);
|
string yp = itos(int(yscale*TI::y(ctr_it)) + offsetY);
|
||||||
string xp = itos(int(xscale*TI::x(ctr_it)) + offsetX);
|
string xp = itos(int(xscale*TI::x(ctr_it)) + offsetX);
|
||||||
|
|
||||||
|
if ((it.format & 0xFF) == textImage) {
|
||||||
|
int imgW = int((it.textRect.right - it.textRect.left) * xscale);
|
||||||
|
int imgH = int((it.textRect.bottom - it.textRect.top) * xscale);
|
||||||
|
imageWriter.write(fout, xp, yp, it.text, imgW, imgH);
|
||||||
|
++itt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string estyle;
|
string estyle;
|
||||||
if (it.format != 1 && it.format != boldSmall) {
|
if (it.format != 1 && it.format != boldSmall) {
|
||||||
if (it.format & textRight)
|
if (it.format & textRight)
|
||||||
@ -274,17 +286,31 @@ void HTMLWriter::writeHTML(gdioutput &gdi, const wstring &file,
|
|||||||
if (fout.bad())
|
if (fout.bad())
|
||||||
throw std::exception("Bad output stream");
|
throw std::exception("Bad output stream");
|
||||||
|
|
||||||
writeHTML(gdi, fout, title, refreshTimeOut, scale);
|
wchar_t drive[20];
|
||||||
|
wchar_t dir[MAX_PATH];
|
||||||
|
wchar_t name[MAX_PATH];
|
||||||
|
wchar_t ext[MAX_PATH];
|
||||||
|
_wsplitpath_s(file.c_str(), drive, dir, name, ext);
|
||||||
|
wstring path = wstring(drive) + dir;
|
||||||
|
|
||||||
|
writeHTML(gdi, fout, title, true, path, refreshTimeOut, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLWriter::writeHTML(gdioutput &gdi, ostream &fout, const wstring &title, int refreshTimeOut, double scale) {
|
void HTMLWriter::writeHTML(gdioutput& gdi, ostream& fout,
|
||||||
|
const wstring& title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring& imageDirectoryDestination,
|
||||||
|
int refreshTimeOut, double scale) {
|
||||||
|
|
||||||
|
ImageWriter imgWriter(imageDirectoryDestination, includeImages);
|
||||||
|
|
||||||
if (scale <= 0)
|
if (scale <= 0)
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
fout << "<!DOCTYPE html>" << endl;
|
fout << "<!DOCTYPE html>" << endl;
|
||||||
fout << "<html>\n<head>\n";
|
fout << "<html>\n<head>\n";
|
||||||
fout << "<meta charset=\"UTF-8\"/>\n";
|
fout << "<meta charset=\"UTF-8\"/>\n";
|
||||||
|
|
||||||
if (refreshTimeOut > 0)
|
if (refreshTimeOut > 0)
|
||||||
fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n";
|
fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n";
|
||||||
|
|
||||||
@ -299,16 +325,16 @@ void HTMLWriter::writeHTML(gdioutput &gdi, ostream &fout, const wstring &title,
|
|||||||
double yscale = 1.3 * scale;
|
double yscale = 1.3 * scale;
|
||||||
double xscale = 1.2 * scale;
|
double xscale = 1.2 * scale;
|
||||||
int offsetY = 0, offsetX = 0;
|
int offsetY = 0, offsetX = 0;
|
||||||
HTMLWriter::formatTL<list<TextInfo>, InterpTextInfo>(fout, styles, gdi.getTL(), yscale, xscale, offsetY, offsetX);
|
HTMLWriter::formatTL<list<TextInfo>, InterpTextInfo>(fout, imgWriter, styles, gdi.getTL(), yscale, xscale, offsetY, offsetX);
|
||||||
|
|
||||||
fout << "<p style=\"position:absolute;left:10px;top:" << int(yscale*(gdi.getPageY()-45)) + offsetY << "px\">";
|
fout << "<p style=\"position:absolute;left:10px;top:" << int(yscale * (gdi.getPageY() - 45)) + offsetY << "px\">";
|
||||||
|
|
||||||
char bf1[256];
|
char bf1[256];
|
||||||
char bf2[256];
|
char bf2[256];
|
||||||
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
||||||
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
||||||
//fout << "Skapad av <i>MeOS</i>: " << bf1 << " "<< bf2 << "\n";
|
//fout << "Skapad av <i>MeOS</i>: " << bf1 << " "<< bf2 << "\n";
|
||||||
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " << bf1 << " "<< bf2 << "\n";
|
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"https://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " << bf1 << " " << bf2 << "\n";
|
||||||
fout << "</p>\n";
|
fout << "</p>\n";
|
||||||
|
|
||||||
fout << "</body>\n";
|
fout << "</body>\n";
|
||||||
@ -341,18 +367,29 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
if (fout.bad())
|
if (fout.bad())
|
||||||
return throw std::exception("Bad output stream");
|
return throw std::exception("Bad output stream");
|
||||||
|
|
||||||
writeTableHTML(gdi, fout, title, false, refreshTimeOut, scale);
|
wchar_t drive[20];
|
||||||
|
wchar_t dir[MAX_PATH];
|
||||||
|
wchar_t name[MAX_PATH];
|
||||||
|
wchar_t ext[MAX_PATH];
|
||||||
|
_wsplitpath_s(file.c_str(), drive, dir, name, ext);
|
||||||
|
wstring path = wstring(drive) + dir;
|
||||||
|
|
||||||
|
writeTableHTML(gdi, fout, title, true, path, false, refreshTimeOut, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
void HTMLWriter::writeTableHTML(gdioutput& gdi,
|
||||||
ostream &fout,
|
ostream& fout,
|
||||||
const wstring &title,
|
const wstring& title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring& imageDirectoryDestination,
|
||||||
bool simpleFormat,
|
bool simpleFormat,
|
||||||
int refreshTimeOut,
|
int refreshTimeOut,
|
||||||
double scale) {
|
double scale) {
|
||||||
if (scale <= 0)
|
if (scale <= 0)
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
|
ImageWriter imgWriter(imageDirectoryDestination, includeImages);
|
||||||
|
|
||||||
fout << "<!DOCTYPE html>" << endl;
|
fout << "<!DOCTYPE html>" << endl;
|
||||||
fout << "<html>\n<head>\n";
|
fout << "<html>\n<head>\n";
|
||||||
fout << "<meta charset=\"UTF-8\"/>\n";
|
fout << "<meta charset=\"UTF-8\"/>\n";
|
||||||
@ -366,14 +403,14 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
fout << "</head>\n";
|
fout << "</head>\n";
|
||||||
|
|
||||||
fout << "<body>\n";
|
fout << "<body>\n";
|
||||||
auto &TL = gdi.getTL();
|
auto& TL = gdi.getTL();
|
||||||
auto it = TL.begin();
|
auto it = TL.begin();
|
||||||
int MaxX = gdi.getPageX() - 100;
|
int MaxX = gdi.getPageX() - 100;
|
||||||
map<int,int> tableCoordinates;
|
map<int, int> tableCoordinates;
|
||||||
|
|
||||||
//Get x-coordinates
|
//Get x-coordinates
|
||||||
while (it!=TL.end()) {
|
while (it != TL.end()) {
|
||||||
tableCoordinates[it->xp]=0;
|
tableCoordinates[it->xp] = 0;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,47 +421,47 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
++mit;
|
++mit;
|
||||||
}
|
}
|
||||||
tableCoordinates[MaxX] = kr;
|
tableCoordinates[MaxX] = kr;
|
||||||
|
|
||||||
vector<bool> sizeSet(kr + 1, false);
|
vector<bool> sizeSet(kr + 1, false);
|
||||||
|
|
||||||
fout << "<table cellspacing=\"0\" border=\"0\">\n";
|
fout << "<table cellspacing=\"0\" border=\"0\">\n";
|
||||||
|
|
||||||
int linecounter=0;
|
int linecounter = 0;
|
||||||
it=TL.begin();
|
it = TL.begin();
|
||||||
|
|
||||||
vector< pair<int, vector<const TextInfo *> > > rows;
|
vector< pair<int, vector<const TextInfo*> > > rows;
|
||||||
rows.reserve(TL.size() / 3);
|
rows.reserve(TL.size() / 3);
|
||||||
vector<int> ypRow;
|
vector<int> ypRow;
|
||||||
int minHeight = 100000;
|
int minHeight = 100000;
|
||||||
|
|
||||||
while (it!=TL.end()) {
|
while (it != TL.end()) {
|
||||||
int y=it->yp;
|
int y = it->yp;
|
||||||
vector<const TextInfo *> row;
|
vector<const TextInfo*> row;
|
||||||
|
|
||||||
int subnormal = 0;
|
int subnormal = 0;
|
||||||
int normal = 0;
|
int normal = 0;
|
||||||
int header = 0;
|
int header = 0;
|
||||||
int mainheader = 0;
|
int mainheader = 0;
|
||||||
while (it!=TL.end() && it->yp==y) {
|
while (it != TL.end() && it->yp == y) {
|
||||||
if (!gdioutput::skipTextRender(it->format)) {
|
if (!gdioutput::skipTextRender(it->format)) {
|
||||||
row.push_back(&*it);
|
row.push_back(&*it);
|
||||||
switch (it->getGdiFont()) {
|
switch (it->getGdiFont()) {
|
||||||
case fontLarge:
|
case fontLarge:
|
||||||
case boldLarge:
|
case boldLarge:
|
||||||
case boldHuge:
|
case boldHuge:
|
||||||
mainheader++;
|
mainheader++;
|
||||||
break;
|
break;
|
||||||
case boldText:
|
case boldText:
|
||||||
case italicMediumPlus:
|
case italicMediumPlus:
|
||||||
case fontMediumPlus:
|
case fontMediumPlus:
|
||||||
header++;
|
header++;
|
||||||
break;
|
break;
|
||||||
case fontSmall:
|
case fontSmall:
|
||||||
case italicSmall:
|
case italicSmall:
|
||||||
subnormal++;
|
subnormal++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
normal++;
|
normal++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
@ -444,27 +481,27 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
int last = ypRow.size();
|
int last = ypRow.size();
|
||||||
ypRow.push_back(y);
|
ypRow.push_back(y);
|
||||||
if (last > 0) {
|
if (last > 0) {
|
||||||
minHeight = min(minHeight, ypRow[last] - ypRow[last-1]);
|
minHeight = min(minHeight, ypRow[last] - ypRow[last - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int numMin = 0;
|
int numMin = 0;
|
||||||
for (size_t gCount = 1; gCount < rows.size(); gCount++) {
|
for (size_t gCount = 1; gCount < rows.size(); gCount++) {
|
||||||
int h = ypRow[gCount] - ypRow[gCount-1];
|
int h = ypRow[gCount] - ypRow[gCount - 1];
|
||||||
if (h == minHeight)
|
if (h == minHeight)
|
||||||
numMin++;
|
numMin++;
|
||||||
}
|
}
|
||||||
if (numMin == 0)
|
if (numMin == 0)
|
||||||
numMin = 1;
|
numMin = 1;
|
||||||
|
|
||||||
int hdrLimit = (rows.size() / numMin) <= 4 ? int(minHeight * 1.2) : int(minHeight * 1.5);
|
int hdrLimit = (rows.size() / numMin) <= 4 ? int(minHeight * 1.2) : int(minHeight * 1.5);
|
||||||
for (size_t gCount = 1; gCount + 1 < rows.size(); gCount++) {
|
for (size_t gCount = 1; gCount + 1 < rows.size(); gCount++) {
|
||||||
int type = rows[gCount].first;
|
int type = rows[gCount].first;
|
||||||
int lastType = gCount > 0 ? rows[gCount-1].first : 0;
|
int lastType = gCount > 0 ? rows[gCount - 1].first : 0;
|
||||||
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
|
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
|
||||||
if (type == 0 && (lastType == 1 || lastType == 2) && (nextType == 1 || nextType == 2))
|
if (type == 0 && (lastType == 1 || lastType == 2) && (nextType == 1 || nextType == 2))
|
||||||
continue; // No reclassify
|
continue; // No reclassify
|
||||||
|
|
||||||
int h = ypRow[gCount] - ypRow[gCount-1];
|
int h = ypRow[gCount] - ypRow[gCount - 1];
|
||||||
if (h > hdrLimit && rows[gCount].first == 0)
|
if (h > hdrLimit && rows[gCount].first == 0)
|
||||||
rows[gCount].first = 2;
|
rows[gCount].first = 2;
|
||||||
}
|
}
|
||||||
@ -472,12 +509,12 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
ypRow.clear();
|
ypRow.clear();
|
||||||
string lineclass;
|
string lineclass;
|
||||||
for (size_t gCount = 0; gCount < rows.size(); gCount++) {
|
for (size_t gCount = 0; gCount < rows.size(); gCount++) {
|
||||||
vector<const TextInfo *> &row = rows[gCount].second;
|
vector<const TextInfo*>& row = rows[gCount].second;
|
||||||
int type = rows[gCount].first;
|
int type = rows[gCount].first;
|
||||||
int lastType = gCount > 0 ? rows[gCount-1].first : 0;
|
int lastType = gCount > 0 ? rows[gCount - 1].first : 0;
|
||||||
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
|
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
|
||||||
|
|
||||||
vector<const TextInfo *>::iterator rit;
|
vector<const TextInfo*>::iterator rit;
|
||||||
fout << "<tr>" << endl;
|
fout << "<tr>" << endl;
|
||||||
|
|
||||||
if (simpleFormat) {
|
if (simpleFormat) {
|
||||||
@ -498,48 +535,55 @@ void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
|||||||
lineclass = "";
|
lineclass = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lineclass = (linecounter&1) ? " class=\"e1\"" : " class=\"e0\"";
|
lineclass = (linecounter & 1) ? " class=\"e1\"" : " class=\"e0\"";
|
||||||
|
|
||||||
linecounter++;
|
linecounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t k=0;k<row.size();k++) {
|
for (size_t k = 0; k < row.size(); k++) {
|
||||||
int thisCol=tableCoordinates[row[k]->xp];
|
int thisCol = tableCoordinates[row[k]->xp];
|
||||||
|
|
||||||
if (k == 0 && thisCol != 0)
|
if (k == 0 && thisCol != 0)
|
||||||
fout << "<td" << lineclass << " colspan=\"" << thisCol << "\"> </td>";
|
fout << "<td" << lineclass << " colspan=\"" << thisCol << "\"> </td>";
|
||||||
|
|
||||||
int nextCol;
|
int nextCol;
|
||||||
if (row.size() == k + 1)
|
if (row.size() == k + 1)
|
||||||
nextCol = tableCoordinates.rbegin()->second;
|
nextCol = tableCoordinates.rbegin()->second;
|
||||||
else
|
else
|
||||||
nextCol = tableCoordinates[row[k + 1]->xp];
|
nextCol = tableCoordinates[row[k + 1]->xp];
|
||||||
|
|
||||||
int colspan = nextCol - thisCol;
|
int colspan = nextCol - thisCol;
|
||||||
|
|
||||||
assert(colspan > 0);
|
assert(colspan > 0);
|
||||||
|
|
||||||
string style;
|
string style;
|
||||||
|
|
||||||
if (row[k]->format&textRight)
|
if (row[k]->format & textRight)
|
||||||
style = " style=\"text-align:right\"";
|
style = " style=\"text-align:right\"";
|
||||||
|
|
||||||
if (colspan == 1 && !sizeSet[thisCol]) {
|
if (colspan == 1 && !sizeSet[thisCol]) {
|
||||||
fout << " <td" << lineclass << style << " width=\"" << int((k + 1 < row.size()) ?
|
fout << " <td" << lineclass << style << " width=\"" << int((k + 1 < row.size()) ?
|
||||||
(row[k + 1]->xp - row[k]->xp) : (MaxX - row[k]->xp)) << "\">";
|
(row[k + 1]->xp - row[k]->xp) : (MaxX - row[k]->xp)) << "\">";
|
||||||
sizeSet[thisCol] = true;
|
sizeSet[thisCol] = true;
|
||||||
}
|
}
|
||||||
else if (colspan > 1)
|
else if (colspan > 1)
|
||||||
fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">";
|
fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">";
|
||||||
else
|
else
|
||||||
fout << " <td" << lineclass << style << ">";
|
fout << " <td" << lineclass << style << ">";
|
||||||
|
|
||||||
gdiFonts font = row[k]->getGdiFont();
|
if ((row[k]->format & 0xFF) == textImage) {
|
||||||
string starttag, endtag;
|
int imgW = int((row[k]->textRect.right - row[k]->textRect.left) * scale);
|
||||||
getStyle(styles, font, gdioutput::narrow(row[k]->font), "", starttag, endtag);
|
int imgH = int((row[k]->textRect.bottom - row[k]->textRect.top) * scale);
|
||||||
|
imgWriter.write(fout, "", "", row[k]->text, imgW, imgH);
|
||||||
fout << starttag << gdioutput::toUTF8(html_table_code(row[k]->text)) << endtag << "</td>" << endl;
|
fout << "</td>" << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gdiFonts font = row[k]->getGdiFont();
|
||||||
|
string starttag, endtag;
|
||||||
|
getStyle(styles, font, gdioutput::narrow(row[k]->font), "", starttag, endtag);
|
||||||
|
|
||||||
|
fout << starttag << gdioutput::toUTF8(html_table_code(row[k]->text)) << endtag << "</td>" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fout << "</tr>\n";
|
fout << "</tr>\n";
|
||||||
|
|
||||||
@ -555,7 +599,7 @@ fout << starttag << gdioutput::toUTF8(html_table_code(row[k]->text)) << endtag <
|
|||||||
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
||||||
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
||||||
wstring meos = getMeosCompectVersion();
|
wstring meos = getMeosCompectVersion();
|
||||||
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS "
|
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"https://www.melin.nu/meos\" target=\"_blank\"><i>MeOS "
|
||||||
<< gdioutput::toUTF8(meos) << "</i></a>: " << bf1 << " " << bf2 << "\n";
|
<< gdioutput::toUTF8(meos) << "</i></a>: " << bf1 << " " << bf2 << "\n";
|
||||||
fout << "</p><br>\n";
|
fout << "</p><br>\n";
|
||||||
}
|
}
|
||||||
@ -781,8 +825,11 @@ void HTMLWriter::generate(gdioutput &gdi,
|
|||||||
double scale) const {
|
double scale) const {
|
||||||
int w, h;
|
int w, h;
|
||||||
gdi.getTargetDimension(w, h);
|
gdi.getTargetDimension(w, h);
|
||||||
|
|
||||||
|
|
||||||
|
ImageWriter imgWriter(L"", false);
|
||||||
|
|
||||||
string meos = "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " + gdioutput::toUTF8(getMeosCompectVersion()) + "</a>";
|
string meos = "<a href=\"https://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " + gdioutput::toUTF8(getMeosCompectVersion()) + "</a>";
|
||||||
|
|
||||||
int margin = (w * marginPercent) / 100;
|
int margin = (w * marginPercent) / 100;
|
||||||
int height = nRows * gdi.getLineHeight();
|
int height = nRows * gdi.getLineHeight();
|
||||||
@ -886,7 +933,7 @@ void HTMLWriter::generate(gdioutput &gdi,
|
|||||||
double xscale = 1.2 * scale;
|
double xscale = 1.2 * scale;
|
||||||
int offsetY = 0, offsetX = 0;
|
int offsetY = 0, offsetX = 0;
|
||||||
|
|
||||||
formatTL<vector<PrintTextInfo>, InterpPrintTextInfo>(sout, styles, p.text, yscale, xscale, offsetY, offsetX);
|
formatTL<vector<PrintTextInfo>, InterpPrintTextInfo>(sout, imgWriter, styles, p.text, yscale, xscale, offsetY, offsetX);
|
||||||
|
|
||||||
output = innerpage;
|
output = innerpage;
|
||||||
replaceAll(output, "@P", itos(ipCounter++));
|
replaceAll(output, "@P", itos(ipCounter++));
|
||||||
@ -921,17 +968,27 @@ void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title
|
|||||||
checkWriteAccess(file);
|
checkWriteAccess(file);
|
||||||
ofstream fout(file.c_str());
|
ofstream fout(file.c_str());
|
||||||
|
|
||||||
write(gdi, fout, title, contentsDescription, respectPageBreak, typeTag, refresh,
|
wchar_t drive[20];
|
||||||
|
wchar_t dir[MAX_PATH];
|
||||||
|
wchar_t name[MAX_PATH];
|
||||||
|
wchar_t ext[MAX_PATH];
|
||||||
|
_wsplitpath_s(file.c_str(), drive, dir, name, ext);
|
||||||
|
wstring path = wstring(drive) + dir;
|
||||||
|
|
||||||
|
write(gdi, fout, title, true, path, contentsDescription, respectPageBreak, typeTag, refresh,
|
||||||
rows, cols, time_ms, margin, scale);
|
rows, cols, time_ms, margin, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLWriter::write(gdioutput &gdi, ostream &fout, const wstring &title, const wstring &contentsDescription,
|
void HTMLWriter::write(gdioutput &gdi, ostream &fout, const wstring &title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring& imageDirectoryDestination,
|
||||||
|
const wstring &contentsDescription,
|
||||||
bool respectPageBreak, const string &typeTag, int refresh,
|
bool respectPageBreak, const string &typeTag, int refresh,
|
||||||
int rows, int cols, int time_ms, int margin, double scale) {
|
int rows, int cols, int time_ms, int margin, double scale) {
|
||||||
if (typeTag == "table")
|
if (typeTag == "table")
|
||||||
writeTableHTML(gdi, fout, title, false, refresh, scale);
|
writeTableHTML(gdi, fout, title, includeImages, imageDirectoryDestination, false, refresh, scale);
|
||||||
else if (typeTag == "free") {
|
else if (typeTag == "free") {
|
||||||
writeHTML(gdi, fout, title, refresh, scale);
|
writeHTML(gdi, fout, title, includeImages, imageDirectoryDestination, refresh, scale);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* auto res = tCache.find(typeTag);
|
/* auto res = tCache.find(typeTag);
|
||||||
@ -972,6 +1029,44 @@ void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title
|
|||||||
param.timePerPage, param.margin, param.htmlScale);
|
param.timePerPage, param.margin, param.htmlScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTMLWriter::write(gdioutput& gdi, ostream& fout, const wstring& title, int refresh, oListParam& param, const oEvent& oe) {
|
||||||
|
write(gdi, fout, title, true, L"", param.getContentsDescriptor(oe), param.pageBreak, param.htmlTypeTag,
|
||||||
|
refresh != 0 ? refresh : param.timePerPage / 1000, param.htmlRows, param.nColumns,
|
||||||
|
param.timePerPage, param.margin, param.htmlScale);
|
||||||
|
}
|
||||||
|
|
||||||
void HTMLWriter::getPage(const oEvent &oe, string &out) const {
|
void HTMLWriter::getPage(const oEvent &oe, string &out) const {
|
||||||
out = page;
|
out = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTMLWriter::ImageWriter::write(ostream& fout, const string& xp, const string& yp, const wstring& img, int width, int height) {
|
||||||
|
if (!writeImages) {
|
||||||
|
if (xp.empty())
|
||||||
|
fout << " ";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (img.empty() || img[0] != 'L')
|
||||||
|
throw meosException("Unsupported image");
|
||||||
|
uint64_t imgId = _wcstoui64(img.c_str() + 1, nullptr, 10);
|
||||||
|
|
||||||
|
if (!savedFiles.count(imgId)) {
|
||||||
|
if (!destination.empty()) {
|
||||||
|
auto& data = image.getRawData(imgId);
|
||||||
|
wstring d = destination + img + L".png";
|
||||||
|
ofstream out(d, ofstream::out | ofstream::binary);
|
||||||
|
out.write((const char *)data.data(), data.size());
|
||||||
|
savedFiles[imgId] = "L" + itos(imgId) + ".png";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
savedFiles[imgId] = "/meos?image=ID" + itos(imgId) + ".png";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string style;
|
||||||
|
if (xp.size() > 0)
|
||||||
|
style = " style=\"position:absolute;left:" + xp + "px;top:" + yp + "px\"";
|
||||||
|
|
||||||
|
fout << "<img src=\"" << savedFiles[imgId] << "\" width=\"" <<
|
||||||
|
width << "\" height=\"" << height << "\"" << style << ">";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -39,6 +39,29 @@ class HTMLWriter {
|
|||||||
|
|
||||||
static string localize(const string &in);
|
static string localize(const string &in);
|
||||||
|
|
||||||
|
|
||||||
|
class ImageWriter {
|
||||||
|
wstring destination;
|
||||||
|
const bool writeImages;
|
||||||
|
const wstring imageDirectoryDestination;
|
||||||
|
map<uint64_t, string> savedFiles;
|
||||||
|
public:
|
||||||
|
ImageWriter(const wstring& dst, bool writeImages) : destination(dst), writeImages(writeImages) {}
|
||||||
|
|
||||||
|
|
||||||
|
void write(ostream &fout, const string &xp, const string &yp, const wstring &img, int width, int height);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename TI>
|
||||||
|
static void formatTL(ostream& fout,
|
||||||
|
ImageWriter& imageWriter,
|
||||||
|
const map< pair<gdiFonts, string>, pair<string, string> >& styles,
|
||||||
|
const T& tl,
|
||||||
|
double& yscale,
|
||||||
|
double& xscale,
|
||||||
|
int& offsetY,
|
||||||
|
int& offsetX);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void reset() {
|
static void reset() {
|
||||||
@ -76,10 +99,15 @@ public:
|
|||||||
|
|
||||||
void getPage(const oEvent &oe, string &out) const;
|
void getPage(const oEvent &oe, string &out) const;
|
||||||
|
|
||||||
static void writeHTML(gdioutput &gdi, ostream &dout, const wstring &title, int refreshTimeOut, double scale);
|
static void writeHTML(gdioutput &gdi, ostream &dout, const wstring &title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring& imageDirectoryDestination,
|
||||||
|
int refreshTimeOut, double scale);
|
||||||
|
|
||||||
static void writeTableHTML(gdioutput &gdi, ostream &fout,
|
static void writeTableHTML(gdioutput &gdi, ostream &fout,
|
||||||
const wstring &title,
|
const wstring &title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring &imageDirectoryDestination,
|
||||||
bool simpleFormat,
|
bool simpleFormat,
|
||||||
int refreshTimeOut,
|
int refreshTimeOut,
|
||||||
double scale);
|
double scale);
|
||||||
@ -92,23 +120,17 @@ public:
|
|||||||
static void writeHTML(gdioutput &gdi, const wstring &file,
|
static void writeHTML(gdioutput &gdi, const wstring &file,
|
||||||
const wstring &title, int refreshTimeOut, double scale);
|
const wstring &title, int refreshTimeOut, double scale);
|
||||||
|
|
||||||
static void write(gdioutput &gdi, const wstring &file, const wstring &title, const wstring &contentsDescription,
|
static void write(gdioutput& gdi, const wstring& file, const wstring& title, int refresh, oListParam& param, const oEvent& oe);
|
||||||
bool respectPageBreak, const string &typeTag, int refresh,
|
static void write(gdioutput& gdi, ostream& fout, const wstring& title, int refresh, oListParam& param, const oEvent& oe);
|
||||||
int rows, int cols, int time_ms, int margin, double scale);
|
|
||||||
|
|
||||||
static void write(gdioutput &gdi, ostream &fout, const wstring &title, const wstring &contentsDescription,
|
static void write(gdioutput& gdi, const wstring& file, const wstring& title, const wstring& contentsDescription,
|
||||||
bool respectPageBreak, const string &typeTag, int refresh,
|
bool respectPageBreak, const string& typeTag, int refresh,
|
||||||
int rows, int cols, int time_ms, int margin, double scale);
|
int rows, int cols, int time_ms, int margin, double scale);
|
||||||
|
|
||||||
static void write(gdioutput &gdi, const wstring &file, const wstring &title, int refresh, oListParam ¶m, const oEvent &oe);
|
|
||||||
|
|
||||||
template<typename T, typename TI>
|
|
||||||
static void formatTL(ostream &fout,
|
|
||||||
const map< pair<gdiFonts, string>, pair<string, string> > &styles,
|
|
||||||
const T &tl,
|
|
||||||
double &yscale,
|
|
||||||
double &xscale,
|
|
||||||
int &offsetY,
|
|
||||||
int &offsetX);
|
|
||||||
|
|
||||||
|
static void write(gdioutput& gdi, ostream& fout, const wstring& title,
|
||||||
|
bool includeImages,
|
||||||
|
const wstring& imageDirectoryDestination,
|
||||||
|
const wstring& contentsDescription,
|
||||||
|
bool respectPageBreak, const string& typeTag, int refresh,
|
||||||
|
int rows, int cols, int time_ms, int margin, double scale);
|
||||||
};
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
319
code/MeosSQL.cpp
319
code/MeosSQL.cpp
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -99,6 +99,11 @@ string C_INT64(string name)
|
|||||||
return " "+name+" BIGINT NOT NULL DEFAULT 0, ";
|
return " "+name+" BIGINT NOT NULL DEFAULT 0, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string C_UINT64(string name)
|
||||||
|
{
|
||||||
|
return " " + name + " BIGINT UNSIGNED NOT NULL DEFAULT 0, ";
|
||||||
|
}
|
||||||
|
|
||||||
string C_STRING(string name, int len=64)
|
string C_STRING(string name, int len=64)
|
||||||
{
|
{
|
||||||
char bf[16];
|
char bf[16];
|
||||||
@ -451,8 +456,21 @@ void MeosSQL::upgradeDB(const string &db, oDataContainer const * dc) {
|
|||||||
sql = sql.substr(0, sql.length() - 2);
|
sql = sql.substr(0, sql.length() - 2);
|
||||||
query.execute(sql);
|
query.execute(sql);
|
||||||
}
|
}
|
||||||
|
if (!eCol.count("BDate")) {
|
||||||
|
string sql = "ALTER TABLE " + db + " ";
|
||||||
|
sql += "ADD COLUMN " + C_INT("BDate");
|
||||||
|
sql = sql.substr(0, sql.length() - 2);
|
||||||
|
query.execute(sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (db == "oPunch") {
|
||||||
|
if (!eCol.count("Unit")) {
|
||||||
|
string sql = "ALTER TABLE " + db + " ";
|
||||||
|
sql += "ADD COLUMN " + C_INT("Unit");
|
||||||
|
sql = sql.substr(0, sql.length() - 2);
|
||||||
|
query.execute(sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc) {
|
if (dc) {
|
||||||
// Ugrade table
|
// Ugrade table
|
||||||
string sqlAdd = dc->generateSQLDefinition(eCol);
|
string sqlAdd = dc->generateSQLDefinition(eCol);
|
||||||
@ -478,7 +496,8 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
monitorId = 0;
|
monitorId = 0;
|
||||||
string dbname(oe->currentNameId.begin(), oe->currentNameId.end());//WCS
|
string dbname(oe->currentNameId.begin(), oe->currentNameId.end());
|
||||||
|
bool tookLock = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto query = con->query();
|
auto query = con->query();
|
||||||
@ -489,11 +508,29 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
auto row = res.at(0);
|
auto row = res.at(0);
|
||||||
|
|
||||||
int version = row["Version"];
|
int version = row["Version"];
|
||||||
|
|
||||||
if (version < oEvent::dbVersion) {
|
if (version < oEvent::dbVersion) {
|
||||||
|
if (version <= 88) {
|
||||||
|
query.exec("LOCK TABLE MeOSMain.oEvent WRITE");
|
||||||
|
tookLock = true;
|
||||||
|
|
||||||
|
query.reset();
|
||||||
|
query << "SELECT Version FROM oEvent WHERE NameId=" << quote << dbname;
|
||||||
|
auto resV = query.store();
|
||||||
|
if (res && res.num_rows() >= 1) {
|
||||||
|
version = res.at(0)["Version"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
query << "UPDATE oEvent SET Version=" << oEvent::dbVersion << " WHERE Id=" << int(row["Id"]);
|
query << "UPDATE oEvent SET Version=" << oEvent::dbVersion << " WHERE Id=" << int(row["Id"]);
|
||||||
query.execute();
|
query.execute();
|
||||||
|
if (version <= 88) {
|
||||||
|
upgradeTimeFormat(dbname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tookLock) {
|
||||||
|
con->query().exec("UNLOCK TABLES");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (version > oEvent::dbVersion) {
|
else if (version > oEvent::dbVersion) {
|
||||||
alert("A newer version av MeOS is required.");
|
alert("A newer version av MeOS is required.");
|
||||||
@ -524,6 +561,10 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const Exception& er) {
|
catch (const Exception& er) {
|
||||||
|
if (tookLock && con) {
|
||||||
|
con->query().exec("UNLOCK TABLES");
|
||||||
|
}
|
||||||
|
|
||||||
setDefaultDB();
|
setDefaultDB();
|
||||||
alert(string(er.what()) + " MySQL Error. Select DB.");
|
alert(string(er.what()) + " MySQL Error. Select DB.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -588,6 +629,7 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
<< C_INT("CardNo")
|
<< C_INT("CardNo")
|
||||||
<< C_UINT("ReadId")
|
<< C_UINT("ReadId")
|
||||||
<< C_UINT("Voltage")
|
<< C_UINT("Voltage")
|
||||||
|
<< C_INT("BDate")
|
||||||
<< C_STRING("Punches", 16*190) << C_END();
|
<< C_STRING("Punches", 16*190) << C_END();
|
||||||
|
|
||||||
query.execute();
|
query.execute();
|
||||||
@ -657,9 +699,12 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
query << C_START("oPunch")
|
query << C_START("oPunch")
|
||||||
<< C_INT("CardNo")
|
<< C_INT("CardNo")
|
||||||
<< C_INT("Time")
|
<< C_INT("Time")
|
||||||
<< C_INT("Type") << C_END();
|
<< C_INT("Type")
|
||||||
|
<< C_INT("Unit") << C_END();
|
||||||
query.execute();
|
query.execute();
|
||||||
|
|
||||||
|
upgradeDB("oPunch", nullptr);
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
query << C_START("oMonitor")
|
query << C_START("oMonitor")
|
||||||
<< C_STRING("Client")
|
<< C_STRING("Client")
|
||||||
@ -691,6 +736,13 @@ bool MeosSQL::openDB(oEvent *oe)
|
|||||||
|
|
||||||
// Create runner/club DB
|
// Create runner/club DB
|
||||||
createRunnerDB(oe, query);
|
createRunnerDB(oe, query);
|
||||||
|
|
||||||
|
query.reset();
|
||||||
|
query << C_START_noid("oImage")
|
||||||
|
<< C_UINT64("Id")
|
||||||
|
<< C_TEXT("Filename")
|
||||||
|
<< " Image LONGBLOB)" << engine();
|
||||||
|
query.execute();
|
||||||
}
|
}
|
||||||
catch (const Exception& er){
|
catch (const Exception& er){
|
||||||
alert(string(er.what()) + " MySQL Error.");
|
alert(string(er.what()) + " MySQL Error.");
|
||||||
@ -979,9 +1031,9 @@ OpFailStatus MeosSQL::uploadRunnerDB(oEvent *oe)
|
|||||||
auto query = con->query();
|
auto query = con->query();
|
||||||
query << "INSERT INTO dbRunner SET " <<
|
query << "INSERT INTO dbRunner SET " <<
|
||||||
"Name=" << quote << rdb[k].name <<
|
"Name=" << quote << rdb[k].name <<
|
||||||
", ExtId=" << rdb[k].extId << ", Club=" << rdb[k].clubNo <<
|
", ExtId=" << rdb[k].getExtId() << ", Club=" << rdb[k].clubNo <<
|
||||||
", CardNo=" << rdb[k].cardNo << ", Sex=" << quote << rdb[k].getSex() <<
|
", CardNo=" << rdb[k].cardNo << ", Sex=" << quote << rdb[k].getSex() <<
|
||||||
", Nation=" << quote << rdb[k].getNationality() << ", BirthYear=" << rdb[k].birthYear;
|
", Nation=" << quote << rdb[k].getNationality() << ", BirthYear=" << rdb[k].getBirthDateInt();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
query.execute();
|
query.execute();
|
||||||
@ -1031,7 +1083,7 @@ bool MeosSQL::storeData(oDataInterface odi, const RowWrapper &row, unsigned long
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
__int64 val = row[(const char*)it_int->name].ulonglong();
|
__int64 val = row[(const char*)it_int->name].longlong();
|
||||||
__int64 oldVal = *(it_int->data64);
|
__int64 oldVal = *(it_int->data64);
|
||||||
if (val != oldVal) {
|
if (val != oldVal) {
|
||||||
memcpy(it_int->data64, &val, 8);
|
memcpy(it_int->data64, &val, 8);
|
||||||
@ -1476,7 +1528,7 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
|
|||||||
RunnerDBEntry &dbn = db->dbe();
|
RunnerDBEntry &dbn = db->dbe();
|
||||||
if (sex.length()==1)
|
if (sex.length()==1)
|
||||||
dbn.sex = sex[0];
|
dbn.sex = sex[0];
|
||||||
dbn.birthYear = short(atoi(birth.c_str()));
|
dbn.setBirthDate(atoi(birth.c_str()));
|
||||||
|
|
||||||
if (nat.length()==3) {
|
if (nat.length()==3) {
|
||||||
dbn.national[0] = nat[0];
|
dbn.national[0] = nat[0];
|
||||||
@ -1546,6 +1598,7 @@ void MeosSQL::storeCard(const RowWrapper &row, oCard &c)
|
|||||||
c.cardNo = row["CardNo"];
|
c.cardNo = row["CardNo"];
|
||||||
c.readId = row["ReadId"];
|
c.readId = row["ReadId"];
|
||||||
c.miliVolt = row["Voltage"];
|
c.miliVolt = row["Voltage"];
|
||||||
|
c.batteryDate = row["BDate"];
|
||||||
c.importPunches(string(row["Punches"]));
|
c.importPunches(string(row["Punches"]));
|
||||||
|
|
||||||
c.sqlUpdated = row["Modified"];
|
c.sqlUpdated = row["Modified"];
|
||||||
@ -1565,10 +1618,10 @@ void MeosSQL::storePunch(const RowWrapper &row, oFreePunch &p, bool rehash)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.CardNo = row["CardNo"];
|
p.CardNo = row["CardNo"];
|
||||||
p.Time = row["Time"];
|
p.punchTime = row["Time"];
|
||||||
p.Type = row["Type"];
|
p.type = row["Type"];
|
||||||
}
|
}
|
||||||
|
p.punchUnit = row["Unit"];
|
||||||
p.sqlUpdated = row["Modified"];
|
p.sqlUpdated = row["Modified"];
|
||||||
p.counter = row["Counter"];
|
p.counter = row["Counter"];
|
||||||
p.Removed = row["Removed"];
|
p.Removed = row["Removed"];
|
||||||
@ -2178,6 +2231,7 @@ OpFailStatus MeosSQL::syncUpdate(oCard *c, bool forceWriteAll)
|
|||||||
auto queryset = con->query();
|
auto queryset = con->query();
|
||||||
queryset << " CardNo=" << c->cardNo
|
queryset << " CardNo=" << c->cardNo
|
||||||
<< ", ReadId=" << c->readId << ", Voltage=" << max(0, c->miliVolt)
|
<< ", ReadId=" << c->readId << ", Voltage=" << max(0, c->miliVolt)
|
||||||
|
<< ", BDate=" << c->batteryDate
|
||||||
<< ", Punches=" << quote << c->getPunchString();
|
<< ", Punches=" << quote << c->getPunchString();
|
||||||
|
|
||||||
return syncUpdate(queryset, "oCard", c);
|
return syncUpdate(queryset, "oCard", c);
|
||||||
@ -2287,6 +2341,77 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t)
|
|||||||
return syncRead(forceRead, t, true);
|
return syncRead(forceRead, t, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MeosSQL::upgradeTimeFormat(const string & dbname) {
|
||||||
|
bool ok = false;
|
||||||
|
try {
|
||||||
|
con->select_db(dbname);
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
catch (const Exception &) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
auto query = con->query();
|
||||||
|
query.exec("LOCK TABLES oEvent WRITE, oClass WRITE, oControl WRITE, "
|
||||||
|
"oCourse WRITE, oPunch WRITE, oRunner WRITE, oTeam WRITE");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto upgradeCol = [this](const string &db, const string &col) {
|
||||||
|
auto query = con->query();
|
||||||
|
string v = "UPDATE " + db + " SET " + col + "=" + col + "*10 WHERE " + col + "<>-1";
|
||||||
|
try {
|
||||||
|
query.execute(v);
|
||||||
|
}
|
||||||
|
catch (const Exception &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto alter = [this](const string &db, const string &col) {
|
||||||
|
auto query = con->query();
|
||||||
|
string v = "ALTER TABLE " + db + " MODIFY COLUMN " + col + " INT NOT NULL DEFAULT 0";
|
||||||
|
try {
|
||||||
|
query.execute(v);
|
||||||
|
}
|
||||||
|
catch (const Exception &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
};
|
||||||
|
upgradeCol("oEvent", "ZeroTime");
|
||||||
|
upgradeCol("oEvent", "MaxTime");
|
||||||
|
upgradeCol("oEvent", "DiffTime");
|
||||||
|
|
||||||
|
upgradeCol("oClass", "FirstStart");
|
||||||
|
upgradeCol("oClass", "StartInterval");
|
||||||
|
upgradeCol("oClass", "MaxTime");
|
||||||
|
|
||||||
|
upgradeCol("oControl", "TimeAdjust");
|
||||||
|
upgradeCol("oControl", "MinTime");
|
||||||
|
|
||||||
|
upgradeCol("oCourse", "RTimeLimit");
|
||||||
|
|
||||||
|
upgradeCol("oPunch", "Time");
|
||||||
|
|
||||||
|
upgradeCol("oRunner", "StartTime");
|
||||||
|
upgradeCol("oRunner", "FinishTime");
|
||||||
|
upgradeCol("oRunner", "InputTime");
|
||||||
|
alter("oRunner", "TimeAdjust");
|
||||||
|
upgradeCol("oRunner", "TimeAdjust");
|
||||||
|
upgradeCol("oRunner", "EntryTime");
|
||||||
|
|
||||||
|
upgradeCol("oTeam", "StartTime");
|
||||||
|
upgradeCol("oTeam", "FinishTime");
|
||||||
|
upgradeCol("oTeam", "InputTime");
|
||||||
|
alter("oTeam", "TimeAdjust");
|
||||||
|
upgradeCol("oTeam", "TimeAdjust");
|
||||||
|
upgradeCol("oTeam", "EntryTime");
|
||||||
|
}
|
||||||
|
|
||||||
OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
|
OpFailStatus MeosSQL::syncRead(bool forceRead, oTeam *t, bool readRecursive)
|
||||||
{
|
{
|
||||||
errorMessage.clear();
|
errorMessage.clear();
|
||||||
@ -2536,7 +2661,7 @@ OpFailStatus MeosSQL::syncReadControls(oEvent *oe, const set<int> &controls) {
|
|||||||
int counter = row["Counter"];
|
int counter = row["Counter"];
|
||||||
string modified = row["Modified"];
|
string modified = row["Modified"];
|
||||||
|
|
||||||
pControl pc = oe->getControl(id, false);
|
pControl pc = oe->getControl(id, false, false);
|
||||||
if (!pc) {
|
if (!pc) {
|
||||||
oControl oc(oe, id);
|
oControl oc(oe, id);
|
||||||
success = min(success, syncRead(true, &oc));
|
success = min(success, syncRead(true, &oc));
|
||||||
@ -2550,7 +2675,7 @@ OpFailStatus MeosSQL::syncReadControls(oEvent *oe, const set<int> &controls) {
|
|||||||
|
|
||||||
// processedCourses should now be empty, unless there are local controls not yet added.
|
// processedCourses should now be empty, unless there are local controls not yet added.
|
||||||
for(set<int>::iterator it = processedControls.begin(); it != processedControls.end(); ++it) {
|
for(set<int>::iterator it = processedControls.begin(); it != processedControls.end(); ++it) {
|
||||||
pControl pc = oe->getControl(*it, false);
|
pControl pc = oe->getControl(*it, false, false);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
success = min(success, syncUpdate(pc, true));
|
success = min(success, syncUpdate(pc, true));
|
||||||
}
|
}
|
||||||
@ -2647,7 +2772,7 @@ OpFailStatus MeosSQL::syncUpdate(oControl *c, bool forceWriteAll) {
|
|||||||
auto queryset = con->query();
|
auto queryset = con->query();
|
||||||
queryset << " Name=" << quote << toString(c->Name) << ", "
|
queryset << " Name=" << quote << toString(c->Name) << ", "
|
||||||
<< " Numbers=" << quote << toString(c->codeNumbers()) << ","
|
<< " Numbers=" << quote << toString(c->codeNumbers()) << ","
|
||||||
<< " Status=" << c->Status
|
<< " Status=" << int(c->Status)
|
||||||
<< c->getDI().generateSQLSet(forceWriteAll);
|
<< c->getDI().generateSQLSet(forceWriteAll);
|
||||||
|
|
||||||
return syncUpdate(queryset, "oControl", c);
|
return syncUpdate(queryset, "oControl", c);
|
||||||
@ -2826,8 +2951,9 @@ OpFailStatus MeosSQL::syncUpdate(oFreePunch *c, bool forceWriteAll)
|
|||||||
}
|
}
|
||||||
auto queryset = con->query();
|
auto queryset = con->query();
|
||||||
queryset << " CardNo=" << c->CardNo << ", "
|
queryset << " CardNo=" << c->CardNo << ", "
|
||||||
<< " Type=" << c->Type << ","
|
<< " Type=" << c->type << ","
|
||||||
<< " Time=" << c->Time;
|
<< " Time=" << c->punchTime << ","
|
||||||
|
<< " Unit=" << c->punchUnit;
|
||||||
|
|
||||||
return syncUpdate(queryset, "oPunch", c);
|
return syncUpdate(queryset, "oPunch", c);
|
||||||
}
|
}
|
||||||
@ -2974,38 +3100,55 @@ OpFailStatus MeosSQL::syncUpdate(QueryWrapper &updateqry,
|
|||||||
if (ob->isRemoved())
|
if (ob->isRemoved())
|
||||||
return opStatusOK;
|
return opStatusOK;
|
||||||
bool setId = false;
|
bool setId = false;
|
||||||
|
bool update = false;
|
||||||
if (ob->Id > 0) {
|
if (ob->Id > 0) {
|
||||||
query << "SELECT Id FROM " << oTable << " WHERE Id=" << ob->Id;
|
query << "SELECT Removed FROM " << oTable << " WHERE Id=" << ob->Id;
|
||||||
auto res=query.store();
|
auto res=query.store();
|
||||||
if (res.empty())
|
if (res.empty())
|
||||||
setId = true;
|
setId = true;
|
||||||
else if (ob->isImplicitlyCreated()) {
|
else if (ob->isImplicitlyCreated()) {
|
||||||
return opStatusWarning;//XXX Should we read this object?
|
return opStatusWarning;//XXX Should we read this object?
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
int removed = res.at(0).at(0);
|
||||||
|
if (removed) {
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(!ob->isImplicitlyCreated());
|
assert(!ob->isImplicitlyCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
query << "INSERT INTO " << oTable << " SET " << updateqry.str();
|
if (update) {
|
||||||
|
query << "UPDATE " << oTable << " SET Removed = 0, " << updateqry.str();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
query << "INSERT INTO " << oTable << " SET " << updateqry.str();
|
||||||
|
|
||||||
if (setId)
|
if (setId)
|
||||||
query << ", Id=" << ob->Id;
|
query << ", Id=" << ob->Id;
|
||||||
|
}
|
||||||
|
|
||||||
if (writeTime) {
|
if (writeTime) {
|
||||||
query << ", Modified='" << ob->getTimeStampN() << "'";
|
query << ", Modified='" << ob->getTimeStampN() << "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
query << " WHERE Id=" << ob->Id;
|
||||||
|
}
|
||||||
|
|
||||||
ResNSel res=query.execute();
|
ResNSel res=query.execute();
|
||||||
if (res) {
|
if (res) {
|
||||||
if (ob->Id > 0 && ob->Id!=(int)res.insert_id) {
|
if (!update) {
|
||||||
ob->correctionNeeded = true;
|
if (ob->Id > 0 && ob->Id != (int)res.insert_id) {
|
||||||
}
|
ob->correctionNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ob->Id != res.insert_id)
|
if (ob->Id != res.insert_id)
|
||||||
ob->changeId((int)res.insert_id);
|
ob->changeId((int)res.insert_id);
|
||||||
|
}
|
||||||
|
|
||||||
updateCounter(oTable, ob->Id, 0);
|
updateCounter(oTable, ob->Id, 0);
|
||||||
ob->oe->updateFreeId(ob);
|
ob->oe->updateFreeId(ob);
|
||||||
@ -3059,8 +3202,12 @@ OpFailStatus MeosSQL::syncUpdate(QueryWrapper &updateqry,
|
|||||||
|
|
||||||
bool MeosSQL::checkOldVersion(oEvent *oe, RowWrapper &row) {
|
bool MeosSQL::checkOldVersion(oEvent *oe, RowWrapper &row) {
|
||||||
int dbv=int(row["BuildVersion"]);
|
int dbv=int(row["BuildVersion"]);
|
||||||
if ( dbv<buildVersion )
|
if (dbv < buildVersion) {
|
||||||
oe->updateChanged();
|
string bv = "UPDATE oEvent SET BuildVersion=if (BuildVersion<" +
|
||||||
|
itos(buildVersion) + "," + itos(buildVersion) + ",BuildVersion) WHERE Id = " + itos(oe->Id);
|
||||||
|
|
||||||
|
con->query().exec(bv);
|
||||||
|
}
|
||||||
else if (dbv>buildVersion)
|
else if (dbv>buildVersion)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -3552,7 +3699,7 @@ bool MeosSQL::syncListControl(oEvent *oe) {
|
|||||||
|
|
||||||
if (int(row["Removed"])) {
|
if (int(row["Removed"])) {
|
||||||
st = opStatusOK;
|
st = opStatusOK;
|
||||||
oControl *c = oe->getControl(Id, false);
|
oControl *c = oe->getControl(Id, false, false);
|
||||||
|
|
||||||
if (c && !c->Removed) {
|
if (c && !c->Removed) {
|
||||||
c->Removed = true;
|
c->Removed = true;
|
||||||
@ -3562,7 +3709,7 @@ bool MeosSQL::syncListControl(oEvent *oe) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
oControl *c = oe->getControl(Id, false);
|
oControl *c = oe->getControl(Id, false, false);
|
||||||
if (c) {
|
if (c) {
|
||||||
if (isOld(counter, modified, c))
|
if (isOld(counter, modified, c))
|
||||||
st = syncRead(false, c);
|
st = syncRead(false, c);
|
||||||
@ -3848,11 +3995,12 @@ bool MeosSQL::dropDatabase(oEvent *oe)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string error;
|
||||||
try {
|
try {
|
||||||
con->drop_db(CmpDataBase);
|
con->drop_db(CmpDataBase);
|
||||||
}
|
}
|
||||||
catch (const Exception& ) {
|
catch (const Exception& ex) {
|
||||||
//Don't care if we fail.
|
error = ex.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -3860,7 +4008,10 @@ bool MeosSQL::dropDatabase(oEvent *oe)
|
|||||||
query << "DELETE FROM oEvent WHERE NameId=" << quote << CmpDataBase;
|
query << "DELETE FROM oEvent WHERE NameId=" << quote << CmpDataBase;
|
||||||
query.execute();
|
query.execute();
|
||||||
}
|
}
|
||||||
catch (const Exception& ) {
|
catch (const Exception& ex) {
|
||||||
|
if (!error.empty())
|
||||||
|
error += ", ";
|
||||||
|
error += ex.what();
|
||||||
//Don't care if we fail.
|
//Don't care if we fail.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3874,6 +4025,9 @@ bool MeosSQL::dropDatabase(oEvent *oe)
|
|||||||
catch (const Exception&) {
|
catch (const Exception&) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!error.empty())
|
||||||
|
throw meosException(error);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3930,7 +4084,9 @@ int getTypeId(const oBase &ob)
|
|||||||
}
|
}
|
||||||
static int skipped = 0, notskipped = 0, readent = 0;
|
static int skipped = 0, notskipped = 0, readent = 0;
|
||||||
|
|
||||||
void MeosSQL::synchronized(const oBase &entity) {
|
void MeosSQL::synchronized(oBase &entity) {
|
||||||
|
entity.Modified.setStamp(entity.sqlUpdated);
|
||||||
|
|
||||||
int id = getTypeId(entity);
|
int id = getTypeId(entity);
|
||||||
readTimes[make_pair(id, entity.getId())] = GetTickCount();
|
readTimes[make_pair(id, entity.getId())] = GetTickCount();
|
||||||
readent++;
|
readent++;
|
||||||
@ -4460,3 +4616,96 @@ OpFailStatus MeosSQL::synchronizeUpdate(oBase *obj) {
|
|||||||
return OpFailStatus::opStatusFail;
|
return OpFailStatus::opStatusFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpFailStatus MeosSQL::enumerateImages(vector<pair<wstring, uint64_t>>& images) {
|
||||||
|
try {
|
||||||
|
auto query = con->query();
|
||||||
|
images.clear();
|
||||||
|
auto res = query.store("SELECT Id, Filename FROM oImage");
|
||||||
|
if (res) {
|
||||||
|
for (int i = 0; i < res.num_rows(); i++) {
|
||||||
|
auto row = res.at(i);
|
||||||
|
wstring fileName = fromUTF((string)row["Filename"]);
|
||||||
|
uint64_t id = row["Id"].ulonglong();
|
||||||
|
images.emplace_back(fileName, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const Exception& ) {
|
||||||
|
return OpFailStatus::opStatusFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpFailStatus::opStatusOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpFailStatus MeosSQL::getImage(uint64_t id, wstring& fileName, vector<uint8_t>& data) {
|
||||||
|
try {
|
||||||
|
auto query = con->query();
|
||||||
|
auto res = query.store("SELECT * FROM oImage WHERE id=" + itos(id));
|
||||||
|
if (res && res.num_rows() > 0) {
|
||||||
|
auto row = res.at(0);
|
||||||
|
fileName = fromUTF((string)row["Filename"]);
|
||||||
|
row["Image"].storeBlob(data);
|
||||||
|
return OpFailStatus::opStatusOK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const Exception&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpFailStatus::opStatusFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
string hexEncode(const vector<uint8_t>& data) {
|
||||||
|
string out;
|
||||||
|
out.reserve(4 + data.size() * 2);
|
||||||
|
out.append("X'");
|
||||||
|
|
||||||
|
char table[17] = "0123456789ABCDEF";
|
||||||
|
char block[33];
|
||||||
|
block[32] = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < data.size();) {
|
||||||
|
if (j + 16 < data.size()) {
|
||||||
|
for (int i = 0; i < 32; ) {
|
||||||
|
uint8_t b = data[j];
|
||||||
|
int bLow = b & 0xF;
|
||||||
|
int bHigh = (b >> 4) & 0xF;
|
||||||
|
block[i++] = table[bHigh];
|
||||||
|
block[i++] = table[bLow];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int i = 0;
|
||||||
|
while (j < data.size()) {
|
||||||
|
uint8_t b = data[j];
|
||||||
|
int bLow = b & 0xF;
|
||||||
|
int bHigh = (b >> 4) & 0xF;
|
||||||
|
block[i++] = table[bHigh];
|
||||||
|
block[i++] = table[bLow];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
block[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(block);
|
||||||
|
}
|
||||||
|
out.append("'");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpFailStatus MeosSQL::storeImage(uint64_t id, const wstring& fileName, const vector<uint8_t>& data) {
|
||||||
|
try {
|
||||||
|
auto query = con->query();
|
||||||
|
auto res = query.store("SELECT Id FROM oImage WHERE Id=" + itos(id));
|
||||||
|
if (res.empty()) {
|
||||||
|
query << ("INSERT INTO oImage SET Id=" + itos(id) + ", Filename=")
|
||||||
|
<< quote << toString(fileName) << ", Image=" << hexEncode(data);
|
||||||
|
query.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception &) {
|
||||||
|
return OpFailStatus::opStatusFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpFailStatus::opStatusOK;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -131,7 +131,7 @@ protected:
|
|||||||
bool checkOldVersion(oEvent *oe, RowWrapper &row);
|
bool checkOldVersion(oEvent *oe, RowWrapper &row);
|
||||||
|
|
||||||
map<pair<int, int>, DWORD> readTimes;
|
map<pair<int, int>, DWORD> readTimes;
|
||||||
void synchronized(const oBase &entity);
|
void synchronized(oBase &entity);
|
||||||
bool skipSynchronize(const oBase &entity) const;
|
bool skipSynchronize(const oBase &entity) const;
|
||||||
|
|
||||||
ResNSel updateCounter(const char *oTable, int id, QueryWrapper *updateqry);
|
ResNSel updateCounter(const char *oTable, int id, QueryWrapper *updateqry);
|
||||||
@ -186,9 +186,14 @@ protected:
|
|||||||
OpFailStatus syncUpdate(oTeam *t, bool forceWriteAll);
|
OpFailStatus syncUpdate(oTeam *t, bool forceWriteAll);
|
||||||
OpFailStatus syncRead(bool forceRead, oTeam *t);
|
OpFailStatus syncRead(bool forceRead, oTeam *t);
|
||||||
|
|
||||||
|
void upgradeTimeFormat(const string &dbname);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
OpFailStatus enumerateImages(vector<pair<wstring, uint64_t>>& images);
|
||||||
|
OpFailStatus getImage(uint64_t id, wstring &fileName, vector<uint8_t> &data);
|
||||||
|
OpFailStatus storeImage(uint64_t id, const wstring& fileName, const vector<uint8_t>& data);
|
||||||
|
|
||||||
bool synchronizeList(oEvent *oe, oListId lid);
|
bool synchronizeList(oEvent *oe, oListId lid);
|
||||||
OpFailStatus synchronizeUpdate(oBase *obj);
|
OpFailStatus synchronizeUpdate(oBase *obj);
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -237,12 +237,12 @@ wstring RunnerWDBEntry::getFamilyName() const
|
|||||||
|
|
||||||
__int64 RunnerWDBEntry::getExtId() const
|
__int64 RunnerWDBEntry::getExtId() const
|
||||||
{
|
{
|
||||||
return dbe().extId;
|
return dbe().getExtId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnerWDBEntry::setExtId(__int64 id)
|
void RunnerWDBEntry::setExtId(__int64 id)
|
||||||
{
|
{
|
||||||
dbe().extId = id;
|
dbe().setExtId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnerDBEntryV2::init(const RunnerDBEntryV1 &dbe)
|
void RunnerDBEntryV2::init(const RunnerDBEntryV1 &dbe)
|
||||||
@ -303,7 +303,7 @@ RunnerWDBEntry *RunnerDB::addRunner(const wchar_t *name,
|
|||||||
en.cardNo = card;
|
en.cardNo = card;
|
||||||
en.clubNo = club;
|
en.clubNo = club;
|
||||||
e.setName(name);
|
e.setName(name);
|
||||||
en.extId = extId;
|
en.setExtId(extId);
|
||||||
|
|
||||||
if (!check(en) ) {
|
if (!check(en) ) {
|
||||||
rdb.pop_back();
|
rdb.pop_back();
|
||||||
@ -336,7 +336,7 @@ RunnerWDBEntry *RunnerDB::addRunner(const char *nameUTF,
|
|||||||
en.cardNo = card;
|
en.cardNo = card;
|
||||||
en.clubNo = club;
|
en.clubNo = club;
|
||||||
e.setNameUTF(nameUTF);
|
e.setNameUTF(nameUTF);
|
||||||
en.extId = extId;
|
en.setExtId(extId);
|
||||||
|
|
||||||
if (!check(en) ) {
|
if (!check(en) ) {
|
||||||
rdb.pop_back();
|
rdb.pop_back();
|
||||||
@ -550,16 +550,16 @@ RunnerWDBEntry *RunnerDB::getRunnerByName(const wstring &name, int clubId,
|
|||||||
int bestYear = 0;
|
int bestYear = 0;
|
||||||
for (size_t k = 0;k<ix2.size(); k++) {
|
for (size_t k = 0;k<ix2.size(); k++) {
|
||||||
const RunnerWDBEntry &re = rwdb[ix2[k]];
|
const RunnerWDBEntry &re = rwdb[ix2[k]];
|
||||||
if (abs(re.dbe().birthYear-expectedBirthYear) < abs(bestYear-expectedBirthYear)) {
|
if (abs(re.dbe().getBirthDay() - expectedBirthYear) < abs(bestYear - expectedBirthYear)) {
|
||||||
bestMatch = ix2[k];
|
bestMatch = ix2[k];
|
||||||
bestYear = re.dbe().birthYear;
|
bestYear = re.dbe().getBirthYear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bestYear>0)
|
if (bestYear>0)
|
||||||
return (RunnerWDBEntry *)&rwdb[bestMatch];
|
return (RunnerWDBEntry *)&rwdb[bestMatch];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnerDB::setupIdHash() const
|
void RunnerDB::setupIdHash() const
|
||||||
@ -569,7 +569,7 @@ void RunnerDB::setupIdHash() const
|
|||||||
|
|
||||||
for (size_t k=0; k<rdb.size(); k++) {
|
for (size_t k=0; k<rdb.size(); k++) {
|
||||||
if (!rdb[k].isRemoved())
|
if (!rdb[k].isRemoved())
|
||||||
idhash[rdb[k].extId] = int(k);
|
idhash[rdb[k].getExtId()] = int(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,13 +1076,13 @@ void RunnerDB::updateAdd(const oRunner &r, map<int, int> &clubIdMap)
|
|||||||
if (dbe == nullptr) {
|
if (dbe == nullptr) {
|
||||||
dbe = addRunner(r.getName().c_str(), 0, localClubId, r.getCardNo());
|
dbe = addRunner(r.getName().c_str(), 0, localClubId, r.getCardNo());
|
||||||
if (dbe)
|
if (dbe)
|
||||||
dbe->dbe().birthYear = r.getDCI().getInt("BirthYear");
|
dbe->dbe().setBirthYear(r.getDCI().getInt("BirthYear"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (dbe->getExtId() == 0) { // Only update entries not in national db.
|
if (dbe->getExtId() == 0) { // Only update entries not in national db.
|
||||||
dbe->setName(r.getName().c_str());
|
dbe->setName(r.getName().c_str());
|
||||||
dbe->dbe().clubNo = localClubId;
|
dbe->dbe().clubNo = localClubId;
|
||||||
dbe->dbe().birthYear = r.getDCI().getInt("BirthYear");
|
dbe->dbe().setBirthYear(r.getDCI().getInt("BirthYear"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1251,13 +1251,13 @@ const shared_ptr<Table> &RunnerDB::getRunnerTB() {
|
|||||||
auto table = make_shared<Table>(oe, 20, L"Löpardatabasen", "runnerdb");
|
auto table = make_shared<Table>(oe, 20, L"Löpardatabasen", "runnerdb");
|
||||||
|
|
||||||
table->addColumn("Index", 70, true, true);
|
table->addColumn("Index", 70, true, true);
|
||||||
table->addColumn("Id", 70, true, true);
|
table->addColumn("Externt Id", 70, true, true);
|
||||||
table->addColumn("Namn", 200, false);
|
table->addColumn("Namn", 200, false);
|
||||||
table->addColumn("Klubb", 200, false);
|
table->addColumn("Klubb", 200, false);
|
||||||
table->addColumn("SI", 70, true, true);
|
table->addColumn("SI", 70, true, true);
|
||||||
table->addColumn("Nationalitet", 70, false, true);
|
table->addColumn("Nationalitet", 70, false, true);
|
||||||
table->addColumn("Kön", 50, false, true);
|
table->addColumn("Kön", 50, false, true);
|
||||||
table->addColumn("Födelseår", 70, true, true);
|
table->addColumn("RunnerBirthDate", 70, true, true);
|
||||||
table->addColumn("Anmäl", 120, false, true);
|
table->addColumn("Anmäl", 120, false, true);
|
||||||
|
|
||||||
table->setTableProp(Table::CAN_INSERT|Table::CAN_DELETE|Table::CAN_PASTE);
|
table->setTableProp(Table::CAN_INSERT|Table::CAN_DELETE|Table::CAN_PASTE);
|
||||||
@ -1330,8 +1330,8 @@ void RunnerDB::refreshRunnerTableData(Table &table) {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
pRunner r = nullptr;
|
pRunner r = nullptr;
|
||||||
if (rdb[k].extId != 0)
|
if (rdb[k].getExtId() != 0)
|
||||||
found = runnerInEvent.lookup(rdb[k].extId, runnerId);
|
found = runnerInEvent.lookup(rdb[k].getExtId(), runnerId);
|
||||||
else if (rdb[k].cardNo != 0) {
|
else if (rdb[k].cardNo != 0) {
|
||||||
found = runnerInEvent.lookup(rdb[k].cardNo + cardIdConstant, runnerId);
|
found = runnerInEvent.lookup(rdb[k].cardNo + cardIdConstant, runnerId);
|
||||||
if (found) {
|
if (found) {
|
||||||
@ -1404,8 +1404,8 @@ void oDBRunnerEntry::addTableRow(Table &table) const {
|
|||||||
table.set(row++, it, TID_INDEX, itow(index+1), false, cellEdit);
|
table.set(row++, it, TID_INDEX, itow(index+1), false, cellEdit);
|
||||||
|
|
||||||
wchar_t bf[16];
|
wchar_t bf[16];
|
||||||
oBase::converExtIdentifierString(rn.extId, bf);
|
oBase::converExtIdentifierString(rn.getExtId(), bf);
|
||||||
table.set(row++, it, TID_ID, bf, false, cellEdit);
|
table.set(row++, it, TID_ID, bf, canEdit, cellEdit);
|
||||||
r.initName();
|
r.initName();
|
||||||
table.set(row++, it, TID_NAME, r.name, canEdit, cellEdit);
|
table.set(row++, it, TID_NAME, r.name, canEdit, cellEdit);
|
||||||
|
|
||||||
@ -1421,14 +1421,14 @@ void oDBRunnerEntry::addTableRow(Table &table) const {
|
|||||||
table.set(row++, it, TID_NATIONAL, nat, canEdit, cellEdit);
|
table.set(row++, it, TID_NATIONAL, nat, canEdit, cellEdit);
|
||||||
wchar_t sex[2] = {wchar_t(rn.sex), 0};
|
wchar_t sex[2] = {wchar_t(rn.sex), 0};
|
||||||
table.set(row++, it, TID_SEX, sex, canEdit, cellEdit);
|
table.set(row++, it, TID_SEX, sex, canEdit, cellEdit);
|
||||||
table.set(row++, it, TID_YEAR, itow(rn.birthYear), canEdit, cellEdit);
|
table.set(row++, it, TID_YEAR, rn.getBirthDate(), canEdit, cellEdit);
|
||||||
|
|
||||||
int runnerId;
|
int runnerId;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
pRunner cr = nullptr;
|
pRunner cr = nullptr;
|
||||||
if (rn.extId != 0)
|
if (rn.getExtId() != 0)
|
||||||
found = db->runnerInEvent.lookup(rn.extId, runnerId);
|
found = db->runnerInEvent.lookup(rn.getExtId(), runnerId);
|
||||||
else if (rn.cardNo != 0) {
|
else if (rn.cardNo != 0) {
|
||||||
found = db->runnerInEvent.lookup(rn.cardNo + cardIdConstant, runnerId);
|
found = db->runnerInEvent.lookup(rn.cardNo + cardIdConstant, runnerId);
|
||||||
if (found) {
|
if (found) {
|
||||||
@ -1467,8 +1467,29 @@ pair<int, bool> oDBRunnerEntry::inputData(int id, const wstring &input,
|
|||||||
throw meosException("Not initialized");
|
throw meosException("Not initialized");
|
||||||
RunnerWDBEntry &r = db->rwdb[index];
|
RunnerWDBEntry &r = db->rwdb[index];
|
||||||
RunnerDBEntry &rd = db->rdb[index];
|
RunnerDBEntry &rd = db->rdb[index];
|
||||||
|
static bool hasWarnedId = false;
|
||||||
|
|
||||||
switch(id) {
|
switch(id) {
|
||||||
|
case TID_ID: {
|
||||||
|
wchar_t bf[16];
|
||||||
|
auto key = oBase::converExtIdentifierString(input);
|
||||||
|
oBase::converExtIdentifierString(key, bf);
|
||||||
|
|
||||||
|
if (compareStringIgnoreCase(bf, input)) {
|
||||||
|
throw meosException(L"Cannot represent ID X#" + input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != r.getExtId() && !hasWarnedId) {
|
||||||
|
if (oe->gdiBase().askOkCancel(L"warn:changeid") == gdioutput::AskAnswer::AnswerCancel)
|
||||||
|
throw meosCancel();
|
||||||
|
hasWarnedId = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.setExtId(key);
|
||||||
|
db->idhash.clear();
|
||||||
|
output = bf;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TID_NAME:
|
case TID_NAME:
|
||||||
r.setName(input.c_str());
|
r.setName(input.c_str());
|
||||||
r.getName(output);
|
r.getName(output);
|
||||||
@ -1503,8 +1524,8 @@ pair<int, bool> oDBRunnerEntry::inputData(int id, const wstring &input,
|
|||||||
output = r.getSex();
|
output = r.getSex();
|
||||||
break;
|
break;
|
||||||
case TID_YEAR:
|
case TID_YEAR:
|
||||||
rd.birthYear = short(_wtoi(input.c_str()));
|
rd.setBirthDate(input);
|
||||||
output = itow(r.getBirthYear());
|
output = rd.getBirthDate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TID_CLUB:
|
case TID_CLUB:
|
||||||
@ -1529,7 +1550,7 @@ void oDBRunnerEntry::fillInput(int id, vector< pair<wstring, size_t> > &out, siz
|
|||||||
void oDBRunnerEntry::remove() {
|
void oDBRunnerEntry::remove() {
|
||||||
RunnerWDBEntry &r = db->rwdb[index];
|
RunnerWDBEntry &r = db->rwdb[index];
|
||||||
r.remove();
|
r.remove();
|
||||||
db->idhash.remove(r.dbe().extId);
|
db->idhash.remove(r.dbe().getExtId());
|
||||||
wstring cname(canonizeName(r.name));
|
wstring cname(canonizeName(r.name));
|
||||||
multimap<wstring, int>::const_iterator it = db->nhash.find(cname);
|
multimap<wstring, int>::const_iterator it = db->nhash.find(cname);
|
||||||
|
|
||||||
@ -1823,6 +1844,20 @@ vector<pair<RunnerWDBEntry *, int>> RunnerDB::getRunnerSuggestions(const wstring
|
|||||||
else
|
else
|
||||||
setupAutoCompleteHash(AutoHashMode::Runners);
|
setupAutoCompleteHash(AutoHashMode::Runners);
|
||||||
|
|
||||||
|
// Check if database key
|
||||||
|
int64_t id = 0;
|
||||||
|
for (int j = 0; j < key.length(); j++) {
|
||||||
|
if (key[j] >= '0' && key[j] <= '9') {
|
||||||
|
id = oBase::converExtIdentifierString(key);
|
||||||
|
wchar_t bf[16];
|
||||||
|
oBase::converExtIdentifierString(id, bf);
|
||||||
|
if (compareStringIgnoreCase(key, bf))
|
||||||
|
id = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vector< pair<int, int> > outOrder;
|
vector< pair<int, int> > outOrder;
|
||||||
set<pair<int, int>> ix;
|
set<pair<int, int>> ix;
|
||||||
wchar_t bf[256];
|
wchar_t bf[256];
|
||||||
@ -1866,8 +1901,15 @@ vector<pair<RunnerWDBEntry *, int>> RunnerDB::getRunnerSuggestions(const wstring
|
|||||||
if (res != runnerHash.end())
|
if (res != runnerHash.end())
|
||||||
res->second.match(*this, ix, nameParts);
|
res->second.match(*this, ix, nameParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id > 0) {
|
||||||
|
auto r = getRunnerById(id);
|
||||||
|
if (r) {
|
||||||
|
ix.emplace(1000, r->getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ix.empty())
|
if (ix.empty())
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1896,3 +1938,85 @@ vector<pair<RunnerWDBEntry *, int>> RunnerDB::getRunnerSuggestions(const wstring
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wstring& RunnerDBEntry::getBirthDate() const {
|
||||||
|
int year = getBirthYear();
|
||||||
|
if (year <= 0 || year>9999)
|
||||||
|
return _EmptyWString;
|
||||||
|
|
||||||
|
int month = getBirthMonth();
|
||||||
|
if (month > 0 && month <= 12) {
|
||||||
|
int day = getBirthDay();
|
||||||
|
if (day > 0 && day <= 31) {
|
||||||
|
wchar_t bf[16];
|
||||||
|
swprintf_s(bf, L"%d-%02d-%02d", year, month, day);
|
||||||
|
wstring& res = StringCache::getInstance().wget();
|
||||||
|
res = bf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itow(year);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerDBEntry::setBirthDate(const wstring& in) {
|
||||||
|
SYSTEMTIME st;
|
||||||
|
if (convertDateYMS(in, st, true) > 0) {
|
||||||
|
setBirthYear(st.wYear);
|
||||||
|
setBirthMonth(st.wMonth);
|
||||||
|
setBirthDay(st.wDay);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int year = _wtoi(in.c_str());
|
||||||
|
if (year > 1900 && year < 9999)
|
||||||
|
setBirthYear(year);
|
||||||
|
else
|
||||||
|
setBirthYear(0);
|
||||||
|
|
||||||
|
setBirthMonth(0);
|
||||||
|
setBirthDay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnerDBEntry::setBirthDate(int dateOrYear) {
|
||||||
|
if (dateOrYear > 0 && dateOrYear < 100)
|
||||||
|
dateOrYear = extendYear(dateOrYear);
|
||||||
|
|
||||||
|
if ((dateOrYear > 1900 && dateOrYear < 9999) || dateOrYear == 0) {
|
||||||
|
setBirthYear(dateOrYear);
|
||||||
|
setBirthMonth(0);
|
||||||
|
setBirthDay(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int d = dateOrYear % 100;
|
||||||
|
dateOrYear /= 100;
|
||||||
|
|
||||||
|
int m = dateOrYear % 100;
|
||||||
|
dateOrYear /= 100;
|
||||||
|
|
||||||
|
int y = extendYear(dateOrYear);
|
||||||
|
if (d > 0 && d <= 31 && m > 0 && m <= 12 && y > 1900 && y < 9999) {
|
||||||
|
setBirthYear(y);
|
||||||
|
setBirthMonth(m);
|
||||||
|
setBirthDay(d);
|
||||||
|
}
|
||||||
|
else if (y > 1900 && y < 9999) {
|
||||||
|
setBirthYear(y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setBirthYear(0);
|
||||||
|
setBirthMonth(0);
|
||||||
|
setBirthDay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunnerDBEntry::getBirthDateInt() const {
|
||||||
|
int y = getBirthYear();
|
||||||
|
int m = getBirthMonth();
|
||||||
|
int d = getBirthDay();
|
||||||
|
|
||||||
|
if (y > 0 && y < 9999 && m > 0 && d > 0)
|
||||||
|
return y * 10000 + m * 100 + d;
|
||||||
|
else
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -97,11 +97,13 @@ struct RunnerDBEntry {
|
|||||||
int clubNo;
|
int clubNo;
|
||||||
char national[3];
|
char national[3];
|
||||||
char sex;
|
char sex;
|
||||||
|
private:
|
||||||
short int birthYear;
|
short int birthYear;
|
||||||
short int reserved;
|
short int reserved;
|
||||||
/** End of V1*/
|
/** End of V1*/
|
||||||
__int64 extId;
|
__int64 extId;
|
||||||
|
|
||||||
|
public:
|
||||||
bool isRemoved() const { return (reserved & 1) == 1; }
|
bool isRemoved() const { return (reserved & 1) == 1; }
|
||||||
void remove() { reserved |= 1; }
|
void remove() { reserved |= 1; }
|
||||||
|
|
||||||
@ -111,6 +113,22 @@ struct RunnerDBEntry {
|
|||||||
bool operator==(const RunnerDBEntry &d) const {
|
bool operator==(const RunnerDBEntry &d) const {
|
||||||
return memcmp(this, &d, sizeof(RunnerDBEntry)) == 0;
|
return memcmp(this, &d, sizeof(RunnerDBEntry)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getBirthYear() const { return birthYear; }
|
||||||
|
int getBirthMonth() const { return (reserved >> 2) & 0xF; }// 4 bits
|
||||||
|
int getBirthDay() const { return (reserved >> 6) & 0x1F; } // 5 bits
|
||||||
|
|
||||||
|
void setBirthYear(int year) { birthYear = year; }
|
||||||
|
void setBirthMonth(int month) { reserved = (reserved & (~(0xF << 2))) | ((0xF & month) << 2); }// 4 bits
|
||||||
|
void setBirthDay(int day) { reserved = (reserved & (~(0x1F << 6))) | ((0x1F & day) << 6); } // 5 bits
|
||||||
|
|
||||||
|
const wstring& getBirthDate() const;
|
||||||
|
void setBirthDate(const wstring& in);
|
||||||
|
void setBirthDate(int dateOrYear);
|
||||||
|
int getBirthDateInt() const;
|
||||||
|
|
||||||
|
void setExtId(__int64 id) { extId = id; }
|
||||||
|
__int64 getExtId() const { return extId; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunnerDB;
|
class RunnerDB;
|
||||||
@ -125,6 +143,8 @@ public:
|
|||||||
void init(RunnerDB *p, size_t ix);
|
void init(RunnerDB *p, size_t ix);
|
||||||
RunnerWDBEntry();
|
RunnerWDBEntry();
|
||||||
|
|
||||||
|
size_t getIndex() const { return ix; }
|
||||||
|
|
||||||
// Link to narrow DB Entry
|
// Link to narrow DB Entry
|
||||||
const RunnerDBEntry &dbe() const;
|
const RunnerDBEntry &dbe() const;
|
||||||
RunnerDBEntry &dbe();
|
RunnerDBEntry &dbe();
|
||||||
@ -145,14 +165,14 @@ public:
|
|||||||
wstring getFamilyName() const;
|
wstring getFamilyName() const;
|
||||||
|
|
||||||
wstring getNationality() const;
|
wstring getNationality() const;
|
||||||
int getBirthYear() const {return dbe().birthYear;}
|
int getBirthYear() const {return dbe().getBirthYear(); }
|
||||||
wstring getSex() const;
|
wstring getSex() const;
|
||||||
|
|
||||||
__int64 getExtId() const;
|
__int64 getExtId() const;
|
||||||
void setExtId(__int64 id);
|
void setExtId(__int64 id);
|
||||||
|
|
||||||
bool isRemoved() const {return (dbe().reserved & 1) == 1;}
|
bool isRemoved() const { return dbe().isRemoved(); }
|
||||||
void remove() {dbe().reserved |= 1;}
|
void remove() { dbe().remove(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<RunnerDBEntry> RunnerDBVector;
|
typedef vector<RunnerDBEntry> RunnerDBVector;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -46,11 +46,11 @@
|
|||||||
//#define DEBUG_SI
|
//#define DEBUG_SI
|
||||||
|
|
||||||
SI_StationData::SI_StationData() {
|
SI_StationData::SI_StationData() {
|
||||||
stationNumber=0;
|
stationNumber = 0;
|
||||||
stationMode=0;
|
stationMode = 0;
|
||||||
extended=false;
|
extended = false;
|
||||||
handShake=false;
|
handShake = false;
|
||||||
autoSend=false;
|
autoSend = false;
|
||||||
radioChannel = 0;
|
radioChannel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,19 +64,28 @@ SI_StationInfo::SI_StationInfo()
|
|||||||
localZeroTime=0;
|
localZeroTime=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SportIdent::SportIdent(HWND hWnd, DWORD Id, bool readVoltage) : readVoltage(readVoltage)
|
SportIdent::SportIdent(HWND hWnd, DWORD Id, bool readVoltage) : readVoltage(readVoltage) {
|
||||||
{
|
ClassId = Id;
|
||||||
ClassId=Id;
|
hWndNotify = hWnd;
|
||||||
hWndNotify=hWnd;
|
|
||||||
|
|
||||||
//hComm=0;
|
n_SI_Info = 0;
|
||||||
//ThreadHandle=0;
|
|
||||||
n_SI_Info=0;
|
|
||||||
|
|
||||||
InitializeCriticalSection(&SyncObj);
|
InitializeCriticalSection(&SyncObj);
|
||||||
|
|
||||||
tcpPortOpen=0;
|
tcpPortOpen = 0;
|
||||||
serverSocket=0;
|
serverSocket = 0;
|
||||||
|
punchMap.resize(31, 0);
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchStart] = oPunch::SpecialPunch::PunchStart;
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchCheck] = oPunch::SpecialPunch::PunchCheck;
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchFinish] = oPunch::SpecialPunch::PunchFinish;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SportIdent::resetPunchMap() {
|
||||||
|
punchMap.resize(31, 0);
|
||||||
|
fill(punchMap.begin(), punchMap.end(), 0);
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchStart] = oPunch::SpecialPunch::PunchStart;
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchCheck] = oPunch::SpecialPunch::PunchCheck;
|
||||||
|
punchMap[oPunch::SpecialPunch::PunchFinish] = oPunch::SpecialPunch::PunchFinish;
|
||||||
}
|
}
|
||||||
|
|
||||||
SportIdent::~SportIdent()
|
SportIdent::~SportIdent()
|
||||||
@ -299,7 +308,7 @@ string decode(BYTE *bf, int read)
|
|||||||
bool SportIdent::openComListen(const wchar_t *com, DWORD BaudRate) {
|
bool SportIdent::openComListen(const wchar_t *com, DWORD BaudRate) {
|
||||||
closeCom(com);
|
closeCom(com);
|
||||||
|
|
||||||
SI_StationInfo *si = findStation(com);
|
SI_StationInfo *si = findStationInt(com);
|
||||||
|
|
||||||
if (!si) {
|
if (!si) {
|
||||||
SI_Info[n_SI_Info].ComPort=com;
|
SI_Info[n_SI_Info].ComPort=com;
|
||||||
@ -309,6 +318,9 @@ bool SportIdent::openComListen(const wchar_t *com, DWORD BaudRate) {
|
|||||||
}
|
}
|
||||||
si->data.clear();
|
si->data.clear();
|
||||||
|
|
||||||
|
if (si->ComPort == L"TEST")
|
||||||
|
return true; // Passive test
|
||||||
|
|
||||||
wstring comfile=wstring(L"//./")+com;
|
wstring comfile=wstring(L"//./")+com;
|
||||||
si->hComm = CreateFile( comfile.c_str(),
|
si->hComm = CreateFile( comfile.c_str(),
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
@ -355,7 +367,7 @@ bool SportIdent::tcpAddPort(int port, DWORD zeroTime)
|
|||||||
{
|
{
|
||||||
closeCom(L"TCP");
|
closeCom(L"TCP");
|
||||||
|
|
||||||
SI_StationInfo *si = findStation(L"TCP");
|
SI_StationInfo *si = findStationInt(L"TCP");
|
||||||
|
|
||||||
if (!si) {
|
if (!si) {
|
||||||
SI_Info[n_SI_Info].ComPort=L"TCP";
|
SI_Info[n_SI_Info].ComPort=L"TCP";
|
||||||
@ -374,7 +386,7 @@ bool SportIdent::openCom(const wchar_t *com)
|
|||||||
{
|
{
|
||||||
closeCom(com);
|
closeCom(com);
|
||||||
|
|
||||||
SI_StationInfo *si = findStation(com);
|
SI_StationInfo *si = findStationInt(com);
|
||||||
|
|
||||||
if (!si) {
|
if (!si) {
|
||||||
SI_Info[n_SI_Info].ComPort=com;
|
SI_Info[n_SI_Info].ComPort=com;
|
||||||
@ -386,7 +398,7 @@ bool SportIdent::openCom(const wchar_t *com)
|
|||||||
si->data.clear();
|
si->data.clear();
|
||||||
|
|
||||||
if (si->ComPort == L"TEST") {
|
if (si->ComPort == L"TEST") {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring comfile=wstring(L"//./")+com;
|
wstring comfile=wstring(L"//./")+com;
|
||||||
@ -511,9 +523,7 @@ bool SportIdent::openCom(const wchar_t *com)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SI_StationInfo* SportIdent::findStationInt(const wstring& com) {
|
||||||
SI_StationInfo *SportIdent::findStation(const wstring &com)
|
|
||||||
{
|
|
||||||
if (com == L"TEST" && n_SI_Info < 30) {
|
if (com == L"TEST" && n_SI_Info < 30) {
|
||||||
if (n_SI_Info == 0 || SI_Info[n_SI_Info - 1].ComPort != com) {
|
if (n_SI_Info == 0 || SI_Info[n_SI_Info - 1].ComPort != com) {
|
||||||
SI_Info[n_SI_Info].ComPort = com;
|
SI_Info[n_SI_Info].ComPort = com;
|
||||||
@ -521,6 +531,26 @@ SI_StationInfo *SportIdent::findStation(const wstring &com)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < n_SI_Info; i++)
|
||||||
|
if (com == SI_Info[i].ComPort)
|
||||||
|
return &SI_Info[i];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SportIdent::addTestStation(const wstring& com) {
|
||||||
|
SI_Info[n_SI_Info].ComPort = com;
|
||||||
|
n_SI_Info++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SI_StationInfo *SportIdent::findStation(const wstring &com) const
|
||||||
|
{
|
||||||
|
if (com == L"TEST" && n_SI_Info < 30) {
|
||||||
|
if (n_SI_Info == 0 || SI_Info[n_SI_Info - 1].ComPort != com) {
|
||||||
|
const_cast<SportIdent*>(this)->addTestStation(com);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(int i=0;i<n_SI_Info; i++)
|
for(int i=0;i<n_SI_Info; i++)
|
||||||
if (com == SI_Info[i].ComPort)
|
if (com == SI_Info[i].ComPort)
|
||||||
return &SI_Info[i];
|
return &SI_Info[i];
|
||||||
@ -537,7 +567,7 @@ void SportIdent::closeCom(const wchar_t *com)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SI_StationInfo *si = findStation(com);
|
SI_StationInfo *si = findStationInt(com);
|
||||||
|
|
||||||
if (si && si->ComPort==L"TCP") {
|
if (si && si->ComPort==L"TCP") {
|
||||||
if (tcpPortOpen) {
|
if (tcpPortOpen) {
|
||||||
@ -890,7 +920,7 @@ int SportIdent::MonitorTCPSI(WORD port, int localZeroTime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addPunch(op.CodeTime/10, op.CodeNo, op.SICardNo, 0);
|
addPunch(op.CodeTime, op.CodeNo, op.SICardNo, 0);
|
||||||
}
|
}
|
||||||
else r=-1;
|
else r=-1;
|
||||||
|
|
||||||
@ -933,10 +963,10 @@ bool SportIdent::MonitorTEST(SI_StationInfo &si)
|
|||||||
|
|
||||||
SICard card(ConvertedTimeStatus::Hour12);
|
SICard card(ConvertedTimeStatus::Hour12);
|
||||||
card.StartPunch.Code = 1;
|
card.StartPunch.Code = 1;
|
||||||
int t = card.StartPunch.Time = 3600*8 + rand()%1000;
|
int t = card.StartPunch.Time = timeConstHour*8 + rand()%1000;
|
||||||
|
|
||||||
card.FinishPunch.Code = 2;
|
card.FinishPunch.Code = 2;
|
||||||
card.FinishPunch.Time = card.StartPunch.Time + 1800 + rand() % 3600;
|
card.FinishPunch.Time = card.StartPunch.Time + timeConstHour/2 + rand() % timeConstHour;
|
||||||
card.CardNumber = tc.cardNo;
|
card.CardNumber = tc.cardNo;
|
||||||
|
|
||||||
for (size_t k = 0; k < tc.punches.size(); k++) {
|
for (size_t k = 0; k < tc.punches.size(); k++) {
|
||||||
@ -947,8 +977,8 @@ bool SportIdent::MonitorTEST(SI_StationInfo &si)
|
|||||||
}
|
}
|
||||||
addCard(card);
|
addCard(card);
|
||||||
|
|
||||||
//Sleep(300 + rand()%600);
|
Sleep(300 + rand()%600);
|
||||||
Sleep(0);
|
//Sleep(0);
|
||||||
if (++longSleepIter > 20) {
|
if (++longSleepIter > 20) {
|
||||||
Sleep(100 + rand() % 600);
|
Sleep(100 + rand() % 600);
|
||||||
longSleepIter = 0;
|
longSleepIter = 0;
|
||||||
@ -1002,12 +1032,15 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
|
|
||||||
DWORD Card=MAKELONG(MAKEWORD(bf[7], bf[6]), MAKEWORD(bf[5], bf[4]));
|
DWORD Card=MAKELONG(MAKEWORD(bf[7], bf[6]), MAKEWORD(bf[5], bf[4]));
|
||||||
|
|
||||||
if (Series<=4 && Series>=1)
|
if (Series <= 4 && Series >= 1)
|
||||||
Card=ShortCard+100000*Series;
|
Card = ShortCard + 100000 * Series;
|
||||||
|
|
||||||
DWORD Time=0;
|
DWORD Time=0;
|
||||||
if (bf[8]&0x1) Time=3600*12;
|
if (bf[8] & 0x1) Time = timeConstHour * 12;
|
||||||
Time+=MAKEWORD(bf[10], bf[9]);
|
Time += MAKEWORD(bf[10], bf[9])*timeConstSecond;
|
||||||
|
uint8_t tss = bf[11]; // Sub second 1/256 seconds
|
||||||
|
int tenth = (((100 * tss) / 256) + 4) / 10;
|
||||||
|
Time += tenth;
|
||||||
#ifdef DEBUG_SI
|
#ifdef DEBUG_SI
|
||||||
char str[128];
|
char str[128];
|
||||||
sprintf_s(str, "EXTENDED: Card = %d, Station = %d, StationMode = %d", Card, Station, si.StationMode);
|
sprintf_s(str, "EXTENDED: Card = %d, Station = %d, StationMode = %d", Card, Station, si.StationMode);
|
||||||
@ -1040,9 +1073,9 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
//if (Series!=1)
|
//if (Series!=1)
|
||||||
// Card+=100000*Series;
|
// Card+=100000*Series;
|
||||||
|
|
||||||
DWORD Time=MAKEWORD(bf[8], bf[7]);
|
DWORD Time = MAKEWORD(bf[8], bf[7]) * timeConstSecond;
|
||||||
BYTE p=bf[1];
|
BYTE p=bf[1];
|
||||||
if (p&0x1) Time+=3600*12;
|
if (p&0x1) Time+=timeConstHour*12;
|
||||||
|
|
||||||
#ifdef DEBUG_SI
|
#ifdef DEBUG_SI
|
||||||
char str[128];
|
char str[128];
|
||||||
@ -1100,7 +1133,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
bf[0]=chRead;
|
bf[0]=chRead;
|
||||||
readBytes(bf+1, 200, hComm);
|
readBytes(bf+1, 200, hComm);
|
||||||
//GetSI5DataExt(hComm);
|
//GetSI5DataExt(hComm);
|
||||||
MessageBox(NULL, L"Programmera stationen utan AUTOSEND!", NULL, MB_OK);
|
MessageBox(NULL, lang.tl(L"Programmera stationen utan AUTOSEND").c_str(), NULL, MB_OK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1108,7 +1141,7 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
BYTE bf[200];
|
BYTE bf[200];
|
||||||
bf[0]=chRead;
|
bf[0]=chRead;
|
||||||
readBytes(bf+1, 200, hComm);
|
readBytes(bf+1, 200, hComm);
|
||||||
MessageBox(NULL, L"Programmera stationen utan AUTOSEND!", NULL, MB_OK);
|
MessageBox(NULL, lang.tl(L"Programmera stationen utan AUTOSEND").c_str(), NULL, MB_OK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xE8:{
|
case 0xE8:{
|
||||||
@ -1125,7 +1158,6 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
// MessageBox(NULL, "SI-card not supported", NULL, MB_OK);
|
// MessageBox(NULL, "SI-card not supported", NULL, MB_OK);
|
||||||
// break;
|
// break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
BYTE bf[128];
|
BYTE bf[128];
|
||||||
bf[0]=chRead;
|
bf[0]=chRead;
|
||||||
int rb=readBytes(bf+1, 120, hComm);
|
int rb=readBytes(bf+1, 120, hComm);
|
||||||
@ -1146,6 +1178,9 @@ bool SportIdent::MonitorSI(SI_StationInfo &si)
|
|||||||
st+=d;
|
st+=d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chRead == 0xEF)
|
||||||
|
MessageBox(NULL, lang.tl(L"Programmera stationen utan AUTOSEND").c_str(), NULL, MB_OK);
|
||||||
//MessageBox(NULL, st.c_str(), "Unknown SI response", MB_OK);
|
//MessageBox(NULL, st.c_str(), "Unknown SI response", MB_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1650,8 +1685,6 @@ bool SportIdent::getCard5Data(BYTE *data, SICard &card)
|
|||||||
analyseSI5Time(data+5, card.FinishPunch.Time, card.FinishPunch.Code);
|
analyseSI5Time(data+5, card.FinishPunch.Time, card.FinishPunch.Code);
|
||||||
analyseSI5Time(data+9, card.CheckPunch.Time, card.CheckPunch.Code);
|
analyseSI5Time(data+9, card.CheckPunch.Time, card.CheckPunch.Code);
|
||||||
|
|
||||||
// card.StartPunch=MAKEWORD(data[4], data[3]);
|
|
||||||
// card.FinishPunch=MAKEWORD(data[6], data[5]);
|
|
||||||
card.nPunch=data[7]-1;
|
card.nPunch=data[7]-1;
|
||||||
|
|
||||||
data+=16;
|
data+=16;
|
||||||
@ -1660,7 +1693,7 @@ bool SportIdent::getCard5Data(BYTE *data, SICard &card)
|
|||||||
if (k<30) {
|
if (k<30) {
|
||||||
DWORD basepointer=3*(k%5)+1+(k/5)*16;
|
DWORD basepointer=3*(k%5)+1+(k/5)*16;
|
||||||
DWORD code=data[basepointer];
|
DWORD code=data[basepointer];
|
||||||
DWORD time;//=MAKEWORD(data[basepointer+2],data[basepointer+1]);
|
DWORD time;
|
||||||
DWORD slask;
|
DWORD slask;
|
||||||
analyseSI5Time(data+basepointer+1, time, slask);
|
analyseSI5Time(data+basepointer+1, time, slask);
|
||||||
|
|
||||||
@ -1710,29 +1743,29 @@ bool SportIdent::getCard9Data(BYTE *data, SICard &card)
|
|||||||
int series = data[24] & 15;
|
int series = data[24] & 15;
|
||||||
|
|
||||||
card.convertedTime = ConvertedTimeStatus::Hour24;
|
card.convertedTime = ConvertedTimeStatus::Hour24;
|
||||||
analysePunch(data+12, card.StartPunch.Time, card.StartPunch.Code);
|
analysePunch(data+12, card.StartPunch.Time, card.StartPunch.Code, useSubsecondMode);
|
||||||
analysePunch(data+16, card.FinishPunch.Time, card.FinishPunch.Code);
|
analysePunch(data+16, card.FinishPunch.Time, card.FinishPunch.Code, useSubsecondMode);
|
||||||
analysePunch(data+8, card.CheckPunch.Time, card.CheckPunch.Code);
|
analysePunch(data+8, card.CheckPunch.Time, card.CheckPunch.Code, false);
|
||||||
|
|
||||||
if (series == 1) {
|
if (series == 1) {
|
||||||
// SI Card 9
|
// SI Card 9
|
||||||
card.nPunch=min(int(data[22]), 50);
|
card.nPunch=min(int(data[22]), 50);
|
||||||
for(unsigned k=0;k<card.nPunch;k++) {
|
for(unsigned k=0;k<card.nPunch;k++) {
|
||||||
analysePunch(14*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code);
|
analysePunch(14*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (series == 2) {
|
else if (series == 2) {
|
||||||
// SI Card 8
|
// SI Card 8
|
||||||
card.nPunch=min(int(data[22]), 30);
|
card.nPunch=min(int(data[22]), 30);
|
||||||
for(unsigned k=0;k<card.nPunch;k++) {
|
for(unsigned k=0;k<card.nPunch;k++) {
|
||||||
analysePunch(34*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code);
|
analysePunch(34*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (series == 4) {
|
else if (series == 4) {
|
||||||
// pCard
|
// pCard
|
||||||
card.nPunch=min(int(data[22]), 20);
|
card.nPunch=min(int(data[22]), 20);
|
||||||
for(unsigned k=0;k<card.nPunch;k++) {
|
for(unsigned k=0;k<card.nPunch;k++) {
|
||||||
analysePunch(44*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code);
|
analysePunch(44*4 + data + 4*k, card.Punch[k].Time, card.Punch[k].Code, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (series == 6) {
|
else if (series == 6) {
|
||||||
@ -1751,7 +1784,7 @@ bool SportIdent::getCard9Data(BYTE *data, SICard &card)
|
|||||||
// Card 10, 11, SIAC
|
// Card 10, 11, SIAC
|
||||||
card.nPunch=min(int(data[22]), 128);
|
card.nPunch=min(int(data[22]), 128);
|
||||||
for(unsigned k=0;k<card.nPunch;k++) {
|
for(unsigned k=0;k<card.nPunch;k++) {
|
||||||
analysePunch(data + 128 + 4*k, card.Punch[k].Time, card.Punch[k].Code);
|
analysePunch(data + 128 + 4*k, card.Punch[k].Time, card.Punch[k].Code, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1774,7 +1807,7 @@ void SportIdent::analyseTPunch(BYTE *data, DWORD &time, DWORD &control) {
|
|||||||
// BYTE day = (dt0 >> 1) & 0x1F;
|
// BYTE day = (dt0 >> 1) & 0x1F;
|
||||||
|
|
||||||
control=cn;
|
control=cn;
|
||||||
time=MAKEWORD(ptl, pth)+3600*12*(dt0&0x1);
|
time = MAKEWORD(ptl, pth) * timeConstSecond + timeConstHour * 12 * (dt0 & 0x1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
control=-1;
|
control=-1;
|
||||||
@ -1810,9 +1843,9 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
|||||||
// DWORD control;
|
// DWORD control;
|
||||||
// DWORD time;
|
// DWORD time;
|
||||||
card.convertedTime = ConvertedTimeStatus::Hour24;
|
card.convertedTime = ConvertedTimeStatus::Hour24;
|
||||||
analysePunch(data+8, card.StartPunch.Time, card.StartPunch.Code);
|
analysePunch(data+8, card.StartPunch.Time, card.StartPunch.Code, useSubsecondMode);
|
||||||
analysePunch(data+4, card.FinishPunch.Time, card.FinishPunch.Code);
|
analysePunch(data+4, card.FinishPunch.Time, card.FinishPunch.Code, useSubsecondMode);
|
||||||
analysePunch(data+12, card.CheckPunch.Time, card.CheckPunch.Code);
|
analysePunch(data+12, card.CheckPunch.Time, card.CheckPunch.Code, false);
|
||||||
card.nPunch=min(int(data[2]), 192);
|
card.nPunch=min(int(data[2]), 192);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -1843,12 +1876,12 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
|||||||
data+=128-16;
|
data+=128-16;
|
||||||
|
|
||||||
for(unsigned k=0;k<card.nPunch;k++) {
|
for(unsigned k=0;k<card.nPunch;k++) {
|
||||||
analysePunch(data+4*k, card.Punch[k].Time, card.Punch[k].Code);
|
analysePunch(data+4*k, card.Punch[k].Time, card.Punch[k].Code, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for extra punches, SI6-bug
|
// Check for extra punches, SI6-bug
|
||||||
for (unsigned k = card.nPunch; k < 192; k++) {
|
for (unsigned k = card.nPunch; k < 192; k++) {
|
||||||
if (!analysePunch(data+4*k, card.Punch[k].Time, card.Punch[k].Code)) {
|
if (!analysePunch(data+4*k, card.Punch[k].Time, card.Punch[k].Code, false)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1860,7 +1893,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SportIdent::analysePunch(BYTE *data, DWORD &time, DWORD &control) {
|
bool SportIdent::analysePunch(BYTE *data, DWORD &time, DWORD &control, bool subSecond) {
|
||||||
if (*LPDWORD(data)!=0xEEEEEEEE && *LPDWORD(data)!=0x0)
|
if (*LPDWORD(data)!=0xEEEEEEEE && *LPDWORD(data)!=0x0)
|
||||||
{
|
{
|
||||||
BYTE ptd=data[0];
|
BYTE ptd=data[0];
|
||||||
@ -1868,8 +1901,16 @@ bool SportIdent::analysePunch(BYTE *data, DWORD &time, DWORD &control) {
|
|||||||
BYTE pth=data[2];
|
BYTE pth=data[2];
|
||||||
BYTE ptl=data[3];
|
BYTE ptl=data[3];
|
||||||
|
|
||||||
control=cn+256*((ptd>>6)&0x3);
|
time = timeConstSecond * MAKEWORD(ptl, pth) + timeConstHour * 12 * (ptd & 0x1);
|
||||||
time=MAKEWORD(ptl, pth)+3600*12*(ptd&0x1);
|
if (!subSecond) {
|
||||||
|
control = cn + 256 * ((ptd >> 6) & 0x3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
control = 0;
|
||||||
|
uint8_t tss = data[1]; // Sub second 1/256 seconds
|
||||||
|
int tenth = (((100 * tss) / 256) + 4) / 10;
|
||||||
|
time += tenth;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1880,15 +1921,15 @@ bool SportIdent::analysePunch(BYTE *data, DWORD &time, DWORD &control) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SportIdent::analyseSI5Time(BYTE *data, DWORD &time, DWORD &control)
|
void SportIdent::analyseSI5Time(BYTE* data, DWORD& time, DWORD& control)
|
||||||
{
|
{
|
||||||
if (*LPWORD(data)!=0xEEEE) {
|
if (*LPWORD(data) != 0xEEEE) {
|
||||||
time=MAKEWORD(data[1], data[0]);
|
time = MAKEWORD(data[1], data[0]) * timeConstSecond;
|
||||||
control=0;
|
control = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
control=-1;
|
control = -1;
|
||||||
time=0;
|
time = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,17 +1947,17 @@ void SICard::analyseHour12Time(DWORD zeroTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SIPunch::analyseHour12Time(DWORD zeroTime) {
|
void SIPunch::analyseHour12Time(DWORD zeroTime) {
|
||||||
if (Code != -1 && Time>=0 && Time <=12*3600) {
|
if (Code != -1 && Time>=0 && Time <=12*timeConstHour) {
|
||||||
if (zeroTime < 12 * 3600) {
|
if (zeroTime < 12 * timeConstHour) {
|
||||||
//Förmiddag
|
//Förmiddag
|
||||||
if (Time < zeroTime)
|
if (Time < zeroTime)
|
||||||
Time += 12 * 3600; //->Eftermiddag
|
Time += 12 * timeConstHour; //->Eftermiddag
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//Eftermiddag
|
//Eftermiddag
|
||||||
if (Time >= zeroTime % (12 * 3600)) {
|
if (Time >= zeroTime % (12 * timeConstHour)) {
|
||||||
//Eftermiddag
|
//Eftermiddag
|
||||||
Time += 12 * 3600;
|
Time += 12 * timeConstHour;
|
||||||
}
|
}
|
||||||
// else Efter midnatt OK.
|
// else Efter midnatt OK.
|
||||||
}
|
}
|
||||||
@ -1985,50 +2026,67 @@ void SportIdent::addCard(const SICard &sic)
|
|||||||
PostMessage(hWndNotify, WM_USER, ClassId, 0);
|
PostMessage(hWndNotify, WM_USER, ClassId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SportIdent::addPunch(DWORD Time, int Station, int Card, int Mode)
|
void SportIdent::addPunch(DWORD Time, int Station, int Card, int Mode) {
|
||||||
{
|
if (!useSubsecondMode)
|
||||||
|
Time -= (Time % timeConstSecond);
|
||||||
|
|
||||||
SICard sic(ConvertedTimeStatus::Hour24);
|
SICard sic(ConvertedTimeStatus::Hour24);
|
||||||
sic.CardNumber=Card;
|
sic.CardNumber = Card;
|
||||||
sic.StartPunch.Code = -1;
|
sic.StartPunch.Code = -1;
|
||||||
sic.CheckPunch.Code = -1;
|
sic.CheckPunch.Code = -1;
|
||||||
sic.FinishPunch.Code = -1;
|
sic.FinishPunch.Code = -1;
|
||||||
|
|
||||||
if (Mode==0 || Mode == 11){ // 11 is dongle
|
auto mapPunch = [this](int code) {
|
||||||
if (Station>30){
|
if (code > 0 && code < punchMap.size() && punchMap[code] > 0)
|
||||||
sic.Punch[0].Code=Station;
|
return punchMap[code];
|
||||||
sic.Punch[0].Time=Time;
|
else
|
||||||
sic.nPunch=1;
|
return code;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Mode == 0 || Mode == 11) { // 11 is dongle
|
||||||
|
int code = (Station & 0xFFFF);
|
||||||
|
int mappedCode = mapPunch(code);
|
||||||
|
int unit = 0;
|
||||||
|
if (mappedCode != code)
|
||||||
|
unit = code;
|
||||||
|
else
|
||||||
|
unit = (Station >> 16) & 0xFFFF;
|
||||||
|
|
||||||
|
if (mappedCode > 30) {
|
||||||
|
sic.Punch[0].Code = Station;
|
||||||
|
sic.Punch[0].Time = Time;
|
||||||
|
sic.nPunch = 1;
|
||||||
}
|
}
|
||||||
else if (Station == oPunch::PunchStart) {
|
else if (mappedCode == oPunch::PunchStart) {
|
||||||
sic.StartPunch.Time = Time;
|
sic.StartPunch.Time = Time;
|
||||||
sic.StartPunch.Code = oPunch::PunchStart;
|
sic.StartPunch.Code = unit;
|
||||||
}
|
}
|
||||||
else if (Station == oPunch::PunchCheck) {
|
else if (mappedCode == oPunch::PunchCheck) {
|
||||||
sic.CheckPunch.Time = Time;
|
sic.CheckPunch.Time = Time;
|
||||||
sic.CheckPunch.Code = oPunch::PunchCheck;
|
sic.CheckPunch.Code = unit;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
sic.FinishPunch.Time=Time;
|
sic.FinishPunch.Time = Time;
|
||||||
sic.FinishPunch.Code = oPunch::PunchFinish;
|
sic.FinishPunch.Code = unit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
if (Mode==0x02 || Mode == 50){
|
if (Mode == 0x02 || Mode == 50) {
|
||||||
sic.Punch[0].Code=Station;
|
sic.Punch[0].Code = Station;
|
||||||
sic.Punch[0].Time=Time;
|
sic.Punch[0].Time = Time;
|
||||||
sic.nPunch=1;
|
sic.nPunch = 1;
|
||||||
}
|
}
|
||||||
else if (Mode == 3) {
|
else if (Mode == 3) {
|
||||||
sic.StartPunch.Time=Time;
|
sic.StartPunch.Time = Time;
|
||||||
sic.StartPunch.Code = oPunch::PunchStart;
|
sic.StartPunch.Code = Station;
|
||||||
}
|
}
|
||||||
else if (Mode == 10) {
|
else if (Mode == 10) {
|
||||||
sic.CheckPunch.Time=Time;
|
sic.CheckPunch.Time = Time;
|
||||||
sic.CheckPunch.Code = oPunch::PunchCheck;
|
sic.CheckPunch.Code = Station;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
sic.FinishPunch.Time=Time;
|
sic.FinishPunch.Time = Time;
|
||||||
sic.FinishPunch.Code = oPunch::PunchFinish;
|
sic.FinishPunch.Code = Station;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sic.punchOnly = true;
|
sic.punchOnly = true;
|
||||||
@ -2084,9 +2142,8 @@ void start_si_thread(void *ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SportIdent::startMonitorThread(const wchar_t *com)
|
void SportIdent::startMonitorThread(const wchar_t *com) {
|
||||||
{
|
SI_StationInfo *si = findStationInt(com);
|
||||||
SI_StationInfo *si = findStation(com);
|
|
||||||
|
|
||||||
if (si && (si->hComm || si->ComPort==L"TCP" || si->ComPort == L"TEST"))
|
if (si && (si->hComm || si->ComPort==L"TCP" || si->ComPort == L"TEST"))
|
||||||
{
|
{
|
||||||
@ -2119,7 +2176,7 @@ void checkport_si_thread(void *ptr)
|
|||||||
*port=0; //No SI found here
|
*port=0; //No SI found here
|
||||||
else {
|
else {
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
SI_StationInfo *sii = si.findStation(bf);
|
const SI_StationInfo *sii = ((const SportIdent &)si).findStation(bf);
|
||||||
if (sii) {
|
if (sii) {
|
||||||
if (sii->data.empty() || sii->data[0].stationNumber>=1024 || sii->data[0].stationMode>15 ||
|
if (sii->data.empty() || sii->data[0].stationNumber>=1024 || sii->data[0].stationMode>15 ||
|
||||||
!(sii->data[0].autoSend || sii->data[0].handShake))
|
!(sii->data[0].autoSend || sii->data[0].handShake))
|
||||||
@ -2178,7 +2235,7 @@ bool SportIdent::autoDetect(list<int> &ComPorts)
|
|||||||
|
|
||||||
bool SportIdent::isPortOpen(const wstring &com)
|
bool SportIdent::isPortOpen(const wstring &com)
|
||||||
{
|
{
|
||||||
SI_StationInfo *si = findStation(com);
|
const SI_StationInfo *si = findStation(com);
|
||||||
|
|
||||||
if (si && si->ComPort==L"TCP")
|
if (si && si->ComPort==L"TCP")
|
||||||
return tcpPortOpen && serverSocket;
|
return tcpPortOpen && serverSocket;
|
||||||
@ -2186,25 +2243,61 @@ bool SportIdent::isPortOpen(const wstring &com)
|
|||||||
return si!=0 && si->hComm && si->ThreadHandle;
|
return si!=0 && si->hComm && si->ThreadHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SportIdent::getInfoString(const wstring &com, vector<wstring> &infov)
|
|
||||||
{
|
bool SportIdent::isAnyOpenUnkownUnit() const {
|
||||||
|
if (tcpPortOpen && serverSocket)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; i < n_SI_Info; i++) {
|
||||||
|
auto& si = SI_Info[i];
|
||||||
|
auto& com = si.ComPort;
|
||||||
|
|
||||||
|
if (com == L"TCP")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (com == L"TEST")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!(si.hComm && si.ThreadHandle))
|
||||||
|
continue; // Not open
|
||||||
|
|
||||||
|
if (si.data.empty())
|
||||||
|
return true; // Listen mode (no contact made)
|
||||||
|
|
||||||
|
switch (si.data[0].stationMode) {
|
||||||
|
case 2: // Known modes
|
||||||
|
case 50:
|
||||||
|
case 4:
|
||||||
|
case 3:
|
||||||
|
case 5:
|
||||||
|
case 7:
|
||||||
|
case 10:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SportIdent::getInfoString(const wstring &com, vector<pair<bool, wstring>> &infov) const {
|
||||||
infov.clear();
|
infov.clear();
|
||||||
SI_StationInfo *si = findStation(com);
|
const SI_StationInfo *si = findStation(com);
|
||||||
|
|
||||||
if (com==L"TCP") {
|
if (com==L"TCP") {
|
||||||
if (!si || !tcpPortOpen || !serverSocket) {
|
if (!si || !tcpPortOpen || !serverSocket) {
|
||||||
infov.push_back(L"TCP: "+lang.tl(L"ej aktiv."));
|
infov.emplace_back(false, L"TCP: "+lang.tl(L"ej aktiv."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t bf[128];
|
wchar_t bf[128];
|
||||||
swprintf_s(bf, lang.tl(L"TCP: Port %d, Nolltid: %s").c_str(), tcpPortOpen, L"00:00:00");//WCS
|
swprintf_s(bf, lang.tl(L"TCP: Port %d, Nolltid: %s").c_str(), tcpPortOpen, L"00:00:00");//WCS
|
||||||
infov.push_back(bf);
|
infov.emplace_back(false, bf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(si!=0 && si->hComm && si->ThreadHandle)) {
|
if (!(si!=0 && si->hComm && si->ThreadHandle)) {
|
||||||
infov.push_back(com+L": "+lang.tl(L"ej aktiv."));
|
infov.emplace_back(false, com+L": "+lang.tl(L"ej aktiv."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2221,7 +2314,7 @@ void SportIdent::getInfoString(const wstring &com, vector<wstring> &infov)
|
|||||||
switch(da.stationMode){
|
switch(da.stationMode){
|
||||||
case 2:
|
case 2:
|
||||||
case 50:
|
case 50:
|
||||||
info+=lang.tl(L"Kontrol");
|
info+=lang.tl(L"Kontroll");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
info+=lang.tl(L"Mål");
|
info+=lang.tl(L"Mål");
|
||||||
@ -2256,12 +2349,15 @@ void SportIdent::getInfoString(const wstring &com, vector<wstring> &infov)
|
|||||||
else if (da.handShake) info+=lang.tl(L"handskakning.");
|
else if (da.handShake) info+=lang.tl(L"handskakning.");
|
||||||
else info+=lang.tl(L"[VARNING] ingen/okänd.");
|
else info+=lang.tl(L"[VARNING] ingen/okänd.");
|
||||||
|
|
||||||
infov.push_back(info);
|
infov.emplace_back(false, info);
|
||||||
|
|
||||||
|
if (da.autoSend && da.stationMode == 5)
|
||||||
|
infov.emplace_back(true, lang.tl("Programmera stationen utan AUTOSEND"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static string formatTimeN(int t) {
|
static string formatTimeN(int t) {
|
||||||
const wstring &wt = formatTime(t);
|
const wstring &wt = formatTime(t, SubSecond::Auto);
|
||||||
string nt(wt.begin(), wt.end());
|
string nt(wt.begin(), wt.end());
|
||||||
return nt;
|
return nt;
|
||||||
}
|
}
|
||||||
@ -2411,7 +2507,7 @@ unsigned int SICard::calculateHash() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string SICard::serializePunches() const {
|
string SICard::serializePunches() const {
|
||||||
string ser;
|
string ser = "*";// Mark of time factor
|
||||||
if (CheckPunch.Code != -1)
|
if (CheckPunch.Code != -1)
|
||||||
ser += "C-" + itos(CheckPunch.Time);
|
ser += "C-" + itos(CheckPunch.Time);
|
||||||
|
|
||||||
@ -2437,24 +2533,31 @@ void SICard::deserializePunches(const string &arg) {
|
|||||||
StartPunch.Code = -1;
|
StartPunch.Code = -1;
|
||||||
CheckPunch.Code = -1;
|
CheckPunch.Code = -1;
|
||||||
vector<string> out;
|
vector<string> out;
|
||||||
split(arg, ";", out);
|
int timeFactor = 10;
|
||||||
|
if (arg.length() > 1 && arg[0] == '*') {
|
||||||
|
split(arg.c_str() + 2, ";", out);
|
||||||
|
timeFactor = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
split(arg, ";", out);
|
||||||
|
}
|
||||||
nPunch = 0;
|
nPunch = 0;
|
||||||
for (size_t k = 0; k< out.size(); k++) {
|
for (size_t k = 0; k< out.size(); k++) {
|
||||||
vector<string> mark;
|
vector<string> mark;
|
||||||
split(out[k], "-", mark);
|
split(out[k], "-", mark);
|
||||||
if (mark.size() != 2)
|
if (mark.size() != 2 || mark[0].empty())
|
||||||
throw std::exception("Invalid string");
|
throw std::exception("Invalid string");
|
||||||
DWORD *tp = 0;
|
DWORD *tp = 0;
|
||||||
if (mark[0] == "F") {
|
if (mark[0][0] == 'F') {
|
||||||
FinishPunch.Code = 1;
|
FinishPunch.Code = atoi(mark[0].c_str() + 1);
|
||||||
tp = &FinishPunch.Time;
|
tp = &FinishPunch.Time;
|
||||||
}
|
}
|
||||||
else if (mark[0] == "S") {
|
else if (mark[0][0] == 'S') {
|
||||||
StartPunch.Code = 1;
|
StartPunch.Code = atoi(mark[0].c_str() + 1);
|
||||||
tp = &StartPunch.Time;
|
tp = &StartPunch.Time;
|
||||||
}
|
}
|
||||||
else if (mark[0] == "C") {
|
else if (mark[0][0] == 'C') {
|
||||||
CheckPunch.Code = 1;
|
CheckPunch.Code = atoi(mark[0].c_str() + 1);
|
||||||
tp = &CheckPunch.Time;
|
tp = &CheckPunch.Time;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2462,12 +2565,51 @@ void SICard::deserializePunches(const string &arg) {
|
|||||||
tp = &Punch[nPunch++].Time;
|
tp = &Punch[nPunch++].Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tp = atoi(mark[1].c_str());
|
*tp = atoi(mark[1].c_str()) * timeFactor;
|
||||||
}
|
}
|
||||||
if (out.size() == 1)
|
if (out.size() == 1)
|
||||||
punchOnly = true;
|
punchOnly = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SICard::getFirstTime() const {
|
||||||
|
if (StartPunch.Time > 0)
|
||||||
|
return StartPunch.Time;
|
||||||
|
|
||||||
|
for (int i = 0; i < nPunch; i++) {
|
||||||
|
if (Punch[i].Time > 0)
|
||||||
|
return Punch[i].Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FinishPunch.Time > 0)
|
||||||
|
return FinishPunch.Time;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
map<int, oPunch::SpecialPunch> SportIdent::getSpecialMappings() const {
|
||||||
|
map<int, oPunch::SpecialPunch> res;
|
||||||
|
for (int j = 1; j < punchMap.size(); j++) {
|
||||||
|
if (punchMap[j] > 0)
|
||||||
|
res[j] = oPunch::SpecialPunch(punchMap[j]);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SportIdent::addSpecialMapping(int code, oPunch::SpecialPunch p) {
|
||||||
|
if (code > 0 && code < punchMap.size())
|
||||||
|
punchMap[code] = p;
|
||||||
|
else
|
||||||
|
throw std::exception("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SportIdent::removeSpecialMapping(int code) {
|
||||||
|
if (code > 0 && code < punchMap.size())
|
||||||
|
punchMap[code] = 0;
|
||||||
|
else
|
||||||
|
throw std::exception("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
void SportIdent::addTestCard(int cardNo, const vector<int> &punches) {
|
void SportIdent::addTestCard(int cardNo, const vector<int> &punches) {
|
||||||
testCards.emplace(cardNo, punches);
|
testCards.emplace(cardNo, punches);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,15 @@
|
|||||||
// SportIdent.h: interface for the SportIdent class.
|
// SportIdent.h: interface for the SportIdent class.
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if !defined(AFX_SPORTIDENT_H__F13F5795_8FA9_4CE6_8497_7407CD590139__INCLUDED_)
|
|
||||||
#define AFX_SPORTIDENT_H__F13F5795_8FA9_4CE6_8497_7407CD590139__INCLUDED_
|
|
||||||
|
|
||||||
#if _MSC_VER > 1000
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif // _MSC_VER > 1000
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include "oPunch.h"
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -108,6 +104,8 @@ struct SICard
|
|||||||
|
|
||||||
string serializePunches() const;
|
string serializePunches() const;
|
||||||
void deserializePunches(const string &arg);
|
void deserializePunches(const string &arg);
|
||||||
|
|
||||||
|
int getFirstTime() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SI_StationData {
|
struct SI_StationData {
|
||||||
@ -154,9 +152,11 @@ struct SI_StationInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SportIdent
|
class SportIdent {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
bool useSubsecondMode = false;
|
||||||
|
|
||||||
bool readSI6Block(HANDLE hComm, BYTE *data);
|
bool readSI6Block(HANDLE hComm, BYTE *data);
|
||||||
bool readSystemData(SI_StationInfo *si, int retry=2);
|
bool readSystemData(SI_StationInfo *si, int retry=2);
|
||||||
bool readSystemDataV2(SI_StationInfo &si);
|
bool readSystemDataV2(SI_StationInfo &si);
|
||||||
@ -195,7 +195,7 @@ protected:
|
|||||||
void getSI9DataExt(HANDLE hComm);
|
void getSI9DataExt(HANDLE hComm);
|
||||||
|
|
||||||
void analyseSI5Time(BYTE *data, DWORD &time, DWORD &control);
|
void analyseSI5Time(BYTE *data, DWORD &time, DWORD &control);
|
||||||
bool analysePunch(BYTE *data, DWORD &time, DWORD &control);
|
bool analysePunch(BYTE *data, DWORD &time, DWORD &control, bool subSecond);
|
||||||
void analyseTPunch(BYTE *data, DWORD &time, DWORD &control);
|
void analyseTPunch(BYTE *data, DWORD &time, DWORD &control);
|
||||||
|
|
||||||
//Card read waiting to be processed.
|
//Card read waiting to be processed.
|
||||||
@ -227,13 +227,25 @@ protected:
|
|||||||
|
|
||||||
bool readVoltage;
|
bool readVoltage;
|
||||||
|
|
||||||
|
vector<int> punchMap;
|
||||||
|
SI_StationInfo* findStationInt(const wstring& com);
|
||||||
|
void addTestStation(const wstring& com);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SI_StationInfo *findStation(const wstring &com);
|
|
||||||
|
map<int, oPunch::SpecialPunch> getSpecialMappings() const;
|
||||||
|
void addSpecialMapping(int code, oPunch::SpecialPunch);
|
||||||
|
void removeSpecialMapping(int code);
|
||||||
|
|
||||||
|
const SI_StationInfo *findStation(const wstring &com) const;
|
||||||
|
|
||||||
/** Log debug data. */
|
/** Log debug data. */
|
||||||
void debugLog(const wchar_t *ptr);
|
void debugLog(const wchar_t *ptr);
|
||||||
|
|
||||||
void getInfoString(const wstring &com, vector<wstring> &info);
|
void getInfoString(const wstring &com, vector<pair<bool, wstring>> &info) const;
|
||||||
|
|
||||||
|
bool isAnyOpenUnkownUnit() const;
|
||||||
|
|
||||||
bool isPortOpen(const wstring &com);
|
bool isPortOpen(const wstring &com);
|
||||||
bool autoDetect(list<int> &ComPorts);
|
bool autoDetect(list<int> &ComPorts);
|
||||||
void stopMonitorThread();
|
void stopMonitorThread();
|
||||||
@ -250,13 +262,14 @@ public:
|
|||||||
void closeCom(const wchar_t *com);
|
void closeCom(const wchar_t *com);
|
||||||
bool openCom(const wchar_t *com);
|
bool openCom(const wchar_t *com);
|
||||||
bool tcpAddPort(int port, DWORD zeroTime);
|
bool tcpAddPort(int port, DWORD zeroTime);
|
||||||
|
|
||||||
bool openComListen(const wchar_t *com, DWORD BaudRate);
|
bool openComListen(const wchar_t *com, DWORD BaudRate);
|
||||||
|
|
||||||
SportIdent(HWND hWnd, DWORD Id, bool readVoltage);
|
SportIdent(HWND hWnd, DWORD Id, bool readVoltage);
|
||||||
|
|
||||||
|
void setSubSecondMode(bool subSec) { useSubsecondMode = subSec; }
|
||||||
|
void resetPunchMap();
|
||||||
|
|
||||||
virtual ~SportIdent();
|
virtual ~SportIdent();
|
||||||
friend void start_si_thread(void *ptr);
|
friend void start_si_thread(void *ptr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !defined(AFX_SPORTIDENT_H__F13F5795_8FA9_4CE6_8497_7407CD590139__INCLUDED_)
|
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
// stdafx.h : include file for standard system include files,
|
#pragma once
|
||||||
// or project specific include files that are used frequently, but
|
|
||||||
// are changed infrequently
|
|
||||||
//
|
|
||||||
|
|
||||||
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
|
||||||
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
|
|
||||||
|
|
||||||
#if _MSC_VER > 1000
|
|
||||||
#pragma once
|
|
||||||
#endif // _MSC_VER > 1000
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
// Windows Header Files:
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include "timeconstants.hpp"
|
||||||
|
|
||||||
// C RunTime Header Files
|
// C RunTime Header Files
|
||||||
|
|
||||||
@ -51,4 +42,3 @@ const extern string _EmptyString;
|
|||||||
const extern string _VacantName;
|
const extern string _VacantName;
|
||||||
const extern wstring _EmptyWString;
|
const extern wstring _EmptyWString;
|
||||||
|
|
||||||
#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -716,7 +716,7 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, const char *startCommand,
|
|||||||
|
|
||||||
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||||
settingsTitle(gdi, "Resultatutskrift / export");
|
settingsTitle(gdi, "Resultatutskrift / export");
|
||||||
wstring time = (state == State::Create && interval <= 0) ? L"10:00" : getTimeMS(interval);
|
wstring time = (state == State::Create && interval <= 0) ? L"10:00" : formatTimeMS(interval, false, SubSecond::Off);
|
||||||
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
||||||
|
|
||||||
if (state == State::Create) {
|
if (state == State::Create) {
|
||||||
@ -822,12 +822,12 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintResultMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
void PrintResultMachine::save(oEvent& oe, gdioutput& gdi, bool doProcess) {
|
||||||
AutoMachine::save(oe, gdi, doProcess);
|
AutoMachine::save(oe, gdi, doProcess);
|
||||||
wstring minute = gdi.getText("Interval");
|
wstring minute = gdi.getText("Interval");
|
||||||
int t = convertAbsoluteTimeMS(minute);
|
int t = convertAbsoluteTimeMS(minute) / timeConstSecond;
|
||||||
|
|
||||||
if (t < 2 || t>7200) {
|
if (t < 2 || t > 7200) {
|
||||||
throw meosException("Intervallet måste anges på formen MM:SS.");
|
throw meosException("Intervallet måste anges på formen MM:SS.");
|
||||||
}
|
}
|
||||||
doExport = gdi.isChecked("DoExport");
|
doExport = gdi.isChecked("DoExport");
|
||||||
@ -980,7 +980,7 @@ void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
|||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe.fillControls(d, oEvent::CTCourseControl);
|
oe.fillControls(d, oEvent::ControlType::CourseControl);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
gdi.setSelection("Controls", controls);
|
gdi.setSelection("Controls", controls);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
@ -998,7 +998,7 @@ void PrewarningMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
|||||||
|
|
||||||
controlsSI.clear();
|
controlsSI.clear();
|
||||||
for (set<int>::iterator it = controls.begin(); it != controls.end(); ++it) {
|
for (set<int>::iterator it = controls.begin(); it != controls.end(); ++it) {
|
||||||
pControl pc = oe.getControl(*it, false);
|
pControl pc = oe.getControl(*it, false, false);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
vector<int> n;
|
vector<int> n;
|
||||||
pc->getNumbers(n);
|
pc->getNumbers(n);
|
||||||
@ -1152,7 +1152,7 @@ void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|||||||
sic.punchOnly = true;
|
sic.punchOnly = true;
|
||||||
sic.nPunch = 1;
|
sic.nPunch = 1;
|
||||||
sic.Punch[0].Code = radio;
|
sic.Punch[0].Code = radio;
|
||||||
sic.Punch[0].Time = 600 + rand() % 1200 + r->getStartTime();
|
sic.Punch[0].Time = timeConstHour/10 + rand() % (1200*timeConstSecond) + r->getStartTime();
|
||||||
si.addCard(sic);
|
si.addCard(sic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1205,7 +1205,7 @@ void SplitsMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
|||||||
if (doProcess) {
|
if (doProcess) {
|
||||||
//Try exporting.
|
//Try exporting.
|
||||||
oe.exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
|
oe.exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
|
||||||
set<int>(), -1, false, true, true, false);
|
set<int>(), -1, false, true, true, false, false);
|
||||||
interval = iv;
|
interval = iv;
|
||||||
synchronize = true;
|
synchronize = true;
|
||||||
}
|
}
|
||||||
@ -1245,7 +1245,7 @@ void SplitsMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|||||||
if ((interval>0 && ast==SyncTimer) || (interval==0 && ast==SyncDataUp)) {
|
if ((interval>0 && ast==SyncTimer) || (interval==0 && ast==SyncDataUp)) {
|
||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false, classes,
|
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false, classes,
|
||||||
leg, false, true, true, false);
|
leg, false, true, true, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1276,16 +1276,16 @@ void SaveMachine::status(gdioutput &gdi) {
|
|||||||
void SaveMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
void SaveMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
||||||
if (interval>0 && ast==SyncTimer) {
|
if (interval>0 && ast==SyncTimer) {
|
||||||
if (!baseFile.empty()) {
|
if (!baseFile.empty()) {
|
||||||
wstring file = baseFile + L"meos_backup_" + oe->getDate() + L"_" + itow(saveIter++) + L".xml";
|
wstring file = baseFile + L"meos_backup_" + oe->getDate() + L"_" + itow(saveIter++) + L".meosxml";
|
||||||
oe->autoSynchronizeLists(true);
|
oe->autoSynchronizeLists(true);
|
||||||
oe->save(file);
|
oe->save(file, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||||
settingsTitle(gdi, "Säkerhetskopiering");
|
settingsTitle(gdi, "Säkerhetskopiering");
|
||||||
wstring time=state == State::Create ? L"10:00" : getTimeMS(interval);
|
wstring time=state == State::Create ? L"10:00" : formatTimeMS(interval, false, SubSecond::Off);
|
||||||
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
||||||
|
|
||||||
int cx = gdi.getCX();
|
int cx = gdi.getCX();
|
||||||
@ -1295,12 +1295,12 @@ void SaveMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
|||||||
gdi.setCX(cx);
|
gdi.setCX(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
void SaveMachine::save(oEvent& oe, gdioutput& gdi, bool doProcess) {
|
||||||
AutoMachine::save(oe, gdi, doProcess);
|
AutoMachine::save(oe, gdi, doProcess);
|
||||||
wstring minute=gdi.getText("Interval");
|
wstring minute = gdi.getText("Interval");
|
||||||
int t=convertAbsoluteTimeMS(minute);
|
int t = convertAbsoluteTimeMS(minute) / timeConstSecond;
|
||||||
|
|
||||||
if (t<2 || t>7200) {
|
if (t < 2 || t>7200) {
|
||||||
throw meosException("Intervallet måste anges på formen MM:SS.");
|
throw meosException("Intervallet måste anges på formen MM:SS.");
|
||||||
}
|
}
|
||||||
wstring f = gdi.getText("BaseFile");
|
wstring f = gdi.getText("BaseFile");
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -76,10 +76,10 @@ TabClass::TabClass(oEvent *poe):TabBase(poe)
|
|||||||
void TabClass::clearCompetitionData() {
|
void TabClass::clearCompetitionData() {
|
||||||
currentResultModuleTags.clear();
|
currentResultModuleTags.clear();
|
||||||
pSettings.clear();
|
pSettings.clear();
|
||||||
pSavedDepth = 3600;
|
pSavedDepth = timeConstHour;
|
||||||
pFirstRestart = 3600;
|
pFirstRestart = timeConstHour;
|
||||||
pTimeScaling = 1.0;
|
pTimeScaling = 1.0;
|
||||||
pInterval = 120;
|
pInterval = 2 * timeConstMinute;
|
||||||
|
|
||||||
currentStage = -1;
|
currentStage = -1;
|
||||||
EditChanged = false;
|
EditChanged = false;
|
||||||
@ -241,6 +241,9 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (bi.id == "ApplyForking") {
|
else if (bi.id == "ApplyForking") {
|
||||||
|
int maxForking = gdi.getTextNo("MaxForkings");
|
||||||
|
if (maxForking < 2)
|
||||||
|
throw meosException("Du måste ange minst två gafflingsvarienater");
|
||||||
showForkingGuide = false;
|
showForkingGuide = false;
|
||||||
pClass pc = oe->getClass(ClassId);
|
pClass pc = oe->getClass(ClassId);
|
||||||
|
|
||||||
@ -259,7 +262,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
allR[k]->setCourseId(0);
|
allR[k]->setCourseId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pair<int,int> res = pc->autoForking(forkingSetup);
|
pair<int,int> res = pc->autoForking(forkingSetup, maxForking);
|
||||||
gdi.alert("Created X distinct forkings using Y courses.#" +
|
gdi.alert("Created X distinct forkings using Y courses.#" +
|
||||||
itos(res.first) + "#" + itos(res.second));
|
itos(res.first) + "#" + itos(res.second));
|
||||||
loadPage(gdi);
|
loadPage(gdi);
|
||||||
@ -307,6 +310,10 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.setSelection("AllStages", set<int>());
|
gdi.setSelection("AllStages", set<int>());
|
||||||
gdi.disableInput("AssignCourses");
|
gdi.disableInput("AssignCourses");
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "AllCourses") {
|
||||||
|
gdi.setSelection("AllCourses", { -1 });
|
||||||
|
//gdi.enableInput("AssignCourses");
|
||||||
|
}
|
||||||
else if (bi.id == "ShowForking") {
|
else if (bi.id == "ShowForking") {
|
||||||
if (!checkClassSelected(gdi))
|
if (!checkClassSelected(gdi))
|
||||||
return false;
|
return false;
|
||||||
@ -469,7 +476,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
int nst = oe->convertAbsoluteTime(st);
|
int nst = oe->convertAbsoluteTime(st);
|
||||||
if (nst >= 0 && warnDrawStartTime(gdi, nst, true)) {
|
if (nst >= 0 && warnDrawStartTime(gdi, nst, true)) {
|
||||||
nst = 3600;
|
nst = timeConstHour;
|
||||||
st = oe->getAbsTime(nst);
|
st = oe->getAbsTime(nst);
|
||||||
}
|
}
|
||||||
if (nst>0)
|
if (nst>0)
|
||||||
@ -695,8 +702,27 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
|||||||
EditChanged=true;
|
EditChanged=true;
|
||||||
if (ii.id=="NStage")
|
if (ii.id=="NStage")
|
||||||
gdi.enableInput("SetNStage");
|
gdi.enableInput("SetNStage");
|
||||||
|
else if (ii.id == "CourseFilter") {
|
||||||
|
gdi.addTimeoutMilli(500, "FilterCourseTimer", MultiCB);
|
||||||
|
}
|
||||||
//else if (ii.id=="")
|
//else if (ii.id=="")
|
||||||
}
|
}
|
||||||
|
else if (type == GUI_TIMER) {
|
||||||
|
TimerInfo& ti = *(TimerInfo*)(data);
|
||||||
|
if (ti.id == "FilterCourseTimer") {
|
||||||
|
const wstring &filter = gdi.getText("CourseFilter");
|
||||||
|
if (filter != courseFilter) {
|
||||||
|
courseFilter = filter;
|
||||||
|
vector<pair<wstring, size_t>> out;
|
||||||
|
oe->getCourses(out, courseFilter, true, false);
|
||||||
|
set<int> sel;
|
||||||
|
gdi.getSelection("AllCourses", sel);
|
||||||
|
gdi.addItem("AllCourses", out);
|
||||||
|
gdi.setSelection("AllCourses", sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,8 +858,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
else ds.ctrl = 0;
|
else ds.ctrl = 0;
|
||||||
|
|
||||||
// Save settings with class
|
// Save settings with class
|
||||||
ds.firstStart = 3600;
|
ds.firstStart = timeConstHour;
|
||||||
ds.interval = 120;
|
ds.interval = 2 * timeConstMinute;
|
||||||
ds.vacant = 1;
|
ds.vacant = 1;
|
||||||
|
|
||||||
res.push_back(ds);
|
res.push_back(ds);
|
||||||
@ -1023,7 +1049,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addInput("FirstStart", oe->getAbsTime(3600), 10, 0, L"Första (ordinarie) start:");
|
gdi.addInput("FirstStart", oe->getAbsTime(timeConstHour), 10, 0, L"Första (ordinarie) start:");
|
||||||
gdi.addInput("MinInterval", L"2:00", 10, 0, L"Minsta startintervall:");
|
gdi.addInput("MinInterval", L"2:00", 10, 0, L"Minsta startintervall:");
|
||||||
gdi.addInput("Vacances", getDefaultVacant(), 10, 0, L"Andel vakanser:");
|
gdi.addInput("Vacances", getDefaultVacant(), 10, 0, L"Andel vakanser:");
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
@ -1085,7 +1111,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
else if (bi.id == "SelectAllNoneP") {
|
else if (bi.id == "SelectAllNoneP") {
|
||||||
bool select = bi.getExtraInt() != 0;
|
bool select = bi.getExtraInt() != 0;
|
||||||
for (int k = 0; k < oe->getNumClasses(); k++) {
|
const int nc = oe->getNumClasses();
|
||||||
|
for (int k = 0; k < nc; k++) {
|
||||||
gdi.check("PLUse" + itos(k), select);
|
gdi.check("PLUse" + itos(k), select);
|
||||||
gdi.setInputStatus("First" + itos(k), select);
|
gdi.setInputStatus("First" + itos(k), select);
|
||||||
}
|
}
|
||||||
@ -1107,8 +1134,8 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
pInterval = interval;
|
pInterval = interval;
|
||||||
|
|
||||||
oListParam par;
|
oListParam par;
|
||||||
|
const int nc = oe->getNumClasses();
|
||||||
for (int k = 0; k < oe->getNumClasses(); k++) {
|
for (int k = 0; k < nc; k++) {
|
||||||
if (!gdi.hasWidget("PLUse" + itos(k)))
|
if (!gdi.hasWidget("PLUse" + itos(k)))
|
||||||
continue;
|
continue;
|
||||||
BaseInfo *biu = gdi.setText("PLUse" + itos(k), L"", false);
|
BaseInfo *biu = gdi.setText("PLUse" + itos(k), L"", false);
|
||||||
@ -1260,7 +1287,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
else if (bi.id == "DrawAll") {
|
else if (bi.id == "DrawAll") {
|
||||||
int origin = bi.getExtraInt();
|
int origin = bi.getExtraInt();
|
||||||
wstring firstStart = oe->getAbsTime(3600);
|
wstring firstStart = oe->getAbsTime(timeConstHour);
|
||||||
wstring minInterval = L"2:00";
|
wstring minInterval = L"2:00";
|
||||||
wstring vacances = getDefaultVacant();
|
wstring vacances = getDefaultVacant();
|
||||||
if (gdi.hasWidget("Vacances")) {
|
if (gdi.hasWidget("Vacances")) {
|
||||||
@ -2529,7 +2556,7 @@ void TabClass::showClassSettings(gdioutput &gdi)
|
|||||||
if (ci.hasFixedTime) {
|
if (ci.hasFixedTime) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
ii = &gdi.addInput(xp + classW + width, y, "I" + itos(id), formatTime(ci.interval*drawInfo.baseInterval), 7, DrawClassesCB);
|
ii = &gdi.addInput(xp + classW + width, y, "I" + itos(id), formatTime(ci.interval*drawInfo.baseInterval, SubSecond::Auto), 7, DrawClassesCB);
|
||||||
if (ci.hasFixedTime) {
|
if (ci.hasFixedTime) {
|
||||||
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
ii->setBgColor(fixedColor).setExtra(fixedColor);
|
||||||
}
|
}
|
||||||
@ -3323,9 +3350,24 @@ bool TabClass::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addListBox("Classes", 200, showAdvanced ? 512 : 420, ClassesCB, L"").isEdit(false).ignore(true);
|
gdi.addListBox("Classes", 200, showAdvanced ? 512 : 420, ClassesCB, L"").isEdit(false).ignore(true);
|
||||||
gdi.setTabStops("Classes", 185);
|
gdi.setTabStops("Classes", 170);
|
||||||
oe->fillClasses(gdi, "Classes", oEvent::extraDrawn, oEvent::filterNone);
|
oe->fillClasses(gdi, "Classes", oEvent::extraDrawn, oEvent::filterNone);
|
||||||
|
|
||||||
|
|
||||||
|
bool hasIgnoreStart = false;
|
||||||
|
bool hasFreeStart = false;
|
||||||
|
|
||||||
|
if (!showAdvanced) {
|
||||||
|
vector<pClass> clsList;
|
||||||
|
oe->getClasses(clsList, false);
|
||||||
|
for (auto c : clsList) {
|
||||||
|
if (c->ignoreStartPunch())
|
||||||
|
hasIgnoreStart = true;
|
||||||
|
if (c->hasFreeStart())
|
||||||
|
hasFreeStart = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
|
|
||||||
@ -3419,11 +3461,15 @@ bool TabClass::loadPage(gdioutput &gdi)
|
|||||||
gdi.addCheckbox("NoTiming", "Utan tidtagning", 0);
|
gdi.addCheckbox("NoTiming", "Utan tidtagning", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showAdvanced) {
|
if (showAdvanced || hasIgnoreStart || hasFreeStart) {
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addCheckbox("FreeStart", "Fri starttid", 0, false, "Klassen lottas inte, startstämpling");
|
|
||||||
gdi.addCheckbox("IgnoreStart", "Ignorera startstämpling", 0, false, "Uppdatera inte starttiden vid startstämpling");
|
if (showAdvanced || hasFreeStart)
|
||||||
|
gdi.addCheckbox("FreeStart", "Fri starttid", 0, false, "Klassen lottas inte, startstämpling");
|
||||||
|
|
||||||
|
if (showAdvanced || hasIgnoreStart)
|
||||||
|
gdi.addCheckbox("IgnoreStart", "Ignorera startstämpling", 0, false, "Uppdatera inte starttiden vid startstämpling");
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
}
|
}
|
||||||
@ -3721,8 +3767,8 @@ void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClas
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int firstStart = 3600,
|
int firstStart = timeConstHour,
|
||||||
interval = 120,
|
interval = 2 * timeConstMinute,
|
||||||
vac = _wtoi(lastNumVac.c_str());
|
vac = _wtoi(lastNumVac.c_str());
|
||||||
|
|
||||||
int pairSize = lastPairSize;
|
int pairSize = lastPairSize;
|
||||||
@ -3787,12 +3833,12 @@ void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClas
|
|||||||
|
|
||||||
if (method == oEvent::DrawMethod::Pursuit || method == oEvent::DrawMethod::ReversePursuit) {
|
if (method == oEvent::DrawMethod::Pursuit || method == oEvent::DrawMethod::ReversePursuit) {
|
||||||
gdi.addInput("MaxAfter", lastMaxAfter, 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart").setSynchData(&lastMaxAfter);
|
gdi.addInput("MaxAfter", lastMaxAfter, 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart").setSynchData(&lastMaxAfter);
|
||||||
gdi.addInput("TimeRestart", oe->getAbsTime(firstStart + 3600), 8, 0, L"Första omstartstid:");
|
gdi.addInput("TimeRestart", oe->getAbsTime(firstStart + timeConstHour), 8, 0, L"Första omstartstid:");
|
||||||
gdi.addInput("ScaleFactor", lastScaleFactor, 8, 0, L"Tidsskalning:").setSynchData(&lastScaleFactor);
|
gdi.addInput("ScaleFactor", lastScaleFactor, 8, 0, L"Tidsskalning:").setSynchData(&lastScaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method != oEvent::DrawMethod::Simultaneous)
|
if (method != oEvent::DrawMethod::Simultaneous)
|
||||||
gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval);
|
gdi.addInput("Interval", formatTime(interval, SubSecond::Auto), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval);
|
||||||
|
|
||||||
if ((method == oEvent::DrawMethod::Random ||
|
if ((method == oEvent::DrawMethod::Random ||
|
||||||
method == oEvent::DrawMethod::SOFT ||
|
method == oEvent::DrawMethod::SOFT ||
|
||||||
@ -3944,9 +3990,9 @@ void TabClass::pursuitDialog(gdioutput &gdi) {
|
|||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
gdi.addInput("MaxAfter", formatTime(pSavedDepth), 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart");
|
gdi.addInput("MaxAfter", formatTime(pSavedDepth, SubSecond::Off), 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart");
|
||||||
gdi.addInput("TimeRestart", L"+" + formatTime(pFirstRestart), 8, 0, L"Första omstartstid:", L"Ange tiden relativt klassens första start");
|
gdi.addInput("TimeRestart", L"+" + formatTime(pFirstRestart, SubSecond::Off), 8, 0, L"Första omstartstid:", L"Ange tiden relativt klassens första start");
|
||||||
gdi.addInput("Interval", formatTime(pInterval), 8, 0, L"Startintervall:", L"Ange startintervall för minutstart");
|
gdi.addInput("Interval", formatTime(pInterval, SubSecond::Off), 8, 0, L"Startintervall:", L"Ange startintervall för minutstart");
|
||||||
wchar_t bf[32];
|
wchar_t bf[32];
|
||||||
swprintf_s(bf, L"%f", pTimeScaling);
|
swprintf_s(bf, L"%f", pTimeScaling);
|
||||||
gdi.addInput("ScaleFactor", bf, 8, 0, L"Tidsskalning:");
|
gdi.addInput("ScaleFactor", bf, 8, 0, L"Tidsskalning:");
|
||||||
@ -4027,7 +4073,7 @@ void TabClass::showClassSelection(gdioutput &gdi, int &bx, int &by, GUICALLBACK
|
|||||||
int cx = gdi.getCX();
|
int cx = gdi.getCX();
|
||||||
int width = gdi.scaleLength(230);
|
int width = gdi.scaleLength(230);
|
||||||
gdi.addListBox("Classes", 200, 480, classesCB, L"Klasser:", L"", true);
|
gdi.addListBox("Classes", 200, 480, classesCB, L"Klasser:", L"", true);
|
||||||
gdi.setTabStops("Classes", 185);
|
gdi.setTabStops("Classes", 170);
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
|
|
||||||
@ -4258,6 +4304,9 @@ void TabClass::defineForking(gdioutput &gdi, bool clearSettings) {
|
|||||||
|
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
gdi.pushY();
|
gdi.pushY();
|
||||||
|
|
||||||
|
courseFilter = L"";
|
||||||
|
gdi.addInput("CourseFilter", courseFilter, 16, MultiCB, L"Filtrera:");
|
||||||
gdi.addListBox("AllCourses", 180, 300, 0, L"Banor:", L"", true);
|
gdi.addListBox("AllCourses", 180, 300, 0, L"Banor:", L"", true);
|
||||||
oe->fillCourses(gdi, "AllCourses", true);
|
oe->fillCourses(gdi, "AllCourses", true);
|
||||||
int bxp = gdi.getCX();
|
int bxp = gdi.getCX();
|
||||||
@ -4292,6 +4341,9 @@ void TabClass::defineForking(gdioutput &gdi, bool clearSettings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.addInput("MaxForkings", L"100", 5, nullptr, L"Max antal gaffllingsvarianter att skapa:",
|
||||||
|
L"Det uppskattade antalet startade lag i klassen är ett lämpligt värde.");
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addButton("ApplyForking", "Calculate and apply forking", MultiCB);
|
gdi.addButton("ApplyForking", "Calculate and apply forking", MultiCB);
|
||||||
@ -4300,9 +4352,11 @@ void TabClass::defineForking(gdioutput &gdi, bool clearSettings) {
|
|||||||
|
|
||||||
gdi.setCX(bxp);
|
gdi.setCX(bxp);
|
||||||
gdi.setCY(byp);
|
gdi.setCY(byp);
|
||||||
|
gdi.addButton("AllCourses", "Välj allt", MultiCB);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addButton("ClearCourses", "Clear selections", MultiCB);
|
gdi.addButton("ClearCourses", "Clear selections", MultiCB);
|
||||||
|
|
||||||
|
gdi.setCX(bxp);
|
||||||
gdi.addString("", 10, "help:assignforking");
|
gdi.addString("", 10, "help:assignforking");
|
||||||
gdi.addString("", ty, tx, boldLarge, L"Assign courses and apply forking to X#" + pc->getName());
|
gdi.addString("", ty, tx, boldLarge, L"Assign courses and apply forking to X#" + pc->getName());
|
||||||
|
|
||||||
@ -4384,7 +4438,7 @@ void TabClass::getClassSettingsTable(gdioutput &gdi, GUICALLBACK cb) {
|
|||||||
gdi.addString("", yp, f, 1, "Direktanmälan");
|
gdi.addString("", yp, f, 1, "Direktanmälan");
|
||||||
|
|
||||||
vector< pair<wstring,size_t> > arg;
|
vector< pair<wstring,size_t> > arg;
|
||||||
oe->fillCourses(arg, true);
|
oe->getCourses(arg, L"", true);
|
||||||
|
|
||||||
for (size_t k = 0; k < cls.size(); k++) {
|
for (size_t k = 0; k < cls.size(); k++) {
|
||||||
pClass it = cls[k];
|
pClass it = cls[k];
|
||||||
@ -4534,8 +4588,11 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
|
|||||||
if (st == STChange) {
|
if (st == STChange) {
|
||||||
if (typeid(sdataBase) != typeid(ListBoxInfo)) {
|
if (typeid(sdataBase) != typeid(ListBoxInfo)) {
|
||||||
InputInfo sdII = dynamic_cast<InputInfo &>(sdataBase);
|
InputInfo sdII = dynamic_cast<InputInfo &>(sdataBase);
|
||||||
|
string rp;
|
||||||
|
gdi.getWidgetRestorePoint(sdKey, rp);
|
||||||
gdi.removeWidget(sdKey);
|
gdi.removeWidget(sdKey);
|
||||||
gdi.addSelection(sdII.getX(), sdII.getY(), sdKey, sdII.getWidth(), 200, MultiCB);
|
gdi.addSelection(sdII.getX(), sdII.getY(), sdKey, int(sdII.getWidth()/gdi.getScale()), 200, MultiCB);
|
||||||
|
gdi.setWidgetRestorePoint(sdKey, rp);
|
||||||
setParallelOptions(sdKey, gdi, pc, leg);
|
setParallelOptions(sdKey, gdi, pc, leg);
|
||||||
}
|
}
|
||||||
else if (forceWrite) {
|
else if (forceWrite) {
|
||||||
@ -4545,9 +4602,12 @@ void TabClass::updateStartData(gdioutput &gdi, pClass pc, int leg, bool updateDe
|
|||||||
else {
|
else {
|
||||||
if (typeid(sdataBase) != typeid(InputInfo)) {
|
if (typeid(sdataBase) != typeid(InputInfo)) {
|
||||||
ListBoxInfo sdLBI = dynamic_cast<ListBoxInfo &>(sdataBase);
|
ListBoxInfo sdLBI = dynamic_cast<ListBoxInfo &>(sdataBase);
|
||||||
|
string rp;
|
||||||
|
gdi.getWidgetRestorePoint(sdKey, rp);
|
||||||
gdi.removeWidget(sdKey);
|
gdi.removeWidget(sdKey);
|
||||||
string val = "-";
|
string val = "-";
|
||||||
gdi.addInput(sdLBI.getX(), sdLBI.getY(), sdKey, pc->getStartDataS(leg), 8, MultiCB);
|
gdi.addInput(sdLBI.getX(), sdLBI.getY(), sdKey, pc->getStartDataS(leg), 8, MultiCB);
|
||||||
|
gdi.setWidgetRestorePoint(sdKey, rp);
|
||||||
}
|
}
|
||||||
else if (forceWrite) {
|
else if (forceWrite) {
|
||||||
gdi.setText(sdKey, pc->getStartDataS(leg), true);
|
gdi.setText(sdKey, pc->getStartDataS(leg), true);
|
||||||
@ -4678,12 +4738,12 @@ void TabClass::writeDrawInfo(gdioutput &gdi, const DrawInfo &drawInfoIn) {
|
|||||||
gdi.setText("Vacances", itow(int(drawInfoIn.vacancyFactor *100.0)) + L"%");
|
gdi.setText("Vacances", itow(int(drawInfoIn.vacancyFactor *100.0)) + L"%");
|
||||||
gdi.setText("Extra", itow(int(drawInfoIn.extraFactor * 100.0) ) + L"%");
|
gdi.setText("Extra", itow(int(drawInfoIn.extraFactor * 100.0) ) + L"%");
|
||||||
|
|
||||||
gdi.setText("BaseInterval", formatTime(drawInfoIn.baseInterval));
|
gdi.setText("BaseInterval", formatTime(drawInfoIn.baseInterval, SubSecond::Off));
|
||||||
|
|
||||||
gdi.check("AllowNeighbours", drawInfoIn.allowNeighbourSameCourse);
|
gdi.check("AllowNeighbours", drawInfoIn.allowNeighbourSameCourse);
|
||||||
gdi.check("CoursesTogether", drawInfoIn.coursesTogether);
|
gdi.check("CoursesTogether", drawInfoIn.coursesTogether);
|
||||||
gdi.setText("MinInterval", formatTime(drawInfoIn.minClassInterval));
|
gdi.setText("MinInterval", formatTime(drawInfoIn.minClassInterval, SubSecond::Off));
|
||||||
gdi.setText("MaxInterval", formatTime(drawInfoIn.maxClassInterval));
|
gdi.setText("MaxInterval", formatTime(drawInfoIn.maxClassInterval, SubSecond::Off));
|
||||||
gdi.setText("nFields", drawInfoIn.nFields);
|
gdi.setText("nFields", drawInfoIn.nFields);
|
||||||
gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart));
|
gdi.setText("FirstStart", oe->getAbsTime(drawInfoIn.firstStart));
|
||||||
}
|
}
|
||||||
@ -4739,10 +4799,10 @@ bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) {
|
|||||||
|
|
||||||
bool TabClass::warnDrawStartTime(gdioutput &gdi, int time, bool absTime) {
|
bool TabClass::warnDrawStartTime(gdioutput &gdi, int time, bool absTime) {
|
||||||
if (absTime)
|
if (absTime)
|
||||||
time = oe->getRelativeTime(formatTimeHMS(time));
|
time = oe->getRelativeTime(formatTimeHMS(time, SubSecond::Off));
|
||||||
|
|
||||||
if (!hasWarnedStartTime && (time > 3600 * 11 && !oe->useLongTimes())) {
|
if (!hasWarnedStartTime && (time > timeConstHour * 11 && !oe->useLongTimes())) {
|
||||||
bool res = gdi.ask(L"warn:latestarttime#" + itow(time/3600));
|
bool res = gdi.ask(L"warn:latestarttime#" + itow(time/timeConstHour));
|
||||||
if (res)
|
if (res)
|
||||||
hasWarnedStartTime = true;
|
hasWarnedStartTime = true;
|
||||||
return !res;
|
return !res;
|
||||||
@ -4812,7 +4872,7 @@ void DrawSettingsCSV::write(gdioutput &gdi, const oEvent &oe, const wstring &fn,
|
|||||||
else line.emplace_back("");
|
else line.emplace_back("");
|
||||||
|
|
||||||
line.push_back(gdi.narrow(oe.getAbsTime(ci.firstStart)));
|
line.push_back(gdi.narrow(oe.getAbsTime(ci.firstStart)));
|
||||||
line.push_back(gdi.narrow(formatTime(ci.interval)));
|
line.push_back(gdi.narrow(formatTime(ci.interval, SubSecond::Off)));
|
||||||
line.push_back(itos(ci.vacant));
|
line.push_back(itos(ci.vacant));
|
||||||
writer.outputRow(line);
|
writer.outputRow(line);
|
||||||
}
|
}
|
||||||
@ -5130,8 +5190,8 @@ public:
|
|||||||
else if (type == GuiEventType::GUI_BUTTON) {
|
else if (type == GuiEventType::GUI_BUTTON) {
|
||||||
if (info.id == "AddGroup") {
|
if (info.id == "AddGroup") {
|
||||||
int id = 1;
|
int id = 1;
|
||||||
int firstStart = 3600;
|
int firstStart = timeConstHour;
|
||||||
int length = 3600;
|
int length = timeConstHour;
|
||||||
for (auto &g : oe.getStartGroups(false)) {
|
for (auto &g : oe.getStartGroups(false)) {
|
||||||
id = max(id, g.first+1);
|
id = max(id, g.first+1);
|
||||||
firstStart = max(firstStart, g.second.lastStart);
|
firstStart = max(firstStart, g.second.lastStart);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -33,9 +33,9 @@ class TabClass :
|
|||||||
int maxTime;
|
int maxTime;
|
||||||
|
|
||||||
PursuitSettings(oClass &c) {
|
PursuitSettings(oClass &c) {
|
||||||
firstTime = 3600;
|
firstTime = timeConstHour;
|
||||||
use = c.interpretClassType() != ctOpen;
|
use = c.interpretClassType() != ctOpen;
|
||||||
maxTime = 3600;
|
maxTime = timeConstHour;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,6 +103,9 @@ class TabClass :
|
|||||||
wstring lastScaleFactor;
|
wstring lastScaleFactor;
|
||||||
wstring lastMaxAfter;
|
wstring lastMaxAfter;
|
||||||
|
|
||||||
|
// Filter for course assignment
|
||||||
|
wstring courseFilter;
|
||||||
|
|
||||||
bool lastHandleBibs;
|
bool lastHandleBibs;
|
||||||
// Generate a table with class settings
|
// Generate a table with class settings
|
||||||
void showClassSettings(gdioutput &gdi);
|
void showClassSettings(gdioutput &gdi);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -351,8 +351,8 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
gdi.dropLine(2.5);
|
||||||
TabList::customTextLines(*oe, "IVExtra", gdi);
|
TabList::customTextLines(*oe, "IVExtra", true, gdi);
|
||||||
|
|
||||||
gdi.dropLine(1);
|
gdi.dropLine(1);
|
||||||
|
|
||||||
@ -364,7 +364,8 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
|
|||||||
oe->getDI().fillDataFields(gdi);
|
oe->getDI().fillDataFields(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id == "SaveSettings") {
|
else if (bi.id == "SaveSettings") {
|
||||||
oe->getDI().saveDataFields(gdi);
|
set<string> modified;
|
||||||
|
oe->getDI().saveDataFields(gdi, modified);
|
||||||
|
|
||||||
TabList::saveExtraLines(*oe, "IVExtra", gdi);
|
TabList::saveExtraLines(*oe, "IVExtra", gdi);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -133,6 +133,8 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
|
|||||||
oe->updateStartTimes(delta);
|
oe->updateStartTimes(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oe->supportSubSeconds(gdi.isChecked("SubSecond"));
|
||||||
|
|
||||||
oe->setDate(date, true);
|
oe->setDate(date, true);
|
||||||
oe->useLongTimes(longTimes);
|
oe->useLongTimes(longTimes);
|
||||||
oe->setName(gdi.getText("Name"), true);
|
oe->setName(gdi.getText("Name"), true);
|
||||||
@ -163,7 +165,7 @@ bool TabCompetition::importFile(HWND hWnd, gdioutput &gdi)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
gdi.setWaitCursor(true);
|
gdi.setWaitCursor(true);
|
||||||
if (oe->open(fileName, true, false)) {
|
if (oe->open(fileName, true, false, false)) {
|
||||||
gdi.setWindowTitle(oe->getTitleName());
|
gdi.setWindowTitle(oe->getTitleName());
|
||||||
resetSaveTimer();
|
resetSaveTimer();
|
||||||
|
|
||||||
@ -171,7 +173,7 @@ bool TabCompetition::importFile(HWND hWnd, gdioutput &gdi)
|
|||||||
wstring base = constructBase(L"base", L"");
|
wstring base = constructBase(L"base", L"");
|
||||||
wchar_t newBase[_MAX_PATH];
|
wchar_t newBase[_MAX_PATH];
|
||||||
getUserFile(newBase, base.c_str());
|
getUserFile(newBase, base.c_str());
|
||||||
oe->save(newBase);
|
oe->save(newBase, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ bool TabCompetition::exportFileAs(HWND hWnd, gdioutput &gdi)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
gdi.setWaitCursor(true);
|
gdi.setWaitCursor(true);
|
||||||
if (!oe->save(fileName.c_str())) {
|
if (!oe->save(fileName.c_str(), false)) {
|
||||||
gdi.alert(L"Fel: Filen " + fileName+ L" kunde inte skrivas.");
|
gdi.alert(L"Fel: Filen " + fileName+ L" kunde inte skrivas.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -662,7 +664,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addCheckbox("Clear", "Nollställ databaser", 0, true);
|
gdi.addCheckbox("Clear", "Nollställ databaser");
|
||||||
|
gdi.addCheckbox("IncludeWithoutClub", "Inkludera klubblösa");
|
||||||
|
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
@ -680,6 +684,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.setWaitCursor(true);
|
gdi.setWaitCursor(true);
|
||||||
gdi.addString("", 0, "Importerar...");
|
gdi.addString("", 0, "Importerar...");
|
||||||
bool clear = gdi.isChecked("Clear");
|
bool clear = gdi.isChecked("Clear");
|
||||||
|
bool requireClub = !gdi.isChecked("IncludeWithoutClub");
|
||||||
wstring club = gdi.getText("ClubFile");
|
wstring club = gdi.getText("ClubFile");
|
||||||
wstring cmp = gdi.getText("CmpFile");
|
wstring cmp = gdi.getText("CmpFile");
|
||||||
if (club == cmp)
|
if (club == cmp)
|
||||||
@ -698,7 +703,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (clubCsv)
|
if (clubCsv)
|
||||||
throw meosException("Klubbfil får inte anges vid CSV import.");
|
throw meosException("Klubbfil får inte anges vid CSV import.");
|
||||||
|
|
||||||
oe->importXML_IOF_Data(club, cmp, clear);
|
oe->importXML_IOF_Data(club, cmp, requireClub, clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
@ -780,7 +785,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
wchar_t newBase[_MAX_PATH];
|
wchar_t newBase[_MAX_PATH];
|
||||||
getUserFile(newBase, base.c_str());
|
getUserFile(newBase, base.c_str());
|
||||||
if (!fileExists(newBase))
|
if (!fileExists(newBase))
|
||||||
oe->save(newBase);
|
oe->save(newBase, false);
|
||||||
|
|
||||||
loadConnectionPage(gdi);
|
loadConnectionPage(gdi);
|
||||||
}
|
}
|
||||||
@ -911,7 +916,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
oEvent nextStage(gdi);
|
oEvent nextStage(gdi);
|
||||||
|
|
||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
success = nextStage.open(file.c_str(), false, false);
|
success = nextStage.open(file.c_str(), false, false, false);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
success = nextStage.getNameId(0) == oe->getDCI().getString("PostEvent");
|
success = nextStage.getNameId(0) == oe->getDCI().getString("PostEvent");
|
||||||
@ -1138,7 +1143,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
wstring startlist = getTempFile();
|
wstring startlist = getTempFile();
|
||||||
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
|
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
|
||||||
oe->exportIOFStartlist(oEvent::IOF30, startlist.c_str(), eventorUTC,
|
oe->exportIOFStartlist(oEvent::IOF30, startlist.c_str(), eventorUTC,
|
||||||
set<int>(), false, false, true);
|
set<int>(), false, false, true, true);
|
||||||
vector<wstring> fileList;
|
vector<wstring> fileList;
|
||||||
fileList.push_back(startlist);
|
fileList.push_back(startlist);
|
||||||
|
|
||||||
@ -1232,7 +1237,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
|
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
|
||||||
oe->exportIOFSplits(oEvent::IOF30, resultlist.c_str(), false,
|
oe->exportIOFSplits(oEvent::IOF30, resultlist.c_str(), false,
|
||||||
eventorUTC, classes, -1, false, true,
|
eventorUTC, classes, -1, false, true,
|
||||||
false, true);
|
false, true, true);
|
||||||
vector<wstring> fileList;
|
vector<wstring> fileList;
|
||||||
fileList.push_back(resultlist);
|
fileList.push_back(resultlist);
|
||||||
|
|
||||||
@ -1332,6 +1337,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addCheckbox("EventorDb", "Uppdatera löpardatabasen", CompetitionCB, true);
|
gdi.addCheckbox("EventorDb", "Uppdatera löpardatabasen", CompetitionCB, true);
|
||||||
|
gdi.addCheckbox("IncludeWithoutClub", "Inkludera klubblösa");
|
||||||
|
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.addButton("Cancel", "Avbryt", CompetitionCB);
|
gdi.addButton("Cancel", "Avbryt", CompetitionCB);
|
||||||
@ -1339,14 +1346,16 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
else if (bi.id == "EventorCmp") {
|
else if (bi.id == "EventorCmp") {
|
||||||
gdi.setInputStatus("EventorSel", gdi.isChecked(bi.id));
|
gdi.setInputStatus("EventorSel", gdi.isChecked(bi.id));
|
||||||
gdi.setInputStatus("EventorNext", gdi.isChecked(bi.id) | gdi.isChecked("EventorDb"));
|
gdi.setInputStatus("EventorNext", gdi.isChecked(bi.id) || gdi.isChecked("EventorDb"));
|
||||||
}
|
}
|
||||||
else if (bi.id == "EventorDb") {
|
else if (bi.id == "EventorDb") {
|
||||||
gdi.setInputStatus("EventorNext", gdi.isChecked(bi.id) | gdi.isChecked("EventorCmp"));
|
gdi.setInputStatus("EventorNext", gdi.isChecked(bi.id) || gdi.isChecked("EventorCmp"));
|
||||||
}
|
}
|
||||||
else if (bi.id == "EventorNext") {
|
else if (bi.id == "EventorNext") {
|
||||||
bool cmp = gdi.isChecked("EventorCmp");
|
bool cmp = gdi.isChecked("EventorCmp");
|
||||||
bool db = gdi.isChecked("EventorDb");
|
bool db = gdi.isChecked("EventorDb");
|
||||||
|
bool withNoClub = gdi.isChecked("IncludeWithoutClub");
|
||||||
|
|
||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
gdi.getSelectedItem("EventorSel", lbi);
|
gdi.getSelectedItem("EventorSel", lbi);
|
||||||
const CompetitionInfo *ci = 0;
|
const CompetitionInfo *ci = 0;
|
||||||
@ -1355,6 +1364,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.clearPage(true);
|
gdi.clearPage(true);
|
||||||
gdi.setData("UpdateDB", db);
|
gdi.setData("UpdateDB", db);
|
||||||
|
gdi.setData("IncludeWithoutClub", withNoClub);
|
||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
if (cmp && ci) {
|
if (cmp && ci) {
|
||||||
gdi.setData("EventIndex", lbi.data);
|
gdi.setData("EventIndex", lbi.data);
|
||||||
@ -1412,11 +1423,14 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.popX();
|
gdi.popX();
|
||||||
}
|
}
|
||||||
else if (bi.id == "EventorImport") {
|
else if (bi.id == "EventorImport") {
|
||||||
const int diffZeroTime = 3600;
|
const int diffZeroTime = timeConstHour;
|
||||||
DWORD id;
|
DWORD id;
|
||||||
DWORD db;
|
DWORD db;
|
||||||
|
DWORD withNoClub;
|
||||||
|
|
||||||
gdi.getData("EventorId", id);
|
gdi.getData("EventorId", id);
|
||||||
gdi.getData("UpdateDB", db);
|
gdi.getData("UpdateDB", db);
|
||||||
|
gdi.getData("IncludeWithoutClub", withNoClub);
|
||||||
|
|
||||||
DWORD eventIndex;
|
DWORD eventIndex;
|
||||||
gdi.getData("EventIndex", eventIndex);
|
gdi.getData("EventIndex", eventIndex);
|
||||||
@ -1444,7 +1458,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
firstStart = t;
|
firstStart = t;
|
||||||
zeroTime = t - diffZeroTime;
|
zeroTime = t - diffZeroTime;
|
||||||
if (zeroTime<0)
|
if (zeroTime<0)
|
||||||
zeroTime += 3600*24;
|
zeroTime += timeConstHour * 24;
|
||||||
|
|
||||||
startType = gdi.getSelectedItem("StartType").first;
|
startType = gdi.getSelectedItem("StartType").first;
|
||||||
lastEntry = gdi.getText("LastEntryDate");
|
lastEntry = gdi.getText("LastEntryDate");
|
||||||
@ -1509,8 +1523,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
else
|
else
|
||||||
tRunnerDB = extractedFiles[0];
|
tRunnerDB = extractedFiles[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
oe->importXML_IOF_Data(tClubs, tRunnerDB, true);
|
oe->importXML_IOF_Data(tClubs, tRunnerDB, withNoClub == 0, true);
|
||||||
removeTempFile(tClubs);
|
removeTempFile(tClubs);
|
||||||
|
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
@ -1522,6 +1536,12 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (createNew && id>0) {
|
if (createNew && id>0) {
|
||||||
gdi.addString("", 1, "Skapar ny tävling");
|
gdi.addString("", 1, "Skapar ny tävling");
|
||||||
oe->newCompetition(L"New");
|
oe->newCompetition(L"New");
|
||||||
|
oe->loadDefaults();
|
||||||
|
|
||||||
|
bool importHiredCard = true;
|
||||||
|
if (importHiredCard)
|
||||||
|
importDefaultHiredCards(gdi);
|
||||||
|
|
||||||
oe->importXML_EntryData(gdi, tEvent, false, false, noFilter, noType);
|
oe->importXML_EntryData(gdi, tEvent, false, false, noFilter, noType);
|
||||||
oe->setZeroTime(formatTimeHMS(zeroTime), false);
|
oe->setZeroTime(formatTimeHMS(zeroTime), false);
|
||||||
oe->getDI().setDate("OrdinaryEntry", lastEntry);
|
oe->getDI().setDate("OrdinaryEntry", lastEntry);
|
||||||
@ -1546,7 +1566,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
if (!course.empty()) {
|
if (!course.empty()) {
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
TabCourse::runCourseImport(gdi, course, oe, true);
|
TabCourse::runCourseImport(gdi, course, oe, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
set<int> clsWithRef;
|
set<int> clsWithRef;
|
||||||
@ -1563,7 +1583,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
switch (startType) {
|
switch (startType) {
|
||||||
case SMCommon:
|
case SMCommon:
|
||||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0",
|
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart, SubSecond::Off), L"0",
|
||||||
L"0", oEvent::VacantPosition::Mixed,
|
L"0", oEvent::VacantPosition::Mixed,
|
||||||
false, false, oEvent::DrawMethod::Random, 1);
|
false, false, oEvent::DrawMethod::Random, 1);
|
||||||
break;
|
break;
|
||||||
@ -1589,7 +1609,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!skip)
|
if (!skip)
|
||||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00",
|
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart, SubSecond::Off), L"2:00",
|
||||||
L"2", oEvent::VacantPosition::Mixed,
|
L"2", oEvent::VacantPosition::Mixed,
|
||||||
true, false, oEvent::DrawMethod::MeOS, 1);
|
true, false, oEvent::DrawMethod::MeOS, 1);
|
||||||
break;
|
break;
|
||||||
@ -1780,7 +1800,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (filterIndex == ImportFormats::IOF30 || filterIndex == ImportFormats::IOF203) {
|
if (filterIndex == ImportFormats::IOF30 || filterIndex == ImportFormats::IOF203) {
|
||||||
bool useUTC = oe->getDCI().getInt("UTC") != 0;
|
bool useUTC = oe->getDCI().getInt("UTC") != 0;
|
||||||
oe->exportIOFStartlist(filterIndex == ImportFormats::IOF30 ? oEvent::IOF30 : oEvent::IOF20,
|
oe->exportIOFStartlist(filterIndex == ImportFormats::IOF30 ? oEvent::IOF30 : oEvent::IOF20,
|
||||||
save.c_str(), useUTC, allTransfer, individual, includeStage, false);
|
save.c_str(), useUTC, allTransfer, individual, includeStage, false, false);
|
||||||
}
|
}
|
||||||
else if (filterIndex == ImportFormats::OE) {
|
else if (filterIndex == ImportFormats::OE) {
|
||||||
oe->exportOECSV(save.c_str(), cSVLanguageHeaderIndex, false);
|
oe->exportOECSV(save.c_str(), cSVLanguageHeaderIndex, false);
|
||||||
@ -1838,7 +1858,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
if (!gdi.hasWidget("LegType")) {
|
if (!gdi.hasWidget("LegType")) {
|
||||||
oe->exportIOFSplits(ver, save.c_str(), true, useUTC,
|
oe->exportIOFSplits(ver, save.c_str(), true, useUTC,
|
||||||
allTransfer, -1, false, unroll, includeStage, false);
|
allTransfer, -1, false, unroll, includeStage, false, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ListBoxInfo leglbi;
|
ListBoxInfo leglbi;
|
||||||
@ -1860,17 +1880,17 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
for (int leg = 0; leg<legMax; leg++) {
|
for (int leg = 0; leg<legMax; leg++) {
|
||||||
file = fileBase + L"_" + itow(leg+1) + fileEnd;
|
file = fileBase + L"_" + itow(leg+1) + fileEnd;
|
||||||
oe->exportIOFSplits(ver, file.c_str(), true, useUTC,
|
oe->exportIOFSplits(ver, file.c_str(), true, useUTC,
|
||||||
allTransfer, leg, false, unroll, includeStage, false);
|
allTransfer, leg, false, unroll, includeStage, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (leglbi.data == 3) {
|
else if (leglbi.data == 3) {
|
||||||
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
|
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
|
||||||
-1, true, unroll, includeStage, false);
|
-1, true, unroll, includeStage, false, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int leg = leglbi.data == 1 ? -1 : leglbi.data - 10;
|
int leg = leglbi.data == 1 ? -1 : leglbi.data - 10;
|
||||||
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
|
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
|
||||||
leg, false, unroll, includeStage, false);
|
leg, false, unroll, includeStage, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1951,6 +1971,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
oe->newCompetition(lang.tl(L"Ny tävling"));
|
oe->newCompetition(lang.tl(L"Ny tävling"));
|
||||||
|
oe->loadDefaults();
|
||||||
gdi.setWindowTitle(L"");
|
gdi.setWindowTitle(L"");
|
||||||
|
|
||||||
if (useEventor()) {
|
if (useEventor()) {
|
||||||
@ -2077,15 +2098,18 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.disableInput("Cancel");
|
gdi.disableInput("Cancel");
|
||||||
gdi.disableInput("BrowseCourse");
|
gdi.disableInput("BrowseCourse");
|
||||||
gdi.disableInput("AddClasses");
|
gdi.disableInput("AddClasses");
|
||||||
|
gdi.disableInput("CreateClasses");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TabCourse::runCourseImport(gdi, filename, oe, gdi.isChecked("AddClasses"));
|
TabCourse::runCourseImport(gdi, filename, oe, gdi.isChecked("AddClasses"),
|
||||||
|
gdi.isChecked("CreateClasses"));
|
||||||
}
|
}
|
||||||
catch (std::exception &) {
|
catch (const std::exception &) {
|
||||||
gdi.enableInput("DoImportCourse");
|
gdi.enableInput("DoImportCourse");
|
||||||
gdi.enableInput("Cancel");
|
gdi.enableInput("Cancel");
|
||||||
gdi.enableInput("BrowseCourse");
|
gdi.enableInput("BrowseCourse");
|
||||||
gdi.enableInput("AddClasses");
|
gdi.enableInput("AddClasses");
|
||||||
|
gdi.enableInput("CreateClasses");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
@ -2136,7 +2160,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.setWaitCursor(true);
|
gdi.setWaitCursor(true);
|
||||||
xml.openOutput(fileName.c_str(), false);
|
xml.openOutput(fileName.c_str(), false);
|
||||||
IOF30Interface writer(oe, false);
|
IOF30Interface writer(oe, false, false);
|
||||||
writer.writeRunnerDB(oe->getRunnerDatabase(), xml);
|
writer.writeRunnerDB(oe->getRunnerDatabase(), xml);
|
||||||
gdi.setWaitCursor(false);
|
gdi.setWaitCursor(false);
|
||||||
}
|
}
|
||||||
@ -2151,7 +2175,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
gdi.setWaitCursor(true);
|
gdi.setWaitCursor(true);
|
||||||
xml.openOutput(fileName.c_str(), false);
|
xml.openOutput(fileName.c_str(), false);
|
||||||
IOF30Interface writer(oe, false);
|
IOF30Interface writer(oe, false, false);
|
||||||
writer.writeClubDB(oe->getRunnerDatabase(), xml);
|
writer.writeClubDB(oe->getRunnerDatabase(), xml);
|
||||||
gdi.setWaitCursor(false);
|
gdi.setWaitCursor(false);
|
||||||
}
|
}
|
||||||
@ -2242,6 +2266,9 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.setInputStatus(gdi.narrow(fn).c_str(), !ii.text.empty());
|
gdi.setInputStatus(gdi.narrow(fn).c_str(), !ii.text.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ii.id == "Name") {
|
||||||
|
updateWarning(gdi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type==GUI_EVENT) {
|
else if (type==GUI_EVENT) {
|
||||||
EventInfo ei=*(EventInfo *)data;
|
EventInfo ei=*(EventInfo *)data;
|
||||||
@ -2277,16 +2304,16 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.setData("RunnerIx", ix);
|
gdi.setData("RunnerIx", ix);
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addSelection("Classes", 200, 300, 0, L"Klasser:");
|
gdi.addSelection("Classes", 200, 300, 0, L"Klasser:");
|
||||||
oe->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterNone);
|
oe->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterOnlySingle);
|
||||||
|
|
||||||
if (lastSelectedClass != -1)
|
if (lastSelectedClass == -1 || !gdi.selectItemByData("Classes", lastSelectedClass))
|
||||||
gdi.selectItemByData("Classes", lastSelectedClass);
|
|
||||||
else
|
|
||||||
gdi.selectFirstItem("Classes");
|
gdi.selectFirstItem("Classes");
|
||||||
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addButton("DBEntry", "Anmäl", CompetitionCB).setDefault();
|
gdi.addButton("DBEntry", "Anmäl", CompetitionCB).setDefault();
|
||||||
|
gdi.setInputStatus("DBEntry", gdi.getSelectedItem("Classes").first > 0); // Cannot change
|
||||||
|
|
||||||
gdi.addButton("CancelEntry", "Avbryt", CompetitionCB).setCancel();
|
gdi.addButton("CancelEntry", "Avbryt", CompetitionCB).setCancel();
|
||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
@ -2339,7 +2366,7 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
|
|||||||
|
|
||||||
if (ti.id == "") {
|
if (ti.id == "") {
|
||||||
wstring fi(bi.FullPath);
|
wstring fi(bi.FullPath);
|
||||||
if (!oe->open(fi, false, false)) {
|
if (!oe->open(fi, false, false, false)) {
|
||||||
gdi.alert("Kunde inte öppna tävlingen.");
|
gdi.alert("Kunde inte öppna tävlingen.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2392,7 +2419,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
|
|||||||
|
|
||||||
gdi.dropLine(0.4);
|
gdi.dropLine(0.4);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2022 Melin Software HB"));
|
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2023 Melin Software HB"));
|
||||||
gdi.dropLine(1);
|
gdi.dropLine(1);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
@ -2422,7 +2449,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
|||||||
gdi.dropLine(1.5);
|
gdi.dropLine(1.5);
|
||||||
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
||||||
|
|
||||||
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2022 Melin Software HB"));
|
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2023 Melin Software HB"));
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
||||||
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
|
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
|
||||||
@ -2463,6 +2490,20 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
|||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabCompetition::updateWarning(gdioutput &gdi) const {
|
||||||
|
const wstring &n = gdi.getText("Name");
|
||||||
|
const wstring &w = gdi.getText("cmpwarning");
|
||||||
|
constexpr int limit = 32;
|
||||||
|
if (n.length() < limit && !w.empty()) {
|
||||||
|
gdi.setText("warningicon", L"", true);
|
||||||
|
gdi.setText("cmpwarning", L"", true);
|
||||||
|
}
|
||||||
|
else if (n.length() >= limit && w.empty()) {
|
||||||
|
gdi.setText("warningicon", L"514", true);
|
||||||
|
gdi.setText("cmpwarning", L"Ett långt tävlingsnamn kan ge oväntad nerskalning av utskrifter.", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool TabCompetition::useEventor() const {
|
bool TabCompetition::useEventor() const {
|
||||||
return oe->getPropertyInt("UseEventor", 0) == 1;
|
return oe->getPropertyInt("UseEventor", 0) == 1;
|
||||||
}
|
}
|
||||||
@ -2566,7 +2607,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addInput("Name", oe->getName(), 24, 0, L"Tävlingsnamn:");
|
gdi.addInput("Name", oe->getName(), 24, CompetitionCB, L"Tävlingsnamn:");
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
|
||||||
gdi.addInput("Annotation", oe->getAnnotation(), 20, 0, L"Kommentar / version:")
|
gdi.addInput("Annotation", oe->getAnnotation(), 20, 0, L"Kommentar / version:")
|
||||||
@ -2579,12 +2620,16 @@ bool TabCompetition::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.dropLine(1.2);
|
gdi.dropLine(1.2);
|
||||||
|
//int ccx = gdi.getCX();
|
||||||
gdi.addCheckbox("LongTimes", "Aktivera stöd för tider över 24 timmar", CompetitionCB, oe->useLongTimes());
|
gdi.addCheckbox("LongTimes", "Aktivera stöd för tider över 24 timmar", CompetitionCB, oe->useLongTimes());
|
||||||
|
gdi.addCheckbox("SubSecond", "Aktivera stöd för tiondels sekunder", CompetitionCB, oe->supportSubSeconds());
|
||||||
|
|
||||||
|
gdi.dropLine(0.3);
|
||||||
if (false && oe->isClient()) {
|
if (false && oe->isClient()) {
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.disableInput("ZeroTime");
|
gdi.disableInput("ZeroTime");
|
||||||
gdi.disableInput("LongTimes");
|
gdi.disableInput("LongTimes");
|
||||||
|
gdi.disableInput("SubSecond");
|
||||||
if (oe->useLongTimes())
|
if (oe->useLongTimes())
|
||||||
gdi.disableInput("Date");
|
gdi.disableInput("Date");
|
||||||
}
|
}
|
||||||
@ -2651,6 +2696,14 @@ bool TabCompetition::loadPage(gdioutput &gdi)
|
|||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.addString("warningicon", textImage, "S25");
|
||||||
|
gdi.dropLine(0.2);
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.addString("cmpwarning", 0, "");
|
||||||
|
updateWarning(gdi);
|
||||||
|
gdi.popX();
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
gdi.setCX(gdi.getCX()+gdi.scaleLength(60));
|
gdi.setCX(gdi.getCX()+gdi.scaleLength(60));
|
||||||
@ -2908,26 +2961,26 @@ void TabCompetition::getEventorCompetitions(gdioutput &gdi,
|
|||||||
date.getObjectString("Clock", ci.firstStart);
|
date.getObjectString("Clock", ci.firstStart);
|
||||||
|
|
||||||
if (useEventorUTC()) {
|
if (useEventorUTC()) {
|
||||||
int offset = getTimeZoneInfo(ci.Date);
|
int offset = getTimeZoneInfo(ci.Date) * timeConstSecond;
|
||||||
int t = convertAbsoluteTimeISO(ci.firstStart);
|
int t = convertAbsoluteTimeISO(ci.firstStart);
|
||||||
int nt = t - offset;
|
int nt = t - offset;
|
||||||
int dayOffset = 0;
|
int dayOffset = 0;
|
||||||
if (nt < 0) {
|
if (nt < 0) {
|
||||||
nt += 24*3600;
|
nt += 24 * timeConstHour;
|
||||||
dayOffset = -1;
|
dayOffset = -1;
|
||||||
}
|
}
|
||||||
else if (nt > 24*3600) {
|
else if (nt > 24* timeConstHour) {
|
||||||
nt -= 24*3600;
|
nt -= 24* timeConstHour;
|
||||||
dayOffset = 1;
|
dayOffset = 1;
|
||||||
}
|
}
|
||||||
ci.firstStart = formatTimeHMS(nt);
|
ci.firstStart = formatTimeHMS(nt, SubSecond::Off);
|
||||||
//TODO: Take dayoffset into account
|
//TODO: Take dayoffset into account
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlEvents[k].getObjectString("WebURL", ci.url);
|
xmlEvents[k].getObjectString("WebURL", ci.url);
|
||||||
xmlobject aco = xmlEvents[k].getObject("Account");
|
xmlobject aco = xmlEvents[k].getObject("Account");
|
||||||
if (aco) {
|
if (aco) {
|
||||||
string type = aco.getAttrib("type").get();
|
string type = aco.getAttrib("type").getStr();
|
||||||
wstring no;
|
wstring no;
|
||||||
aco.getObjectString("AccountNo", no);
|
aco.getObjectString("AccountNo", no);
|
||||||
|
|
||||||
@ -2960,8 +3013,8 @@ void TabCompetition::getEventorCompetitions(gdioutput &gdi,
|
|||||||
|
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
convertDateYMS(breakDate, st, false);
|
convertDateYMS(breakDate, st, false);
|
||||||
__int64 time = SystemTimeToInt64Second(st) - 1;
|
__int64 time = SystemTimeToInt64TenthSecond(st) - 10;
|
||||||
breakDate = convertSystemDate(Int64SecondToSystemTime(time));
|
breakDate = convertSystemDate(Int64TenthSecondToSystemTime(time));
|
||||||
|
|
||||||
if (ci.lastNormalEntryDate.empty() || ci.lastNormalEntryDate >= breakDate)
|
if (ci.lastNormalEntryDate.empty() || ci.lastNormalEntryDate >= breakDate)
|
||||||
ci.lastNormalEntryDate = breakDate;
|
ci.lastNormalEntryDate = breakDate;
|
||||||
@ -3080,7 +3133,9 @@ void TabCompetition::getEventorCmpData(gdioutput &gdi, int id,
|
|||||||
if (dbFile.length() > 0) {
|
if (dbFile.length() > 0) {
|
||||||
gdi.addString("", 0, "Hämtar löpardatabasen...");
|
gdi.addString("", 0, "Hämtar löpardatabasen...");
|
||||||
gdi.refreshFast();
|
gdi.refreshFast();
|
||||||
dwl.downloadFile(eventorBase + L"export/cachedcompetitors?organisationIds=1&includePreselectedClasses=false&zip=true" + iofExportVersion, dbFile, key);
|
//dwl.downloadFile(eventorBase + L"export/cachedcompetitors?organisationIds=1&includePreselectedClasses=false&zip=true" + iofExportVersion, dbFile, key);
|
||||||
|
dwl.downloadFile(eventorBase + L"export/cachedcompetitors?includePreselectedClasses=false&zip=true" + iofExportVersion, dbFile, key);
|
||||||
|
|
||||||
dwl.createDownloadThread();
|
dwl.createDownloadThread();
|
||||||
while (dwl.isWorking()) {
|
while (dwl.isWorking()) {
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
@ -3640,7 +3695,7 @@ FlowOperation TabCompetition::checkStageFilter(gdioutput & gdi,
|
|||||||
xml.read(fname);
|
xml.read(fname);
|
||||||
xmlobject xo = xml.getObject("EntryList");
|
xmlobject xo = xml.getObject("EntryList");
|
||||||
set<int> scanFilter;
|
set<int> scanFilter;
|
||||||
IOF30Interface reader(oe, false);
|
IOF30Interface reader(oe, false, false);
|
||||||
vector<string> idProviders;
|
vector<string> idProviders;
|
||||||
if (xo) {
|
if (xo) {
|
||||||
if (xo.getAttrib("iofVersion")) {
|
if (xo.getAttrib("iofVersion")) {
|
||||||
@ -3967,9 +4022,7 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
|
|||||||
gdi.addString("", 1, "Tidszon");
|
gdi.addString("", 1, "Tidszon");
|
||||||
|
|
||||||
gdi.dropLine(0.3);
|
gdi.dropLine(0.3);
|
||||||
gdi.addCheckbox("UTC", "Exportera tider i UTC", 0,
|
gdi.addCheckbox("UTC", "Exportera tider i UTC", nullptr, oe->getDCI().getInt("UTC") != 0);
|
||||||
oe->getDCI().getInt("UTC") == 1);
|
|
||||||
|
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
gdi.popY();
|
gdi.popY();
|
||||||
@ -3999,16 +4052,60 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
|
|||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
|
|
||||||
gdi.addString("", 1, "Åldersgränser, reducerad anmälningsavgift");
|
gdi.addString("", 1, "Åldersgränser, reducerad anmälningsavgift");
|
||||||
fields.clear();
|
gdi.addString("", 0, "Ungdomar och äldre kan få reducerad avgift");
|
||||||
fields.push_back("YouthAge");
|
gdi.dropLine(0.5);
|
||||||
fields.push_back("SeniorAge");
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
oe->getDI().buildDataFields(gdi, fields, 10);
|
auto yfields = oe->getDI().buildDataFields(gdi, { "YouthAge" , "SeniorAge" }, 10);
|
||||||
|
|
||||||
|
class HandleAge : public GuiHandler {
|
||||||
|
public:
|
||||||
|
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) final {
|
||||||
|
if (type == GuiEventType::GUI_INPUT)
|
||||||
|
update(gdi, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(gdioutput &gdi, bool update) {
|
||||||
|
int youth = gdi.getTextNo("YouthAge_odc");
|
||||||
|
int senior = gdi.getTextNo("SeniorAge_odc");
|
||||||
|
|
||||||
|
InputInfo &ii = dynamic_cast<InputInfo &>(gdi.getBaseInfo("SeniorAge_odc"));
|
||||||
|
bool warn = senior > 1 && senior <= youth + 1;
|
||||||
|
ii.setBgColor(warn ? colorLightRed : colorDefault);
|
||||||
|
|
||||||
|
string i1, i2, i3;
|
||||||
|
if (youth <= 0 && senior <= 0) {
|
||||||
|
i1 = "Ingen reducerad avgift";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i1 = "Reducerad avgift för:";
|
||||||
|
|
||||||
|
if (youth > 0)
|
||||||
|
i2 = "Unga, till och med X år#" + itos(youth);
|
||||||
|
else
|
||||||
|
i2 = "Äldre, från och med X år#" + itos(senior);
|
||||||
|
|
||||||
|
if (youth > 0 && senior > 0)
|
||||||
|
i3 = "Äldre, från och med X år#" + itos(senior);
|
||||||
|
}
|
||||||
|
gdi.setText("ReduceInfo", lang.tl(i1), update);
|
||||||
|
gdi.setText("ReduceInfoL1", i2.empty() ? L"" : L"\u25AA " + lang.tl(i2), update);
|
||||||
|
gdi.setText("ReduceInfoL2", i3.empty() ? L"" : L"\u25AA " + lang.tl(i3), update);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(2.8);
|
||||||
|
gdi.addString("ReduceInfo", 0, "Ingen reducerad avgift");
|
||||||
|
gdi.addString("ReduceInfoL1", 0, "-");
|
||||||
|
gdi.addString("ReduceInfoL2", 0, "-");
|
||||||
|
|
||||||
|
auto handler = make_shared<HandleAge>();
|
||||||
|
yfields[0]->setHandler(handler);
|
||||||
|
yfields[1]->setHandler(handler);
|
||||||
|
|
||||||
|
gdi.dropLine(0.3);
|
||||||
|
|
||||||
gdi.addString("", 1, "Valuta");
|
gdi.addString("", 1, "Valuta");
|
||||||
fields.clear();
|
fields.clear();
|
||||||
@ -4053,6 +4150,8 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
|
|||||||
oe->getDI().buildDataFields(gdi, fields, 10);
|
oe->getDI().buildDataFields(gdi, fields, 10);
|
||||||
oe->getDI().fillDataFields(gdi);
|
oe->getDI().fillDataFields(gdi);
|
||||||
|
|
||||||
|
handler->update(gdi, false);
|
||||||
|
|
||||||
gdi.dropLine(1);
|
gdi.dropLine(1);
|
||||||
int bottom = gdi.getCY();
|
int bottom = gdi.getCY();
|
||||||
|
|
||||||
@ -4097,17 +4196,16 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TabCompetition::saveSettings(gdioutput &gdi) {
|
void TabCompetition::saveSettings(gdioutput &gdi) {
|
||||||
vector<string> fields;
|
vector<string> fields = { "CardFee" ,"EliteFee" ,"EntryFee","YouthFee" };
|
||||||
vector<int> fees(4);
|
vector<int> fees(4);
|
||||||
fields.push_back("CardFee");
|
|
||||||
fields.push_back("EliteFee");
|
|
||||||
fields.push_back("EntryFee");
|
|
||||||
fields.push_back("YouthFee");
|
|
||||||
|
|
||||||
for (int k = 0; k<4; k++)
|
for (int k = 0; k<4; k++)
|
||||||
fees[k] = oe->getDCI().getInt(fields[k]);
|
fees[k] = oe->getDCI().getInt(fields[k]);
|
||||||
|
|
||||||
wstring factor = oe->getDCI().getString("LateEntryFactor");
|
wstring factor = oe->getDCI().getString("LateEntryFactor");
|
||||||
oe->getDI().saveDataFields(gdi);
|
set<string> modified;
|
||||||
|
|
||||||
|
oe->getDI().saveDataFields(gdi, modified);
|
||||||
|
|
||||||
bool changedFee = false;
|
bool changedFee = false;
|
||||||
bool changedCardFee = false;
|
bool changedCardFee = false;
|
||||||
@ -4119,33 +4217,60 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
|
|||||||
else {
|
else {
|
||||||
changedCardFee = true;
|
changedCardFee = true;
|
||||||
if (oe->getDCI().getInt(fields[k]) == 0)
|
if (oe->getDCI().getInt(fields[k]) == 0)
|
||||||
oe->getDI().setInt(fields[k].c_str(), -1); // Disallow zero card fee. -1 means no fee.
|
oe->getDI().setInt(fields[k], -1); // Disallow zero card fee. -1 means no fee.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (factor != oe->getDCI().getString("LateEntryFactor"))
|
if (factor != oe->getDCI().getString("LateEntryFactor"))
|
||||||
changedFee = true;
|
changedFee = true;
|
||||||
|
|
||||||
oe->getDI().setInt("UTC", gdi.isChecked("UTC") ? 1 : 0);
|
if (oe->getDI().setInt("UTC", gdi.isChecked("UTC") ? 1 : 0))
|
||||||
|
setEventorUTC(gdi.isChecked("UTC"));
|
||||||
|
|
||||||
|
if (oe->getDI().setInt("CurrencyFactor", gdi.isChecked("UseFraction") ? 100 : 1))
|
||||||
|
modified.insert("CurrencyFactor");
|
||||||
|
|
||||||
|
if (oe->getDI().setInt("CurrencyPreSymbol", gdi.isChecked("PreSymbol") ? 1 : 0))
|
||||||
|
modified.insert("CurrencyPreSymbol");
|
||||||
|
|
||||||
oe->getDI().setInt("CurrencyFactor", gdi.isChecked("UseFraction") ? 100 : 1);
|
|
||||||
oe->getDI().setInt("CurrencyPreSymbol", gdi.isChecked("PreSymbol") ? 1 : 0);
|
|
||||||
oe->setCurrency(-1, L"", L"", false);
|
oe->setCurrency(-1, L"", L"", false);
|
||||||
|
|
||||||
vector< pair<wstring, size_t> > modes;
|
wstring pm = oe->getDCI().getString("PayModes");
|
||||||
|
vector<pair<wstring, size_t>> modes;
|
||||||
oe->getPayModes(modes);
|
oe->getPayModes(modes);
|
||||||
for (size_t k = 0; k < modes.size(); k++) {
|
for (size_t k = 0; k < modes.size(); k++) {
|
||||||
string field = "M"+itos(k);
|
string field = "M"+itos(k);
|
||||||
if (gdi.hasWidget(field)) {
|
if (gdi.hasWidget(field)) {
|
||||||
wstring mode = gdi.getText("M"+itos(k));
|
wstring mode = gdi.getText("M"+itos(k));
|
||||||
int id = gdi.getBaseInfo(field.c_str()).getExtraInt();
|
int id = gdi.getBaseInfo(field).getExtraInt();
|
||||||
oe->setPayMode(id, mode);
|
oe->setPayMode(id, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pm != oe->getDCI().getString("PayModes"))
|
||||||
|
modified.insert("PayModes");
|
||||||
|
|
||||||
// Read from model
|
// Read from model
|
||||||
if (oe->isChanged()) {
|
if (oe->isChanged()) {
|
||||||
oe->setProperty("Organizer", oe->getDCI().getString("Organizer"));
|
vector<string> props = { "Organizer" ,"Street" ,"Address" ,"EMail" ,"Homepage" ,
|
||||||
|
"YouthAge","SeniorAge","Account", "LateEntryFactor","CurrencySymbol",
|
||||||
|
"CurrencyFactor","CurrencyPreSymbol","CurrencySeparator",
|
||||||
|
"CardFee","EliteFee","EntryFee","YouthFee", "PayModes" };
|
||||||
|
|
||||||
|
auto dci = oe->getDCI();
|
||||||
|
for (const string &p : props) {
|
||||||
|
if (modified.count(p)) {
|
||||||
|
if (dci.isString(p))
|
||||||
|
oe->setProperty(p.c_str(), dci.getString(p));
|
||||||
|
else if (dci.isInt(p))
|
||||||
|
oe->setProperty(p.c_str(), dci.getInt(p));
|
||||||
|
else
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//oe->setProperty("PayModes", oe->getDCI().getString("PayModes"));
|
||||||
|
|
||||||
|
/*oe->setProperty("Organizer", oe->getDCI().getString("Organizer"));
|
||||||
oe->setProperty("Street", oe->getDCI().getString("Street"));
|
oe->setProperty("Street", oe->getDCI().getString("Street"));
|
||||||
oe->setProperty("Address", oe->getDCI().getString("Address"));
|
oe->setProperty("Address", oe->getDCI().getString("Address"));
|
||||||
oe->setProperty("EMail", oe->getDCI().getString("EMail"));
|
oe->setProperty("EMail", oe->getDCI().getString("EMail"));
|
||||||
@ -4166,8 +4291,8 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
|
|||||||
oe->setProperty("CurrencyFactor", oe->getDCI().getInt("CurrencyFactor"));
|
oe->setProperty("CurrencyFactor", oe->getDCI().getInt("CurrencyFactor"));
|
||||||
oe->setProperty("CurrencyPreSymbol", oe->getDCI().getInt("CurrencyPreSymbol"));
|
oe->setProperty("CurrencyPreSymbol", oe->getDCI().getInt("CurrencyPreSymbol"));
|
||||||
oe->setProperty("CurrencySeparator", oe->getDCI().getString("CurrencySeparator"));
|
oe->setProperty("CurrencySeparator", oe->getDCI().getString("CurrencySeparator"));
|
||||||
|
*/
|
||||||
oe->setProperty("PayModes", oe->getDCI().getString("PayModes"));
|
//oe->setProperty("PayModes", oe->getDCI().getString("PayModes"));
|
||||||
}
|
}
|
||||||
oe->synchronize(true);
|
oe->synchronize(true);
|
||||||
set<int> dummy;
|
set<int> dummy;
|
||||||
@ -4260,7 +4385,7 @@ void TabCompetition::mergeCompetition(gdioutput &gdi) {
|
|||||||
if (!thisFile.empty()) {
|
if (!thisFile.empty()) {
|
||||||
wchar_t newBase[_MAX_PATH];
|
wchar_t newBase[_MAX_PATH];
|
||||||
getUserFile(newBase, thisFile.c_str());
|
getUserFile(newBase, thisFile.c_str());
|
||||||
mergeEvent->save(newBase);
|
mergeEvent->save(newBase, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
tc->oe->merge(*mergeEvent, baseEvent.get(), allowRemove, numAdd, numRemove, numUpdate);
|
tc->oe->merge(*mergeEvent, baseEvent.get(), allowRemove, numAdd, numRemove, numUpdate);
|
||||||
@ -4285,7 +4410,7 @@ void TabCompetition::mergeCompetition(gdioutput &gdi) {
|
|||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
else if (bi.id == "Browse") {
|
else if (bi.id == "Browse") {
|
||||||
wstring fn = gdi.browseForOpen({ make_pair(L"xml", L"*.xml") }, L"xml");
|
wstring fn = gdi.browseForOpen({ make_pair(L"MeOS-data", L"*.meosxml;*.xml;*.bu?") }, L"meosxml");
|
||||||
if (fn.empty())
|
if (fn.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -4296,7 +4421,7 @@ void TabCompetition::mergeCompetition(gdioutput &gdi) {
|
|||||||
else if (bi.id == "Read") {
|
else if (bi.id == "Read") {
|
||||||
mergeEvent = make_shared<oEvent>(gdi);
|
mergeEvent = make_shared<oEvent>(gdi);
|
||||||
|
|
||||||
if (!mergeEvent->open(tc->mergeFile, true, true))
|
if (!mergeEvent->open(tc->mergeFile, true, true, false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gdi.restore("merge", false);
|
gdi.restore("merge", false);
|
||||||
@ -4384,7 +4509,7 @@ void TabCompetition::mergeCompetition(gdioutput &gdi) {
|
|||||||
baseEvent = make_shared<oEvent>(gdi);
|
baseEvent = make_shared<oEvent>(gdi);
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
try {
|
try {
|
||||||
ok = baseEvent->open(base, true, true);
|
ok = baseEvent->open(base, true, true, false);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -60,6 +60,8 @@ class TabCompetition :
|
|||||||
void copyrightLine(gdioutput &gdi) const;
|
void copyrightLine(gdioutput &gdi) const;
|
||||||
void loadAboutPage(gdioutput &gdi) const;
|
void loadAboutPage(gdioutput &gdi) const;
|
||||||
|
|
||||||
|
void updateWarning(gdioutput &gdi) const;
|
||||||
|
|
||||||
int organizorId;
|
int organizorId;
|
||||||
|
|
||||||
int lastChangeClassType;
|
int lastChangeClassType;
|
||||||
@ -118,6 +120,7 @@ class TabCompetition :
|
|||||||
void meosFeatures(gdioutput &gdi, bool newGuide);
|
void meosFeatures(gdioutput &gdi, bool newGuide);
|
||||||
|
|
||||||
void newCompetitionGuide(gdioutput &gdi, int step);
|
void newCompetitionGuide(gdioutput &gdi, int step);
|
||||||
|
void createNewCmp(gdioutput &gdi, bool useExisting);
|
||||||
|
|
||||||
void entryForm(gdioutput &gdi, bool isGuide);
|
void entryForm(gdioutput &gdi, bool isGuide);
|
||||||
FlowOperation saveEntries(gdioutput &gdi, bool removeRemoved, bool isGuide);
|
FlowOperation saveEntries(gdioutput &gdi, bool removeRemoved, bool isGuide);
|
||||||
@ -132,6 +135,8 @@ class TabCompetition :
|
|||||||
void entryChoice(gdioutput &gdi);
|
void entryChoice(gdioutput &gdi);
|
||||||
void createCompetition(gdioutput &gdi);
|
void createCompetition(gdioutput &gdi);
|
||||||
|
|
||||||
|
void importDefaultHiredCards(gdioutput& gdi);
|
||||||
|
|
||||||
void listBackups(gdioutput &gdi);
|
void listBackups(gdioutput &gdi);
|
||||||
|
|
||||||
shared_ptr<GuiHandler> mergeHandler;
|
shared_ptr<GuiHandler> mergeHandler;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -55,35 +55,46 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
|
|||||||
if (pc) {
|
if (pc) {
|
||||||
pc->synchronize();
|
pc->synchronize();
|
||||||
|
|
||||||
if (pc->getStatus() == oControl::StatusStart ||
|
if (oControl::isSpecialControl(pc->getStatus())) {
|
||||||
pc->getStatus() == oControl::StatusFinish) {
|
|
||||||
gdi.selectItemByData("Controls", pc->getId());
|
gdi.selectItemByData("Controls", pc->getId());
|
||||||
gdi.selectItemByData("Status", oControl::StatusOK);
|
gdi.selectItemByData("Status", int(oControl::ControlStatus::StatusOK));
|
||||||
gdi.setText("ControlID", makeDash(L"-"), true);
|
gdi.setText("ControlID", makeDash(L"-"), true);
|
||||||
|
|
||||||
gdi.setText("Code", L"");
|
gdi.setText("Code", L"");
|
||||||
gdi.setText("Name", pc->getName());
|
gdi.setText("Name", pc->getName());
|
||||||
gdi.setText("TimeAdjust", L"00:00");
|
gdi.setText("TimeAdjust", pc->getTimeAdjustS());
|
||||||
gdi.setText("MinTime", makeDash(L"-"));
|
gdi.setText("MinTime", makeDash(L"-"));
|
||||||
gdi.setText("Point", L"");
|
gdi.setText("Point", L"");
|
||||||
|
gdi.disableInput("Visitors");
|
||||||
|
gdi.disableInput("Courses");
|
||||||
|
|
||||||
controlId = pc->getId();
|
controlId = pc->getId();
|
||||||
|
|
||||||
gdi.enableInput("Remove");
|
gdi.enableInput("Remove");
|
||||||
gdi.enableInput("Save");
|
gdi.enableInput("Save");
|
||||||
gdi.enableEditControls(false);
|
gdi.enableEditControls(false);
|
||||||
gdi.enableInput("Name");
|
gdi.enableInput("Name");
|
||||||
|
|
||||||
|
if (pc->getUnitCode() > 0) {
|
||||||
|
gdi.setText("Code", itow(pc->getUnitCode()));
|
||||||
|
gdi.enableInput("TimeAdjust");
|
||||||
|
gdi.setText("Info", lang.tl("Du kan justera tiden för en viss enhet"), true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gdi.setText("Info", L"", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gdi.selectItemByData("Controls", pc->getId());
|
gdi.selectItemByData("Controls", pc->getId());
|
||||||
gdi.selectItemByData("Status", pc->getStatus());
|
gdi.selectItemByData("Status", int(pc->getStatus()));
|
||||||
const int numVisit = pc->getNumVisitors(true);
|
const int numVisit = pc->getNumVisitors(true);
|
||||||
const int numVisitExp = pc->getNumVisitors(false);
|
const int numVisitExp = pc->getNumVisitors(false);
|
||||||
|
|
||||||
wstring info;
|
wstring info;
|
||||||
if (numVisit > 0) {
|
if (numVisit > 0) {
|
||||||
info = L"Antal besökare X, genomsnittlig bomtid Y, största bomtid Z#" +
|
info = L"Antal besökare X, genomsnittlig bomtid Y, största bomtid Z#" +
|
||||||
itow(numVisit) + L" (" + itow(numVisitExp) + L")#" + getTimeMS(pc->getMissedTimeTotal() / numVisit) +
|
itow(numVisit) + L" (" + itow(numVisitExp) + L")#" + formatTimeMS(pc->getMissedTimeTotal() / numVisit, false, SubSecond::Off) +
|
||||||
L"#" + getTimeMS(pc->getMissedTimeMax());
|
L"#" + formatTimeMS(pc->getMissedTimeMax(), false, SubSecond::Off);
|
||||||
}
|
}
|
||||||
else if (numVisitExp > 0) {
|
else if (numVisitExp > 0) {
|
||||||
info = L"Förväntat antal besökare: X#" + itow(numVisitExp);
|
info = L"Förväntat antal besökare: X#" + itow(numVisitExp);
|
||||||
@ -108,19 +119,20 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
|
|||||||
gdi.enableEditControls(true);
|
gdi.enableEditControls(true);
|
||||||
|
|
||||||
oControl::ControlStatus st = pc->getStatus();
|
oControl::ControlStatus st = pc->getStatus();
|
||||||
if (st == oControl::StatusRogaining || st == oControl::StatusNoTiming || st == oControl::StatusBadNoTiming)
|
if (st == oControl::ControlStatus::StatusRogaining || st == oControl::ControlStatus::StatusRogainingRequired ||
|
||||||
|
st == oControl::ControlStatus::StatusNoTiming || st == oControl::ControlStatus::StatusBadNoTiming)
|
||||||
gdi.disableInput("MinTime");
|
gdi.disableInput("MinTime");
|
||||||
|
|
||||||
if (st == oControl::StatusNoTiming || st == oControl::StatusBadNoTiming)
|
if (st == oControl::ControlStatus::StatusNoTiming || st == oControl::ControlStatus::StatusBadNoTiming)
|
||||||
gdi.disableInput("TimeAdjust");
|
gdi.disableInput("TimeAdjust");
|
||||||
|
|
||||||
if (gdi.hasWidget("Point") && st != oControl::StatusRogaining)
|
if (gdi.hasWidget("Point") && st != oControl::ControlStatus::StatusRogaining && st != oControl::ControlStatus::StatusRogainingRequired)
|
||||||
gdi.disableInput("Point");
|
gdi.disableInput("Point");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gdi.selectItemByData("Controls", -1);
|
gdi.selectItemByData("Controls", -1);
|
||||||
gdi.selectItemByData("Status", oControl::StatusOK);
|
gdi.selectItemByData("Status", int(oControl::ControlStatus::StatusOK));
|
||||||
gdi.setText("Code", L"");
|
gdi.setText("Code", L"");
|
||||||
gdi.setText("Name", L"");
|
gdi.setText("Name", L"");
|
||||||
controlId = 0;
|
controlId = 0;
|
||||||
@ -145,26 +157,58 @@ int ControlsCB(gdioutput *gdi, int type, void *data)
|
|||||||
return tc.controlCB(*gdi, type, data);
|
return tc.controlCB(*gdi, type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabControl::save(gdioutput &gdi)
|
void TabControl::save(gdioutput &gdi) {
|
||||||
{
|
|
||||||
if (controlId==0)
|
if (controlId==0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DWORD pcid = controlId;
|
pControl pc = oe->getControl(controlId, false, true);
|
||||||
|
|
||||||
pControl pc;
|
|
||||||
pc = oe->getControl(pcid, false);
|
|
||||||
|
|
||||||
if (!pc)
|
if (!pc)
|
||||||
throw std::exception("Internal error");
|
throw std::exception("Internal error");
|
||||||
if (pc->getStatus() != oControl::StatusFinish && pc->getStatus() != oControl::StatusStart) {
|
|
||||||
|
if (!pc->isAddedToEvent()) {
|
||||||
|
if (gdi.getText("TimeAdjust") == pc->getTimeAdjustS()
|
||||||
|
&& gdi.getText("Name") == pc->getName())
|
||||||
|
return; // Virtual control with no change.
|
||||||
|
|
||||||
|
oe->synchronizeList(oListId::oLControlId);
|
||||||
|
pc = oe->getControl(controlId, false, true);
|
||||||
|
|
||||||
|
if (!pc->isAddedToEvent())
|
||||||
|
pc = oe->addControl(*pc);
|
||||||
|
|
||||||
|
if (!pc)
|
||||||
|
throw std::exception("Internal error");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool defaultName = false;
|
||||||
|
|
||||||
|
if (!oControl::isSpecialControl(pc->getStatus())) {
|
||||||
|
int oldFirst = pc->getFirstNumber();
|
||||||
|
|
||||||
if (!pc->setNumbers(gdi.getText("Code")))
|
if (!pc->setNumbers(gdi.getText("Code")))
|
||||||
gdi.alert("Kodsiffran måste vara ett heltal. Flera kodsiffror måste separeras med komma.");
|
gdi.alert("Kodsiffran måste vara ett heltal. Flera kodsiffror måste separeras med komma.");
|
||||||
|
|
||||||
|
int newFirst = pc->getFirstNumber();
|
||||||
|
if (oldFirst != newFirst && pc->getId() == oldFirst) {
|
||||||
|
// Update id if possible (make new control and remove old)
|
||||||
|
if (!oe->isControlUsed(pc->getId()) && oe->getControl(newFirst) == nullptr) {
|
||||||
|
pc->setName(gdi.getText("Name"));
|
||||||
|
if (!pc->hasName())
|
||||||
|
defaultName = true;
|
||||||
|
|
||||||
|
pc = oe->addControl(newFirst, newFirst, L"");
|
||||||
|
pc->synchronize();
|
||||||
|
controlId = pc->getId();
|
||||||
|
pc->setNumbers(gdi.getText("Code"));
|
||||||
|
oe->removeControl(oldFirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pc->setStatus(oControl::ControlStatus(gdi.getSelectedItem("Status").first));
|
pc->setStatus(oControl::ControlStatus(gdi.getSelectedItem("Status").first));
|
||||||
pc->setTimeAdjust(gdi.getText("TimeAdjust"));
|
pc->setTimeAdjust(gdi.getText("TimeAdjust"));
|
||||||
if (pc->getStatus() != oControl::StatusRogaining) {
|
if (pc->getStatus() != oControl::ControlStatus::StatusRogaining && pc->getStatus() != oControl::ControlStatus::StatusRogainingRequired) {
|
||||||
if (pc->getStatus() != oControl::StatusNoTiming && pc->getStatus() != oControl::StatusBadNoTiming)
|
if (pc->getStatus() != oControl::ControlStatus::StatusNoTiming && pc->getStatus() != oControl::ControlStatus::StatusBadNoTiming)
|
||||||
pc->setMinTime(gdi.getText("MinTime"));
|
pc->setMinTime(gdi.getText("MinTime"));
|
||||||
pc->setRogainingPoints(0);
|
pc->setRogainingPoints(0);
|
||||||
}
|
}
|
||||||
@ -175,12 +219,65 @@ void TabControl::save(gdioutput &gdi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (pc->isUnit()) {
|
||||||
|
// Ensure cache is up-to-date
|
||||||
|
auto type = pc->getUnitType();
|
||||||
|
int oldAdjust = oe->getUnitAdjustment(type, pc->getUnitCode());
|
||||||
|
|
||||||
pc->setName(gdi.getText("Name"));
|
if (pc->setTimeAdjust(gdi.getText("TimeAdjust"))) {
|
||||||
|
|
||||||
|
// Cache is not updated. No new adjustment applied
|
||||||
|
assert(oldAdjust == oe->getUnitAdjustment(type, pc->getUnitCode()));
|
||||||
|
|
||||||
|
vector<pair<pRunner, pFreePunch>> adjustList;
|
||||||
|
|
||||||
|
if (type == oPunch::SpecialPunch::PunchStart) {
|
||||||
|
auto pList = oe->getPunchesByType(type, pc->getUnitCode());
|
||||||
|
for (auto p : pList) {
|
||||||
|
pRunner r = oe->getRunnerByCardNo(p->getCardNo(), p->getTimeInt(), oEvent::CardLookupProperty::Any);
|
||||||
|
if (r && !r->getCard() && r->getStartTime() == p->getTimeInt()) {
|
||||||
|
// Need not adjust runners with card.
|
||||||
|
adjustList.emplace_back(r, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == oPunch::SpecialPunch::PunchFinish) {
|
||||||
|
auto pList = oe->getPunchesByType(type, pc->getUnitCode());
|
||||||
|
for (auto p : pList) {
|
||||||
|
pRunner r = oe->getRunnerByCardNo(p->getCardNo(), p->getTimeInt(), oEvent::CardLookupProperty::Any);
|
||||||
|
if (r && !r->getCard() && r->getFinishTime() == p->getTimeInt()) {
|
||||||
|
// Need not adjust runners with card.
|
||||||
|
adjustList.emplace_back(r, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear cache to make sure adjustment takes effect
|
||||||
|
pc->clearCache();
|
||||||
|
oe->clearUnitAdjustmentCache();
|
||||||
|
|
||||||
|
// With new adjustment applied
|
||||||
|
assert(oldAdjust != oe->getUnitAdjustment(type, pc->getUnitCode()));
|
||||||
|
|
||||||
|
for (auto& rp : adjustList) {
|
||||||
|
if (type == oPunch::SpecialPunch::PunchStart) {
|
||||||
|
rp.first->setStartTime(rp.second->getTimeInt(), true, oBase::ChangeType::Update, true);
|
||||||
|
}
|
||||||
|
else if (type == oPunch::SpecialPunch::PunchFinish) {
|
||||||
|
rp.first->setFinishTime(rp.second->getTimeInt());
|
||||||
|
}
|
||||||
|
rp.first->synchronize(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defaultName)
|
||||||
|
pc->setName(gdi.getText("Name"));
|
||||||
|
|
||||||
pc->synchronize();
|
pc->synchronize();
|
||||||
vector< pair<wstring, size_t> > d;
|
|
||||||
oe->fillControls(d, oEvent::CTAll);
|
vector<pair<wstring, size_t>> d;
|
||||||
|
oe->fillControls(d, oEvent::ControlType::All);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
|
|
||||||
oe->reEvaluateAll(set<int>(), true);
|
oe->reEvaluateAll(set<int>(), true);
|
||||||
@ -239,8 +336,8 @@ void TabControl::courseTable(Table &table) const {
|
|||||||
|
|
||||||
void TabControl::visitorTable(Table &table) const {
|
void TabControl::visitorTable(Table &table) const {
|
||||||
vector<pCard> c;
|
vector<pCard> c;
|
||||||
oe->getCards(c);
|
oe->getCards(c, true, false);
|
||||||
pControl pc = oe->getControl(controlId, false);
|
pControl pc = oe->getControl(controlId, false, true);
|
||||||
|
|
||||||
if (!pc)
|
if (!pc)
|
||||||
return;
|
return;
|
||||||
@ -297,7 +394,7 @@ void TabControl::visitorTable(Table &table) const {
|
|||||||
lang.tl("Ja") : lang.tl("Nej"), false);
|
lang.tl("Ja") : lang.tl("Nej"), false);
|
||||||
table.set(row++, it, TID_CARD, it.getCardNoString(), false);
|
table.set(row++, it, TID_CARD, it.getCardNoString(), false);
|
||||||
|
|
||||||
table.set(row++, it, TID_STATUS, punch->getTime(), false);
|
table.set(row++, it, TID_STATUS, punch->getTime(false, SubSecond::Auto), false);
|
||||||
table.set(row++, it, TID_CONTROL, punch->getType(), false);
|
table.set(row++, it, TID_CONTROL, punch->getType(), false);
|
||||||
table.set(row++, it, TID_CODES, j>0 ? p[j-1]->getType() : L"-", true);
|
table.set(row++, it, TID_CODES, j>0 ? p[j-1]->getType() : L"-", true);
|
||||||
}
|
}
|
||||||
@ -316,15 +413,24 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
|
|||||||
bool rogaining = false;
|
bool rogaining = false;
|
||||||
if (controlId>0) {
|
if (controlId>0) {
|
||||||
save(gdi);
|
save(gdi);
|
||||||
pControl pc = oe->getControl(controlId, false);
|
pControl pc = oe->getControl(controlId, false, true);
|
||||||
rogaining = pc && pc->getStatus() == oControl::StatusRogaining;
|
rogaining = pc && (pc->getStatus() == oControl::ControlStatus::StatusRogaining || pc->getStatus() == oControl::ControlStatus::StatusRogainingRequired);
|
||||||
}
|
}
|
||||||
pControl pc = oe->addControl(0,oe->getNextControlNumber(), L"");
|
int nextCtrl = oe->getNextControlNumber();
|
||||||
|
int nextId = nextCtrl;
|
||||||
|
if (oe->getControl(nextId)) {
|
||||||
|
nextId += 1000;
|
||||||
|
if (oe->getControl(nextId))
|
||||||
|
nextId = 0; // Use default
|
||||||
|
}
|
||||||
|
pControl pc = oe->addControl(nextId, nextCtrl, L"");
|
||||||
|
|
||||||
if (rogaining)
|
if (rogaining)
|
||||||
pc->setStatus(oControl::StatusRogaining);
|
pc->setStatus(oControl::ControlStatus::StatusRogaining);
|
||||||
|
|
||||||
|
pc->synchronize();
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe->fillControls(d, oEvent::CTAll);
|
oe->fillControls(d, oEvent::ControlType::All);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
selectControl(gdi, pc);
|
selectControl(gdi, pc);
|
||||||
}
|
}
|
||||||
@ -342,7 +448,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
|
|||||||
oe->removeControl(cid);
|
oe->removeControl(cid);
|
||||||
|
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe->fillControls(d, oEvent::CTAll);
|
oe->fillControls(d, oEvent::ControlType::All);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
selectControl(gdi, 0);
|
selectControl(gdi, 0);
|
||||||
}
|
}
|
||||||
@ -409,16 +515,17 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (gdi.isInputChanged(""))
|
if (gdi.isInputChanged(""))
|
||||||
save(gdi);
|
save(gdi);
|
||||||
|
|
||||||
pControl pc=oe->getControl(bi.data, false);
|
pControl pc=oe->getControl(bi.data, false, true);
|
||||||
if (!pc)
|
if (!pc)
|
||||||
throw std::exception("Internal error");
|
throw std::exception("Internal error");
|
||||||
|
|
||||||
selectControl(gdi, pc);
|
selectControl(gdi, pc);
|
||||||
}
|
}
|
||||||
else if (bi.id == "Status" ) {
|
else if (bi.id == "Status" ) {
|
||||||
gdi.setInputStatus("MinTime", bi.data != oControl::StatusRogaining && bi.data != oControl::StatusNoTiming && bi.data != oControl::StatusBadNoTiming, true);
|
oControl::ControlStatus st = (oControl::ControlStatus)bi.data;
|
||||||
gdi.setInputStatus("Point", bi.data == oControl::StatusRogaining, true);
|
gdi.setInputStatus("MinTime", st != oControl::ControlStatus::StatusRogaining && st != oControl::ControlStatus::StatusRogainingRequired && st != oControl::ControlStatus::StatusNoTiming && st != oControl::ControlStatus::StatusBadNoTiming, true);
|
||||||
gdi.setInputStatus("TimeAdjust", bi.data != oControl::StatusNoTiming && bi.data != oControl::StatusBadNoTiming, true);
|
gdi.setInputStatus("Point", st == oControl::ControlStatus::StatusRogaining || st != oControl::ControlStatus::StatusRogainingRequired, true);
|
||||||
|
gdi.setInputStatus("TimeAdjust", st != oControl::ControlStatus::StatusNoTiming && st != oControl::ControlStatus::StatusBadNoTiming, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type==GUI_CLEAR) {
|
else if (type==GUI_CLEAR) {
|
||||||
@ -454,10 +561,10 @@ bool TabControl::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
gdi.pushY();
|
gdi.pushY();
|
||||||
gdi.addListBox("Controls", 250, 530, ControlsCB).isEdit(false).ignore(true);
|
gdi.addListBox("Controls", 250, 530, ControlsCB).isEdit(false).ignore(true);
|
||||||
gdi.setTabStops("Controls", 40, 160);
|
gdi.setTabStops("Controls", 44, 160);
|
||||||
|
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe->fillControls(d, oEvent::CTAll);
|
oe->fillControls(d, oEvent::ControlType::All);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
@ -515,7 +622,7 @@ bool TabControl::loadPage(gdioutput &gdi)
|
|||||||
gdi.dropLine(1.5);
|
gdi.dropLine(1.5);
|
||||||
gdi.addString("", 10, "help:89064");
|
gdi.addString("", 10, "help:89064");
|
||||||
|
|
||||||
selectControl(gdi, oe->getControl(controlId, false));
|
selectControl(gdi, oe->getControl(controlId, false, true));
|
||||||
|
|
||||||
gdi.setOnClearCb(ControlsCB);
|
gdi.setOnClearCb(ControlsCB);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -459,7 +459,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
|||||||
ext.push_back(make_pair(L"IOF CourseData, version 3.0 (xml)", L"*.xml"));
|
ext.push_back(make_pair(L"IOF CourseData, version 3.0 (xml)", L"*.xml"));
|
||||||
wstring save = gdi.browseForSave(ext, L"xml", FilterIndex);
|
wstring save = gdi.browseForSave(ext, L"xml", FilterIndex);
|
||||||
if (save.length()>0) {
|
if (save.length()>0) {
|
||||||
IOF30Interface iof30(oe, false);
|
IOF30Interface iof30(oe, false, false);
|
||||||
xmlparser xml;
|
xmlparser xml;
|
||||||
xml.openOutput(save.c_str(), false);
|
xml.openOutput(save.c_str(), false);
|
||||||
iof30.writeCourses(xml);
|
iof30.writeCourses(xml);
|
||||||
@ -477,15 +477,19 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.disableInput("Cancel");
|
gdi.disableInput("Cancel");
|
||||||
gdi.disableInput("BrowseCourse");
|
gdi.disableInput("BrowseCourse");
|
||||||
gdi.disableInput("AddClasses");
|
gdi.disableInput("AddClasses");
|
||||||
|
gdi.disableInput("CreateClasses");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TabCourse::runCourseImport(gdi, filename, oe, gdi.isChecked("AddClasses"));
|
TabCourse::runCourseImport(gdi, filename, oe,
|
||||||
|
gdi.isChecked("AddClasses"),
|
||||||
|
gdi.isChecked("CreateClasses"));
|
||||||
}
|
}
|
||||||
catch (std::exception &) {
|
catch (const std::exception &) {
|
||||||
gdi.enableInput("DoImportCourse");
|
gdi.enableInput("DoImportCourse");
|
||||||
gdi.enableInput("Cancel");
|
gdi.enableInput("Cancel");
|
||||||
gdi.enableInput("BrowseCourse");
|
gdi.enableInput("BrowseCourse");
|
||||||
gdi.enableInput("AddClasses");
|
gdi.enableInput("AddClasses");
|
||||||
|
gdi.enableInput("CreateClasses");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
gdi.addButton("Cancel", "OK", CourseCB);
|
gdi.addButton("Cancel", "OK", CourseCB);
|
||||||
@ -525,8 +529,8 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
int firstStart = 3600;
|
int firstStart = timeConstHour;
|
||||||
int interval = 2*60;
|
int interval = 2*timeConstMinute;
|
||||||
int vac = 1;
|
int vac = 1;
|
||||||
gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:");
|
gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:");
|
||||||
gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):");
|
gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):");
|
||||||
@ -891,14 +895,14 @@ bool TabCourse::loadPage(gdioutput &gdi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
||||||
oEvent *oe, bool addClasses) {
|
oEvent *oe, bool addToClasses, bool createClasses) {
|
||||||
if (csvparser::iscsv(filename) != csvparser::CSV::NoCSV) {
|
if (csvparser::iscsv(filename) != csvparser::CSV::NoCSV) {
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.addString("", 0, "Importerar OCAD csv-fil...");
|
gdi.addString("", 0, "Importerar OCAD csv-fil...");
|
||||||
gdi.refreshFast();
|
gdi.refreshFast();
|
||||||
csvparser csv;
|
csvparser csv;
|
||||||
if (csv.importOCAD_CSV(*oe, filename, addClasses)) {
|
if (csv.importOCAD_CSV(*oe, filename, addToClasses)) {
|
||||||
gdi.addString("", 1, "Klart.").setColor(colorGreen);
|
gdi.addString("", 1, "Klart.").setColor(colorGreen);
|
||||||
}
|
}
|
||||||
else gdi.addString("", 0, "Operationen misslyckades.").setColor(colorRed);
|
else gdi.addString("", 0, "Operationen misslyckades.").setColor(colorRed);
|
||||||
@ -906,12 +910,64 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
|||||||
gdi.dropLine(2.5);
|
gdi.dropLine(2.5);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
}
|
}
|
||||||
|
else if (filename.find(L".txt") != wstring::npos || filename.find(L".TXT") != wstring::npos) {
|
||||||
|
ifstream fin(filename);
|
||||||
|
|
||||||
|
if (!fin.good())
|
||||||
|
throw meosException(L"Cannot read " + filename);
|
||||||
|
|
||||||
|
char bf[2048];
|
||||||
|
vector<string> sw;
|
||||||
|
int importedC = oe->getNumCourses() + 1;
|
||||||
|
int line = 0;
|
||||||
|
while (fin.good()) {
|
||||||
|
fin.getline(bf, 2048);
|
||||||
|
if (strlen(bf) < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (0 == line && uint8_t(bf[0]) == 0xEF && uint8_t(bf[1]) == 0xBB && uint8_t(bf[2]) == 0xBF)
|
||||||
|
split(bf+3, " ;,", sw);
|
||||||
|
else
|
||||||
|
split(bf, " ;,", sw);
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (sw.size() <= 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wstring name;
|
||||||
|
int first = 0;
|
||||||
|
if (atoi(sw[0].c_str()) < 30 && trim(sw[0]).length() > 2) {
|
||||||
|
name = gdioutput::fromUTF8(trim(sw[0]));
|
||||||
|
first = 1;
|
||||||
|
}
|
||||||
|
if (name.empty())
|
||||||
|
name = lang.tl("Bana X#" + itos(importedC++));
|
||||||
|
|
||||||
|
string cs;
|
||||||
|
for (int i = first; i < sw.size(); i++) {
|
||||||
|
if (trim(sw[i]).empty())
|
||||||
|
continue;
|
||||||
|
int c = atoi(sw[i].c_str());
|
||||||
|
if (c >= 30 && c < 1000)
|
||||||
|
cs += itos(c) + " ";
|
||||||
|
else {
|
||||||
|
throw meosException("Kan inte tolka 'X' som en bana#" + string(bf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCourse pc = oe->addCourse(name);
|
||||||
|
pc->importControls(cs, true, false);
|
||||||
|
pc->synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
fin.close();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
set<int> noFilter;
|
set<int> noFilter;
|
||||||
string noType;
|
string noType;
|
||||||
oe->importXML_EntryData(gdi, filename.c_str(), addClasses, false, noFilter, noType);
|
oe->importXML_EntryData(gdi, filename.c_str(), addToClasses, false, noFilter, noType);
|
||||||
}
|
}
|
||||||
if (addClasses) {
|
if (addToClasses) {
|
||||||
// There is specific course-class matching inside the import of each format,
|
// There is specific course-class matching inside the import of each format,
|
||||||
// that uses additional information. Here we try to match based on a generic approach.
|
// that uses additional information. Here we try to match based on a generic approach.
|
||||||
vector<pClass> cls;
|
vector<pClass> cls;
|
||||||
@ -1012,6 +1068,34 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
|||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (createClasses) {
|
||||||
|
vector<pClass> cls;
|
||||||
|
vector<pCourse> crs;
|
||||||
|
oe->getClasses(cls, false);
|
||||||
|
oe->getCourses(crs);
|
||||||
|
unordered_set<int> usedCourseId;
|
||||||
|
vector<pCourse> usedCrs;
|
||||||
|
for (size_t k = 0; k < cls.size(); k++) {
|
||||||
|
cls[k]->getCourses(-1, usedCrs);
|
||||||
|
for (pCourse pc : usedCrs)
|
||||||
|
usedCourseId.insert(pc->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
set<wstring> usedNames;
|
||||||
|
for (pCourse pc : crs) {
|
||||||
|
if (usedCourseId.count(pc->getId()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pClass matchCls = oe->getClassCreate(-1, pc->getName(), usedNames);
|
||||||
|
if (!matchCls || matchCls->getCourse(false)) {
|
||||||
|
oe->addClass(pc->getName() + lang.tl(" Bana"), pc->getId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
matchCls->setCourse(pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(baseButtonWidth),
|
gdi.addButton(gdi.getWidth()+20, 45, gdi.scaleLength(baseButtonWidth),
|
||||||
"Print", "Skriv ut...", CourseCB,
|
"Print", "Skriv ut...", CourseCB,
|
||||||
"Skriv ut listan.", true, false);
|
"Skriv ut listan.", true, false);
|
||||||
@ -1043,6 +1127,7 @@ void TabCourse::setupCourseImport(gdioutput& gdi, GUICALLBACK cb) {
|
|||||||
|
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addCheckbox("AddClasses", "Lägg till klasser", 0, true);
|
gdi.addCheckbox("AddClasses", "Lägg till klasser", 0, true);
|
||||||
|
gdi.addCheckbox("CreateClasses", "Skapa en klass för varje bana", 0, false);
|
||||||
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
@ -1060,9 +1145,9 @@ void TabCourse::fillCourseControls(gdioutput &gdi, const wstring &ctrl) {
|
|||||||
vector< pair<wstring, size_t> > item;
|
vector< pair<wstring, size_t> > item;
|
||||||
map<int, int> used;
|
map<int, int> used;
|
||||||
for (size_t k = 0; k < nr.size(); k++) {
|
for (size_t k = 0; k < nr.size(); k++) {
|
||||||
pControl pc = oe->getControl(nr[k], false);
|
pControl pc = oe->getControl(nr[k], false, false);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
if (pc->getStatus() == oControl::StatusOK)
|
if (pc->getStatus() == oControl::ControlStatus::StatusOK)
|
||||||
++used[pc->getFirstNumber()];
|
++used[pc->getFirstNumber()];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1085,7 +1170,7 @@ void TabCourse::fillCourseControls(gdioutput &gdi, const wstring &ctrl) {
|
|||||||
|
|
||||||
void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops) {
|
void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops) {
|
||||||
vector< pair<wstring, size_t> > ac;
|
vector< pair<wstring, size_t> > ac;
|
||||||
oe->fillCourses(ac, true);
|
oe->getCourses(ac, L"", true);
|
||||||
set<int> skipped;
|
set<int> skipped;
|
||||||
skipped.insert(crs.getId());
|
skipped.insert(crs.getId());
|
||||||
pCourse longer = crs.getLongerVersion();
|
pCourse longer = crs.getLongerVersion();
|
||||||
@ -1223,7 +1308,7 @@ wstring TabCourse::encodeCourse(const wstring &in, bool rogaining, bool firstSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wstring &TabCourse::formatControl(int id, wstring &bf) const {
|
const wstring &TabCourse::formatControl(int id, wstring &bf) const {
|
||||||
pControl ctrl = oe->getControl(id, false);
|
pControl ctrl = oe->getControl(id, false, true);
|
||||||
if (ctrl) {
|
if (ctrl) {
|
||||||
bf = ctrl->getString();
|
bf = ctrl->getString();
|
||||||
return bf;
|
return bf;
|
||||||
@ -1231,3 +1316,4 @@ const wstring &TabCourse::formatControl(int id, wstring &bf) const {
|
|||||||
else
|
else
|
||||||
return itow(id);
|
return itow(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -70,7 +70,7 @@ public:
|
|||||||
~TabCourse(void);
|
~TabCourse(void);
|
||||||
|
|
||||||
static void runCourseImport(gdioutput& gdi, const wstring &filename,
|
static void runCourseImport(gdioutput& gdi, const wstring &filename,
|
||||||
oEvent *oe, bool addClasses);
|
oEvent *oe, bool addToClasses, bool createClasses);
|
||||||
|
|
||||||
static void setupCourseImport(gdioutput& gdi, GUICALLBACK cb);
|
static void setupCourseImport(gdioutput& gdi, GUICALLBACK cb);
|
||||||
|
|
||||||
|
|||||||
181
code/TabList.cpp
181
code/TabList.cpp
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -341,7 +341,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
else if (bi.id=="Copy") {
|
else if (bi.id=="Copy") {
|
||||||
ostringstream fout;
|
ostringstream fout;
|
||||||
HTMLWriter::writeTableHTML(gdi, fout, L"MeOS", true, 0, 1.0);
|
HTMLWriter::writeTableHTML(gdi, fout, L"MeOS", false, L"", true, 0, 1.0);
|
||||||
string res = fout.str();
|
string res = fout.str();
|
||||||
gdi.copyToClipboard(res, L"");
|
gdi.copyToClipboard(res, L"");
|
||||||
}
|
}
|
||||||
@ -570,32 +570,44 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
else if (bi.id=="CancelPS") {
|
else if (bi.id=="CancelPS") {
|
||||||
gdi.getTabs().get(TabType(bi.getExtraInt()))->loadPage(gdi);
|
gdi.getTabs().get(TabType(bi.getExtraInt()))->loadPage(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id=="SavePS") {
|
else if (bi.id == "SavePS") {
|
||||||
string ctype;
|
string ctype;
|
||||||
gdi.getData("Type", ctype);
|
gdi.getData("Type", ctype);
|
||||||
saveExtraLines(*oe, ctype.c_str(), gdi);
|
saveExtraLines(*oe, ctype.c_str(), gdi);
|
||||||
|
|
||||||
if (gdi.hasWidget("SplitAnalysis")) {
|
if (gdi.hasWidget("SplitAnalysis")) {
|
||||||
int aflag = (gdi.isChecked("SplitAnalysis") ? 0 : 1) + (gdi.isChecked("Speed") ? 0 : 2)
|
int aflag = (gdi.isChecked("SplitAnalysis") ? 0 : 1) + (gdi.isChecked("Speed") ? 0 : 2)
|
||||||
+ (gdi.isChecked("Results") ? 0 : 4);
|
+ (gdi.isChecked("Results") ? 0 : 4);
|
||||||
oe->getDI().setInt("Analysis", aflag);
|
oe->getDI().setInt("Analysis", aflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdi.hasWidget("SplitPrintList")) {
|
||||||
if (gdi.hasWidget("WideFormat")) {
|
auto res = gdi.getSelectedItem("SplitPrintList");
|
||||||
bool wide = gdi.isChecked("WideFormat");
|
if (res.second) {
|
||||||
oe->setProperty("WideSplitFormat", wide);
|
if (res.first == -10)
|
||||||
|
oe->getDI().setString("SplitPrint", L"");
|
||||||
if (wide && gdi.hasWidget("NumPerPage")) {
|
else {
|
||||||
pair<int, bool> res = gdi.getSelectedItem("NumPerPage");
|
EStdListType type = oe->getListContainer().getType(res.first);
|
||||||
if (res.second)
|
string id = oe->getListContainer().getUniqueId(type);
|
||||||
oe->setProperty("NumSplitsOnePage", res.first);
|
oe->getDI().setString("SplitPrint", gdioutput::widen(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gdi.hasWidget("WideFormat")) {
|
||||||
|
bool wide = gdi.isChecked("WideFormat");
|
||||||
|
oe->setProperty("WideSplitFormat", wide);
|
||||||
|
|
||||||
int no = gdi.getTextNo("MaxWaitTime");
|
if (wide && gdi.hasWidget("NumPerPage")) {
|
||||||
if (no >= 0)
|
pair<int, bool> res = gdi.getSelectedItem("NumPerPage");
|
||||||
oe->setProperty("SplitPrintMaxWait", no);
|
if (res.second)
|
||||||
}
|
oe->setProperty("NumSplitsOnePage", res.first);
|
||||||
}
|
|
||||||
|
int no = gdi.getTextNo("MaxWaitTime");
|
||||||
|
if (no >= 0)
|
||||||
|
oe->setProperty("SplitPrintMaxWait", no);
|
||||||
|
}
|
||||||
|
}
|
||||||
gdi.getTabs().get(TabType(bi.getExtraInt()))->loadPage(gdi);
|
gdi.getTabs().get(TabType(bi.getExtraInt()))->loadPage(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id == "PrinterSetup") {
|
else if (bi.id == "PrinterSetup") {
|
||||||
@ -1071,11 +1083,21 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
return listCB(gdi, GUI_BUTTON, &bi);
|
return listCB(gdi, GUI_BUTTON, &bi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gdi.clearPage(false);
|
gdi.clearPage(false);
|
||||||
gdi.addString("", boldLarge, "Tillgängliga listor");
|
gdi.addString("", boldLarge, "Tillgängliga listor");
|
||||||
int xx = gdi.getCX() + gdi.scaleLength(360);
|
|
||||||
int bx = gdi.getCX();
|
int bx = gdi.getCX();
|
||||||
|
int xx = bx + gdi.scaleLength(360);
|
||||||
|
TextInfo ti;
|
||||||
|
for (size_t k = 0; k < installedLists.size(); k++) {
|
||||||
|
ti.text = installedLists[k].first;
|
||||||
|
gdi.calcStringSize(ti);
|
||||||
|
xx = max(xx, bx + ti.realWidth + 10);
|
||||||
|
}
|
||||||
|
for (size_t k = 0; k < lists.size(); k++) {
|
||||||
|
ti.text = lists[k].first;
|
||||||
|
gdi.calcStringSize(ti);
|
||||||
|
xx = max(xx, bx + ti.realWidth + 10);
|
||||||
|
}
|
||||||
if (!installedLists.empty()) {
|
if (!installedLists.empty()) {
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addString("", 1, "Listor i tävlingen");
|
gdi.addString("", 1, "Listor i tävlingen");
|
||||||
@ -1141,8 +1163,13 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
xmlobject xlist = xml.getObject(0);
|
xmlobject xlist = xml.getObject(0);
|
||||||
oe->synchronize();
|
oe->synchronize();
|
||||||
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
|
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
|
||||||
oe->synchronize(true);
|
|
||||||
|
set<uint64_t> imgUsed;
|
||||||
|
oe->getListContainer().getUsedImages(imgUsed);
|
||||||
|
for (uint64_t id : imgUsed)
|
||||||
|
oe->saveImage(id);
|
||||||
|
|
||||||
|
oe->synchronize(true);
|
||||||
loadPage(gdi);
|
loadPage(gdi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1218,6 +1245,12 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
|||||||
|
|
||||||
oe->synchronize(false);
|
oe->synchronize(false);
|
||||||
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
|
oe->getListContainer().load(MetaListContainer::ExternalList, xlist, false);
|
||||||
|
|
||||||
|
set<uint64_t> imgUsed;
|
||||||
|
oe->getListContainer().getUsedImages(imgUsed);
|
||||||
|
for (uint64_t id : imgUsed)
|
||||||
|
oe->saveImage(id);
|
||||||
|
|
||||||
oe->synchronize(true);
|
oe->synchronize(true);
|
||||||
oe->loadGeneralResults(true, false);
|
oe->loadGeneralResults(true, false);
|
||||||
}
|
}
|
||||||
@ -1286,7 +1319,7 @@ pair<gdioutput *, TabList *> TabList::makeOwnWindow(gdioutput &gdi) {
|
|||||||
|
|
||||||
void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) {
|
void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) {
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe.fillControls(d, oEvent::CTCourseControl);
|
oe.fillControls(d, oEvent::ControlType::CourseControl);
|
||||||
|
|
||||||
if (from) {
|
if (from) {
|
||||||
gdi.enableInput("ResultSpecialFrom");
|
gdi.enableInput("ResultSpecialFrom");
|
||||||
@ -2216,7 +2249,7 @@ void TabList::settingsResultList(gdioutput &gdi)
|
|||||||
vector< pair<wstring, size_t> > lists;
|
vector< pair<wstring, size_t> > lists;
|
||||||
vector< pair<wstring, size_t> > dlists;
|
vector< pair<wstring, size_t> > dlists;
|
||||||
const MetaListContainer &lc = oe->getListContainer();
|
const MetaListContainer &lc = oe->getListContainer();
|
||||||
lc.getLists(dlists, false, true, !oe->hasTeam());
|
lc.getLists(dlists, false, true, !oe->hasTeam(), false);
|
||||||
set<int> usedListIx;
|
set<int> usedListIx;
|
||||||
map<string, int> tag2ListIx;
|
map<string, int> tag2ListIx;
|
||||||
for (size_t k = 0; k < dlists.size(); k++) {
|
for (size_t k = 0; k < dlists.size(); k++) {
|
||||||
@ -2725,31 +2758,72 @@ void TabList::splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter,
|
|||||||
gdi.addString("", boldLarge, "Inställningar startbevis");
|
gdi.addString("", boldLarge, "Inställningar startbevis");
|
||||||
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|
||||||
gdi.fillRight();
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
if (setupPrinter) {
|
|
||||||
gdi.addButton("PrinterSetup", "Skrivare...", ListsCB, "Skrivarinställningar");
|
|
||||||
gdi.dropLine(0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!oe.empty() && type == Splits) {
|
if (!oe.empty() && type == Splits) {
|
||||||
bool withSplitAnalysis = (oe.getDCI().getInt("Analysis") & 1) == 0;
|
gdi.fillRight();
|
||||||
|
gdi.addSelection("SplitPrintList", 200, 200, nullptr, L"Sträcktidslista:");
|
||||||
|
if (setupPrinter) {
|
||||||
|
gdi.dropLine(0.9);
|
||||||
|
gdi.addButton("PrinterSetup", "Skrivare...", ListsCB, "Skrivarinställningar");
|
||||||
|
gdi.dropLine(2.8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gdi.dropLine(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.popX();
|
||||||
|
gdi.addString("", 10, "info:customsplitprint");
|
||||||
|
gdi.dropLine();
|
||||||
|
vector<pair<wstring, size_t>> lists;
|
||||||
|
oe.getListContainer().getLists(lists, false, false, false, true);
|
||||||
|
lists.insert(lists.begin(), make_pair(lang.tl("Standard"), -10));
|
||||||
|
gdi.addItem("SplitPrintList", lists);
|
||||||
|
wstring listId = oe.getDCI().getString("SplitPrint");
|
||||||
|
EStdListType type = oe.getListContainer().getCodeFromUnqiueId(gdioutput::narrow(listId));
|
||||||
|
if (type == EStdListType::EStdNone)
|
||||||
|
gdi.selectFirstItem("SplitPrintList");
|
||||||
|
else {
|
||||||
|
for (auto& t : lists) {
|
||||||
|
if (type == oe.getListContainer().getType(t.second))
|
||||||
|
gdi.selectItemByData("SplitPrintList", t.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if ()
|
||||||
|
/* bool withSplitAnalysis = (oe.getDCI().getInt("Analysis") & 1) == 0;
|
||||||
bool withSpeed = (oe.getDCI().getInt("Analysis") & 2) == 0;
|
bool withSpeed = (oe.getDCI().getInt("Analysis") & 2) == 0;
|
||||||
bool withResult = (oe.getDCI().getInt("Analysis") & 4) == 0;
|
bool withResult = (oe.getDCI().getInt("Analysis") & 4) == 0;
|
||||||
|
|
||||||
gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, withSplitAnalysis);
|
gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, withSplitAnalysis);
|
||||||
gdi.addCheckbox("Speed", "Med km-tid", 0, withSpeed);
|
gdi.addCheckbox("Speed", "Med km-tid", 0, withSpeed);
|
||||||
gdi.addCheckbox("Results", "Med resultat", 0, withResult);
|
gdi.addCheckbox("Results", "Med resultat", 0, withResult);*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (setupPrinter) {
|
||||||
|
gdi.dropLine(0.2);
|
||||||
|
gdi.addButton("PrinterSetup", "Skrivare...", ListsCB, "Skrivarinställningar");
|
||||||
|
}
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.fillDown();
|
|
||||||
|
RECT rc;
|
||||||
|
rc.top = gdi.getCY();
|
||||||
|
rc.left = gdi.getCX();
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(8));
|
||||||
|
gdi.dropLine();
|
||||||
|
|
||||||
const char *ctype = type == Splits ? "SPExtra" : "EntryExtra";
|
const char *ctype = type == Splits ? "SPExtra" : "EntryExtra";
|
||||||
customTextLines(oe, ctype, gdi);
|
customTextLines(oe, ctype, !oe.empty(), gdi);
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
|
||||||
|
rc.right = gdi.getWidth();
|
||||||
|
rc.bottom = gdi.getCY();
|
||||||
|
|
||||||
|
gdi.addRectangle(rc, colorLightCyan);
|
||||||
|
|
||||||
if (type == Splits) {
|
if (type == Splits) {
|
||||||
|
gdi.dropLine(1.5);
|
||||||
const bool wideFormat = oe.getPropertyInt("WideSplitFormat", 0) == 1;
|
const bool wideFormat = oe.getPropertyInt("WideSplitFormat", 0) == 1;
|
||||||
gdi.addCheckbox("WideFormat", "Sträcktider i kolumner (för standardpapper)", ListsCB, wideFormat);
|
gdi.addCheckbox("WideFormat", "Sträcktider i kolumner (för standardpapper)", ListsCB, wideFormat);
|
||||||
|
|
||||||
@ -2769,7 +2843,7 @@ void TabList::splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.setData("Type", ctype);
|
gdi.setData("Type", ctype);
|
||||||
gdi.addButton("SavePS", "OK", ListsCB).setDefault().setExtra(returnMode);
|
gdi.addButton("SavePS", "OK", ListsCB).setDefault().setExtra(returnMode);
|
||||||
@ -2791,11 +2865,12 @@ void TabList::saveExtraLines(oEvent &oe, const char *dataField, gdioutput &gdi)
|
|||||||
oe.setExtraLines(dataField, lines);
|
oe.setExtraLines(dataField, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabList::customTextLines(oEvent &oe, const char *dataField, gdioutput &gdi) {
|
void TabList::customTextLines(oEvent &oe, const char *dataField, bool withSymbols, gdioutput &gdi) {
|
||||||
gdi.dropLine(2.5);
|
|
||||||
gdi.addString("", fontMediumPlus, "Egna textrader");
|
gdi.addString("", fontMediumPlus, "Egna textrader");
|
||||||
gdi.dropLine(0.3);
|
if (withSymbols) {
|
||||||
gdi.addString("", 10, "help:custom_text_lines");
|
gdi.dropLine(0.3);
|
||||||
|
gdi.addString("", 10, "help:custom_text_lines");
|
||||||
|
}
|
||||||
gdi.dropLine(0.8);
|
gdi.dropLine(0.8);
|
||||||
int yp = gdi.getCY();
|
int yp = gdi.getCY();
|
||||||
|
|
||||||
@ -2825,18 +2900,20 @@ void TabList::customTextLines(oEvent &oe, const char *dataField, gdioutput &gdi)
|
|||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
}
|
}
|
||||||
gdi.pushX();
|
if (withSymbols) {
|
||||||
gdi.pushY();
|
gdi.pushX();
|
||||||
|
gdi.pushY();
|
||||||
|
|
||||||
gdi.setCX(xp);
|
gdi.setCX(xp);
|
||||||
gdi.setCY(yp);
|
gdi.setCY(yp);
|
||||||
gdi.addListBox("Symbols", 500, 160);
|
gdi.addListBox("Symbols", 500, 160);
|
||||||
gdi.setTabStops("Symbols", 300);
|
gdi.setTabStops("Symbols", 300);
|
||||||
vector < pair<wstring, size_t>> symb;
|
vector < pair<wstring, size_t>> symb;
|
||||||
MetaList::fillSymbols(symb);
|
MetaList::fillSymbols(symb);
|
||||||
gdi.addItem("Symbols", symb);
|
gdi.addItem("Symbols", symb);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.popY();
|
gdi.popY();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabList::liveResult(gdioutput &gdi, oListInfo &li) {
|
void TabList::liveResult(gdioutput &gdi, oListInfo &li) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -147,7 +147,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter, TabType returnMode, PrintSettingsSelection type);
|
static void splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter, TabType returnMode, PrintSettingsSelection type);
|
||||||
static void customTextLines(oEvent &oe, const char *dataField, gdioutput &gdi);
|
static void customTextLines(oEvent &oe, const char *dataField, bool withSymbols, gdioutput &gdi);
|
||||||
static void saveExtraLines(oEvent &oe, const char *dataField, gdioutput &gdi);
|
static void saveExtraLines(oEvent &oe, const char *dataField, gdioutput &gdi);
|
||||||
static void enableWideFormat(gdioutput &gdi, bool wide);
|
static void enableWideFormat(gdioutput &gdi, bool wide);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -28,6 +28,9 @@
|
|||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
|
|
||||||
#include "oEvent.h"
|
#include "oEvent.h"
|
||||||
|
#include "metalist.h"
|
||||||
|
#include "generalresult.h"
|
||||||
|
|
||||||
#include "xmlparser.h"
|
#include "xmlparser.h"
|
||||||
#include "gdioutput.h"
|
#include "gdioutput.h"
|
||||||
#include "gdiconstants.h"
|
#include "gdiconstants.h"
|
||||||
@ -197,7 +200,7 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
|||||||
gdi.setText("Team", L"");
|
gdi.setText("Team", L"");
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.setText("TimeAdjust", getTimeMS(r->getTimeAdjustment()));
|
gdi.setText("TimeAdjust", formatTimeMS(r->getTimeAdjustment(false), false));
|
||||||
gdi.setText("PointAdjust", -r->getPointAdjustment());
|
gdi.setText("PointAdjust", -r->getPointAdjustment());
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@ -221,13 +224,13 @@ void TabRunner::selectRunner(gdioutput &gdi, pRunner r) {
|
|||||||
out += L" (" + itow(placeAcc[k]) + L")";
|
out += L" (" + itow(placeAcc[k]) + L")";
|
||||||
|
|
||||||
if (after[k] > 0)
|
if (after[k] > 0)
|
||||||
out += L" +" + getTimeMS(after[k]);
|
out += L" +" + formatTimeMS(after[k], false);
|
||||||
|
|
||||||
if (k < afterAcc.size() && afterAcc[k]>0)
|
if (k < afterAcc.size() && afterAcc[k]>0)
|
||||||
out += L" (+" + getTimeMS(afterAcc[k]) + L")";
|
out += L" (+" + formatTimeMS(afterAcc[k], false) + L")";
|
||||||
|
|
||||||
if (delta[k] > 0)
|
if (delta[k] > 0)
|
||||||
out += L" B: " + getTimeMS(delta[k]);
|
out += L" B: " + formatTimeMS(delta[k], false);
|
||||||
|
|
||||||
out += L" | ";
|
out += L" | ";
|
||||||
|
|
||||||
@ -528,7 +531,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
|||||||
else
|
else
|
||||||
classId = lbi.data;
|
classId = lbi.data;
|
||||||
|
|
||||||
int year = 0;
|
const wstring year;
|
||||||
pRunner r;
|
pRunner r;
|
||||||
bool cardNoChanged = false;
|
bool cardNoChanged = false;
|
||||||
if (runnerId==0) {
|
if (runnerId==0) {
|
||||||
@ -926,11 +929,12 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
if (!r) return 0;
|
if (!r) return 0;
|
||||||
|
|
||||||
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
|
gdioutput gdiprint(2.0, gdi.getHWNDTarget(), splitPrinter);
|
||||||
if (bi.getExtraInt() == 0)
|
if (bi.getExtraInt() == 0)
|
||||||
r->printSplits(gdiprint);
|
r->printSplits(gdiprint);
|
||||||
else
|
else
|
||||||
r->printStartInfo(gdiprint);
|
r->printStartInfo(gdiprint);
|
||||||
gdiprint.print(oe, 0, false, true);
|
|
||||||
|
gdiprint.print(oe, nullptr, false, true);
|
||||||
gdiprint.fetchPrinterSettings(splitPrinter);
|
gdiprint.fetchPrinterSettings(splitPrinter);
|
||||||
}
|
}
|
||||||
else if (bi.id == "PrintSettings") {
|
else if (bi.id == "PrintSettings") {
|
||||||
@ -961,7 +965,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
pRunner r = oe->getRunner(runnerId, 0);
|
pRunner r = oe->getRunner(runnerId, 0);
|
||||||
if (!name.empty() && r && r->getName() != name && r->getNameRaw() != name) {
|
if (!name.empty() && r && r->getName() != name && r->getNameRaw() != name) {
|
||||||
if (gdi.ask(L"Vill du lägga till deltagaren 'X'?#" + name)) {
|
if (gdi.ask(L"Vill du lägga till deltagaren 'X'?#" + name)) {
|
||||||
r = oe->addRunner(name, 0, 0, 0,0, false);
|
r = oe->addRunner(name, 0, 0, 0, L"", false);
|
||||||
runnerId = r->getId();
|
runnerId = r->getId();
|
||||||
}
|
}
|
||||||
save(gdi, runnerId, false);
|
save(gdi, runnerId, false);
|
||||||
@ -973,7 +977,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
gdi.getSelectedItem("RClass", lbi);
|
gdi.getSelectedItem("RClass", lbi);
|
||||||
|
|
||||||
pRunner r = oe->addRunner(oe->getAutoRunnerName(), 0,0,0,0, false);
|
pRunner r = oe->addRunner(oe->getAutoRunnerName(), 0, 0, 0, L"", false);
|
||||||
int clsId = lbi.data;
|
int clsId = lbi.data;
|
||||||
if (clsId > 0) {
|
if (clsId > 0) {
|
||||||
pClass tCls = oe->getClass(clsId);
|
pClass tCls = oe->getClass(clsId);
|
||||||
@ -1095,7 +1099,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
r->synchronize();
|
r->synchronize();
|
||||||
card->fillPunches(gdi, "Punches", r->getCourse(true));
|
card->fillPunches(gdi, "Punches", r->getCourse(true));
|
||||||
|
|
||||||
gdi.setText("Time", r->getRunningTimeS(true));
|
gdi.setText("Time", r->getRunningTimeS(true, SubSecond::Auto));
|
||||||
gdi.selectItemByData("Status", r->getStatus());
|
gdi.selectItemByData("Status", r->getStatus());
|
||||||
}
|
}
|
||||||
else if (bi.id=="Check") {
|
else if (bi.id=="Check") {
|
||||||
@ -1123,8 +1127,46 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
gdi.clearAutoComplete(ii.id);
|
gdi.clearAutoComplete(ii.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ii.id == "CardNo") {
|
||||||
|
bool show = false;
|
||||||
|
if (ii.text.length() > 0) {
|
||||||
|
vector<AutoCompleteRecord> records;
|
||||||
|
getAutoCompleteUnpairedCards(gdi, ii.text, records);
|
||||||
|
if (!records.empty()) {
|
||||||
|
auto& ac = gdi.addAutoComplete(ii.id);
|
||||||
|
ac.setAutoCompleteHandler(this);
|
||||||
|
ac.setData(records);
|
||||||
|
ac.show();
|
||||||
|
show = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!show) {
|
||||||
|
gdi.clearAutoComplete(ii.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type==GUI_INPUT) {
|
else if (type == GUI_FOCUS) {
|
||||||
|
InputInfo ii = *(InputInfo*)data;
|
||||||
|
if (ii.id == "CardNo") {
|
||||||
|
pRunner r = runnerId > 0 ? oe->getRunner(runnerId, 0) : nullptr;
|
||||||
|
if (r && r->getCard() == nullptr) {
|
||||||
|
bool show = false;
|
||||||
|
vector<AutoCompleteRecord> records;
|
||||||
|
getAutoCompleteUnpairedCards(gdi, L"", records);
|
||||||
|
if (!records.empty()) {
|
||||||
|
auto& ac = gdi.addAutoComplete(ii.id);
|
||||||
|
ac.setAutoCompleteHandler(this);
|
||||||
|
ac.setData(records);
|
||||||
|
ac.show();
|
||||||
|
show = true;
|
||||||
|
}
|
||||||
|
if (!show) {
|
||||||
|
gdi.clearAutoComplete(ii.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == GUI_INPUT) {
|
||||||
InputInfo ii=*(InputInfo *)data;
|
InputInfo ii=*(InputInfo *)data;
|
||||||
|
|
||||||
if (ii.id=="CardNo") {
|
if (ii.id=="CardNo") {
|
||||||
@ -1311,7 +1353,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
|||||||
ac.setAutoCompleteHandler(this);
|
ac.setAutoCompleteHandler(this);
|
||||||
vector<AutoCompleteRecord> items;
|
vector<AutoCompleteRecord> items;
|
||||||
for (auto club : clubs)
|
for (auto club : clubs)
|
||||||
items.emplace_back(club->getDisplayName(), club->getName(), club->getId());
|
items.emplace_back(club->getDisplayName(), -int(items.size()), club->getName(), club->getId());
|
||||||
|
|
||||||
ac.setData(items);
|
ac.setData(items);
|
||||||
ac.show();
|
ac.show();
|
||||||
@ -1650,12 +1692,12 @@ void TabRunner::showRunnerReport(gdioutput &gdi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wstring tInfo = t->getName();
|
wstring tInfo = t->getName();
|
||||||
if (t->statusOK(true)) {
|
if (t->statusOK(true, true)) {
|
||||||
tInfo += L", " + t->getRunningTimeS(true) + lang.tl(", Placering: ") + t->getPlaceS();
|
tInfo += L", " + t->getRunningTimeS(true, SubSecond::Auto) + lang.tl(", Placering: ") + t->getPlaceS();
|
||||||
if (t->getTimeAfter(-1) > 0)
|
if (t->getTimeAfter(-1, true) > 0)
|
||||||
tInfo += L", +" + formatTime(t->getTimeAfter(-1));
|
tInfo += L", +" + formatTime(t->getTimeAfter(-1, true));
|
||||||
}
|
}
|
||||||
else if (t->getStatusComputed() != StatusUnknown) {
|
else if (t->getStatusComputed(true) != StatusUnknown) {
|
||||||
tInfo += L" " + t->getStatusS(true, true);
|
tInfo += L" " + t->getStatusS(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1719,7 +1761,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
|
|
||||||
gdi.dropLine(0.3);
|
gdi.dropLine(0.3);
|
||||||
|
|
||||||
if (r->statusOK(true)) {
|
if (r->statusOK(true, true)) {
|
||||||
int total, finished, dns;
|
int total, finished, dns;
|
||||||
r->getClassRef(true)->getNumResults(r->getLegNumber(), total, finished, dns);
|
r->getClassRef(true)->getNumResults(r->getLegNumber(), total, finished, dns);
|
||||||
|
|
||||||
@ -1736,7 +1778,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (r->getStatusComputed() != StatusUnknown) {
|
else if (r->getStatusComputed(true) != StatusUnknown) {
|
||||||
gdi.addStringUT(fontMediumPlus, str).setColor(colorRed);
|
gdi.addStringUT(fontMediumPlus, str).setColor(colorRed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1747,7 +1789,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
gdi.addString("", fontMedium, L"Starttid: X #" + r->getStartTimeCompact());
|
gdi.addString("", fontMedium, L"Starttid: X #" + r->getStartTimeCompact());
|
||||||
|
|
||||||
if (r->getFinishTime() > 0)
|
if (r->getFinishTime() > 0)
|
||||||
gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS());
|
gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS(false, SubSecond::Auto));
|
||||||
|
|
||||||
const wstring &after = oe.formatListString(lRunnerTimeAfter, r);
|
const wstring &after = oe.formatListString(lRunnerTimeAfter, r);
|
||||||
if (!after.empty()) {
|
if (!after.empty()) {
|
||||||
@ -1811,7 +1853,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
GDICOLOR color = colorDefault;
|
GDICOLOR color = colorDefault;
|
||||||
if (k < int(after.size()) ) {
|
if (k < int(after.size()) ) {
|
||||||
if (after[k] > 0)
|
if (after[k] > 0)
|
||||||
split += L" (" + itow(place[k]) + L", +" + getTimeMS(after[k]) + L")";
|
split += L" (" + itow(place[k]) + L", +" + formatTimeMS(after[k], false) + L")";
|
||||||
else if (place[k] == 1)
|
else if (place[k] == 1)
|
||||||
split += lang.tl(" (sträckseger)");
|
split += lang.tl(" (sträckseger)");
|
||||||
else if (place[k] > 0)
|
else if (place[k] > 0)
|
||||||
@ -1823,11 +1865,11 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
gdi.addStringUT(yp + lh, cx, fontMedium, split, limit);
|
gdi.addStringUT(yp + lh, cx, fontMedium, split, limit);
|
||||||
|
|
||||||
if (k>0 && k < int(placeAcc.size())) {
|
if (k>0 && k < int(placeAcc.size())) {
|
||||||
split = r->getPunchTimeS(k, false);
|
split = r->getPunchTimeS(k, false, false, SubSecond::Auto);
|
||||||
wstring pl = placeAcc[k] > 0 ? itow(placeAcc[k]) : L"-";
|
wstring pl = placeAcc[k] > 0 ? itow(placeAcc[k]) : L"-";
|
||||||
if (k < int(afterAcc.size()) ) {
|
if (k < int(afterAcc.size()) ) {
|
||||||
if (afterAcc[k] > 0)
|
if (afterAcc[k] > 0)
|
||||||
split += L" (" + pl + L", +" + getTimeMS(afterAcc[k]) + L")";
|
split += L" (" + pl + L", +" + formatTimeMS(afterAcc[k], false) + L")";
|
||||||
else if (placeAcc[k] == 1)
|
else if (placeAcc[k] == 1)
|
||||||
split += lang.tl(" (ledare)");
|
split += lang.tl(" (ledare)");
|
||||||
else if (placeAcc[k] > 0)
|
else if (placeAcc[k] > 0)
|
||||||
@ -1837,7 +1879,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k < int(delta.size()) && delta[k] > 0 ) {
|
if (k < int(delta.size()) && delta[k] > 0 ) {
|
||||||
gdi.addString("", yp + 3*lh, cx, fontMedium, L"Bomtid: X#" + getTimeMS(delta[k]));
|
gdi.addString("", yp + 3*lh, cx, fontMedium, L"Bomtid: X#" + formatTimeMS(delta[k], false, SubSecond::Off));
|
||||||
|
|
||||||
color = (delta[k] > bestTime * 0.5 && delta[k]>60 ) ?
|
color = (delta[k] > bestTime * 0.5 && delta[k]>60 ) ?
|
||||||
colorMediumDarkRed : colorMediumRed;
|
colorMediumDarkRed : colorMediumRed;
|
||||||
@ -1897,7 +1939,7 @@ void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
|||||||
if (st > 0 && t > st) {
|
if (st > 0 && t > st) {
|
||||||
wstring split = formatTimeHMS(t-st);
|
wstring split = formatTimeHMS(t-st);
|
||||||
if (lastT>0 && st != lastT && lastT < t)
|
if (lastT>0 && st != lastT && lastT < t)
|
||||||
split += L" (" + getTimeMS(t-lastT) + L")";
|
split += L" (" + formatTimeMS(t-lastT, false) + L")";
|
||||||
gdi.addStringUT(yp + 2*lh, cx, normalText, split, limit);
|
gdi.addStringUT(yp + 2*lh, cx, normalText, split, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2267,8 +2309,8 @@ void TabRunner::updateStatus(gdioutput &gdi, pRunner r) {
|
|||||||
if (!r) return;
|
if (!r) return;
|
||||||
|
|
||||||
gdi.setText("Start", r->getStartTimeS());
|
gdi.setText("Start", r->getStartTimeS());
|
||||||
gdi.setText("Finish", r->getFinishTimeS());
|
gdi.setText("Finish", r->getFinishTimeS(false, SubSecond::Auto));
|
||||||
gdi.setText("Time", r->getRunningTimeS(false));
|
gdi.setText("Time", r->getRunningTimeS(false, SubSecond::Auto));
|
||||||
gdi.setText("Points", itow(r->getRogainingPoints(false, false)));
|
gdi.setText("Points", itow(r->getRogainingPoints(false, false)));
|
||||||
|
|
||||||
gdi.selectItemByData("Status", r->getStatus());
|
gdi.selectItemByData("Status", r->getStatus());
|
||||||
@ -2321,7 +2363,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
|
|||||||
|
|
||||||
wstring ptime;
|
wstring ptime;
|
||||||
if (punch->getTimeInt() > 0)
|
if (punch->getTimeInt() > 0)
|
||||||
ptime = punch->getTime();
|
ptime = punch->getTime(false, SubSecond::Auto);
|
||||||
|
|
||||||
gdi.setText("PTime", ptime);
|
gdi.setText("PTime", ptime);
|
||||||
|
|
||||||
@ -2386,7 +2428,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
|
|||||||
if (!oc) return 0;
|
if (!oc) return 0;
|
||||||
vector<int> nmp;
|
vector<int> nmp;
|
||||||
|
|
||||||
if (oc->getStatus() == oControl::StatusRogaining) {
|
if (oc->getStatus() == oControl::ControlStatus::StatusRogaining || oc->getStatus() == oControl::ControlStatus::StatusRogainingRequired) {
|
||||||
r->evaluateCard(true, nmp, oc->getFirstNumber(), oBase::ChangeType::Update); //Add this punch
|
r->evaluateCard(true, nmp, oc->getFirstNumber(), oBase::ChangeType::Update); //Add this punch
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2524,6 +2566,9 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
|||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.dropLine(0.5);
|
gdi.dropLine(0.5);
|
||||||
|
|
||||||
|
const int hy = gdi.getCY();
|
||||||
|
|
||||||
gdi.addString("", boldLarge, "Deltagare");
|
gdi.addString("", boldLarge, "Deltagare");
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.registerEvent("SearchRunner", runnerSearchCB).setKeyCommand(KC_FIND);
|
gdi.registerEvent("SearchRunner", runnerSearchCB).setKeyCommand(KC_FIND);
|
||||||
@ -2552,7 +2597,7 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
|||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
|
||||||
gdi.dropLine(1);
|
gdi.setCY(hy);
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
gdi.addInput("Name", L"", 16, RunnerCB, L"Namn:");
|
gdi.addInput("Name", L"", 16, RunnerCB, L"Namn:");
|
||||||
@ -2736,11 +2781,11 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
|||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
|
gdi.setCY(hy);
|
||||||
int hx = gdi.getCX();
|
int hx = gdi.getCX();
|
||||||
int hy = gdi.getCY();
|
|
||||||
gdi.setCX(hx + gdi.scaleLength(5));
|
gdi.setCX(hx + gdi.scaleLength(5));
|
||||||
|
|
||||||
gdi.dropLine(2.5);
|
gdi.dropLine(2.0);
|
||||||
gdi.addListBox("Punches", 150, 300, PunchesCB, L"Stämplingar:").ignore(true);
|
gdi.addListBox("Punches", 150, 300, PunchesCB, L"Stämplingar:").ignore(true);
|
||||||
gdi.addButton("RemoveC", "Ta bort stämpling >>", RunnerCB);
|
gdi.addButton("RemoveC", "Ta bort stämpling >>", RunnerCB);
|
||||||
|
|
||||||
@ -2755,7 +2800,8 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
|||||||
int contY = gdi.getCY();
|
int contY = gdi.getCY();
|
||||||
|
|
||||||
gdi.newColumn();
|
gdi.newColumn();
|
||||||
gdi.dropLine(2.5);
|
gdi.setCY(hy);
|
||||||
|
gdi.dropLine(2.0);
|
||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
gdi.addListBox("Course", 140, 300, PunchesCB, L"Banmall:").ignore(true);
|
gdi.addListBox("Course", 140, 300, PunchesCB, L"Banmall:").ignore(true);
|
||||||
gdi.addButton("AddC", "<< Lägg till stämpling", PunchesCB);
|
gdi.addButton("AddC", "<< Lägg till stämpling", PunchesCB);
|
||||||
@ -3136,7 +3182,7 @@ void TabRunner::loadEconomy(gdioutput &gdi, oRunner &r) {
|
|||||||
|
|
||||||
void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
|
void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
|
||||||
auto bi = gdi.setText(info.getTarget(), info.getCurrent().c_str());
|
auto bi = gdi.setText(info.getTarget(), info.getCurrent().c_str());
|
||||||
if (bi) {
|
if (bi->id == "Name") {
|
||||||
int ix = info.getCurrentInt();
|
int ix = info.getCurrentInt();
|
||||||
bi->setExtra(ix);
|
bi->setExtra(ix);
|
||||||
if (info.getTarget() == "Name") {
|
if (info.getTarget() == "Name") {
|
||||||
@ -3153,6 +3199,10 @@ void TabRunner::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (bi->id == "CardNo") {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
gdi.clearAutoComplete("");
|
gdi.clearAutoComplete("");
|
||||||
gdi.TabFocus(1);
|
gdi.TabFocus(1);
|
||||||
}
|
}
|
||||||
@ -3173,3 +3223,81 @@ pClub TabRunner::extractClub(oEvent *oe, gdioutput &gdi) {
|
|||||||
}
|
}
|
||||||
return dbClub;
|
return dbClub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabRunner::getAutoCompleteUnpairedCards(gdioutput & gdi,
|
||||||
|
const wstring& w,
|
||||||
|
vector<AutoCompleteRecord>& records) {
|
||||||
|
|
||||||
|
pCourse matchCourse = nullptr;
|
||||||
|
ListBoxInfo lbi;
|
||||||
|
auto cls = gdi.getSelectedItem("RClass");
|
||||||
|
if (runnerId) {
|
||||||
|
pRunner r = oe->getRunner(runnerId, 0);
|
||||||
|
if (r && r->getClassId(true) == cls.first)
|
||||||
|
matchCourse = r->getCourse(false);
|
||||||
|
}
|
||||||
|
if (!matchCourse && cls.first) {
|
||||||
|
pClass cPtr = oe->getClass(cls.first);
|
||||||
|
|
||||||
|
matchCourse = cPtr ? cPtr->getCourse(true) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
records.clear();
|
||||||
|
int nr = _wtoi(w.c_str());
|
||||||
|
char sIn[32];
|
||||||
|
char sComp[32];
|
||||||
|
|
||||||
|
vector<pCard> cards;
|
||||||
|
oe->getCards(cards, false, true);
|
||||||
|
if (w.empty())
|
||||||
|
sIn[0] = 0;
|
||||||
|
else
|
||||||
|
sprintf_s(sIn, "%d", nr);
|
||||||
|
|
||||||
|
vector<pair<int, pCard>> matchedCards;
|
||||||
|
|
||||||
|
for (pCard c : cards) {
|
||||||
|
sprintf_s(sComp, "%d", c->getCardNo());
|
||||||
|
bool match = true;
|
||||||
|
int i = 0;
|
||||||
|
while (sIn[i]) {
|
||||||
|
if (sComp[i] != sIn[i]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
int score = 0;
|
||||||
|
if (matchCourse) {
|
||||||
|
int d = matchCourse->distance(*c);
|
||||||
|
if (d < 0)
|
||||||
|
d = min(10 - d, 20);
|
||||||
|
else
|
||||||
|
d = max(d, 10);
|
||||||
|
|
||||||
|
int age = c->getAge();
|
||||||
|
if (age > 10000)
|
||||||
|
age = 10000;
|
||||||
|
if (age < 0)
|
||||||
|
age = 0;
|
||||||
|
|
||||||
|
score = d * 10000 + age;
|
||||||
|
|
||||||
|
matchedCards.emplace_back(score, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(matchedCards.begin(), matchedCards.end());
|
||||||
|
|
||||||
|
wstring star;
|
||||||
|
for (auto &mc : matchedCards) {
|
||||||
|
wstring m = mc.second->getModified().getUpdateTime();
|
||||||
|
const wstring& cno = mc.second->getCardNoString();
|
||||||
|
star = mc.first < 3 * 10000 ? L"*" : L""; // Star if contents matches course
|
||||||
|
records.emplace_back(cno + star + L", "
|
||||||
|
+ lang.tl("X stämplingar#" + itos(mc.second->getNumControlPunches(-1, -1)))
|
||||||
|
+ L" (" + m + L")", -int(records.size()), cno, mc.second->getCardNo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include "autocompletehandler.h"
|
#include "autocompletehandler.h"
|
||||||
|
|
||||||
class Table;
|
class Table;
|
||||||
|
struct AutoCompleteRecord;
|
||||||
|
|
||||||
class TabRunner :
|
class TabRunner :
|
||||||
public TabBase, AutoCompleteHandler
|
public TabBase, AutoCompleteHandler
|
||||||
@ -107,6 +108,8 @@ private:
|
|||||||
shared_ptr<EconomyHandler> ecoHandler;
|
shared_ptr<EconomyHandler> ecoHandler;
|
||||||
EconomyHandler *getEconomyHandler(oRunner &r);
|
EconomyHandler *getEconomyHandler(oRunner &r);
|
||||||
|
|
||||||
|
void getAutoCompleteUnpairedCards(gdioutput &gdi, const wstring& w, vector<AutoCompleteRecord>& records);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void clearCompetitionData();
|
void clearCompetitionData();
|
||||||
public:
|
public:
|
||||||
|
|||||||
1696
code/TabSI.cpp
1696
code/TabSI.cpp
File diff suppressed because it is too large
Load Diff
66
code/TabSI.h
66
code/TabSI.h
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -30,9 +30,9 @@ struct PunchInfo;
|
|||||||
class csvparser;
|
class csvparser;
|
||||||
struct AutoCompleteRecord;
|
struct AutoCompleteRecord;
|
||||||
|
|
||||||
class TabSI : public TabBase, AutoCompleteHandler {
|
class TabSI final : public TabBase, AutoCompleteHandler {
|
||||||
public:
|
public:
|
||||||
enum SIMode {
|
enum class SIMode {
|
||||||
ModeReadOut,
|
ModeReadOut,
|
||||||
ModeAssignCards,
|
ModeAssignCards,
|
||||||
ModeCheckCards,
|
ModeCheckCards,
|
||||||
@ -40,9 +40,15 @@ public:
|
|||||||
ModeCardData,
|
ModeCardData,
|
||||||
ModeRegisterCards,
|
ModeRegisterCards,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
map<SIMode, string> modeName;
|
||||||
|
|
||||||
void setMode(SIMode m) { mode = m; }
|
void setMode(SIMode m) { mode = m; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Try to automatcally assign a class to runner (if none is given)
|
/** Try to automatcally assign a class to runner (if none is given)
|
||||||
Return true if runner has a class on exist */
|
Return true if runner has a class on exist */
|
||||||
bool autoAssignClass(pRunner r, const SICard &sic);
|
bool autoAssignClass(pRunner r, const SICard &sic);
|
||||||
@ -57,13 +63,13 @@ private:
|
|||||||
bool silent=false);
|
bool silent=false);
|
||||||
bool processUnmatched(gdioutput &gdi, const SICard &csic, bool silent);
|
bool processUnmatched(gdioutput &gdi, const SICard &csic, bool silent);
|
||||||
|
|
||||||
void rentCardInfo(gdioutput &gdi, int width);
|
|
||||||
|
|
||||||
bool interactiveReadout;
|
bool interactiveReadout;
|
||||||
bool useDatabase;
|
bool useDatabase;
|
||||||
bool printSplits;
|
bool printSplits;
|
||||||
bool printStartInfo;
|
bool printStartInfo;
|
||||||
bool manualInput;
|
bool manualInput;
|
||||||
|
bool multipleStarts = false;
|
||||||
|
|
||||||
PrinterObject splitPrinter;
|
PrinterObject splitPrinter;
|
||||||
list< pair<unsigned, int> > printPunchRunnerIdQueue;
|
list< pair<unsigned, int> > printPunchRunnerIdQueue;
|
||||||
void addToPrintQueue(pRunner r);
|
void addToPrintQueue(pRunner r);
|
||||||
@ -97,10 +103,9 @@ private:
|
|||||||
//Operation mode
|
//Operation mode
|
||||||
SIMode mode;
|
SIMode mode;
|
||||||
bool lockedFunction = false;
|
bool lockedFunction = false;
|
||||||
bool allowControl = true;
|
|
||||||
bool allowFinish = true;
|
|
||||||
bool allowStart = false;
|
|
||||||
|
|
||||||
|
void changeMapping(gdioutput& gdi) const;
|
||||||
|
void fillMappings(gdioutput& gdi) const;
|
||||||
int currentAssignIndex;
|
int currentAssignIndex;
|
||||||
|
|
||||||
void printSIInfo(gdioutput &gdi, const wstring &port) const;
|
void printSIInfo(gdioutput &gdi, const wstring &port) const;
|
||||||
@ -219,10 +224,47 @@ private:
|
|||||||
int readoutFunctionX = 0;
|
int readoutFunctionX = 0;
|
||||||
int readoutFunctionY = 0;
|
int readoutFunctionY = 0;
|
||||||
|
|
||||||
|
int optionBarPosY = 0;
|
||||||
|
int optionBarPosX = 0;
|
||||||
|
int check_toolbar_xb = 0;
|
||||||
|
int check_toolbar_yb = 0;
|
||||||
|
|
||||||
|
enum class CheckBox {
|
||||||
|
Interactive,
|
||||||
|
UseDB,
|
||||||
|
PrintSplits,
|
||||||
|
PrintStart,
|
||||||
|
Manual,
|
||||||
|
SeveralTurns,
|
||||||
|
AutoTie,
|
||||||
|
AutoTieRent
|
||||||
|
};
|
||||||
|
|
||||||
|
void checkBoxToolBar(gdioutput& gdi, const set<CheckBox> &items) const;
|
||||||
|
|
||||||
|
|
||||||
void playSoundResource(int res) const;
|
void playSoundResource(int res) const;
|
||||||
void playSoundFile(const wstring& file) const;
|
void playSoundFile(const wstring& file) const;
|
||||||
|
|
||||||
|
struct StoredReadout {
|
||||||
|
wstring info;
|
||||||
|
wstring warnings;
|
||||||
|
wstring cardno;
|
||||||
|
wstring statusline;
|
||||||
|
vector<int> MP;
|
||||||
|
GDICOLOR color;
|
||||||
|
bool rentCard = false;
|
||||||
|
|
||||||
|
RECT computeRC(gdioutput &gdi) const;
|
||||||
|
void render(gdioutput &gdi, const RECT &rc) const;
|
||||||
|
static void rentCardInfo(gdioutput &gdi, const RECT &rcIn);
|
||||||
|
};
|
||||||
|
|
||||||
|
list<StoredReadout> readCards;
|
||||||
|
void renderReadCard(gdioutput &gdi, int maxNumber);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void clearCompetitionData();
|
void clearCompetitionData() final;
|
||||||
|
|
||||||
static wstring getPlace(const oRunner *r);
|
static wstring getPlace(const oRunner *r);
|
||||||
static wstring getTimeString(const oRunner *r);
|
static wstring getTimeString(const oRunner *r);
|
||||||
@ -271,6 +313,8 @@ public:
|
|||||||
|
|
||||||
int siCB(gdioutput &gdi, int type, void *data);
|
int siCB(gdioutput &gdi, int type, void *data);
|
||||||
|
|
||||||
|
void writeDefaultHiredCards();
|
||||||
|
|
||||||
void logCard(gdioutput &gdi, const SICard &card);
|
void logCard(gdioutput &gdi, const SICard &card);
|
||||||
|
|
||||||
void setCardNumberField(const string &fieldId) {insertCardNumberField=fieldId;}
|
void setCardNumberField(const string &fieldId) {insertCardNumberField=fieldId;}
|
||||||
@ -286,7 +330,7 @@ public:
|
|||||||
void clearQueue() { CardQueue.clear(); }
|
void clearQueue() { CardQueue.clear(); }
|
||||||
void refillComPorts(gdioutput &gdi);
|
void refillComPorts(gdioutput &gdi);
|
||||||
|
|
||||||
bool loadPage(gdioutput &gdi);
|
bool loadPage(gdioutput &gdi) final;
|
||||||
void showReadoutMode(gdioutput & gdi);
|
void showReadoutMode(gdioutput & gdi);
|
||||||
|
|
||||||
void showReadoutStatus(gdioutput &gdi, const oRunner *r,
|
void showReadoutStatus(gdioutput &gdi, const oRunner *r,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -176,7 +176,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
|||||||
gdi.fillDown();
|
gdi.fillDown();
|
||||||
|
|
||||||
vector< pair<wstring, size_t> > d;
|
vector< pair<wstring, size_t> > d;
|
||||||
oe->fillControls(d, oEvent::CTCourseControl);
|
oe->fillControls(d, oEvent::ControlType::CourseControl);
|
||||||
gdi.addItem("Controls", d);
|
gdi.addItem("Controls", d);
|
||||||
|
|
||||||
gdi.setSelection("Controls", controlsToWatch);
|
gdi.setSelection("Controls", controlsToWatch);
|
||||||
@ -382,7 +382,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
|||||||
controlsToWatch.insert(-2); // Non empty but no control
|
controlsToWatch.insert(-2); // Non empty but no control
|
||||||
|
|
||||||
for (set<int>::iterator it=controlsToWatch.begin();it!=controlsToWatch.end();++it) {
|
for (set<int>::iterator it=controlsToWatch.begin();it!=controlsToWatch.end();++it) {
|
||||||
pControl pc=oe->getControl(*it, false);
|
pControl pc=oe->getControl(*it, false, false);
|
||||||
if (pc) {
|
if (pc) {
|
||||||
pc->setRadio(true);
|
pc->setRadio(true);
|
||||||
pc->synchronize(true);
|
pc->synchronize(true);
|
||||||
@ -722,7 +722,7 @@ void TabSpeaker::splitAnalysis(gdioutput &gdi, int xp, int yp, pRunner r)
|
|||||||
else
|
else
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
timeloss += pc->getControlOrdinal(j) + L". " + formatTime(delta[j]);
|
timeloss += pc->getControlOrdinal(j) + L". " + formatTime(delta[j], SubSecond::Auto);
|
||||||
}
|
}
|
||||||
if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) {
|
if (timeloss.length() > charlimit || (!timeloss.empty() && !first && j+1 == delta.size())) {
|
||||||
gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed);
|
gdi.addStringUT(yp, xp, 0, timeloss).setColor(colorDarkRed);
|
||||||
@ -1223,7 +1223,7 @@ void TabSpeaker::storeManualTime(gdioutput &gdi)
|
|||||||
throw std::exception(bf);
|
throw std::exception(bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
oe->addFreePunch(itime, punch, sino, true);
|
oe->addFreePunch(itime, punch, 0, sino, true);
|
||||||
|
|
||||||
gdi.restore("manual", false);
|
gdi.restore("manual", false);
|
||||||
gdi.addString("", 0, L"Löpare: X, kontroll: Y, kl Z#" + Name + L"#" + oPunch::getType(punch) + L"#" + oe->getAbsTime(itime));
|
gdi.addString("", 0, L"Löpare: X, kontroll: Y, kl Z#" + Name + L"#" + oPunch::getType(punch) + L"#" + oe->getAbsTime(itime));
|
||||||
@ -1432,7 +1432,7 @@ void TabSpeaker::loadSettings(vector< multimap<string, wstring> > &settings) {
|
|||||||
xmlList allS;
|
xmlList allS;
|
||||||
s.getObjects(allS);
|
s.getObjects(allS);
|
||||||
for (auto &prop : allS) {
|
for (auto &prop : allS) {
|
||||||
settings.back().insert(make_pair(prop.getName(), prop.getw()));
|
settings.back().insert(make_pair(prop.getName(), prop.getWStr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -274,9 +274,9 @@ void TabTeam::updateTeamStatus(gdioutput &gdi, pTeam t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gdi.setText("Start", t->getStartTimeS());
|
gdi.setText("Start", t->getStartTimeS());
|
||||||
gdi.setText("Finish",t->getFinishTimeS());
|
gdi.setText("Finish",t->getFinishTimeS(false, SubSecond::Auto));
|
||||||
gdi.setText("Time", t->getRunningTimeS(true));
|
gdi.setText("Time", t->getRunningTimeS(true, SubSecond::Auto));
|
||||||
gdi.setText("TimeAdjust", getTimeMS(t->getTimeAdjustment()));
|
gdi.setText("TimeAdjust", formatTimeMS(t->getTimeAdjustment(false), false, SubSecond::Auto));
|
||||||
gdi.setText("PointAdjust", -t->getPointAdjustment());
|
gdi.setText("PointAdjust", -t->getPointAdjustment());
|
||||||
gdi.selectItemByData("Status", t->getStatus());
|
gdi.selectItemByData("Status", t->getStatus());
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r = oe->addRunner(name, t->getClubId(), t->getClassId(false), cardNo, 0, false);
|
r = oe->addRunner(name, t->getClubId(), t->getClassId(false), cardNo, L"", false);
|
||||||
|
|
||||||
r->setName(name, true);
|
r->setName(name, true);
|
||||||
r->setCardNo(cardNo, true);
|
r->setCardNo(cardNo, true);
|
||||||
@ -659,7 +659,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
bool rent = gdi.isChecked("DirRent");
|
bool rent = gdi.isChecked("DirRent");
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(false), card, 0, false);
|
r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(false), card, L"", false);
|
||||||
}
|
}
|
||||||
if (rent)
|
if (rent)
|
||||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||||
@ -728,7 +728,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
pTeam t = oe->getTeam(teamId);
|
pTeam t = oe->getTeam(teamId);
|
||||||
if (!t || !t->getClassRef(false))
|
if (!t || !t->getClassRef(false))
|
||||||
return 0;
|
return 0;
|
||||||
|
t->synchronize();
|
||||||
pClass pc = t->getClassRef(false);
|
pClass pc = t->getClassRef(false);
|
||||||
int nf = pc->getNumForks();
|
int nf = pc->getNumForks();
|
||||||
ListBoxInfo lbi;
|
ListBoxInfo lbi;
|
||||||
@ -745,7 +745,13 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
int currentKey = max(newSno-1, 0) % nf;
|
int currentKey = max(newSno-1, 0) % nf;
|
||||||
if (currentKey == lbi.data) {
|
if (currentKey == lbi.data) {
|
||||||
|
for (int j = 0; j < t->getNumRunners(); j++) {
|
||||||
|
if (t->getRunner(j)) {
|
||||||
|
t->getRunner(j)->setCourseId(0);
|
||||||
|
t->synchronize(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
t->setStartNo(newSno, oBase::ChangeType::Update);
|
t->setStartNo(newSno, oBase::ChangeType::Update);
|
||||||
t->synchronize(true);
|
t->synchronize(true);
|
||||||
t->evaluate(oBase::ChangeType::Update);
|
t->evaluate(oBase::ChangeType::Update);
|
||||||
@ -1163,6 +1169,9 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (ii.id == "R" + itos(i)) {
|
||||||
|
enableRunner(gdi, i, !ii.text.empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,7 +1186,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
|||||||
ac.setAutoCompleteHandler(this);
|
ac.setAutoCompleteHandler(this);
|
||||||
vector<AutoCompleteRecord> items;
|
vector<AutoCompleteRecord> items;
|
||||||
for (auto club : clubs)
|
for (auto club : clubs)
|
||||||
items.emplace_back(club->getDisplayName(), club->getName(), club->getId());
|
items.emplace_back(club->getDisplayName(), -int(items.size()), club->getName(), club->getId());
|
||||||
|
|
||||||
ac.setData(items);
|
ac.setData(items);
|
||||||
ac.show();
|
ac.show();
|
||||||
@ -1228,32 +1237,37 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
|||||||
int yp = gdi.getCY();
|
int yp = gdi.getCY();
|
||||||
int numberPos = xp;
|
int numberPos = xp;
|
||||||
xp += gdi.scaleLength(25);
|
xp += gdi.scaleLength(25);
|
||||||
int dx[6] = {0, 184, 220, 290, 316, 364};
|
const int dxIn[6] = {0, 184, 220, 300, 326, 374};
|
||||||
dx[1] = gdi.getInputDimension(18).first + gdi.scaleLength(4);
|
int dx[6];
|
||||||
for (int i = 2; i<6; i++)
|
dx[0] = 0;
|
||||||
dx[i] = dx[1] + gdi.scaleLength(dx[i]-188);
|
|
||||||
|
|
||||||
|
for (int i = 1; i < 6; i++) {
|
||||||
|
if (i == 1)
|
||||||
|
dx[i] = gdi.getInputDimension(18).first + gdi.scaleLength(4);
|
||||||
|
else if (i == 3)
|
||||||
|
dx[i] = dx[i-1] + gdi.getInputDimension(7).first + gdi.scaleLength(4);
|
||||||
|
else
|
||||||
|
dx[i] = dx[i-1] + gdi.scaleLength(dxIn[i] - dxIn[i-1]);
|
||||||
|
}
|
||||||
gdi.addString("", yp, xp + dx[0], 0, "Namn:");
|
gdi.addString("", yp, xp + dx[0], 0, "Namn:");
|
||||||
gdi.addString("", yp, xp + dx[2], 0, "Bricka:");
|
gdi.addString("", yp, xp + dx[2], 0, "Bricka:");
|
||||||
gdi.addString("", yp, xp + dx[3], 0, "Hyrd:");
|
gdi.addString("", yp, xp + dx[3]- gdi.scaleLength(5), 0, "Hyrd:");
|
||||||
gdi.addString("", yp, xp + dx[5], 0, "Status:");
|
gdi.addString("", yp, xp + dx[5], 0, "Status:");
|
||||||
gdi.dropLine(0.5);
|
gdi.dropLine(0.5);
|
||||||
|
const int textOffY = gdi.scaleLength(4);
|
||||||
for (unsigned i = 0; i < pc->getNumStages(); i++) {
|
for (unsigned i = 0; i < pc->getNumStages(); i++) {
|
||||||
yp = gdi.getCY() - gdi.scaleLength(3);
|
yp = gdi.getCY() - gdi.scaleLength(3);
|
||||||
|
|
||||||
sprintf_s(bf, "R%d", i);
|
sprintf_s(bf, "R%d", i);
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
bool hasSI = false;
|
bool hasSI = false;
|
||||||
gdi.addStringUT(yp, numberPos, 0, pc->getLegNumber(i) + L".");
|
gdi.addStringUT(yp + textOffY, numberPos, 0, pc->getLegNumber(i) + L".");
|
||||||
if (pc->getLegRunner(i) == i) {
|
if (pc->getLegRunner(i) == i) {
|
||||||
|
|
||||||
gdi.addInput(xp + dx[0], yp, bf, L"", 18, TeamCB);//Name
|
gdi.addInput(xp + dx[0], yp, bf, L"", 18, TeamCB);//Name
|
||||||
gdi.addButton(xp + dx[1], yp - 2, gdi.scaleLength(28), "DR" + itos(i), "<>", TeamCB, "Knyt löpare till sträckan.", false, false); // Change
|
gdi.addButton(xp + dx[1], yp - 2, gdi.scaleLength(28), "DR" + itos(i), "<>", TeamCB, "Knyt löpare till sträckan.", false, false); // Change
|
||||||
sprintf_s(bf_si, "SI%d", i);
|
sprintf_s(bf_si, "SI%d", i);
|
||||||
hasSI = true;
|
hasSI = true;
|
||||||
gdi.addInput(xp + dx[2], yp, bf_si, L"", 5, TeamCB).setExtra(i); //Si
|
gdi.addInput(xp + dx[2], yp, bf_si, L"", 7, TeamCB).setExtra(i); //Si
|
||||||
|
|
||||||
gdi.addCheckbox(xp + dx[3], yp + gdi.scaleLength(10), "RENT" + itos(i), "", 0, false); //Rentcard
|
gdi.addCheckbox(xp + dx[3], yp + gdi.scaleLength(10), "RENT" + itos(i), "", 0, false); //Rentcard
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1262,16 +1276,17 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
|||||||
}
|
}
|
||||||
gdi.addButton(xp + dx[4], yp - 2, gdi.scaleLength(38), "MR" + itos(i), "...", TeamCB, "Redigera deltagaren.", false, false); // Change
|
gdi.addButton(xp + dx[4], yp - 2, gdi.scaleLength(38), "MR" + itos(i), "...", TeamCB, "Redigera deltagaren.", false, false); // Change
|
||||||
|
|
||||||
gdi.addString(("STATUS" + itos(i)).c_str(), yp + gdi.scaleLength(5), xp + dx[5], 0, "#MMMMMMMMMMMMMMMM");
|
gdi.addString(("STATUS" + itos(i)).c_str(), yp + textOffY, xp + dx[5], 0, "#MMMMMMMMMMMMMMMM");
|
||||||
gdi.setText("STATUS" + itos(i), L"", false);
|
gdi.setText("STATUS" + itos(i), L"", false);
|
||||||
gdi.dropLine(0.5);
|
gdi.dropLine(0.5);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
|
||||||
if (t) {
|
if (t) {
|
||||||
pRunner r = t->getRunner(i);
|
pRunner r = t->getRunner(i);
|
||||||
|
enableRunner(gdi, i, r != nullptr);
|
||||||
if (r) {
|
if (r) {
|
||||||
gdi.setText(bf, r->getNameRaw())->setExtra(r->getId());
|
gdi.setText(bf, r->getNameRaw())->setExtra(r->getId());
|
||||||
|
r->getPlace(true); // Ensure computed status is up-to-date
|
||||||
if (hasSI) {
|
if (hasSI) {
|
||||||
int cno = r->getCardNo();
|
int cno = r->getCardNo();
|
||||||
gdi.setText(bf_si, cno > 0 ? itow(cno) : L"");
|
gdi.setText(bf_si, cno > 0 ? itow(cno) : L"");
|
||||||
@ -1279,13 +1294,13 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
|||||||
gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0);
|
gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0);
|
||||||
}
|
}
|
||||||
string sid = "STATUS" + itos(i);
|
string sid = "STATUS" + itos(i);
|
||||||
if (r->statusOK(true)) {
|
if (r->statusOK(true, true)) {
|
||||||
TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(true), false);
|
TextInfo * ti = (TextInfo *)gdi.setText(sid, L"OK, " + r->getRunningTimeS(true, SubSecond::Auto), false);
|
||||||
if (ti)
|
if (ti)
|
||||||
ti->setColor(colorGreen);
|
ti->setColor(colorGreen);
|
||||||
}
|
}
|
||||||
else if (r->getStatusComputed() != StatusUnknown) {
|
else if (r->getStatusComputed(true) != StatusUnknown) {
|
||||||
TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false, true) + L", " + r->getRunningTimeS(true), false);
|
TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false, true) + L", " + r->getRunningTimeS(true, SubSecond::Auto), false);
|
||||||
if (ti)
|
if (ti)
|
||||||
ti->setColor(colorRed);
|
ti->setColor(colorRed);
|
||||||
}
|
}
|
||||||
@ -1334,6 +1349,15 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
|||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabTeam::enableRunner(gdioutput& gdi, int index, bool enable) {
|
||||||
|
string ix = itos(index);
|
||||||
|
string si = ("SI" + ix);
|
||||||
|
bool hasSI = enable || !gdi.getText(si, true).empty();
|
||||||
|
gdi.setInputStatus(si.c_str(), hasSI, true);
|
||||||
|
gdi.setInputStatus(("RENT" + ix).c_str(), hasSI, true);
|
||||||
|
gdi.setInputStatus(("MR" + ix).c_str(), enable, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool TabTeam::loadPage(gdioutput &gdi, int id) {
|
bool TabTeam::loadPage(gdioutput &gdi, int id) {
|
||||||
teamId = id;
|
teamId = id;
|
||||||
return loadPage(gdi);
|
return loadPage(gdi);
|
||||||
@ -1457,12 +1481,13 @@ bool TabTeam::loadPage(gdioutput &gdi)
|
|||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.selectItemByData("Status", 0);
|
gdi.selectItemByData("Status", 0);
|
||||||
|
|
||||||
gdi.addString("TeamInfo", 0, "").setColor(colorRed);
|
|
||||||
gdi.dropLine(0.4);
|
gdi.dropLine(0.4);
|
||||||
|
|
||||||
if (oe->hasAnyRestartTime()) {
|
if (oe->hasAnyRestartTime()) {
|
||||||
gdi.addCheckbox("NoRestart", "Förhindra omstart", 0, false, "Förhindra att laget deltar i någon omstart");
|
gdi.addCheckbox("NoRestart", "Förhindra omstart", 0, false, "Förhindra att laget deltar i någon omstart");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdi.addString("TeamInfo", 0, " ").setColor(colorRed);
|
||||||
gdi.dropLine(1.5);
|
gdi.dropLine(1.5);
|
||||||
|
|
||||||
const bool multiDay = oe->hasPrevStage();
|
const bool multiDay = oe->hasPrevStage();
|
||||||
@ -1694,7 +1719,7 @@ void TabTeam::saveTeamImport(gdioutput &gdi, bool useExisting) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = oe->addRunner(member.name, member.club, 0, member.cardNo, 0, false);
|
r = oe->addRunner(member.name, member.club, 0, member.cardNo, L"", false);
|
||||||
|
|
||||||
if (r && !member.course.empty()) {
|
if (r && !member.course.empty()) {
|
||||||
pCourse pc = oe->getCourse(member.course);
|
pCourse pc = oe->getCourse(member.course);
|
||||||
@ -1783,7 +1808,7 @@ void TabTeam::doAddTeamMembers(gdioutput &gdi) {
|
|||||||
continue;
|
continue;
|
||||||
pRunner r = 0;
|
pRunner r = 0;
|
||||||
if (withFee) {
|
if (withFee) {
|
||||||
r = oe->addRunner(nn, mt->getClubId(), 0, 0, 0, false);
|
r = oe->addRunner(nn, mt->getClubId(), 0, 0, L"", false);
|
||||||
r->synchronize();
|
r->synchronize();
|
||||||
mt->setRunner(j, r, false);
|
mt->setRunner(j, r, false);
|
||||||
r->addClassDefaultFee(true);
|
r->addClassDefaultFee(true);
|
||||||
@ -1849,7 +1874,7 @@ void TabTeam::showRunners(gdioutput &gdi, const char *title,
|
|||||||
void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
|
void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
|
||||||
if (r && t && leg < t->getNumRunners()) {
|
if (r && t && leg < t->getNumRunners()) {
|
||||||
pRunner oldR = t->getRunner(leg);
|
pRunner oldR = t->getRunner(leg);
|
||||||
gdioutput::AskAnswer ans = gdioutput::AnswerNo;
|
gdioutput::AskAnswer ans = gdioutput::AskAnswer::AnswerNo;
|
||||||
if (r == oldR) {
|
if (r == oldR) {
|
||||||
gdi.restore("SelectR");
|
gdi.restore("SelectR");
|
||||||
return;
|
return;
|
||||||
@ -1868,9 +1893,9 @@ void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
|
|||||||
ans = gdi.askCancel(L"Vill du att X går in i laget?#" + r->getName());
|
ans = gdi.askCancel(L"Vill du att X går in i laget?#" + r->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ans == gdioutput::AnswerNo)
|
if (ans == gdioutput::AskAnswer::AnswerNo)
|
||||||
return;
|
return;
|
||||||
else if (ans == gdioutput::AnswerCancel) {
|
else if (ans == gdioutput::AskAnswer::AnswerCancel) {
|
||||||
gdi.restore("SelectR");
|
gdi.restore("SelectR");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -74,6 +74,10 @@ private:
|
|||||||
|
|
||||||
void switchRunners(pTeam team, int leg, pRunner r, pRunner oldR);
|
void switchRunners(pTeam team, int leg, pRunner r, pRunner oldR);
|
||||||
|
|
||||||
|
/** Enable or disable edit for a team runner*/
|
||||||
|
void enableRunner(gdioutput &gdi, int index, bool enable);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void clearCompetitionData();
|
void clearCompetitionData();
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -278,7 +278,8 @@ void Table::filter(int col, const wstring &filt, bool forceFilter)
|
|||||||
|
|
||||||
sortIndex.resize(2);
|
sortIndex.resize(2);
|
||||||
for (size_t k=2;k<baseIndex.size();k++) {
|
for (size_t k=2;k<baseIndex.size();k++) {
|
||||||
if (filterMatchString(Data[baseIndex[k].index].cells[col].contents, filt_lc))
|
int score;
|
||||||
|
if (filterMatchString(Data[baseIndex[k].index].cells[col].contents, filt_lc, score))
|
||||||
sortIndex.push_back(baseIndex[k]);
|
sortIndex.push_back(baseIndex[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -415,6 +415,7 @@ struct TableSortIndex {
|
|||||||
enum {TID_CLASSNAME, TID_COURSE, TID_NUM, TID_ID, TID_MODIFIED,
|
enum {TID_CLASSNAME, TID_COURSE, TID_NUM, TID_ID, TID_MODIFIED,
|
||||||
TID_RUNNER, TID_CLUB, TID_START, TID_TIME,
|
TID_RUNNER, TID_CLUB, TID_START, TID_TIME,
|
||||||
TID_FINISH, TID_STATUS, TID_RUNNINGTIME, TID_PLACE, TID_POINTS,
|
TID_FINISH, TID_STATUS, TID_RUNNINGTIME, TID_PLACE, TID_POINTS,
|
||||||
TID_CARD, TID_TEAM, TID_LEG, TID_CONTROL, TID_CODES, TID_FEE, TID_PAID,
|
TID_CARD, TID_TEAM, TID_LEG, TID_CONTROL, TID_UNIT, TID_CODES, TID_FEE, TID_PAID,
|
||||||
TID_INPUTTIME, TID_INPUTSTATUS, TID_INPUTPOINTS, TID_INPUTPLACE,
|
TID_INPUTTIME, TID_INPUTSTATUS, TID_INPUTPOINTS, TID_INPUTPLACE,
|
||||||
TID_NAME, TID_NATIONAL, TID_SEX, TID_YEAR, TID_INDEX, TID_ENTER, TID_STARTNO, TID_VOLTAGE};
|
TID_NAME, TID_NATIONAL, TID_SEX, TID_YEAR, TID_INDEX,
|
||||||
|
TID_ENTER, TID_STARTNO, TID_VOLTAGE, TID_BATTERYDATE};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -62,7 +62,7 @@ void TimeStamp::update()
|
|||||||
|
|
||||||
__int64 ¤ttime=*(__int64*)&ft;
|
__int64 ¤ttime=*(__int64*)&ft;
|
||||||
|
|
||||||
Time=unsigned((currenttime/10000000L) - minYearConstant*365*24*3600);
|
Time=unsigned((currenttime/10000000L) - minYearConstant*365*24*timeConstSecPerHour);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimeStamp::getAge() const
|
int TimeStamp::getAge() const
|
||||||
@ -73,7 +73,7 @@ int TimeStamp::getAge() const
|
|||||||
SystemTimeToFileTime(&st, &ft);
|
SystemTimeToFileTime(&st, &ft);
|
||||||
__int64 ¤ttime=*(__int64*)&ft;
|
__int64 ¤ttime=*(__int64*)&ft;
|
||||||
|
|
||||||
int CTime=int((currenttime/10000000)-minYearConstant*365*24*3600);
|
int CTime=int((currenttime/10000000)-minYearConstant*365*24* timeConstSecPerHour);
|
||||||
|
|
||||||
return CTime-Time;
|
return CTime-Time;
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ const string &TimeStamp::getStamp() const
|
|||||||
return stampCode;
|
return stampCode;
|
||||||
|
|
||||||
stampCodeTime = Time;
|
stampCodeTime = Time;
|
||||||
__int64 ft64=(__int64(Time)+minYearConstant*365*24*3600)*10000000;
|
__int64 ft64=(__int64(Time)+minYearConstant*365*24* timeConstSecPerHour)*10000000;
|
||||||
FILETIME &ft=*(FILETIME*)&ft64;
|
FILETIME &ft=*(FILETIME*)&ft64;
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
FileTimeToSystemTime(&ft, &st);
|
FileTimeToSystemTime(&ft, &st);
|
||||||
@ -105,9 +105,20 @@ const string &TimeStamp::getStamp(const string &sqlStampIn) const {
|
|||||||
return stampCode;
|
return stampCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wstring TimeStamp::getUpdateTime() const {
|
||||||
|
__int64 ft64 = (__int64(Time) + minYearConstant * 365 * 24 * timeConstSecPerHour) * 10000000;
|
||||||
|
FILETIME& ft = *(FILETIME*)&ft64;
|
||||||
|
SYSTEMTIME st;
|
||||||
|
FileTimeToSystemTime(&ft, &st);
|
||||||
|
wchar_t bf[32];
|
||||||
|
swprintf_s(bf, L"%02d:%02d", st.wHour, st.wMinute);
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wstring TimeStamp::getStampString() const
|
wstring TimeStamp::getStampString() const
|
||||||
{
|
{
|
||||||
__int64 ft64=(__int64(Time)+minYearConstant*365*24*3600)*10000000;
|
__int64 ft64=(__int64(Time)+minYearConstant*365*24* timeConstSecPerHour)*10000000;
|
||||||
FILETIME &ft=*(FILETIME*)&ft64;
|
FILETIME &ft=*(FILETIME*)&ft64;
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
FileTimeToSystemTime(&ft, &st);
|
FileTimeToSystemTime(&ft, &st);
|
||||||
@ -120,7 +131,7 @@ wstring TimeStamp::getStampString() const
|
|||||||
|
|
||||||
string TimeStamp::getStampStringN() const
|
string TimeStamp::getStampStringN() const
|
||||||
{
|
{
|
||||||
__int64 ft64 = (__int64(Time) + minYearConstant * 365 * 24 * 3600) * 10000000;
|
__int64 ft64 = (__int64(Time) + minYearConstant * 365 * 24 * timeConstSecPerHour) * 10000000;
|
||||||
FILETIME &ft = *(FILETIME*)&ft64;
|
FILETIME &ft = *(FILETIME*)&ft64;
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
FileTimeToSystemTime(&ft, &st);
|
FileTimeToSystemTime(&ft, &st);
|
||||||
@ -147,19 +158,41 @@ void TimeStamp::setStamp(const string &s)
|
|||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
memset(&st, 0, sizeof(st));
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
|
auto parse = [](const char* data, int size, const char*& next) -> int {
|
||||||
|
int ix = 0;
|
||||||
|
int out = 0;
|
||||||
|
while (ix < size && data[ix] >= '0' && data[ix] <= '9') {
|
||||||
|
out = (out << 1) + (out << 3) + data[ix] - '0';
|
||||||
|
ix++;
|
||||||
|
}
|
||||||
|
while (data[ix] && (data[ix] == ' ' || data[ix] == '-' || data[ix] == ':')) {
|
||||||
|
ix++;
|
||||||
|
}
|
||||||
|
next = data + ix;
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
//const char *ptr=s.c_str();
|
//const char *ptr=s.c_str();
|
||||||
//sscanf(s.c_str(), "%4hd%2hd%2hd%2hd%2hd%2hd", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
//sscanf(s.c_str(), "%4hd%2hd%2hd%2hd%2hd%2hd", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
||||||
st.wYear=atoi(s.substr(0, 4).c_str());
|
/*st.wYear = atoi(s.substr(0, 4).c_str());
|
||||||
st.wMonth=atoi(s.substr(4, 2).c_str());
|
st.wMonth=atoi(s.substr(4, 2).c_str());
|
||||||
st.wDay=atoi(s.substr(6, 2).c_str());
|
st.wDay=atoi(s.substr(6, 2).c_str());
|
||||||
st.wHour=atoi(s.substr(8, 2).c_str());
|
st.wHour=atoi(s.substr(8, 2).c_str());
|
||||||
st.wMinute=atoi(s.substr(10, 2).c_str());
|
st.wMinute=atoi(s.substr(10, 2).c_str());
|
||||||
st.wSecond=atoi(s.substr(12, 2).c_str());
|
st.wSecond=atoi(s.substr(12, 2).c_str());
|
||||||
|
*/
|
||||||
|
const char* ptr = s.data();
|
||||||
|
|
||||||
|
st.wYear = parse(ptr, 4, ptr);
|
||||||
|
st.wMonth = parse(ptr, 2, ptr);
|
||||||
|
st.wDay = parse(ptr, 2, ptr);
|
||||||
|
st.wHour = parse(ptr, 2, ptr);
|
||||||
|
st.wMinute = parse(ptr, 2, ptr);
|
||||||
|
st.wSecond = parse(ptr, 2, ptr);
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
SystemTimeToFileTime(&st, &ft);
|
SystemTimeToFileTime(&st, &ft);
|
||||||
|
|
||||||
__int64 ¤ttime=*(__int64*)&ft;
|
__int64 ¤ttime=*(__int64*)&ft;
|
||||||
|
|
||||||
Time = unsigned((currenttime/10000000)-minYearConstant*365*24*3600);
|
Time = unsigned((currenttime/10000000)-minYearConstant*365*24* timeConstSecPerHour);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
#endif // _MSC_VER > 1000
|
#endif // _MSC_VER > 1000
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -39,6 +39,8 @@ public:
|
|||||||
const string &getStamp() const;
|
const string &getStamp() const;
|
||||||
const string &getStamp(const string &sqlStampIn) const;
|
const string &getStamp(const string &sqlStampIn) const;
|
||||||
|
|
||||||
|
const wstring getUpdateTime() const;
|
||||||
|
|
||||||
wstring getStampString() const;
|
wstring getStampString() const;
|
||||||
string getStampStringN() const;
|
string getStampStringN() const;
|
||||||
int getAge() const;
|
int getAge() const;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -42,7 +42,7 @@ AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol,
|
|||||||
double w = (gdi.getWidth() + 20) *nCol + margin;
|
double w = (gdi.getWidth() + 20) *nCol + margin;
|
||||||
double s = width / w;
|
double s = width / w;
|
||||||
if ((fabs(s - 1.0) > 1e-3)) {
|
if ((fabs(s - 1.0) > 1e-3)) {
|
||||||
gdi.scaleSize(s, true, false);
|
gdi.scaleSize(s, true, gdioutput::ScaleOperation::NoRefresh);
|
||||||
}
|
}
|
||||||
pageInfo.topMargin = 20;
|
pageInfo.topMargin = 20;
|
||||||
pageInfo.scaleX = 1.0f;
|
pageInfo.scaleX = 1.0f;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -176,7 +176,10 @@ void AutoCompleteInfo::enter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoCompleteInfo::setData(const vector<AutoCompleteRecord> &items) {
|
void AutoCompleteInfo::setData(const vector<AutoCompleteRecord> &itemsIn) {
|
||||||
|
vector<AutoCompleteRecord> items = itemsIn;
|
||||||
|
stable_sort(items.begin(), items.end());
|
||||||
|
|
||||||
int newDataIx = -1;
|
int newDataIx = -1;
|
||||||
if (modifedAutoComplete && size_t(currentIx) < data.size()) {
|
if (modifedAutoComplete && size_t(currentIx) < data.size()) {
|
||||||
for (size_t k = 0; k < items.size(); k++) {
|
for (size_t k = 0; k < items.size(); k++) {
|
||||||
@ -188,6 +191,6 @@ void AutoCompleteInfo::setData(const vector<AutoCompleteRecord> &items) {
|
|||||||
newDataIx = 0;
|
newDataIx = 0;
|
||||||
modifedAutoComplete = false;
|
modifedAutoComplete = false;
|
||||||
}
|
}
|
||||||
data = items;
|
data = std::move(items);
|
||||||
currentIx = newDataIx;
|
currentIx = newDataIx;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -29,10 +29,17 @@ class AutoCompleteHandler;
|
|||||||
|
|
||||||
struct AutoCompleteRecord {
|
struct AutoCompleteRecord {
|
||||||
AutoCompleteRecord() : id(-1) {}
|
AutoCompleteRecord() : id(-1) {}
|
||||||
AutoCompleteRecord(const wstring &display, const wstring &name, int id) : display(display), name(name), id(id) {}
|
AutoCompleteRecord(const wstring &display, int prio, const wstring &name, int id) : display(display), prio(prio), name(name), id(id) {}
|
||||||
wstring display;
|
wstring display;
|
||||||
wstring name;
|
wstring name;
|
||||||
int id;
|
int id;
|
||||||
|
int prio = 0;
|
||||||
|
bool operator<(const AutoCompleteRecord& rec) const {
|
||||||
|
if (prio != rec.prio)
|
||||||
|
return prio > rec.prio;
|
||||||
|
else
|
||||||
|
return display < rec.display;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoCompleteInfo {
|
class AutoCompleteInfo {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
204
code/binencoder.cpp
Normal file
204
code/binencoder.cpp
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/************************************************************************
|
||||||
|
MeOS - Orienteering Software
|
||||||
|
Copyright (C) 2009-2023 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 "stdafx.h"
|
||||||
|
#include "meos_util.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
#include "binencoder.h"
|
||||||
|
|
||||||
|
Encoder92::Encoder92() {
|
||||||
|
int d = 32;
|
||||||
|
fill(reverse_table, reverse_table + 128, 0);
|
||||||
|
fill(used, used + 128, false);
|
||||||
|
for (int j = 0; j < 92; j++) {
|
||||||
|
table[j] = d++;
|
||||||
|
while (d == '"' || d == '<' || d == '&' || d=='>')
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
table[91] = '\t';
|
||||||
|
swap(table[0], table[1]);
|
||||||
|
|
||||||
|
for (int j = 0; j < 92; j++) {
|
||||||
|
reverse_table[table[j]] = j;
|
||||||
|
used[table[j]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Encoder92::encode92(const uint8_t datain[13], uint8_t dataout[16]) {
|
||||||
|
uint64_t w64bitA = *(uint64_t*)&datain[0];
|
||||||
|
uint32_t w32bitB = *(uint32_t*)&datain[8];
|
||||||
|
uint32_t w8bitC = datain[12];
|
||||||
|
|
||||||
|
// Consume 60 bits of data from w64bitA (4 bits will remain)
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
dataout[i] = w64bitA & 0b00111111;
|
||||||
|
w64bitA = w64bitA >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume 30 bits of data from w32bitB (2 bits will remain)
|
||||||
|
for (int i = 10; i < 15; i++) {
|
||||||
|
dataout[i] = w32bitB & 0b00111111;
|
||||||
|
w32bitB = w32bitB >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume remaining 2 + 4 bits
|
||||||
|
dataout[15] = int8_t(w32bitB | (w64bitA << 2));
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i+=2) {
|
||||||
|
int extraData = (w8bitC & 0x1);
|
||||||
|
w8bitC = w8bitC >> 1;
|
||||||
|
int combined = (extraData << 12) | dataout[i] | (dataout[i+1] << 6); // 13 bits 0 -- 8192
|
||||||
|
dataout[i] = combined % 92;
|
||||||
|
dataout[i+1] = combined / 92;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Encoder92::decode92(const uint8_t datain[16], uint8_t dataout[13]) {
|
||||||
|
uint8_t datain_64[16];
|
||||||
|
uint32_t w8bitC = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i += 2) {
|
||||||
|
int combined = datain[i] + datain[i + 1] * 92;
|
||||||
|
datain_64[i] = combined & 0b00111111;
|
||||||
|
combined = combined >> 6;
|
||||||
|
datain_64[i+1] = combined & 0b00111111;
|
||||||
|
combined = combined >> 6;
|
||||||
|
w8bitC |= (combined << (i/2));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t w64bitA = 0;
|
||||||
|
uint32_t w32bitB = 0;
|
||||||
|
|
||||||
|
// Reconstruct 60 bits of data to w64bitA
|
||||||
|
for (int i = 9; i >= 0; i--) {
|
||||||
|
w64bitA <<= 6;
|
||||||
|
w64bitA |= datain_64[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstruct 30 bits of data to w32bitB
|
||||||
|
for (int i = 14; i >= 10; i--) {
|
||||||
|
w32bitB <<= 6;
|
||||||
|
w32bitB |= datain_64[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add remaining bits
|
||||||
|
w32bitB = w32bitB | ((datain_64[15] & 0b11) << 30);
|
||||||
|
uint64_t highBits = (datain_64[15] >> 2) & 0b1111;
|
||||||
|
w64bitA = w64bitA | (highBits << 60ll);
|
||||||
|
|
||||||
|
*((uint64_t*)&dataout[0]) = w64bitA;
|
||||||
|
*((uint32_t*)&dataout[8]) = w32bitB;
|
||||||
|
dataout[12] = int8_t(w8bitC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Encoder92::encode92(const vector<uint8_t>& bytesIn, string& encodedString) {
|
||||||
|
int m13 = bytesIn.size()%13;
|
||||||
|
int extra = m13 > 0 ? 13 - m13 : 0;
|
||||||
|
int blocks = (bytesIn.size() + extra) / 13;
|
||||||
|
|
||||||
|
encodedString = itos(bytesIn.size()) + ":";
|
||||||
|
int outLen = encodedString.length();
|
||||||
|
encodedString.resize(encodedString.size() + blocks * 16, ' ');
|
||||||
|
const uint8_t* inPtr = bytesIn.data();
|
||||||
|
//uint8_t* outPtr = encodedString.data() + outLen;
|
||||||
|
uint8_t datain[13];
|
||||||
|
fill(datain, datain + 13, 0);
|
||||||
|
uint8_t dataout[16];
|
||||||
|
int fullBlocks = blocks;
|
||||||
|
if (extra > 0)
|
||||||
|
fullBlocks--;
|
||||||
|
|
||||||
|
for (int i = 0; i < fullBlocks; i++) {
|
||||||
|
//for (int j = 0; j < 13; j++)
|
||||||
|
encode92(inPtr, dataout);
|
||||||
|
inPtr += 13;
|
||||||
|
for (int j = 0; j < 16; j++)
|
||||||
|
encodedString[outLen++] = table[dataout[j]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extra > 0) {
|
||||||
|
for (int j = 0; j < m13; j++) {
|
||||||
|
datain[j] = inPtr[j];
|
||||||
|
}
|
||||||
|
encode92(datain, dataout);
|
||||||
|
for (int j = 0; j < 16; j++)
|
||||||
|
encodedString[outLen++] = table[dataout[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Encoder92::decode92(const string& encodedString, vector<uint8_t>& bytesOut) {
|
||||||
|
bytesOut.clear();
|
||||||
|
if (encodedString.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned size = atoi(encodedString.c_str());
|
||||||
|
string start = itos(size);
|
||||||
|
int len = start.length();
|
||||||
|
if (encodedString.size() < len || encodedString[len] != ':' || size<0)
|
||||||
|
throw std::exception("Invalid data");
|
||||||
|
|
||||||
|
int m13 = size % 13;
|
||||||
|
int extra = m13 > 0 ? 13 - m13 : 0;
|
||||||
|
int blocks = (size + extra) / 13;
|
||||||
|
|
||||||
|
int inDataSize = blocks * 16;
|
||||||
|
if (encodedString.size() < len + 1 + inDataSize)
|
||||||
|
throw std::exception("Invalid data");
|
||||||
|
|
||||||
|
bytesOut.resize(size);
|
||||||
|
auto outPtr = bytesOut.data();
|
||||||
|
|
||||||
|
uint8_t datain[16];
|
||||||
|
uint8_t dataout[13];
|
||||||
|
int fullBlocks = blocks;
|
||||||
|
if (extra > 0)
|
||||||
|
fullBlocks--;
|
||||||
|
|
||||||
|
const char *inPtr = encodedString.c_str() + len + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < fullBlocks; i++) {
|
||||||
|
for (int j = 0; j < 16; j++) {
|
||||||
|
int v = inPtr[j];
|
||||||
|
if (v < 0 || v > 127 || !used[v])
|
||||||
|
throw std::exception("Invalid data");
|
||||||
|
datain[j] = reverse_table[inPtr[j]];
|
||||||
|
}
|
||||||
|
decode92(datain, outPtr);
|
||||||
|
inPtr += 16;
|
||||||
|
outPtr += 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extra > 0) {
|
||||||
|
for (int j = 0; j < 16; j++) {
|
||||||
|
int v = inPtr[j];
|
||||||
|
if (v < 0 || v > 127 || !used[v])
|
||||||
|
throw std::exception("Invalid data");
|
||||||
|
datain[j] = reverse_table[inPtr[j]];
|
||||||
|
}
|
||||||
|
decode92(datain, dataout);
|
||||||
|
for (int j = 0; j < m13; j++)
|
||||||
|
outPtr[j] = dataout[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
39
code/binencoder.h
Normal file
39
code/binencoder.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
MeOS - Orienteering Software
|
||||||
|
Copyright (C) 2009-2023 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 <cstdint>
|
||||||
|
|
||||||
|
class Encoder92 {
|
||||||
|
int8_t table[92];
|
||||||
|
int8_t reverse_table[128];
|
||||||
|
bool used[128];
|
||||||
|
public:
|
||||||
|
Encoder92();
|
||||||
|
|
||||||
|
void encode92(const uint8_t datain[13], uint8_t dataout[16]);
|
||||||
|
void decode92(const uint8_t datain[16], uint8_t dataout[13]);
|
||||||
|
|
||||||
|
void encode92(const vector<uint8_t>& bytesIn, string& encodedString);
|
||||||
|
void decode92(const string& encodedString, vector<uint8_t>& bytesOut);
|
||||||
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -220,7 +220,7 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
|
|||||||
|
|
||||||
for (size_t k = 0; k < it->getNumStages(); k++) {
|
for (size_t k = 0; k < it->getNumStages(); k++) {
|
||||||
StartTypes st = it->getStartType(k);
|
StartTypes st = it->getStartType(k);
|
||||||
if (st == STDrawn || st == STHunting) {
|
if (st == STDrawn || st == STPursuit) {
|
||||||
cnf.legNStart[k].push_back(it->getId());
|
cnf.legNStart[k].push_back(it->getId());
|
||||||
if (cnf.timeStart.size() <= k)
|
if (cnf.timeStart.size() <= k)
|
||||||
cnf.timeStart.resize(k+1);
|
cnf.timeStart.resize(k+1);
|
||||||
@ -243,7 +243,7 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
|
|||||||
|
|
||||||
for (size_t k = 0; k < it->getNumStages(); k++) {
|
for (size_t k = 0; k < it->getNumStages(); k++) {
|
||||||
StartTypes st = it->getStartType(k);
|
StartTypes st = it->getStartType(k);
|
||||||
if (st == STDrawn || st == STHunting) {
|
if (st == STDrawn || st == STPursuit) {
|
||||||
cnf.raceNStart[k].push_back(it->getId());
|
cnf.raceNStart[k].push_back(it->getId());
|
||||||
if (cnf.timeStart.size() <= k)
|
if (cnf.timeStart.size() <= k)
|
||||||
cnf.timeStart.resize(k+1);
|
cnf.timeStart.resize(k+1);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -189,11 +189,10 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
|
|||||||
//Import runners!
|
//Import runners!
|
||||||
int runner=0;
|
int runner=0;
|
||||||
while( (rindex+OSRrentcard)<sp.size() && sp[rindex+OSRfname].length()>0 ){
|
while( (rindex+OSRrentcard)<sp.size() && sp[rindex+OSRfname].length()>0 ){
|
||||||
int year = extendYear(wtoi(sp[rindex+OSRyb]));
|
|
||||||
int cardNo = wtoi(sp[rindex+OSRcard]);
|
int cardNo = wtoi(sp[rindex+OSRcard]);
|
||||||
wstring sname = sp[rindex+OSRsname] + L", " + sp[rindex+OSRfname];
|
wstring sname = sp[rindex+OSRsname] + L", " + sp[rindex+OSRfname];
|
||||||
pRunner r = event.addRunner(sname, ClubId,
|
pRunner r = event.addRunner(sname, ClubId,
|
||||||
ClassId, cardNo, year, false);
|
ClassId, cardNo, sp[rindex + OSRyb], false);
|
||||||
|
|
||||||
r->setEntrySource(externalSourceId);
|
r->setEntrySource(externalSourceId);
|
||||||
oDataInterface DI=r->getDI();
|
oDataInterface DI=r->getDI();
|
||||||
@ -697,10 +696,10 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Import runners!
|
//Import runners!
|
||||||
pRunner r1=event.addRunner(sp[RAIDrunner1], ClubId, ClassId, 0, 0, false);
|
pRunner r1=event.addRunner(sp[RAIDrunner1], ClubId, ClassId, 0, L"", false);
|
||||||
team->setRunner(0, r1, false);
|
team->setRunner(0, r1, false);
|
||||||
|
|
||||||
pRunner r2=event.addRunner(sp[RAIDrunner2], ClubId, ClassId, 0, 0, false);
|
pRunner r2=event.addRunner(sp[RAIDrunner2], ClubId, ClassId, 0, L"", false);
|
||||||
team->setRunner(1, r2, false);
|
team->setRunner(1, r2, false);
|
||||||
|
|
||||||
team->evaluate(oBase::ChangeType::Update);
|
team->evaluate(oBase::ChangeType::Update);
|
||||||
@ -812,15 +811,16 @@ bool csvparser::importPunches(const oEvent &oe, const wstring &file, vector<Punc
|
|||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return false; // Invalid file
|
return false; // Invalid file
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
int card = wtoi(sp[cardIndex]);
|
const int card = wtoi(sp[cardIndex]);
|
||||||
int time = oe.getRelativeTime(processedTime);
|
const int time = oe.getRelativeTime(processedTime);
|
||||||
|
|
||||||
if (card>0) {
|
if (card>0) {
|
||||||
PunchInfo pi;
|
PunchInfo pi;
|
||||||
pi.card = card;
|
pi.card = card;
|
||||||
pi.time = time;
|
pi.time = time;
|
||||||
string pd(processedDate.begin(), processedDate.end());
|
//string pd(processedDate.begin(), processedDate.end());
|
||||||
strncpy_s(pi.date, sizeof(pi.date), pd.c_str(), 26);
|
string pd = gdioutput::narrow(processedDate);
|
||||||
|
strncpy_s(pi.date, pd.c_str(), 26);
|
||||||
pi.date[26] = 0;
|
pi.date[26] = 0;
|
||||||
punches.push_back(pi);
|
punches.push_back(pi);
|
||||||
nimport++;
|
nimport++;
|
||||||
@ -1204,7 +1204,7 @@ void csvparser::parse(const wstring &file, list< vector<wstring> > &data) {
|
|||||||
string rbf;
|
string rbf;
|
||||||
|
|
||||||
if (!fin.good())
|
if (!fin.good())
|
||||||
throw meosException("Failed to read file");
|
throw meosException(L"Failed to read file, " + file);
|
||||||
|
|
||||||
bool isUTF8 = false;
|
bool isUTF8 = false;
|
||||||
bool firstLine = true;
|
bool firstLine = true;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -162,10 +162,11 @@ ClassResultFraction = Fraction of class complete
|
|||||||
ClassStartName = Start name
|
ClassStartName = Start name
|
||||||
ClassStartTime = Class, start time, name
|
ClassStartTime = Class, start time, name
|
||||||
ClassStartTimeClub = Class, start time, club
|
ClassStartTimeClub = Class, start time, club
|
||||||
|
ClubClassStartTime = Club, class, start time
|
||||||
ClassTotalResult = Class, total result
|
ClassTotalResult = Class, total result
|
||||||
Club = Club
|
Club = Club
|
||||||
ClubName = Club
|
ClubName = Club
|
||||||
ClubRunner = Club (competitor)
|
ClubRunner = Club (Competitors)
|
||||||
CmpDate = Competition date
|
CmpDate = Competition date
|
||||||
CmpName = Competition name
|
CmpName = Competition name
|
||||||
CourseClimb = Course climb
|
CourseClimb = Course climb
|
||||||
@ -282,7 +283,7 @@ FilterHasCard = With card
|
|||||||
FilterNoCard = Without card
|
FilterNoCard = Without card
|
||||||
FilterNotVacant = Not vacant
|
FilterNotVacant = Not vacant
|
||||||
FilterOnlyVacant = Only vacant
|
FilterOnlyVacant = Only vacant
|
||||||
FilterRentCard = Borrowed card
|
FilterRentCard = Hired card
|
||||||
FilterResult = With result
|
FilterResult = With result
|
||||||
FilterStarted = Has started
|
FilterStarted = Has started
|
||||||
Filtrering = Filtering
|
Filtrering = Filtering
|
||||||
@ -357,10 +358,10 @@ Hjälp = Help
|
|||||||
Hoppar över stafettklass: X = Skipping relay class: X
|
Hoppar över stafettklass: X = Skipping relay class: X
|
||||||
Huvudlista = Main list
|
Huvudlista = Main list
|
||||||
Hyravgift = Card hire
|
Hyravgift = Card hire
|
||||||
Hyrbricka = Borrowed card
|
Hyrbricka = Hired card
|
||||||
Hyrbricksrapport = Report with Borrowed Cards
|
Hyrbricksrapport = Report with Hired Cards
|
||||||
Hyrbricksrapport - %s = Borrowed Cards - %s
|
Hyrbricksrapport - %s = Hired Cards - %s
|
||||||
Hyrd = Borrowed
|
Hyrd = Hired
|
||||||
Hämta (efter)anmälningar från Eventor = Fetch (late) entries from Eventor
|
Hämta (efter)anmälningar från Eventor = Fetch (late) entries from Eventor
|
||||||
Hämta data från Eventor = Fetch Data from Eventor
|
Hämta data från Eventor = Fetch Data from Eventor
|
||||||
Hämta efteranmälningar = Fetch Late Entries
|
Hämta efteranmälningar = Fetch Late Entries
|
||||||
@ -393,7 +394,7 @@ Importera = Import
|
|||||||
Importera IOF (xml) = Import IOF (xml)
|
Importera IOF (xml) = Import IOF (xml)
|
||||||
Importera anmälningar = Import Entries
|
Importera anmälningar = Import Entries
|
||||||
Importera banor = Import Courses
|
Importera banor = Import Courses
|
||||||
Importera banor/klasser = Import courses/classes
|
Importera banor/klasser = Import Courses and Classes
|
||||||
Importera en tävling från fil = Import competition from file
|
Importera en tävling från fil = Import competition from file
|
||||||
Importera fil = Import File
|
Importera fil = Import File
|
||||||
Importera från OCAD = Import from OCAD
|
Importera från OCAD = Import from OCAD
|
||||||
@ -1041,7 +1042,7 @@ TeamClub = Team's club
|
|||||||
TeamLegTimeAfter = Team's time behind on leg
|
TeamLegTimeAfter = Team's time behind on leg
|
||||||
TeamLegTimeStatus = Team's time / status on leg
|
TeamLegTimeStatus = Team's time / status on leg
|
||||||
TeamName = Team name
|
TeamName = Team name
|
||||||
TeamPlace = Team's place
|
TeamPlace = Team's place after leg
|
||||||
TeamRogainingPoint = Team's rogaining points
|
TeamRogainingPoint = Team's rogaining points
|
||||||
TeamRunner = Name of team member
|
TeamRunner = Name of team member
|
||||||
TeamRunnerCard = Card number of team member
|
TeamRunnerCard = Card number of team member
|
||||||
@ -1242,7 +1243,7 @@ Välj vilka kolumner du vill visa = Choose columns to show
|
|||||||
Välj vy = Choose view
|
Välj vy = Choose view
|
||||||
Välkommen till MeOS = Welcome to MeOS
|
Välkommen till MeOS = Welcome to MeOS
|
||||||
Vänligen betala senast = Please pay at latest
|
Vänligen betala senast = Please pay at latest
|
||||||
Vänligen återlämna hyrbrickan = Please return your borrowed card
|
Vänligen återlämna hyrbrickan = Please return your hired card
|
||||||
Växling = Changeover
|
Växling = Changeover
|
||||||
Webb = Web Document
|
Webb = Web Document
|
||||||
Webbdokument = Web document
|
Webbdokument = Web document
|
||||||
@ -1319,7 +1320,7 @@ help:41072 = Select a punch from the list to change or remove it. You can add mi
|
|||||||
help:41641 = Enter a first start time and start interval. Draw random gives an unconditionally random start order. Swedish draw method uses special rules to distribute runners from the same club. Clumped start means the whole class starts in small groups during the specified interval (extended mass start). In the field leg, you can specify which leg is to be drawn, if the class has several.
|
help:41641 = Enter a first start time and start interval. Draw random gives an unconditionally random start order. Swedish draw method uses special rules to distribute runners from the same club. Clumped start means the whole class starts in small groups during the specified interval (extended mass start). In the field leg, you can specify which leg is to be drawn, if the class has several.
|
||||||
help:425188 = You can handle runners that didn't start automatically by reading out SI stations (clear/check/start/controls) in SportIdent Config+. Save the readout as a semi colon separated text file and import this file into MeOS. Runners in this import get a registration. Then you can give DNS status to all runners without registration. If you later import more runners, you can reset the status (from DNS to Unknown) on the runners now imported.
|
help:425188 = You can handle runners that didn't start automatically by reading out SI stations (clear/check/start/controls) in SportIdent Config+. Save the readout as a semi colon separated text file and import this file into MeOS. Runners in this import get a registration. Then you can give DNS status to all runners without registration. If you later import more runners, you can reset the status (from DNS to Unknown) on the runners now imported.
|
||||||
info:readoutbase = Activate the SI unit by selecting its COM-port, or by searching for installed SI units. Press Information to get status for the selected port.\n\nInteractive readout lets you directly handle problems, such as wrong card number. Do not use this option when runners with problems are handled separately.\n\nThe runner database is used if you want to automatically add new runners. The punches are used to find (guess) the right class.
|
info:readoutbase = Activate the SI unit by selecting its COM-port, or by searching for installed SI units. Press Information to get status for the selected port.\n\nInteractive readout lets you directly handle problems, such as wrong card number. Do not use this option when runners with problems are handled separately.\n\nThe runner database is used if you want to automatically add new runners. The punches are used to find (guess) the right class.
|
||||||
info:readoutmore = Sound selection lets you enable sound signals to be played back on reading out a card.\n\nShow readout in window opens a new window designed to be shown on a screen turned towards the competitor.\n\nIf you have connected a punching unit (for example finish punch) you can decide if you want to accept start, radio, or finish punches. This is a filter to prevent (for example) unexpected start punches from being recieved by mistake, which could overwrite the drawn starting time.
|
info:readoutmore = Lock the function to prevent accidental changes.\n\nSound selection lets you enable sound signals to be played back on reading out a card.\n\nOpen Readout Window shows a new window designed to be shown on a screen turned towards the competitor, showing information about the last readout.\n\nSeveral races per competitor can be used if you are allowed do several attempts on the course. A new entry is created for each readout.
|
||||||
help:50431 = You are now connected to a server. To open a competition on the server, select it in the list and click open. Do add a competition to the server, open the competition locally and select upload. When you have opened a competition on the server, you will see all other connected MeOS clients.
|
help:50431 = You are now connected to a server. To open a competition on the server, select it in the list and click open. Do add a competition to the server, open the competition locally and select upload. When you have opened a competition on the server, you will see all other connected MeOS clients.
|
||||||
help:52726 = Connect to a server below.\n\nInstallation\nDownload and install MySQL 5 (Community Edition) from www.mysql.com. You can use default settings. It is only necessary to install MySQL on the computer acting server. When MySQL is installed, start MySQL Command Line Client and create a user account for MeOS. You write like this:\n\n> CREATE USER meos;\nGRANT ALL ON *.* TO meos;\n\nYou have now created a user meos with no password. Enter the name of the server below (you may have to configure firewalls to let through the traffic).\n\nAs an alternative you can use the built-in root account of MySQL. User name is 'root' and password is the one you provided when installing MySQL.
|
help:52726 = Connect to a server below.\n\nInstallation\nDownload and install MySQL 5 (Community Edition) from www.mysql.com. You can use default settings. It is only necessary to install MySQL on the computer acting server. When MySQL is installed, start MySQL Command Line Client and create a user account for MeOS. You write like this:\n\n> CREATE USER meos;\nGRANT ALL ON *.* TO meos;\n\nYou have now created a user meos with no password. Enter the name of the server below (you may have to configure firewalls to let through the traffic).\n\nAs an alternative you can use the built-in root account of MySQL. User name is 'root' and password is the one you provided when installing MySQL.
|
||||||
help:5422 = Found no SI unit. Are they connected and started?
|
help:5422 = Found no SI unit. Are they connected and started?
|
||||||
@ -2596,3 +2597,64 @@ Duplicerad nummerlapp: X, Y = Duplicated bib: X, Y
|
|||||||
Saknat lag mellan X och Y = Missing team between X and Y
|
Saknat lag mellan X och Y = Missing team between X and Y
|
||||||
Lag utan nummerlapp: X = Team with no bib: X
|
Lag utan nummerlapp: X = Team with no bib: X
|
||||||
Brickavläsning = Card Readout
|
Brickavläsning = Card Readout
|
||||||
|
Ett långt tävlingsnamn kan ge oväntad nerskalning av utskrifter = A long competition name may cause unwanted downscale of printed lists
|
||||||
|
Ingen reducerad avgift = No reduced fee
|
||||||
|
Reducerad avgift = Reduced fee
|
||||||
|
Reducerad avgift för = Reduced fee for
|
||||||
|
Unga, till och med X år = Young people, up to X years
|
||||||
|
Ungdomar och äldre kan få reducerad avgift = Elder and younger people can have a reduced fee
|
||||||
|
Äldre, från och med X år = Elders, X years and above
|
||||||
|
Programmera stationen utan AUTOSEND = Program the unit with AUTO SEND off
|
||||||
|
Aktivera stöd för tiondels sekunder = Activate support for subsecond timing.
|
||||||
|
Automatisk hyrbrickshantering genom registrerade hyrbrickor = Automatic handling of hired cards using pre-registered card numbers
|
||||||
|
prefsAutoTieRent = Automatic handling of hired cards
|
||||||
|
prefsExpResFilename = Default export filename
|
||||||
|
prefsExpTypeIOF = Default export type
|
||||||
|
prefsExpWithRaceNo = Include race number when exporting
|
||||||
|
Ignorerade X duplikat = Ignored X duplicates
|
||||||
|
info:customsplitprint = You can use a cusom list for the split printout. Design the list and use the function 'For Split Times' in the list editor to make changes for split printout.\n\nYou can control the list to use per class by using the table mode.
|
||||||
|
Sträcktidslista = Split time list
|
||||||
|
info:nosplitprint = Cannot load the specified list.\n\nUsing defaults instead.
|
||||||
|
Välj deltagare för förhandsgranskning = Select competitor for preview
|
||||||
|
Inkludera bomanalys = Include analysis of lost time
|
||||||
|
Inkludera individuellt resultat = Include indiviual result
|
||||||
|
Inkludera sträcktider = Include splits
|
||||||
|
Inkludera tempo = Include tempo
|
||||||
|
Skapa en klass för varje bana = Create a class for each course
|
||||||
|
Ingen[competition] = None
|
||||||
|
Basera på en tidigare tävling = Base on existing competition
|
||||||
|
Baserad på X = Based on X
|
||||||
|
info:multiple_start = A competitor may do multiple starts with the same card. Automatic new entry for each readout.
|
||||||
|
Flera starter per deltagare = Several races per competitor
|
||||||
|
Image = Image
|
||||||
|
NumEntries = Number of entries
|
||||||
|
NumStarts = Numer of starts
|
||||||
|
TotalRunLength = Total running distance
|
||||||
|
TotalRunTime = Total running time
|
||||||
|
X stämplingar = X punches
|
||||||
|
RunnerBirthDate = Birth date
|
||||||
|
Avbryt inläsning = Cancel readout
|
||||||
|
Spara oparad bricka = Save unpaired card
|
||||||
|
warn:changeid = The field External Id is usually used to match entities with other databases (such as entry, result, or economy systems). If you make incomaptible changes, various and hard-to-understand problems might arise.
|
||||||
|
Cannot represent ID X = Cannot represent ID 'X'
|
||||||
|
Batteridatum = Battery date
|
||||||
|
Enhet = Unit
|
||||||
|
Öppna avläsningsfönster = Open readout window
|
||||||
|
info:readoutwindow = The readout window shows information on the latest card readout.
|
||||||
|
info:mapcontrol = MeOS is unable to determine what function a unit has unless it is directly attached to the computer. Therefore the programmed punch code is used to determine the type. You can control the interpretation below. Numbers higher than 30 are always interpreted as controls.\n\nBe careful when using start punches; they may permanently overwrite the drawn starting time.
|
||||||
|
Checkenhet = Check unit
|
||||||
|
Målenhet = Finish unit
|
||||||
|
Startenhet = Start unit
|
||||||
|
Du kan justera tiden för en viss enhet = You can adjust the time for a single unit
|
||||||
|
ClubTeam = Club (Teams)
|
||||||
|
CourseNumber = Course number
|
||||||
|
Enhetskod = Unit code
|
||||||
|
Tolkning av radiostämplingar med okänd typ = Interpretation of punches of unknown type
|
||||||
|
TeamCourseName = Course name for team/leg
|
||||||
|
TeamCourseNumber = Course number for team/leg
|
||||||
|
TeamLegName = Namn på sträcka
|
||||||
|
Du måste ange minst två gafflingsvarienater = You must specify at least 2 variants
|
||||||
|
Max antal gaffllingsvarianter att skapa = Maximum number of forking keys to create
|
||||||
|
Det uppskattade antalet startade lag i klassen är ett lämpligt värde = The estimated number of teams in the class is a suitable value
|
||||||
|
Lägg till bild = Add image
|
||||||
|
Använd listan för sträcktidsutskrift = Use list for split time printing
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -61,6 +61,7 @@ constexpr int absolutePosition = 1 << 17;
|
|||||||
constexpr int skipBoundingBox = 1 << 18;
|
constexpr int skipBoundingBox = 1 << 18;
|
||||||
constexpr int hiddenText = 1 << 19;
|
constexpr int hiddenText = 1 << 19;
|
||||||
constexpr int textLimitEllipsis = 1 << 20;
|
constexpr int textLimitEllipsis = 1 << 20;
|
||||||
|
constexpr int imageNoUpdatePos = 1 << 21;
|
||||||
|
|
||||||
enum GDICOLOR {
|
enum GDICOLOR {
|
||||||
colorBlack = RGB(0, 0, 0),
|
colorBlack = RGB(0, 0, 0),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
675
code/gdioutput.h
675
code/gdioutput.h
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -99,7 +99,7 @@ class AutoCompleteInfo;
|
|||||||
|
|
||||||
class Recorder;
|
class Recorder;
|
||||||
|
|
||||||
class gdioutput {
|
class gdioutput {
|
||||||
protected:
|
protected:
|
||||||
string tag;
|
string tag;
|
||||||
// Database error state warning
|
// Database error state warning
|
||||||
@ -109,30 +109,30 @@ protected:
|
|||||||
bool useTables;
|
bool useTables;
|
||||||
// Set to true when in test mode
|
// Set to true when in test mode
|
||||||
bool isTestMode;
|
bool isTestMode;
|
||||||
|
|
||||||
bool highContrast;
|
bool highContrast;
|
||||||
|
|
||||||
void deleteFonts();
|
void deleteFonts();
|
||||||
void constructor(double _scale);
|
void constructor(double _scale);
|
||||||
|
|
||||||
void updateStringPosCache();
|
void updateStringPosCache();
|
||||||
vector<TextInfo *> shownStrings;
|
vector<TextInfo*> shownStrings;
|
||||||
|
|
||||||
void enableCheckBoxLink(TextInfo &ti, bool enable);
|
void enableCheckBoxLink(TextInfo& ti, bool enable);
|
||||||
|
|
||||||
//void CalculateCS(TextInfo &text);
|
//void CalculateCS(TextInfo &text);
|
||||||
//void printPage(PrinterObject &po, int StartY, int &EndY, bool calculate);
|
//void printPage(PrinterObject &po, int StartY, int &EndY, bool calculate);
|
||||||
void printPage(PrinterObject &po, const PageInfo &pageInfo, RenderedPage &page);
|
void printPage(PrinterObject& po, const PageInfo& pageInfo, RenderedPage& page);
|
||||||
bool startDoc(PrinterObject &po);
|
bool startDoc(PrinterObject& po);
|
||||||
|
|
||||||
bool getSelectedItem(ListBoxInfo &lbi);
|
bool getSelectedItem(ListBoxInfo& lbi);
|
||||||
bool doPrint(PrinterObject &po, PageInfo &pageInfo, pEvent oe, bool respectPageBreak);
|
bool doPrint(PrinterObject& po, PageInfo& pageInfo, pEvent oe, bool respectPageBreak);
|
||||||
|
|
||||||
PrinterObject *po_default;
|
PrinterObject* po_default;
|
||||||
|
|
||||||
void restoreInternal(const RestoreInfo &ri);
|
void restoreInternal(const RestoreInfo& ri);
|
||||||
|
|
||||||
void drawCloseBox(HDC hDC, RECT &Close, bool pressed);
|
void drawCloseBox(HDC hDC, RECT& Close, bool pressed);
|
||||||
|
|
||||||
void setFontCtrl(HWND hWnd);
|
void setFontCtrl(HWND hWnd);
|
||||||
|
|
||||||
@ -145,14 +145,20 @@ protected:
|
|||||||
//by avoiding to loop through complete TL.
|
//by avoiding to loop through complete TL.
|
||||||
list<TextInfo>::iterator itTL;
|
list<TextInfo>::iterator itTL;
|
||||||
|
|
||||||
|
// References into TL for all images
|
||||||
|
vector<TextInfo*> imageReferences;
|
||||||
|
|
||||||
|
// Needed after removing images to clear unused references
|
||||||
|
void updateImageReferences();
|
||||||
|
|
||||||
list<ButtonInfo> BI;
|
list<ButtonInfo> BI;
|
||||||
unordered_map<HWND, ButtonInfo *> biByHwnd;
|
unordered_map<HWND, ButtonInfo*> biByHwnd;
|
||||||
|
|
||||||
list<InputInfo> II;
|
list<InputInfo> II;
|
||||||
unordered_map<HWND, InputInfo *> iiByHwnd;
|
unordered_map<HWND, InputInfo*> iiByHwnd;
|
||||||
|
|
||||||
list<ListBoxInfo> LBI;
|
list<ListBoxInfo> LBI;
|
||||||
unordered_map<HWND, ListBoxInfo *> lbiByHwnd;
|
unordered_map<HWND, ListBoxInfo*> lbiByHwnd;
|
||||||
|
|
||||||
list<DataStore> DataInfo;
|
list<DataStore> DataInfo;
|
||||||
list<EventInfo> Events;
|
list<EventInfo> Events;
|
||||||
@ -160,7 +166,7 @@ protected:
|
|||||||
list<TableInfo> Tables;
|
list<TableInfo> Tables;
|
||||||
list<TimerInfo> timers;
|
list<TimerInfo> timers;
|
||||||
|
|
||||||
Toolbar *toolbar;
|
Toolbar* toolbar;
|
||||||
ToolList toolTips;
|
ToolList toolTips;
|
||||||
|
|
||||||
map<string, RestoreInfo> restorePoints;
|
map<string, RestoreInfo> restorePoints;
|
||||||
@ -191,10 +197,10 @@ protected:
|
|||||||
mutable map<pair<int, wstring>, int> fontHeightCache;
|
mutable map<pair<int, wstring>, int> fontHeightCache;
|
||||||
|
|
||||||
map<wstring, GDIImplFontSet> fonts;
|
map<wstring, GDIImplFontSet> fonts;
|
||||||
const GDIImplFontSet &getCurrentFont() const;
|
const GDIImplFontSet& getCurrentFont() const;
|
||||||
const GDIImplFontSet &getFont(const wstring &font) const;
|
const GDIImplFontSet& getFont(const wstring& font) const;
|
||||||
const GDIImplFontSet &loadFont(const wstring &font);
|
const GDIImplFontSet& loadFont(const wstring& font);
|
||||||
mutable const GDIImplFontSet *currentFontSet;
|
mutable const GDIImplFontSet* currentFontSet;
|
||||||
|
|
||||||
int MaxX;
|
int MaxX;
|
||||||
int MaxY;
|
int MaxY;
|
||||||
@ -203,16 +209,25 @@ protected:
|
|||||||
int SX;
|
int SX;
|
||||||
int SY;
|
int SY;
|
||||||
|
|
||||||
int Direction;
|
enum class FlowDirection {
|
||||||
|
Down,
|
||||||
|
Right,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
|
FlowDirection flowDirection;
|
||||||
|
|
||||||
int OffsetY; //Range 0 -- MaxY
|
int OffsetY; //Range 0 -- MaxY
|
||||||
int OffsetX; //Range 0 -- MaxX
|
int OffsetX; //Range 0 -- MaxX
|
||||||
|
|
||||||
|
// Maximum height of a text block of the current view.
|
||||||
|
int maxTextBlockHeight = 0;
|
||||||
|
|
||||||
//Set to true if we should not update window during "addText" operations
|
//Set to true if we should not update window during "addText" operations
|
||||||
bool manualUpdate;
|
bool manualUpdate;
|
||||||
|
|
||||||
LRESULT ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam);
|
LRESULT ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam);
|
||||||
void getWindowText(HWND hWnd, wstring &text);
|
void getWindowText(HWND hWnd, wstring& text);
|
||||||
double scale;
|
double scale;
|
||||||
HFONT getGUIFont() const;
|
HFONT getGUIFont() const;
|
||||||
|
|
||||||
@ -223,18 +238,18 @@ protected:
|
|||||||
mutable DWORD lastColor;
|
mutable DWORD lastColor;
|
||||||
mutable wstring lastFont;
|
mutable wstring lastFont;
|
||||||
|
|
||||||
void initCommon(double scale, const wstring &font);
|
void initCommon(double scale, const wstring& font);
|
||||||
|
|
||||||
void processButtonMessage(ButtonInfo &bi, WPARAM wParam);
|
void processButtonMessage(ButtonInfo& bi, WPARAM wParam);
|
||||||
void processEditMessage(InputInfo &bi, WPARAM wParam);
|
void processEditMessage(InputInfo& bi, WPARAM wParam);
|
||||||
void processComboMessage(ListBoxInfo &bi, WPARAM wParam);
|
void processComboMessage(ListBoxInfo& bi, WPARAM wParam);
|
||||||
void processListMessage(ListBoxInfo &bi, WPARAM wParam);
|
void processListMessage(ListBoxInfo& bi, WPARAM wParam);
|
||||||
|
|
||||||
void doEnter();
|
void doEnter();
|
||||||
void doEscape();
|
void doEscape();
|
||||||
bool doUpDown(int direction);
|
bool doUpDown(int direction);
|
||||||
|
|
||||||
FixedTabs *tabs;
|
FixedTabs* tabs;
|
||||||
|
|
||||||
wstring currentFont;
|
wstring currentFont;
|
||||||
vector< GDIImplFontEnum > enumeratedFonts;
|
vector< GDIImplFontEnum > enumeratedFonts;
|
||||||
@ -265,7 +280,7 @@ protected:
|
|||||||
wstring str;
|
wstring str;
|
||||||
bool reached;
|
bool reached;
|
||||||
|
|
||||||
ScreenStringInfo(const RECT &r, const wstring &s) {
|
ScreenStringInfo(const RECT& r, const wstring& s) {
|
||||||
rc = r;
|
rc = r;
|
||||||
str = s;
|
str = s;
|
||||||
reached = false;
|
reached = false;
|
||||||
@ -283,146 +298,156 @@ protected:
|
|||||||
friend class TestMeOS;
|
friend class TestMeOS;
|
||||||
|
|
||||||
// Recorder, the second member is true if the recorder is owned and should be deleted
|
// Recorder, the second member is true if the recorder is owned and should be deleted
|
||||||
pair<Recorder *, bool> recorder;
|
pair<Recorder*, bool> recorder;
|
||||||
list< pair<const SubCommand *, string> > subCommands;
|
list< pair<const SubCommand*, string> > subCommands;
|
||||||
|
|
||||||
shared_ptr<AnimationData> animationData;
|
shared_ptr<AnimationData> animationData;
|
||||||
|
|
||||||
shared_ptr<AutoCompleteInfo> autoCompleteInfo;
|
shared_ptr<AutoCompleteInfo> autoCompleteInfo;
|
||||||
|
|
||||||
wstring delayedAlert;
|
wstring delayedAlert;
|
||||||
|
|
||||||
|
struct GuiMeasure {
|
||||||
|
int height = 0;
|
||||||
|
int extraX = 0;
|
||||||
|
int letterWidth = 0;
|
||||||
|
float avgCharWidth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable shared_ptr<GuiMeasure> guiMeasure;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AutoCompleteInfo &addAutoComplete(const string &key);
|
AutoCompleteInfo& addAutoComplete(const string& key);
|
||||||
void clearAutoComplete(const string &key);
|
void clearAutoComplete(const string& key);
|
||||||
bool hasAutoComplete() const { return autoCompleteInfo != nullptr; }
|
bool hasAutoComplete() const { return autoCompleteInfo != nullptr; }
|
||||||
// Return the bounding dimension of the desktop
|
// Return the bounding dimension of the desktop
|
||||||
void getVirtualScreenSize(RECT &rc);
|
void getVirtualScreenSize(RECT& rc);
|
||||||
|
|
||||||
void getWindowsPosition(RECT &rc) const;
|
void getWindowsPosition(RECT& rc) const;
|
||||||
void setWindowsPosition(const RECT &rc);
|
void setWindowsPosition(const RECT& rc);
|
||||||
|
|
||||||
|
|
||||||
void initRecorder(Recorder *rec);
|
|
||||||
Recorder &getRecorder();
|
|
||||||
string dbPress(const string &id, int extra);
|
|
||||||
string dbPress(const string &id, const char *extra);
|
|
||||||
|
|
||||||
string dbSelect(const string &id, int data);
|
|
||||||
void dbInput(const string &id, const string &test);
|
|
||||||
void dbCheck(const string &id, bool state);
|
|
||||||
string dbClick(const string &id, int extra);
|
|
||||||
void dbDblClick(const string &id, int data);
|
|
||||||
|
|
||||||
void dbRegisterSubCommand(const SubCommand *cmd, const string &action);
|
void initRecorder(Recorder* rec);
|
||||||
|
Recorder& getRecorder();
|
||||||
|
string dbPress(const string& id, int extra);
|
||||||
|
string dbPress(const string& id, const char* extra);
|
||||||
|
|
||||||
|
string dbSelect(const string& id, int data);
|
||||||
|
void dbInput(const string& id, const string& test);
|
||||||
|
void dbCheck(const string& id, bool state);
|
||||||
|
string dbClick(const string& id, int extra);
|
||||||
|
void dbDblClick(const string& id, int data);
|
||||||
|
|
||||||
|
void dbRegisterSubCommand(const SubCommand* cmd, const string& action);
|
||||||
void runSubCommand();
|
void runSubCommand();
|
||||||
|
|
||||||
// Add the next answer for a dialog popup
|
// Add the next answer for a dialog popup
|
||||||
void dbPushDialogAnswer(const string &answer);
|
void dbPushDialogAnswer(const string& answer);
|
||||||
mutable list<string> cmdAnswers;
|
mutable list<string> cmdAnswers;
|
||||||
|
|
||||||
int dbGetStringCount(const string &str, bool subString) const;
|
int dbGetStringCount(const string& str, bool subString) const;
|
||||||
|
|
||||||
// Ensure list of stored answers is empty
|
// Ensure list of stored answers is empty
|
||||||
void clearDialogAnswers(bool checkEmpty);
|
void clearDialogAnswers(bool checkEmpty);
|
||||||
|
|
||||||
void internalSelect(ListBoxInfo &bi);
|
void internalSelect(ListBoxInfo& bi);
|
||||||
|
|
||||||
bool isTest() const {return isTestMode;}
|
bool isTest() const { return isTestMode; }
|
||||||
const string &getTag() const {return tag;}
|
const string& getTag() const { return tag; }
|
||||||
bool hasTag(const string &t) const {return tag == t;}
|
bool hasTag(const string& t) const { return tag == t; }
|
||||||
static const wstring &recodeToWide(const string &input);
|
static const wstring& recodeToWide(const string& input);
|
||||||
static const string &recodeToNarrow(const wstring &input);
|
static const string& recodeToNarrow(const wstring& input);
|
||||||
|
|
||||||
static const wstring &widen(const string &input);
|
static const wstring& widen(const string& input);
|
||||||
static const string &narrow(const wstring &input);
|
static const string& narrow(const wstring& input);
|
||||||
|
|
||||||
static const string &toUTF8(const wstring &input);
|
static const string& toUTF8(const wstring& input);
|
||||||
static const wstring &fromUTF8(const string &input);
|
static const wstring& fromUTF8(const string& input);
|
||||||
|
|
||||||
//void setEncoding(FontEncoding encoding);
|
//void setEncoding(FontEncoding encoding);
|
||||||
//FontEncoding getEncoding() const;
|
//FontEncoding getEncoding() const;
|
||||||
|
|
||||||
void getFontInfo(const TextInfo &ti, FontInfo &fi) const;
|
void getFontInfo(const TextInfo& ti, FontInfo& fi) const;
|
||||||
|
|
||||||
/** Return true if rendering text should be skipped for
|
/** Return true if rendering text should be skipped for
|
||||||
this format. */
|
this format. */
|
||||||
static bool skipTextRender(int format);
|
static bool skipTextRender(int format);
|
||||||
|
|
||||||
const list<TextInfo> &getTL() const {return TL;}
|
const list<TextInfo>& getTL() const { return TL; }
|
||||||
|
|
||||||
void getEnumeratedFonts(vector< pair<wstring, size_t> > &output) const;
|
void getEnumeratedFonts(vector< pair<wstring, size_t> >& output) const;
|
||||||
const wstring &getFontName(int id);
|
const wstring& getFontName(int id);
|
||||||
double getRelativeFontScale(gdiFonts font, const wchar_t *fontFace) const;
|
double getRelativeFontScale(gdiFonts font, const wchar_t* fontFace) const;
|
||||||
|
|
||||||
bool isFullScreen() const {return fullScreen;}
|
bool isFullScreen() const { return fullScreen; }
|
||||||
void setFullScreen(bool useFullScreen);
|
void setFullScreen(bool useFullScreen);
|
||||||
void setColorMode(DWORD bgColor1, DWORD bgColor2 = -1,
|
void setColorMode(DWORD bgColor1, DWORD bgColor2 = -1,
|
||||||
DWORD fgColor = -1, const wstring &bgImage = L"");
|
DWORD fgColor = -1, const wstring& bgImage = L"");
|
||||||
|
|
||||||
DWORD getFGColor() const;
|
DWORD getFGColor() const;
|
||||||
DWORD getBGColor() const;
|
DWORD getBGColor() const;
|
||||||
DWORD getBGColor2() const;
|
DWORD getBGColor2() const;
|
||||||
const wstring &getBGImage() const;
|
const wstring& getBGImage() const;
|
||||||
|
|
||||||
void setAnimationMode(const shared_ptr<AnimationData> &mode);
|
void setAnimationMode(const shared_ptr<AnimationData>& mode);
|
||||||
|
|
||||||
void setAutoScroll(double speed);
|
void setAutoScroll(double speed);
|
||||||
void getAutoScroll(double &speed, double &pos) const;
|
void getAutoScroll(double& speed, double& pos) const;
|
||||||
void storeAutoPos(double pos);
|
void storeAutoPos(double pos);
|
||||||
int getAutoScrollDir() const {return (autoSpeed > 0 ? 1:-1);}
|
int getAutoScrollDir() const { return (autoSpeed > 0 ? 1 : -1); }
|
||||||
int setHighContrastMaxWidth();
|
int setHighContrastMaxWidth();
|
||||||
void hideBackground(bool hide) {hideBG = hide;}
|
void hideBackground(bool hide) { hideBG = hide; }
|
||||||
HWND getToolbarWindow() const;
|
HWND getToolbarWindow() const;
|
||||||
bool hasToolbar() const;
|
bool hasToolbar() const;
|
||||||
void activateToolbar(bool active);
|
void activateToolbar(bool active);
|
||||||
|
|
||||||
void processToolbarMessage(const string &id, Table *data);
|
void processToolbarMessage(const string& id, Table* data);
|
||||||
|
|
||||||
void synchronizeListScroll(const string &id1, const string &id2);
|
void synchronizeListScroll(const string& id1, const string& id2);
|
||||||
|
|
||||||
FixedTabs &getTabs();
|
FixedTabs& getTabs();
|
||||||
|
|
||||||
// True if up/down is locked, i.e, don't move page
|
// True if up/down is locked, i.e, don't move page
|
||||||
bool lockUpDown;
|
bool lockUpDown;
|
||||||
|
|
||||||
|
|
||||||
double getScale() const {return scale;}
|
double getScale() const { return scale; }
|
||||||
void enableEditControls(bool enable, bool processAll = false);
|
void enableEditControls(bool enable, bool processAll = false);
|
||||||
|
|
||||||
bool hasEditControl() const;
|
bool hasEditControl() const;
|
||||||
|
|
||||||
void setFont(int size, const wstring &font);
|
void setFont(int size, const wstring& font);
|
||||||
|
|
||||||
int getButtonHeight() const;
|
int getButtonHeight() const;
|
||||||
int scaleLength(int input) const {return int(scale*input + 0.5);}
|
int scaleLength(int input) const { return int(scale * input + 0.5); }
|
||||||
|
|
||||||
// Fill in current printer settings
|
// Fill in current printer settings
|
||||||
void fetchPrinterSettings(PrinterObject &po) const;
|
void fetchPrinterSettings(PrinterObject& po) const;
|
||||||
|
|
||||||
void tableCB(ButtonInfo &bu, Table *t);
|
void tableCB(ButtonInfo& bu, Table* t);
|
||||||
|
|
||||||
wchar_t *getExtra(const char *id) const;
|
wchar_t* getExtra(const char* id) const;
|
||||||
int getExtraInt(const char *id) const;
|
int getExtraInt(const char* id) const;
|
||||||
|
|
||||||
void enableTables();
|
void enableTables();
|
||||||
void disableTables();
|
void disableTables();
|
||||||
|
|
||||||
void pasteText(const char *id);
|
void pasteText(const char* id);
|
||||||
void print(pEvent oe, Table *t = 0, bool printMeOSHeader = true, bool noMargin = false, bool respectPageBreak = true);
|
void print(pEvent oe, Table* t = nullptr, bool printMeOSHeader = true, bool noMargin = false, bool respectPageBreak = true);
|
||||||
void print(PrinterObject &po, pEvent oe, bool printMeOSHeader = true, bool noMargin=false, bool respectPageBreak = true);
|
void print(PrinterObject& po, pEvent oe, bool printMeOSHeader = true, bool noMargin = false, bool respectPageBreak = true);
|
||||||
void printSetup(PrinterObject &po);
|
void printSetup(PrinterObject& po);
|
||||||
void destroyPrinterDC(PrinterObject &po);
|
void destroyPrinterDC(PrinterObject& po);
|
||||||
|
|
||||||
void setSelection(const string &id, const set<int> &selection);
|
void setSelection(const string& id, const set<int>& selection);
|
||||||
void setSelection(const wstring &id, const set<int> &selection) {
|
void setSelection(const wstring& id, const set<int>& selection) {
|
||||||
setSelection(narrow(id), selection);
|
setSelection(narrow(id), selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSelection(const string &id, set<int> &selection);
|
|
||||||
|
|
||||||
HWND getHWNDTarget() const {return hWndTarget;}
|
void getSelection(const string& id, set<int>& selection);
|
||||||
HWND getHWNDMain() const {return hWndAppMain;}
|
|
||||||
|
HWND getHWNDTarget() const { return hWndTarget; }
|
||||||
|
HWND getHWNDMain() const { return hWndAppMain; }
|
||||||
|
|
||||||
void scrollToBottom();
|
void scrollToBottom();
|
||||||
void scrollTo(int x, int y);
|
void scrollTo(int x, int y);
|
||||||
@ -430,84 +455,88 @@ public:
|
|||||||
|
|
||||||
void selectTab(int Id);
|
void selectTab(int Id);
|
||||||
|
|
||||||
void addTable(const shared_ptr<Table> &table, int x, int y);
|
void addTable(const shared_ptr<Table>& table, int x, int y);
|
||||||
Table &getTable() const; //Get the (last) table. If needed, add support for named tables...
|
Table& getTable() const; //Get the (last) table. If needed, add support for named tables...
|
||||||
|
|
||||||
|
|
||||||
ToolInfo &addToolTip(const string &id, const wstring &tip, HWND hWnd, RECT *rc=0);
|
ToolInfo& addToolTip(const string& id, const wstring& tip, HWND hWnd, RECT* rc = nullptr);
|
||||||
ToolInfo *getToolTip(const string &id);
|
ToolInfo* getToolTip(const string& id);
|
||||||
ToolInfo &updateToolTip(const string &id, const wstring &tip);
|
ToolInfo& updateToolTip(const string& id, const wstring& tip);
|
||||||
|
|
||||||
HWND getToolTip(){return hWndToolTip;}
|
HWND getToolTip() { return hWndToolTip; }
|
||||||
|
|
||||||
void init(HWND hWnd, HWND hMainApp, HWND hTab);
|
void init(HWND hWnd, HWND hMainApp, HWND hTab);
|
||||||
bool openDoc(const wchar_t *doc);
|
bool openDoc(const wchar_t* doc);
|
||||||
wstring browseForSave(const vector< pair<wstring, wstring> > &filter,
|
wstring browseForSave(const vector< pair<wstring, wstring> >& filter,
|
||||||
const wstring &defext, int &FilterIndex);
|
const wstring& defext, int& FilterIndex);
|
||||||
wstring browseForOpen(const vector< pair<wstring, wstring> > &filter,
|
wstring browseForOpen(const vector< pair<wstring, wstring> >& filter,
|
||||||
const wstring &defext);
|
const wstring& defext);
|
||||||
wstring browseForFolder(const wstring &folderStart, const wchar_t *descr);
|
wstring browseForFolder(const wstring& folderStart, const wchar_t* descr);
|
||||||
|
|
||||||
bool clipOffset(int PageX, int PageY, int &MaxOffsetX, int &MaxOffsetY);
|
|
||||||
RectangleInfo &addRectangle(RECT &rc, GDICOLOR Color = GDICOLOR(-1),
|
|
||||||
bool DrawBorder = true, bool addFirst = false);
|
|
||||||
|
|
||||||
RectangleInfo &getRectangle(const char *id);
|
|
||||||
|
|
||||||
DWORD makeEvent(const string &id, const string &origin,
|
|
||||||
DWORD data, int extraData, bool flushEvent);
|
|
||||||
|
|
||||||
void unregisterEvent(const string &id);
|
bool clipOffset(int PageX, int PageY, int& MaxOffsetX, int& MaxOffsetY);
|
||||||
EventInfo ®isterEvent(const string &id, GUICALLBACK cb);
|
RectangleInfo& addRectangle(const RECT& rc, GDICOLOR Color = GDICOLOR(-1),
|
||||||
|
bool DrawBorder = true, bool addFirst = false);
|
||||||
|
|
||||||
int sendCtrlMessage(const string &id);
|
RectangleInfo& getRectangle(const char* id);
|
||||||
|
|
||||||
|
DWORD makeEvent(const string& id, const string& origin,
|
||||||
|
DWORD data, int extraData, bool flushEvent);
|
||||||
|
|
||||||
|
void unregisterEvent(const string& id);
|
||||||
|
EventInfo& registerEvent(const string& id, GUICALLBACK cb);
|
||||||
|
|
||||||
|
int sendCtrlMessage(const string& id);
|
||||||
bool canClear();
|
bool canClear();
|
||||||
void setOnClearCb(GUICALLBACK cb);
|
void setOnClearCb(GUICALLBACK cb);
|
||||||
void setPostClearCb(GUICALLBACK cb);
|
void setPostClearCb(GUICALLBACK cb);
|
||||||
|
|
||||||
void restore(const string &id="", bool DoRefresh=true);
|
void restore(const string& id = "", bool DoRefresh = true);
|
||||||
|
|
||||||
/// Restore, but do not update client area size,
|
/// Restore, but do not update client area size,
|
||||||
/// position, zoom, scrollbars, and do not refresh
|
/// position, zoom, scrollbars, and do not refresh
|
||||||
void restoreNoUpdate(const string &id);
|
void restoreNoUpdate(const string& id);
|
||||||
|
|
||||||
void setRestorePoint();
|
void setRestorePoint();
|
||||||
void setRestorePoint(const string &id);
|
void setRestorePoint(const string& id);
|
||||||
|
|
||||||
bool removeWidget(const string &id);
|
bool removeWidget(const string& id);
|
||||||
bool hideWidget(const string &id, bool hide = true);
|
bool hideWidget(const string& id, bool hide = true);
|
||||||
|
|
||||||
|
// Get and set restore point presence for a widget
|
||||||
|
bool getWidgetRestorePoint(const string& id, string& restorePoint) const;
|
||||||
|
void setWidgetRestorePoint(const string& id, const string& restorePoint);
|
||||||
|
|
||||||
void CheckInterfaceTimeouts(DWORD T);
|
void CheckInterfaceTimeouts(DWORD T);
|
||||||
bool RemoveFirstInfoBox(const string &id);
|
bool RemoveFirstInfoBox(const string& id);
|
||||||
void drawBoxText(HDC hDC, RECT &tr, InfoBox &Box, bool highligh);
|
void drawBoxText(HDC hDC, RECT& tr, InfoBox& Box, bool highligh);
|
||||||
void drawBoxes(HDC hDC, RECT &rc);
|
void drawBoxes(HDC hDC, RECT& rc);
|
||||||
void drawBox(HDC hDC, InfoBox &Box, RECT &pos);
|
void drawBox(HDC hDC, InfoBox& Box, RECT& pos);
|
||||||
void addInfoBox(string id, wstring text, int TimeOut=0, GUICALLBACK cb=0);
|
void addInfoBox(string id, wstring text, int TimeOut = 0, GUICALLBACK cb = nullptr);
|
||||||
void updateObjectPositions();
|
void updateObjectPositions();
|
||||||
void drawBackground(HDC hDC, RECT &rc);
|
void drawBackground(HDC hDC, RECT& rc);
|
||||||
void renderRectangle(HDC hDC, RECT *clipRegion, const RectangleInfo &ri);
|
void renderRectangle(HDC hDC, RECT* clipRegion, const RectangleInfo& ri);
|
||||||
|
|
||||||
void updateScrollbars() const;
|
void updateScrollbars() const;
|
||||||
|
|
||||||
void setOffsetY(int oy) {OffsetY=oy;}
|
void setOffsetY(int oy) { OffsetY = oy; }
|
||||||
void setOffsetX(int ox) {OffsetX=ox;}
|
void setOffsetX(int ox) { OffsetX = ox; }
|
||||||
int getPageY() const;
|
int getPageY() const;
|
||||||
int getPageX() const;
|
int getPageX() const;
|
||||||
int getOffsetY() const {return OffsetY;}
|
int getOffsetY() const { return OffsetY; }
|
||||||
int getOffsetX() const {return OffsetX;}
|
int getOffsetX() const { return OffsetX; }
|
||||||
|
|
||||||
void RenderString(TextInfo &ti, const wstring &text, HDC hDC);
|
void RenderString(TextInfo& ti, const wstring& text, HDC hDC);
|
||||||
void RenderString(TextInfo &ti, HDC hDC=0);
|
void RenderString(TextInfo& ti, HDC hDC = 0);
|
||||||
void calcStringSize(TextInfo &ti, HDC hDC=0) const;
|
void calcStringSize(TextInfo& ti, HDC hDC = 0) const;
|
||||||
void formatString(const TextInfo &ti, HDC hDC) const;
|
void formatString(const TextInfo& ti, HDC hDC) const;
|
||||||
|
|
||||||
static wstring getTimerText(TextInfo *tit, DWORD T);
|
static wstring getTimerText(TextInfo* tit, DWORD T);
|
||||||
static wstring getTimerText(int ZeroTime, int format);
|
static wstring getTimerText(int ZeroTime, int format);
|
||||||
|
|
||||||
void fadeOut(string Id, int ms);
|
void fadeOut(string Id, int ms);
|
||||||
void setWaitCursor(bool wait);
|
void setWaitCursor(bool wait);
|
||||||
void setWindowTitle(const wstring &title);
|
void setWindowTitle(const wstring& title);
|
||||||
bool selectFirstItem(const string &name);
|
bool selectFirstItem(const string& name);
|
||||||
void removeString(string Id);
|
void removeString(string Id);
|
||||||
void refresh() const;
|
void refresh() const;
|
||||||
void refreshFast() const;
|
void refreshFast() const;
|
||||||
@ -515,269 +544,295 @@ public:
|
|||||||
void takeShownStringsSnapshot();
|
void takeShownStringsSnapshot();
|
||||||
void refreshSmartFromSnapshot(bool allowMoveOffset);
|
void refreshSmartFromSnapshot(bool allowMoveOffset);
|
||||||
|
|
||||||
void dropLine(double lines=1){CurrentY+=int(lineHeight*lines); MaxY=max(MaxY, CurrentY);}
|
void dropLine(double lines = 1) { CurrentY += int(lineHeight * lines); MaxY = max(MaxY, CurrentY); }
|
||||||
int getCX() const {return CurrentX;}
|
int getCX() const { return CurrentX; }
|
||||||
int getCY() const {return CurrentY;}
|
int getCY() const { return CurrentY; }
|
||||||
int getWidth() const {return MaxX;}
|
int getWidth() const { return MaxX; }
|
||||||
int getHeight() const {return MaxY;}
|
int getHeight() const { return MaxY; }
|
||||||
void getTargetDimension(int &x, int &y) const;
|
void getTargetDimension(int& x, int& y) const;
|
||||||
|
|
||||||
pair<int, int> getPos() const { return make_pair(CurrentX, CurrentY); }
|
pair<int, int> getPos() const { return make_pair(CurrentX, CurrentY); }
|
||||||
void setPos(const pair<int, int> &p) { CurrentX = p.first; CurrentY = p.second; }
|
void setPos(const pair<int, int>& p) { CurrentX = p.first; CurrentY = p.second; }
|
||||||
|
|
||||||
void setCX(int cx){CurrentX=cx;}
|
void setCX(int cx) { CurrentX = cx; }
|
||||||
void setCY(int cy){CurrentY=cy;}
|
void setCY(int cy) { CurrentY = cy; }
|
||||||
int getLineHeight() const {return lineHeight;}
|
int getLineHeight() const { return lineHeight; }
|
||||||
int getLineHeight(gdiFonts font, const wchar_t *face) const;
|
int getLineHeight(gdiFonts font, const wchar_t* face) const;
|
||||||
|
|
||||||
BaseInfo *setInputFocus(const string &id, bool select=false);
|
BaseInfo* setInputFocus(const string& id, bool select = false);
|
||||||
InputInfo *getInputFocus();
|
InputInfo* getInputFocus();
|
||||||
|
|
||||||
void enableInput(const char *id, bool acceptMissing = false,
|
void enableInput(const char* id, bool acceptMissing = false,
|
||||||
int requireExtraMatch = -1) {setInputStatus(id, true, acceptMissing, requireExtraMatch);}
|
int requireExtraMatch = -1) {
|
||||||
void disableInput(const char *id, bool acceptMissing = false,
|
setInputStatus(id, true, acceptMissing, requireExtraMatch);
|
||||||
int requireExtraMatch = -1) {setInputStatus(id, false, acceptMissing, requireExtraMatch);}
|
}
|
||||||
void setInputStatus(const char *id, bool status, bool acceptMissing = false, int requireExtraMatch = -1);
|
void disableInput(const char* id, bool acceptMissing = false,
|
||||||
void setInputStatus(const string &id, bool status, bool acceptMissing = false, int requireExtraMatch = -1)
|
int requireExtraMatch = -1) {
|
||||||
{setInputStatus(id.c_str(), status, acceptMissing, requireExtraMatch);}
|
setInputStatus(id, false, acceptMissing, requireExtraMatch);
|
||||||
|
}
|
||||||
|
void setInputStatus(const char* id, bool status, bool acceptMissing = false, int requireExtraMatch = -1);
|
||||||
|
void setInputStatus(const string& id, bool status, bool acceptMissing = false, int requireExtraMatch = -1)
|
||||||
|
{
|
||||||
|
setInputStatus(id.c_str(), status, acceptMissing, requireExtraMatch);
|
||||||
|
}
|
||||||
|
|
||||||
void setTabStops(const string &Name, int t1, int t2=-1);
|
void setTabStops(const string& name, int t1, int t2 = -1);
|
||||||
void setData(const string &id, DWORD data);
|
void setData(const string& id, DWORD data);
|
||||||
void setData(const string &id, void *data);
|
void setData(const string& id, void* data);
|
||||||
void setData(const string &id, const string &data);
|
void setData(const string& id, const string& data);
|
||||||
|
|
||||||
void *getData(const string &id) const;
|
void* getData(const string& id) const;
|
||||||
int getDataInt(const string &id) const { return int(size_t(getData(id))); }
|
int getDataInt(const string& id) const { return int(size_t(getData(id))); }
|
||||||
|
|
||||||
bool getData(const string &id, string &out) const;
|
bool getData(const string& id, string& out) const;
|
||||||
|
|
||||||
|
|
||||||
DWORD selectColor(wstring &def, DWORD input);
|
DWORD selectColor(wstring& def, DWORD input);
|
||||||
|
|
||||||
void autoRefresh(bool flag) {manualUpdate = !flag;}
|
void autoRefresh(bool flag) { manualUpdate = !flag; }
|
||||||
|
|
||||||
bool getData(const string &id, DWORD &data) const;
|
bool getData(const string& id, DWORD& data) const;
|
||||||
bool hasData(const char *id) const;
|
bool hasData(const char* id) const;
|
||||||
|
|
||||||
int getItemDataByName(const char *id, const char *name) const;
|
int getItemDataByName(const char* id, const char* name) const;
|
||||||
bool selectItemByData(const char *id, int data);
|
bool selectItemByData(const char* id, int data);
|
||||||
bool selectItemByIndex(const char *id, int index);
|
bool selectItemByIndex(const char* id, int index);
|
||||||
|
|
||||||
void removeSelected(const char *id);
|
void removeSelected(const char* id);
|
||||||
|
|
||||||
bool selectItemByData(const string &id, int data) {
|
bool selectItemByData(const string& id, int data) {
|
||||||
return selectItemByData(id.c_str(), data);
|
return selectItemByData(id.c_str(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AskAnswer {AnswerNo = 0, AnswerYes = 1, AnswerCancel = 2};
|
enum class AskAnswer { AnswerNo = 0, AnswerYes = 1, AnswerCancel = 2, AnswerOK = 3 };
|
||||||
bool ask(const wstring &s);
|
bool ask(const wstring& s);
|
||||||
AskAnswer askCancel(const wstring &s);
|
AskAnswer askOkCancel(const wstring& s);
|
||||||
|
AskAnswer askCancel(const wstring& s);
|
||||||
|
|
||||||
void alert(const string &msg) const;
|
void alert(const string& msg) const;
|
||||||
void alert(const wstring &msg) const;
|
void alert(const wstring& msg) const;
|
||||||
// Alert from main thread (via callback)
|
// Alert from main thread (via callback)
|
||||||
void delayAlert(const wstring& msg);
|
void delayAlert(const wstring& msg);
|
||||||
// Get and clear any delayed alert
|
// Get and clear any delayed alert
|
||||||
wstring getDelayedAlert();
|
wstring getDelayedAlert();
|
||||||
|
|
||||||
void fillDown(){Direction=1;}
|
void fillDown() { flowDirection = FlowDirection::Down; }
|
||||||
void fillRight(){Direction=0;}
|
void fillRight() { flowDirection = FlowDirection::Right; }
|
||||||
void fillNone(){Direction=-1;}
|
void fillNone() { flowDirection = FlowDirection::None; }
|
||||||
void newColumn(){CurrentY=START_YP; CurrentX=MaxX+10;}
|
|
||||||
void newRow(){CurrentY=MaxY; CurrentX=10;}
|
|
||||||
|
|
||||||
void pushX(){SX=CurrentX;}
|
void newColumn() { CurrentY = START_YP; CurrentX = MaxX + 10; }
|
||||||
void pushY(){SY=CurrentY;}
|
void newRow() { CurrentY = MaxY; CurrentX = 10; }
|
||||||
void popX(){CurrentX=SX;}
|
|
||||||
void popY(){CurrentY=SY;}
|
void pushX() { SX = CurrentX; }
|
||||||
|
void pushY() { SY = CurrentY; }
|
||||||
|
void popX() { CurrentX = SX; }
|
||||||
|
void popY() { CurrentY = SY; }
|
||||||
|
|
||||||
bool updatePos(int x, int y, int width, int height);
|
bool updatePos(int x, int y, int width, int height);
|
||||||
void adjustDimension(int width, int height);
|
void adjustDimension(int width, int height);
|
||||||
|
|
||||||
/** Return a selected item*/
|
/** Return a selected item*/
|
||||||
bool getSelectedItem(const string &id, ListBoxInfo &lbi);
|
bool getSelectedItem(const string& id, ListBoxInfo& lbi);
|
||||||
|
|
||||||
/** Get number of items in a list box.'*/
|
/** Get number of items in a list box.'*/
|
||||||
int getNumItems(const char *id);
|
int getNumItems(const char* id);
|
||||||
|
|
||||||
/** Return the selected data in first, second indicates if data was available*/
|
/** Return the selected data in first, second indicates if data was available*/
|
||||||
pair<int, bool> getSelectedItem(const string &id);
|
pair<int, bool> getSelectedItem(const string& id);
|
||||||
pair<int, bool> getSelectedItem(const char *id);
|
pair<int, bool> getSelectedItem(const char* id);
|
||||||
|
|
||||||
bool addItem(const string &id, const wstring &text, size_t data = 0);
|
bool addItem(const string& id, const wstring& text, size_t data = 0);
|
||||||
bool addItem(const string &id, const vector< pair<wstring, size_t> > &items);
|
bool addItem(const string& id, const vector< pair<wstring, size_t> >& items);
|
||||||
|
|
||||||
void filterOnData(const string &id, const unordered_set<int> &filter);
|
|
||||||
|
|
||||||
bool clearList(const string &id);
|
void filterOnData(const string& id, const unordered_set<int>& filter);
|
||||||
|
|
||||||
bool hasWidget(const string &id) const;
|
bool clearList(const string& id);
|
||||||
|
|
||||||
const wstring &getText(const char *id, bool acceptMissing = false, int requireExtraMatch = -1) const;
|
bool hasWidget(const string& id) const;
|
||||||
|
|
||||||
BaseInfo &getBaseInfo(const string &id) const {
|
const wstring& getText(const char* id, bool acceptMissing = false, int requireExtraMatch = -1) const;
|
||||||
return getBaseInfo(id.c_str());
|
|
||||||
|
BaseInfo& getBaseInfo(const string& id, int requireExtraMatch = -1) const {
|
||||||
|
return getBaseInfo(id.c_str(), requireExtraMatch);
|
||||||
}
|
}
|
||||||
BaseInfo &getBaseInfo(const char *id) const;
|
BaseInfo& getBaseInfo(const char* id, int requireExtraMatch = -1) const;
|
||||||
BaseInfo &getBaseInfo(const wchar_t *id) const {
|
BaseInfo& getBaseInfo(const wchar_t* id, int requireExtraMatch = -1) const {
|
||||||
return getBaseInfo(narrow(id).c_str());
|
return getBaseInfo(narrow(id).c_str(), requireExtraMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getTextNo(const char *id, bool acceptMissing = false) const;
|
int getTextNo(const char* id, bool acceptMissing = false) const;
|
||||||
int getTextNo(const string &id, bool acceptMissing = false) const
|
int getTextNo(const string& id, bool acceptMissing = false) const
|
||||||
{return getTextNo(id.c_str(), acceptMissing);}
|
{
|
||||||
|
return getTextNo(id.c_str(), acceptMissing);
|
||||||
|
}
|
||||||
|
|
||||||
const wstring &getText(const string &id, bool acceptMissing = false) const
|
const wstring& getText(const string& id, bool acceptMissing = false) const
|
||||||
{return getText(id.c_str(), acceptMissing);}
|
{
|
||||||
|
return getText(id.c_str(), acceptMissing);
|
||||||
|
}
|
||||||
|
|
||||||
// Insert text and notify "focusList"
|
// Insert text and notify "focusList"
|
||||||
bool insertText(const string &id, const wstring &text);
|
bool insertText(const string& id, const wstring& text);
|
||||||
|
|
||||||
int getFontHeight(int format, const wstring &fontFace) const;
|
int getFontHeight(int format, const wstring& fontFace) const;
|
||||||
|
|
||||||
// The html version should be UTF-8.
|
// The html version should be UTF-8.
|
||||||
void copyToClipboard(const string &html,
|
void copyToClipboard(const string& html,
|
||||||
const wstring &txt) const;
|
const wstring& txt) const;
|
||||||
|
|
||||||
BaseInfo *setTextTranslate(const char *id, const wstring &text, bool update=false);
|
BaseInfo* setTextTranslate(const char* id, const wstring& text, bool update = false);
|
||||||
BaseInfo *setTextTranslate(const char *id, const wchar_t *text, bool update=false);
|
BaseInfo* setTextTranslate(const char* id, const wchar_t* text, bool update = false);
|
||||||
BaseInfo *setTextTranslate(const string &id, const wstring &text, bool update=false);
|
BaseInfo* setTextTranslate(const string& id, const wstring& text, bool update = false);
|
||||||
|
|
||||||
|
|
||||||
BaseInfo *setText(const char *id, const wstring &text, bool update=false, int requireExtraMatch = -1);
|
BaseInfo* setText(const char* id, const wstring& text, bool update = false, int requireExtraMatch = -1);
|
||||||
BaseInfo *setText(const wchar_t *id, const wstring &text, bool update=false) {
|
BaseInfo* setText(const wchar_t* id, const wstring& text, bool update = false) {
|
||||||
return setText(narrow(id), text, update);
|
return setText(narrow(id), text, update);
|
||||||
}
|
}
|
||||||
BaseInfo *setText(const char *id, int number, bool update=false);
|
BaseInfo* setText(const char* id, int number, bool update = false);
|
||||||
BaseInfo *setText(const string &id, const wstring &text, bool update=false)
|
BaseInfo* setText(const string& id, const wstring& text, bool update = false)
|
||||||
{return setText(id.c_str(), text, update);}
|
{
|
||||||
BaseInfo *setTextZeroBlank(const char *id, int number, bool update=false);
|
return setText(id.c_str(), text, update);
|
||||||
BaseInfo *setText(const string &id, int number, bool update=false)
|
}
|
||||||
{return setText(id.c_str(), number, update);}
|
BaseInfo* setTextZeroBlank(const char* id, int number, bool update = false);
|
||||||
|
BaseInfo* setText(const string& id, int number, bool update = false)
|
||||||
|
{
|
||||||
|
return setText(id.c_str(), number, update);
|
||||||
|
}
|
||||||
|
|
||||||
void clearPage(bool autoRefresh, bool keepToolbar = false);
|
void clearPage(bool autoRefresh, bool keepToolbar = false);
|
||||||
|
|
||||||
void TabFocus(int direction=1);
|
void TabFocus(int direction = 1);
|
||||||
void enter();
|
void enter();
|
||||||
void escape();
|
void escape();
|
||||||
bool upDown(int direction);
|
bool upDown(int direction);
|
||||||
void keyCommand(KeyCommandCode code);
|
void keyCommand(KeyCommandCode code);
|
||||||
|
|
||||||
LRESULT ProcessMsg(UINT iMessage, LPARAM lParam, WPARAM wParam);
|
LRESULT ProcessMsg(UINT iMessage, LPARAM lParam, WPARAM wParam);
|
||||||
void setWindow(HWND hWnd){hWndTarget=hWnd;}
|
void setWindow(HWND hWnd) { hWndTarget = hWnd; }
|
||||||
|
|
||||||
void scaleSize(double scale, bool allowSmallScale = false, bool doRefresh = true);
|
enum class ScaleOperation {
|
||||||
|
NoRefresh,
|
||||||
|
Refresh,
|
||||||
|
NoUpdate
|
||||||
|
};
|
||||||
|
|
||||||
ButtonInfo &addButton(const string &id, const wstring &text, GUICALLBACK cb = 0,
|
void scaleSize(double scale, bool allowSmallScale = false, ScaleOperation type = ScaleOperation::Refresh);
|
||||||
const wstring &tooltip = L"");
|
|
||||||
|
|
||||||
ButtonInfo &addButton(int x, int y, const string &id, const wstring &text,
|
ButtonInfo& addButton(const string& id, const wstring& text, GUICALLBACK cb = nullptr,
|
||||||
GUICALLBACK cb = 0, const wstring &tooltop=L"");
|
const wstring& tooltip = L"");
|
||||||
|
|
||||||
ButtonInfo &addButton(int x, int y, int w, const string &id, const wstring &text,
|
ButtonInfo& addButton(int x, int y, const string& id, const wstring& text,
|
||||||
GUICALLBACK cb, const wstring &tooltop, bool absPos, bool hasState);
|
GUICALLBACK cb = nullptr, const wstring& tooltop = L"");
|
||||||
|
|
||||||
|
ButtonInfo& addButton(int x, int y, int w, const string& id, const wstring& text,
|
||||||
|
GUICALLBACK cb, const wstring& tooltop, bool absPos, bool hasState);
|
||||||
|
|
||||||
|
ButtonInfo& addCheckbox(const string& id, const wstring& text, GUICALLBACK cb = nullptr,
|
||||||
|
bool Checked = true, const wstring& tooltip = L"");
|
||||||
|
ButtonInfo& addCheckbox(int x, int y, const string& id,
|
||||||
|
const wstring& text, GUICALLBACK cb = nullptr,
|
||||||
|
bool checked = true, const wstring& tooltop = L"", bool absPos = false);
|
||||||
|
|
||||||
ButtonInfo &addCheckbox(const string &id, const wstring &text, GUICALLBACK cb=0,
|
|
||||||
bool Checked=true, const wstring &tooltip = L"");
|
|
||||||
ButtonInfo &addCheckbox(int x, int y, const string &id,
|
|
||||||
const wstring &text, GUICALLBACK cb=0,
|
|
||||||
bool checked=true, const wstring &tooltop = L"", bool absPos=false);
|
|
||||||
|
|
||||||
|
|
||||||
/// XXX Temporary
|
/// XXX Temporary
|
||||||
ButtonInfo &addButton(const string &id, const string &text, GUICALLBACK cb = 0, const string &tooltip="");
|
ButtonInfo& addButton(const string& id, const string& text, GUICALLBACK cb = nullptr, const string& tooltip = "");
|
||||||
|
|
||||||
ButtonInfo &addButton(int x, int y, const string &id, const string &text,
|
ButtonInfo& addButton(int x, int y, const string& id, const string& text,
|
||||||
GUICALLBACK cb = 0, const string &tooltop="");
|
GUICALLBACK cb = nullptr, const string& tooltop = "");
|
||||||
ButtonInfo &addButton(int x, int y, int w, const string &id, const string &text,
|
ButtonInfo& addButton(int x, int y, int w, const string& id, const string& text,
|
||||||
GUICALLBACK cb, const string &tooltop, bool AbsPos, bool hasState);
|
GUICALLBACK cb, const string& tooltop, bool AbsPos, bool hasState);
|
||||||
|
|
||||||
ButtonInfo &addCheckbox(const string &id, const string &text, GUICALLBACK cb=0, bool Checked=true, const string &Help="");
|
ButtonInfo& addCheckbox(const string& id, const string& text, GUICALLBACK cb = nullptr, bool Checked = true, const string& Help = "");
|
||||||
ButtonInfo &addCheckbox(int x, int y, const string &id, const string &text, GUICALLBACK cb=0, bool Checked=true, const string &Help="", bool AbsPos=false);
|
ButtonInfo& addCheckbox(int x, int y, const string& id, const string& text, GUICALLBACK cb = nullptr, bool Checked = true, const string& Help = "", bool AbsPos = false);
|
||||||
/// XXX
|
/// XXX
|
||||||
|
|
||||||
bool isChecked(const string &id);
|
|
||||||
void check(const string &id, bool state, bool keepOriginalState = false);
|
|
||||||
|
|
||||||
bool isInputChanged(const string &exclude);
|
bool isChecked(const string& id);
|
||||||
|
void check(const string& id, bool state, bool keepOriginalState = false);
|
||||||
|
|
||||||
|
bool isInputChanged(const string& exclude);
|
||||||
|
|
||||||
/** Get width of input widget with specified length (chars)*/
|
/** Get width of input widget with specified length (chars)*/
|
||||||
pair<int,int> getInputDimension(int length) const;
|
pair<int, int> getInputDimension(int length) const;
|
||||||
|
|
||||||
InputInfo &addInput(const string &id, const wstring &text = L"", int length=16, GUICALLBACK cb=0,
|
InputInfo& addInput(const string& id, const wstring& text = L"", int length = 16, GUICALLBACK cb = nullptr,
|
||||||
const wstring &Explanation = L"", const wstring &tooltip=L"");
|
const wstring& Explanation = L"", const wstring& tooltip = L"");
|
||||||
InputInfo &addInput(int x, int y, const string &id, const wstring &text, int length,
|
InputInfo& addInput(int x, int y, const string& id, const wstring& text, int length,
|
||||||
GUICALLBACK cb=0, const wstring &Explanation = L"", const wstring &tooltip=L"");
|
GUICALLBACK cb = nullptr, const wstring& Explanation = L"", const wstring& tooltip = L"");
|
||||||
|
|
||||||
InputInfo *replaceSelection(const char *id, const wstring &text);
|
InputInfo* replaceSelection(const char* id, const wstring& text);
|
||||||
|
|
||||||
InputInfo &addInputBox(const string &id, int width, int height, const wstring &text,
|
InputInfo& addInputBox(const string& id, int width, int height, const wstring& text,
|
||||||
GUICALLBACK cb, const wstring &explanation);
|
GUICALLBACK cb, const wstring& explanation);
|
||||||
|
|
||||||
InputInfo &addInputBox(const string &id, int x, int y, int width, int height,
|
InputInfo& addInputBox(const string& id, int x, int y, int width, int height,
|
||||||
const wstring &text, GUICALLBACK cb, const wstring &explanation);
|
const wstring& text, GUICALLBACK cb, const wstring& explanation);
|
||||||
|
|
||||||
ListBoxInfo &addListBox(const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"", bool multiple=false);
|
ListBoxInfo& addListBox(const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"", bool multiple = false);
|
||||||
ListBoxInfo &addListBox(int x, int y, const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"", bool multiple=false);
|
ListBoxInfo& addListBox(int x, int y, const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"", bool multiple = false);
|
||||||
|
|
||||||
ListBoxInfo &addSelection(const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"");
|
ListBoxInfo& addSelection(const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"");
|
||||||
ListBoxInfo &addSelection(int x, int y, const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"");
|
ListBoxInfo& addSelection(int x, int y, const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"");
|
||||||
|
|
||||||
ListBoxInfo &addCombo(const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"");
|
ListBoxInfo& addCombo(const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"");
|
||||||
ListBoxInfo &addCombo(int x, int y, const string &id, int width, int height, GUICALLBACK cb=0, const wstring &explanation=L"", const wstring &tooltip=L"");
|
ListBoxInfo& addCombo(int x, int y, const string& id, int width, int height, GUICALLBACK cb = nullptr, const wstring& explanation = L"", const wstring& tooltip = L"");
|
||||||
|
|
||||||
// Grows a listbox, selection, combo in X-direction to fit current contents. Returns true if changed.
|
// Grows a listbox, selection, combo in X-direction to fit current contents. Returns true if changed.
|
||||||
bool autoGrow(const char *id);
|
bool autoGrow(const char* id);
|
||||||
|
|
||||||
|
void setListDescription(const wstring& desc);
|
||||||
|
|
||||||
void setListDescription(const wstring &desc);
|
|
||||||
|
|
||||||
// Wide versions
|
// Wide versions
|
||||||
TextInfo &addString(const string &id, int format, const wstring &text, GUICALLBACK cb=0);
|
TextInfo& addString(const string& id, int format, const wstring& text, GUICALLBACK cb = nullptr);
|
||||||
TextInfo &addString(const string &id, int yp, int xp, int format, const wstring &text,
|
TextInfo& addString(const string& id, int yp, int xp, int format, const wstring& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
TextInfo &addString(const char *id, int format, const wstring &text, GUICALLBACK cb=0);
|
TextInfo& addString(const char* id, int format, const wstring& text, GUICALLBACK cb = nullptr);
|
||||||
TextInfo &addString(const char *id, int yp, int xp, int format, const wstring &text,
|
TextInfo& addString(const char* id, int yp, int xp, int format, const wstring& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
// Untranslated versions
|
// Untranslated versions
|
||||||
TextInfo &addStringUT(int yp, int xp, int format, const wstring &text,
|
TextInfo& addStringUT(int yp, int xp, int format, const wstring& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
TextInfo &addStringUT(int format, const wstring &text, GUICALLBACK cb=0);
|
TextInfo& addStringUT(int format, const wstring& text, GUICALLBACK cb = nullptr);
|
||||||
|
|
||||||
// Temporary XXX
|
// Temporary XXX
|
||||||
TextInfo &addString(const string &id, int format, const string &text, GUICALLBACK cb=0);
|
TextInfo& addString(const string& id, int format, const string& text, GUICALLBACK cb = nullptr);
|
||||||
TextInfo &addString(const string &id, int yp, int xp, int format, const string &text,
|
TextInfo& addString(const string& id, int yp, int xp, int format, const string& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
TextInfo &addString(const char *id, int format, const string &text, GUICALLBACK cb=0);
|
TextInfo& addString(const char* id, int format, const string& text, GUICALLBACK cb = nullptr);
|
||||||
TextInfo &addString(const char *id, int yp, int xp, int format, const string &text,
|
TextInfo& addString(const char* id, int yp, int xp, int format, const string& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
// Untranslated versions
|
// Untranslated versions
|
||||||
TextInfo &addStringUT(int yp, int xp, int format, const string &text,
|
TextInfo& addStringUT(int yp, int xp, int format, const string& text,
|
||||||
int xlimit=0, GUICALLBACK cb=0, const wchar_t *fontFace = 0);
|
int xlimit = 0, GUICALLBACK cb = nullptr, const wchar_t* fontFace = nullptr);
|
||||||
TextInfo &addStringUT(int format, const string &text, GUICALLBACK cb=0);
|
TextInfo& addStringUT(int format, const string& text, GUICALLBACK cb = nullptr);
|
||||||
// XXX Temporary
|
// XXX Temporary
|
||||||
|
|
||||||
TextInfo &addTimer(int yp, int xp, int format, DWORD ZeroTime,
|
TextInfo& addImage(const string& id, int yp, int xp, int format, const wstring& imageId,
|
||||||
int xlimit=0, GUICALLBACK cb=0, int TimeOut=NOTIMEOUT, const wchar_t *fontFace = 0);
|
int width = 0, int height = 0, GUICALLBACK cb = nullptr);
|
||||||
TextInfo &addTimeout(int TimeOut, GUICALLBACK cb);
|
|
||||||
|
|
||||||
void removeTimeoutMilli(const string &id);
|
TextInfo& addTimer(int yp, int xp, int format, DWORD ZeroTime,
|
||||||
TimerInfo &addTimeoutMilli(int timeOut, const string &id, GUICALLBACK cb);
|
int xlimit = 0, GUICALLBACK cb = nullptr, int TimeOut = NOTIMEOUT, const wchar_t* fontFace = nullptr);
|
||||||
void timerProc(TimerInfo &timer, DWORD timeout);
|
|
||||||
|
|
||||||
void removeHandler(GuiHandler *h);
|
TextInfo& addTimeout(int TimeOut, GUICALLBACK cb);
|
||||||
|
|
||||||
void draw(HDC hDC, RECT &windowArea, RECT &drawArea);
|
void removeTimeoutMilli(const string& id);
|
||||||
|
TimerInfo& addTimeoutMilli(int timeOut, const string& id, GUICALLBACK cb);
|
||||||
|
void timerProc(TimerInfo& timer, DWORD timeout);
|
||||||
|
|
||||||
|
void removeHandler(GuiHandler* h);
|
||||||
|
|
||||||
|
void draw(HDC hDC, RECT& windowArea, RECT& drawArea);
|
||||||
|
|
||||||
void closeWindow();
|
void closeWindow();
|
||||||
|
|
||||||
int popupMenu(int x, int y, const vector<pair<wstring, int>> &menuItems) const;
|
int popupMenu(int x, int y, const vector<pair<wstring, int>>& menuItems) const;
|
||||||
|
|
||||||
void setDBErrorState(bool state);
|
void setDBErrorState(bool state);
|
||||||
friend class Table;
|
friend class Table;
|
||||||
friend gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y, bool fixedSize);
|
friend gdioutput* createExtraWindow(const string& tag, const wstring& title, int max_x, int max_y, bool fixedSize);
|
||||||
|
|
||||||
gdioutput(const string &tag, double _scale);
|
gdioutput(const string& tag, double _scale);
|
||||||
gdioutput(double _scale, HWND hWndTarget, const PrinterObject &defprn);
|
gdioutput(double _scale, HWND hWndTarget, const PrinterObject& defprn);
|
||||||
virtual ~gdioutput();
|
virtual ~gdioutput();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -82,6 +82,10 @@ public:
|
|||||||
GuiHandler &getHandler() const;
|
GuiHandler &getHandler() const;
|
||||||
BaseInfo &setHandler(const GuiHandler *h) {handler = const_cast<GuiHandler *>(h); return *this;}
|
BaseInfo &setHandler(const GuiHandler *h) {handler = const_cast<GuiHandler *>(h); return *this;}
|
||||||
BaseInfo &setHandler(const shared_ptr<GuiHandler> &h) { managedHandler = h; return *this; }
|
BaseInfo &setHandler(const shared_ptr<GuiHandler> &h) { managedHandler = h; return *this; }
|
||||||
|
void clearHandler() {
|
||||||
|
handler = nullptr;
|
||||||
|
managedHandler.reset();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RestoreInfo : public BaseInfo
|
class RestoreInfo : public BaseInfo
|
||||||
@ -108,6 +112,12 @@ public:
|
|||||||
GUICALLBACK onClear;
|
GUICALLBACK onClear;
|
||||||
GUICALLBACK postClear;
|
GUICALLBACK postClear;
|
||||||
|
|
||||||
|
set<string> restorePoints;
|
||||||
|
|
||||||
|
bool operator<(const RestoreInfo &r) const {
|
||||||
|
return nLBI < r.nLBI || nBI < r.nBI || nII < r.nII || nTL < r.nTL || nRect < r.nRect || nData < r.nData;
|
||||||
|
}
|
||||||
|
|
||||||
HWND getControlWindow() const {throw std::exception("Unsupported");}
|
HWND getControlWindow() const {throw std::exception("Unsupported");}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -387,11 +397,12 @@ private:
|
|||||||
DWORD dataInt;
|
DWORD dataInt;
|
||||||
wstring dataString;
|
wstring dataString;
|
||||||
gdioutput *parent;
|
gdioutput *parent;
|
||||||
TimerInfo(gdioutput *gdi, GUICALLBACK cb) : parent(gdi), callBack(cb), setWnd(0), timerId(++globalTimerId) {}
|
|
||||||
HWND setWnd;
|
HWND setWnd;
|
||||||
public:
|
public:
|
||||||
~TimerInfo();
|
~TimerInfo();
|
||||||
|
TimerInfo(gdioutput* gdi, GUICALLBACK cb) : parent(gdi), callBack(cb), setWnd(0), timerId(++globalTimerId) {}
|
||||||
|
TimerInfo(const TimerInfo&) = delete;
|
||||||
|
TimerInfo& operator=(const TimerInfo&) = delete;
|
||||||
int getId() const { return timerId; }
|
int getId() const { return timerId; }
|
||||||
BaseInfo &setExtra(const wchar_t *e) {return BaseInfo::setExtra(e);}
|
BaseInfo &setExtra(const wchar_t *e) {return BaseInfo::setExtra(e);}
|
||||||
BaseInfo &setExtra(int e) {return BaseInfo::setExtra(e);}
|
BaseInfo &setExtra(int e) {return BaseInfo::setExtra(e);}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -266,7 +266,7 @@ template<class T> void GeneralResult::sort(vector<T *> &rt, SortOrder so) const
|
|||||||
ps = None;
|
ps = None;
|
||||||
|
|
||||||
vector< pair<int, oAbstractRunner *> > arr(rt.size());
|
vector< pair<int, oAbstractRunner *> > arr(rt.size());
|
||||||
const int maxT = 3600 * 100;
|
const int maxT = timeConstHour * 100;
|
||||||
for (size_t k = 0; k < rt.size(); k++) {
|
for (size_t k = 0; k < rt.size(); k++) {
|
||||||
arr[k].first = 0;
|
arr[k].first = 0;
|
||||||
if (ps == ClassWise) {
|
if (ps == ClassWise) {
|
||||||
@ -293,7 +293,7 @@ template<class T> void GeneralResult::sort(vector<T *> &rt, SortOrder so) const
|
|||||||
ord = maxT - ord;
|
ord = maxT - ord;
|
||||||
}
|
}
|
||||||
else if (so == SortByStartTime || so == ClassStartTime ||
|
else if (so == SortByStartTime || so == ClassStartTime ||
|
||||||
so == ClassStartTimeClub) {
|
so == ClassStartTimeClub || so == ClubClassStartTime) {
|
||||||
ord = tr.getStartTime();
|
ord = tr.getStartTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +593,7 @@ int TotalResultAtControl::deduceTime(oRunner &runner, int startTime) const {
|
|||||||
pair<int,int> TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
|
pair<int,int> TotalResultAtControl::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
|
||||||
if (asTeamMember)
|
if (asTeamMember)
|
||||||
return make_pair(runner.getLegNumber(), 0);
|
return make_pair(runner.getLegNumber(), 0);
|
||||||
const int TK = 3600 * 24 * 7;
|
const int TK = timeConstHour * 24 * 7;
|
||||||
RunnerStatus inputStatus = StatusOK;
|
RunnerStatus inputStatus = StatusOK;
|
||||||
|
|
||||||
if (runner.getTeam()) {
|
if (runner.getTeam()) {
|
||||||
@ -781,7 +781,7 @@ RunnerStatus DynamicResult::toStatus(int status) const {
|
|||||||
|
|
||||||
pair<int,int> DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
|
pair<int,int> DynamicResult::score(oTeam &team, RunnerStatus st, int time, int points) const {
|
||||||
if (getMethod(MTScore)) {
|
if (getMethod(MTScore)) {
|
||||||
parser.addSymbol("ComputedTime", time);
|
parser.addSymbol("ComputedTime", time / timeConstSecond);
|
||||||
parser.addSymbol("ComputedStatus", st);
|
parser.addSymbol("ComputedStatus", st);
|
||||||
parser.addSymbol("ComputedPoints", points);
|
parser.addSymbol("ComputedPoints", points);
|
||||||
return make_pair(0, getMethod(MTScore)->evaluate(parser));
|
return make_pair(0, getMethod(MTScore)->evaluate(parser));
|
||||||
@ -801,7 +801,7 @@ RunnerStatus DynamicResult::deduceStatus(oTeam &team) const {
|
|||||||
|
|
||||||
int DynamicResult::deduceTime(oTeam &team) const {
|
int DynamicResult::deduceTime(oTeam &team) const {
|
||||||
if (getMethod(MDeduceTTime))
|
if (getMethod(MDeduceTTime))
|
||||||
return getMethod(MDeduceTTime)->evaluate(parser);
|
return getMethod(MDeduceTTime)->evaluate(parser) * timeConstSecond + team.getSubSeconds();
|
||||||
else if (getMethodSource(MDeduceTTime).empty())
|
else if (getMethodSource(MDeduceTTime).empty())
|
||||||
return GeneralResult::deduceTime(team);
|
return GeneralResult::deduceTime(team);
|
||||||
else throw meosException("Syntax error");
|
else throw meosException("Syntax error");
|
||||||
@ -817,7 +817,7 @@ int DynamicResult::deducePoints(oTeam &team) const {
|
|||||||
|
|
||||||
pair<int,int> DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
|
pair<int,int> DynamicResult::score(oRunner &runner, RunnerStatus st, int time, int points, bool asTeamMember) const {
|
||||||
if (getMethod(MRScore)) {
|
if (getMethod(MRScore)) {
|
||||||
parser.addSymbol("ComputedTime", time);
|
parser.addSymbol("ComputedTime", time / timeConstSecond);
|
||||||
parser.addSymbol("ComputedStatus", st);
|
parser.addSymbol("ComputedStatus", st);
|
||||||
parser.addSymbol("ComputedPoints", points);
|
parser.addSymbol("ComputedPoints", points);
|
||||||
return make_pair(0, getMethod(MRScore)->evaluate(parser));
|
return make_pair(0, getMethod(MRScore)->evaluate(parser));
|
||||||
@ -837,7 +837,7 @@ RunnerStatus DynamicResult::deduceStatus(oRunner &runner) const {
|
|||||||
|
|
||||||
int DynamicResult::deduceTime(oRunner &runner, int startTime) const {
|
int DynamicResult::deduceTime(oRunner &runner, int startTime) const {
|
||||||
if (getMethod(MDeduceRTime))
|
if (getMethod(MDeduceRTime))
|
||||||
return getMethod(MDeduceRTime)->evaluate(parser);
|
return getMethod(MDeduceRTime)->evaluate(parser) * timeConstSecond + runner.getSubSeconds();
|
||||||
else if (getMethodSource(MDeduceRTime).empty())
|
else if (getMethodSource(MDeduceRTime).empty())
|
||||||
return GeneralResult::deduceTime(runner, startTime);
|
return GeneralResult::deduceTime(runner, startTime);
|
||||||
else throw meosException("Syntax error");
|
else throw meosException("Syntax error");
|
||||||
@ -1160,24 +1160,24 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) con
|
|||||||
if (st == StatusUnknown && ft > 0)
|
if (st == StatusUnknown && ft > 0)
|
||||||
st = StatusOK;
|
st = StatusOK;
|
||||||
parser.addSymbol("Status", st);
|
parser.addSymbol("Status", st);
|
||||||
parser.addSymbol("Start", runner.getStartTime());
|
parser.addSymbol("Start", runner.getStartTime() / timeConstSecond);
|
||||||
parser.addSymbol("Finish", ft);
|
parser.addSymbol("Finish", ft / timeConstSecond);
|
||||||
parser.addSymbol("Time", runner.getRunningTime(useComputed));
|
parser.addSymbol("Time", runner.getRunningTime(useComputed) / timeConstSecond);
|
||||||
parser.addSymbol("Place", runner.getPlace(false));
|
parser.addSymbol("Place", runner.getPlace(false));
|
||||||
parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false));
|
parser.addSymbol("Points", runner.getRogainingPoints(useComputed, false));
|
||||||
parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed));
|
parser.addSymbol("PointReduction", runner.getRogainingReduction(useComputed));
|
||||||
parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed));
|
parser.addSymbol("PointOvertime", runner.getRogainingOvertime(useComputed) / timeConstSecond);
|
||||||
parser.addSymbol("PointGross", runner.getRogainingPointsGross(useComputed));
|
parser.addSymbol("PointGross", runner.getRogainingPointsGross(useComputed));
|
||||||
|
|
||||||
parser.addSymbol("PointAdjustment", runner.getPointAdjustment());
|
parser.addSymbol("PointAdjustment", runner.getPointAdjustment());
|
||||||
parser.addSymbol("TimeAdjustment", runner.getTimeAdjustment());
|
parser.addSymbol("TimeAdjustment", runner.getTimeAdjustment(true) / timeConstSecond);
|
||||||
|
|
||||||
parser.addSymbol("TotalStatus", runner.getTotalStatus());
|
parser.addSymbol("TotalStatus", runner.getTotalStatus(false));
|
||||||
parser.addSymbol("TotalTime", runner.getTotalRunningTime());
|
parser.addSymbol("TotalTime", runner.getTotalRunningTime()/timeConstSecond);
|
||||||
parser.addSymbol("TotalPlace", runner.getTotalPlace(false));
|
parser.addSymbol("TotalPlace", runner.getTotalPlace(false));
|
||||||
|
|
||||||
parser.addSymbol("InputStatus", runner.getInputStatus());
|
parser.addSymbol("InputStatus", runner.getInputStatus());
|
||||||
parser.addSymbol("InputTime", runner.getInputTime());
|
parser.addSymbol("InputTime", runner.getInputTime() / timeConstSecond);
|
||||||
parser.addSymbol("InputPlace", runner.getInputPlace());
|
parser.addSymbol("InputPlace", runner.getInputPlace());
|
||||||
parser.addSymbol("InputPoints", runner.getInputPoints());
|
parser.addSymbol("InputPoints", runner.getInputPoints());
|
||||||
parser.addSymbol("Shorten", runner.getNumShortening());
|
parser.addSymbol("Shorten", runner.getNumShortening());
|
||||||
@ -1191,13 +1191,16 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) con
|
|||||||
for (RunnerStatus s : inst)
|
for (RunnerStatus s : inst)
|
||||||
iinst.push_back(s);
|
iinst.push_back(s);
|
||||||
|
|
||||||
|
for (int &t : times)
|
||||||
|
t /= timeConstSecond;
|
||||||
|
|
||||||
parser.addSymbol("StageStatus", iinst);
|
parser.addSymbol("StageStatus", iinst);
|
||||||
parser.addSymbol("StageTime", times);
|
parser.addSymbol("StageTime", times);
|
||||||
parser.addSymbol("StagePlace", places);
|
parser.addSymbol("StagePlace", places);
|
||||||
parser.addSymbol("StagePoints", points);
|
parser.addSymbol("StagePoints", points);
|
||||||
|
|
||||||
parser.addSymbol("InputStatus", runner.getInputStatus());
|
parser.addSymbol("InputStatus", runner.getInputStatus());
|
||||||
parser.addSymbol("InputTime", runner.getInputTime());
|
parser.addSymbol("InputTime", runner.getInputTime() / timeConstSecond);
|
||||||
parser.addSymbol("InputPlace", runner.getInputPlace());
|
parser.addSymbol("InputPlace", runner.getInputPlace());
|
||||||
parser.addSymbol("InputPoints", runner.getInputPoints());
|
parser.addSymbol("InputPoints", runner.getInputPoints());
|
||||||
|
|
||||||
@ -1226,13 +1229,13 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
|
|||||||
for (int k = 0; k < nr; k++) {
|
for (int k = 0; k < nr; k++) {
|
||||||
pRunner r = team.getRunner(k);
|
pRunner r = team.getRunner(k);
|
||||||
if (r) {
|
if (r) {
|
||||||
oAbstractRunner::TempResult &res = r->getTempResult();
|
const oAbstractRunner::TempResult &res = r->getTempResult();
|
||||||
status[k] = res.getStatus();
|
status[k] = res.getStatus();
|
||||||
time[k] = res.getRunningTime();
|
time[k] = res.getRunningTime() / timeConstSecond;
|
||||||
if (time[k] > 0 && status[k] == StatusUnknown)
|
if (time[k] > 0 && status[k] == StatusUnknown)
|
||||||
status[k] = StatusOK;
|
status[k] = StatusOK;
|
||||||
start[k] = res.getStartTime();
|
start[k] = res.getStartTime() / timeConstSecond;
|
||||||
finish[k] = res.getFinishTime();
|
finish[k] = res.getFinishTime() / timeConstSecond;
|
||||||
points[k] = res.getPoints();
|
points[k] = res.getPoints();
|
||||||
if (classResult) {
|
if (classResult) {
|
||||||
r->updateComputedResultFromTemp();
|
r->updateComputedResultFromTemp();
|
||||||
@ -1281,7 +1284,7 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
|
|||||||
pClass cls = team.getClassRef(true);
|
pClass cls = team.getClassRef(true);
|
||||||
if (cls) {
|
if (cls) {
|
||||||
int nl = max<int>(1, cls->getNumStages() - 1);
|
int nl = max<int>(1, cls->getNumStages() - 1);
|
||||||
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, nl, false, false));
|
parser.addSymbol("ShortestClassTime", cls->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, nl, false, false) / timeConstSecond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1303,7 +1306,7 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
|
|||||||
int ip = 0;
|
int ip = 0;
|
||||||
for (size_t k = 0; k < punches.size(); k++) {
|
for (size_t k = 0; k < punches.size(); k++) {
|
||||||
if (punches[k]->getTypeCode() >= 30) {
|
if (punches[k]->getTypeCode() >= 30) {
|
||||||
times[ip] = punches[k]->getAdjustedTime();
|
times[ip] = punches[k]->getAdjustedTime() / timeConstSecond;
|
||||||
codes[ip] = punches[k]->getTypeCode();
|
codes[ip] = punches[k]->getTypeCode();
|
||||||
controls[ip] = punches[k]->isUsedInCourse() ? punches[k]->getControlId() : -1;
|
controls[ip] = punches[k]->isUsedInCourse() ? punches[k]->getControlId() : -1;
|
||||||
ip++;
|
ip++;
|
||||||
@ -1345,16 +1348,16 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
|
|||||||
if (ctrl->isSingleStatusOK()) {
|
if (ctrl->isSingleStatusOK()) {
|
||||||
eCrs.push_back(ctrl->getFirstNumber());
|
eCrs.push_back(ctrl->getFirstNumber());
|
||||||
if (size_t(k) < sp.size()) {
|
if (size_t(k) < sp.size()) {
|
||||||
if (sp[k].status == SplitData::OK) {
|
if (sp[k].hasTime()) {
|
||||||
eAccTime.push_back(sp[k].time - start);
|
eAccTime.push_back((sp[k].getTime(false) - start) / timeConstSecond);
|
||||||
eSplitTime.push_back(sp[k].time - st);
|
eSplitTime.push_back((sp[k].getTime(false) - st) / timeConstSecond);
|
||||||
st = sp[k].time;
|
st = sp[k].getTime(false);
|
||||||
}
|
}
|
||||||
else if (sp[k].status == SplitData::NoTime) {
|
else if (sp[k].getStatus() == SplitData::SplitStatus::NoTime) {
|
||||||
eAccTime.push_back(st - start);
|
eAccTime.push_back( (st - start) / timeConstSecond);
|
||||||
eSplitTime.push_back(0);
|
eSplitTime.push_back(0);
|
||||||
}
|
}
|
||||||
else if (sp[k].status == SplitData::Missing) {
|
else if (sp[k].isMissing()) {
|
||||||
eAccTime.push_back(0);
|
eAccTime.push_back(0);
|
||||||
eSplitTime.push_back(-1);
|
eSplitTime.push_back(-1);
|
||||||
}
|
}
|
||||||
@ -1362,8 +1365,8 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runner.getFinishTime() > 0) {
|
if (runner.getFinishTime() > 0) {
|
||||||
eAccTime.push_back(runner.getFinishTime() - start);
|
eAccTime.push_back((runner.getFinishTime() - start) / timeConstSecond);
|
||||||
eSplitTime.push_back(runner.getFinishTime() - st);
|
eSplitTime.push_back((runner.getFinishTime() - st) / timeConstSecond);
|
||||||
}
|
}
|
||||||
else if (!eAccTime.empty()) {
|
else if (!eAccTime.empty()) {
|
||||||
eAccTime.push_back(0);
|
eAccTime.push_back(0);
|
||||||
@ -1394,7 +1397,7 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
|
|||||||
pClass cls = runner.getClassRef(true);
|
pClass cls = runner.getClassRef(true);
|
||||||
if (cls) {
|
if (cls) {
|
||||||
int nl = runner.getLegNumber();
|
int nl = runner.getLegNumber();
|
||||||
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(oClass::AllowRecompute::Yes, nl, false));
|
parser.addSymbol("ShortestClassTime", cls->getBestLegTime(oClass::AllowRecompute::Yes, nl, false) / timeConstSecond);
|
||||||
}
|
}
|
||||||
vector<int> delta;
|
vector<int> delta;
|
||||||
vector<int> place;
|
vector<int> place;
|
||||||
@ -1523,7 +1526,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
|
|||||||
else {
|
else {
|
||||||
oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult, inclPreliminary);
|
oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult, inclPreliminary);
|
||||||
for (pRunner r : runners) {
|
for (pRunner r : runners) {
|
||||||
ri.status = r->getTotalStatus();
|
ri.status = r->getTotalStatus(false);
|
||||||
if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) {
|
if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) {
|
||||||
if (r->getFinishTime() == 0) {
|
if (r->getFinishTime() == 0) {
|
||||||
if (!inclForestRunners)
|
if (!inclForestRunners)
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
193
code/image.cpp
193
code/image.cpp
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -89,9 +89,9 @@ vector<uint8_t> Image::loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HBITMAP Image::read_png(vector<uint8_t> &inData, int &width, int &height, ImageMethod method) {
|
HBITMAP Image::read_png(vector<uint8_t> &&inData, int &width, int &height, ImageMethod method) {
|
||||||
PngData inputStream;
|
PngData inputStream;
|
||||||
inputStream.memory.swap(inData);
|
inputStream.memory = std::move(inData);
|
||||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
if (!png)
|
if (!png)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -196,25 +196,57 @@ HBITMAP Image::read_png(vector<uint8_t> &inData, int &width, int &height, ImageM
|
|||||||
row[x + 3] = src[x + 3];
|
row[x + 3] = src[x + 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (method == ImageMethod::WhiteTransparent) {
|
||||||
|
for (size_t x = 0; x < cbStride; x += 4) {
|
||||||
|
row[x + 2] = src[x + 0]; // Red
|
||||||
|
row[x + 1] = src[x + 1]; // Green
|
||||||
|
row[x + 0] = src[x + 2]; // Blue
|
||||||
|
row[x + 3] = src[x + 3];
|
||||||
|
if (src[x + 0] == 0xFF && src[x + 1] == 0xFF && src[x + 2] == 0xFF) {
|
||||||
|
row[x + 3] = 0;
|
||||||
|
row[x + 2] = 0;
|
||||||
|
row[x + 1] = 0;
|
||||||
|
row[x + 0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return hbmp;
|
return hbmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
HBITMAP Image::read_png_file(const wstring &filename, int &width, int &height, ImageMethod method) {
|
uint64_t Image::computeHash(const vector<uint8_t>& data) {
|
||||||
width = 0;
|
uint64_t h = data.size();
|
||||||
height = 0;
|
size_t siz4 = data.size() / 4;
|
||||||
PngData inputStream;
|
const uint32_t* ptr = (const uint32_t *)data.data();
|
||||||
inputStream.memory;
|
size_t lim = siz4 * 4;
|
||||||
|
for (size_t e = siz4 * 4; e < data.size(); e++)
|
||||||
|
h = h * 256 + data[e];
|
||||||
|
|
||||||
|
for (size_t e = 0; e < siz4; e++) {
|
||||||
|
h = 997 * h + ptr[e];
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::read_file(const wstring& filename, vector<uint8_t>& data) {
|
||||||
ifstream fin;
|
ifstream fin;
|
||||||
fin.open(filename, ios::binary);
|
fin.open(filename, ios::binary);
|
||||||
fin.seekg(0, ios::end);
|
fin.seekg(0, ios::end);
|
||||||
int p2 = (int)fin.tellg();
|
int p2 = (int)fin.tellg();
|
||||||
fin.seekg(0, ios::beg);
|
fin.seekg(0, ios::beg);
|
||||||
inputStream.memory.resize(p2);
|
data.resize(p2);
|
||||||
fin.read((char *)&inputStream.memory[0], inputStream.memory.size());
|
fin.read((char*)data.data(), data.size());
|
||||||
fin.close();
|
fin.close();
|
||||||
return read_png(inputStream.memory, width, height, method);
|
}
|
||||||
|
|
||||||
|
HBITMAP Image::read_png_file(const wstring &filename, int &width, int &height, uint64_t &hash, ImageMethod method) {
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
PngData inputStream;
|
||||||
|
read_file(filename, inputStream.memory);
|
||||||
|
hash = computeHash(inputStream.memory);
|
||||||
|
return read_png(std::move(inputStream.memory), width, height, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
HBITMAP Image::read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method) {
|
HBITMAP Image::read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method) {
|
||||||
@ -224,7 +256,7 @@ HBITMAP Image::read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int
|
|||||||
inputStream.memory = loadResourceToMemory(lpName, lpType);
|
inputStream.memory = loadResourceToMemory(lpName, lpType);
|
||||||
if (inputStream.memory.empty())
|
if (inputStream.memory.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return read_png(inputStream.memory, width, height, method);
|
return read_png(std::move(inputStream.memory), width, height, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image()
|
Image::Image()
|
||||||
@ -236,7 +268,7 @@ Image::~Image()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loads the PNG containing the splash image into a HBITMAP.
|
// Loads the PNG containing the splash image into a HBITMAP.
|
||||||
HBITMAP Image::loadImage(int resource, ImageMethod method) {
|
HBITMAP Image::loadImage(uint64_t resource, ImageMethod method) {
|
||||||
if (images.count(resource))
|
if (images.count(resource))
|
||||||
return images[resource].image;
|
return images[resource].image;
|
||||||
|
|
||||||
@ -250,18 +282,22 @@ HBITMAP Image::loadImage(int resource, ImageMethod method) {
|
|||||||
return hbmp;
|
return hbmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Image::getWidth(int resource) {
|
int Image::getWidth(uint64_t resource) {
|
||||||
loadImage(resource, ImageMethod::Default);
|
loadImage(resource, ImageMethod::Default);
|
||||||
return images[resource].width;
|
return images[resource].width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Image::getHeight(int resource) {
|
int Image::getHeight(uint64_t resource) {
|
||||||
loadImage(resource, ImageMethod::Default);
|
loadImage(resource, ImageMethod::Default);
|
||||||
return images[resource].height;
|
return images[resource].height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height) {
|
void Image::drawImage(uint64_t resource, ImageMethod method, HDC hDC, int x, int y, int width, int height) {
|
||||||
HBITMAP bmp = loadImage(resource, method);
|
HBITMAP bmp = loadImage(resource, method);
|
||||||
|
auto res = images.find(resource);
|
||||||
|
if (res == images.end())
|
||||||
|
return;
|
||||||
|
|
||||||
HDC memdc = CreateCompatibleDC(hDC);
|
HDC memdc = CreateCompatibleDC(hDC);
|
||||||
SelectObject(memdc, bmp);
|
SelectObject(memdc, bmp);
|
||||||
|
|
||||||
@ -270,7 +306,130 @@ void Image::drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, i
|
|||||||
bf.BlendFlags = 0;
|
bf.BlendFlags = 0;
|
||||||
bf.SourceConstantAlpha =0xFF;
|
bf.SourceConstantAlpha =0xFF;
|
||||||
bf.AlphaFormat = AC_SRC_ALPHA;
|
bf.AlphaFormat = AC_SRC_ALPHA;
|
||||||
AlphaBlend(hDC, x, y, width, height, memdc, 0, 0, width, height, bf);
|
AlphaBlend(hDC, x, y, width, height, memdc, 0, 0, res->second.width, res->second.height, bf);
|
||||||
|
|
||||||
DeleteDC(memdc);
|
DeleteDC(memdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Image::loadFromFile(const wstring& path, ImageMethod method) {
|
||||||
|
vector<uint8_t> bytes;
|
||||||
|
read_file(path, bytes);
|
||||||
|
|
||||||
|
uint64_t hash = computeHash(bytes);
|
||||||
|
|
||||||
|
auto res = images.emplace(hash, Bmp());
|
||||||
|
if (res.second) {
|
||||||
|
wchar_t drive[20];
|
||||||
|
wchar_t dir[MAX_PATH];
|
||||||
|
wchar_t name[MAX_PATH];
|
||||||
|
wchar_t ext[MAX_PATH];
|
||||||
|
_wsplitpath_s(path.c_str(), drive, dir, name, ext);
|
||||||
|
Bmp &out = res.first->second;
|
||||||
|
out.fileName = wstring(name) + ext;
|
||||||
|
out.rawData = bytes;
|
||||||
|
out.image = read_png(std::move(bytes), out.width, out.height, method);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Image::loadFromMemory(const wstring& fileName, const vector<uint8_t>& bytes, ImageMethod method) {
|
||||||
|
uint64_t hash = computeHash(bytes);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::provideFromMemory(uint64_t id, const wstring& fileName, const vector<uint8_t>& bytes) {
|
||||||
|
uint64_t hash = computeHash(bytes);
|
||||||
|
if (id != hash)
|
||||||
|
throw meosException(L"Corrupted image: " + fileName);
|
||||||
|
|
||||||
|
images[id].fileName = fileName;
|
||||||
|
images[id].rawData = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::addImage(uint64_t id, const wstring& fileName) {
|
||||||
|
images[id].fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::reloadImage(uint64_t imgId, ImageMethod method) {
|
||||||
|
auto res = images.find(imgId);
|
||||||
|
if (res != images.end() && res->second.rawData.size() > 0) {
|
||||||
|
auto copy = res->second.rawData;
|
||||||
|
res->second.destroy();
|
||||||
|
res->second.image = read_png(std::move(copy), res->second.width, res->second.height, method);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw meosException("Unknown image " + itos(imgId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::clearLoaded() {
|
||||||
|
for (auto iter = images.begin(); iter != images.end(); ) {
|
||||||
|
if (iter->second.fileName.empty())
|
||||||
|
++iter;
|
||||||
|
else {
|
||||||
|
iter = images.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Bmp::~Bmp() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::Bmp::destroy() {
|
||||||
|
if (image) {
|
||||||
|
DeleteObject(image);
|
||||||
|
image = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Image::enumerateImages(vector<pair<wstring, size_t>>& img) const {
|
||||||
|
img.clear();
|
||||||
|
for (auto& bmp : images) {
|
||||||
|
if (bmp.second.fileName.size() > 0)
|
||||||
|
img.emplace_back(bmp.second.fileName, img.size());
|
||||||
|
}
|
||||||
|
sort(img.begin(), img.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Image::getIdFromEnumeration(int enumerationIx) const {
|
||||||
|
int ix = 0;
|
||||||
|
for (auto& bmp : images) {
|
||||||
|
if (bmp.second.fileName.size() > 0) {
|
||||||
|
if (enumerationIx == ix++) {
|
||||||
|
return bmp.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw meosException("Internal error");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Image::getEnumerationIxFromId(uint64_t imgId) const {
|
||||||
|
int ix = 0;
|
||||||
|
for (auto& bmp : images) {
|
||||||
|
if (bmp.second.fileName.size() > 0) {
|
||||||
|
if (imgId == bmp.first)
|
||||||
|
return ix;
|
||||||
|
ix++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wstring& Image::getFileName(uint64_t imgId) const {
|
||||||
|
if (!hasImage(imgId))
|
||||||
|
throw meosException("Missing image: " + itos(imgId));
|
||||||
|
return images.at(imgId).fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vector<uint8_t>& Image::getRawData(uint64_t imgId) const {
|
||||||
|
if (!hasImage(imgId))
|
||||||
|
throw meosException("Missing image: " + itos(imgId));
|
||||||
|
return images.at(imgId).rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Image::hasImage(uint64_t imgId) const {
|
||||||
|
auto res = images.find(imgId);
|
||||||
|
return res != images.end() && res->second.rawData.size() > 0;
|
||||||
|
}
|
||||||
|
|||||||
51
code/image.h
51
code/image.h
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -29,34 +29,57 @@ class Image {
|
|||||||
public:
|
public:
|
||||||
enum class ImageMethod {
|
enum class ImageMethod {
|
||||||
Default,
|
Default,
|
||||||
MonoAlpha
|
MonoAlpha,
|
||||||
|
WhiteTransparent
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static HBITMAP read_png_file(const wstring &filename, int &width, int &height, ImageMethod method);
|
static uint64_t computeHash(const vector<uint8_t>& data);
|
||||||
|
|
||||||
|
static void read_file(const wstring& filename, vector<uint8_t>& data);
|
||||||
|
|
||||||
|
static HBITMAP read_png_file(const wstring &filename, int &width, int &height, uint64_t &hash, ImageMethod method);
|
||||||
static HBITMAP read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method);
|
static HBITMAP read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method);
|
||||||
static HBITMAP read_png(vector<uint8_t> &data, int &width, int &height, ImageMethod method);
|
static HBITMAP read_png(vector<uint8_t> &&data, int &width, int &height, ImageMethod method);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Bmp {
|
struct Bmp {
|
||||||
HBITMAP image;
|
HBITMAP image = nullptr;
|
||||||
int width;
|
int width = -1;
|
||||||
int height;
|
int height = -1;
|
||||||
|
wstring fileName;
|
||||||
|
vector<uint8_t> rawData;
|
||||||
|
~Bmp();
|
||||||
|
void destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
map<int, Bmp> images;
|
map<uint64_t, Bmp> images;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HBITMAP loadImage(int resource, ImageMethod method);
|
HBITMAP loadImage(uint64_t resource, ImageMethod method);
|
||||||
|
|
||||||
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
|
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
|
||||||
|
|
||||||
int getWidth(int resource);
|
int getWidth(uint64_t resource);
|
||||||
int getHeight(int resource);
|
int getHeight(uint64_t resource);
|
||||||
void drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height);
|
void drawImage(uint64_t resource, ImageMethod method, HDC hDC, int x, int y, int width, int height);
|
||||||
|
|
||||||
|
uint64_t loadFromFile(const wstring& path, ImageMethod method);
|
||||||
|
uint64_t loadFromMemory(const wstring& fileName, const vector<uint8_t> &bytes, ImageMethod method);
|
||||||
|
void provideFromMemory(uint64_t id, const wstring& fileName, const vector<uint8_t>& bytes);
|
||||||
|
void addImage(uint64_t id, const wstring& fileName);
|
||||||
|
|
||||||
|
void clearLoaded();
|
||||||
|
|
||||||
|
void enumerateImages(vector<pair<wstring, size_t>>& img) const;
|
||||||
|
uint64_t getIdFromEnumeration(int enumerationIx) const;
|
||||||
|
int getEnumerationIxFromId(uint64_t imgId) const;
|
||||||
|
|
||||||
|
bool hasImage(uint64_t imgId) const;
|
||||||
|
void reloadImage(uint64_t imgId, ImageMethod method);
|
||||||
|
|
||||||
|
const wstring& getFileName(uint64_t imgId) const;
|
||||||
|
const vector<uint8_t> &getRawData(uint64_t imgId) const;
|
||||||
Image();
|
Image();
|
||||||
~Image();
|
~Image();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
BIN
code/info24.png
Normal file
BIN
code/info24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 874 B |
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -501,9 +501,9 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
|
|||||||
ch = true;
|
ch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunnerStatus s = bc.getStatusComputed();
|
RunnerStatus s = bc.getStatusComputed(true);
|
||||||
|
|
||||||
int rt = bc.getRunningTime(true) * 10;
|
int rt = bc.getRunningTime(true) * (10/timeConstSecond);
|
||||||
if (rt > 0) {
|
if (rt > 0) {
|
||||||
if (s == RunnerStatus::StatusUnknown)
|
if (s == RunnerStatus::StatusUnknown)
|
||||||
s = RunnerStatus::StatusOK;
|
s = RunnerStatus::StatusOK;
|
||||||
@ -521,7 +521,7 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
|
|||||||
|
|
||||||
int st = -1;
|
int st = -1;
|
||||||
if (bc.startTimeAvailable())
|
if (bc.startTimeAvailable())
|
||||||
st = convertRelativeTime(bc, bc.getStartTime()) * 10;
|
st = convertRelativeTime(bc, bc.getStartTime()) * (10 / timeConstSecond);
|
||||||
|
|
||||||
if (st != startTime) {
|
if (st != startTime) {
|
||||||
startTime = st;
|
startTime = st;
|
||||||
@ -564,7 +564,7 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
|
|||||||
|
|
||||||
pTeam t = r.getTeam();
|
pTeam t = r.getTeam();
|
||||||
if (useTotalResults) {
|
if (useTotalResults) {
|
||||||
legInput = r.getTotalTimeInput() * 10;
|
legInput = r.getTotalTimeInput() * (10 / timeConstSecond);
|
||||||
s = r.getTotalStatusInput();
|
s = r.getTotalStatusInput();
|
||||||
}
|
}
|
||||||
else if (t && !isQF && r.getLegNumber() > 0) {
|
else if (t && !isQF && r.getLegNumber() > 0) {
|
||||||
@ -578,7 +578,7 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ltu > 0) {
|
if (ltu > 0) {
|
||||||
legInput = t->getLegRunningTime(ltu - 1, true, false) * 10;
|
legInput = t->getLegRunningTime(ltu - 1, true, false) * (10 / timeConstSecond);
|
||||||
s = t->getLegStatus(ltu - 1, true, false);
|
s = t->getLegStatus(ltu - 1, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,7 +625,7 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<RadioTime> newRT;
|
vector<RadioTime> newRT;
|
||||||
if (r.getClassId(false) > 0 && r.getStatusComputed() != RunnerStatus::StatusNoTiming) {
|
if (r.getClassId(false) > 0 && r.getStatusComputed(true) != RunnerStatus::StatusNoTiming) {
|
||||||
const vector<int> &radios = cmp.getControls(r.getClassId(true), r.getLegNumber());
|
const vector<int> &radios = cmp.getControls(r.getClassId(true), r.getLegNumber());
|
||||||
for (size_t k = 0; k < radios.size(); k++) {
|
for (size_t k = 0; k < radios.size(); k++) {
|
||||||
RadioTime radioTime;
|
RadioTime radioTime;
|
||||||
@ -634,7 +634,7 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
|
|||||||
r.getSplitTime(radioTime.radioId, s_split, radioTime.runningTime);
|
r.getSplitTime(radioTime.radioId, s_split, radioTime.runningTime);
|
||||||
|
|
||||||
if (radioTime.runningTime > 0) {
|
if (radioTime.runningTime > 0) {
|
||||||
radioTime.runningTime*=10;
|
radioTime.runningTime *= (10 / timeConstSecond);
|
||||||
newRT.push_back(radioTime);
|
newRT.push_back(radioTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -224,8 +224,8 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
bool forceComplete;
|
bool forceComplete;
|
||||||
|
|
||||||
bool includeTotal;
|
bool includeTotal = false;
|
||||||
bool withCourse;
|
bool withCourse = false;
|
||||||
|
|
||||||
list<InfoBase *> toCommit;
|
list<InfoBase *> toCommit;
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -54,9 +54,9 @@ vector<int> parseSGTimes(const oEvent &oe, const wstring &name) {
|
|||||||
return times;
|
return times;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOF30Interface::IOF30Interface(oEvent *oe, bool forceSplitFee) : oe(*oe), useGMT(false), teamsAsIndividual(false),
|
IOF30Interface::IOF30Interface(oEvent *oe, bool forceSplitFee, bool useEventorQuirks) : oe(*oe), useGMT(false), teamsAsIndividual(false),
|
||||||
entrySourceId(1), unrollLoops(true),
|
entrySourceId(1), unrollLoops(true),
|
||||||
includeStageRaceInfo(true) {
|
includeStageRaceInfo(true), useEventorQuirks(useEventorQuirks) {
|
||||||
cachedStageNumber = -1;
|
cachedStageNumber = -1;
|
||||||
splitLateFee = forceSplitFee || oe->getPropertyInt("SplitLateFees", false) == 1;
|
splitLateFee = forceSplitFee || oe->getPropertyInt("SplitLateFees", false) == 1;
|
||||||
}
|
}
|
||||||
@ -705,7 +705,7 @@ void IOF30Interface::assignTeamCourse(gdioutput &gdi, oTeam *team, int iClass, i
|
|||||||
if (team) {
|
if (team) {
|
||||||
pRunner r = team->getRunner(legId);
|
pRunner r = team->getRunner(legId);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(false), 0, 0, false);
|
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(false), 0, L"", false);
|
||||||
if (r) {
|
if (r) {
|
||||||
r->setEntrySource(entrySourceId);
|
r->setEntrySource(entrySourceId);
|
||||||
r->flagEntryTouched(true);
|
r->flagEntryTouched(true);
|
||||||
@ -959,7 +959,8 @@ void IOF30Interface::prescanCompetitorList(xmlobject &xo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOF30Interface::readCompetitorList(gdioutput &gdi, const xmlobject &xo, int &personCount) {
|
void IOF30Interface::readCompetitorList(gdioutput &gdi, const xmlobject &xo,
|
||||||
|
bool onlyWithClub, int &personCount, int &duplicateCount) {
|
||||||
if (!xo)
|
if (!xo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -971,11 +972,10 @@ void IOF30Interface::readCompetitorList(gdioutput &gdi, const xmlobject &xo, int
|
|||||||
xmlList xl;
|
xmlList xl;
|
||||||
xo.getObjects(xl);
|
xo.getObjects(xl);
|
||||||
|
|
||||||
xmlList::const_iterator it;
|
unordered_multimap<size_t, int> duplicateCheck;
|
||||||
|
for (auto &it : xl) {
|
||||||
for (it = xl.begin(); it != xl.end(); ++it) {
|
if (it.is("Competitor")) {
|
||||||
if (it->is("Competitor")) {
|
if (readXMLCompetitorDB(it, onlyWithClub, duplicateCheck, duplicateCount))
|
||||||
if (readXMLCompetitorDB(*it))
|
|
||||||
personCount++;
|
personCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1409,12 +1409,17 @@ void IOF30Interface::readStartList(gdioutput &gdi, xmlobject &xo, int &entRead,
|
|||||||
if (raceToInfo.size() == 1) {
|
if (raceToInfo.size() == 1) {
|
||||||
RaceInfo &raceInfo = raceToInfo.begin()->second;
|
RaceInfo &raceInfo = raceToInfo.begin()->second;
|
||||||
if (raceInfo.courseId > 0) {
|
if (raceInfo.courseId > 0) {
|
||||||
if (pc->getCourse() == 0) {
|
if (pc->getCourse() == nullptr) {
|
||||||
pCourse crs = oe.addCourse(pc->getName(), raceInfo.length, raceInfo.courseId);
|
pCourse crs = raceInfo.courseId > 0 ? oe.getCourse(raceInfo.courseId) : nullptr;
|
||||||
crs->setStart(raceInfo.startName, false);
|
if (crs == nullptr)
|
||||||
crs->getDI().setInt("Climb", raceInfo.climb);
|
crs = oe.addCourse(pc->getName(), raceInfo.length, raceInfo.courseId);
|
||||||
pc->setCourse(crs);
|
|
||||||
crs->synchronize();
|
if (crs != nullptr) {
|
||||||
|
crs->setStart(raceInfo.startName, false);
|
||||||
|
crs->getDI().setInt("Climb", raceInfo.climb);
|
||||||
|
pc->setCourse(crs);
|
||||||
|
crs->synchronize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1639,12 +1644,12 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
|
|||||||
timeStr.swap(tTime);
|
timeStr.swap(tTime);
|
||||||
int t = convertAbsoluteTimeISO(timeStr);
|
int t = convertAbsoluteTimeISO(timeStr);
|
||||||
if (t >= 0 && oe.getNumRunners() == 0) {
|
if (t >= 0 && oe.getNumRunners() == 0) {
|
||||||
int zt = t - 3600;
|
int zt = t - timeConstHour;
|
||||||
if (zt < 0)
|
if (zt < 0)
|
||||||
zt += 3600*24;
|
zt += timeConstHour *24;
|
||||||
|
|
||||||
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
|
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
|
||||||
oe.setZeroTime(formatTimeHMS(zt), false);
|
oe.setZeroTime(formatTimeHMS(zt, SubSecond::Auto), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
|
if (!oe.hasFlag(oEvent::TransferFlags::FlagManualDateTime))
|
||||||
@ -1762,7 +1767,7 @@ void IOF30Interface::readEvent(gdioutput &gdi, const xmlobject &xo,
|
|||||||
xmlList nameList;
|
xmlList nameList;
|
||||||
s.getObjects("Name", nameList);
|
s.getObjects("Name", nameList);
|
||||||
for (auto s : nameList) {
|
for (auto s : nameList) {
|
||||||
services.emplace_back(id, s.getw());
|
services.emplace_back(id, s.getWStr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2079,7 +2084,7 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
|
|||||||
|
|
||||||
if (cardNo > 0 && r == 0 && team) {
|
if (cardNo > 0 && r == 0 && team) {
|
||||||
// We got no person, but a card number. Add the runner anonymously.
|
// We got no person, but a card number. Add the runner anonymously.
|
||||||
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(false), cardNo, 0, false);
|
r = oe.addRunner(lang.tl(L"N.N."), team->getClubId(), team->getClassId(false), cardNo, L"", false);
|
||||||
r->flagEntryTouched(true);
|
r->flagEntryTouched(true);
|
||||||
r->setEntrySource(entrySourceId);
|
r->setEntrySource(entrySourceId);
|
||||||
r->synchronize();
|
r->synchronize();
|
||||||
@ -2197,7 +2202,7 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
|
|||||||
if (ts >= 2 && times[ts - 2] < times[ts - 1])
|
if (ts >= 2 && times[ts - 2] < times[ts - 1])
|
||||||
oe.setStartGroup(groupId, times[ts - 2], times[ts - 1], groupName);
|
oe.setStartGroup(groupId, times[ts - 2], times[ts - 1], groupName);
|
||||||
else
|
else
|
||||||
oe.setStartGroup(groupId, 3600, 3600 * 2, groupName);
|
oe.setStartGroup(groupId, timeConstHour, timeConstHour * 2, groupName);
|
||||||
}
|
}
|
||||||
r->setStartGroup(groupId);
|
r->setStartGroup(groupId);
|
||||||
}
|
}
|
||||||
@ -2415,14 +2420,14 @@ pRunner IOF30Interface::readPersonResult(gdioutput &gdi, pClass pc, xmlobject &x
|
|||||||
int time = split.getObjectInt("Time");
|
int time = split.getObjectInt("Time");
|
||||||
split.getObjectString("status", s);
|
split.getObjectString("status", s);
|
||||||
if (s != L"missing")
|
if (s != L"missing")
|
||||||
card->addPunch(code, st + time, 0);
|
card->addPunch(code, st + time, 0, 0);
|
||||||
|
|
||||||
if (s != L"additional")
|
if (s != L"additional")
|
||||||
controls.push_back(code);
|
controls.push_back(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ft > 0)
|
if (ft > 0)
|
||||||
card->addPunch(oPunch::PunchFinish, ft, 0);
|
card->addPunch(oPunch::PunchFinish, ft, 0, 0);
|
||||||
|
|
||||||
//Update to SQL-source
|
//Update to SQL-source
|
||||||
card->synchronize();
|
card->synchronize();
|
||||||
@ -2469,11 +2474,11 @@ void IOF30Interface::readId(const xmlobject &person, int &pid, __int64 &extId) c
|
|||||||
person.getObjects("Id", sids);
|
person.getObjects("Id", sids);
|
||||||
for (auto &x : sids) {
|
for (auto &x : sids) {
|
||||||
auto type = x.getAttrib("type");
|
auto type = x.getAttrib("type");
|
||||||
if (type && type.get() == preferredIdProvider) {
|
if (type && type.getPtr() == preferredIdProvider) {
|
||||||
sid = x.getw();
|
sid = x.getWStr();
|
||||||
}
|
}
|
||||||
else if (bsid.empty())
|
else if (bsid.empty())
|
||||||
bsid = x.getw();
|
bsid = x.getWStr();
|
||||||
}
|
}
|
||||||
if (sid.empty())
|
if (sid.empty())
|
||||||
pid = oBase::idFromExtId(oBase::converExtIdentifierString(bsid));
|
pid = oBase::idFromExtId(oBase::converExtIdentifierString(bsid));
|
||||||
@ -2583,9 +2588,8 @@ pRunner IOF30Interface::readPerson(gdioutput &gdi, const xmlobject &person) {
|
|||||||
if (s != sUnknown)
|
if (s != sUnknown)
|
||||||
r->setSex(s);
|
r->setSex(s);
|
||||||
person.getObjectString("BirthDate", tmp);
|
person.getObjectString("BirthDate", tmp);
|
||||||
if (tmp.length()>=4) {
|
if (tmp.length()>=4) {
|
||||||
tmp = tmp.substr(0, 4);
|
r->setBirthDate(tmp);
|
||||||
r->setBirthYear(_wtoi(tmp.c_str()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNationality(person.getObject("Nationality"), DI);
|
getNationality(person.getObject("Nationality"), DI);
|
||||||
@ -2884,9 +2888,9 @@ void IOF30Interface::FeeInfo::add(IOF30Interface::FeeInfo &fi) {
|
|||||||
if (!fi.toTime.empty()) {
|
if (!fi.toTime.empty()) {
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
convertDateYMS(fi.toTime, st, false);
|
convertDateYMS(fi.toTime, st, false);
|
||||||
__int64 sec = SystemTimeToInt64Second(st);
|
__int64 sec = SystemTimeToInt64TenthSecond(st);
|
||||||
sec -= 3600;
|
sec -= timeConstHour;
|
||||||
fi.toTime = convertSystemDate(Int64SecondToSystemTime(sec));
|
fi.toTime = convertSystemDate(Int64TenthSecondToSystemTime(sec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (fi.fromTime.empty() || (fi.fromTime < toTime && !toTime.empty()))
|
//if (fi.fromTime.empty() || (fi.fromTime < toTime && !toTime.empty()))
|
||||||
@ -3069,7 +3073,7 @@ void IOF30Interface::setupRelayClass(pClass pc, const vector<LegInfo> &legs) {
|
|||||||
|
|
||||||
pc->setNumStages(nStage);
|
pc->setNumStages(nStage);
|
||||||
pc->setStartType(0, STTime, false);
|
pc->setStartType(0, STTime, false);
|
||||||
pc->setStartData(0, oe.getAbsTime(3600));
|
pc->setStartData(0, oe.getAbsTime(timeConstHour));
|
||||||
|
|
||||||
int ix = 0;
|
int ix = 0;
|
||||||
for (size_t k = 0; k < legs.size(); k++) {
|
for (size_t k = 0; k < legs.size(); k++) {
|
||||||
@ -3097,10 +3101,24 @@ wstring IOF30Interface::getCurrentTime() const {
|
|||||||
return getLocalDate() + L"T" + getLocalTimeOnly();
|
return getLocalDate() + L"T" + getLocalTimeOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wstring IOF30Interface::formatRelTime(int rt) {
|
||||||
|
wchar_t bf[32];
|
||||||
|
if (oe.useSubSecond())
|
||||||
|
swprintf_s(bf, L"%d.%d", rt / timeConstSecond, rt % timeConstSecond);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"%d", rt / timeConstSecond);
|
||||||
|
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int IOF30Interface::parseISO8601Time(const xmlobject &xo) {
|
int IOF30Interface::parseISO8601Time(const xmlobject &xo) {
|
||||||
if (!xo)
|
if (!xo)
|
||||||
return 0;
|
return 0;
|
||||||
const char *t = xo.getRaw();
|
const char *t = xo.getRawPtr();
|
||||||
|
if (!t)
|
||||||
|
return 0;
|
||||||
int tIx = -1;
|
int tIx = -1;
|
||||||
int zIx = -1;
|
int zIx = -1;
|
||||||
for (int k = 0; t[k] != 0; k++) {
|
for (int k = 0; t[k] != 0; k++) {
|
||||||
@ -3160,9 +3178,9 @@ void IOF30Interface::getLocalDateTime(const string &date, const string &time,
|
|||||||
int idate = convertDateYMS(date, st, true);
|
int idate = convertDateYMS(date, st, true);
|
||||||
if (idate != -1) {
|
if (idate != -1) {
|
||||||
if (zone == "Z" || zone == "z") {
|
if (zone == "Z" || zone == "z") {
|
||||||
st.wHour = atime / 3600;
|
st.wHour = atime / timeConstHour;
|
||||||
st.wMinute = (atime / 60) % 60;
|
st.wMinute = (atime / timeConstMinute) % 60;
|
||||||
st.wSecond = atime % 60;
|
st.wSecond = (atime / timeConstSecond) % 60;
|
||||||
|
|
||||||
SYSTEMTIME localTime;
|
SYSTEMTIME localTime;
|
||||||
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
||||||
@ -3219,26 +3237,24 @@ void IOF30Interface::getLocalDateTime(const wstring &date, const wstring &time,
|
|||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
memset(&st, 0, sizeof(SYSTEMTIME));
|
memset(&st, 0, sizeof(SYSTEMTIME));
|
||||||
|
|
||||||
int atime = convertAbsoluteTimeISO(wTime);
|
const int atime = convertAbsoluteTimeISO(wTime);
|
||||||
int idate = convertDateYMS(date, st, true);
|
int idate = convertDateYMS(date, st, true);
|
||||||
if (idate != -1) {
|
if (idate != -1) {
|
||||||
if (zone == L"Z" || zone == L"z") {
|
if (zone == L"Z" || zone == L"z") {
|
||||||
st.wHour = atime / 3600;
|
st.wHour = atime / timeConstHour;
|
||||||
st.wMinute = (atime / 60) % 60;
|
st.wMinute = (atime / timeConstMinute) % 60;
|
||||||
st.wSecond = atime % 60;
|
st.wSecond = (atime / timeConstSecond) % 60;
|
||||||
|
|
||||||
SYSTEMTIME localTime;
|
SYSTEMTIME localTime;
|
||||||
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
memset(&localTime, 0, sizeof(SYSTEMTIME));
|
||||||
SystemTimeToTzSpecificLocalTime(0, &st, &localTime);
|
SystemTimeToTzSpecificLocalTime(0, &st, &localTime);
|
||||||
|
|
||||||
atime = localTime.wHour * 3600 + localTime.wMinute * 60 + localTime.wSecond;
|
//atime = localTime.wHour * 3600 + localTime.wMinute * 60 + localTime.wSecond;
|
||||||
wchar_t bf[64];
|
wchar_t bf[64];
|
||||||
wsprintf(bf, L"%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
wsprintf(bf, L"%02d:%02d:%02d", localTime.wHour, localTime.wMinute, localTime.wSecond);
|
||||||
timeOut = bf;
|
timeOut = bf;
|
||||||
wsprintf(bf, L"%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
wsprintf(bf, L"%d-%02d-%02d", localTime.wYear, localTime.wMonth, localTime.wDay);
|
||||||
dateOut = bf;
|
dateOut = bf;
|
||||||
//dateOut = itow(localTime.wYear) + L"-" + itow(localTime.wMonth) + L"-" + itow(localTime.wDay);
|
|
||||||
//timeOut = itow(localTime.wHour) + L":" + itow(localTime.wMinute) + L":" + itow(localTime.wSecond);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dateOut = date;
|
dateOut = date;
|
||||||
@ -3460,16 +3476,16 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
xml.write("StartTime", oe.getAbsDateTimeISO(r.getStartTime(), true, useGMT));
|
xml.write("StartTime", oe.getAbsDateTimeISO(r.getStartTime(), true, useGMT));
|
||||||
|
|
||||||
bool hasTiming = (!r.getClassRef(false) || r.getClassRef(true)->getNoTiming() == false) &&
|
bool hasTiming = (!r.getClassRef(false) || r.getClassRef(true)->getNoTiming() == false) &&
|
||||||
r.getStatusComputed() != RunnerStatus::StatusNoTiming && !r.noTiming();
|
r.getStatusComputed(true) != RunnerStatus::StatusNoTiming && !r.noTiming();
|
||||||
|
|
||||||
int finishTime, runningTime, place, after;
|
int finishTime, runningTime, place, after;
|
||||||
RunnerStatus status;
|
RunnerStatus status;
|
||||||
if (!patrolResult) {
|
if (!patrolResult) {
|
||||||
place = r.getPlace();
|
place = r.getPlace();
|
||||||
finishTime = r.getFinishTimeAdjusted();
|
finishTime = r.getFinishTimeAdjusted(false);
|
||||||
runningTime = r.getRunningTime(true);
|
runningTime = r.getRunningTime(true);
|
||||||
after = r.getTimeAfter();
|
after = r.getTimeAfter();
|
||||||
status = r.getStatusComputed();
|
status = r.getStatusComputed(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int pl = r.getParResultLeg();
|
int pl = r.getParResultLeg();
|
||||||
@ -3480,7 +3496,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
else
|
else
|
||||||
finishTime = 0;
|
finishTime = 0;
|
||||||
|
|
||||||
after = r.getTeam()->getTimeAfter(pl);
|
after = r.getTeam()->getTimeAfter(pl, true);
|
||||||
status = r.getTeam()->getLegStatus(pl, true, false);
|
status = r.getTeam()->getLegStatus(pl, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3494,23 +3510,23 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
xml.write("FinishTime", oe.getAbsDateTimeISO(finishTime, true, useGMT));
|
xml.write("FinishTime", oe.getAbsDateTimeISO(finishTime, true, useGMT));
|
||||||
|
|
||||||
if (runningTime > 0)
|
if (runningTime > 0)
|
||||||
xml.write("Time", runningTime);
|
xml.write("Time", formatRelTime(runningTime));
|
||||||
|
|
||||||
if (after >= 0) {
|
if (after >= 0) {
|
||||||
if (teamMember) {
|
if (teamMember) {
|
||||||
xml.write("TimeBehind", "type", L"Leg", itow(after));
|
xml.write("TimeBehind", "type", L"Leg", formatRelTime(after));
|
||||||
|
|
||||||
int afterCourse = r.getTimeAfterCourse();
|
int afterCourse = r.getTimeAfterCourse();
|
||||||
if (afterCourse >= 0)
|
if (afterCourse >= 0)
|
||||||
xml.write("TimeBehind", "type", L"Course", itow(afterCourse));
|
xml.write("TimeBehind", "type", L"Course", formatRelTime(afterCourse));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
xml.write("TimeBehind", after);
|
xml.write("TimeBehind", formatRelTime(after));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.getClassRef(false)) {
|
if (r.getClassRef(false)) {
|
||||||
|
|
||||||
if (r.statusOK(true) && hasTiming) {
|
if (r.statusOK(true, true) && hasTiming) {
|
||||||
if (!teamMember && place > 0 && place < 50000) {
|
if (!teamMember && place > 0 && place < 50000) {
|
||||||
xml.write("Position", place);
|
xml.write("Position", place);
|
||||||
}
|
}
|
||||||
@ -3536,7 +3552,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
|
|
||||||
int rt = r.getTotalRunningTime();
|
int rt = r.getTotalRunningTime();
|
||||||
if (rt > 0 && hasTiming)
|
if (rt > 0 && hasTiming)
|
||||||
xml.write("Time", rt);
|
xml.write("Time", formatRelTime(rt));
|
||||||
|
|
||||||
RunnerStatus stat = r.getTotalStatus();
|
RunnerStatus stat = r.getTotalStatus();
|
||||||
|
|
||||||
@ -3546,7 +3562,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
int after = r.getTotalRunningTime() -
|
int after = r.getTotalRunningTime() -
|
||||||
r.getClassRef(true)->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
|
r.getClassRef(true)->getTotalLegLeaderTime(oClass::AllowRecompute::Yes, tleg, true, true);
|
||||||
if (after >= 0)
|
if (after >= 0)
|
||||||
xml.write("TimeBehind", after);
|
xml.write("TimeBehind", formatRelTime(after));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat == StatusOK && hasTiming)
|
if (stat == StatusOK && hasTiming)
|
||||||
@ -3563,7 +3579,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
writeCourse(xml, *crs);
|
writeCourse(xml, *crs);
|
||||||
|
|
||||||
const vector<SplitData> &sp = r.getSplitTimes(doUnroll);
|
const vector<SplitData> &sp = r.getSplitTimes(doUnroll);
|
||||||
RunnerStatus st = r.getStatusComputed();
|
RunnerStatus st = r.getStatusComputed(true);
|
||||||
if (r.getStatus()>0 && st != StatusDNS &&
|
if (r.getStatus()>0 && st != StatusDNS &&
|
||||||
st != StatusCANCEL &&
|
st != StatusCANCEL &&
|
||||||
st != StatusNotCompetiting) {
|
st != StatusNotCompetiting) {
|
||||||
@ -3579,7 +3595,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
break;
|
break;
|
||||||
if (crs->getControl(k)->isRogaining(hasRogaining)) {
|
if (crs->getControl(k)->isRogaining(hasRogaining)) {
|
||||||
if (sp[k].hasTime()) {
|
if (sp[k].hasTime()) {
|
||||||
int time = sp[k].time - r.getStartTime();
|
int time = sp[k].getTime(false) - r.getStartTime();
|
||||||
int control = crs->getControl(k)->getFirstNumber();
|
int control = crs->getControl(k)->getFirstNumber();
|
||||||
rogaining.insert(make_pair(time, control));
|
rogaining.insert(make_pair(time, control));
|
||||||
}
|
}
|
||||||
@ -3596,7 +3612,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
xml.startTag("SplitTime");
|
xml.startTag("SplitTime");
|
||||||
xml.write("ControlCode", crs->getControl(k)->getFirstNumber());
|
xml.write("ControlCode", crs->getControl(k)->getFirstNumber());
|
||||||
if (sp[k].hasTime() && hasTiming)
|
if (sp[k].hasTime() && hasTiming)
|
||||||
xml.write("Time", sp[k].time - r.getStartTime());
|
xml.write("Time", formatRelTime(sp[k].getTime(false) - r.getStartTime()));
|
||||||
xml.endTag();
|
xml.endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3604,7 +3620,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
xml.startTag("SplitTime", "status", "Additional");
|
xml.startTag("SplitTime", "status", "Additional");
|
||||||
xml.write("ControlCode", it->second);
|
xml.write("ControlCode", it->second);
|
||||||
if (it->first != -1)
|
if (it->first != -1)
|
||||||
xml.write("Time", it->first);
|
xml.write("Time", formatRelTime(it->first));
|
||||||
xml.endTag();
|
xml.endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3617,7 +3633,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
|||||||
xml.startTag("SplitTime", "status", "Additional");
|
xml.startTag("SplitTime", "status", "Additional");
|
||||||
xml.write("ControlCode", p->getTypeCode());
|
xml.write("ControlCode", p->getTypeCode());
|
||||||
if (p->getTimeInt() > r.getStartTime())
|
if (p->getTimeInt() > r.getStartTime())
|
||||||
xml.write("Time", p->getTimeInt() - r.getStartTime());
|
xml.write("Time", formatRelTime(p->getTimeInt() - r.getStartTime()));
|
||||||
xml.endTag();
|
xml.endTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3653,7 +3669,8 @@ void IOF30Interface::writeFees(xmlparser &xml, const oRunner &r) const {
|
|||||||
void IOF30Interface::writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInputTime) {
|
void IOF30Interface::writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInputTime) {
|
||||||
xml.startTag("TeamResult");
|
xml.startTag("TeamResult");
|
||||||
|
|
||||||
xml.write("EntryId", t.getId());
|
writeTeamEntryId(t, xml);
|
||||||
|
|
||||||
xml.write("Name", t.getName());
|
xml.write("Name", t.getName());
|
||||||
|
|
||||||
if (t.getClubRef())
|
if (t.getClubRef())
|
||||||
@ -3672,6 +3689,24 @@ void IOF30Interface::writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInp
|
|||||||
xml.endTag();
|
xml.endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOF30Interface::writeTeamEntryId(const oTeam& t, xmlparser& xml)
|
||||||
|
{
|
||||||
|
bool isImported = t.getEntrySource() != 0;
|
||||||
|
wstring id;
|
||||||
|
if (t.getExtIdentifier() != 0) {
|
||||||
|
id = t.getExtIdentifierString();
|
||||||
|
isImported = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
id = itow(t.getId());
|
||||||
|
|
||||||
|
if (isImported)
|
||||||
|
xml.write("EntryId", id);
|
||||||
|
else if (!useEventorQuirks) {
|
||||||
|
xml.write("EntryId", "type", L"MeOS", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int IOF30Interface::getStageNumber() {
|
int IOF30Interface::getStageNumber() {
|
||||||
if (cachedStageNumber >= 0)
|
if (cachedStageNumber >= 0)
|
||||||
return cachedStageNumber;
|
return cachedStageNumber;
|
||||||
@ -4002,7 +4037,8 @@ void IOF30Interface::writeTeamNoPersonStart(xmlparser &xml, const oTeam &t, int
|
|||||||
void IOF30Interface::writeTeamStart(xmlparser &xml, const oTeam &t) {
|
void IOF30Interface::writeTeamStart(xmlparser &xml, const oTeam &t) {
|
||||||
xml.startTag("TeamStart");
|
xml.startTag("TeamStart");
|
||||||
|
|
||||||
xml.write("EntryId", t.getId());
|
writeTeamEntryId(t, xml);
|
||||||
|
|
||||||
xml.write("Name", t.getName());
|
xml.write("Name", t.getName());
|
||||||
|
|
||||||
if (t.getClubRef())
|
if (t.getClubRef())
|
||||||
@ -4072,7 +4108,25 @@ void IOF30Interface::writeLegOrder(xmlparser &xml, const oClass *pc, int legNo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
size_t hash_entry(const wstring& name, int clubId, int card, const wstring &birth) {
|
||||||
|
size_t h = 0;
|
||||||
|
for (int j = 0; j < name.size(); j++) {
|
||||||
|
h = h * 37 + name[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
h = h * 997 + clubId;
|
||||||
|
h = h * 997 + card;
|
||||||
|
for (int j = 0; j < birth.size(); j++) {
|
||||||
|
if (birth[j] >= '0' && birth[j] <= '9')
|
||||||
|
h = h * 997 + birth[j];
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor,
|
||||||
|
bool onlyWithClub,
|
||||||
|
unordered_multimap<size_t, int>& duplicateCheck,
|
||||||
|
int &duplicateCount) {
|
||||||
|
|
||||||
if (!xCompetitor) return false;
|
if (!xCompetitor) return false;
|
||||||
|
|
||||||
@ -4083,10 +4137,7 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
|||||||
int pidI;
|
int pidI;
|
||||||
long long pid;
|
long long pid;
|
||||||
readId(person, pidI, pid);
|
readId(person, pidI, pid);
|
||||||
/*
|
|
||||||
wstring pidS;
|
|
||||||
person.getObjectString("Id", pidS);xxx
|
|
||||||
long long pid = oBase::converExtIdentifierString(pidS);*/
|
|
||||||
xmlobject pname = person.getObject("Name");
|
xmlobject pname = person.getObject("Name");
|
||||||
if (!pname) return false;
|
if (!pname) return false;
|
||||||
|
|
||||||
@ -4100,7 +4151,7 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
|||||||
xmlobject &card = cards[k];
|
xmlobject &card = cards[k];
|
||||||
if (card) {
|
if (card) {
|
||||||
xmlattrib pSystem = card.getAttrib("punchingSystem");
|
xmlattrib pSystem = card.getAttrib("punchingSystem");
|
||||||
if (!pSystem || _stricmp(pSystem.get(), "SI") == 0) {
|
if (!pSystem || _stricmp(pSystem.getPtr(), "SI") == 0) {
|
||||||
cardno = card.getObjectInt(0);
|
cardno = card.getObjectInt(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4116,13 +4167,13 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
|||||||
if (given.empty() || family.empty())
|
if (given.empty() || family.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//string name(given+" "+family);
|
|
||||||
wstring name(family + L", " + given);
|
wstring name(family + L", " + given);
|
||||||
|
|
||||||
char sex[2];
|
char sex[2];
|
||||||
person.getObjectString("sex", sex, 2);
|
person.getObjectString("sex", sex, 2);
|
||||||
|
|
||||||
int birth = person.getObjectInt("BirthDate");
|
wstring birth;
|
||||||
|
person.getObjectString("BirthDate", birth);
|
||||||
|
|
||||||
xmlobject nat=person.getObject("Nationality");
|
xmlobject nat=person.getObject("Nationality");
|
||||||
|
|
||||||
@ -4137,8 +4188,26 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
|||||||
clubId = xClub.getObjectInt("Id");
|
clubId = xClub.getObjectInt("Id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onlyWithClub && clubId == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t eHash = hash_entry(name, clubId, cardno, birth);
|
||||||
|
|
||||||
RunnerDB &runnerDB = oe.getRunnerDatabase();
|
RunnerDB &runnerDB = oe.getRunnerDatabase();
|
||||||
|
|
||||||
|
|
||||||
|
auto dupCheck = duplicateCheck.equal_range(eHash);
|
||||||
|
wstring dupName;
|
||||||
|
for (auto it = dupCheck.first; it != dupCheck.second; ++it) {
|
||||||
|
int ix = it->second;
|
||||||
|
RunnerWDBEntry* dupCand = runnerDB.getRunnerByIndex(ix);
|
||||||
|
dupCand->getName(dupName);
|
||||||
|
if (dupName == name && clubId == dupCand->dbe().clubNo && cardno == dupCand->dbe().cardNo) {
|
||||||
|
duplicateCount++;
|
||||||
|
return false; // Duplicate person
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RunnerWDBEntry *rde = runnerDB.getRunnerById(pid);
|
RunnerWDBEntry *rde = runnerDB.getRunnerById(pid);
|
||||||
|
|
||||||
if (!rde) {
|
if (!rde) {
|
||||||
@ -4152,10 +4221,12 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rde) {
|
if (rde) {
|
||||||
|
duplicateCheck.emplace(eHash, rde->getIndex());
|
||||||
rde->setExtId(pid);
|
rde->setExtId(pid);
|
||||||
rde->setName(name.c_str());
|
rde->setName(name.c_str());
|
||||||
|
rde->dbe().cardNo = cardno;
|
||||||
rde->dbe().clubNo = clubId;
|
rde->dbe().clubNo = clubId;
|
||||||
rde->dbe().birthYear = extendYear(birth);
|
rde->dbe().setBirthDate(birth);
|
||||||
rde->dbe().sex = sex[0];
|
rde->dbe().sex = sex[0];
|
||||||
memcpy(rde->dbe().national, national, 3);
|
memcpy(rde->dbe().national, national, 3);
|
||||||
}
|
}
|
||||||
@ -4276,14 +4347,14 @@ bool IOF30Interface::readControl(const xmlobject &xControl) {
|
|||||||
pControl pc = 0;
|
pControl pc = 0;
|
||||||
|
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
pc = oe.getControl(code, true);
|
pc = oe.getControl(code, true, false);
|
||||||
}
|
}
|
||||||
else if (type == 1) {
|
else if (type == 1) {
|
||||||
wstring start = getStartName(trim(idStr));
|
wstring start = getStartName(trim(idStr));
|
||||||
pc = oe.getControl(getStartIndex(idStr), true);
|
pc = oe.getControl(getStartIndex(idStr), true, false);
|
||||||
pc->setNumbers(L"");
|
pc->setNumbers(L"");
|
||||||
pc->setName(start);
|
pc->setName(start);
|
||||||
pc->setStatus(oControl::StatusStart);
|
pc->setStatus(oControl::ControlStatus::StatusStart);
|
||||||
}
|
}
|
||||||
else if (type == 2) {
|
else if (type == 2) {
|
||||||
wstring finish = trim(idStr);
|
wstring finish = trim(idStr);
|
||||||
@ -4294,10 +4365,10 @@ bool IOF30Interface::readControl(const xmlobject &xControl) {
|
|||||||
finish = lang.tl(L"Mål ") + itow(num);
|
finish = lang.tl(L"Mål ") + itow(num);
|
||||||
else
|
else
|
||||||
finish = lang.tl(L"Mål");
|
finish = lang.tl(L"Mål");
|
||||||
pc = oe.getControl(getFinishIndex(num), true);
|
pc = oe.getControl(getFinishIndex(num), true, false);
|
||||||
pc->setNumbers(L"");
|
pc->setNumbers(L"");
|
||||||
pc->setName(finish);
|
pc->setName(finish);
|
||||||
pc->setStatus(oControl::StatusFinish);
|
pc->setStatus(oControl::ControlStatus::StatusFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pc) {
|
if (pc) {
|
||||||
@ -4395,7 +4466,7 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
|
|||||||
if (type == "Start" && startName.empty()) {
|
if (type == "Start" && startName.empty()) {
|
||||||
wstring idStr;
|
wstring idStr;
|
||||||
xControls[k].getObjectString("Control", idStr);
|
xControls[k].getObjectString("Control", idStr);
|
||||||
pControl pStart = oe.getControl(getStartIndex(idStr), false);
|
pControl pStart = oe.getControl(getStartIndex(idStr), false, false);
|
||||||
if (pStart)
|
if (pStart)
|
||||||
startName = pStart->getName();
|
startName = pStart->getName();
|
||||||
}
|
}
|
||||||
@ -4407,14 +4478,14 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
|
|||||||
xControls[k].getObjects("Control", xPunchControls);
|
xControls[k].getObjects("Control", xPunchControls);
|
||||||
pControl pCtrl = 0;
|
pControl pCtrl = 0;
|
||||||
if (xPunchControls.size() == 1) {
|
if (xPunchControls.size() == 1) {
|
||||||
pCtrl = oe.getControl(xPunchControls[0].getInt(), true);
|
pCtrl = oe.getControl(xPunchControls[0].getInt(), true, false);
|
||||||
}
|
}
|
||||||
else if (xPunchControls.size()>1) {
|
else if (xPunchControls.size()>1) {
|
||||||
pCtrl = oe.addControl(1000*cid + xPunchControls[0].getInt(),xPunchControls[0].getInt(), L"");
|
pCtrl = oe.addControl(1000*cid + xPunchControls[0].getInt(),xPunchControls[0].getInt(), L"");
|
||||||
if (pCtrl) {
|
if (pCtrl) {
|
||||||
wstring cc;
|
wstring cc;
|
||||||
for (size_t j = 0; j < xPunchControls.size(); j++)
|
for (size_t j = 0; j < xPunchControls.size(); j++)
|
||||||
cc += wstring(xPunchControls[j].getw()) + L" ";
|
cc += xPunchControls[j].getWStr() + L" ";
|
||||||
|
|
||||||
pCtrl->setNumbers(cc);
|
pCtrl->setNumbers(cc);
|
||||||
}
|
}
|
||||||
@ -4426,7 +4497,7 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
|
|||||||
int score = xControls[k].getObjectInt("Score");
|
int score = xControls[k].getObjectInt("Score");
|
||||||
if (score > 0) {
|
if (score > 0) {
|
||||||
pCtrl->getDI().setInt("Rogaining", score);
|
pCtrl->getDI().setInt("Rogaining", score);
|
||||||
pCtrl->setStatus(oControl::StatusRogaining);
|
pCtrl->setStatus(oControl::ControlStatus::StatusRogaining);
|
||||||
hasRogaining = true;
|
hasRogaining = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4459,7 +4530,7 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
|
|||||||
if (hasRogaining) {
|
if (hasRogaining) {
|
||||||
int mt = oe.getMaximalTime();
|
int mt = oe.getMaximalTime();
|
||||||
if (mt == 0)
|
if (mt == 0)
|
||||||
mt = 3600;
|
mt = timeConstHour;
|
||||||
pc->setMaximumRogainingTime(mt);
|
pc->setMaximumRogainingTime(mt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4508,7 +4579,7 @@ void IOF30Interface::writeCourses(xmlparser &xml) {
|
|||||||
xml.endTag();
|
xml.endTag();
|
||||||
set<wstring> ids;
|
set<wstring> ids;
|
||||||
for (size_t k = 0; k < ctrl.size(); k++) {
|
for (size_t k = 0; k < ctrl.size(); k++) {
|
||||||
if (ctrl[k]->getStatus() != oControl::StatusFinish && ctrl[k]->getStatus() != oControl::StatusStart) {
|
if (!oControl::isSpecialControl(ctrl[k]->getStatus())) {
|
||||||
wstring id = writeControl(xml, *ctrl[k], ids);
|
wstring id = writeControl(xml, *ctrl[k], ids);
|
||||||
ctrlId2ExportId[ctrl[k]->getId()] = id;
|
ctrlId2ExportId[ctrl[k]->getId()] = id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class oEvent;
|
class oEvent;
|
||||||
class xmlobject;
|
class xmlobject;
|
||||||
@ -72,7 +73,8 @@ class IOF30Interface {
|
|||||||
bool unrollLoops;
|
bool unrollLoops;
|
||||||
// Include data on stage number
|
// Include data on stage number
|
||||||
bool includeStageRaceInfo;
|
bool includeStageRaceInfo;
|
||||||
void operator=(const IOF30Interface &);
|
|
||||||
|
const IOF30Interface &operator=(const IOF30Interface &) = delete;
|
||||||
|
|
||||||
set<wstring> matchedClasses;
|
set<wstring> matchedClasses;
|
||||||
|
|
||||||
@ -193,6 +195,7 @@ class IOF30Interface {
|
|||||||
|
|
||||||
int parseISO8601Time(const xmlobject &xo);
|
int parseISO8601Time(const xmlobject &xo);
|
||||||
wstring getCurrentTime() const;
|
wstring getCurrentTime() const;
|
||||||
|
wstring formatRelTime(int rt);
|
||||||
|
|
||||||
static void getNationality(const xmlobject &xCountry, oDataInterface &di);
|
static void getNationality(const xmlobject &xCountry, oDataInterface &di);
|
||||||
|
|
||||||
@ -220,6 +223,8 @@ class IOF30Interface {
|
|||||||
|
|
||||||
void writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInputTime);
|
void writeTeamResult(xmlparser &xml, const oTeam &t, bool hasInputTime);
|
||||||
|
|
||||||
|
void writeTeamEntryId(const oTeam& t, xmlparser& xml);
|
||||||
|
|
||||||
void writeResult(xmlparser &xml, const oRunner &rPerson, const oRunner &rResultCarrier,
|
void writeResult(xmlparser &xml, const oRunner &rPerson, const oRunner &rResultCarrier,
|
||||||
bool includeCourse, bool includeRaceNumber, bool teamMember, bool hasInputTime);
|
bool includeCourse, bool includeRaceNumber, bool teamMember, bool hasInputTime);
|
||||||
|
|
||||||
@ -249,7 +254,10 @@ class IOF30Interface {
|
|||||||
// Returns zero if no stage number
|
// Returns zero if no stage number
|
||||||
int getStageNumber();
|
int getStageNumber();
|
||||||
|
|
||||||
bool readXMLCompetitorDB(const xmlobject &xCompetitor);
|
bool readXMLCompetitorDB(const xmlobject &xCompetitor,
|
||||||
|
bool onlyWithClub,
|
||||||
|
unordered_multimap<size_t, int> &duplicateCheck,
|
||||||
|
int &duplicateCount);
|
||||||
void writeXMLCompetitorDB(xmlparser &xml, const RunnerDB &db, const RunnerWDBEntry &rde) const;
|
void writeXMLCompetitorDB(xmlparser &xml, const RunnerDB &db, const RunnerWDBEntry &rde) const;
|
||||||
|
|
||||||
int getStartIndex(const wstring &startId);
|
int getStartIndex(const wstring &startId);
|
||||||
@ -258,7 +266,7 @@ class IOF30Interface {
|
|||||||
pCourse readCourse(const xmlobject &xcrs);
|
pCourse readCourse(const xmlobject &xcrs);
|
||||||
|
|
||||||
void readCourseGroups(xmlobject xClassCourse, vector< vector<pCourse> > &crs);
|
void readCourseGroups(xmlobject xClassCourse, vector< vector<pCourse> > &crs);
|
||||||
void bindClassCourse(oClass &pc, const vector< vector<pCourse> > &crs);
|
void bindClassCourse(oClass &pc, const vector<vector<pCourse>> &crs);
|
||||||
|
|
||||||
static wstring constructCourseName(const xmlobject &xcrs);
|
static wstring constructCourseName(const xmlobject &xcrs);
|
||||||
static wstring constructCourseName(const wstring &family, const wstring &name);
|
static wstring constructCourseName(const wstring &family, const wstring &name);
|
||||||
@ -290,8 +298,10 @@ class IOF30Interface {
|
|||||||
|
|
||||||
set<int> readCrsIds;
|
set<int> readCrsIds;
|
||||||
|
|
||||||
|
bool useEventorQuirks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IOF30Interface(oEvent *oe, bool forceSplitFee);
|
IOF30Interface(oEvent *oe, bool forceSplitFee, bool useEventorQuirks);
|
||||||
virtual ~IOF30Interface() {}
|
virtual ~IOF30Interface() {}
|
||||||
|
|
||||||
static void getLocalDateTime(const wstring &datetime, wstring &dateOut, wstring &timeOut);
|
static void getLocalDateTime(const wstring &datetime, wstring &dateOut, wstring &timeOut);
|
||||||
@ -321,7 +331,8 @@ public:
|
|||||||
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||||
|
|
||||||
void prescanCompetitorList(xmlobject &xo);
|
void prescanCompetitorList(xmlobject &xo);
|
||||||
void readCompetitorList(gdioutput &gdi, const xmlobject &xo, int &personCount);
|
void readCompetitorList(gdioutput &gdi, const xmlobject &xo,
|
||||||
|
bool onlyWithClub, int &personCount, int& duplicateCount);
|
||||||
|
|
||||||
void readClubList(gdioutput &gdi, const xmlobject &xo, int &clubCount);
|
void readClubList(gdioutput &gdi, const xmlobject &xo, int &clubCount);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ Third Party Code. Additional copyright notices and license terms applicable to p
|
|||||||
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
|
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
|
||||||
|
|
||||||
------------------------------------
|
------------------------------------
|
||||||
Copyright 2007-2020 Melin Software HB.
|
Copyright 2007-2023 Melin Software HB.
|
||||||
|
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -37,6 +37,9 @@
|
|||||||
#include "generalresult.h"
|
#include "generalresult.h"
|
||||||
#include "gdiconstants.h"
|
#include "gdiconstants.h"
|
||||||
#include "autocomplete.h"
|
#include "autocomplete.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
extern Image image;
|
||||||
|
|
||||||
ListEditor::ListEditor(oEvent *oe_) {
|
ListEditor::ListEditor(oEvent *oe_) {
|
||||||
oe = oe_;
|
oe = oe_;
|
||||||
@ -62,13 +65,6 @@ void ListEditor::setCurrentList(MetaList *lst) {
|
|||||||
delete currentList;
|
delete currentList;
|
||||||
currentList = lst;
|
currentList = lst;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void ListEditor::load(MetaList *list) {
|
|
||||||
currentList = list;
|
|
||||||
currentIndex = -1;
|
|
||||||
dirtyInt = true;
|
|
||||||
dirtyExt = true;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void ListEditor::load(const MetaListContainer &mlc, int index) {
|
void ListEditor::load(const MetaListContainer &mlc, int index) {
|
||||||
const MetaList &mc = mlc.getList(index);
|
const MetaList &mc = mlc.getList(index);
|
||||||
@ -117,6 +113,8 @@ void ListEditor::show(gdioutput &gdi) {
|
|||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
gdi.addButton("EditList", "Egenskaper", editListCB);
|
gdi.addButton("EditList", "Egenskaper", editListCB);
|
||||||
|
gdi.addButton("SplitPrint", "Sträcktidslista", editListCB);
|
||||||
|
|
||||||
gdi.setCX(gdi.getCX() + gdi.scaleLength(32));
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(32));
|
||||||
gdi.addButton("OpenFile", "Öppna fil", editListCB);
|
gdi.addButton("OpenFile", "Öppna fil", editListCB);
|
||||||
gdi.addButton("OpenInside", "Öppna från aktuell tävling", editListCB);
|
gdi.addButton("OpenInside", "Öppna från aktuell tävling", editListCB);
|
||||||
@ -137,6 +135,21 @@ void ListEditor::show(gdioutput &gdi) {
|
|||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
|
|
||||||
int dx = gdi.getCX();
|
int dx = gdi.getCX();
|
||||||
|
|
||||||
|
if (currentList && currentList->isSplitPrintList()) {
|
||||||
|
gdi.setCX(bx);
|
||||||
|
gdi.addString("", 0, "Välj deltagare för förhandsgranskning:");
|
||||||
|
gdi.addSelection("Runner", 300, 300, editListCB);
|
||||||
|
oe->fillRunners(gdi, "Runner", false, 0);
|
||||||
|
if (currentRunnerId > 0 && oe->getRunner(currentRunnerId, 0))
|
||||||
|
gdi.selectItemByData("Runner", currentRunnerId);
|
||||||
|
else {
|
||||||
|
gdi.selectFirstItem("Runner");
|
||||||
|
currentRunnerId = gdi.getSelectedItem("Runner").first;
|
||||||
|
}
|
||||||
|
gdi.dropLine(2);
|
||||||
|
}
|
||||||
|
|
||||||
int dy = gdi.getCY();
|
int dy = gdi.getCY();
|
||||||
|
|
||||||
RECT rc;
|
RECT rc;
|
||||||
@ -156,6 +169,7 @@ void ListEditor::show(gdioutput &gdi) {
|
|||||||
makeDirty(gdi, NoTouch, NoTouch);
|
makeDirty(gdi, NoTouch, NoTouch);
|
||||||
if (!currentList) {
|
if (!currentList) {
|
||||||
gdi.disableInput("EditList");
|
gdi.disableInput("EditList");
|
||||||
|
gdi.disableInput("SplitPrint");
|
||||||
gdi.disableInput("SaveFile");
|
gdi.disableInput("SaveFile");
|
||||||
gdi.disableInput("SaveFileCopy", true);
|
gdi.disableInput("SaveFileCopy", true);
|
||||||
gdi.disableInput("SaveInside");
|
gdi.disableInput("SaveInside");
|
||||||
@ -223,8 +237,17 @@ void ListEditor::show(gdioutput &gdi) {
|
|||||||
gdi.addButton("AddLine3", "Lägg till rad", editListCB);
|
gdi.addButton("AddLine3", "Lägg till rad", editListCB);
|
||||||
|
|
||||||
gdi.setRestorePoint("EditList");
|
gdi.setRestorePoint("EditList");
|
||||||
|
renderListPreview(gdi);
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditor::renderListPreview(gdioutput &gdi) {
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
|
gdi.fillDown();
|
||||||
|
RECT rc;
|
||||||
|
pRunner splitPrintR = nullptr;
|
||||||
|
if (currentList->isSplitPrintList() && currentRunnerId)
|
||||||
|
splitPrintR = oe->getRunner(currentRunnerId, 0);
|
||||||
|
|
||||||
oListInfo li;
|
oListInfo li;
|
||||||
oListParam par;
|
oListParam par;
|
||||||
@ -232,30 +255,59 @@ void ListEditor::show(gdioutput &gdi) {
|
|||||||
par.splitAnalysis = true;
|
par.splitAnalysis = true;
|
||||||
par.setLegNumberCoded(-1);
|
par.setLegNumberCoded(-1);
|
||||||
par.inputNumber = 0;
|
par.inputNumber = 0;
|
||||||
gdi.fillDown();
|
|
||||||
|
|
||||||
|
if (splitPrintR) {
|
||||||
|
par.selection.insert(splitPrintR->getClassId(true));
|
||||||
|
par.showInterTimes = false;
|
||||||
|
par.setLegNumberCoded(splitPrintR->getLegNumber());
|
||||||
|
par.filterMaxPer = 3;
|
||||||
|
par.alwaysInclude = splitPrintR;
|
||||||
|
par.showHeader = false;
|
||||||
|
}
|
||||||
|
double originalScale = 0;
|
||||||
try {
|
try {
|
||||||
currentList->interpret(oe, gdi, par, li);
|
|
||||||
rc.left = gdi.getCX();
|
rc.left = gdi.getCX();
|
||||||
rc.right = gdi.getCX() + gdi.getWidth() - 20;
|
rc.right = gdi.getCX() + gdi.getWidth() - gdi.scaleLength(20);
|
||||||
rc.top = gdi.getCY();
|
rc.top = gdi.getCY();
|
||||||
rc.bottom = rc.top + 4;
|
rc.bottom = rc.top + 4;
|
||||||
|
|
||||||
gdi.addRectangle(rc, colorDarkGreen, false, false);
|
gdi.addRectangle(rc, colorDarkGreen, false, false);
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|
||||||
oe->generateList(gdi, false, li, true);
|
currentList->interpret(oe, gdi, par, li);
|
||||||
|
|
||||||
|
if (splitPrintR) {
|
||||||
|
auto& sp = *li.getSplitPrintInfo();
|
||||||
|
li.getParam().filterMaxPer = sp.numClassResults;
|
||||||
|
|
||||||
|
const bool wideFormat = oe->getPropertyInt("WideSplitFormat", 0) == 1;
|
||||||
|
if (!wideFormat)
|
||||||
|
li.shrinkSize();
|
||||||
|
|
||||||
|
rc.left = gdi.getCX();
|
||||||
|
rc.top = gdi.getCY();
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(10));
|
||||||
|
gdi.dropLine();
|
||||||
|
|
||||||
|
splitPrintR->printSplits(gdi, &li);
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
rc.right = rc.left + gdi.scaleLength(250);
|
||||||
|
rc.bottom = gdi.getHeight();
|
||||||
|
gdi.addRectangle(rc, GDICOLOR::colorLightYellow);
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oe->generateList(gdi, false, li, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (meosException &ex) {
|
catch (meosException& ex) {
|
||||||
gdi.addString("", 1, "Listan kan inte visas").setColor(colorRed);
|
gdi.addString("", 1, "Listan kan inte visas").setColor(colorRed);
|
||||||
gdi.addString("", 0, ex.wwhat());
|
gdi.addString("", 0, ex.wwhat());
|
||||||
}
|
}
|
||||||
catch (std::exception &ex) {
|
catch (std::exception& ex) {
|
||||||
gdi.addString("", 1, "Listan kan inte visas").setColor(colorRed);
|
gdi.addString("", 1, "Listan kan inte visas").setColor(colorRed);
|
||||||
gdi.addString("", 0, ex.what());
|
gdi.addString("", 0, ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int editListCB(gdioutput *gdi, int type, void *data)
|
int editListCB(gdioutput *gdi, int type, void *data)
|
||||||
@ -274,7 +326,8 @@ void ListEditor::showLine(gdioutput &gdi, const vector<MetaListPost> &line, int
|
|||||||
addButton(gdi, line[k], gdi.getCX(), gdi.getCY(), ix, k);
|
addButton(gdi, line[k], gdi.getCX(), gdi.getCY(), ix, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.addButton("AddPost" + itos(ix), "Lägg till ny", editListCB);
|
gdi.addButton("AddPost", "Lägg till ny", editListCB).setExtra(ix);
|
||||||
|
gdi.addButton("AddImage", "Lägg till bild", editListCB).setExtra(ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonInfo &ListEditor::addButton(gdioutput &gdi, const MetaListPost &mlp, int x, int y, int lineIx, int ix) const {
|
ButtonInfo &ListEditor::addButton(gdioutput &gdi, const MetaListPost &mlp, int x, int y, int lineIx, int ix) const {
|
||||||
@ -282,6 +335,17 @@ ButtonInfo &ListEditor::addButton(gdioutput &gdi, const MetaListPost &mlp, int x
|
|||||||
if (mlp.getType() == L"String") {
|
if (mlp.getType() == L"String") {
|
||||||
cap = L"Text: X#" + mlp.getText();
|
cap = L"Text: X#" + mlp.getText();
|
||||||
}
|
}
|
||||||
|
else if (mlp.getType() == L"Image") {
|
||||||
|
if (mlp.getText().empty())
|
||||||
|
cap = L"Image";
|
||||||
|
else {
|
||||||
|
uint64_t imgId = mlp.getImageId();
|
||||||
|
if (!image.hasImage(imgId))
|
||||||
|
cap = L"Error";
|
||||||
|
else
|
||||||
|
cap = image.getFileName(imgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
const wstring &text = mlp.getText();
|
const wstring &text = mlp.getText();
|
||||||
if (text.length() > 0) {
|
if (text.length() > 0) {
|
||||||
@ -364,6 +428,26 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
if (ii.id == "Text" && ii.text != lastShownExampleText) {
|
if (ii.id == "Text" && ii.text != lastShownExampleText) {
|
||||||
showExample(gdi);
|
showExample(gdi);
|
||||||
}
|
}
|
||||||
|
else if (ii.id == "ImgWidth" || ii.id == "ImgHeight") {
|
||||||
|
if (gdi.isChecked("PreserveAspectRatio")) {
|
||||||
|
auto sel = gdi.getSelectedItem("Image");
|
||||||
|
if (sel.second && sel.first >= 0) {
|
||||||
|
auto imgId = image.getIdFromEnumeration(sel.first);
|
||||||
|
int h = image.getHeight(imgId);
|
||||||
|
int w = image.getWidth(imgId);
|
||||||
|
int ww, hh;
|
||||||
|
if (ii.id == "ImgWidth") {
|
||||||
|
ww = _wtoi(ii.text.c_str());
|
||||||
|
hh = (ww * h + w/2) / w;
|
||||||
|
gdi.setText("ImgHeight", hh);
|
||||||
|
} else {
|
||||||
|
hh = _wtoi(ii.text.c_str());
|
||||||
|
ww = (hh * w + h / 2) / h;
|
||||||
|
gdi.setText("ImgWidth", ww);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_BUTTON) {
|
else if (type == GUI_BUTTON) {
|
||||||
ButtonInfo bi = dynamic_cast<ButtonInfo &>(data);
|
ButtonInfo bi = dynamic_cast<ButtonInfo &>(data);
|
||||||
@ -376,66 +460,64 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
biSrc.setExtra(res);
|
biSrc.setExtra(res);
|
||||||
oe->setProperty("Colors", c);
|
oe->setProperty("Colors", c);
|
||||||
}
|
}
|
||||||
/*CHOOSECOLOR cc;
|
|
||||||
memset(&cc, 0, sizeof(cc));
|
|
||||||
cc.lStructSize = sizeof(cc);
|
|
||||||
cc.hwndOwner = gdi.getHWND();
|
|
||||||
cc.rgbResult = COLORREF(bi.getExtra());
|
|
||||||
if (GDICOLOR((int)bi.getExtra()) != colorDefault)
|
|
||||||
cc.Flags |= CC_RGBINIT;
|
|
||||||
|
|
||||||
COLORREF staticColor[16];
|
|
||||||
memset(staticColor, 0, 16*sizeof(COLORREF));
|
|
||||||
|
|
||||||
const string &c = oe->getPropertyString("Colors", "");
|
|
||||||
const char *end = c.c_str() + c.length();
|
|
||||||
const char * pEnd = c.c_str();
|
|
||||||
int pix = 0;
|
|
||||||
while(pEnd < end && pix < 16) {
|
|
||||||
staticColor[pix++] = strtol(pEnd,(char **)&pEnd,16);
|
|
||||||
}
|
|
||||||
|
|
||||||
cc.lpCustColors = staticColor;
|
|
||||||
if (ChooseColor(&cc)) {
|
|
||||||
data.setExtra((int)cc.rgbResult);
|
|
||||||
|
|
||||||
wstring co;
|
|
||||||
for (ix = 0; ix < 16; ix++) {
|
|
||||||
wchar_t bf[16];
|
|
||||||
swprintf_s(bf, L"%x ", staticColor[ix]);
|
|
||||||
co += bf;
|
|
||||||
}
|
|
||||||
oe->setProperty("Colors", co);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
if ( bi.id.substr(0, 8) == "EditPost" ) {
|
else if (bi.id == "NewImage") {
|
||||||
|
vector<pair<wstring, wstring>> ext = { make_pair(L">Bilder", L"*.png") };
|
||||||
|
wstring fn = gdi.browseForOpen(ext, L"png");
|
||||||
|
if (!fn.empty()) {
|
||||||
|
bool transparent = gdi.isChecked("TransparentWhite");
|
||||||
|
|
||||||
|
uint64_t imgId = image.loadFromFile(fn, transparent ? Image::ImageMethod::WhiteTransparent : Image::ImageMethod::Default);
|
||||||
|
int selIx = selectImage(gdi, imgId);
|
||||||
|
previewImage(gdi, selIx);
|
||||||
|
updateImageStatus(gdi, selIx);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bi.id == "TransparentWhite") {
|
||||||
|
bool transparent = gdi.isChecked("TransparentWhite");
|
||||||
|
int data = gdi.getSelectedItem("Image").first;
|
||||||
|
|
||||||
|
if (data >= 0) {
|
||||||
|
uint64_t imgId = image.getIdFromEnumeration(data);
|
||||||
|
image.reloadImage(imgId, transparent ? Image::ImageMethod::WhiteTransparent : Image::ImageMethod::Default);
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( bi.id.substr(0, 8) == "EditPost" ) {
|
||||||
if (gdi.hasData("CurrentId")) {
|
if (gdi.hasData("CurrentId")) {
|
||||||
DWORD id;
|
checkUnsaved(gdi);
|
||||||
gdi.getData("CurrentId", id);
|
|
||||||
getPosFromId(id, groupIx, lineIx, ix);
|
|
||||||
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
|
||||||
saveListPost(gdi, mlp);
|
|
||||||
}
|
}
|
||||||
int id = atoi(bi.id.substr(8).c_str());
|
int id = atoi(bi.id.substr(8).c_str());
|
||||||
getPosFromId(id, groupIx, lineIx, ix);
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
||||||
editListPost(gdi, mlp, id);
|
if (mlp.getTypeRaw() == EPostType::lImage)
|
||||||
|
editImage(gdi, mlp, id);
|
||||||
|
else
|
||||||
|
editListPost(gdi, mlp, id);
|
||||||
}
|
}
|
||||||
else if ( bi.id.substr(0, 7) == "AddPost" ) {
|
else if (bi.id == "AddPost" || bi.id == "AddImage") {
|
||||||
checkUnsaved(gdi);
|
checkUnsaved(gdi);
|
||||||
gdi.restore("EditList", true);
|
gdi.restore("EditList", true);
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
lineIx = atoi(bi.id.substr(7).c_str());
|
lineIx = bi.getExtraInt();
|
||||||
groupIx = (lineIx / 100) - 1;
|
groupIx = (lineIx / 100) - 1;
|
||||||
int ixOutput = 0;
|
int ixOutput = 0;
|
||||||
MetaListPost &mlp = currentList->addNew(groupIx, lineIx % 100, ixOutput);
|
MetaListPost &mlp = currentList->addNew(groupIx, lineIx % 100, ixOutput);
|
||||||
int xp = bi.xp;
|
if (bi.id == "AddImage")
|
||||||
int yp = bi.yp;
|
mlp.setType(EPostType::lImage);
|
||||||
|
|
||||||
|
auto& post = dynamic_cast<ButtonInfo&>(gdi.getBaseInfo("AddPost", lineIx));
|
||||||
|
|
||||||
|
int xp = post.xp;
|
||||||
|
int yp = post.yp;
|
||||||
ButtonInfo &nb = addButton(gdi, mlp, xp, yp, lineIx, ixOutput);
|
ButtonInfo &nb = addButton(gdi, mlp, xp, yp, lineIx, ixOutput);
|
||||||
//gdi.addButton(xp, yp, string("Foo"), string("FoooBar"), 0);
|
|
||||||
int w, h;
|
int w, h;
|
||||||
nb.getDimension(gdi, w, h);
|
nb.getDimension(gdi, w, h);
|
||||||
biSrc.moveButton(gdi, xp+w, yp);
|
post.moveButton(gdi, xp + w, yp);
|
||||||
|
int w2, h2;
|
||||||
|
post.getDimension(gdi, w2, h2);
|
||||||
|
dynamic_cast<ButtonInfo&>(gdi.getBaseInfo("AddImage", lineIx)).moveButton(gdi, xp + w + w2, yp);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.setRestorePoint("EditList");
|
gdi.setRestorePoint("EditList");
|
||||||
makeDirty(gdi, MakeDirty, MakeDirty);
|
makeDirty(gdi, MakeDirty, MakeDirty);
|
||||||
@ -463,9 +545,13 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
else if (bi.id == "UseLeg") {
|
else if (bi.id == "UseLeg") {
|
||||||
gdi.setInputStatus("Leg", gdi.isChecked(bi.id));
|
gdi.setInputStatus("Leg", gdi.isChecked(bi.id));
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "UseForSplit") {
|
||||||
|
statusSplitPrint(gdi, gdi.isChecked(bi.id));
|
||||||
|
}
|
||||||
else if (bi.id == "Cancel") {
|
else if (bi.id == "Cancel") {
|
||||||
gdi.restore("EditList");
|
gdi.restore("EditList");
|
||||||
gdi.enableInput("EditList");
|
gdi.enableInput("EditList");
|
||||||
|
gdi.enableInput("SplitPrint");
|
||||||
}
|
}
|
||||||
else if (bi.id == "CancelNew") {
|
else if (bi.id == "CancelNew") {
|
||||||
gdi.clearPage(false);
|
gdi.clearPage(false);
|
||||||
@ -473,26 +559,35 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
show(gdi);
|
show(gdi);
|
||||||
}
|
}
|
||||||
else if (bi.id == "Apply" || bi.id == "MoveLeft" || bi.id == "MoveRight") {
|
else if (bi.id == "Apply" || bi.id == "MoveLeft" || bi.id == "MoveRight") {
|
||||||
|
bool image = gdi.hasData("IsEditingImage");
|
||||||
DWORD id;
|
DWORD id;
|
||||||
gdi.getData("CurrentId", id);
|
gdi.getData("CurrentId", id);
|
||||||
getPosFromId(id, groupIx, lineIx, ix);
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
|
|
||||||
if (bi.id == "MoveLeft")
|
if (bi.id == "MoveLeft") {
|
||||||
currentList->moveOnRow(groupIx, lineIx, ix, -1);
|
currentList->moveOnRow(groupIx, lineIx, ix, -1);
|
||||||
else if (bi.id == "MoveRight")
|
id--;
|
||||||
|
}
|
||||||
|
else if (bi.id == "MoveRight") {
|
||||||
currentList->moveOnRow(groupIx, lineIx, ix, 1);
|
currentList->moveOnRow(groupIx, lineIx, ix, 1);
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
gdi.setData("CurrentId", id);
|
||||||
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
||||||
|
|
||||||
bool force = saveListPost(gdi, mlp);
|
bool force = checkUnsaved(gdi);//saveListPost(gdi, mlp);
|
||||||
|
|
||||||
if (!gdi.hasData("NoRedraw") || force) {
|
if (!gdi.hasData("NoRedraw") || force) {
|
||||||
gdi.restore("BeginListEdit", false);
|
gdi.restore("BeginListEdit", false);
|
||||||
show(gdi);
|
show(gdi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bi.id != "Apply")
|
if (bi.id != "Apply") {
|
||||||
editListPost(gdi, mlp, bi.getExtraInt());
|
if (image)
|
||||||
|
editImage(gdi, mlp, bi.getExtraInt());
|
||||||
|
else
|
||||||
|
editListPost(gdi, mlp, bi.getExtraInt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (bi.id == "ApplyListProp") {
|
else if (bi.id == "ApplyListProp") {
|
||||||
wstring name = gdi.getText("Name");
|
wstring name = gdi.getText("Name");
|
||||||
@ -532,7 +627,6 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
|
|
||||||
list.setSubFilters(subFiltersOut);
|
list.setSubFilters(subFiltersOut);
|
||||||
|
|
||||||
|
|
||||||
for (int k = 0; k < 4; k++) {
|
for (int k = 0; k < 4; k++) {
|
||||||
list.setFontFace(k, gdi.getText("Font" + itos(k)),
|
list.setFontFace(k, gdi.getText("Font" + itos(k)),
|
||||||
gdi.getTextNo("FontFactor" + itos(k)));
|
gdi.getTextNo("FontFactor" + itos(k)));
|
||||||
@ -541,7 +635,6 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
list.setExtraSpace(k, f);
|
list.setExtraSpace(k, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
list.setSupportFromTo(gdi.isChecked("SupportFrom"), gdi.isChecked("SupportTo"));
|
list.setSupportFromTo(gdi.isChecked("SupportFrom"), gdi.isChecked("SupportTo"));
|
||||||
list.setSupportLegSelection(gdi.isChecked("SupportLegSelection"));
|
list.setSupportLegSelection(gdi.isChecked("SupportLegSelection"));
|
||||||
|
|
||||||
@ -552,9 +645,32 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
show(gdi);
|
show(gdi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "ApplySplitList") {
|
||||||
|
MetaList& list = *currentList;
|
||||||
|
if (!gdi.isChecked("UseForSplit"))
|
||||||
|
list.setSplitPrintInfo(nullptr);
|
||||||
|
else {
|
||||||
|
auto spInfo = make_shared<SplitPrintListInfo>();
|
||||||
|
spInfo->includeSplitTimes = gdi.isChecked("Split");
|
||||||
|
spInfo->withSpeed = gdi.isChecked("Speed");
|
||||||
|
spInfo->withResult = gdi.isChecked("Result");
|
||||||
|
spInfo->withAnalysis = gdi.isChecked("Analysis");
|
||||||
|
list.setSplitPrintInfo(spInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeDirty(gdi, MakeDirty, MakeDirty);
|
||||||
|
|
||||||
|
if (!gdi.hasData("NoRedraw")) {
|
||||||
|
gdi.clearPage(false);
|
||||||
|
show(gdi);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (bi.id == "EditList") {
|
else if (bi.id == "EditList") {
|
||||||
editListProp(gdi, false);
|
editListProp(gdi, false);
|
||||||
}
|
}
|
||||||
|
else if (bi.id == "SplitPrint") {
|
||||||
|
splitPrintList(gdi);
|
||||||
|
}
|
||||||
else if (bi.id == "NewList") {
|
else if (bi.id == "NewList") {
|
||||||
if (!checkSave(gdi))
|
if (!checkSave(gdi))
|
||||||
return 0;
|
return 0;
|
||||||
@ -645,7 +761,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
|
|
||||||
gdi.pushX();
|
gdi.pushX();
|
||||||
vector< pair<wstring, size_t> > lists;
|
vector< pair<wstring, size_t> > lists;
|
||||||
oe->getListContainer().getLists(lists, true, false, false);
|
oe->getListContainer().getLists(lists, true, false, false, false);
|
||||||
|
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
gdi.addSelection("OpenList", 250, 400, editListCB, L"Välj lista:");
|
gdi.addSelection("OpenList", 250, 400, editListCB, L"Välj lista:");
|
||||||
@ -691,6 +807,11 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
savedFileName.clear();
|
savedFileName.clear();
|
||||||
oe->synchronize(false);
|
oe->synchronize(false);
|
||||||
|
|
||||||
|
set<uint64_t> imgUsed;
|
||||||
|
currentList->getUsedImages(imgUsed);
|
||||||
|
for (uint64_t id : imgUsed)
|
||||||
|
oe->saveImage(id);
|
||||||
|
|
||||||
if (currentIndex != -1) {
|
if (currentIndex != -1) {
|
||||||
oe->getListContainer().saveList(currentIndex, *currentList);
|
oe->getListContainer().saveList(currentIndex, *currentList);
|
||||||
}
|
}
|
||||||
@ -733,15 +854,6 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*else if (bi.id == "BrowseFont") {
|
|
||||||
InitCommonControls();
|
|
||||||
CHOOSEFONT cf;
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
|
||||||
cf.lStructSize = sizeof(cf);
|
|
||||||
cf.hwndOwner = gdi.getHWND();
|
|
||||||
ChooseFont(&cf);
|
|
||||||
EnumFontFamilies(
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
else if (type == GUI_LISTBOX) {
|
else if (type == GUI_LISTBOX) {
|
||||||
ListBoxInfo &lbi = dynamic_cast<ListBoxInfo &>(data);
|
ListBoxInfo &lbi = dynamic_cast<ListBoxInfo &>(data);
|
||||||
@ -758,6 +870,10 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
else
|
else
|
||||||
gdi.setText("AlignText", L"");
|
gdi.setText("AlignText", L"");
|
||||||
}
|
}
|
||||||
|
else if (lbi.id == "Image") {
|
||||||
|
previewImage(gdi, lbi.data);
|
||||||
|
updateImageStatus(gdi, lbi.data);
|
||||||
|
}
|
||||||
else if (lbi.id == "Type") {
|
else if (lbi.id == "Type") {
|
||||||
updateType(lbi.data, gdi);
|
updateType(lbi.data, gdi);
|
||||||
}
|
}
|
||||||
@ -784,6 +900,12 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
else if (lbi.id == "OpenList") {
|
else if (lbi.id == "OpenList") {
|
||||||
enableOpen(gdi);
|
enableOpen(gdi);
|
||||||
}
|
}
|
||||||
|
else if (lbi.id == "Runner") {
|
||||||
|
currentRunnerId = lbi.getDataInt();
|
||||||
|
gdi.restore("EditList", false);
|
||||||
|
renderListPreview(gdi);
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type==GUI_CLEAR) {
|
else if (type==GUI_CLEAR) {
|
||||||
return checkSave(gdi);
|
return checkSave(gdi);
|
||||||
@ -845,6 +967,26 @@ bool ListEditor::saveListPost(gdioutput &gdi, MetaListPost &mlp) {
|
|||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ListEditor::saveImage(gdioutput& gdi, MetaListPost& mlp) {
|
||||||
|
ListBoxInfo lbi;
|
||||||
|
int selIx = gdi.getSelectedItem("Image").first;
|
||||||
|
|
||||||
|
if (selIx >= 0) {
|
||||||
|
auto imgId = image.getIdFromEnumeration(selIx);
|
||||||
|
mlp.setText(itow(imgId));
|
||||||
|
mlp.setImageDimension(gdi.getTextNo("ImgWidth"), gdi.getTextNo("ImgHeight"));
|
||||||
|
mlp.setImageOffset(gdi.getTextNo("ImgOffsetX"), gdi.getTextNo("ImgOffsetY"));
|
||||||
|
mlp.setImageStyle(gdi.isChecked("TransparentWhite") ? 1 : 0);
|
||||||
|
mlp.imageUnderText(gdi.isChecked("ImageUnderText"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mlp.setText(L"");
|
||||||
|
}
|
||||||
|
makeDirty(gdi, MakeDirty, MakeDirty);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int ListEditor::readLeg(gdioutput &gdi, EPostType newType, bool checkError) const {
|
int ListEditor::readLeg(gdioutput &gdi, EPostType newType, bool checkError) const {
|
||||||
if (MetaList::isResultModuleOutput(newType)) {
|
if (MetaList::isResultModuleOutput(newType)) {
|
||||||
int leg = gdi.getTextNo("Leg");
|
int leg = gdi.getTextNo("Leg");
|
||||||
@ -863,6 +1005,13 @@ int ListEditor::readLeg(gdioutput &gdi, EPostType newType, bool checkError) cons
|
|||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (MetaList::isAllLegType(newType)) {
|
||||||
|
int leg = gdi.getSelectedItem("LegSel").first;
|
||||||
|
if (leg >= 0)
|
||||||
|
return leg - 1; // -1 -> automatic
|
||||||
|
else
|
||||||
|
return -2; // All legs
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (gdi.isChecked("UseLeg")) {
|
if (gdi.isChecked("UseLeg")) {
|
||||||
int leg = gdi.getTextNo("Leg");
|
int leg = gdi.getTextNo("Leg");
|
||||||
@ -899,7 +1048,7 @@ void ListEditor::updateType(int iType, gdioutput & gdi) {
|
|||||||
if (gdi.getText("Leg").empty())
|
if (gdi.getText("Leg").empty())
|
||||||
gdi.setText("Leg", L"0");
|
gdi.setText("Leg", L"0");
|
||||||
}
|
}
|
||||||
else if (MetaList::isAllStageType(type)) {
|
else if (MetaList::isAllStageType(type) || MetaList::isAllLegType(type)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -915,23 +1064,36 @@ void ListEditor::updateType(int iType, gdioutput & gdi) {
|
|||||||
showExample(gdi, type);
|
showExample(gdi, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListEditor::checkUnsaved(gdioutput &gdi) {
|
bool ListEditor::checkUnsaved(gdioutput& gdi) {
|
||||||
if (gdi.hasData("IsEditing")) {
|
if (gdi.hasData("IsEditing")) {
|
||||||
if (gdi.hasData("CurrentId")) {
|
DWORD id;
|
||||||
DWORD id;
|
gdi.getData("CurrentId", id);
|
||||||
gdi.getData("CurrentId", id);
|
int groupIx, lineIx, ix;
|
||||||
int groupIx, lineIx, ix;
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
getPosFromId(id, groupIx, lineIx, ix);
|
MetaListPost& mlp = currentList->getMLP(groupIx, lineIx, ix);
|
||||||
MetaListPost &mlp = currentList->getMLP(groupIx, lineIx, ix);
|
return saveListPost(gdi, mlp);
|
||||||
saveListPost(gdi, mlp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (gdi.hasData("IsEditingList")) {
|
else if (gdi.hasData("IsEditingImage")) {
|
||||||
|
DWORD id;
|
||||||
|
gdi.getData("CurrentId", id);
|
||||||
|
int groupIx, lineIx, ix;
|
||||||
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
|
MetaListPost& mlp = currentList->getMLP(groupIx, lineIx, ix);
|
||||||
|
return saveImage(gdi, mlp);
|
||||||
|
}
|
||||||
|
else if (gdi.hasData("IsEditingList")) {
|
||||||
if (gdi.isInputChanged("")) {
|
if (gdi.isInputChanged("")) {
|
||||||
gdi.setData("NoRedraw", 1);
|
gdi.setData("NoRedraw", 1);
|
||||||
gdi.sendCtrlMessage("ApplyListProp");
|
gdi.sendCtrlMessage("ApplyListProp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (gdi.hasData("IsSplitListEdit")) {
|
||||||
|
if (gdi.isInputChanged("")) {
|
||||||
|
gdi.setData("NoRedraw", 1);
|
||||||
|
gdi.sendCtrlMessage("ApplySplitList");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListEditor::updateAlign(gdioutput &gdi, int val) {
|
void ListEditor::updateAlign(gdioutput &gdi, int val) {
|
||||||
@ -949,38 +1111,17 @@ void ListEditor::updateAlign(gdioutput &gdi, int val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||||
checkUnsaved(gdi);
|
|
||||||
gdi.restore("EditList", false);
|
|
||||||
gdi.dropLine();
|
|
||||||
|
|
||||||
gdi.enableInput("EditList");
|
|
||||||
int groupIx, lineIx, ix;
|
int groupIx, lineIx, ix;
|
||||||
getPosFromId(id, groupIx, lineIx, ix);
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
const bool hasResultModule = currentList && !currentList->getResultModule().empty();
|
|
||||||
int x1 = gdi.getCX();
|
|
||||||
int y1 = gdi.getCY();
|
|
||||||
int margin = gdi.scaleLength(10);
|
|
||||||
gdi.setCX(x1+margin);
|
|
||||||
|
|
||||||
gdi.dropLine();
|
int x1, y1, boxY;
|
||||||
gdi.pushX();
|
editDlgStart(gdi, id, "Listpost", x1, y1, boxY);
|
||||||
gdi.fillRight();
|
|
||||||
gdi.addString("", boldLarge, "Listpost").setColor(colorDarkGrey);
|
|
||||||
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
|
||||||
|
|
||||||
gdi.addButton("MoveLeft", "<< Flytta vänster", editListCB).setExtra(id-1);
|
int maxX = gdi.getCX();
|
||||||
if (ix == 0)
|
|
||||||
gdi.setInputStatus("MoveLeft", false);
|
|
||||||
|
|
||||||
gdi.addButton("MoveRight", "Flytta höger >>", editListCB).setExtra(id+1);
|
|
||||||
if (ix + 1 == currentList->getNumPostsOnLine(groupIx, lineIx))
|
|
||||||
gdi.setInputStatus("MoveRight", false);
|
|
||||||
|
|
||||||
gdi.dropLine(1);
|
|
||||||
int boxY = gdi.getCY();
|
|
||||||
gdi.dropLine(2);
|
|
||||||
|
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
|
const bool hasResultModule = currentList && !currentList->getResultModule().empty();
|
||||||
|
|
||||||
vector< pair<wstring, size_t> > types;
|
vector< pair<wstring, size_t> > types;
|
||||||
int currentType;
|
int currentType;
|
||||||
mlp.getTypes(types, currentType);
|
mlp.getTypes(types, currentType);
|
||||||
@ -1039,22 +1180,7 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
|||||||
int leg = mlp.getLeg();
|
int leg = mlp.getLeg();
|
||||||
|
|
||||||
legStageTypeIndex(gdi, storedType, leg);
|
legStageTypeIndex(gdi, storedType, leg);
|
||||||
/*gdi.addCheckbox(xpUseLeg, ypUseLeg, "UseLeg", getIndexDescription(storedType), editListCB, leg != -1);
|
|
||||||
//gdi.dropLine(-0.2);
|
|
||||||
int dx = gdi.scaleLength(250);
|
|
||||||
int dy = -gdi.getLineHeight() / 5;
|
|
||||||
|
|
||||||
//gdi.setCX(gdi.getCX() + gdi.scaleLength(100));
|
|
||||||
if (MetaList::isResultModuleOutput(storedType))
|
|
||||||
gdi.addInput(xpUseLeg + dx, ypUseLeg + dy, "Leg", leg >= 0 ? itow(leg) : L"0", 4);
|
|
||||||
else
|
|
||||||
gdi.addInput(xpUseLeg + dx, ypUseLeg + dy, "Leg", leg >= 0 ? itow(leg + 1) : L"", 4);
|
|
||||||
|
|
||||||
gdi.setInputStatus("Leg", leg != -1);
|
|
||||||
*/
|
|
||||||
if (MetaList::isResultModuleOutput(storedType)) {
|
if (MetaList::isResultModuleOutput(storedType)) {
|
||||||
//gdi.check("UseLeg", true);
|
|
||||||
//gdi.disableInput("UseLeg");
|
|
||||||
if (gdi.hasWidget("UseResultModule")) {
|
if (gdi.hasWidget("UseResultModule")) {
|
||||||
gdi.check("UseResultModule", true);
|
gdi.check("UseResultModule", true);
|
||||||
gdi.disableInput("UseResultModule");
|
gdi.disableInput("UseResultModule");
|
||||||
@ -1083,9 +1209,6 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
|||||||
gdi.dropLine(1.9);
|
gdi.dropLine(1.9);
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.fillRight();
|
gdi.fillRight();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gdi.dropLine(2);
|
gdi.dropLine(2);
|
||||||
|
|
||||||
int maxY = gdi.getCY();
|
int maxY = gdi.getCY();
|
||||||
@ -1115,7 +1238,7 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
|||||||
|
|
||||||
|
|
||||||
gdi.addInput("MinIndent", itow(mlp.getMinimalIndent()), 7, 0, L"Justering i sidled:");
|
gdi.addInput("MinIndent", itow(mlp.getMinimalIndent()), 7, 0, L"Justering i sidled:");
|
||||||
int maxX = gdi.getCX();
|
maxX = max(maxX, gdi.getCX());
|
||||||
gdi.popX();
|
gdi.popX();
|
||||||
gdi.dropLine(3);
|
gdi.dropLine(3);
|
||||||
vector< pair<wstring, size_t> > fonts;
|
vector< pair<wstring, size_t> > fonts;
|
||||||
@ -1136,8 +1259,6 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
|||||||
gdi.addItem("TextAdjust", lang.tl("Centrera"), textCenter);
|
gdi.addItem("TextAdjust", lang.tl("Centrera"), textCenter);
|
||||||
gdi.selectItemByData("TextAdjust", mlp.getTextAdjustNum());
|
gdi.selectItemByData("TextAdjust", mlp.getTextAdjustNum());
|
||||||
|
|
||||||
//gdi.popX();
|
|
||||||
//gdi.dropLine(2);
|
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
gdi.addButton("Color", "Färg...", editListCB).setExtra(mlp.getColorValue());
|
gdi.addButton("Color", "Färg...", editListCB).setExtra(mlp.getColorValue());
|
||||||
|
|
||||||
@ -1190,6 +1311,166 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
|||||||
gdi.refresh();
|
gdi.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListEditor::editDlgStart(gdioutput& gdi, int id, const char *title, int &x1, int &y1, int &boxY) {
|
||||||
|
int groupIx, lineIx, ix;
|
||||||
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
|
|
||||||
|
checkUnsaved(gdi);
|
||||||
|
gdi.restore("EditList", false);
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.enableInput("EditList");
|
||||||
|
gdi.enableInput("SplitPrint");
|
||||||
|
|
||||||
|
x1 = gdi.getCX();
|
||||||
|
y1 = gdi.getCY();
|
||||||
|
int margin = gdi.scaleLength(10);
|
||||||
|
gdi.setCX(x1 + margin);
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.pushX();
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.addString("", boldLarge, title).setColor(colorDarkGrey);
|
||||||
|
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
||||||
|
|
||||||
|
gdi.addButton("MoveLeft", "<< Flytta vänster", editListCB).setExtra(id - 1);
|
||||||
|
if (ix == 0)
|
||||||
|
gdi.setInputStatus("MoveLeft", false);
|
||||||
|
|
||||||
|
gdi.addButton("MoveRight", "Flytta höger >>", editListCB).setExtra(id + 1);
|
||||||
|
if (ix + 1 == currentList->getNumPostsOnLine(groupIx, lineIx))
|
||||||
|
gdi.setInputStatus("MoveRight", false);
|
||||||
|
|
||||||
|
gdi.dropLine(1);
|
||||||
|
boxY = gdi.getCY();
|
||||||
|
gdi.dropLine(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditor::editImage(gdioutput& gdi, const MetaListPost& mlp, int id) {
|
||||||
|
int groupIx, lineIx, ix;
|
||||||
|
getPosFromId(id, groupIx, lineIx, ix);
|
||||||
|
|
||||||
|
uint64_t imgId = mlp.getImageId();
|
||||||
|
|
||||||
|
int x1, y1, boxY;
|
||||||
|
editDlgStart(gdi, id, "Bild", x1, y1, boxY);
|
||||||
|
|
||||||
|
int maxX = gdi.getCX();
|
||||||
|
gdi.popX();
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.dropLine(1);
|
||||||
|
|
||||||
|
gdi.addSelection("Image", 200, 200, editListCB, L"Välj bild:", L"Välj bland befintliga bilder");
|
||||||
|
|
||||||
|
int selIx = selectImage(gdi, imgId);
|
||||||
|
|
||||||
|
gdi.dropLine(1);
|
||||||
|
gdi.addButton("NewImage", "Ny bild...", editListCB);
|
||||||
|
|
||||||
|
int maxY = 0;
|
||||||
|
maxX = max(maxX, gdi.getCX());
|
||||||
|
int innerBoxLowerCX = maxX + gdi.scaleLength(6);
|
||||||
|
maxX += gdi.scaleLength(12);
|
||||||
|
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine(3);
|
||||||
|
|
||||||
|
wstring wh, ww, xoff, yoff;
|
||||||
|
bool keepRatio = true;
|
||||||
|
if (imgId) {
|
||||||
|
int h = mlp.getImageHeight();
|
||||||
|
int w = mlp.getImageWidth();
|
||||||
|
wh = itow(h);
|
||||||
|
ww = itow(w);
|
||||||
|
|
||||||
|
int hImg = image.getHeight(imgId);
|
||||||
|
int wImg = image.getWidth(imgId);
|
||||||
|
|
||||||
|
int hComputed = (w * hImg + wImg / 2) / wImg;
|
||||||
|
int wComputed = (h * wImg + hImg / 2) / hImg;
|
||||||
|
|
||||||
|
keepRatio = std::abs(h - hComputed) <= 1 || std::abs(w - wComputed) <= 1;
|
||||||
|
|
||||||
|
xoff = itow(mlp.getImageOffsetX());
|
||||||
|
yoff = itow(mlp.getImageOffsetY());
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.addInput("ImgWidth", ww, 5, editListCB, L"Bredd:");
|
||||||
|
gdi.addInput("ImgHeight", wh, 5, editListCB, L"Höjd:");
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.addCheckbox("PreserveAspectRatio", "Bevara höjd/bredd-relationen", nullptr, keepRatio);
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine(2);
|
||||||
|
|
||||||
|
gdi.dropLine(1);
|
||||||
|
gdi.addString("", 0, "Förskjutning:");
|
||||||
|
gdi.dropLine(-1);
|
||||||
|
|
||||||
|
gdi.addInput("ImgOffsetX", xoff, 5, editListCB, L"Horizontell:");
|
||||||
|
gdi.addInput("ImgOffsetY", yoff, 5, editListCB, L"Vertikal:");
|
||||||
|
|
||||||
|
gdi.popX();
|
||||||
|
gdi.dropLine(3);
|
||||||
|
|
||||||
|
gdi.addCheckbox("TransparentWhite", "Tolka vitt som genomskinligt", editListCB, mlp.getImageStyle() == 1);
|
||||||
|
gdi.addCheckbox("ImageUnderText", "Bild under text", editListCB, mlp.imageUnderText());
|
||||||
|
|
||||||
|
bool hasImg = imgId != 0;
|
||||||
|
gdi.setInputStatus("ImgWidth", hasImg);
|
||||||
|
gdi.setInputStatus("ImgHeight", hasImg);
|
||||||
|
gdi.setInputStatus("ImgOffsetX", hasImg);
|
||||||
|
gdi.setInputStatus("ImgOffsetY", hasImg);
|
||||||
|
|
||||||
|
gdi.setInputStatus("PreserveAspectRatio", hasImg);
|
||||||
|
|
||||||
|
gdi.dropLine(3);
|
||||||
|
gdi.setData("CurrentId", id);
|
||||||
|
gdi.addButton("Remove", "Radera", editListCB, "Ta bort listposten");
|
||||||
|
gdi.addButton("Cancel", "Avbryt", editListCB).setCancel();
|
||||||
|
|
||||||
|
gdi.updatePos(gdi.getCX(), gdi.getCY(), gdi.scaleLength(20), 0);
|
||||||
|
gdi.addButton("Apply", "OK", editListCB).setDefault();
|
||||||
|
|
||||||
|
gdi.dropLine(1);
|
||||||
|
maxY = max(maxY, gdi.getCY());
|
||||||
|
maxX = max(gdi.getCX(), maxX);
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
|
||||||
|
rc.top = y1;
|
||||||
|
rc.left = x1;
|
||||||
|
rc.right = maxX + gdi.scaleLength(6);
|
||||||
|
rc.bottom = maxY + gdi.scaleLength(6) + gdi.getLineHeight();
|
||||||
|
|
||||||
|
gdi.addRectangle(rc, colorLightBlue, true, false);
|
||||||
|
|
||||||
|
gdi.setData("IsEditingImage", 1);
|
||||||
|
|
||||||
|
gdi.scrollToBottom();
|
||||||
|
gdi.setCX(rc.right + gdi.scaleLength(10));
|
||||||
|
gdi.setCY(boxY);
|
||||||
|
|
||||||
|
if (imgId != 0) {
|
||||||
|
previewImage(gdi, selIx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ListEditor::selectImage(gdioutput &gdi, uint64_t imgId) {
|
||||||
|
vector<pair<wstring, size_t>> img;
|
||||||
|
image.enumerateImages(img);
|
||||||
|
img.emplace(img.begin(), lang.tl("Ingen[bild]"), -2);
|
||||||
|
gdi.addItem("Image", img);
|
||||||
|
|
||||||
|
int ix = image.getEnumerationIxFromId(imgId);
|
||||||
|
if (ix >= 0)
|
||||||
|
gdi.selectItemByData("Image", ix);
|
||||||
|
else
|
||||||
|
gdi.selectFirstItem("Image");
|
||||||
|
|
||||||
|
return ix;
|
||||||
|
}
|
||||||
|
|
||||||
void ListEditor::showExample(gdioutput &gdi, EPostType type) {
|
void ListEditor::showExample(gdioutput &gdi, EPostType type) {
|
||||||
if (type == EPostType::lLastItem) {
|
if (type == EPostType::lLastItem) {
|
||||||
type = EPostType(gdi.getSelectedItem("Type").first);
|
type = EPostType(gdi.getSelectedItem("Type").first);
|
||||||
@ -1275,6 +1556,46 @@ void ListEditor::showExample(gdioutput &gdi, const MetaListPost &mlp) {
|
|||||||
gdi.addRectangle(rrInner, color, true);
|
gdi.addRectangle(rrInner, color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListEditor::previewImage(gdioutput& gdi, int data) const {
|
||||||
|
gdi.restoreNoUpdate("image_preview");
|
||||||
|
gdi.setRestorePoint("image_preview");
|
||||||
|
if (data >= 0) {
|
||||||
|
auto imgId = image.getIdFromEnumeration(data);
|
||||||
|
oe->loadImage(imgId);
|
||||||
|
bool transparent = gdi.isChecked("TransparentWhite");
|
||||||
|
image.reloadImage(imgId, transparent ? Image::ImageMethod::WhiteTransparent : Image::ImageMethod::Default);
|
||||||
|
gdi.addImage("", gdi.getCY(), gdi.getCX(), 0, itow(imgId));
|
||||||
|
}
|
||||||
|
gdi.refreshFast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditor::updateImageStatus(gdioutput& gdi, int data) {
|
||||||
|
bool hasImg = int(data) >= 0;
|
||||||
|
gdi.setInputStatus("ImgWidth", hasImg);
|
||||||
|
gdi.setInputStatus("ImgHeight", hasImg);
|
||||||
|
gdi.setInputStatus("PreserveAspectRatio", hasImg);
|
||||||
|
gdi.setInputStatus("ImgOffsetX", hasImg);
|
||||||
|
gdi.setInputStatus("ImgOffsetY", hasImg);
|
||||||
|
|
||||||
|
if (hasImg) {
|
||||||
|
auto imgId = image.getIdFromEnumeration(data);
|
||||||
|
int h = image.getHeight(imgId);
|
||||||
|
int w = image.getWidth(imgId);
|
||||||
|
gdi.setText("ImgWidth", w);
|
||||||
|
gdi.setText("ImgHeight", h);
|
||||||
|
|
||||||
|
if (gdi.getTextNo("ImgOffsetX") == 0 && gdi.getTextNo("ImgOffsetY") == 0) {
|
||||||
|
// Change from blank to "0"
|
||||||
|
gdi.setText("ImgOffsetX", 0);
|
||||||
|
gdi.setText("ImgOffsetY", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gdi.setText("ImgWidth", L"");
|
||||||
|
gdi.setText("ImgHeight", L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const wchar_t *ListEditor::getIndexDescription(EPostType type) {
|
const wchar_t *ListEditor::getIndexDescription(EPostType type) {
|
||||||
if (type == lResultModuleTime || type == lResultModuleTimeTeam)
|
if (type == lResultModuleTime || type == lResultModuleTimeTeam)
|
||||||
return L"Index in X[index]#OutputTimes";
|
return L"Index in X[index]#OutputTimes";
|
||||||
@ -1310,7 +1631,7 @@ bool ListEditor::legStageTypeIndex(gdioutput &gdi, EPostType type, int leg) {
|
|||||||
gdi.setText("Leg", legW);
|
gdi.setText("Leg", legW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (MetaList::isAllStageType(type)) {
|
else if (MetaList::isAllStageType(type) || MetaList::isAllLegType(type)) {
|
||||||
if (gdi.hasWidget("UseLeg"))
|
if (gdi.hasWidget("UseLeg"))
|
||||||
gdi.removeWidget("UseLeg");
|
gdi.removeWidget("UseLeg");
|
||||||
|
|
||||||
@ -1322,9 +1643,22 @@ bool ListEditor::legStageTypeIndex(gdioutput &gdi, EPostType type, int leg) {
|
|||||||
else
|
else
|
||||||
gdi.addString("TUseLeg", ypUseLeg, xpUseLeg, 0, getIndexDescription(type));
|
gdi.addString("TUseLeg", ypUseLeg, xpUseLeg, 0, getIndexDescription(type));
|
||||||
|
|
||||||
if (!gdi.hasWidget("LegSel")) {
|
if (!gdi.hasWidget("LegSel"))
|
||||||
gdi.addSelection(xpUseLeg + dx, ypUseLeg + dy, "LegSel", 160, gdi.scaleLength(300), editListCB);
|
gdi.addSelection(xpUseLeg + dx, ypUseLeg + dy, "LegSel", 160, gdi.scaleLength(300), editListCB);
|
||||||
vector<pair<wstring, size_t>> items;
|
vector<pair<wstring, size_t>> items;
|
||||||
|
if (MetaList::isAllLegType(type)) {
|
||||||
|
items.emplace_back(lang.tl("Automatisk"), 0);
|
||||||
|
items.emplace_back(lang.tl("Alla sträckor"), -2);
|
||||||
|
for (int j = 1; j <= 50; j++) {
|
||||||
|
items.emplace_back(lang.tl("Sträcka X#" + itos(j)), j);
|
||||||
|
}
|
||||||
|
gdi.addItem("LegSel", items);
|
||||||
|
if (leg >= -1)
|
||||||
|
gdi.selectItemByData("LegSel", leg + 1);
|
||||||
|
else if (leg == -2)
|
||||||
|
gdi.selectItemByData("LegSel", -2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
items.emplace_back(lang.tl("Alla tidigare etapper"), -2);
|
items.emplace_back(lang.tl("Alla tidigare etapper"), -2);
|
||||||
for (int j = 1; j < 20; j++) {
|
for (int j = 1; j < 20; j++) {
|
||||||
items.emplace_back(lang.tl("Etapp X#" + itos(j)), j);
|
items.emplace_back(lang.tl("Etapp X#" + itos(j)), j);
|
||||||
@ -1373,6 +1707,7 @@ void ListEditor::editListProp(gdioutput &gdi, bool newList) {
|
|||||||
if (!newList) {
|
if (!newList) {
|
||||||
gdi.restore("EditList", false);
|
gdi.restore("EditList", false);
|
||||||
gdi.disableInput("EditList");
|
gdi.disableInput("EditList");
|
||||||
|
gdi.disableInput("SplitPrint");
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi.dropLine(0.8);
|
gdi.dropLine(0.8);
|
||||||
@ -1552,6 +1887,80 @@ void ListEditor::editListProp(gdioutput &gdi, bool newList) {
|
|||||||
gdi.setInputFocus("Name");
|
gdi.setInputFocus("Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListEditor::statusSplitPrint(gdioutput& gdi, bool status) {
|
||||||
|
gdi.setInputStatus("Split", status);
|
||||||
|
gdi.setInputStatus("Speed", status);
|
||||||
|
gdi.setInputStatus("Result", status);
|
||||||
|
gdi.setInputStatus("Analysis", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditor::splitPrintList(gdioutput& gdi) {
|
||||||
|
checkUnsaved(gdi);
|
||||||
|
|
||||||
|
if (!currentList)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MetaList& list = *currentList;
|
||||||
|
|
||||||
|
gdi.restore("EditList", false);
|
||||||
|
gdi.disableInput("EditList");
|
||||||
|
gdi.disableInput("SplitPrint");
|
||||||
|
|
||||||
|
gdi.dropLine(0.8);
|
||||||
|
|
||||||
|
int x1 = gdi.getCX();
|
||||||
|
int y1 = gdi.getCY();
|
||||||
|
int margin = gdi.scaleLength(10);
|
||||||
|
gdi.setCX(x1 + margin);
|
||||||
|
|
||||||
|
gdi.dropLine();
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.addString("", boldLarge, "Sträcktidsutskrift").setColor(colorDarkGrey);
|
||||||
|
gdi.dropLine();
|
||||||
|
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.pushX();
|
||||||
|
|
||||||
|
bool isSP = list.isSplitPrintList();
|
||||||
|
auto sp = list.getSplitPrintInfo();
|
||||||
|
gdi.fillDown();
|
||||||
|
|
||||||
|
gdi.addCheckbox("UseForSplit", "Använd listan för sträcktidsutskrift", editListCB, isSP);
|
||||||
|
|
||||||
|
gdi.dropLine(0.5);
|
||||||
|
gdi.fillRight();
|
||||||
|
gdi.addCheckbox("Split", "Inkludera sträcktider", nullptr, isSP ? sp->includeSplitTimes : true);
|
||||||
|
gdi.addCheckbox("Speed", "Inkludera tempo", nullptr, isSP ? sp->withSpeed : true);
|
||||||
|
gdi.addCheckbox("Result", "Inkludera individuellt resultat", nullptr, isSP ? sp->withResult : true);
|
||||||
|
gdi.addCheckbox("Analysis", "Inkludera bomanalys", nullptr, isSP ? sp->withAnalysis : true);
|
||||||
|
|
||||||
|
statusSplitPrint(gdi, isSP);
|
||||||
|
|
||||||
|
gdi.dropLine(0.8);
|
||||||
|
gdi.setCX(gdi.getCX() + 20);
|
||||||
|
gdi.addButton("ApplySplitList", "OK", editListCB);
|
||||||
|
gdi.addButton("Cancel", "Avbryt", editListCB);
|
||||||
|
|
||||||
|
gdi.dropLine(3);
|
||||||
|
int maxY = gdi.getCY();
|
||||||
|
int maxX = gdi.getCX();
|
||||||
|
|
||||||
|
gdi.fillDown();
|
||||||
|
gdi.popX();
|
||||||
|
gdi.setData("IsSplitListEdit", 1);
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
rc.top = y1;
|
||||||
|
rc.left = x1;
|
||||||
|
rc.right = maxX + gdi.scaleLength(6);
|
||||||
|
rc.bottom = maxY;
|
||||||
|
|
||||||
|
gdi.addRectangle(rc, colorLightBlue, true);
|
||||||
|
|
||||||
|
gdi.scrollToBottom();
|
||||||
|
gdi.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void ListEditor::makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside) {
|
void ListEditor::makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside) {
|
||||||
if (inside == MakeDirty)
|
if (inside == MakeDirty)
|
||||||
dirtyInt = true;
|
dirtyInt = true;
|
||||||
@ -1575,10 +1984,10 @@ void ListEditor::makeDirty(gdioutput &gdi, DirtyFlag inside, DirtyFlag outside)
|
|||||||
bool ListEditor::checkSave(gdioutput &gdi) {
|
bool ListEditor::checkSave(gdioutput &gdi) {
|
||||||
if (dirtyInt || dirtyExt) {
|
if (dirtyInt || dirtyExt) {
|
||||||
gdioutput::AskAnswer answer = gdi.askCancel(L"Vill du spara ändringar?");
|
gdioutput::AskAnswer answer = gdi.askCancel(L"Vill du spara ändringar?");
|
||||||
if (answer == gdioutput::AnswerCancel)
|
if (answer == gdioutput::AskAnswer::AnswerCancel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (answer == gdioutput::AnswerYes) {
|
if (answer == gdioutput::AskAnswer::AnswerYes) {
|
||||||
if (currentIndex >= 0)
|
if (currentIndex >= 0)
|
||||||
gdi.sendCtrlMessage("SaveInside");
|
gdi.sendCtrlMessage("SaveInside");
|
||||||
else if (gdi.sendCtrlMessage("SaveFile") == 0)
|
else if (gdi.sendCtrlMessage("SaveFile") == 0)
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -43,6 +43,7 @@ private:
|
|||||||
MetaList *currentList;
|
MetaList *currentList;
|
||||||
void setCurrentList(MetaList *lst);
|
void setCurrentList(MetaList *lst);
|
||||||
int currentIndex;
|
int currentIndex;
|
||||||
|
int currentRunnerId = 0;
|
||||||
wstring savedFileName;
|
wstring savedFileName;
|
||||||
bool dirtyExt;
|
bool dirtyExt;
|
||||||
bool dirtyInt;
|
bool dirtyInt;
|
||||||
@ -54,12 +55,22 @@ private:
|
|||||||
void updateType(int iType, gdioutput &gdi);
|
void updateType(int iType, gdioutput &gdi);
|
||||||
|
|
||||||
bool saveListPost(gdioutput &gdi, MetaListPost &mlp);
|
bool saveListPost(gdioutput &gdi, MetaListPost &mlp);
|
||||||
|
bool saveImage(gdioutput& gdi, MetaListPost& mlp);
|
||||||
|
|
||||||
|
static int selectImage(gdioutput& gdi, uint64_t imgId);
|
||||||
|
|
||||||
|
void updateImageStatus(gdioutput& gdi, int data);
|
||||||
|
|
||||||
ButtonInfo &addButton(gdioutput &gdi, const MetaListPost &mlp, int x, int y,
|
ButtonInfo &addButton(gdioutput &gdi, const MetaListPost &mlp, int x, int y,
|
||||||
int lineIx, int ix) const;
|
int lineIx, int ix) const;
|
||||||
|
|
||||||
|
|
||||||
|
void ListEditor::editDlgStart(gdioutput& gdi, int id, const char* title, int& x1, int& y1, int& boxY);
|
||||||
|
|
||||||
void editListPost(gdioutput &gdi, const MetaListPost &mlp, int id);
|
void editListPost(gdioutput &gdi, const MetaListPost &mlp, int id);
|
||||||
|
void editImage(gdioutput& gdi, const MetaListPost& mlp, int id);
|
||||||
|
void previewImage(gdioutput &gdi, int data) const;
|
||||||
|
|
||||||
void showExample(gdioutput &gdi, EPostType type = EPostType::lLastItem);
|
void showExample(gdioutput &gdi, EPostType type = EPostType::lLastItem);
|
||||||
|
|
||||||
void showExample(gdioutput &gdi, const MetaListPost &mlp);
|
void showExample(gdioutput &gdi, const MetaListPost &mlp);
|
||||||
@ -68,10 +79,14 @@ private:
|
|||||||
|
|
||||||
void editListProp(gdioutput &gdi, bool newList);
|
void editListProp(gdioutput &gdi, bool newList);
|
||||||
|
|
||||||
|
void statusSplitPrint(gdioutput& gdi, bool status);
|
||||||
|
|
||||||
|
void splitPrintList(gdioutput& gdi);
|
||||||
|
|
||||||
enum DirtyFlag {MakeDirty, ClearDirty, NoTouch};
|
enum DirtyFlag {MakeDirty, ClearDirty, NoTouch};
|
||||||
|
|
||||||
/// Check (and autosave) if there are unsaved changes in a dialog box
|
/// Check (and autosave) if there are unsaved changes in a dialog box. Return force flag
|
||||||
void checkUnsaved(gdioutput &gdi);
|
bool checkUnsaved(gdioutput &gdi);
|
||||||
|
|
||||||
/// Check and ask if there are changes to save
|
/// Check and ask if there are changes to save
|
||||||
bool checkSave(gdioutput &gdi);
|
bool checkSave(gdioutput &gdi);
|
||||||
@ -91,6 +106,7 @@ private:
|
|||||||
|
|
||||||
bool legStageTypeIndex(gdioutput &gdi, EPostType type, int leg);
|
bool legStageTypeIndex(gdioutput &gdi, EPostType type, int leg);
|
||||||
|
|
||||||
|
void renderListPreview(gdioutput& gdi);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ListEditor(oEvent *oe);
|
ListEditor(oEvent *oe);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/********************i****************************************************
|
/********************i****************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -89,10 +89,21 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
|
|||||||
gdi.setData("PunchSync", 1);
|
gdi.setData("PunchSync", 1);
|
||||||
gdi.setRestorePoint("LiveResult");
|
gdi.setRestorePoint("LiveResult");
|
||||||
|
|
||||||
|
readoutResult();
|
||||||
|
|
||||||
|
resYPos = h/3;
|
||||||
|
|
||||||
|
calculateResults();
|
||||||
|
showResultList = 0;
|
||||||
|
gdi.addTimeoutMilli(1000, "res", 0).setHandler(this);
|
||||||
|
gdi.refreshFast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiveResult::readoutResult() {
|
||||||
lastTime = 0;
|
lastTime = 0;
|
||||||
vector<const oFreePunch *> pp;
|
vector<const oFreePunch*> pp;
|
||||||
oe->synchronizeList({ oListId::oLRunnerId, oListId::oLPunchId });
|
oe->synchronizeList({ oListId::oLRunnerId, oListId::oLPunchId });
|
||||||
|
|
||||||
oe->getLatestPunches(lastTime, pp);
|
oe->getLatestPunches(lastTime, pp);
|
||||||
processedPunches.clear();
|
processedPunches.clear();
|
||||||
|
|
||||||
@ -103,14 +114,14 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
|
|||||||
fromPunch = oPunch::PunchStart;
|
fromPunch = oPunch::PunchStart;
|
||||||
if (toPunch == 0)
|
if (toPunch == 0)
|
||||||
toPunch = oPunch::PunchFinish;
|
toPunch = oPunch::PunchFinish;
|
||||||
|
|
||||||
for (size_t k = 0; k < pp.size(); k++) {
|
for (size_t k = 0; k < pp.size(); k++) {
|
||||||
lastTime = max(pp[k]->getModificationTime(), lastTime);
|
lastTime = max(pp[k]->getModificationTime(), lastTime);
|
||||||
pRunner r = pp[k]->getTiedRunner();
|
pRunner r = pp[k]->getTiedRunner();
|
||||||
if (r) {
|
if (r) {
|
||||||
pair<int, int> key = make_pair(r->getId(), pp[k]->getControlId());
|
pair<int, int> key = make_pair(r->getId(), pp[k]->getControlId());
|
||||||
processedPunches[key] = max(processedPunches[key], pp[k]->getAdjustedTime());
|
processedPunches[key] = max(processedPunches[key], pp[k]->getAdjustedTime());
|
||||||
|
|
||||||
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId(true)))
|
if (!li.getParam().selection.empty() && !li.getParam().selection.count(r->getClassId(true)))
|
||||||
continue; // Filter class
|
continue; // Filter class
|
||||||
|
|
||||||
@ -125,9 +136,9 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
|
|||||||
startFinishTime.clear();
|
startFinishTime.clear();
|
||||||
results.clear();
|
results.clear();
|
||||||
for (map<int, pair<vector<int>, vector<int> > >::iterator it = storedPunches.begin();
|
for (map<int, pair<vector<int>, vector<int> > >::iterator it = storedPunches.begin();
|
||||||
it != storedPunches.end(); ++it) {
|
it != storedPunches.end(); ++it) {
|
||||||
vector<int> &froms = it->second.first;
|
vector<int>& froms = it->second.first;
|
||||||
vector<int> &tos = it->second.second;
|
vector<int>& tos = it->second.second;
|
||||||
pRunner r = oe->getRunner(it->first, 0);
|
pRunner r = oe->getRunner(it->first, 0);
|
||||||
for (size_t j = 0; j < tos.size(); j++) {
|
for (size_t j = 0; j < tos.size(); j++) {
|
||||||
int fin = pp[tos[j]]->getAdjustedTime();
|
int fin = pp[tos[j]]->getAdjustedTime();
|
||||||
@ -141,22 +152,15 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (time < 100000000 && r->getStatus() <= StatusOK) {
|
if (time < 100000000 && r->getStatus() <= StatusOK) {
|
||||||
// results.push_back(Result());
|
// results.push_back(Result());
|
||||||
// results.back().r = r;
|
// results.back().r = r;
|
||||||
// results.back().time = time;
|
// results.back().time = time;
|
||||||
startFinishTime[r->getId()].first = sta;
|
startFinishTime[r->getId()].first = sta;
|
||||||
startFinishTime[r->getId()].second = fin;
|
startFinishTime[r->getId()].second = fin;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resYPos = h/3;
|
|
||||||
|
|
||||||
calculateResults();
|
|
||||||
showResultList = 0;
|
|
||||||
gdi.addTimeoutMilli(1000, "res", 0).setHandler(this);
|
|
||||||
gdi.refreshFast();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -352,20 +356,41 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
|
|||||||
|
|
||||||
if (doRefresh)
|
if (doRefresh)
|
||||||
gdi.refreshFast();
|
gdi.refreshFast();
|
||||||
|
else {
|
||||||
|
auto resCopy = results;
|
||||||
|
calculateResults();
|
||||||
|
bool reshow = false;
|
||||||
|
if (resCopy.size() != results.size())
|
||||||
|
reshow = true;
|
||||||
|
else {
|
||||||
|
for (size_t i = 0; i < results.size(); i++) {
|
||||||
|
if (resCopy[i].name.empty())
|
||||||
|
break;
|
||||||
|
if (resCopy[i].runnerId != results[i].runnerId) {
|
||||||
|
reshow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resCopy[i].time != results[i].time) {
|
||||||
|
reshow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRunner r = oe->getRunner(results[i].runnerId, 0);
|
||||||
|
if (!r || resCopy[i].name != r->getName()) {
|
||||||
|
reshow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reshow) {
|
||||||
|
showResults(gdi);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type == GUI_TIMEOUT) {
|
else if (type == GUI_TIMEOUT) {
|
||||||
gdi.restore("LiveResult", false);
|
showResults(gdi);
|
||||||
int h,w;
|
|
||||||
gdi.getTargetDimension(w, h);
|
|
||||||
gdi.fillDown();
|
|
||||||
BaseInfo *bi = gdi.setTextTranslate("timing", L"MeOS Timing", false);
|
|
||||||
TextInfo &ti = dynamic_cast<TextInfo &>(*bi);
|
|
||||||
ti.changeFont(getFont(gdi, 0.7));
|
|
||||||
gdi.refreshFast();
|
|
||||||
resYPos = ti.textRect.bottom + gdi.scaleLength(20);
|
|
||||||
calculateResults();
|
|
||||||
showResultList = 0;
|
|
||||||
gdi.addTimeoutMilli(300, "res", 0).setHandler(this);
|
|
||||||
}
|
}
|
||||||
else if (type == GUI_TIMER) {
|
else if (type == GUI_TIMER) {
|
||||||
if (size_t(showResultList) >= results.size())
|
if (size_t(showResultList) >= results.size())
|
||||||
@ -379,9 +404,10 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
|
|||||||
gdi.addTimeoutMilli(10, "res" + itos(showResultList), 0).setHandler(this);
|
gdi.addTimeoutMilli(10, "res" + itos(showResultList), 0).setHandler(this);
|
||||||
}
|
}
|
||||||
else if (res.place > 0) {
|
else if (res.place > 0) {
|
||||||
|
res.name = r->getName();
|
||||||
int h,w;
|
int h,w;
|
||||||
gdi.getTargetDimension(w, h);
|
gdi.getTargetDimension(w, h);
|
||||||
|
|
||||||
gdi.takeShownStringsSnapshot();
|
gdi.takeShownStringsSnapshot();
|
||||||
TextInfo &ti = gdi.addStringUT(y, 30, fontLarge, itow(res.place) + L".", 0, 0, font.c_str());
|
TextInfo &ti = gdi.addStringUT(y, 30, fontLarge, itow(res.place) + L".", 0, 0, font.c_str());
|
||||||
int ht = ti.textRect.bottom - ti.textRect.top;
|
int ht = ti.textRect.bottom - ti.textRect.top;
|
||||||
@ -400,6 +426,22 @@ void LiveResult::handle(gdioutput &gdi, BaseInfo &bu, GuiEventType type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LiveResult::showResults(gdioutput &gdi) {
|
||||||
|
gdi.restore("LiveResult", false);
|
||||||
|
int h, w;
|
||||||
|
gdi.getTargetDimension(w, h);
|
||||||
|
gdi.fillDown();
|
||||||
|
BaseInfo* bi = gdi.setTextTranslate("timing", L"MeOS Timing", false);
|
||||||
|
TextInfo& ti = dynamic_cast<TextInfo&>(*bi);
|
||||||
|
ti.changeFont(getFont(gdi, 0.7));
|
||||||
|
gdi.refreshFast();
|
||||||
|
resYPos = ti.textRect.bottom + gdi.scaleLength(20);
|
||||||
|
calculateResults();
|
||||||
|
showResultList = 0;
|
||||||
|
gdi.addTimeoutMilli(300, "res", 0).setHandler(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void LiveResult::calculateResults() {
|
void LiveResult::calculateResults() {
|
||||||
rToWatch.clear();
|
rToWatch.clear();
|
||||||
results.clear();
|
results.clear();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -49,14 +49,17 @@ class LiveResult : public GuiHandler {
|
|||||||
int place;
|
int place;
|
||||||
int runnerId;
|
int runnerId;
|
||||||
int time;
|
int time;
|
||||||
|
wstring name;
|
||||||
bool operator<(const Result &b) const {
|
bool operator<(const Result &b) const {
|
||||||
return time < b.time;
|
return time < b.time;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
vector< Result > results;
|
vector<Result> results;
|
||||||
|
|
||||||
void calculateResults();
|
void calculateResults();
|
||||||
|
void readoutResult();
|
||||||
|
void showResults(gdioutput& gdi);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LiveResult(oEvent *oe);
|
LiveResult(oEvent *oe);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -54,7 +54,7 @@ void MachineContainer::AbstractMachine::load(const xmlobject &data) {
|
|||||||
xmlList out;
|
xmlList out;
|
||||||
data.getObjects(out);
|
data.getObjects(out);
|
||||||
for (auto &x : out) {
|
for (auto &x : out) {
|
||||||
props[x.getName()] = x.getw();
|
props[x.getName()] = x.getWStr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -1832,14 +1832,13 @@ bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getUserFile(wchar_t *FileNamePath, const wchar_t *FileName)
|
bool getUserFile(wchar_t* FileNamePath, const wchar_t* FileName) {
|
||||||
{
|
|
||||||
wchar_t Path[MAX_PATH];
|
wchar_t Path[MAX_PATH];
|
||||||
wchar_t AppPath[MAX_PATH];
|
wchar_t AppPath[MAX_PATH];
|
||||||
|
|
||||||
if (SHGetSpecialFolderPath(hWndMain, Path, CSIDL_APPDATA, 1)!=NOERROR) {
|
if (SHGetSpecialFolderPath(hWndMain, Path, CSIDL_APPDATA, 1) != NOERROR) {
|
||||||
int i=wcslen(Path);
|
int i = wcslen(Path);
|
||||||
if (Path[i-1]!='\\')
|
if (Path[i - 1] != '\\')
|
||||||
wcscat_s(Path, MAX_PATH, L"\\");
|
wcscat_s(Path, MAX_PATH, L"\\");
|
||||||
|
|
||||||
wcscpy_s(AppPath, MAX_PATH, Path);
|
wcscpy_s(AppPath, MAX_PATH, Path);
|
||||||
|
|||||||
@ -52,6 +52,7 @@ IDB_ECO BITMAP "bmp00001.bmp"
|
|||||||
|
|
||||||
IDI_SPLASHIMAGE PNG "meos.png"
|
IDI_SPLASHIMAGE PNG "meos.png"
|
||||||
IDI_MEOSIMAGE PNG "title.png"
|
IDI_MEOSIMAGE PNG "title.png"
|
||||||
|
IDI_MEOSINFO PNG "info24.png"
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// English (United States) resources
|
// English (United States) resources
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -152,7 +152,7 @@ int getRelativeDay() {
|
|||||||
return int(qp);
|
return int(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
__int64 SystemTimeToInt64Second(const SYSTEMTIME &st) {
|
__int64 SystemTimeToInt64TenthSecond(const SYSTEMTIME &st) {
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
SystemTimeToFileTime(&st, &ft);
|
SystemTimeToFileTime(&st, &ft);
|
||||||
|
|
||||||
@ -160,16 +160,16 @@ __int64 SystemTimeToInt64Second(const SYSTEMTIME &st) {
|
|||||||
u.HighPart = ft.dwHighDateTime;
|
u.HighPart = ft.dwHighDateTime;
|
||||||
u.LowPart = ft.dwLowDateTime;
|
u.LowPart = ft.dwLowDateTime;
|
||||||
__int64 qp = u.QuadPart;
|
__int64 qp = u.QuadPart;
|
||||||
qp /= __int64(10) * 1000 * 1000;
|
qp /= __int64(1000 * 1000 * timeUnitsPerSecond);
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSTEMTIME Int64SecondToSystemTime(__int64 time) {
|
SYSTEMTIME Int64TenthSecondToSystemTime(__int64 time) {
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
|
|
||||||
ULARGE_INTEGER u;
|
ULARGE_INTEGER u;
|
||||||
u.QuadPart = time * __int64(10) * 1000 * 1000;
|
u.QuadPart = time * __int64(1000 * 1000 * timeUnitsPerSecond);
|
||||||
ft.dwHighDateTime = u.HighPart;
|
ft.dwHighDateTime = u.HighPart;
|
||||||
ft.dwLowDateTime = u.LowPart;
|
ft.dwLowDateTime = u.LowPart;
|
||||||
|
|
||||||
@ -257,44 +257,87 @@ int convertDateYMS(const wstring &m, SYSTEMTIME &st, bool checkValid) {
|
|||||||
return convertDateYMS(ms, st, checkValid);
|
return convertDateYMS(ms, st, checkValid);
|
||||||
}
|
}
|
||||||
//Absolute time string to SYSTEM TIME
|
//Absolute time string to SYSTEM TIME
|
||||||
int convertDateYMS(const string &m, SYSTEMTIME &st, bool checkValid) {
|
int convertDateYMS(const string& m, SYSTEMTIME& st, bool checkValid) {
|
||||||
memset(&st, 0, sizeof(st));
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
if (m.length()==0)
|
if (m.length() == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int len=m.length();
|
int len = m.length();
|
||||||
for (int k=0;k<len;k++) {
|
int dashCount = 0;
|
||||||
BYTE b=m[k];
|
for (int k = 0; k < len; k++) {
|
||||||
|
BYTE b = m[k];
|
||||||
if (b == 'T')
|
if (b == 'T')
|
||||||
break;
|
break;
|
||||||
if ( !(b=='-' || b==' ' || (b>='0' && b<='9')) )
|
if (!(b == '-' || b == ' ' || (b >= '0' && b <= '9')))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (b == '-')
|
||||||
|
dashCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int year=atoi(m.c_str());
|
int year = atoi(m.c_str());
|
||||||
if (year<1900 || year>3000)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int month=0;
|
if (dashCount == 0) {
|
||||||
int day=0;
|
int day = year % 100;
|
||||||
int kp=m.find_first_of('-');
|
year /= 100;
|
||||||
|
int month = year % 100;
|
||||||
|
year /= 100;
|
||||||
|
|
||||||
if (kp!=string::npos) {
|
if ((year > 0 && year < 100) || (year == 0 && m.size() > 2 && m[0] == '0' && m[1] == '0'))
|
||||||
string mtext=m.substr(kp+1);
|
year = extendYear(year);
|
||||||
month=atoi(mtext.c_str());
|
|
||||||
|
|
||||||
if (month<1 || month>12) {
|
if (year < 1900 || year>3000)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (month < 1 || month>12) {
|
||||||
if (checkValid)
|
if (checkValid)
|
||||||
return -1;
|
return -1;
|
||||||
month = 1;
|
month = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
kp=mtext.find_last_of('-');
|
if (day < 1 || day>31) {
|
||||||
|
if (checkValid)
|
||||||
|
return -1;
|
||||||
|
day = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (kp!=string::npos) {
|
st.wYear = year;
|
||||||
day=atoi(mtext.substr(kp+1).c_str());
|
st.wMonth = month;
|
||||||
if (day<1 || day>31) {
|
st.wDay = day;
|
||||||
|
|
||||||
|
int t = year * 100 * 100 + month * 100 + day;
|
||||||
|
if (t < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((year > 0 && year < 100) || (year == 0 && m.size() > 2 && m[0] == '0' && m[1] == '0'))
|
||||||
|
year = extendYear(year);
|
||||||
|
|
||||||
|
if (year < 1900 || year>3000)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int month = 0;
|
||||||
|
int day = 0;
|
||||||
|
int kp = m.find_first_of('-');
|
||||||
|
|
||||||
|
if (kp != string::npos) {
|
||||||
|
string mtext = m.substr(kp + 1);
|
||||||
|
month = atoi(mtext.c_str());
|
||||||
|
|
||||||
|
if (month < 1 || month>12) {
|
||||||
|
if (checkValid)
|
||||||
|
return -1;
|
||||||
|
month = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp = mtext.find_last_of('-');
|
||||||
|
|
||||||
|
if (kp != string::npos) {
|
||||||
|
day = atoi(mtext.substr(kp + 1).c_str());
|
||||||
|
if (day < 1 || day>31) {
|
||||||
if (checkValid)
|
if (checkValid)
|
||||||
return -1;
|
return -1;
|
||||||
day = 1;
|
day = 1;
|
||||||
@ -306,8 +349,8 @@ int convertDateYMS(const string &m, SYSTEMTIME &st, bool checkValid) {
|
|||||||
st.wDay = day;
|
st.wDay = day;
|
||||||
|
|
||||||
|
|
||||||
int t = year*100*100+month*100+day;
|
int t = year * 100 * 100 + month * 100 + day;
|
||||||
if (t<0) return -1;
|
if (t < 0) return -1;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -356,7 +399,7 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
|
|||||||
return -1;
|
return -1;
|
||||||
if (tpart < daysZeroTime)
|
if (tpart < daysZeroTime)
|
||||||
days--;
|
days--;
|
||||||
return days * 3600 * 24 + tpart;
|
return days * timeConstHour * 24 + tpart;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -364,7 +407,7 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
|
|||||||
int plusIndex = -1;
|
int plusIndex = -1;
|
||||||
for (int k=0;k<len;k++) {
|
for (int k=0;k<len;k++) {
|
||||||
BYTE b=m[k];
|
BYTE b=m[k];
|
||||||
if ( !(isspace(b) || b==':' || (b>='0' && b<='9')) ) {
|
if ( !(isspace(b) || b==':' || (b>='0' && b<='9') || b == '.' || b == ',') ) {
|
||||||
if (b=='+' && plusIndex ==-1 && k>0)
|
if (b=='+' && plusIndex ==-1 && k>0)
|
||||||
plusIndex = k;
|
plusIndex = k;
|
||||||
else
|
else
|
||||||
@ -377,7 +420,7 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
|
|||||||
int d = atoi(m.c_str());
|
int d = atoi(m.c_str());
|
||||||
|
|
||||||
if (d>0 && t>=0)
|
if (d>0 && t>=0)
|
||||||
return d*24*3600 + t;
|
return d*24* timeConstHour + t;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -389,6 +432,7 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
|
|||||||
|
|
||||||
int minute=0;
|
int minute=0;
|
||||||
int second=0;
|
int second=0;
|
||||||
|
int tenth = 0;
|
||||||
int kp=m.find_first_of(':');
|
int kp=m.find_first_of(':');
|
||||||
|
|
||||||
if (kp!=string::npos) {
|
if (kp!=string::npos) {
|
||||||
@ -401,13 +445,27 @@ int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) {
|
|||||||
kp=mtext.find_last_of(':');
|
kp=mtext.find_last_of(':');
|
||||||
|
|
||||||
if (kp!=string::npos) {
|
if (kp!=string::npos) {
|
||||||
second=atoi(mtext.substr(kp+1).c_str());
|
second=atoi(mtext.c_str() + kp+1);
|
||||||
if (second<0 || second>60)
|
if (second<0 || second>60)
|
||||||
second=0;
|
second=0;
|
||||||
|
|
||||||
|
if (timeConstSecond > 1) {
|
||||||
|
kp = mtext.find_last_of('.');
|
||||||
|
if (kp == string::npos)
|
||||||
|
kp = mtext.find_last_of(',');
|
||||||
|
if (kp != string::npos) {
|
||||||
|
tenth = atoi(mtext.c_str() + kp + 1);
|
||||||
|
if (tenth < 0 || tenth >= 10)
|
||||||
|
tenth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int t=hour*3600+minute*60+second;
|
|
||||||
if (t<0) return 0;
|
int t = hour * timeConstHour + minute * timeConstMinute + second * timeConstSecond + tenth;
|
||||||
|
|
||||||
|
if (t<0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -477,7 +535,7 @@ int convertAbsoluteTimeISO(const string &m)
|
|||||||
if (second<0 || second>60)
|
if (second<0 || second>60)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int t = hour*3600 + minute*60 + second;
|
int t = hour * timeConstHour + minute * timeConstMinute + second;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -509,31 +567,50 @@ int convertAbsoluteTimeMS(const string &m)
|
|||||||
mtext=m;
|
mtext=m;
|
||||||
|
|
||||||
minute=atoi(mtext.c_str());
|
minute=atoi(mtext.c_str());
|
||||||
|
int hour = 0;
|
||||||
if (minute<0 || minute>60*24)
|
if (minute<0 || minute>60*24)
|
||||||
minute=0;
|
minute=0;
|
||||||
|
|
||||||
int kp=mtext.find_first_of(':');
|
int kp=mtext.find_first_of(':');
|
||||||
|
bool gotSecond = false;
|
||||||
if (kp!=string::npos) {
|
if (kp!=string::npos) {
|
||||||
mtext = mtext.substr(kp+1);
|
mtext = mtext.substr(kp+1);
|
||||||
second = atoi(mtext.c_str());
|
second = atoi(mtext.c_str());
|
||||||
|
gotSecond = true;
|
||||||
if (second<0 || second>60)
|
if (second<0 || second>60)
|
||||||
second=0;
|
second=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int t=minute*60+second;
|
int t;
|
||||||
|
kp = mtext.find_first_of(':');
|
||||||
kp=mtext.find_first_of(':');
|
if (kp != string::npos) {
|
||||||
if (kp!=string::npos) {
|
|
||||||
//Allow also for format +-HH:MM:SS
|
//Allow also for format +-HH:MM:SS
|
||||||
mtext = mtext.substr(kp+1);
|
hour = minute;
|
||||||
second=atoi(mtext.c_str());
|
minute = second;
|
||||||
if (second<0 || second>60)
|
|
||||||
second=0;
|
mtext = mtext.substr(kp + 1);
|
||||||
else
|
second = atoi(mtext.c_str());
|
||||||
t = t*60 + second;
|
if (second < 0 || second>60)
|
||||||
|
second = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tenth = 0;
|
||||||
|
if (timeConstSecond > 1) {
|
||||||
|
kp = mtext.find_first_of('.');
|
||||||
|
if (kp == string::npos)
|
||||||
|
kp = mtext.find_last_of(',');
|
||||||
|
if (kp != string::npos) {
|
||||||
|
tenth = atoi(mtext.c_str() + kp + 1);
|
||||||
|
if (!gotSecond) { // Reinterpret minute as second (no minute was specified)
|
||||||
|
second = minute;
|
||||||
|
minute = 0;
|
||||||
|
}
|
||||||
|
if (tenth < 0 || tenth >= 10)
|
||||||
|
tenth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t = hour * timeConstHour + minute * timeConstMinute + second * timeConstSecond + tenth;
|
||||||
|
|
||||||
return sign*t;
|
return sign*t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,13 +620,37 @@ int convertAbsoluteTimeMS(const wstring &m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Generate +-MM:SS or +-HH:MM:SS
|
//Generate +-MM:SS or +-HH:MM:SS
|
||||||
const wstring &getTimeMS(int m) {
|
const wstring &formatTimeMS(int m, bool force2digit, SubSecond mode) {
|
||||||
wchar_t bf[32];
|
wchar_t bf[32];
|
||||||
int am = abs(m);
|
int am = abs(m);
|
||||||
if (am < 3600 || !MeOSUtil::useHourFormat)
|
if (am < timeConstHour || !MeOSUtil::useHourFormat) {
|
||||||
swprintf_s(bf, L"-%02d:%02d", am/60, am%60);
|
if (force2digit) {
|
||||||
else if (am < 3600*48)
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0))
|
||||||
swprintf_s(bf, L"-%02d:%02d:%02d", am/3600, (am/60)%60, am%60);
|
swprintf_s(bf, L"-%02d:%02d", am / timeConstMinute, (am / timeConstSecond) % 60);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"-%02d:%02d.%d", am / timeConstMinute, (am / timeConstSecond) % 60, am % timeConstSecond);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0))
|
||||||
|
swprintf_s(bf, L"-%d:%02d", am / timeConstMinute, (am / timeConstSecond) % 60);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"-%d:%02d.%d", am / timeConstMinute, (am / timeConstSecond) % 60, am % timeConstSecond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (am < timeConstHour * 48) {
|
||||||
|
if (force2digit) {
|
||||||
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0))
|
||||||
|
swprintf_s(bf, L"-%02d:%02d:%02d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"-%02d:%02d:%02d.%d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60, am % timeConstSecond);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0))
|
||||||
|
swprintf_s(bf, L"-%d:%02d:%02d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"-%d:%02d:%02d.%d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60, am % timeConstSecond);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
m = 0;
|
m = 0;
|
||||||
bf[0] = 0x2013;
|
bf[0] = 0x2013;
|
||||||
@ -564,15 +665,25 @@ const wstring &getTimeMS(int m) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &formatTime(int rt) {
|
const wstring &formatTime(int rt, SubSecond mode) {
|
||||||
wstring &res = StringCache::getInstance().wget();
|
wstring &res = StringCache::getInstance().wget();
|
||||||
if (rt>0 && rt<3600*999) {
|
if (rt>0 && rt<timeConstHour*999) {
|
||||||
wchar_t bf[16];
|
wchar_t bf[40];
|
||||||
if (rt>=3600 && MeOSUtil::useHourFormat)
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && rt % 10 == 0)) {
|
||||||
swprintf_s(bf, 16, L"%d:%02d:%02d", rt/3600,(rt/60)%60, rt%60);
|
if (rt >= timeConstHour && MeOSUtil::useHourFormat)
|
||||||
else
|
swprintf_s(bf, L"%d:%02d:%02d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60);
|
||||||
swprintf_s(bf, 16, L"%d:%02d", (rt/60), rt%60);
|
else
|
||||||
|
swprintf_s(bf, L"%d:%02d", (rt / timeConstMinute), (rt / timeConstSecond) % 60);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (rt >= timeConstHour && MeOSUtil::useHourFormat)
|
||||||
|
swprintf_s(bf, L"%d:%02d:%02d.%d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60, rt%timeConstSecond);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, L"%d:%02d.%d", (rt / timeConstMinute), (rt / timeConstSecond) % 60, rt%timeConstSecond);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
res = bf;
|
res = bf;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -583,12 +694,12 @@ const wstring &formatTime(int rt) {
|
|||||||
|
|
||||||
const string &formatTimeN(int rt) {
|
const string &formatTimeN(int rt) {
|
||||||
string &res = StringCache::getInstance().get();
|
string &res = StringCache::getInstance().get();
|
||||||
if (rt>0 && rt<3600*999) {
|
if (rt>0 && rt<timeConstHour *999) {
|
||||||
char bf[16];
|
char bf[16];
|
||||||
if (rt>=3600 && MeOSUtil::useHourFormat)
|
if (rt>= timeConstHour && MeOSUtil::useHourFormat)
|
||||||
sprintf_s(bf, 16, "%d:%02d:%02d", rt/3600,(rt/60)%60, rt%60);
|
sprintf_s(bf, 16, "%d:%02d:%02d", rt/ timeConstHour,(rt/timeConstMinute)%60, (rt/timeConstSecond)%60);
|
||||||
else
|
else
|
||||||
sprintf_s(bf, 16, "%d:%02d", (rt/60), rt%60);
|
sprintf_s(bf, 16, "%d:%02d", (rt/timeConstMinute), (rt/timeConstSecond)%60);
|
||||||
|
|
||||||
res = bf;
|
res = bf;
|
||||||
return res;
|
return res;
|
||||||
@ -597,11 +708,15 @@ const string &formatTimeN(int rt) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wstring &formatTimeHMS(int rt) {
|
const wstring &formatTimeHMS(int rt, SubSecond mode) {
|
||||||
wstring &res = StringCache::getInstance().wget();
|
wstring &res = StringCache::getInstance().wget();
|
||||||
if (rt>=0) {
|
if (rt>=0) {
|
||||||
wchar_t bf[32];
|
wchar_t bf[40];
|
||||||
swprintf_s(bf, 16, L"%02d:%02d:%02d", rt/3600,(rt/60)%60, rt%60);
|
if (mode == SubSecond::Off || (mode == SubSecond::Auto && rt%10 == 0))
|
||||||
|
swprintf_s(bf, 16, L"%02d:%02d:%02d", rt/timeConstHour,(rt/timeConstMinute)%60, (rt/timeConstSecond)%60);
|
||||||
|
else
|
||||||
|
swprintf_s(bf, 16, L"%02d:%02d:%02d.%d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60, rt % timeConstSecond);
|
||||||
|
|
||||||
res = bf;
|
res = bf;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -612,10 +727,10 @@ const wstring &formatTimeHMS(int rt) {
|
|||||||
|
|
||||||
wstring formatTimeIOF(int rt, int zeroTime)
|
wstring formatTimeIOF(int rt, int zeroTime)
|
||||||
{
|
{
|
||||||
if (rt>0 && rt<(3600*24*10)) {
|
if (rt > 0) {
|
||||||
rt+=zeroTime;
|
rt += zeroTime;
|
||||||
wchar_t bf[16];
|
wchar_t bf[16];
|
||||||
swprintf_s(bf, 16, L"%02d:%02d:%02d", (rt/3600)%24,(rt/60)%60, rt%60);
|
swprintf_s(bf, 16, L"%02d:%02d:%02d", (rt / timeConstHour) % 24, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60);
|
||||||
|
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
@ -766,7 +881,7 @@ wstring itow(int64_t i) {
|
|||||||
|
|
||||||
wstring itow(uint64_t i) {
|
wstring itow(uint64_t i) {
|
||||||
wchar_t bf[32];
|
wchar_t bf[32];
|
||||||
_i64tow_s(i, bf, 32, 10);
|
_ui64tow_s(i, bf, 32, 10);
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,14 +934,19 @@ bool filterMatchString(const string &c, const char *filt_lc)
|
|||||||
return strstr(key, filt_lc)!=0;
|
return strstr(key, filt_lc)!=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filterMatchString(const wstring &c, const wchar_t *filt_lc) {
|
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score) {
|
||||||
|
score = 0;
|
||||||
if (filt_lc[0] == 0)
|
if (filt_lc[0] == 0)
|
||||||
return true;
|
return true;
|
||||||
wchar_t key[2048];
|
wchar_t key[2048];
|
||||||
wcscpy_s(key, c.c_str());
|
wcscpy_s(key, c.c_str());
|
||||||
CharLowerBuff(key, c.length());
|
CharLowerBuff(key, c.length());
|
||||||
|
bool match = wcsstr(key, filt_lc) != 0;
|
||||||
return wcsstr(key, filt_lc)!=0;
|
if (match) {
|
||||||
|
while (filt_lc[score] && key[score] && filt_lc[score] == key[score])
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1936,8 +2056,8 @@ int getTimeZoneInfo(const wstring &date) {
|
|||||||
else if (datecodeUTC < datecode)
|
else if (datecodeUTC < datecode)
|
||||||
daydiff = -1;
|
daydiff = -1;
|
||||||
|
|
||||||
int t = st.wHour * 3600;
|
int t = st.wHour * timeConstSecPerHour;
|
||||||
int tUTC = daydiff * 24 * 3600 + utc.wHour * 3600 + utc.wMinute * 60 + utc.wSecond;
|
int tUTC = daydiff * 24 * timeConstSecPerHour + utc.wHour * timeConstSecPerHour + utc.wMinute * timeConstSecPerMin + utc.wSecond;
|
||||||
|
|
||||||
lastValue = tUTC - t;
|
lastValue = tUTC - t;
|
||||||
return lastValue;
|
return lastValue;
|
||||||
@ -1949,12 +2069,12 @@ wstring getTimeZoneString(const wstring &date) {
|
|||||||
return L"+00:00";
|
return L"+00:00";
|
||||||
else if (a>0) {
|
else if (a>0) {
|
||||||
wchar_t bf[12];
|
wchar_t bf[12];
|
||||||
swprintf_s(bf, L"-%02d:%02d", a/3600, (a/60)%60);
|
swprintf_s(bf, L"-%02d:%02d", a/timeConstSecPerHour, (a/timeConstMinPerHour)%60);
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wchar_t bf[12];
|
wchar_t bf[12];
|
||||||
swprintf_s(bf, L"+%02d:%02d", a/-3600, (a/-60)%60);
|
swprintf_s(bf, L"+%02d:%02d", a/-timeConstSecPerHour, (a/-timeConstMinPerHour)%60);
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2291,3 +2411,97 @@ const char* meosException::narrow(const wstring& msg) {
|
|||||||
static string nmsg(msg.begin(), msg.end());
|
static string nmsg(msg.begin(), msg.end());
|
||||||
return nmsg.c_str();
|
return nmsg.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parseRelativeTime(const char *data) {
|
||||||
|
if (data) {
|
||||||
|
int ret = atoi(data);
|
||||||
|
if (timeConstSecond > 1) {
|
||||||
|
int j = 0;
|
||||||
|
while (data[j]) {
|
||||||
|
if (data[j] == '.') {
|
||||||
|
int t = data[j + 1] - '0';
|
||||||
|
if (t > 0 && t < 10) {
|
||||||
|
if (ret < 0 || data[0] == '-')
|
||||||
|
return ret * timeConstSecond - t;
|
||||||
|
else
|
||||||
|
return ret * timeConstSecond + t;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == -1)
|
||||||
|
return ret; // Special value
|
||||||
|
|
||||||
|
return ret * timeConstSecond;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseRelativeTime(const wchar_t *data) {
|
||||||
|
if (data) {
|
||||||
|
int ret = _wtoi(data);
|
||||||
|
if (timeConstSecond > 1) {
|
||||||
|
int j = 0;
|
||||||
|
while (data[j]) {
|
||||||
|
if (data[j] == '.') {
|
||||||
|
int t = data[j + 1] - '0';
|
||||||
|
if (t > 0 && t < 10) {
|
||||||
|
if (ret < 0 || data[0] == '-')
|
||||||
|
return ret * timeConstSecond - t;
|
||||||
|
else
|
||||||
|
return ret * timeConstSecond + t;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == -1)
|
||||||
|
return ret; // Special value
|
||||||
|
|
||||||
|
return ret * timeConstSecond;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wstring &codeRelativeTimeW(int rt) {
|
||||||
|
wchar_t bf[32];
|
||||||
|
int subSec = timeConstSecond == 1 ? 0 : rt % timeConstSecond;
|
||||||
|
|
||||||
|
if (timeConstSecond == 1 || rt == -1)
|
||||||
|
return itow(rt);
|
||||||
|
else if (subSec == 0 && rt != -10)
|
||||||
|
return itow(rt / timeConstSecond);
|
||||||
|
else if (rt > 0) {
|
||||||
|
swprintf_s(bf, L"%d.%d", rt / timeConstSecond, rt % timeConstSecond);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rt = -rt;
|
||||||
|
swprintf_s(bf, L"-%d.%d", rt / timeConstSecond, rt % timeConstSecond);
|
||||||
|
}
|
||||||
|
wstring &res = StringCache::getInstance().wget();
|
||||||
|
res = bf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string &codeRelativeTime(int rt) {
|
||||||
|
char bf[32];
|
||||||
|
int subSec = timeConstSecond == 1 ? 0 : rt % timeConstSecond;
|
||||||
|
|
||||||
|
if (timeConstSecond == 1 || rt == -1)
|
||||||
|
return itos(rt);
|
||||||
|
else if (subSec == 0 && rt != -10)
|
||||||
|
return itos(rt / timeConstSecond);
|
||||||
|
else if (rt > 0) {
|
||||||
|
sprintf_s(bf, "%d.%d", rt / timeConstSecond, rt % timeConstSecond);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rt = -rt;
|
||||||
|
sprintf_s(bf, "-%d.%d", rt / timeConstSecond, rt % timeConstSecond);
|
||||||
|
}
|
||||||
|
string &res = StringCache::getInstance().get();
|
||||||
|
res = bf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -72,9 +72,22 @@ int getRelativeDay();
|
|||||||
/// Get time and date in a format that forms a part of a filename
|
/// Get time and date in a format that forms a part of a filename
|
||||||
wstring getLocalTimeFileName();
|
wstring getLocalTimeFileName();
|
||||||
|
|
||||||
const wstring &getTimeMS(int m);
|
enum class SubSecond {
|
||||||
const wstring &formatTime(int rt);
|
Off,
|
||||||
const wstring &formatTimeHMS(int rt);
|
On,
|
||||||
|
Auto
|
||||||
|
};
|
||||||
|
|
||||||
|
int parseRelativeTime(const char *data);
|
||||||
|
int parseRelativeTime(const wchar_t *data);
|
||||||
|
|
||||||
|
const wstring &codeRelativeTimeW(int rt);
|
||||||
|
const string &codeRelativeTime(int rt);
|
||||||
|
|
||||||
|
// Format time MM:SS.t (force2digit=true) or M:SS.t (force2digit=false)
|
||||||
|
const wstring &formatTimeMS(int m, bool force2digit, SubSecond mode = SubSecond::Auto);
|
||||||
|
const wstring &formatTime(int rt, SubSecond mode = SubSecond::Auto);
|
||||||
|
const wstring &formatTimeHMS(int rt, SubSecond mode = SubSecond::Auto);
|
||||||
|
|
||||||
wstring formatTimeIOF(int rt, int zeroTime);
|
wstring formatTimeIOF(int rt, int zeroTime);
|
||||||
|
|
||||||
@ -91,8 +104,8 @@ void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &
|
|||||||
//string formatDate(int m, bool useIsoFormat);
|
//string formatDate(int m, bool useIsoFormat);
|
||||||
wstring formatDate(int m, bool useIsoFormat);
|
wstring formatDate(int m, bool useIsoFormat);
|
||||||
|
|
||||||
__int64 SystemTimeToInt64Second(const SYSTEMTIME &st);
|
__int64 SystemTimeToInt64TenthSecond(const SYSTEMTIME &st);
|
||||||
SYSTEMTIME Int64SecondToSystemTime(__int64 time);
|
SYSTEMTIME Int64TenthSecondToSystemTime(__int64 time);
|
||||||
|
|
||||||
#define NOTIME 0x7FFFFFFF
|
#define NOTIME 0x7FFFFFFF
|
||||||
|
|
||||||
@ -141,7 +154,7 @@ wstring itow(uint64_t i);
|
|||||||
|
|
||||||
///Lower case match (filt_lc must be lc)
|
///Lower case match (filt_lc must be lc)
|
||||||
bool filterMatchString(const string &c, const char *filt_lc);
|
bool filterMatchString(const string &c, const char *filt_lc);
|
||||||
bool filterMatchString(const wstring &c, const wchar_t *filt_lc);
|
bool filterMatchString(const wstring &c, const wchar_t *filt_lc, int &score);
|
||||||
|
|
||||||
bool matchNumber(int number, const wchar_t *key);
|
bool matchNumber(int number, const wchar_t *key);
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -43,3 +43,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class meosCancel : public meosException {
|
||||||
|
|
||||||
|
};
|
||||||
|
|||||||
@ -462,6 +462,7 @@
|
|||||||
<ClCompile Include="animationdata.cpp" />
|
<ClCompile Include="animationdata.cpp" />
|
||||||
<ClCompile Include="autocomplete.cpp" />
|
<ClCompile Include="autocomplete.cpp" />
|
||||||
<ClCompile Include="autotask.cpp" />
|
<ClCompile Include="autotask.cpp" />
|
||||||
|
<ClCompile Include="binencoder.cpp" />
|
||||||
<ClCompile Include="classconfiginfo.cpp" />
|
<ClCompile Include="classconfiginfo.cpp" />
|
||||||
<ClCompile Include="csvparser.cpp">
|
<ClCompile Include="csvparser.cpp">
|
||||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
@ -669,6 +670,7 @@
|
|||||||
<ClInclude Include="autocomplete.h" />
|
<ClInclude Include="autocomplete.h" />
|
||||||
<ClInclude Include="autocompletehandler.h" />
|
<ClInclude Include="autocompletehandler.h" />
|
||||||
<ClInclude Include="autotask.h" />
|
<ClInclude Include="autotask.h" />
|
||||||
|
<ClInclude Include="binencoder.h" />
|
||||||
<ClInclude Include="classconfiginfo.h" />
|
<ClInclude Include="classconfiginfo.h" />
|
||||||
<ClInclude Include="gdiconstants.h" />
|
<ClInclude Include="gdiconstants.h" />
|
||||||
<ClInclude Include="gdifonts.h" />
|
<ClInclude Include="gdifonts.h" />
|
||||||
@ -710,6 +712,7 @@
|
|||||||
<ClInclude Include="speakermonitor.h" />
|
<ClInclude Include="speakermonitor.h" />
|
||||||
<ClInclude Include="subcommand.h" />
|
<ClInclude Include="subcommand.h" />
|
||||||
<ClInclude Include="testmeos.h" />
|
<ClInclude Include="testmeos.h" />
|
||||||
|
<ClInclude Include="timeconstants.hpp" />
|
||||||
<ClInclude Include="toolbar.h" />
|
<ClInclude Include="toolbar.h" />
|
||||||
<ClInclude Include="csvparser.h" />
|
<ClInclude Include="csvparser.h" />
|
||||||
<ClInclude Include="download.h" />
|
<ClInclude Include="download.h" />
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -23,23 +23,23 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "meos_util.h"
|
#include "meos_util.h"
|
||||||
|
|
||||||
//ABCDEFGHIJKLMNO
|
//ABCDEFGHIJKLMNOP
|
||||||
int getMeosBuild() {
|
int getMeosBuild() {
|
||||||
string revision("$Rev: 1152 $");
|
string revision("$Rev: 1225 $");
|
||||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMeosDate() {
|
wstring getMeosDate() {
|
||||||
wstring date(L"$Date: 2022-05-04 14:47:48 +0200 (ons, 04 maj 2022) $");
|
wstring date(L"$Date: 2023-02-08 19:30:10 +0100 (ons, 08 feb 2023) $");
|
||||||
return date.substr(7,10);
|
return date.substr(7,10);
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getBuildType() {
|
wstring getBuildType() {
|
||||||
return L"U1"; // No parantheses (...)
|
return L"Beta 1"; // No parantheses (...)
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMajorVersion() {
|
wstring getMajorVersion() {
|
||||||
return L"3.8";
|
return L"3.9";
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring getMeosFullVersion() {
|
wstring getMeosFullVersion() {
|
||||||
@ -67,31 +67,8 @@ wstring getMeosCompectVersion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
||||||
{
|
{
|
||||||
developSupp.emplace_back(L"Almby IK, Örebro");//2019--
|
supp.emplace_back(L"OK Gorm, Denmark");//2020-
|
||||||
supp.emplace_back(L"Ligue PACA");
|
|
||||||
supp.emplace_back(L"SC vebr-sport");
|
|
||||||
supp.emplace_back(L"IP Skogen Göteborg");
|
|
||||||
supp.emplace_back(L"Smedjebackens Orientering");
|
|
||||||
supp.emplace_back(L"Gudhems IF");
|
|
||||||
supp.emplace_back(L"Kexholm SK");
|
|
||||||
supp.emplace_back(L"Utby IK");
|
|
||||||
supp.emplace_back(L"JWOC 2019");
|
|
||||||
developSupp.emplace_back(L"OK Nackhe");
|
|
||||||
supp.emplace_back(L"OK Rodhen");
|
|
||||||
developSupp.emplace_back(L"SongTao Wang / Henan Zhixing Exploration Sports Culture Co., Ltd.");
|
|
||||||
developSupp.emplace_back(L"Australian and Oceania Orienteering Championships 2019");
|
|
||||||
supp.emplace_back(L"Järfälla OK");
|
|
||||||
supp.emplace_back(L"TJ Slávia Farmaceut Bratislava");
|
|
||||||
supp.emplace_back(L"Magnus Thornell, Surahammars SOK");
|
|
||||||
supp.emplace_back(L"Mariager Fjord OK");
|
|
||||||
supp.emplace_back(L"Nässjö OK");
|
|
||||||
supp.emplace_back(L"Ringsjö OK");
|
|
||||||
supp.emplace_back(L"Big Foot Orienteers");
|
|
||||||
supp.emplace_back(L"Erik Hulthen, Mölndal Outdoor IF");
|
|
||||||
supp.emplace_back(L"Bay Area Orienteering Club");
|
|
||||||
supp.emplace_back(L"Finspångs SOK");
|
|
||||||
supp.emplace_back(L"OK Gorm, Denmark");
|
|
||||||
supp.emplace_back(L"Nyköpings OK");
|
supp.emplace_back(L"Nyköpings OK");
|
||||||
supp.emplace_back(L"Thomas Engberg, VK Uvarna");
|
supp.emplace_back(L"Thomas Engberg, VK Uvarna");
|
||||||
supp.emplace_back(L"LG Axmalm, Sävedalens AIK");
|
supp.emplace_back(L"LG Axmalm, Sävedalens AIK");
|
||||||
@ -113,11 +90,9 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
|||||||
supp.emplace_back(L"Fredrik Magnusson, Laholms IF");
|
supp.emplace_back(L"Fredrik Magnusson, Laholms IF");
|
||||||
supp.emplace_back(L"KOB ATU Košice");
|
supp.emplace_back(L"KOB ATU Košice");
|
||||||
supp.emplace_back(L"Alfta-Ösa OK");
|
supp.emplace_back(L"Alfta-Ösa OK");
|
||||||
supp.emplace_back(L"HEYRIES, ACA Aix en Provence");
|
|
||||||
supp.emplace_back(L"IFK Kiruna");
|
supp.emplace_back(L"IFK Kiruna");
|
||||||
supp.emplace_back(L"Smedjebackens OK");
|
supp.emplace_back(L"Smedjebackens OK");
|
||||||
supp.emplace_back(L"Gunnar Persson, Svanesunds GIF");
|
supp.emplace_back(L"Gunnar Persson, Svanesunds GIF");
|
||||||
supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice");
|
|
||||||
supp.emplace_back(L"Køge Orienteringsklub");
|
supp.emplace_back(L"Køge Orienteringsklub");
|
||||||
supp.emplace_back(L"Simrishamns OK");
|
supp.emplace_back(L"Simrishamns OK");
|
||||||
supp.emplace_back(L"OK Fryksdalen");
|
supp.emplace_back(L"OK Fryksdalen");
|
||||||
@ -137,6 +112,7 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
|||||||
supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK");
|
supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK");
|
||||||
supp.emplace_back(L"O-Liceo, Spain");
|
supp.emplace_back(L"O-Liceo, Spain");
|
||||||
developSupp.emplace_back(L"Västerviks OK");
|
developSupp.emplace_back(L"Västerviks OK");
|
||||||
|
supp.emplace_back(L"Aarhus 1900 Orientering");
|
||||||
supp.emplace_back(L"Ljusne Ala OK");
|
supp.emplace_back(L"Ljusne Ala OK");
|
||||||
supp.emplace_back(L"Sävedalens AIK");
|
supp.emplace_back(L"Sävedalens AIK");
|
||||||
supp.emplace_back(L"Foothills Wanderers Orienteering Club");
|
supp.emplace_back(L"Foothills Wanderers Orienteering Club");
|
||||||
@ -144,6 +120,22 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
|||||||
supp.emplace_back(L"Per Ågren, OK Enen");
|
supp.emplace_back(L"Per Ågren, OK Enen");
|
||||||
supp.emplace_back(L"OK Roslagen");
|
supp.emplace_back(L"OK Roslagen");
|
||||||
supp.emplace_back(L"OK Kolmården");
|
supp.emplace_back(L"OK Kolmården");
|
||||||
|
developSupp.emplace_back(L"Orienteering Queensland Inc.");
|
||||||
|
supp.emplace_back(L"Eksjö SOK");
|
||||||
|
supp.emplace_back(L"Kolding OK");
|
||||||
|
developSupp.emplace_back(L"Alfta-Ösa OK");
|
||||||
|
supp.emplace_back(L"Erik Almséus, IFK Hedemora OK");
|
||||||
|
supp.emplace_back(L"IK Gandvik, Skara");
|
||||||
|
supp.emplace_back(L"Mats Kågeson");
|
||||||
|
supp.emplace_back(L"Lerums SOK");
|
||||||
|
supp.emplace_back(L"OSC Hamburg");
|
||||||
|
supp.emplace_back(L"HEYRIES, ACA Aix en Provence");
|
||||||
|
developSupp.emplace_back(L"IFK Mora OK");
|
||||||
|
supp.emplace_back(L"OK Rodhen");
|
||||||
|
supp.emplace_back(L"Big Foot Orienteers");
|
||||||
|
developSupp.emplace_back(L"OK Måsen");
|
||||||
|
supp.emplace_back(L"Ligue PACA");
|
||||||
|
supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice");
|
||||||
|
|
||||||
reverse(supp.begin(), supp.end());
|
reverse(supp.begin(), supp.end());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -37,8 +37,11 @@
|
|||||||
#include "localizer.h"
|
#include "localizer.h"
|
||||||
#include "gdifonts.h"
|
#include "gdifonts.h"
|
||||||
#include "autocomplete.h"
|
#include "autocomplete.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "binencoder.h"
|
||||||
|
|
||||||
extern oEvent *gEvent;
|
extern oEvent *gEvent;
|
||||||
|
extern Image image;
|
||||||
|
|
||||||
const int MAXLISTPARAMID = 10000000;
|
const int MAXLISTPARAMID = 10000000;
|
||||||
|
|
||||||
@ -438,9 +441,11 @@ int checksum(const wstring &str) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MetaList::initUniqueIndex() const {
|
void MetaList::initUniqueIndex() const {
|
||||||
__int64 ix = 0;
|
int64_t ix = 0;
|
||||||
|
|
||||||
|
if (splitPrintInfo)
|
||||||
|
ix = splitPrintInfo->checkSum();
|
||||||
|
|
||||||
for (int i = 0; i<4; i++) {
|
for (int i = 0; i<4; i++) {
|
||||||
const vector< vector<MetaListPost> > &lines = data[i];
|
const vector< vector<MetaListPost> > &lines = data[i];
|
||||||
@ -461,6 +466,15 @@ void MetaList::initUniqueIndex() const {
|
|||||||
value = value * 31 + mp.mergeWithPrevious;
|
value = value * 31 + mp.mergeWithPrevious;
|
||||||
value = value * 31 + mp.color;
|
value = value * 31 + mp.color;
|
||||||
value = value * 31 + mp.textAdjust;
|
value = value * 31 + mp.textAdjust;
|
||||||
|
if (mp.type == lImage) {
|
||||||
|
value = value * 31 + mp.imageHeight;
|
||||||
|
value = value * 31 + mp.imageWidth;
|
||||||
|
value = value * 31 + mp.imageStyle;
|
||||||
|
value = value * 31 + mp.imageOffsetX;
|
||||||
|
value = value * 31 + mp.imageOffsetY;
|
||||||
|
value = value * 31 + mp.imageStyleUnderText;
|
||||||
|
}
|
||||||
|
|
||||||
ix = ix * 997 + value;
|
ix = ix * 997 + value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,12 +593,23 @@ void MetaList::addRow(int ix) {
|
|||||||
|
|
||||||
static void setFixedWidth(oPrintPost &added,
|
static void setFixedWidth(oPrintPost &added,
|
||||||
const map<tuple<int,int,int>, int> &indexPosToWidth,
|
const map<tuple<int,int,int>, int> &indexPosToWidth,
|
||||||
int type, int j, int k) {
|
int type, int j, int k,
|
||||||
map<tuple<int,int,int>, int>::const_iterator res = indexPosToWidth.find(tuple<int,int,int>(type, j, k));
|
const MetaListPost &mlp) {
|
||||||
if (res != indexPosToWidth.end())
|
if (added.type == lImage) {
|
||||||
added.fixedWidth = res->second;
|
added.fixedWidth = mlp.getImageWidth();
|
||||||
else
|
added.fixedHeight = mlp.getImageHeight();
|
||||||
added.fixedWidth = 0;
|
added.dx += mlp.getImageOffsetX();
|
||||||
|
added.dy += mlp.getImageOffsetY();
|
||||||
|
if (mlp.imageUnderText())
|
||||||
|
added.imageNoUpdatePos = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map<tuple<int, int, int>, int>::const_iterator res = indexPosToWidth.find(tuple<int, int, int>(type, j, k));
|
||||||
|
if (res != indexPosToWidth.end())
|
||||||
|
added.fixedWidth = res->second;
|
||||||
|
else
|
||||||
|
added.fixedWidth = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par, oListInfo &li) const {
|
void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par, oListInfo &li) const {
|
||||||
@ -592,6 +617,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
PositionVer2 pos;
|
PositionVer2 pos;
|
||||||
const bool large = par.useLargeSize;
|
const bool large = par.useLargeSize;
|
||||||
li.lp = par;
|
li.lp = par;
|
||||||
|
li.setSplitPrintInfo(getSplitPrintInfo());
|
||||||
gdiFonts normal, header, small, italic;
|
gdiFonts normal, header, small, italic;
|
||||||
double s_factor;
|
double s_factor;
|
||||||
oe->calculateResults({}, oEvent::ResultType::ClassResult, false);
|
oe->calculateResults({}, oEvent::ResultType::ClassResult, false);
|
||||||
@ -668,7 +694,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i<4; i++) {
|
for (int i = 0; i<4; i++) {
|
||||||
const vector< vector<MetaListPost> > &lines = mList.data[i];
|
const vector<vector<MetaListPost>> &lines = mList.data[i];
|
||||||
gdiFonts defaultFont = normal;
|
gdiFonts defaultFont = normal;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -687,6 +713,10 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
return MetaList::isAllStageType(mp.type) && mp.leg == -1;
|
return MetaList::isAllStageType(mp.type) && mp.leg == -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto isAllLegType = [](const MetaListPost& mp) {
|
||||||
|
return MetaList::isAllLegType(mp.type) && mp.leg == -2;
|
||||||
|
};
|
||||||
|
|
||||||
for (size_t j = 0; j<lines.size(); j++) {
|
for (size_t j = 0; j<lines.size(); j++) {
|
||||||
if (i == 0 && j == 0)
|
if (i == 0 && j == 0)
|
||||||
defaultFont = boldLarge;
|
defaultFont = boldLarge;
|
||||||
@ -694,8 +724,16 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
dataCopy[i].emplace_back();
|
dataCopy[i].emplace_back();
|
||||||
vector<MetaListPost> &lineCopy = dataCopy[i].back();
|
vector<MetaListPost> &lineCopy = dataCopy[i].back();
|
||||||
|
|
||||||
int firstStage = -1;
|
int firstStage = -1, firstLeg = -1;
|
||||||
for (size_t k = 0; k < lines[j].size(); k++) {
|
for (size_t k = 0; k < lines[j].size(); k++) {
|
||||||
|
if (lines[j][k].type == lImage) {
|
||||||
|
auto id = lines[j][k].getImageId();
|
||||||
|
if (id > 0) {
|
||||||
|
oe->loadImage(id);
|
||||||
|
image.reloadImage(id, lines[j][k].getImageStyle() ? Image::ImageMethod::WhiteTransparent : Image::ImageMethod::Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isAllStageType(lines[j][k])) {
|
if (isAllStageType(lines[j][k])) {
|
||||||
if (firstStage == -1)
|
if (firstStage == -1)
|
||||||
firstStage = k;
|
firstStage = k;
|
||||||
@ -711,6 +749,26 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
firstStage = -1;
|
firstStage = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isAllLegType(lines[j][k])) {
|
||||||
|
if (firstLeg == -1)
|
||||||
|
firstLeg = k;
|
||||||
|
|
||||||
|
if (k + 1 == lines[j].size() || !isAllLegType(lines[j][k + 1])) {
|
||||||
|
int ns = 0;
|
||||||
|
vector<pClass> allC;
|
||||||
|
oe->getClasses(allC, false);
|
||||||
|
for (pClass c : allC)
|
||||||
|
ns = max<int>(ns, c->getNumStages());
|
||||||
|
|
||||||
|
for (int s = 1; s <= ns; s++) {
|
||||||
|
for (size_t f = firstLeg; f <= k; f++) {
|
||||||
|
lineCopy.push_back(lines[j][f]);
|
||||||
|
lineCopy.back().leg = s - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstLeg = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
lineCopy.push_back(lines[j][k]);
|
lineCopy.push_back(lines[j][k]);
|
||||||
}
|
}
|
||||||
@ -786,12 +844,18 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
}
|
}
|
||||||
if (mp.limitWidth && mp.blockWidth > 0)
|
if (mp.limitWidth && mp.blockWidth > 0)
|
||||||
width = gdi.scaleLength(mp.blockWidth);
|
width = gdi.scaleLength(mp.blockWidth);
|
||||||
else
|
else if (mp.type == lImage) {
|
||||||
|
if (mp.imageUnderText())
|
||||||
|
width = 1;
|
||||||
|
else
|
||||||
|
width = gdi.scaleLength(mp.getImageWidth());
|
||||||
|
}
|
||||||
|
else {
|
||||||
width = li.getMaxCharWidth(oe, gdi, par.selection, typeFormats, font,
|
width = li.getMaxCharWidth(oe, gdi, par.selection, typeFormats, font,
|
||||||
oPrintPost::encodeFont(fontFaces[i].font,
|
oPrintPost::encodeFont(fontFaces[i].font,
|
||||||
fontFaces[i].scale).c_str(),
|
fontFaces[i].scale).c_str(),
|
||||||
large, max(mp.blockWidth, extraMinWidth));
|
large, max(mp.blockWidth, extraMinWidth));
|
||||||
|
}
|
||||||
++linePostCount[make_pair(i, j)]; // Count how many positions on this line
|
++linePostCount[make_pair(i, j)]; // Count how many positions on this line
|
||||||
indexPosToWidth[tuple<int,int,int>(i, j, k)] = width;
|
indexPosToWidth[tuple<int,int,int>(i, j, k)] = width;
|
||||||
}
|
}
|
||||||
@ -911,10 +975,10 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
fontFaces[MLHead].scale);
|
fontFaces[MLHead].scale);
|
||||||
|
|
||||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||||
setFixedWidth(added, indexPosToWidth, MLHead, j, k);
|
setFixedWidth(added, indexPosToWidth, MLHead, j, k, mp);
|
||||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLHead, j, k)];
|
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLHead, j, k)];
|
||||||
added.color = mp.color;
|
added.color = mp.color;
|
||||||
if (!mp.mergeWithPrevious)
|
if (!mp.mergeWithPrevious && mp.type != lImage)
|
||||||
base = &added;
|
base = &added;
|
||||||
added.useStrictWidth = mp.getLimitBlockWidth();
|
added.useStrictWidth = mp.getLimitBlockWidth();
|
||||||
if (added.useStrictWidth)
|
if (added.useStrictWidth)
|
||||||
@ -928,9 +992,14 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
added.fixedWidth = 0;
|
added.fixedWidth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = &added;
|
last = mp.type != lImage ? &added : nullptr;
|
||||||
|
|
||||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLHead)]);
|
if (mp.type == lImage) {
|
||||||
|
if (!mp.imageUnderText())
|
||||||
|
next_dy = max(next_dy, gdi.scaleLength(mp.getImageHeight()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_dy = max(next_dy, fontHeight[make_pair(font, MLHead)]);
|
||||||
}
|
}
|
||||||
dy += next_dy;
|
dy += next_dy;
|
||||||
next_dy = lineHeight;
|
next_dy = lineHeight;
|
||||||
@ -965,10 +1034,10 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
fontFaces[MLSubHead].scale);
|
fontFaces[MLSubHead].scale);
|
||||||
|
|
||||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||||
setFixedWidth(added, indexPosToWidth, MLSubHead, j, k);
|
setFixedWidth(added, indexPosToWidth, MLSubHead, j, k, mp);
|
||||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubHead, j, k)];
|
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubHead, j, k)];
|
||||||
added.color = mp.color;
|
added.color = mp.color;
|
||||||
if (!mp.mergeWithPrevious)
|
if (!mp.mergeWithPrevious && mp.type != lImage)
|
||||||
base = &added;
|
base = &added;
|
||||||
|
|
||||||
added.useStrictWidth = mp.getLimitBlockWidth();
|
added.useStrictWidth = mp.getLimitBlockWidth();
|
||||||
@ -983,9 +1052,14 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
added.fixedWidth = 0;
|
added.fixedWidth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = &added;
|
last = mp.type != lImage ? &added : nullptr;
|
||||||
|
|
||||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLSubHead)]);
|
if (mp.type == lImage) {
|
||||||
|
if (!mp.imageUnderText())
|
||||||
|
next_dy = max(next_dy, gdi.scaleLength(mp.getImageHeight()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_dy = max(next_dy, fontHeight[make_pair(font, MLSubHead)]);
|
||||||
}
|
}
|
||||||
dy += next_dy;
|
dy += next_dy;
|
||||||
}
|
}
|
||||||
@ -1007,7 +1081,13 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
if (mp.font != formatIgnore)
|
if (mp.font != formatIgnore)
|
||||||
font = mp.font;
|
font = mp.font;
|
||||||
|
|
||||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLList)]);
|
if (mp.type == lImage) {
|
||||||
|
if (!mp.imageUnderText())
|
||||||
|
next_dy = max(next_dy, gdi.scaleLength(mp.getImageHeight()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_dy = max(next_dy, fontHeight[make_pair(font, MLList)]);
|
||||||
|
|
||||||
bool dmy;
|
bool dmy;
|
||||||
oPrintPost &added = li.addListPost(oPrintPost(mp.type, encode(mp.type, mp.text, dmy), font|mp.textAdjust,
|
oPrintPost &added = li.addListPost(oPrintPost(mp.type, encode(mp.type, mp.text, dmy), font|mp.textAdjust,
|
||||||
pos.get(label, s_factor),
|
pos.get(label, s_factor),
|
||||||
@ -1016,14 +1096,14 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
fontFaces[MLList].scale);
|
fontFaces[MLList].scale);
|
||||||
|
|
||||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||||
setFixedWidth(added, indexPosToWidth, MLList, j, k);
|
setFixedWidth(added, indexPosToWidth, MLList, j, k, mp);
|
||||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLList, j, k)];
|
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLList, j, k)];
|
||||||
added.useStrictWidth = mp.getLimitBlockWidth();
|
added.useStrictWidth = mp.getLimitBlockWidth();
|
||||||
if (added.useStrictWidth)
|
if (added.useStrictWidth)
|
||||||
added.format |= textLimitEllipsis;
|
added.format |= textLimitEllipsis;
|
||||||
|
|
||||||
added.color = mp.color;
|
added.color = mp.color;
|
||||||
if (!mp.mergeWithPrevious)
|
if (!mp.mergeWithPrevious && mp.type != lImage)
|
||||||
base = &added;
|
base = &added;
|
||||||
|
|
||||||
if (last && mp.mergeWithPrevious) {
|
if (last && mp.mergeWithPrevious) {
|
||||||
@ -1033,7 +1113,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
added.fixedWidth = 0;
|
added.fixedWidth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = &added;
|
last = mp.type != lImage ? &added : nullptr;
|
||||||
}
|
}
|
||||||
dy += next_dy;
|
dy += next_dy;
|
||||||
}
|
}
|
||||||
@ -1062,7 +1142,13 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
else
|
else
|
||||||
xp = pos.get(label, s_factor);
|
xp = pos.get(label, s_factor);
|
||||||
|
|
||||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLSubList)]);
|
if (mp.type == lImage) {
|
||||||
|
if (!mp.imageUnderText())
|
||||||
|
next_dy = max(next_dy, gdi.scaleLength(mp.getImageHeight()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_dy = max(next_dy, fontHeight[make_pair(font, MLSubList)]);
|
||||||
|
|
||||||
bool dmy;
|
bool dmy;
|
||||||
oPrintPost &added = li.addSubListPost(oPrintPost(mp.type, encode(mp.type, mp.text, dmy), font|mp.textAdjust,
|
oPrintPost &added = li.addSubListPost(oPrintPost(mp.type, encode(mp.type, mp.text, dmy), font|mp.textAdjust,
|
||||||
xp, dy+sublist_dy, mp.leg == -1 ? parLegNumber : make_pair(mp.leg, true))).
|
xp, dy+sublist_dy, mp.leg == -1 ? parLegNumber : make_pair(mp.leg, true))).
|
||||||
@ -1070,11 +1156,11 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
fontFaces[MLSubList].scale);
|
fontFaces[MLSubList].scale);
|
||||||
|
|
||||||
added.color = mp.color;
|
added.color = mp.color;
|
||||||
if (!mp.mergeWithPrevious)
|
if (!mp.mergeWithPrevious && mp.type != lImage)
|
||||||
base = &added;
|
base = &added;
|
||||||
|
|
||||||
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
added.resultModuleIndex = getResultModuleIndex(oe, li, mp);
|
||||||
setFixedWidth(added, indexPosToWidth, MLSubList, j, k);
|
setFixedWidth(added, indexPosToWidth, MLSubList, j, k, mp);
|
||||||
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubList, j, k)];
|
added.xlimit = indexPosToWidthSrc[tuple<int, int, int>(MLSubList, j, k)];
|
||||||
added.useStrictWidth = mp.getLimitBlockWidth();
|
added.useStrictWidth = mp.getLimitBlockWidth();
|
||||||
if (added.useStrictWidth)
|
if (added.useStrictWidth)
|
||||||
@ -1087,7 +1173,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
|||||||
added.fixedWidth = 0;
|
added.fixedWidth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last = &added;
|
last = mp.type != lImage ? &added : nullptr;
|
||||||
}
|
}
|
||||||
dy += next_dy;
|
dy += next_dy;
|
||||||
}
|
}
|
||||||
@ -1387,11 +1473,11 @@ bool Position::postAdjust() {
|
|||||||
void MetaList::save(const wstring &file, const oEvent *oe) const {
|
void MetaList::save(const wstring &file, const oEvent *oe) const {
|
||||||
xmlparser xml;
|
xmlparser xml;
|
||||||
xml.openOutput(file.c_str(), true);
|
xml.openOutput(file.c_str(), true);
|
||||||
save(xml, oe);
|
save(xml, true, oe);
|
||||||
xml.closeOut();
|
xml.closeOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaList::save(xmlparser &xml, const oEvent *oe) const {
|
void MetaList::save(xmlparser &xml, bool includeImages, const oEvent *oe) const {
|
||||||
initSymbols();
|
initSymbols();
|
||||||
xml.startTag("MeOSListDefinition", "version", getMajorVersion());
|
xml.startTag("MeOSListDefinition", "version", getMajorVersion());
|
||||||
// xml.write("Title", defaultTitle);
|
// xml.write("Title", defaultTitle);
|
||||||
@ -1401,6 +1487,13 @@ void MetaList::save(xmlparser &xml, const oEvent *oe) const {
|
|||||||
xml.write("ListOrigin", listOrigin);
|
xml.write("ListOrigin", listOrigin);
|
||||||
xml.write("Tag", tag);
|
xml.write("Tag", tag);
|
||||||
xml.write("UID", getUniqueId());
|
xml.write("UID", getUniqueId());
|
||||||
|
|
||||||
|
if (splitPrintInfo) {
|
||||||
|
xml.startTag("SplitPrint");
|
||||||
|
splitPrintInfo->serialize(xml);
|
||||||
|
xml.endTag();
|
||||||
|
}
|
||||||
|
|
||||||
xml.write("SortOrder", orderToSymbol[sortOrder]);
|
xml.write("SortOrder", orderToSymbol[sortOrder]);
|
||||||
xml.write("ListType", baseTypeToSymbol[listType]);
|
xml.write("ListType", baseTypeToSymbol[listType]);
|
||||||
xml.write("SubListType", baseTypeToSymbol[listSubType]);
|
xml.write("SubListType", baseTypeToSymbol[listSubType]);
|
||||||
@ -1454,6 +1547,22 @@ void MetaList::save(xmlparser &xml, const oEvent *oe) const {
|
|||||||
serialize(xml, "List", getList());
|
serialize(xml, "List", getList());
|
||||||
serialize(xml, "SubList", getSubList());
|
serialize(xml, "SubList", getSubList());
|
||||||
|
|
||||||
|
if (includeImages) {
|
||||||
|
set<uint64_t> img;
|
||||||
|
getUsedImages(img);
|
||||||
|
Encoder92 binEncoder;
|
||||||
|
for (auto imgId : img) {
|
||||||
|
wstring fileName = image.getFileName(imgId);
|
||||||
|
auto rawData = image.getRawData(imgId);
|
||||||
|
string encoded;
|
||||||
|
binEncoder.encode92(rawData, encoded);
|
||||||
|
vector<pair<string, wstring>> props;
|
||||||
|
props.emplace_back("filename", fileName);
|
||||||
|
props.emplace_back("id", itow(imgId));
|
||||||
|
xml.writeAscii("Image", props, encoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml.endTag();
|
xml.endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,6 +1584,11 @@ void MetaList::load(const xmlobject &xDef) {
|
|||||||
xDef.getObjectString("UID", uniqueIndex);
|
xDef.getObjectString("UID", uniqueIndex);
|
||||||
xDef.getObjectString("ResultModule", resultModule);
|
xDef.getObjectString("ResultModule", resultModule);
|
||||||
|
|
||||||
|
auto xSplitPrint = xDef.getObject("SplitPrint");
|
||||||
|
if (xSplitPrint) {
|
||||||
|
splitPrintInfo = make_shared<SplitPrintListInfo>();
|
||||||
|
splitPrintInfo->deserialize(xSplitPrint);
|
||||||
|
}
|
||||||
// string db = "Specified res mod: " + resultModule + "\n";
|
// string db = "Specified res mod: " + resultModule + "\n";
|
||||||
// OutputDebugString(db.c_str());
|
// OutputDebugString(db.c_str());
|
||||||
|
|
||||||
@ -1523,29 +1637,29 @@ void MetaList::load(const xmlobject &xDef) {
|
|||||||
xmlobject xSubListFont = xDef.getObject("SubListFont");
|
xmlobject xSubListFont = xDef.getObject("SubListFont");
|
||||||
|
|
||||||
if (xHeadFont) {
|
if (xHeadFont) {
|
||||||
const wchar_t *f = xHeadFont.getw();
|
const wchar_t *f = xHeadFont.getWPtr();
|
||||||
fontFaces[MLHead].font = f != 0 ? f : L"arial";
|
fontFaces[MLHead].font = f != nullptr ? f : L"arial";
|
||||||
fontFaces[MLHead].scale = xHeadFont.getObjectInt("scale");
|
fontFaces[MLHead].scale = xHeadFont.getObjectInt("scale");
|
||||||
fontFaces[MLHead].extraSpaceAbove = xHeadFont.getObjectInt("above");
|
fontFaces[MLHead].extraSpaceAbove = xHeadFont.getObjectInt("above");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xSubHeadFont) {
|
if (xSubHeadFont) {
|
||||||
const wchar_t *f = xSubHeadFont.getw();
|
const wchar_t *f = xSubHeadFont.getWPtr();
|
||||||
fontFaces[MLSubHead].font = f != 0 ? f : L"arial";
|
fontFaces[MLSubHead].font = f != nullptr ? f : L"arial";
|
||||||
fontFaces[MLSubHead].scale = xSubHeadFont.getObjectInt("scale");
|
fontFaces[MLSubHead].scale = xSubHeadFont.getObjectInt("scale");
|
||||||
fontFaces[MLSubHead].extraSpaceAbove = xSubHeadFont.getObjectInt("above");
|
fontFaces[MLSubHead].extraSpaceAbove = xSubHeadFont.getObjectInt("above");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xListFont) {
|
if (xListFont) {
|
||||||
const wchar_t *f = xListFont.getw();
|
const wchar_t *f = xListFont.getWPtr();
|
||||||
fontFaces[MLList].font = f != 0 ? f : L"arial";
|
fontFaces[MLList].font = f != nullptr ? f : L"arial";
|
||||||
fontFaces[MLList].scale = xListFont.getObjectInt("scale");
|
fontFaces[MLList].scale = xListFont.getObjectInt("scale");
|
||||||
fontFaces[MLList].extraSpaceAbove = xListFont.getObjectInt("above");
|
fontFaces[MLList].extraSpaceAbove = xListFont.getObjectInt("above");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xSubListFont) {
|
if (xSubListFont) {
|
||||||
const wchar_t *f = xSubListFont.getw();
|
const wchar_t *f = xSubListFont.getWPtr();
|
||||||
fontFaces[MLSubList].font = f != 0 ? f : L"arial";
|
fontFaces[MLSubList].font = f != nullptr ? f : L"arial";
|
||||||
fontFaces[MLSubList].scale = xSubListFont.getObjectInt("scale");
|
fontFaces[MLSubList].scale = xSubListFont.getObjectInt("scale");
|
||||||
fontFaces[MLSubList].extraSpaceAbove = xSubListFont.getObjectInt("above");
|
fontFaces[MLSubList].extraSpaceAbove = xSubListFont.getObjectInt("above");
|
||||||
}
|
}
|
||||||
@ -1605,7 +1719,7 @@ void MetaList::load(const xmlobject &xDef) {
|
|||||||
xDef.getObjects("Filter", f);
|
xDef.getObjects("Filter", f);
|
||||||
|
|
||||||
for (size_t k = 0; k<f.size(); k++) {
|
for (size_t k = 0; k<f.size(); k++) {
|
||||||
string attrib = f[k].getAttrib("name").get();
|
string attrib = f[k].getAttrib("name").getStr();
|
||||||
if (symbolToFilter.count(attrib) == 0) {
|
if (symbolToFilter.count(attrib) == 0) {
|
||||||
string err = "Invalid filter X#" + attrib;
|
string err = "Invalid filter X#" + attrib;
|
||||||
throw std::exception(err.c_str());
|
throw std::exception(err.c_str());
|
||||||
@ -1620,13 +1734,29 @@ void MetaList::load(const xmlobject &xDef) {
|
|||||||
xDef.getObjects("SubFilter", f);
|
xDef.getObjects("SubFilter", f);
|
||||||
|
|
||||||
for (size_t k = 0; k<f.size(); k++) {
|
for (size_t k = 0; k<f.size(); k++) {
|
||||||
string attrib = f[k].getAttrib("name").get();
|
string attrib = f[k].getAttrib("name").getStr();
|
||||||
if (symbolToSubFilter.count(attrib) == 0) {
|
if (symbolToSubFilter.count(attrib) == 0) {
|
||||||
string err = "Invalid filter X#" + attrib;
|
string err = "Invalid filter X#" + attrib;
|
||||||
throw std::exception(err.c_str());
|
throw std::exception(err.c_str());
|
||||||
}
|
}
|
||||||
addSubFilter(symbolToSubFilter[attrib]);
|
addSubFilter(symbolToSubFilter[attrib]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlList imgs;
|
||||||
|
xDef.getObjects("Image", imgs);
|
||||||
|
|
||||||
|
Encoder92 binEncoder;
|
||||||
|
vector<uint8_t> bytes;
|
||||||
|
for (auto& img : imgs) {
|
||||||
|
wstring fileName, id;
|
||||||
|
img.getObjectString("filename", fileName);
|
||||||
|
img.getObjectString("id", id);
|
||||||
|
uint64_t imgId = _wcstoui64(id.c_str(), nullptr, 10);
|
||||||
|
string data = img.getRawStr();
|
||||||
|
binEncoder.decode92(data, bytes);
|
||||||
|
image.provideFromMemory(imgId, fileName, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaList::getDynamicResults(vector<DynamicResultRef> &resultModules) const {
|
void MetaList::getDynamicResults(vector<DynamicResultRef> &resultModules) const {
|
||||||
@ -1729,6 +1859,14 @@ bool MetaListContainer::updateResultModule(const DynamicResult &dr, bool updateS
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetaListContainer::getUsedImages(set<uint64_t>& imgId) const {
|
||||||
|
for (size_t i = 0; i < data.size(); i++) {
|
||||||
|
if (data[i].first == ExternalList) {
|
||||||
|
data[i].second.getUsedImages(imgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MetaList::serialize(xmlparser &xml, const string &tagp,
|
void MetaList::serialize(xmlparser &xml, const string &tagp,
|
||||||
const vector< vector<MetaListPost> > &lp) const {
|
const vector< vector<MetaListPost> > &lp) const {
|
||||||
xml.startTag(tagp.c_str());
|
xml.startTag(tagp.c_str());
|
||||||
@ -1802,6 +1940,8 @@ void MetaListPost::getTypes(vector< pair<wstring, size_t> > &types, int ¤t
|
|||||||
continue;
|
continue;
|
||||||
if (it->first == lAlignNext)
|
if (it->first == lAlignNext)
|
||||||
continue;
|
continue;
|
||||||
|
if (it->first == lImage)
|
||||||
|
continue;
|
||||||
|
|
||||||
types.push_back(make_pair(lang.tl(it->second), it->first));
|
types.push_back(make_pair(lang.tl(it->second), it->first));
|
||||||
}
|
}
|
||||||
@ -1895,6 +2035,21 @@ void MetaListPost::serialize(xmlparser &xml) const {
|
|||||||
xml.write("PackPrevious", packPrevious);
|
xml.write("PackPrevious", packPrevious);
|
||||||
xml.write("LimitWidth", limitWidth);
|
xml.write("LimitWidth", limitWidth);
|
||||||
|
|
||||||
|
if (imageWidth != 0)
|
||||||
|
xml.write("ImageWidth", imageWidth);
|
||||||
|
if (imageHeight != 0)
|
||||||
|
xml.write("ImageHeight", imageHeight);
|
||||||
|
|
||||||
|
if (imageOffsetX != 0)
|
||||||
|
xml.write("ImageOffsetX", imageOffsetX);
|
||||||
|
if (imageOffsetY != 0)
|
||||||
|
xml.write("ImageOffsetY", imageOffsetY);
|
||||||
|
|
||||||
|
if (imageStyle != 0)
|
||||||
|
xml.write("ImageStyle", imageStyle);
|
||||||
|
|
||||||
|
if (imageStyleUnderText)
|
||||||
|
xml.writeBool("UnderText", imageStyleUnderText);
|
||||||
|
|
||||||
if (font != formatIgnore)
|
if (font != formatIgnore)
|
||||||
xml.write("Font", getFont());
|
xml.write("Font", getFont());
|
||||||
@ -1914,7 +2069,7 @@ void MetaListPost::deserialize(const xmlobject &xml) {
|
|||||||
if (!xml)
|
if (!xml)
|
||||||
throw meosException("Ogiltigt filformat");
|
throw meosException("Ogiltigt filformat");
|
||||||
|
|
||||||
wstring tp = xml.getAttrib("Type").wget();
|
wstring tp = xml.getAttrib("Type").getWStr();
|
||||||
if (MetaList::symbolToType.count(tp) == 0) {
|
if (MetaList::symbolToType.count(tp) == 0) {
|
||||||
wstring err = L"Invalid type X#" + tp;
|
wstring err = L"Invalid type X#" + tp;
|
||||||
throw meosException(err);
|
throw meosException(err);
|
||||||
@ -1946,6 +2101,15 @@ void MetaListPost::deserialize(const xmlobject &xml) {
|
|||||||
limitWidth = xml.getObjectBool("LimitWidth");
|
limitWidth = xml.getObjectBool("LimitWidth");
|
||||||
|
|
||||||
mergeWithPrevious = xml.getObjectInt("MergePrevious") != 0;
|
mergeWithPrevious = xml.getObjectInt("MergePrevious") != 0;
|
||||||
|
|
||||||
|
imageWidth = xml.getObjectInt("ImageWidth");
|
||||||
|
imageHeight = xml.getObjectInt("ImageHeight");
|
||||||
|
imageOffsetX = xml.getObjectInt("ImageOffsetX");
|
||||||
|
imageOffsetY = xml.getObjectInt("ImageOffsetY");
|
||||||
|
|
||||||
|
imageStyle = xml.getObjectInt("ImageStyle");
|
||||||
|
imageStyleUnderText = xml.getObjectBool("UnderText");
|
||||||
|
|
||||||
xml.getObjectString("TextAdjust", at);
|
xml.getObjectString("TextAdjust", at);
|
||||||
|
|
||||||
if (at == L"Right")
|
if (at == L"Right")
|
||||||
@ -1970,6 +2134,28 @@ void MetaListPost::deserialize(const xmlobject &xml) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetaList::getUsedImages(set<uint64_t>& imgId) const {
|
||||||
|
for (auto& v1 : data) {
|
||||||
|
for (auto& v2 : v1) {
|
||||||
|
for (auto& v3 : v2) {
|
||||||
|
if (v3.type == lImage) {
|
||||||
|
auto id = v3.getImageId();
|
||||||
|
if (id != 0)
|
||||||
|
imgId.insert(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t MetaListPost::getImageId() const {
|
||||||
|
if (type == lImage) {
|
||||||
|
uint64_t imgId = _wcstoui64(getText().c_str(), nullptr, 10);
|
||||||
|
return imgId;
|
||||||
|
}
|
||||||
|
throw meosException("Internal error");
|
||||||
|
}
|
||||||
|
|
||||||
map<EPostType, wstring> MetaList::typeToSymbol;
|
map<EPostType, wstring> MetaList::typeToSymbol;
|
||||||
map<wstring, EPostType> MetaList::symbolToType;
|
map<wstring, EPostType> MetaList::symbolToType;
|
||||||
map<oListInfo::EBaseType, string> MetaList::baseTypeToSymbol;
|
map<oListInfo::EBaseType, string> MetaList::baseTypeToSymbol;
|
||||||
@ -2006,6 +2192,7 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lClassNumEntries] = L"ClassNumEntries";
|
typeToSymbol[lClassNumEntries] = L"ClassNumEntries";
|
||||||
typeToSymbol[lCourseLength] = L"CourseLength";
|
typeToSymbol[lCourseLength] = L"CourseLength";
|
||||||
typeToSymbol[lCourseName] = L"CourseName";
|
typeToSymbol[lCourseName] = L"CourseName";
|
||||||
|
typeToSymbol[lCourseNumber] = L"CourseNumber";
|
||||||
typeToSymbol[lCourseClimb] = L"CourseClimb";
|
typeToSymbol[lCourseClimb] = L"CourseClimb";
|
||||||
typeToSymbol[lCourseUsage] = L"CourseUsage";
|
typeToSymbol[lCourseUsage] = L"CourseUsage";
|
||||||
typeToSymbol[lCourseUsageNoVacant] = L"CourseUsageNoVacant";
|
typeToSymbol[lCourseUsageNoVacant] = L"CourseUsageNoVacant";
|
||||||
@ -2066,6 +2253,7 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lResultModuleNumberTeam] = L"ResultModuleNumberTeam";
|
typeToSymbol[lResultModuleNumberTeam] = L"ResultModuleNumberTeam";
|
||||||
|
|
||||||
typeToSymbol[lRunnerBirthYear] = L"RunnerBirthYear";
|
typeToSymbol[lRunnerBirthYear] = L"RunnerBirthYear";
|
||||||
|
typeToSymbol[lRunnerBirthDate] = L"RunnerBirthDate";
|
||||||
typeToSymbol[lRunnerAge] = L"RunnerAge";
|
typeToSymbol[lRunnerAge] = L"RunnerAge";
|
||||||
typeToSymbol[lRunnerSex] = L"RunnerSex";
|
typeToSymbol[lRunnerSex] = L"RunnerSex";
|
||||||
typeToSymbol[lRunnerNationality] = L"RunnerNationality";
|
typeToSymbol[lRunnerNationality] = L"RunnerNationality";
|
||||||
@ -2080,6 +2268,10 @@ void MetaList::initSymbols() {
|
|||||||
|
|
||||||
typeToSymbol[lTeamName] = L"TeamName";
|
typeToSymbol[lTeamName] = L"TeamName";
|
||||||
typeToSymbol[lTeamStart] = L"TeamStart";
|
typeToSymbol[lTeamStart] = L"TeamStart";
|
||||||
|
typeToSymbol[lTeamCourseName] = L"TeamCourseName";
|
||||||
|
typeToSymbol[lTeamCourseNumber] = L"TeamCourseNumber";
|
||||||
|
typeToSymbol[lTeamLegName] = L"TeamLegName";
|
||||||
|
|
||||||
typeToSymbol[lTeamStartCond] = L"TeamStartCond";
|
typeToSymbol[lTeamStartCond] = L"TeamStartCond";
|
||||||
typeToSymbol[lTeamStartZero] = L"TeamStartZero";
|
typeToSymbol[lTeamStartZero] = L"TeamStartZero";
|
||||||
|
|
||||||
@ -2160,7 +2352,13 @@ void MetaList::initSymbols() {
|
|||||||
typeToSymbol[lControlRunnersLeft] = L"ControlRunnersLeft";
|
typeToSymbol[lControlRunnersLeft] = L"ControlRunnersLeft";
|
||||||
typeToSymbol[lControlCodes] = L"ControlCodes";
|
typeToSymbol[lControlCodes] = L"ControlCodes";
|
||||||
|
|
||||||
|
typeToSymbol[lNumEntries] = L"NumEntries";
|
||||||
|
typeToSymbol[lNumStarts] = L"NumStarts";
|
||||||
|
typeToSymbol[lTotalRunLength] = L"TotalRunLength";
|
||||||
|
typeToSymbol[lTotalRunTime] = L"TotalRunTime";
|
||||||
|
|
||||||
typeToSymbol[lLineBreak] = L"LineBreak";
|
typeToSymbol[lLineBreak] = L"LineBreak";
|
||||||
|
typeToSymbol[lImage] = L"Image";
|
||||||
|
|
||||||
for (map<EPostType, wstring>::iterator it = typeToSymbol.begin();
|
for (map<EPostType, wstring>::iterator it = typeToSymbol.begin();
|
||||||
it != typeToSymbol.end(); ++it) {
|
it != typeToSymbol.end(); ++it) {
|
||||||
@ -2175,7 +2373,8 @@ void MetaList::initSymbols() {
|
|||||||
|
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeRunner] = "Runner";
|
baseTypeToSymbol[oListInfo::EBaseTypeRunner] = "Runner";
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeTeam] = "Team";
|
baseTypeToSymbol[oListInfo::EBaseTypeTeam] = "Team";
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeClub] = "ClubRunner";
|
baseTypeToSymbol[oListInfo::EBaseTypeClubRunner] = "ClubRunner";
|
||||||
|
baseTypeToSymbol[oListInfo::EBaseTypeClubTeam] = "ClubTeam";
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeCoursePunches] = "CoursePunches";
|
baseTypeToSymbol[oListInfo::EBaseTypeCoursePunches] = "CoursePunches";
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeAllPunches] = "AllPunches";
|
baseTypeToSymbol[oListInfo::EBaseTypeAllPunches] = "AllPunches";
|
||||||
baseTypeToSymbol[oListInfo::EBaseTypeNone] = "None";
|
baseTypeToSymbol[oListInfo::EBaseTypeNone] = "None";
|
||||||
@ -2199,6 +2398,7 @@ void MetaList::initSymbols() {
|
|||||||
|
|
||||||
orderToSymbol[ClassStartTime] = "ClassStartTime";
|
orderToSymbol[ClassStartTime] = "ClassStartTime";
|
||||||
orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub";
|
orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub";
|
||||||
|
orderToSymbol[ClubClassStartTime] = "ClubClassStartTime";
|
||||||
orderToSymbol[ClassResult] = "ClassResult";
|
orderToSymbol[ClassResult] = "ClassResult";
|
||||||
orderToSymbol[ClassDefaultResult] = "ClassDefaultResult";
|
orderToSymbol[ClassDefaultResult] = "ClassDefaultResult";
|
||||||
orderToSymbol[ClassCourseResult] = "ClassCourseResult";
|
orderToSymbol[ClassCourseResult] = "ClassCourseResult";
|
||||||
@ -2323,6 +2523,15 @@ MetaList &MetaListContainer::getList(int index) {
|
|||||||
return data[index].second;
|
return data[index].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MetaList& MetaListContainer::getList(EStdListType type) const {
|
||||||
|
auto res = globalIndex.find(type);
|
||||||
|
if (res != globalIndex.end())
|
||||||
|
return getList(res->second);
|
||||||
|
|
||||||
|
throw meosException("List Error: X#Unknown type " + itos(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MetaList &MetaListContainer::addExternal(const MetaList &ml) {
|
MetaList &MetaListContainer::addExternal(const MetaList &ml) {
|
||||||
data.push_back(make_pair(ExternalList, ml));
|
data.push_back(make_pair(ExternalList, ml));
|
||||||
if (owner)
|
if (owner)
|
||||||
@ -2343,7 +2552,7 @@ void MetaListContainer::save(MetaListType type, xmlparser &xml, const oEvent *oe
|
|||||||
|
|
||||||
for (size_t k = 0; k<data.size(); k++) {
|
for (size_t k = 0; k<data.size(); k++) {
|
||||||
if (data[k].first == type)
|
if (data[k].first == type)
|
||||||
data[k].second.save(xml, oe);
|
data[k].second.save(xml, false, oe);
|
||||||
}
|
}
|
||||||
if (type == ExternalList) {
|
if (type == ExternalList) {
|
||||||
setupIndex(EFirstLoadedList);
|
setupIndex(EFirstLoadedList);
|
||||||
@ -2385,7 +2594,7 @@ bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool igno
|
|||||||
xmlattrib ver = xList[k].getAttrib("version");
|
xmlattrib ver = xList[k].getAttrib("version");
|
||||||
bool newVersion = false;
|
bool newVersion = false;
|
||||||
if (ver) {
|
if (ver) {
|
||||||
wstring vers = ver.wget();
|
wstring vers = ver.getWStr();
|
||||||
if (vers > majVer) {
|
if (vers > majVer) {
|
||||||
newVersion = true;
|
newVersion = true;
|
||||||
}
|
}
|
||||||
@ -2451,6 +2660,7 @@ bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool igno
|
|||||||
it->second.nextList = 0; // Clear relation
|
it->second.nextList = 0; // Clear relation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pushLevel) {
|
if (!pushLevel) {
|
||||||
xDef.getObjects("MeOSResultCalculationSet", xList);
|
xDef.getObjects("MeOSResultCalculationSet", xList);
|
||||||
decltype(freeResultModules) copy;
|
decltype(freeResultModules) copy;
|
||||||
@ -2467,7 +2677,7 @@ bool MetaListContainer::load(MetaListType type, const xmlobject &xDef, bool igno
|
|||||||
|
|
||||||
freeResultModules.emplace(dr->getTag(), GeneralResultCtr(dr->getTag().c_str(), dr->getName(false), dr));
|
freeResultModules.emplace(dr->getTag(), GeneralResultCtr(dr->getTag().c_str(), dr->getName(false), dr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner)
|
if (owner)
|
||||||
owner->updateChanged();
|
owner->updateChanged();
|
||||||
}
|
}
|
||||||
@ -2661,7 +2871,7 @@ EStdListType MetaListContainer::getType(const int index) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MetaListContainer::getLists(vector<pair<wstring, size_t> > &lists, bool markBuiltIn,
|
void MetaListContainer::getLists(vector<pair<wstring, size_t> > &lists, bool markBuiltIn,
|
||||||
bool resultListOnly, bool noTeamList) const {
|
bool resultListOnly, bool noTeamList, bool onlyForSplitPrint) const {
|
||||||
lists.clear();
|
lists.clear();
|
||||||
size_t currentIx = 0;
|
size_t currentIx = 0;
|
||||||
for (bool i : {false, true}) {
|
for (bool i : {false, true}) {
|
||||||
@ -2677,6 +2887,9 @@ void MetaListContainer::getLists(vector<pair<wstring, size_t> > &lists, bool mar
|
|||||||
if ((data[k].first == InternalList) == (i != markBuiltIn))
|
if ((data[k].first == InternalList) == (i != markBuiltIn))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (onlyForSplitPrint && !data[k].second.isSplitPrintList())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (data[k].first == InternalList) {
|
if (data[k].first == InternalList) {
|
||||||
if (markBuiltIn)
|
if (markBuiltIn)
|
||||||
lists.push_back(make_pair(L"[" + lang.tl(data[k].second.getListName()) + L"]", k));
|
lists.push_back(make_pair(L"[" + lang.tl(data[k].second.getListName()) + L"]", k));
|
||||||
@ -2790,11 +3003,15 @@ void MetaListContainer::saveList(int index, const MetaList &ml) {
|
|||||||
if (data[index].first == InternalList)
|
if (data[index].first == InternalList)
|
||||||
throw meosException("Invalid list type");
|
throw meosException("Invalid list type");
|
||||||
|
|
||||||
|
string oldId = data[index].second.getUniqueId();
|
||||||
|
|
||||||
data[index].first = ExternalList;
|
data[index].first = ExternalList;
|
||||||
data[index].second = ml;
|
data[index].second = ml;
|
||||||
data[index].second.initUniqueIndex();
|
data[index].second.initUniqueIndex();
|
||||||
if (owner)
|
if (owner) {
|
||||||
|
owner->updateListReferences(oldId, data[index].second.getUniqueId());
|
||||||
owner->updateChanged();
|
owner->updateChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaList::getFilters(vector< pair<wstring, bool> > &filters) const {
|
void MetaList::getFilters(vector< pair<wstring, bool> > &filters) const {
|
||||||
@ -2894,6 +3111,7 @@ void MetaList::getSortOrder(bool forceIncludeCustom, vector< pair<wstring, size_
|
|||||||
if (it->first != Custom || forceIncludeCustom || !resultModule.empty() || currentOrder == Custom)
|
if (it->first != Custom || forceIncludeCustom || !resultModule.empty() || currentOrder == Custom)
|
||||||
orders.push_back(make_pair(lang.tl(it->second), it->first));
|
orders.push_back(make_pair(lang.tl(it->second), it->first));
|
||||||
}
|
}
|
||||||
|
sort(orders.begin(), orders.end());
|
||||||
currentOrder = sortOrder;
|
currentOrder = sortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2906,7 +3124,7 @@ void MetaList::getBaseType(vector< pair<wstring, size_t> > &types, int ¤tT
|
|||||||
continue;
|
continue;
|
||||||
types.push_back(make_pair(lang.tl(it->second), it->first));
|
types.push_back(make_pair(lang.tl(it->second), it->first));
|
||||||
}
|
}
|
||||||
|
sort(types.begin(), types.end());
|
||||||
currentType = listType;
|
currentType = listType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2937,6 +3155,7 @@ void MetaList::getSubType(vector< pair<wstring, size_t> > &types, int ¤tTy
|
|||||||
types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t));
|
types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort(types.begin()+1, types.end());
|
||||||
currentType = listSubType;
|
currentType = listSubType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3098,7 +3317,8 @@ EPostType MetaList::getTypeFromSymbol(wstring &symb) noexcept {
|
|||||||
|
|
||||||
void MetaList::fillSymbols(vector < pair<wstring, size_t>> &symb) {
|
void MetaList::fillSymbols(vector < pair<wstring, size_t>> &symb) {
|
||||||
for (auto s : symbolToType) {
|
for (auto s : symbolToType) {
|
||||||
if (s.second == lAlignNext || s.second == lNone || s.second == lLineBreak)
|
if (s.second == lAlignNext || s.second == lNone
|
||||||
|
|| s.second == lLineBreak || s.second == lImage)
|
||||||
continue;
|
continue;
|
||||||
wstring desc = L"[" + s.first + L"]\t" + lang.tl(s.first);
|
wstring desc = L"[" + s.first + L"]\t" + lang.tl(s.first);
|
||||||
symb.emplace_back(desc, size_t(s.second));
|
symb.emplace_back(desc, size_t(s.second));
|
||||||
@ -3224,19 +3444,44 @@ void MetaListContainer::updateGeneralResult(string tag, const shared_ptr<Dynamic
|
|||||||
owner->updateChanged();
|
owner->updateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaList::getAutoComplete(const wstring &w, vector<AutoCompleteRecord> &records) {
|
void MetaList::getAutoComplete(const wstring& w, vector<AutoCompleteRecord>& records) {
|
||||||
records.clear();
|
records.clear();
|
||||||
wchar_t s_lc[1024];
|
vector<wstring> ws, ws2;
|
||||||
wcscpy_s(s_lc, w.c_str());
|
split(w, L" ", ws);
|
||||||
CharLowerBuff(s_lc, w.length());
|
|
||||||
|
vector<vector<wchar_t>> s_lc(ws.size());
|
||||||
|
|
||||||
|
for (int j = 0; j < ws.size(); j++) {
|
||||||
|
s_lc[j].resize(ws[j].size() + 1);
|
||||||
|
ws[j] = trim(ws[j]);
|
||||||
|
wcscpy_s(s_lc[j].data(), s_lc[j].size(), ws[j].c_str());
|
||||||
|
CharLowerBuff(s_lc[j].data(), ws[j].length());
|
||||||
|
}
|
||||||
|
|
||||||
wstring tl;
|
wstring tl;
|
||||||
for (auto &ts : typeToSymbol) {
|
for (auto& ts : typeToSymbol) {
|
||||||
if (ts.first == lNone || ts.first == lAlignNext)
|
if (ts.first == lNone || ts.first == lAlignNext || ts.first == lImage)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tl = lang.tl(ts.second);
|
tl = lang.tl(ts.second);
|
||||||
if (filterMatchString(ts.second, s_lc) || filterMatchString(tl, s_lc)) {
|
int score = 0;
|
||||||
records.emplace_back(tl, ts.second, ts.first);
|
int fScore;
|
||||||
|
for (int j = 0; j < ws.size(); j++) {
|
||||||
|
if (filterMatchString(ts.second, s_lc[j].data(), fScore))
|
||||||
|
score += 1 + fScore * (ws.size() == 1) ? 2 : 0;
|
||||||
|
|
||||||
|
if (filterMatchString(tl, s_lc[j].data(), fScore)) {
|
||||||
|
score++;
|
||||||
|
split(tl, L" ", ws2);
|
||||||
|
for (int i = 0; i < ws2.size(); i++) {
|
||||||
|
if (filterMatchString(ws2[i], s_lc[j].data(), fScore)) {
|
||||||
|
int diff = std::abs(int(ws2[i].length() - ws[j].length()));
|
||||||
|
score += max(5 - diff, 0) + fScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (score > 0)
|
||||||
|
records.emplace_back(tl, score, ts.second, ts.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -94,6 +94,15 @@ private:
|
|||||||
gdiFonts font;
|
gdiFonts font;
|
||||||
int textAdjust; // 0, textRight, textCenter
|
int textAdjust; // 0, textRight, textCenter
|
||||||
GDICOLOR color;
|
GDICOLOR color;
|
||||||
|
|
||||||
|
// Image
|
||||||
|
int imageWidth = 0;
|
||||||
|
int imageHeight = 0;
|
||||||
|
int imageStyle = 0;
|
||||||
|
int imageOffsetX = 0;
|
||||||
|
int imageOffsetY = 0;
|
||||||
|
bool imageStyleUnderText = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MetaListPost(EPostType type_, EPostType align_ = lNone, int leg_ = -1);
|
MetaListPost(EPostType type_, EPostType align_ = lNone, int leg_ = -1);
|
||||||
@ -109,11 +118,47 @@ public:
|
|||||||
MetaListPost &limitBlockWidth(bool lim = true) { limitWidth = lim; return *this; }
|
MetaListPost &limitBlockWidth(bool lim = true) { limitWidth = lim; return *this; }
|
||||||
MetaListPost &packWithPrevious(bool pack = true) { packPrevious = pack; return *this; }
|
MetaListPost &packWithPrevious(bool pack = true) { packPrevious = pack; return *this; }
|
||||||
|
|
||||||
|
|
||||||
MetaListPost &indent(int ind) {minimalIndent = ind; return *this;}
|
MetaListPost &indent(int ind) {minimalIndent = ind; return *this;}
|
||||||
|
|
||||||
void getTypes(vector< pair<wstring, size_t> > &types, int ¤tType) const;
|
void getTypes(vector< pair<wstring, size_t> > &types, int ¤tType) const;
|
||||||
|
|
||||||
|
uint64_t getImageId() const;
|
||||||
|
void setImageDimension(int x, int y) {
|
||||||
|
imageWidth = x;
|
||||||
|
imageHeight = y;
|
||||||
|
}
|
||||||
|
int getImageWidth() const {
|
||||||
|
return imageWidth;
|
||||||
|
}
|
||||||
|
int getImageHeight() const {
|
||||||
|
return imageHeight;
|
||||||
|
}
|
||||||
|
void setImageOffset(int x, int y) {
|
||||||
|
imageOffsetX = x;
|
||||||
|
imageOffsetY = y;
|
||||||
|
}
|
||||||
|
int getImageOffsetX() const {
|
||||||
|
return imageOffsetX;
|
||||||
|
}
|
||||||
|
int getImageOffsetY() const {
|
||||||
|
return imageOffsetY;
|
||||||
|
}
|
||||||
|
int getImageStyle() const {
|
||||||
|
return imageStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImageStyle(int style) {
|
||||||
|
imageStyle = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool imageUnderText() const {
|
||||||
|
return imageStyleUnderText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void imageUnderText(bool ut) {
|
||||||
|
imageStyleUnderText = ut;
|
||||||
|
}
|
||||||
|
|
||||||
const wstring &getType() const;
|
const wstring &getType() const;
|
||||||
MetaListPost &setType(EPostType type_) {type = type_; return *this;}
|
MetaListPost &setType(EPostType type_) {type = type_; return *this;}
|
||||||
EPostType getTypeRaw() const { return type; }
|
EPostType getTypeRaw() const { return type; }
|
||||||
@ -236,8 +281,20 @@ private:
|
|||||||
|
|
||||||
static bool isBreak(int x);
|
static bool isBreak(int x);
|
||||||
|
|
||||||
|
shared_ptr<SplitPrintListInfo> splitPrintInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool isSplitPrintList() const { return splitPrintInfo != nullptr; }
|
||||||
|
|
||||||
|
const shared_ptr<SplitPrintListInfo>& getSplitPrintInfo() const {
|
||||||
|
return splitPrintInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSplitPrintInfo(const shared_ptr<SplitPrintListInfo>& info) {
|
||||||
|
splitPrintInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
static wstring encode(EPostType type, const wstring &input, bool &foundSymbol);
|
static wstring encode(EPostType type, const wstring &input, bool &foundSymbol);
|
||||||
static const wstring &fromResultModuleNumber(const wstring &in, int nr, wstring &out);
|
static const wstring &fromResultModuleNumber(const wstring &in, int nr, wstring &out);
|
||||||
|
|
||||||
@ -246,12 +303,21 @@ public:
|
|||||||
MetaList();
|
MetaList();
|
||||||
virtual ~MetaList() {}
|
virtual ~MetaList() {}
|
||||||
|
|
||||||
|
void getUsedImages(set<uint64_t>& imgId) const;
|
||||||
|
|
||||||
static constexpr bool isAllStageType(EPostType type) {
|
static constexpr bool isAllStageType(EPostType type) {
|
||||||
return type == lRunnerStagePlace || type == lRunnerStageStatus ||
|
return type == lRunnerStagePlace || type == lRunnerStageStatus ||
|
||||||
type == lRunnerStageTime || type == lRunnerStageTimeStatus ||
|
type == lRunnerStageTime || type == lRunnerStageTimeStatus ||
|
||||||
type == lRunnerStagePoints || type == lRunnerStageNumber;
|
type == lRunnerStagePoints || type == lRunnerStageNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr bool isAllLegType(EPostType type) {
|
||||||
|
return type == lTeamCourseName || type == lTeamCourseNumber ||
|
||||||
|
type == lTeamLegName || type == lTeamRunner || type == lTeamRunnerCard ||
|
||||||
|
type == lTeamLegTimeStatus || type == lTeamLegTimeAfter ||
|
||||||
|
type == lTeamPlace || type ==lTeamStart;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr bool isResultModuleOutput(EPostType type) {
|
static constexpr bool isResultModuleOutput(EPostType type) {
|
||||||
return type == lResultModuleNumber || type == lResultModuleTime ||
|
return type == lResultModuleNumber || type == lResultModuleTime ||
|
||||||
type == lResultModuleTimeTeam || type == lResultModuleNumberTeam;
|
type == lResultModuleTimeTeam || type == lResultModuleNumberTeam;
|
||||||
@ -329,7 +395,7 @@ public:
|
|||||||
|
|
||||||
bool isValidIx(size_t gIx, size_t lIx, size_t ix) const;
|
bool isValidIx(size_t gIx, size_t lIx, size_t ix) const;
|
||||||
|
|
||||||
void save(xmlparser &xml, const oEvent *oe) const;
|
void save(xmlparser &xml, bool includeImages, const oEvent *oe) const;
|
||||||
void load(const xmlobject &xDef);
|
void load(const xmlobject &xDef);
|
||||||
|
|
||||||
void interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par, oListInfo &li) const;
|
void interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par, oListInfo &li) const;
|
||||||
@ -371,6 +437,8 @@ public:
|
|||||||
friend class MetaListPost;
|
friend class MetaListPost;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Image;
|
||||||
|
|
||||||
class MetaListContainer {
|
class MetaListContainer {
|
||||||
public:
|
public:
|
||||||
enum MetaListType {InternalList, ExternalList, RemovedList};
|
enum MetaListType {InternalList, ExternalList, RemovedList};
|
||||||
@ -391,7 +459,6 @@ public:
|
|||||||
|
|
||||||
virtual ~MetaListContainer();
|
virtual ~MetaListContainer();
|
||||||
|
|
||||||
|
|
||||||
void getFreeResultModules(vector<pair<string, shared_ptr<DynamicResult>>> &res) const;
|
void getFreeResultModules(vector<pair<string, shared_ptr<DynamicResult>>> &res) const;
|
||||||
|
|
||||||
string getUniqueId(EStdListType code) const;
|
string getUniqueId(EStdListType code) const;
|
||||||
@ -400,6 +467,8 @@ public:
|
|||||||
|
|
||||||
bool updateResultModule(const DynamicResult &res, bool updateSimilar);
|
bool updateResultModule(const DynamicResult &res, bool updateSimilar);
|
||||||
|
|
||||||
|
void getUsedImages(set<uint64_t>& imgId) const;
|
||||||
|
|
||||||
int getNumParam() const {return listParam.size();}
|
int getNumParam() const {return listParam.size();}
|
||||||
int getNumLists() const {return data.size();}
|
int getNumLists() const {return data.size();}
|
||||||
int getNumLists(MetaListType) const;
|
int getNumLists(MetaListType) const;
|
||||||
@ -409,6 +478,7 @@ public:
|
|||||||
|
|
||||||
const MetaList &getList(int index) const;
|
const MetaList &getList(int index) const;
|
||||||
MetaList &getList(int index);
|
MetaList &getList(int index);
|
||||||
|
const MetaList& getList(EStdListType type) const;
|
||||||
|
|
||||||
const oListParam &getParam(int index) const;
|
const oListParam &getParam(int index) const;
|
||||||
oListParam &getParam(int index);
|
oListParam &getParam(int index);
|
||||||
@ -421,7 +491,8 @@ public:
|
|||||||
void getLists(vector< pair<wstring, size_t> > &lists,
|
void getLists(vector< pair<wstring, size_t> > &lists,
|
||||||
bool markBuiltIn,
|
bool markBuiltIn,
|
||||||
bool resultListOnly,
|
bool resultListOnly,
|
||||||
bool noTeamList) const;
|
bool noTeamList,
|
||||||
|
bool onlyForSplitPrint) const;
|
||||||
|
|
||||||
const string &getTag(int index) const;
|
const string &getTag(int index) const;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -563,14 +563,14 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
w[i] = gdi.scaleLength(w[i]);
|
w[i] = gdi.scaleLength(w[i]);
|
||||||
|
|
||||||
set<wstring> errors;
|
set<wstring> errors;
|
||||||
currentResult->prepareCalculations(*oe, false, {}, rr, tr, inputNumber);
|
currentResult->prepareCalculations(*oe, true, {}, rr, tr, inputNumber);
|
||||||
|
|
||||||
for (size_t k = 0; k < rr.size(); k++) {
|
for (size_t k = 0; k < rr.size(); k++) {
|
||||||
int txp = xp;
|
int txp = xp;
|
||||||
int wi = 0;
|
int wi = 0;
|
||||||
gdi.addStringUT(yp, txp, 0, rr[k]->getCompleteIdentification(), w[wi]-diff);
|
gdi.addStringUT(yp, txp, 0, rr[k]->getCompleteIdentification(), w[wi]-diff);
|
||||||
txp += w[wi++];
|
txp += w[wi++];
|
||||||
currentResult->prepareCalculations(*rr[k], false);
|
currentResult->prepareCalculations(*rr[k], true);
|
||||||
int rt = 0, pt = 0;
|
int rt = 0, pt = 0;
|
||||||
RunnerStatus st = StatusUnknown;
|
RunnerStatus st = StatusUnknown;
|
||||||
|
|
||||||
@ -674,7 +674,7 @@ int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) {
|
|||||||
int wi = 0;
|
int wi = 0;
|
||||||
gdi.addStringUT(yp, txp, 0, tr[k]->getName(), w[wi]-diff);
|
gdi.addStringUT(yp, txp, 0, tr[k]->getName(), w[wi]-diff);
|
||||||
txp += w[wi++];
|
txp += w[wi++];
|
||||||
currentResult->prepareCalculations(*tr[k], false);
|
currentResult->prepareCalculations(*tr[k], true);
|
||||||
int rt = 0, pt = 0;
|
int rt = 0, pt = 0;
|
||||||
RunnerStatus st = StatusUnknown;
|
RunnerStatus st = StatusUnknown;
|
||||||
{
|
{
|
||||||
@ -920,10 +920,10 @@ void MethodEditor::makeDirty(gdioutput &gdi, DirtyFlag inside) {
|
|||||||
bool MethodEditor::checkSave(gdioutput &gdi) {
|
bool MethodEditor::checkSave(gdioutput &gdi) {
|
||||||
if (dirtyInt) {
|
if (dirtyInt) {
|
||||||
gdioutput::AskAnswer answer = gdi.askCancel(L"Vill du spara ändringar?");
|
gdioutput::AskAnswer answer = gdi.askCancel(L"Vill du spara ändringar?");
|
||||||
if (answer == gdioutput::AnswerCancel)
|
if (answer == gdioutput::AskAnswer::AnswerCancel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (answer == gdioutput::AnswerYes) {
|
if (answer == gdioutput::AskAnswer::AnswerYes) {
|
||||||
gdi.sendCtrlMessage("SaveInside");
|
gdi.sendCtrlMessage("SaveInside");
|
||||||
}
|
}
|
||||||
makeDirty(gdi, ClearDirty);
|
makeDirty(gdi, ClearDirty);
|
||||||
@ -1004,11 +1004,11 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
|
|||||||
if (isTeam)
|
if (isTeam)
|
||||||
oe->getTeams(art->getClassId(true), tt, false);
|
oe->getTeams(art->getClassId(true), tt, false);
|
||||||
|
|
||||||
currentResult->prepareCalculations(*oe, false, {art->getClassId(true)}, rr, tt, inputNumber);
|
currentResult->prepareCalculations(*oe, true, {art->getClassId(true)}, rr, tt, inputNumber);
|
||||||
gdi_new->addString("", fontMediumPlus, "Debug Output");
|
gdi_new->addString("", fontMediumPlus, "Debug Output");
|
||||||
if (!isTeam) {
|
if (!isTeam) {
|
||||||
oRunner &r = *pRunner(art);
|
oRunner &r = *pRunner(art);
|
||||||
currentResult->prepareCalculations(r, false);
|
currentResult->prepareCalculations(r, true);
|
||||||
int rt = 0, pt = 0;
|
int rt = 0, pt = 0;
|
||||||
RunnerStatus st = StatusUnknown;
|
RunnerStatus st = StatusUnknown;
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
@ -1065,7 +1065,7 @@ void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
oTeam &t = *pTeam(art);
|
oTeam &t = *pTeam(art);
|
||||||
currentResult->prepareCalculations(t, false);
|
currentResult->prepareCalculations(t, true);
|
||||||
int rt = 0, pt = 0;
|
int rt = 0, pt = 0;
|
||||||
RunnerStatus st = StatusUnknown;
|
RunnerStatus st = StatusUnknown;
|
||||||
gdi.dropLine();
|
gdi.dropLine();
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/************************************************************************
|
/************************************************************************
|
||||||
MeOS - Orienteering Software
|
MeOS - Orienteering Software
|
||||||
Copyright (C) 2009-2022 Melin Software HB
|
Copyright (C) 2009-2023 Melin Software HB
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include "MeosSQL.h"
|
#include "MeosSQL.h"
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
|
||||||
MySQLReconnect::MySQLReconnect(const wstring &errorIn) : AutoMachine("MySQL-daemon", Machines::mMySQLReconnect), error(errorIn) {
|
MySQLReconnect::MySQLReconnect(const wstring &errorIn) : AutoMachine("MySQL-service", Machines::mMySQLReconnect), error(errorIn) {
|
||||||
timeError = getLocalTime();
|
timeError = getLocalTime();
|
||||||
hThread=0;
|
hThread=0;
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ bool MySQLReconnect::stop() {
|
|||||||
if (interval==0)
|
if (interval==0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return MessageBox(0, L"If this daemon is stopped, then MeOS will not reconnect to the network. Continue?",
|
return MessageBox(0, L"If this service is stopped, MeOS will not reconnect to the network. Continue?",
|
||||||
L"Warning", MB_YESNO|MB_ICONWARNING)==IDYES;
|
L"Warning", MB_YESNO|MB_ICONWARNING)==IDYES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user