MeOS version 3.8.1277 RC1
This commit is contained in:
parent
67e7e24bd5
commit
62a69d2e1f
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -35,6 +35,7 @@
|
||||
#include "RunnerDB.h"
|
||||
#include "progress.h"
|
||||
#include "metalist.h"
|
||||
#include "machinecontainer.h"
|
||||
#include "MeOSFeatures.h"
|
||||
#include "meosexception.h"
|
||||
#include "generalresult.h"
|
||||
@ -419,6 +420,11 @@ void MeosSQL::upgradeDB(const string &db, oDataContainer const * dc) {
|
||||
sql = sql.substr(0, sql.length() - 2);
|
||||
query.execute(sql);
|
||||
}
|
||||
if (!eCol.count("Machine")) {
|
||||
string sql = "ALTER TABLE oEvent ADD COLUMN " + C_MTEXT("Machine");
|
||||
sql = sql.substr(0, sql.length() - 2);
|
||||
query.execute(sql);
|
||||
}
|
||||
}
|
||||
else if (db == "oCourse") {
|
||||
if (!eCol.count("Legs")) {
|
||||
@ -556,7 +562,8 @@ bool MeosSQL::openDB(oEvent *oe)
|
||||
<< C_STRING("NameId", 64)
|
||||
<< C_UINT("BuildVersion")
|
||||
<< oe->getDI().generateSQLDefinition()
|
||||
<< C_MTEXT("Lists") << C_END();
|
||||
<< C_MTEXT("Lists")
|
||||
<< C_MTEXT("Machine") << C_END();
|
||||
query.execute();
|
||||
|
||||
// Upgrade oEvent
|
||||
@ -818,7 +825,8 @@ OpFailStatus MeosSQL::SyncUpdate(oEvent *oe)
|
||||
<< " NameId=" << quote << toString(oe->currentNameId) << ", "
|
||||
<< " ZeroTime=" << unsigned(oe->ZeroTime) << ", "
|
||||
<< " BuildVersion=" << buildVersion << ", "
|
||||
<< " Lists=" << quote << listEnc
|
||||
<< " Lists=" << quote << listEnc << ", "
|
||||
<< " Machine=" <<quote << oe->getMachineContainer().save()
|
||||
<< oe->getDI().generateSQLSet(true);
|
||||
|
||||
if (syncUpdate(queryset, "oEvent", oe) == opStatusFail)
|
||||
@ -1185,6 +1193,9 @@ OpFailStatus MeosSQL::SyncRead(oEvent *oe) {
|
||||
retValue = opStatusWarning;
|
||||
}
|
||||
|
||||
const string &mRaw = row.raw_string(res.field_num("Machine"));
|
||||
oe->getMachineContainer().load(mRaw);
|
||||
|
||||
oDataInterface odi=oe->getDI();
|
||||
storeData(odi, row, oe->dataRevision);
|
||||
oe->changed = false;
|
||||
@ -2589,7 +2600,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClub *c)
|
||||
}
|
||||
try {
|
||||
auto query = con->query();
|
||||
query << "SELECT * FROM oClub WHERE Id=" << c->Id;
|
||||
query << "SELECT * FROM oClub WHERE Id=" << c->Id << andWhereOld(c);
|
||||
auto res = query.store();
|
||||
|
||||
RowWrapper row;
|
||||
@ -2611,8 +2622,7 @@ OpFailStatus MeosSQL::syncRead(bool forceRead, oClub *c)
|
||||
return syncUpdate(c, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//Something is wrong!? Deleted?
|
||||
else if (c->changed) {
|
||||
return syncUpdate(c, true);
|
||||
}
|
||||
return opStatusOK;
|
||||
@ -3097,6 +3107,9 @@ OpFailStatus MeosSQL::SyncEvent(oEvent *oe) {
|
||||
catch (std::exception &ex) {
|
||||
alert(ex.what());
|
||||
}
|
||||
const string &mRaw = row.raw_string(res.field_num("Machine"));
|
||||
oe->getMachineContainer().load(mRaw);
|
||||
|
||||
oe->counter = counter;
|
||||
oDataInterface odi=oe->getDI();
|
||||
storeData(odi, row, oe->dataRevision);
|
||||
@ -3124,7 +3137,8 @@ OpFailStatus MeosSQL::SyncEvent(oEvent *oe) {
|
||||
<< " ZeroTime=" << unsigned(oe->ZeroTime) << ", "
|
||||
<< " BuildVersion=if (BuildVersion<" <<
|
||||
buildVersion << "," << buildVersion << ",BuildVersion), "
|
||||
<< " Lists=" << quote << listEnc
|
||||
<< " Lists=" << quote << listEnc << ", "
|
||||
<< " Machine=" << quote << oe->getMachineContainer().save()
|
||||
<< oe->getDI().generateSQLSet(false);
|
||||
|
||||
syncUpdate(queryset, "oEvent", oe);
|
||||
@ -3156,7 +3170,8 @@ OpFailStatus MeosSQL::SyncEvent(oEvent *oe) {
|
||||
<< " ZeroTime=" << unsigned(oe->ZeroTime) << ","
|
||||
<< " BuildVersion=if (BuildVersion<" <<
|
||||
buildVersion << "," << buildVersion << ",BuildVersion),"
|
||||
<< " Lists=" << quote << listEnc
|
||||
<< " Lists=" << quote << listEnc << ", "
|
||||
<< " Machine=" << quote << oe->getMachineContainer().save()
|
||||
<< oe->getDI().generateSQLSet(false);
|
||||
|
||||
syncUpdate(queryset, "oEvent", oe);
|
||||
@ -3223,7 +3238,7 @@ bool MeosSQL::syncListRunner(oEvent *oe)
|
||||
st = OpFailStatus::opStatusOK;
|
||||
oRunner *r=oe->getRunner(Id, 0);
|
||||
|
||||
if (r) {
|
||||
if (r && !r->Removed) {
|
||||
r->Removed=true;
|
||||
if (r->tInTeam)
|
||||
r->tInTeam->correctRemove(r);
|
||||
@ -3233,6 +3248,8 @@ bool MeosSQL::syncListRunner(oEvent *oe)
|
||||
}
|
||||
|
||||
r->changedObject();
|
||||
r->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else{
|
||||
@ -3290,9 +3307,11 @@ bool MeosSQL::syncListClass(oEvent *oe) {
|
||||
if (int(row["Removed"])) {
|
||||
st = OpFailStatus::opStatusOK;
|
||||
oClass *c = oe->getClass(Id);
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->changedObject();
|
||||
c->Removed = true;
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3355,9 +3374,11 @@ bool MeosSQL::syncListClub(oEvent *oe)
|
||||
st = opStatusOK;
|
||||
oClub *c = oe->getClub(Id);
|
||||
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->Removed = true;
|
||||
c->changedObject();
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3413,9 +3434,11 @@ bool MeosSQL::syncListCourse(oEvent *oe) {
|
||||
st = opStatusOK;
|
||||
oCourse *c = oe->getCourse(Id);
|
||||
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->Removed = true;
|
||||
c->changedObject();
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3469,9 +3492,11 @@ bool MeosSQL::syncListCard(oEvent *oe)
|
||||
if (int(row["Removed"])) {
|
||||
st = opStatusOK;
|
||||
oCard *c = oe->getCard(Id);
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->changedObject();
|
||||
c->Removed = true;
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3529,9 +3554,11 @@ bool MeosSQL::syncListControl(oEvent *oe) {
|
||||
st = opStatusOK;
|
||||
oControl *c = oe->getControl(Id, false);
|
||||
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->Removed = true;
|
||||
c->changedObject();
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3588,13 +3615,16 @@ bool MeosSQL::syncListPunch(oEvent *oe)
|
||||
if (int(row["Removed"])) {
|
||||
st = OpFailStatus::opStatusOK;
|
||||
oFreePunch *c=oe->getPunch(Id);
|
||||
if (c) {
|
||||
if (c && !c->Removed) {
|
||||
c->Removed=true;
|
||||
int cid = c->getControlId();
|
||||
oFreePunch::rehashPunches(*oe, c->CardNo, 0);
|
||||
pRunner r = oe->getRunner(c->tRunnerId, 0);
|
||||
if (r)
|
||||
r->markClassChanged(cid);
|
||||
|
||||
c->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3653,10 +3683,12 @@ bool MeosSQL::syncListTeam(oEvent *oe) {
|
||||
if (int(row["Removed"])) {
|
||||
st = OpFailStatus::opStatusOK;
|
||||
oTeam *t = oe->getTeam(Id);
|
||||
if (t) {
|
||||
if (t && !t->Removed) {
|
||||
t->changedObject();
|
||||
t->prepareRemove();
|
||||
t->Removed = true;
|
||||
t->changed = false;
|
||||
oe->dataRevision++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -3696,15 +3728,19 @@ bool MeosSQL::syncListTeam(oEvent *oe) {
|
||||
|
||||
string MeosSQL::selectUpdated(const char *oTable, const SqlUpdated &updated) {
|
||||
string p1 = string("SELECT Id, Counter, Modified, Removed FROM ") + oTable;
|
||||
string cond1 = p1 + " WHERE Counter>" + itos(updated.counter);
|
||||
if (updated.updated.empty())
|
||||
return cond1;
|
||||
|
||||
string q = "(" + p1 + " WHERE Counter>" + itos(updated.counter) + ") UNION ALL ("+
|
||||
string q = "(" + cond1 + ") UNION ALL ("+
|
||||
p1 + " WHERE Modified>'" + updated.updated + "' AND Counter<=" + itos(updated.counter) + ")";
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
bool MeosSQL::checkConnection(oEvent *oe)
|
||||
{
|
||||
if (!con->connected())
|
||||
return false;
|
||||
errorMessage.clear();
|
||||
|
||||
if (!oe) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -40,7 +40,9 @@ RestService::~RestService() {
|
||||
}
|
||||
}
|
||||
|
||||
void RestService::save(oEvent &oe, gdioutput &gdi) {
|
||||
void RestService::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
|
||||
if (!server) {
|
||||
server = RestServer::construct();
|
||||
|
||||
@ -49,7 +51,8 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
||||
oe.setProperty("ServicePort", xport);
|
||||
|
||||
port = xport;
|
||||
server->startService(port);
|
||||
if (doProcess)
|
||||
server->startService(port);
|
||||
}
|
||||
else
|
||||
throw meosException("Invalid port number");
|
||||
@ -74,7 +77,7 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
||||
|
||||
void ListIpAddresses(vector<string>& ip);
|
||||
|
||||
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void RestService::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
if (port == -1) {
|
||||
port = oe.getPropertyInt("ServicePort", 2009);
|
||||
rootMap = oe.getPropertyString("ServiceRootMap", "");
|
||||
@ -100,7 +103,7 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.addInput("RootMap", gdi.recodeToWide(rootMap));
|
||||
gdi.setInputStatus("RootMap", !rootMap.empty());
|
||||
|
||||
startCancelInterval(gdi, "Save", created, IntervalNone, L"");
|
||||
startCancelInterval(gdi, "Save", state, IntervalNone, L"");
|
||||
|
||||
if (!server) {
|
||||
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos");
|
||||
@ -128,8 +131,7 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
}
|
||||
|
||||
void RestService::status(gdioutput &gdi) {
|
||||
gdi.pushX();
|
||||
gdi.addString("", 1, name);
|
||||
AutoMachine::status(gdi);
|
||||
|
||||
if (server) {
|
||||
gdi.addString("", 0, "Server startad på X#" + itos(port));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -34,8 +34,8 @@ class RestService :
|
||||
string rootMap;
|
||||
public:
|
||||
|
||||
void save(oEvent &oe, gdioutput &gdi) override;
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created) override;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) override;
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state) override;
|
||||
RestService *clone() const override { return new RestService(*this); }
|
||||
void status(gdioutput &gdi) override;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) override;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
647
code/TabAuto.cpp
647
code/TabAuto.cpp
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -44,6 +44,7 @@
|
||||
|
||||
#include "gdiconstants.h"
|
||||
#include "meosexception.h"
|
||||
#include "machinecontainer.h"
|
||||
#include "HTMLWriter.h"
|
||||
|
||||
static TabAuto *tabAuto = 0;
|
||||
@ -98,6 +99,18 @@ AutoMachine *TabAuto::getMachine(int id) {
|
||||
throw meosException("Service X not found.#" + itos(id));
|
||||
}
|
||||
|
||||
void AutoMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
machineName = gdi.getText("MachineName");
|
||||
}
|
||||
|
||||
void AutoMachine::status(gdioutput &gdi) {
|
||||
gdi.pushX();
|
||||
if (machineName.empty())
|
||||
gdi.addString("", 1, name);
|
||||
else
|
||||
gdi.addString("", 1, L"#" + lang.tl(name) + L" (" + machineName + L")");
|
||||
}
|
||||
|
||||
TabAuto::~TabAuto(void)
|
||||
{
|
||||
list<AutoMachine *>::iterator it;
|
||||
@ -108,27 +121,41 @@ TabAuto::~TabAuto(void)
|
||||
tabAuto=0;
|
||||
}
|
||||
|
||||
|
||||
void tabAutoKillMachines()
|
||||
void TabAuto::tabAutoKillMachines()
|
||||
{
|
||||
if (tabAuto)
|
||||
tabAuto->killMachines();
|
||||
}
|
||||
|
||||
void tabAutoRegister(TabAuto *ta)
|
||||
void TabAuto::tabAutoRegister(TabAuto *ta)
|
||||
{
|
||||
tabAuto=ta;
|
||||
}
|
||||
|
||||
void tabAutoAddMachinge(const AutoMachine &am)
|
||||
AutoMachine &TabAuto::tabAutoAddMachinge(const AutoMachine &am)
|
||||
{
|
||||
if (tabAuto) {
|
||||
tabAuto->addMachine(am);
|
||||
}
|
||||
if (tabAuto)
|
||||
return tabAuto->addMachine(am);
|
||||
throw meosException("Internal error");
|
||||
}
|
||||
|
||||
void tabForceSync(gdioutput &gdi, pEvent oe)
|
||||
bool TabAuto::hasActiveReconnectionMachine()
|
||||
{
|
||||
if (tabAuto)
|
||||
return tabAuto->hasActiveReconnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TabAuto::hasActiveReconnection() const {
|
||||
for (auto am : machines) {
|
||||
if (am->getType() == Machines::mMySQLReconnect)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void tabForceSync(gdioutput &gdi, pEvent oe) {
|
||||
if (tabAuto)
|
||||
tabAuto->syncCallback(gdi);
|
||||
}
|
||||
@ -152,31 +179,38 @@ int AutomaticCB(gdioutput *gdi, int type, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TabAuto::syncCallback(gdioutput &gdi)
|
||||
void TabAuto::syncCallback(gdioutput& gdi)
|
||||
{
|
||||
list<AutoMachine*> toRemove;
|
||||
wstring msg;
|
||||
try {
|
||||
list<AutoMachine *>::iterator it;
|
||||
for (it=machines.begin(); it!=machines.end(); ++it) {
|
||||
AutoMachine *am=*it;
|
||||
list<AutoMachine*>::iterator it;
|
||||
for (it = machines.begin(); it != machines.end(); ++it) {
|
||||
try {
|
||||
AutoMachine* am = *it;
|
||||
if (am && am->synchronize && !am->isEditMode())
|
||||
am->process(gdi, oe, SyncDataUp);
|
||||
if (am->removeMe())
|
||||
toRemove.push_back(am);
|
||||
}
|
||||
catch (meosException& ex) {
|
||||
msg = ex.wwhat();
|
||||
}
|
||||
catch (std::exception& ex) {
|
||||
msg = gdi.widen(ex.what());
|
||||
}
|
||||
catch (...) {
|
||||
msg = L"Ett okänt fel inträffade.";
|
||||
}
|
||||
}
|
||||
catch (meosException &ex) {
|
||||
msg = ex.wwhat();
|
||||
}
|
||||
catch(std::exception &ex) {
|
||||
msg = gdi.widen(ex.what());
|
||||
}
|
||||
catch(...) {
|
||||
msg = L"Ett okänt fel inträffade.";
|
||||
|
||||
for (auto* r : toRemove) {
|
||||
stopMachine(r);
|
||||
}
|
||||
|
||||
if (!msg.empty()) {
|
||||
gdi.alert(msg);
|
||||
gdi.setWaitCursor(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TabAuto::updateSyncInfo()
|
||||
@ -195,25 +229,45 @@ void TabAuto::updateSyncInfo()
|
||||
}
|
||||
}
|
||||
|
||||
void TabAuto::timerCallback(gdioutput &gdi)
|
||||
{
|
||||
void TabAuto::timerCallback(gdioutput &gdi) {
|
||||
DWORD tc=GetTickCount();
|
||||
|
||||
list<AutoMachine *>::iterator it;
|
||||
bool reload=false;
|
||||
list<AutoMachine*> toRemove;
|
||||
wstring msg;
|
||||
|
||||
for (it=machines.begin(); it!=machines.end(); ++it) {
|
||||
AutoMachine *am=*it;
|
||||
for (it = machines.begin(); it != machines.end(); ++it) {
|
||||
AutoMachine* am = *it;
|
||||
if (am && am->interval && tc >= am->timeout && !am->isEditMode()) {
|
||||
am->process(gdi, oe, SyncTimer);
|
||||
setTimer(am);
|
||||
reload=true;
|
||||
try {
|
||||
am->process(gdi, oe, SyncTimer);
|
||||
}
|
||||
catch (meosException& ex) {
|
||||
msg = ex.wwhat();
|
||||
}
|
||||
catch (std::exception& ex) {
|
||||
msg = gdi.widen(ex.what());
|
||||
}
|
||||
catch (...) {
|
||||
msg = L"Ett okänt fel inträffade.";
|
||||
}
|
||||
reload = true;
|
||||
if (am->removeMe())
|
||||
toRemove.push_back(am);
|
||||
else
|
||||
setTimer(am);
|
||||
}
|
||||
}
|
||||
for (auto* r : toRemove) {
|
||||
stopMachine(r);
|
||||
}
|
||||
|
||||
DWORD d=0;
|
||||
if (reload && !editMode && gdi.getData("AutoPage", d) && d)
|
||||
loadPage(gdi, false);
|
||||
|
||||
if (!msg.empty())
|
||||
throw meosException(msg);
|
||||
}
|
||||
|
||||
void TabAuto::setTimer(AutoMachine *am)
|
||||
@ -255,16 +309,8 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
if (!newPath.empty())
|
||||
gdi.setText(edit, newPath);
|
||||
}
|
||||
else if (bu.id == "StartBackup") {
|
||||
SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt()));
|
||||
if (sm)
|
||||
sm->saveSettings(gdi);
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="Result") {
|
||||
PrintResultMachine *sm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mPrintResultsMachine);
|
||||
settings(gdi, getMachine(bu.getExtraInt()), AutoMachine::State::Create, mPrintResultsMachine);
|
||||
}
|
||||
else if (bu.id == "BrowseFile") {
|
||||
static int index = 0;
|
||||
@ -302,168 +348,37 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
}
|
||||
else if (bu.id=="Splits") {
|
||||
SplitsMachine *sm=dynamic_cast<SplitsMachine*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mSplitsMachine);
|
||||
settings(gdi, sm, AutoMachine::State::Create, mSplitsMachine);
|
||||
}
|
||||
else if (bu.id=="Prewarning") {
|
||||
PrewarningMachine *sm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mPrewarningMachine);
|
||||
settings(gdi, sm, AutoMachine::State::Create, mPrewarningMachine);
|
||||
}
|
||||
else if (bu.id=="Punches") {
|
||||
PunchMachine *sm=dynamic_cast<PunchMachine*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mPunchMachine);
|
||||
settings(gdi, sm, AutoMachine::State::Create, mPunchMachine);
|
||||
}
|
||||
else if (bu.id=="OnlineResults") {
|
||||
OnlineResults *sm=dynamic_cast<OnlineResults*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mOnlineResults);
|
||||
settings(gdi, getMachine(bu.getExtraInt()), AutoMachine::State::Create, mOnlineResults);
|
||||
}
|
||||
else if (bu.id=="OnlineInput") {
|
||||
OnlineInput *sm=dynamic_cast<OnlineInput*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mOnlineInput);
|
||||
settings(gdi, getMachine(bu.getExtraInt()), AutoMachine::State::Create, mOnlineInput);
|
||||
}
|
||||
else if (bu.id=="SaveBackup") {
|
||||
SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt()));
|
||||
settings(gdi, sm, mSaveBackup);
|
||||
settings(gdi, getMachine(bu.getExtraInt()), AutoMachine::State::Create, mSaveBackup);
|
||||
}
|
||||
else if (bu.id == "InfoService") {
|
||||
settings(gdi, getMachine(bu.getExtraInt()), mInfoService);
|
||||
}
|
||||
else if (bu.id=="StartResult") {
|
||||
#ifndef MEOSDB
|
||||
wstring minute=gdi.getText("Interval");
|
||||
int t=convertAbsoluteTimeMS(minute);
|
||||
|
||||
if (t<2 || t>7200) {
|
||||
gdi.alert("Intervallet måste anges på formen MM:SS.");
|
||||
}
|
||||
else {
|
||||
PrintResultMachine *prm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
||||
|
||||
if (prm) {
|
||||
prm->interval = t;
|
||||
prm->doExport = gdi.isChecked("DoExport");
|
||||
prm->doPrint = gdi.isChecked("DoPrint");
|
||||
prm->exportFile = gdi.getText("ExportFile");
|
||||
prm->exportScript = gdi.getText("ExportScript");
|
||||
|
||||
if (!prm->readOnly) {
|
||||
prm->structuredExport = gdi.isChecked("StructuredExport");
|
||||
prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
|
||||
|
||||
gdi.getSelection("Classes", prm->classesToPrint);
|
||||
|
||||
ListBoxInfo lbi;
|
||||
if (gdi.getSelectedItem("ListType", lbi)) {
|
||||
oListParam par;
|
||||
par.selection=prm->classesToPrint;
|
||||
par.listCode = EStdListType(lbi.data);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.showHeader = gdi.isChecked("ShowHeader");
|
||||
par.showInterTimes = gdi.isChecked("ShowInterResults");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
int legNr = gdi.getSelectedItem("LegNumber").first;
|
||||
if (legNr >= 0)
|
||||
par.setLegNumberCoded(legNr);
|
||||
else
|
||||
par.setLegNumberCoded(0);
|
||||
|
||||
oe->generateListInfo(par, prm->listInfo);
|
||||
}
|
||||
}
|
||||
prm->po.onlyChanged = gdi.isChecked("OnlyChanged");
|
||||
prm->pageBreak = gdi.isChecked("PageBreak");
|
||||
prm->showHeader = gdi.isChecked("ShowHeader");
|
||||
|
||||
prm->showInterResult = gdi.isChecked("ShowInterResults");
|
||||
prm->splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
prm->synchronize=true; //To force continuos data sync.
|
||||
setTimer(prm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (bu.id=="StartSplits") {
|
||||
|
||||
wstring ivt = gdi.getText("Interval");
|
||||
|
||||
int iv = gdi.getTextNo("Interval");
|
||||
const wstring &file=gdi.getText("FileName");
|
||||
|
||||
if (!ivt.empty() && (iv < 1 || iv > 7200)) {
|
||||
throw meosException(L"Ogiltigt antal sekunder: X#" + gdi.getText("Interval"));
|
||||
}
|
||||
|
||||
if (file.empty()) {
|
||||
throw meosException("Filnamnet får inte vara tomt");
|
||||
}
|
||||
|
||||
//Try exporting.
|
||||
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
|
||||
set<int>(), -1, false, true, true, false);
|
||||
SplitsMachine *sm=dynamic_cast<SplitsMachine*>(getMachine(bu.getExtraInt()));
|
||||
|
||||
if (sm) {
|
||||
sm->interval=iv;
|
||||
|
||||
sm->file=file;
|
||||
sm->synchronize=true;
|
||||
setTimer(sm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
settings(gdi, getMachine(bu.getExtraInt()), AutoMachine::State::Create, mInfoService);
|
||||
}
|
||||
else if (bu.id=="Save") { // General save
|
||||
AutoMachine *sm=getMachine(bu.getExtraInt());
|
||||
if (sm) {
|
||||
sm->save(*oe, gdi);
|
||||
sm->save(*oe, gdi, true);
|
||||
setTimer(sm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="StartPrewarning") {
|
||||
PrewarningMachine *pwm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
|
||||
|
||||
if (pwm) {
|
||||
pwm->waveFolder=gdi.getText("WaveFolder");
|
||||
gdi.getSelection("Controls", pwm->controls);
|
||||
|
||||
oe->synchronizeList(oListId::oLPunchId);
|
||||
oe->clearPrewarningSounds();
|
||||
|
||||
pwm->synchronizePunches=true;
|
||||
pwm->controlsSI.clear();
|
||||
for (set<int>::iterator it=pwm->controls.begin();it!=pwm->controls.end();++it) {
|
||||
pControl pc=oe->getControl(*it, false);
|
||||
|
||||
if (pc)
|
||||
pwm->controlsSI.insert(pc->Numbers, pc->Numbers+pc->nNumbers);
|
||||
}
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="StartPunch") {
|
||||
|
||||
wstring minute=gdi.getText("Interval");
|
||||
int t=_wtoi(minute.c_str());
|
||||
|
||||
if (t<1 || t>7200) {
|
||||
throw meosException(L"Ogiltigt antal sekunder: X#" + minute);
|
||||
}
|
||||
else {
|
||||
PunchMachine *pm=dynamic_cast<PunchMachine*>(getMachine(bu.getExtraInt()));
|
||||
|
||||
if (pm) {
|
||||
pm->interval=t;
|
||||
pm->radio=gdi.getTextNo("Radio");
|
||||
setTimer(pm);
|
||||
}
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "Cancel") {
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
@ -474,6 +389,40 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "SaveMachine") {
|
||||
auto sm = getMachine(bu.getExtraInt());
|
||||
sm->save(*oe, gdi, false);
|
||||
wstring iv;
|
||||
if (gdi.hasWidget("Interval"))
|
||||
iv = gdi.getText("Interval");
|
||||
sm->saveMachine(*oe, iv);
|
||||
oe->updateChanged();
|
||||
oe->synchronize(false);
|
||||
}
|
||||
else if (bu.id == "Erase") {
|
||||
auto sm = getMachine(bu.getExtraInt());
|
||||
if (sm) {
|
||||
oe->getMachineContainer().erase(sm->getTypeString(), sm->getMachineName());
|
||||
oe->updateChanged();
|
||||
oe->synchronize();
|
||||
stopMachine(sm);
|
||||
}
|
||||
|
||||
updateSyncInfo();
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "CreateLoad") {
|
||||
auto sm = oe->getMachineContainer().enumerate();
|
||||
int ix = bu.getExtraInt();
|
||||
if (ix < sm.size()) {
|
||||
auto &m = sm[ix];
|
||||
Machines type = AutoMachine::getType(m.first);
|
||||
AutoMachine *am = AutoMachine::construct(type);
|
||||
machines.push_back(am);
|
||||
am->loadMachine(*oe, m.second);
|
||||
settings(gdi, am, AutoMachine::State::Load, am->getType());
|
||||
}
|
||||
}
|
||||
else if (bu.id == "PrinterSetup") {
|
||||
PrintResultMachine *prm =
|
||||
dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
||||
@ -548,13 +497,16 @@ bool TabAuto::stopMachine(AutoMachine *am)
|
||||
return false;
|
||||
}
|
||||
|
||||
void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) {
|
||||
void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, AutoMachine::State state, Machines ms) {
|
||||
editMode=true;
|
||||
bool createNew = (sm==0) || (ms == Machines::Unknown);
|
||||
if (sm) {
|
||||
if (state == AutoMachine::State::Create)
|
||||
state = AutoMachine::State::Edit;
|
||||
|
||||
ms = sm->getType();
|
||||
}
|
||||
else {
|
||||
state = AutoMachine::State::Create;
|
||||
sm = AutoMachine::construct(ms);
|
||||
machines.push_back(sm);
|
||||
}
|
||||
@ -566,7 +518,7 @@ void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) {
|
||||
int d = gdi.scaleLength(6);
|
||||
gdi.setCX(cx + d);
|
||||
sm->setEditMode(true);
|
||||
sm->settings(gdi, *oe, createNew);
|
||||
sm->settings(gdi, *oe, state);
|
||||
int w = gdi.getWidth();
|
||||
int h = gdi.getHeight();
|
||||
|
||||
@ -592,6 +544,7 @@ void TabAuto::killMachines()
|
||||
bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
|
||||
{
|
||||
oe->checkDB();
|
||||
oe->synchronize();
|
||||
tabAuto=this;
|
||||
editMode=false;
|
||||
gdi.selectTab(tabId);
|
||||
@ -608,34 +561,74 @@ bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
|
||||
gdi.setData("AutoPage", 1);
|
||||
gdi.addString("", boldLarge, "Automater");
|
||||
gdi.setRestorePoint();
|
||||
gdi.fillDown();
|
||||
gdi.pushX();
|
||||
|
||||
gdi.addString("", 10, "help:10000");
|
||||
|
||||
auto sm = oe->getMachineContainer().enumerate();
|
||||
|
||||
set<pair<string, wstring>> startedMachines;
|
||||
for (auto &m : machines) {
|
||||
string t;
|
||||
m->getType(t);
|
||||
startedMachines.emplace(t, m->machineName);
|
||||
}
|
||||
decltype(sm) sm2;
|
||||
for (auto &m : sm) {
|
||||
if (startedMachines.count(m) == 0)
|
||||
sm2.push_back(m);
|
||||
}
|
||||
sm2.swap(sm);
|
||||
|
||||
if (sm.size() > 0) {
|
||||
gdi.dropLine();
|
||||
gdi.addString("", fontMediumPlus, "Sparade automater").setColor(colorDarkBlue);
|
||||
gdi.dropLine(0.3);
|
||||
gdi.fillRight();
|
||||
|
||||
for (int ix = 0; ix < sm.size(); ix++) {
|
||||
if (ix > 0 && ix % 3 == 0) {
|
||||
gdi.dropLine(2.5);
|
||||
gdi.popX();
|
||||
}
|
||||
|
||||
auto &m = sm[ix];
|
||||
Machines type = AutoMachine::getType(m.first);
|
||||
if (m.second == L"default")
|
||||
gdi.addButton("CreateLoad", AutoMachine::getDescription(type), AutomaticCB).setExtra(ix);
|
||||
else
|
||||
gdi.addButton("CreateLoad", L"#" + lang.tl(AutoMachine::getDescription(type))
|
||||
+ L" (" + m.second + L")", AutomaticCB).setExtra(ix);
|
||||
}
|
||||
gdi.popX();
|
||||
gdi.dropLine(2);
|
||||
gdi.fillDown();
|
||||
}
|
||||
|
||||
gdi.dropLine();
|
||||
gdi.addString("", fontMediumPlus, "Tillgängliga automater").setColor(colorDarkBlue);
|
||||
gdi.dropLine();
|
||||
gdi.dropLine(0.3);
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
gdi.addButton("Result", "Resultatutskrift / export", AutomaticCB, "tooltip:resultprint");
|
||||
gdi.addButton("OnlineResults", "Resultat online", AutomaticCB, "Publicera resultat direkt på nätet");
|
||||
gdi.addButton("OnlineInput", "Inmatning online", AutomaticCB, "Hämta stämplingar m.m. från nätet");
|
||||
gdi.addButton("Result", AutoMachine::getDescription(Machines::mPrintResultsMachine), AutomaticCB, "tooltip:resultprint");
|
||||
gdi.addButton("OnlineResults", AutoMachine::getDescription(Machines::mOnlineResults), AutomaticCB, "Publicera resultat direkt på nätet");
|
||||
gdi.addButton("OnlineInput", AutoMachine::getDescription(Machines::mOnlineInput), AutomaticCB, "Hämta stämplingar m.m. från nätet");
|
||||
gdi.popX();
|
||||
gdi.dropLine(2.5);
|
||||
gdi.addButton("SaveBackup", "Säkerhetskopiering", AutomaticCB);
|
||||
gdi.addButton("InfoService", "Informationsserver", AutomaticCB);
|
||||
gdi.addButton("Punches", "Stämplingstest", AutomaticCB, "Simulera inläsning av stämplar");
|
||||
gdi.addButton("SaveBackup", AutoMachine::getDescription(Machines::mSaveBackup), AutomaticCB);
|
||||
gdi.addButton("InfoService", AutoMachine::getDescription(Machines::mInfoService), AutomaticCB);
|
||||
gdi.addButton("Punches", AutoMachine::getDescription(Machines::mPunchMachine), AutomaticCB, "Simulera inläsning av stämplar");
|
||||
gdi.popX();
|
||||
gdi.dropLine(2.5);
|
||||
gdi.addButton("Splits", "Sträcktider (WinSplits)", AutomaticCB, "Spara sträcktider till en fil för automatisk synkronisering med WinSplits");
|
||||
gdi.addButton("Prewarning", "Förvarningsröst", AutomaticCB, "tooltip:voice");
|
||||
|
||||
gdi.addButton("Splits", AutoMachine::getDescription(Machines::mSplitsMachine), AutomaticCB, "Spara sträcktider till en fil för automatisk synkronisering med WinSplits");
|
||||
gdi.addButton("Prewarning", AutoMachine::getDescription(Machines::mPrewarningMachine), AutomaticCB, "tooltip:voice");
|
||||
|
||||
gdi.fillDown();
|
||||
gdi.dropLine(3);
|
||||
gdi.popX();
|
||||
|
||||
if (!machines.empty()) {
|
||||
gdi.addString("", fontMediumPlus, "Startade automater").setColor(colorDarkBlue);;
|
||||
gdi.addString("", fontMediumPlus, "Startade automater").setColor(colorDarkBlue);
|
||||
list<AutoMachine *>::iterator it;
|
||||
|
||||
int baseX = gdi.getCX();
|
||||
@ -666,30 +659,44 @@ bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
|
||||
gdi.setOffset(storedOY, storedOY, true);
|
||||
}
|
||||
if (showSettingsLast && !machines.empty())
|
||||
settings(gdi, *machines.rbegin(), Machines::Unknown);
|
||||
settings(gdi, *machines.rbegin(), AutoMachine::State::Edit, Machines::Unknown);
|
||||
|
||||
gdi.refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoMachine::settingsTitle(gdioutput &gdi, char *title) {
|
||||
gdi.fillDown();
|
||||
gdi.dropLine(0.5);
|
||||
gdi.addString("", fontMediumPlus, title).setColor(colorDarkBlue);
|
||||
gdi.dropLine(0.5);
|
||||
}
|
||||
|
||||
void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool created, IntervalType type, const wstring &intervalIn) {
|
||||
void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, State state, IntervalType type, const wstring &intervalIn) {
|
||||
gdi.pushX();
|
||||
gdi.fillRight();
|
||||
|
||||
gdi.addInput("MachineName", machineName, 10, nullptr, L"Namn", L"Om du vill kan du namnge automaten");
|
||||
|
||||
if (type == IntervalMinute)
|
||||
gdi.addInput("Interval", intervalIn, 7, 0, L"Tidsintervall (MM:SS):");
|
||||
else if (type == IntervalSecond)
|
||||
gdi.addInput("Interval", intervalIn, 7, 0, L"Tidsintervall (sekunder):");
|
||||
|
||||
gdi.dropLine(1);
|
||||
gdi.addButton(startCommand, created ? "Starta automaten" : "OK", AutomaticCB).setExtra(getId());
|
||||
if (!created)
|
||||
gdi.addButton(startCommand,
|
||||
(state == State::Create || state == State::Load) ? "Starta automaten" : "OK", AutomaticCB).setExtra(getId());
|
||||
|
||||
if (hasSaveMachine())
|
||||
gdi.addButton("SaveMachine", "Spara inställningar", AutomaticCB).setExtra(getId());
|
||||
|
||||
if (state == State::Load)
|
||||
gdi.addButton("Erase", "Radera", AutomaticCB).setExtra(getId());
|
||||
|
||||
if (state == State::Edit)
|
||||
gdi.addButton("Cancel", "Avbryt", AutomaticCB).setExtra(getId());
|
||||
|
||||
gdi.addButton("Stop", created ? "Avbryt" : "Stoppa automaten", AutomaticCB).setExtra(getId());
|
||||
gdi.addButton("Stop", (state == State::Create || state == State::Load) ? "Avbryt" : "Stoppa automaten", AutomaticCB).setExtra(getId());
|
||||
|
||||
gdi.popX();
|
||||
gdi.fillDown();
|
||||
@ -704,13 +711,12 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool c
|
||||
gdi.dropLine();
|
||||
}
|
||||
|
||||
|
||||
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
settingsTitle(gdi, "Resultatutskrift / export");
|
||||
wstring time = (created && interval <= 0) ? L"10:00" : getTimeMS(interval);
|
||||
startCancelInterval(gdi, "StartResult", created, IntervalMinute, time);
|
||||
wstring time = (state == State::Create && interval <= 0) ? L"10:00" : getTimeMS(interval);
|
||||
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
||||
|
||||
if (created) {
|
||||
if (state == State::Create) {
|
||||
oe.getAllClasses(classesToPrint);
|
||||
}
|
||||
|
||||
@ -813,6 +819,55 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
}
|
||||
}
|
||||
|
||||
void PrintResultMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
wstring minute = gdi.getText("Interval");
|
||||
int t = convertAbsoluteTimeMS(minute);
|
||||
|
||||
if (t < 2 || t>7200) {
|
||||
throw meosException("Intervallet måste anges på formen MM:SS.");
|
||||
}
|
||||
doExport = gdi.isChecked("DoExport");
|
||||
doPrint = gdi.isChecked("DoPrint");
|
||||
exportFile = gdi.getText("ExportFile");
|
||||
exportScript = gdi.getText("ExportScript");
|
||||
|
||||
if (!readOnly) {
|
||||
structuredExport = gdi.isChecked("StructuredExport");
|
||||
htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
|
||||
|
||||
gdi.getSelection("Classes", classesToPrint);
|
||||
|
||||
ListBoxInfo lbi;
|
||||
if (gdi.getSelectedItem("ListType", lbi)) {
|
||||
oListParam par;
|
||||
par.selection = classesToPrint;
|
||||
par.listCode = EStdListType(lbi.data);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.showHeader = gdi.isChecked("ShowHeader");
|
||||
par.showInterTimes = gdi.isChecked("ShowInterResults");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
int legNr = gdi.getSelectedItem("LegNumber").first;
|
||||
if (legNr >= 0)
|
||||
par.setLegNumberCoded(legNr);
|
||||
else
|
||||
par.setLegNumberCoded(0);
|
||||
|
||||
oe.generateListInfo(par, listInfo);
|
||||
}
|
||||
}
|
||||
po.onlyChanged = gdi.isChecked("OnlyChanged");
|
||||
pageBreak = gdi.isChecked("PageBreak");
|
||||
showHeader = gdi.isChecked("ShowHeader");
|
||||
|
||||
showInterResult = gdi.isChecked("ShowInterResults");
|
||||
splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
if (doProcess) {
|
||||
interval = t;
|
||||
synchronize = true; //To force continuos data sync.
|
||||
}
|
||||
}
|
||||
|
||||
void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
{
|
||||
if (lock)
|
||||
@ -876,7 +931,7 @@ void PrintResultMachine::status(gdioutput &gdi)
|
||||
{
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
gdi.addString("", 0, name);
|
||||
AutoMachine::status(gdi);
|
||||
gdi.addString("", 0, listInfo.getName());
|
||||
gdi.dropLine();
|
||||
if (doExport) {
|
||||
@ -903,9 +958,9 @@ void PrintResultMachine::status(gdioutput &gdi)
|
||||
gdi.popX();
|
||||
}
|
||||
|
||||
void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
settingsTitle(gdi, "Förvarningsröst");
|
||||
startCancelInterval(gdi, "StartPrewarning", created, IntervalNone, L"");
|
||||
startCancelInterval(gdi, "Save", state, IntervalNone, L"");
|
||||
|
||||
gdi.addString("", 10, "help:computer_voice");
|
||||
|
||||
@ -930,6 +985,27 @@ void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.popX();
|
||||
}
|
||||
|
||||
void PrewarningMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
waveFolder = gdi.getText("WaveFolder");
|
||||
gdi.getSelection("Controls", controls);
|
||||
|
||||
oe.synchronizeList(oListId::oLPunchId);
|
||||
oe.clearPrewarningSounds();
|
||||
|
||||
controlsSI.clear();
|
||||
for (set<int>::iterator it = controls.begin(); it != controls.end(); ++it) {
|
||||
pControl pc = oe.getControl(*it, false);
|
||||
if (pc) {
|
||||
vector<int> n;
|
||||
pc->getNumbers(n);
|
||||
controlsSI.insert(n.begin(), n.end());
|
||||
}
|
||||
}
|
||||
if (doProcess)
|
||||
synchronizePunches = true;
|
||||
}
|
||||
|
||||
void PrewarningMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
{
|
||||
oe->playPrewarningSounds(waveFolder, controlsSI);
|
||||
@ -937,7 +1013,7 @@ void PrewarningMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
|
||||
void PrewarningMachine::status(gdioutput &gdi)
|
||||
{
|
||||
gdi.addString("", 1, name);
|
||||
AutoMachine::status(gdi);
|
||||
|
||||
string info="Förvarning på (SI-kod): ";
|
||||
bool first=true;
|
||||
@ -968,10 +1044,10 @@ void PrewarningMachine::status(gdioutput &gdi)
|
||||
gdi.popX();
|
||||
}
|
||||
|
||||
void PunchMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void PunchMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
settingsTitle(gdi, "Test av stämplingsinläsningar");
|
||||
wstring time=created ? L"10" : itow(interval);
|
||||
startCancelInterval(gdi, "StartPunch", created, IntervalSecond, time);
|
||||
wstring time = state == State::Create ? L"10" : itow(interval);
|
||||
startCancelInterval(gdi, "Save", state, IntervalSecond, time);
|
||||
|
||||
gdi.addString("", 10, "help:simulate");
|
||||
|
||||
@ -995,9 +1071,23 @@ void PunchMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.addButton("GenerateCMP", "Generera testtävling", AutomaticCB);
|
||||
}
|
||||
|
||||
void PunchMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
wstring minute = gdi.getText("Interval");
|
||||
int t = _wtoi(minute.c_str());
|
||||
|
||||
if (t<1 || t>7200) {
|
||||
throw meosException(L"Ogiltigt antal sekunder: X#" + minute);
|
||||
}
|
||||
else {
|
||||
interval = t;
|
||||
radio = gdi.getTextNo("Radio");
|
||||
}
|
||||
}
|
||||
|
||||
void PunchMachine::status(gdioutput &gdi)
|
||||
{
|
||||
gdi.addString("", 1, name);
|
||||
AutoMachine::status(gdi);
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
if (interval>0){
|
||||
@ -1066,15 +1156,15 @@ void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
#endif
|
||||
}
|
||||
|
||||
void SplitsMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void SplitsMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
wstring time;
|
||||
if (interval>0)
|
||||
time = itow(interval);
|
||||
else if (created)
|
||||
else if (state == State::Create)
|
||||
time = L"30";
|
||||
|
||||
settingsTitle(gdi, "Sträcktider / WinSplits");
|
||||
startCancelInterval(gdi, "StartSplits", created, IntervalSecond, time);
|
||||
startCancelInterval(gdi, "Save", state, IntervalSecond, time);
|
||||
|
||||
gdi.addString("", 0, "Intervall (sekunder). Lämna blankt för att uppdatera när "
|
||||
"tävlingsdata ändras.");
|
||||
@ -1094,9 +1184,33 @@ void SplitsMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
|
||||
}
|
||||
|
||||
void SplitsMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
wstring ivt = gdi.getText("Interval");
|
||||
|
||||
int iv = gdi.getTextNo("Interval");
|
||||
file = gdi.getText("FileName");
|
||||
|
||||
if (!ivt.empty() && (iv < 1 || iv > 7200)) {
|
||||
throw meosException(L"Ogiltigt antal sekunder: X#" + gdi.getText("Interval"));
|
||||
}
|
||||
|
||||
if (file.empty()) {
|
||||
throw meosException("Filnamnet får inte vara tomt");
|
||||
}
|
||||
|
||||
if (doProcess) {
|
||||
//Try exporting.
|
||||
oe.exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
|
||||
set<int>(), -1, false, true, true, false);
|
||||
interval = iv;
|
||||
synchronize = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SplitsMachine::status(gdioutput &gdi)
|
||||
{
|
||||
gdi.addString("", 1, name);
|
||||
AutoMachine::status(gdi);
|
||||
if (!file.empty()) {
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
@ -1133,7 +1247,8 @@ void SplitsMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
}
|
||||
|
||||
void SaveMachine::status(gdioutput &gdi) {
|
||||
gdi.addString("", 1, name);
|
||||
AutoMachine::status(gdi);
|
||||
|
||||
if (!baseFile.empty()) {
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
@ -1165,10 +1280,10 @@ void SaveMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
||||
}
|
||||
}
|
||||
|
||||
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
settingsTitle(gdi, "Säkerhetskopiering");
|
||||
wstring time=created ? L"10:00" : getTimeMS(interval);
|
||||
startCancelInterval(gdi, "StartBackup", created, IntervalMinute, time);
|
||||
wstring time=state == State::Create ? L"10:00" : getTimeMS(interval);
|
||||
startCancelInterval(gdi, "Save", state, IntervalMinute, time);
|
||||
|
||||
int cx = gdi.getCX();
|
||||
gdi.addInput("BaseFile", baseFile, 32, 0, L"Mapp:");
|
||||
@ -1177,8 +1292,8 @@ void SaveMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.setCX(cx);
|
||||
}
|
||||
|
||||
void SaveMachine::saveSettings(gdioutput &gdi) {
|
||||
|
||||
void SaveMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
|
||||
AutoMachine::save(oe, gdi, doProcess);
|
||||
wstring minute=gdi.getText("Interval");
|
||||
int t=convertAbsoluteTimeMS(minute);
|
||||
|
||||
@ -1193,23 +1308,83 @@ void SaveMachine::saveSettings(gdioutput &gdi) {
|
||||
if (*f.rbegin() != '\\' && *f.rbegin() != '/')
|
||||
f += L"\\";
|
||||
|
||||
wstring sample = f + L"sample.txt";
|
||||
ofstream fout(sample.c_str(), ios_base::trunc|ios_base::out);
|
||||
bool bad = false;
|
||||
if (fout.bad())
|
||||
bad = true;
|
||||
else {
|
||||
fout << "foo" << endl;
|
||||
fout.close();
|
||||
bad = fout.bad();
|
||||
_wremove(sample.c_str());
|
||||
}
|
||||
if (bad)
|
||||
throw meosException(L"Ogiltig destination X#" + f);
|
||||
if (doProcess) {
|
||||
wstring sample = f + L"sample.txt";
|
||||
ofstream fout(sample.c_str(), ios_base::trunc | ios_base::out);
|
||||
bool bad = false;
|
||||
if (fout.bad())
|
||||
bad = true;
|
||||
else {
|
||||
fout << "foo" << endl;
|
||||
fout.close();
|
||||
bad = fout.bad();
|
||||
_wremove(sample.c_str());
|
||||
}
|
||||
if (bad)
|
||||
throw meosException(L"Ogiltig destination X#" + f);
|
||||
|
||||
interval = t;
|
||||
}
|
||||
baseFile = f;
|
||||
interval = t;
|
||||
}
|
||||
|
||||
void TabAuto::clearCompetitionData() {
|
||||
}
|
||||
|
||||
Machines AutoMachine::getType(const string &typeStr) {
|
||||
if (typeStr == "onlineinput")
|
||||
return Machines::mOnlineInput;
|
||||
else if (typeStr == "onlineresults")
|
||||
return Machines::mOnlineResults;
|
||||
return Machines::Unknown;
|
||||
}
|
||||
|
||||
string AutoMachine::getDescription(Machines type) {
|
||||
switch (type) {
|
||||
case mPrintResultsMachine:
|
||||
return "Resultatutskrift / export";
|
||||
case mPunchMachine:
|
||||
return "Stämplingstest";
|
||||
case mSplitsMachine:
|
||||
return "Sträcktider (WinSplits)";
|
||||
case mPrewarningMachine:
|
||||
return "Förvarningsröst";
|
||||
case mOnlineResults:
|
||||
return "Resultat online";
|
||||
case mOnlineInput:
|
||||
return "Inmatning online";
|
||||
case mSaveBackup:
|
||||
return "Säkerhetskopiering";
|
||||
case mInfoService:
|
||||
return "Informationsserver";
|
||||
case mMySQLReconnect:
|
||||
return "MySQL reconnect";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
string AutoMachine::getTypeString(Machines type) {
|
||||
switch (type) {
|
||||
case mPrintResultsMachine:
|
||||
return "printresult";
|
||||
case mPunchMachine:
|
||||
return "punchtest";
|
||||
case mSplitsMachine:
|
||||
return "splits";
|
||||
case mPrewarningMachine:
|
||||
return "prewarning";
|
||||
case mOnlineResults:
|
||||
return "onlineresults";
|
||||
case mOnlineInput:
|
||||
return "onlineinput";
|
||||
case mSaveBackup:
|
||||
return "backup";
|
||||
case mInfoService:
|
||||
return "infoserver";
|
||||
case mMySQLReconnect:
|
||||
return "reconnect";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
112
code/TabAuto.h
112
code/TabAuto.h
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -51,6 +51,14 @@ enum Machines {
|
||||
|
||||
class AutoMachine
|
||||
{
|
||||
public:
|
||||
|
||||
enum class State {
|
||||
Edit,
|
||||
Create,
|
||||
Load
|
||||
};
|
||||
|
||||
private:
|
||||
int myid;
|
||||
static int uniqueId;
|
||||
@ -61,21 +69,47 @@ protected:
|
||||
|
||||
void settingsTitle(gdioutput &gdi, char *title);
|
||||
enum IntervalType {IntervalNone, IntervalMinute, IntervalSecond};
|
||||
void startCancelInterval(gdioutput &gdi, char *startCommand, bool created, IntervalType type, const wstring &interval);
|
||||
void startCancelInterval(gdioutput &gdi, char *startCommand, State state, IntervalType type, const wstring &interval);
|
||||
|
||||
virtual bool hasSaveMachine() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual void saveMachine(oEvent &oe, const wstring &guiInterval) {
|
||||
}
|
||||
|
||||
virtual void loadMachine(oEvent &oe, const wstring &name) {
|
||||
}
|
||||
|
||||
// Return true to auto-remove
|
||||
virtual bool removeMe() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static AutoMachine *getMachine(int id);
|
||||
static void resetGlobalId() {uniqueId = 1;}
|
||||
int getId() const {return myid;}
|
||||
static AutoMachine* construct(Machines);
|
||||
static Machines getType(const string &typeStr);
|
||||
static string getDescription(Machines type);
|
||||
static string getTypeString(Machines type);
|
||||
string getTypeString() const { return getTypeString(type); }
|
||||
wstring getMachineName() const {
|
||||
return machineName.empty() ? L"default" : machineName;
|
||||
}
|
||||
|
||||
void setEditMode(bool em) {editMode = em;}
|
||||
string name;
|
||||
wstring machineName;
|
||||
DWORD interval; //Interval seconds
|
||||
DWORD timeout; //Timeout (TickCount)
|
||||
bool synchronize;
|
||||
bool synchronizePunches;
|
||||
virtual void settings(gdioutput &gdi, oEvent &oe, bool created) = 0;
|
||||
virtual void save(oEvent &oe, gdioutput &gdi) {}
|
||||
|
||||
virtual void settings(gdioutput &gdi, oEvent &oe, State state) = 0;
|
||||
virtual void save(oEvent &oe, gdioutput &gdi, bool doProcess) = 0;
|
||||
virtual void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) = 0;
|
||||
virtual bool isEditMode() const {return editMode;}
|
||||
virtual void status(gdioutput &gdi) = 0;
|
||||
@ -119,9 +153,10 @@ public:
|
||||
prm->errorLock = false;
|
||||
return prm;
|
||||
}
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state) final;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final;
|
||||
|
||||
void setHTML(const wstring &file, int timeout) {
|
||||
exportFile = file;
|
||||
@ -176,10 +211,10 @@ public:
|
||||
return prm;
|
||||
}
|
||||
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void saveSettings(gdioutput &gdi);
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state) final;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final;
|
||||
|
||||
SaveMachine():AutoMachine("Säkerhetskopiera", Machines::mSaveBackup) , saveIter(0) {
|
||||
}
|
||||
@ -194,10 +229,12 @@ protected:
|
||||
set<int> controls;
|
||||
set<int> controlsSI;
|
||||
public:
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state);
|
||||
PrewarningMachine *clone() const {return new PrewarningMachine(*this);}
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final;
|
||||
|
||||
PrewarningMachine():AutoMachine("Förvarningsröst", Machines::mPrewarningMachine) {}
|
||||
friend class TabAuto;
|
||||
};
|
||||
@ -210,12 +247,21 @@ protected:
|
||||
wstring timeError;
|
||||
wstring timeReconnect;
|
||||
HANDLE hThread;
|
||||
bool toRemove = false;
|
||||
|
||||
public:
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state);
|
||||
MySQLReconnect *clone() const {return new MySQLReconnect(*this);}
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
bool stop();
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final {
|
||||
}
|
||||
|
||||
bool removeMe() const final {
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
MySQLReconnect(const wstring &error);
|
||||
virtual ~MySQLReconnect();
|
||||
friend class TabAuto;
|
||||
@ -230,9 +276,11 @@ protected:
|
||||
int radio;
|
||||
public:
|
||||
PunchMachine *clone() const {return new PunchMachine(*this);}
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state) final;
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final;
|
||||
|
||||
PunchMachine():AutoMachine("Stämplingsautomat", Machines::mPunchMachine), radio(0) {}
|
||||
friend class TabAuto;
|
||||
};
|
||||
@ -246,9 +294,11 @@ protected:
|
||||
int leg;
|
||||
public:
|
||||
SplitsMachine *clone() const {return new SplitsMachine(*this);}
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
void settings(gdioutput &gdi, oEvent &oe, State state) final;
|
||||
void status(gdioutput &gdi) final;
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) final;
|
||||
void save(oEvent &oe, gdioutput &gdi, bool doProcess) final;
|
||||
|
||||
SplitsMachine() : AutoMachine("Sträcktider/WinSplits", Machines::mSplitsMachine), leg(-1) {}
|
||||
friend class TabAuto;
|
||||
};
|
||||
@ -273,20 +323,22 @@ private:
|
||||
void timerCallback(gdioutput &gdi);
|
||||
void syncCallback(gdioutput &gdi);
|
||||
|
||||
void settings(gdioutput &gdi, AutoMachine *sm, Machines type);
|
||||
void settings(gdioutput &gdi, AutoMachine *sm, AutoMachine::State state, Machines type);
|
||||
|
||||
protected:
|
||||
void clearCompetitionData();
|
||||
bool hasActiveReconnection() const;
|
||||
|
||||
public:
|
||||
|
||||
AutoMachine *getMachine(int id);
|
||||
//AutoMachine *getMachine(const string &name);
|
||||
bool stopMachine(AutoMachine *am);
|
||||
void killMachines();
|
||||
void addMachine(const AutoMachine &am) {
|
||||
|
||||
AutoMachine &addMachine(const AutoMachine &am) {
|
||||
machines.push_back(am.clone());
|
||||
setTimer(machines.back());
|
||||
return *machines.back();
|
||||
}
|
||||
|
||||
int processButton(gdioutput &gdi, const ButtonInfo &bu);
|
||||
@ -305,8 +357,10 @@ public:
|
||||
|
||||
friend class AutoTask;
|
||||
friend void tabForceSync(gdioutput &gdi, pEvent oe);
|
||||
|
||||
static void tabAutoKillMachines();
|
||||
static void tabAutoRegister(TabAuto* ta);
|
||||
static AutoMachine& tabAutoAddMachinge(const AutoMachine& am);
|
||||
static bool hasActiveReconnectionMachine();
|
||||
};
|
||||
|
||||
void tabAutoKillMachines();
|
||||
void tabAutoRegister(TabAuto *ta);
|
||||
void tabAutoAddMachinge(const AutoMachine &am);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -310,89 +310,94 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id == "ShowForking") {
|
||||
if (!checkClassSelected(gdi))
|
||||
return false;
|
||||
pClass pc=oe->getClass(ClassId);
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
if (!pc)
|
||||
throw std::exception("Klassen finns ej.");
|
||||
|
||||
vector< vector<int> > forks;
|
||||
set< pair<int, int> > unfairLegs;
|
||||
vector< vector<int> > legOrder;
|
||||
|
||||
pc->checkForking(legOrder, forks, unfairLegs);
|
||||
|
||||
gdioutput *gdi_new = getExtraWindow("fork", true);
|
||||
wstring title = lang.tl(L"Forkings for X#" + pc->getName());
|
||||
if (!gdi_new)
|
||||
gdi_new = createExtraWindow("fork", title,
|
||||
gdi.scaleLength(1024) );
|
||||
gdi.scaleLength(1024));
|
||||
else
|
||||
gdi_new->setWindowTitle(title);
|
||||
|
||||
gdi_new->clearPage(false);
|
||||
|
||||
gdi_new->addString("", fontMediumPlus, "Forkings");
|
||||
|
||||
for (size_t k = 0; k < forks.size(); k++) {
|
||||
gdi_new->dropLine(0.7);
|
||||
wstring ver = itow(k+1) + L": ";
|
||||
for (size_t j = 0; j < legOrder[k].size(); j++) {
|
||||
pCourse crs = oe->getCourse(legOrder[k][j]);
|
||||
if (crs) {
|
||||
if (j>0)
|
||||
ver += L", ";
|
||||
ver += crs->getName();
|
||||
}
|
||||
}
|
||||
gdi_new->addStringUT(1, ver);
|
||||
gdi_new->pushX();
|
||||
gdi_new->fillRight();
|
||||
for (size_t j = 0; j < forks[k].size(); j++) {
|
||||
wstring ctrl;
|
||||
if (forks[k][j] > 0)
|
||||
ctrl += itow(forks[k][j]);
|
||||
else {
|
||||
if (j == 0)
|
||||
ctrl += lang.tl("Start");
|
||||
else if (j + 1 == forks[k].size())
|
||||
ctrl += lang.tl("Mål");
|
||||
else
|
||||
ctrl += lang.tl("Växel");
|
||||
}
|
||||
int next = -100;
|
||||
if (j + 1 < forks[k].size()) {
|
||||
ctrl += L",";
|
||||
next = forks[k][j+1];
|
||||
}
|
||||
int prev = j>0 ? forks[k][j-1] : -100;
|
||||
|
||||
bool warn = unfairLegs.count(make_pair(prev, forks[k][j])) != 0;// ||
|
||||
//unfairLegs.count(make_pair(forks[k][j], next)) != 0;
|
||||
|
||||
TextInfo &ti = gdi_new->addStringUT(italicText, ctrl);
|
||||
if (warn) {
|
||||
ti.setColor(colorRed);
|
||||
ti.format = boldText;
|
||||
}
|
||||
gdi.setCX(gdi.getCX() - gdi.scaleLength(4));
|
||||
}
|
||||
gdi_new->popX();
|
||||
gdi_new->fillDown();
|
||||
gdi_new->dropLine();
|
||||
if (pc->hasCoursePool()) {
|
||||
gdi_new->addString("", fontMediumPlus, "Klassen använder banpool");
|
||||
}
|
||||
else {
|
||||
vector< vector<int> > forks;
|
||||
set< pair<int, int> > unfairLegs;
|
||||
vector< vector<int> > legOrder;
|
||||
|
||||
if (!unfairLegs.empty()) {
|
||||
gdi_new->dropLine();
|
||||
gdi_new->addString("", fontMediumPlus, "Unfair control legs");
|
||||
gdi_new->dropLine(0.5);
|
||||
for (set< pair<int, int> >::const_iterator p = unfairLegs.begin();
|
||||
p != unfairLegs.end(); ++p) {
|
||||
pc->checkForking(legOrder, forks, unfairLegs);
|
||||
|
||||
wstring f = p->first > 0 ? itow(p->first) : lang.tl("Växel");
|
||||
wstring s = p->second > 0 ? itow(p->second) : lang.tl("Växel");
|
||||
gdi_new->addStringUT(0, makeDash(f + L" - " + s));
|
||||
gdi_new->addString("", fontMediumPlus, "Forkings");
|
||||
|
||||
for (size_t k = 0; k < forks.size(); k++) {
|
||||
gdi_new->dropLine(0.7);
|
||||
wstring ver = itow(k + 1) + L": ";
|
||||
for (size_t j = 0; j < legOrder[k].size(); j++) {
|
||||
pCourse crs = oe->getCourse(legOrder[k][j]);
|
||||
if (crs) {
|
||||
if (j > 0)
|
||||
ver += L", ";
|
||||
ver += crs->getName();
|
||||
}
|
||||
}
|
||||
gdi_new->addStringUT(1, ver);
|
||||
gdi_new->pushX();
|
||||
gdi_new->fillRight();
|
||||
for (size_t j = 0; j < forks[k].size(); j++) {
|
||||
wstring ctrl;
|
||||
if (forks[k][j] > 0)
|
||||
ctrl += itow(forks[k][j]);
|
||||
else {
|
||||
if (j == 0)
|
||||
ctrl += lang.tl("Start");
|
||||
else if (j + 1 == forks[k].size())
|
||||
ctrl += lang.tl("Mål");
|
||||
else
|
||||
ctrl += lang.tl("Växel");
|
||||
}
|
||||
int next = -100;
|
||||
if (j + 1 < forks[k].size()) {
|
||||
ctrl += L",";
|
||||
next = forks[k][j + 1];
|
||||
}
|
||||
int prev = j > 0 ? forks[k][j - 1] : -100;
|
||||
|
||||
bool warn = unfairLegs.count(make_pair(prev, forks[k][j])) != 0;// ||
|
||||
//unfairLegs.count(make_pair(forks[k][j], next)) != 0;
|
||||
|
||||
TextInfo &ti = gdi_new->addStringUT(italicText, ctrl);
|
||||
if (warn) {
|
||||
ti.setColor(colorRed);
|
||||
ti.format = boldText;
|
||||
}
|
||||
gdi.setCX(gdi.getCX() - gdi.scaleLength(4));
|
||||
}
|
||||
gdi_new->popX();
|
||||
gdi_new->fillDown();
|
||||
gdi_new->dropLine();
|
||||
}
|
||||
|
||||
if (!unfairLegs.empty()) {
|
||||
gdi_new->dropLine();
|
||||
gdi_new->addString("", fontMediumPlus, "Unfair control legs");
|
||||
gdi_new->dropLine(0.5);
|
||||
for (set< pair<int, int> >::const_iterator p = unfairLegs.begin();
|
||||
p != unfairLegs.end(); ++p) {
|
||||
|
||||
wstring f = p->first > 0 ? itow(p->first) : lang.tl("Växel");
|
||||
wstring s = p->second > 0 ? itow(p->second) : lang.tl("Växel");
|
||||
gdi_new->addStringUT(0, makeDash(f + L" - " + s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gdi_new->dropLine();
|
||||
gdi_new->addButton("CloseWindow", "Stäng", ClassesCB);
|
||||
gdi_new->refresh();
|
||||
@ -1923,7 +1928,37 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.refresh();
|
||||
return 0;
|
||||
}
|
||||
else if (bi.id=="Split") {
|
||||
else if (bi.id == "Duplicate") {
|
||||
save(gdi, true);
|
||||
if (!checkClassSelected(gdi))
|
||||
return false;
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
if (!pc)
|
||||
throw std::exception("Class not found");
|
||||
|
||||
oClass copyClass(*pc);
|
||||
copyClass.clearDuplicate();
|
||||
wstring name = pc->getName();
|
||||
wstring dup = lang.tl(" (kopia)");
|
||||
size_t pos = name.find(dup);
|
||||
wstring base;
|
||||
if (pos > 0 && pos < string::npos)
|
||||
base = name.substr(0, pos);
|
||||
else
|
||||
base = name;
|
||||
|
||||
name = base + dup;
|
||||
int cnt = 1;
|
||||
while (oe->getClass(name) != nullptr)
|
||||
name = base + dup + L" " + itow(++cnt);
|
||||
|
||||
copyClass.setName(name, true);
|
||||
pc = oe->addClass(copyClass);
|
||||
oe->fillClasses(gdi, "Classes", oEvent::extraDrawn, oEvent::filterNone);
|
||||
selectClass(gdi, pc->getId());
|
||||
gdi.setInputFocus("Name", true);
|
||||
}
|
||||
else if (bi.id == "Split") {
|
||||
save(gdi, true);
|
||||
if (!checkClassSelected(gdi))
|
||||
return false;
|
||||
@ -3463,7 +3498,7 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
func.push_back(ButtonData("Merge", "Slå ihop klasser...", false));
|
||||
func.push_back(ButtonData("Split", "Dela klassen...", false));
|
||||
}
|
||||
|
||||
func.emplace_back("Duplicate", "Duplicera", false);
|
||||
|
||||
if (showAdvanced && oe->getMeOSFeatures().hasFeature(MeOSFeatures::Vacancy)) {
|
||||
vector<pRunner> rr;
|
||||
@ -4185,11 +4220,18 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
|
||||
void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const {
|
||||
if (!gdi.hasWidget("FairForking"))
|
||||
return;
|
||||
BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
|
||||
TextInfo &text = dynamic_cast<TextInfo &>(*bi);
|
||||
|
||||
if (pc->hasCoursePool()) {
|
||||
text.setColor(colorBlack);
|
||||
gdi.setText("FairForking", L"", true);
|
||||
return;
|
||||
}
|
||||
|
||||
vector< vector<int> > forks;
|
||||
vector< vector<int> > forksC;
|
||||
set< pair<int, int> > unfairLegs;
|
||||
BaseInfo *bi = gdi.setText("FairForking", gdi.getText("FairForking"), false);
|
||||
TextInfo &text = dynamic_cast<TextInfo &>(*bi);
|
||||
if (pc->checkForking(forksC, forks, unfairLegs)) {
|
||||
text.setColor(colorGreen);
|
||||
gdi.setText("FairForking", lang.tl("The forking is fair."), true);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -157,8 +157,8 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
|
||||
bool TabCompetition::importFile(HWND hWnd, gdioutput &gdi)
|
||||
{
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"xml-data", L"*.xml;*.bu?"));
|
||||
wstring fileName = gdi.browseForOpen(ext, L"xml");
|
||||
ext.push_back(make_pair(L"MeOS-data", L"*.meosxml;*.xml;*.bu?"));
|
||||
wstring fileName = gdi.browseForOpen(ext, L"meosxml");
|
||||
if (fileName.empty())
|
||||
return false;
|
||||
|
||||
@ -182,8 +182,8 @@ bool TabCompetition::exportFileAs(HWND hWnd, gdioutput &gdi)
|
||||
{
|
||||
int ix = 0;
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"xml-data", L"*.xml"));
|
||||
wstring fileName = gdi.browseForSave(ext, L"xml", ix);
|
||||
ext.push_back(make_pair(L"MeOS-data", L"*.meosxml"));
|
||||
wstring fileName = gdi.browseForSave(ext, L"meosxml", ix);
|
||||
if (fileName.empty())
|
||||
return false;
|
||||
|
||||
@ -779,7 +779,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
wstring base = constructBase(L"base", L"");
|
||||
wchar_t newBase[_MAX_PATH];
|
||||
getUserFile(newBase, base.c_str());
|
||||
if (!fileExist(newBase))
|
||||
if (!fileExists(newBase))
|
||||
oe->save(newBase);
|
||||
|
||||
loadConnectionPage(gdi);
|
||||
@ -2382,7 +2382,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
|
||||
|
||||
gdi.dropLine(0.4);
|
||||
gdi.fillDown();
|
||||
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2020 Melin Software HB"));
|
||||
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2021 Melin Software HB"));
|
||||
gdi.dropLine(1);
|
||||
gdi.popX();
|
||||
|
||||
@ -2412,7 +2412,7 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
||||
gdi.dropLine(1.5);
|
||||
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
|
||||
|
||||
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2020 Melin Software HB"));
|
||||
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2021 Melin Software HB"));
|
||||
gdi.dropLine();
|
||||
gdi.addStringUT(10, "The database connection used is MySQL++\nCopyright "
|
||||
"(c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB,"
|
||||
@ -2764,7 +2764,7 @@ void TabCompetition::textSizeControl(gdioutput &gdi) const
|
||||
}
|
||||
|
||||
int TabCompetition::getOrganizer(bool updateEvent) {
|
||||
wstring apikey = oe->getPropertyStringDecrypt("apikey", "");
|
||||
wstring apikey = gdioutput::widen(oe->getPropertyStringDecrypt("apikey", ""));
|
||||
if (apikey.empty())
|
||||
return 0;
|
||||
if (!isAscii(apikey))
|
||||
@ -2837,7 +2837,7 @@ int TabCompetition::getOrganizer(bool updateEvent) {
|
||||
}
|
||||
|
||||
void TabCompetition::getAPIKey(vector< pair<wstring, wstring> > &key) const {
|
||||
wstring apikey = oe->getPropertyStringDecrypt("apikey", "");
|
||||
wstring apikey = gdioutput::widen(oe->getPropertyStringDecrypt("apikey", ""));
|
||||
|
||||
if (apikey.empty() || organizorId == 0)
|
||||
throw std::exception("Internal error");
|
||||
@ -2989,7 +2989,7 @@ void TabCompetition::getEventorCmpData(gdioutput &gdi, int id,
|
||||
|
||||
pw.setProgress(1);
|
||||
vector< pair<wstring, wstring> > key;
|
||||
wstring apikey = oe->getPropertyStringDecrypt("apikey", "");
|
||||
wstring apikey = gdioutput::widen(oe->getPropertyStringDecrypt("apikey", ""));
|
||||
key.push_back(pair<wstring, wstring>(L"ApiKey", apikey));
|
||||
|
||||
gdi.fillRight();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -108,10 +108,10 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
|
||||
gdi.enableEditControls(true);
|
||||
|
||||
oControl::ControlStatus st = pc->getStatus();
|
||||
if (st == oControl::StatusRogaining || st == oControl::StatusNoTiming)
|
||||
if (st == oControl::StatusRogaining || st == oControl::StatusNoTiming || st == oControl::StatusBadNoTiming)
|
||||
gdi.disableInput("MinTime");
|
||||
|
||||
if (st == oControl::StatusNoTiming)
|
||||
if (st == oControl::StatusNoTiming || st == oControl::StatusBadNoTiming)
|
||||
gdi.disableInput("TimeAdjust");
|
||||
|
||||
if (gdi.hasWidget("Point") && st != oControl::StatusRogaining)
|
||||
@ -164,7 +164,7 @@ void TabControl::save(gdioutput &gdi)
|
||||
pc->setStatus(oControl::ControlStatus(gdi.getSelectedItem("Status").first));
|
||||
pc->setTimeAdjust(gdi.getText("TimeAdjust"));
|
||||
if (pc->getStatus() != oControl::StatusRogaining) {
|
||||
if (pc->getStatus() != oControl::StatusNoTiming)
|
||||
if (pc->getStatus() != oControl::StatusNoTiming && pc->getStatus() != oControl::StatusBadNoTiming)
|
||||
pc->setMinTime(gdi.getText("MinTime"));
|
||||
pc->setRogainingPoints(0);
|
||||
}
|
||||
@ -416,9 +416,9 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
|
||||
selectControl(gdi, pc);
|
||||
}
|
||||
else if (bi.id == "Status" ) {
|
||||
gdi.setInputStatus("MinTime", bi.data != oControl::StatusRogaining && bi.data != oControl::StatusNoTiming, true);
|
||||
gdi.setInputStatus("MinTime", bi.data != oControl::StatusRogaining && bi.data != oControl::StatusNoTiming && bi.data != oControl::StatusBadNoTiming, true);
|
||||
gdi.setInputStatus("Point", bi.data == oControl::StatusRogaining, true);
|
||||
gdi.setInputStatus("TimeAdjust", bi.data != oControl::StatusNoTiming, true);
|
||||
gdi.setInputStatus("TimeAdjust", bi.data != oControl::StatusNoTiming && bi.data != oControl::StatusBadNoTiming, true);
|
||||
}
|
||||
}
|
||||
else if (type==GUI_CLEAR) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -543,7 +543,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
|
||||
if (!htmlTarget.empty()) {
|
||||
prm.setHTML(htmlTarget, currentList.getParam().timePerPage / 1000);
|
||||
}
|
||||
tabAutoAddMachinge(prm);
|
||||
TabAuto::tabAutoAddMachinge(prm);
|
||||
dynamic_cast<TabAuto *>(gdi.getTabs().get(TAutoTab))->loadPage(gdi, true);
|
||||
}
|
||||
else if (bi.id == "WideFormat") {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
157
code/TabSI.cpp
157
code/TabSI.cpp
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -26,6 +26,8 @@
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <commdlg.h>
|
||||
#include <MMSystem.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "oEvent.h"
|
||||
@ -134,7 +136,83 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
allowControl = gdi.isChecked(bi.id);
|
||||
else if (bi.id == "AllowFinish")
|
||||
allowFinish = gdi.isChecked(bi.id);
|
||||
if (bi.id == "ClearMemory") {
|
||||
else if (bi.id == "PlaySound") {
|
||||
oe->setProperty("PlaySound", gdi.isChecked(bi.id) ? 1 : 0);
|
||||
}
|
||||
else if (bi.id == "SoundChoice") {
|
||||
gdi.disableInput("SoundChoice");
|
||||
gdi.setRestorePoint("Sound");
|
||||
gdi.dropLine();
|
||||
gdi.fillDown();
|
||||
gdi.addString("", fontMediumPlus, "help:selectsound");
|
||||
gdi.dropLine(0.5);
|
||||
gdi.pushX();
|
||||
gdi.fillRight();
|
||||
|
||||
auto addSoundWidget = [&gdi, this](const wchar_t *name, SND type, const wstring &label) {
|
||||
string nname = gdioutput::narrow(name);
|
||||
gdi.addInput(nname, oe->getPropertyString(nname.c_str(), L""), 32, nullptr, label);
|
||||
gdi.dropLine(0.8);
|
||||
gdi.addButton("BrowseSound", "Bläddra...", SportIdentCB).setExtra(name);
|
||||
gdi.addButton("TestSound", "Testa", SportIdentCB).setExtra(int(type));
|
||||
gdi.dropLine(3);
|
||||
gdi.popX();
|
||||
};
|
||||
|
||||
addSoundWidget(L"SoundOK", SND::OK, L"Status OK:");
|
||||
addSoundWidget(L"SoundNotOK", SND::NotOK, L"Status inte OK (röd utgång):");
|
||||
addSoundWidget(L"SoundLeader", SND::Leader, L"Ny ledare i klassen:");
|
||||
addSoundWidget(L"SoundAction", SND::ActionNeeded, L"Åtgärd krävs:");
|
||||
|
||||
gdi.addButton("CloseSound", "OK", SportIdentCB);
|
||||
gdi.popX();
|
||||
gdi.dropLine(3);
|
||||
gdi.scrollToBottom();
|
||||
gdi.refresh();
|
||||
/*
|
||||
fn = oe->getPropertyString("SoundOK", L"");
|
||||
res = 50;
|
||||
break;
|
||||
case SND::NotOK:
|
||||
fn = oe->getPropertyString("SoundNotOK", L"");
|
||||
res = 52;
|
||||
break;
|
||||
case SND::Leader:
|
||||
fn = oe->getPropertyString("SoundLeader", L"");
|
||||
res = 51;
|
||||
break;
|
||||
case SND::ActionNeeded:
|
||||
fn = oe->getPropertyString("SoundAction", L"");
|
||||
|
||||
|
||||
*/
|
||||
}
|
||||
else if (bi.id == "BrowseSound") {
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"Ljud (wav)", L"*.wav"));
|
||||
|
||||
wstring file = gdi.browseForOpen(ext, L"wav");
|
||||
if (!file.empty()) {
|
||||
wchar_t *type = bi.getExtra();
|
||||
string name = gdioutput::narrow(type);
|
||||
gdi.setText(name, file);
|
||||
oe->setProperty(name.c_str(), file);
|
||||
}
|
||||
}
|
||||
else if (bi.id == "SoundOK" || bi.id == "SoundNotOK" ||
|
||||
bi.id == "SoundLeader" || bi.id == "SoundAction") {
|
||||
oe->setProperty(bi.id.c_str(), bi.text);
|
||||
}
|
||||
else if (bi.id == "TestSound") {
|
||||
oe->setProperty("PlaySound", 1);
|
||||
gdi.check(bi.id, true);
|
||||
playReadoutSound(SND(bi.getExtraInt()));
|
||||
}
|
||||
else if (bi.id == "CloseSound") {
|
||||
gdi.restore("Sound", true);
|
||||
gdi.enableInput("SoundChoice");
|
||||
}
|
||||
else if (bi.id == "ClearMemory") {
|
||||
if (gdi.ask(L"Do you want to clear the card memory?")) {
|
||||
savedCards.clear();
|
||||
loadPage(gdi);
|
||||
@ -1678,7 +1756,7 @@ void TabSI::showReadCards(gdioutput &gdi, vector<SICard> &cards)
|
||||
SportIdent &TabSI::getSI(const gdioutput &gdi) {
|
||||
if (!gSI) {
|
||||
HWND hWnd=gdi.getHWNDMain();
|
||||
gSI = new SportIdent(hWnd, 0, gEvent->getPropertyInt("ReadVoltageExp", 0) != 0);
|
||||
gSI = new SportIdent(hWnd, 0, true);
|
||||
}
|
||||
return *gSI;
|
||||
}
|
||||
@ -1787,11 +1865,19 @@ bool TabSI::loadPage(gdioutput &gdi) {
|
||||
gdi.selectItemByData("ReadType", mode);
|
||||
|
||||
gdi.dropLine(-0.1);
|
||||
gdi.addButton("LockFunction", "Lås funktion...", SportIdentCB);
|
||||
gdi.addButton("LockFunction", "Lås funktion", SportIdentCB);
|
||||
readoutFunctionX = gdi.getCX();
|
||||
readoutFunctionY = gdi.getCY();
|
||||
gdi.dropLine(0.3);
|
||||
|
||||
gdi.addCheckbox("PlaySound", "Ljud", SportIdentCB, oe->getPropertyInt("PlaySound", 1) != 0,
|
||||
"Spela upp ett ljud för att indikera resultatet av brickavläsningen.");
|
||||
gdi.dropLine(-0.3);
|
||||
|
||||
gdi.addButton("SoundChoice", "Ljudval...", SportIdentCB);
|
||||
|
||||
gdi.dropLine(0.3);
|
||||
|
||||
gdi.addString("Allow", 0, "Tillåt:");
|
||||
gdi.addCheckbox("AllowStart", "Start", SportIdentCB, allowStart);
|
||||
gdi.addCheckbox("AllowControl", "Radio", SportIdentCB, allowControl);
|
||||
@ -1883,6 +1969,8 @@ void TabSI::updateReadoutFunction(gdioutput &gdi) {
|
||||
gdi.hideWidget("AllowStart", hide);
|
||||
gdi.hideWidget("AllowControl", hide);
|
||||
gdi.hideWidget("AllowFinish", hide);
|
||||
gdi.hideWidget("SoundChoice", hide);
|
||||
gdi.hideWidget("PlaySound", hide);
|
||||
}
|
||||
|
||||
void InsertSICard(gdioutput &gdi, SICard &sic)
|
||||
@ -2054,6 +2142,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gEvent->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
|
||||
|
||||
if (sic.punchOnly) {
|
||||
@ -2092,6 +2181,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
else {
|
||||
CardQueue.push_back(sic);
|
||||
gdi.addInfoBox("SIREAD", L"info:readout_action#" + gEvent->getCurrentTimeS()+L"#"+itow(sic.CardNumber), 0, SportIdentCB);
|
||||
playReadoutSound(SND::ActionNeeded);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2099,8 +2189,10 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
if (!readBefore) {
|
||||
if (r && r->getClassId(false) && !sameCardNewRace)
|
||||
processCard(gdi, r, sic, true);
|
||||
else
|
||||
else {
|
||||
processUnmatched(gdi, sic, true);
|
||||
playReadoutSound(SND::ActionNeeded);
|
||||
}
|
||||
}
|
||||
else
|
||||
gdi.addInfoBox("SIREAD", L"Brickan redan inläst.", 0, SportIdentCB);
|
||||
@ -2126,6 +2218,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
name = itow(sic.CardNumber) + name;
|
||||
CardQueue.push_back(sic);
|
||||
gdi.addInfoBox("SIREAD", L"info:readout_queue#" + gEvent->getCurrentTimeS() + L"#" + name);
|
||||
playReadoutSound(SND::ActionNeeded);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2166,6 +2259,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
gdi.scrollToBottom();
|
||||
gdi.refresh();
|
||||
activeSIC.clear(0);
|
||||
playReadoutSound(SND::ActionNeeded);
|
||||
checkMoreCardsInQueue(gdi);
|
||||
return;
|
||||
}
|
||||
@ -2422,7 +2516,7 @@ bool TabSI::processUnmatched(gdioutput &gdi, const SICard &csic, bool silent)
|
||||
gdi.addInfoBox("SIINFO", L"#" + info, 10000);
|
||||
}
|
||||
gdi.makeEvent("DataUpdate", "sireadout", 0, 0, true);
|
||||
|
||||
playReadoutSound(SND::ActionNeeded);
|
||||
checkMoreCardsInQueue(gdi);
|
||||
return true;
|
||||
}
|
||||
@ -2619,6 +2713,11 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
runner->getTeam()->getLegPlaceS(runner->getLegNumber(), false) :
|
||||
runner->getPlaceS();
|
||||
|
||||
if (placeS == L"1")
|
||||
playReadoutSound(SND::Leader);
|
||||
else
|
||||
playReadoutSound(SND::OK);
|
||||
|
||||
if (!silent) {
|
||||
gdi.fillDown();
|
||||
//gdi.dropLine();
|
||||
@ -2651,6 +2750,8 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
else {
|
||||
wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true, true);
|
||||
|
||||
playReadoutSound(SND::NotOK);
|
||||
|
||||
if (!MP.empty()) {
|
||||
msg=msg + L", (";
|
||||
vector<int>::iterator it;
|
||||
@ -4258,7 +4359,49 @@ void TabSI::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
|
||||
gdi.TabFocus(1);
|
||||
}
|
||||
|
||||
|
||||
bool TabSI::showDatabase() const {
|
||||
return useDatabase && oe->useRunnerDb();
|
||||
}
|
||||
void TabSI::playReadoutSound(SND type) {
|
||||
if (!oe->getPropertyInt("PlaySound", 0))
|
||||
return;
|
||||
int res = -1;
|
||||
wstring fn;
|
||||
switch (type) {
|
||||
case SND::OK:
|
||||
fn = oe->getPropertyString("SoundOK", L"");
|
||||
res = 50;
|
||||
break;
|
||||
case SND::NotOK:
|
||||
fn = oe->getPropertyString("SoundNotOK", L"");
|
||||
res = 52;
|
||||
break;
|
||||
case SND::Leader:
|
||||
fn = oe->getPropertyString("SoundLeader", L"");
|
||||
res = 51;
|
||||
break;
|
||||
case SND::ActionNeeded:
|
||||
fn = oe->getPropertyString("SoundAction", L"");
|
||||
res = 53;
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkedSound.count(fn) || (!fn.empty() && fileExists(fn))) {
|
||||
playSoundFile(fn);
|
||||
checkedSound.insert(fn);
|
||||
}
|
||||
else {
|
||||
playSoundResource(res);
|
||||
}
|
||||
}
|
||||
|
||||
void TabSI::playSoundResource(int res) const {
|
||||
PlaySound(MAKEINTRESOURCE(res), GetModuleHandle(nullptr), SND_RESOURCE| SND_ASYNC);
|
||||
//OutputDebugString((L"Play: " + itow(res)).c_str());
|
||||
|
||||
}
|
||||
|
||||
void TabSI::playSoundFile(const wstring& file) const {
|
||||
PlaySound(file.c_str(), nullptr, SND_FILENAME | SND_ASYNC);
|
||||
//OutputDebugString(file.c_str());
|
||||
}
|
||||
|
||||
15
code/TabSI.h
15
code/TabSI.h
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -68,6 +68,17 @@ private:
|
||||
list< pair<unsigned, int> > printPunchRunnerIdQueue;
|
||||
void addToPrintQueue(pRunner r);
|
||||
|
||||
enum class SND {
|
||||
OK,
|
||||
Leader,
|
||||
NotOK,
|
||||
ActionNeeded
|
||||
};
|
||||
|
||||
set<wstring> checkedSound;
|
||||
|
||||
void playReadoutSound(SND type);
|
||||
|
||||
vector<PunchInfo> punches;
|
||||
vector<SICard> cards;
|
||||
vector<wstring> filterDate;
|
||||
@ -206,6 +217,8 @@ private:
|
||||
int readoutFunctionX = 0;
|
||||
int readoutFunctionY = 0;
|
||||
|
||||
void playSoundResource(int res) const;
|
||||
void playSoundFile(const wstring& file) const;
|
||||
protected:
|
||||
void clearCompetitionData();
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -1102,7 +1102,7 @@ bool TabSpeaker::loadPage(gdioutput &gdi) {
|
||||
|
||||
if (getExtraWindows().size() == 1) {
|
||||
wstring sf = getSpeakerSettingsFile();
|
||||
if (fileExist(sf.c_str())) {
|
||||
if (fileExists(sf)) {
|
||||
if ((cx + db) > basex && (cx + db + bw) >= limitX) {
|
||||
cx = basex; db = 0;
|
||||
cy += gdi.getButtonHeight() + 4;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -1908,13 +1908,17 @@ void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
|
||||
void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
|
||||
vector<int> mp;
|
||||
bool removeAnnonumousTeamMember = false;
|
||||
int crsIdR = r->getCourseId();
|
||||
int crsIdROld = oldR ? oldR->getCourseId() : 0;
|
||||
|
||||
if (r->getTeam()) {
|
||||
pTeam otherTeam = r->getTeam();
|
||||
int otherLeg = r->getLegNumber();
|
||||
otherTeam->setRunner(otherLeg, oldR, true);
|
||||
if (oldR)
|
||||
if (oldR) {
|
||||
oldR->setCourseId(crsIdR);
|
||||
oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
|
||||
}
|
||||
otherTeam->checkValdParSetup();
|
||||
otherTeam->apply(oBase::ChangeType::Update, nullptr);
|
||||
otherTeam->synchronize(true);
|
||||
@ -1927,11 +1931,13 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
|
||||
else
|
||||
oldR->setClassId(r->getClassId(false), true);
|
||||
removeAnnonumousTeamMember = oldR->isAnnonumousTeamMember();
|
||||
oldR->setCourseId(crsIdR);
|
||||
oldR->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
|
||||
oldR->synchronize(true);
|
||||
}
|
||||
|
||||
t->setRunner(leg, r, true);
|
||||
r->setCourseId(crsIdROld);
|
||||
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
|
||||
t->checkValdParSetup();
|
||||
t->apply(oBase::ChangeType::Update, nullptr);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
520
code/Table.cpp
520
code/Table.cpp
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -90,10 +90,8 @@ Table::~Table(void)
|
||||
}
|
||||
|
||||
void Table::clearCellSelection(gdioutput *gdi) {
|
||||
upperRow = -1;
|
||||
lowerRow = -1;
|
||||
upperCol = -1;
|
||||
lowerCol = -1;
|
||||
sel.reset();
|
||||
selScreen.reset();
|
||||
if (gdi) {
|
||||
HDC hDC = GetDC(gdi->getHWNDTarget());
|
||||
clearSelectionBitmap(gdi, hDC);
|
||||
@ -183,6 +181,7 @@ void Table::addRow(int rowId, oBase *object)
|
||||
return;
|
||||
}
|
||||
|
||||
dataRowToIndex.clear();
|
||||
TableRow tr(nTitles, object);
|
||||
tr.height=rowHeight;
|
||||
tr.id = rowId;
|
||||
@ -244,7 +243,9 @@ void Table::filter(int col, const wstring &filt, bool forceFilter)
|
||||
|
||||
if (filt==oldFilter && (!forceFilter || filt.empty()))
|
||||
return;
|
||||
else if (wcsncmp(oldFilter.c_str(), filt.c_str(), oldFilter.length())==0) {
|
||||
dataRowToIndex.clear();
|
||||
|
||||
if (wcsncmp(oldFilter.c_str(), filt.c_str(), oldFilter.length())==0) {
|
||||
if (sortIndex.empty())
|
||||
return;
|
||||
//Filter more...
|
||||
@ -252,6 +253,7 @@ void Table::filter(int col, const wstring &filt, bool forceFilter)
|
||||
baseIndex[0]=sortIndex[0];
|
||||
baseIndex[1]=sortIndex[1];
|
||||
swap(baseIndex, sortIndex);
|
||||
sortIndex.reserve(baseIndex.size());
|
||||
Titles[col].filter=filt;
|
||||
}
|
||||
else {
|
||||
@ -293,16 +295,20 @@ bool Table::compareRow(int indexA, int indexB) const {
|
||||
//return Data[indexA].key < Data[indexB].key;
|
||||
}
|
||||
|
||||
void Table::sort(int col)
|
||||
void Table::sort(int col, bool forceDirection)
|
||||
{
|
||||
int origCol = col;
|
||||
bool reverse = col < 0;
|
||||
if (col < 0)
|
||||
col = -(10+col);
|
||||
|
||||
if (sortIndex.size()<2)
|
||||
return;
|
||||
|
||||
dataRowToIndex.clear();
|
||||
|
||||
currentSortColumn=col;
|
||||
if (PrevSort!=col && PrevSort!=-(10+col)) {
|
||||
if (forceDirection || (PrevSort!=col && PrevSort!=-(10+col))) {
|
||||
if (Titles[col].isnumeric) {
|
||||
bool hasDeci = false;
|
||||
for(size_t k=2; k<sortIndex.size(); k++){
|
||||
@ -420,7 +426,7 @@ void Table::sort(int col)
|
||||
//DWORD sEnd = GetTickCount();
|
||||
//string st = itos(sEnd-sStart);
|
||||
TableSortIndex::table = 0;
|
||||
PrevSort=col;
|
||||
PrevSort = origCol;
|
||||
|
||||
if (reverse)
|
||||
std::reverse(sortIndex.begin()+2, sortIndex.end());
|
||||
@ -434,7 +440,7 @@ void Table::sort(int col)
|
||||
PrevSort=col;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int TablesCB(gdioutput *gdi, int type, void *data) {
|
||||
if (type!=GUI_LINK || gdi->Tables.empty())
|
||||
return 0;
|
||||
@ -451,7 +457,7 @@ int TablesCB(gdioutput *gdi, int type, void *data) {
|
||||
|
||||
gdi->refresh();
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
void Table::getDimension(gdioutput &gdi, int &dx, int &dy, bool filteredResult) const
|
||||
{
|
||||
@ -507,7 +513,7 @@ void Table::restoreCell(HDC hDC, const TableCell &cell)
|
||||
}
|
||||
}
|
||||
|
||||
void Table::moveCell(HDC hDC, gdioutput &gdi, const TableCell &cell, int dx, int dy)
|
||||
void Table::moveCell(HDC hDC, gdioutput &gdi, int col, const TableCell &cell, int dx, int dy)
|
||||
{
|
||||
RECT rc=cell.absPos;
|
||||
rc.left+=dx; rc.right+=dx;
|
||||
@ -526,7 +532,7 @@ void Table::moveCell(HDC hDC, gdioutput &gdi, const TableCell &cell, int dx, int
|
||||
dx=0;
|
||||
dy=0;
|
||||
}
|
||||
highlightCell(hDC, gdi, cell, RGB(255, 0,0), dx, dy);
|
||||
highlightCell(hDC, gdi, col, cell, RGB(255, 0,0), dx, dy);
|
||||
}
|
||||
|
||||
void Table::stopMoveCell(HDC hDC, const TableCell &cell, int dx, int dy)
|
||||
@ -554,94 +560,94 @@ void Table::stopMoveCell(HDC hDC, const TableCell &cell, int dx, int dy)
|
||||
|
||||
bool Table::mouseMove(gdioutput &gdi, int x, int y)
|
||||
{
|
||||
int row=getRow(y);
|
||||
int col=-1;
|
||||
int row = getRow(y);
|
||||
int col = -1;
|
||||
|
||||
if (row!=-1)
|
||||
col=getColumn(x);
|
||||
if (row != -1)
|
||||
col = getColumn(x);
|
||||
|
||||
HWND hWnd=gdi.getHWNDTarget();
|
||||
HWND hWnd = gdi.getHWNDTarget();
|
||||
|
||||
if (colSelected!=-1) {
|
||||
TableCell &cell=Data[0].cells[colSelected];
|
||||
HDC hDC=GetDC(hWnd);
|
||||
if (colSelected != -1) {
|
||||
TableCell &cell = Data[0].cells[colSelected];
|
||||
HDC hDC = GetDC(hWnd);
|
||||
|
||||
restoreCell(hDC, cell);
|
||||
|
||||
if (col!=highCol) {
|
||||
if (unsigned(highRow)<Data.size() && unsigned(highCol)<nTitles)
|
||||
if (col != highCol) {
|
||||
if (unsigned(highRow) < Data.size() && unsigned(highCol) < nTitles)
|
||||
redrawCell(gdi, hDC, highCol, highRow);
|
||||
|
||||
DWORD c=RGB(240, 200, 140);
|
||||
if (unsigned(col)<nTitles)
|
||||
highlightCell(hDC, gdi, Data[0].cells[col], c, 0,0);
|
||||
DWORD c = RGB(240, 220, 180);
|
||||
if (unsigned(col) < nTitles)
|
||||
highlightCell(hDC, gdi, col, Data[0].cells[col], c, 0, 0);
|
||||
}
|
||||
|
||||
//highlightCell(hDC, cell, RGB(255,0,0), x-startX, y-startY);
|
||||
moveCell(hDC, gdi, cell, x-startX, y-startY);
|
||||
moveCell(hDC, gdi, colSelected, cell, x - startX, y - startY);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
highRow=0;
|
||||
highCol=col;
|
||||
highRow = 0;
|
||||
highCol = col;
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(hWnd, &rc);
|
||||
|
||||
if (x<=rc.left || x>=rc.right || y<rc.top || y>rc.bottom)
|
||||
row=-1;
|
||||
if (x <= rc.left || x >= rc.right || y<rc.top || y>rc.bottom)
|
||||
row = -1;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (startSelect) {
|
||||
int c = getColumn(x, true);
|
||||
if (c != -1)
|
||||
upperCol = c;
|
||||
sel.upperCol = c, selScreen.upperCol = -1;
|
||||
c = getRow(y, true);
|
||||
if (c != -1 && c>=0) {
|
||||
upperRow = max<int>(c, 2);
|
||||
if (c != -1 && c >= 0) {
|
||||
sel.upperRow = max<int>(c, 2), selScreen.upperRow = -1;
|
||||
}
|
||||
|
||||
HDC hDC=GetDC(hWnd);
|
||||
if (unsigned(highRow)<Data.size() && unsigned(highCol)<Titles.size())
|
||||
HDC hDC = GetDC(hWnd);
|
||||
if (unsigned(highRow) < Data.size() && unsigned(highCol) < Titles.size())
|
||||
redrawCell(gdi, hDC, highCol, highRow);
|
||||
highRow = -1;
|
||||
drawSelection(gdi, hDC, false);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
scrollToCell(gdi, upperRow, upperCol);
|
||||
scrollToCell(gdi, sel.upperRow, sel.upperCol);
|
||||
ret = true;
|
||||
}
|
||||
else if (row>=0 && col>=0) {
|
||||
POINT pt = {x, y};
|
||||
else if (row >= 0 && col >= 0) {
|
||||
POINT pt = { x, y };
|
||||
ClientToScreen(hWnd, &pt);
|
||||
HWND hUnder = WindowFromPoint(pt);
|
||||
|
||||
if (hUnder == hWnd) {
|
||||
//int index=sortIndex[row].index;
|
||||
TableRow &trow=Data[row];
|
||||
TableCell &cell=trow.cells[col];
|
||||
TableRow &trow = Data[row];
|
||||
TableCell &cell = trow.cells[col];
|
||||
|
||||
if (highRow!=row || highCol!=col) {
|
||||
if (highRow != row || highCol != col) {
|
||||
|
||||
HDC hDC=GetDC(hWnd);
|
||||
HDC hDC = GetDC(hWnd);
|
||||
|
||||
if (unsigned(highRow)<Data.size() && unsigned(highCol)<Titles.size())
|
||||
if (unsigned(highRow) < Data.size() && unsigned(highCol) < Titles.size())
|
||||
redrawCell(gdi, hDC, highCol, highRow);
|
||||
|
||||
if (row >= 2) {
|
||||
DWORD c;
|
||||
if (cell.canEdit)
|
||||
c=RGB(240, 240, 150);
|
||||
c = RGB(240, 240, 150);
|
||||
else
|
||||
c=RGB(240, 200, 140);
|
||||
c = RGB(240, 200, 140);
|
||||
|
||||
highlightCell(hDC, gdi, cell, c, 0,0);
|
||||
highlightCell(hDC, gdi, col, cell, c, 0, 0);
|
||||
}
|
||||
|
||||
ReleaseDC(hWnd, hDC);
|
||||
SetCapture(hWnd);
|
||||
highCol=col;
|
||||
highRow=row;
|
||||
highCol = col;
|
||||
highRow = row;
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
@ -650,33 +656,33 @@ bool Table::mouseMove(gdioutput &gdi, int x, int y)
|
||||
if (ret)
|
||||
return true;
|
||||
|
||||
if (unsigned(highRow)<Data.size() && unsigned(highCol)<Titles.size()) {
|
||||
if (unsigned(highRow) < Data.size() && unsigned(highCol) < Titles.size()) {
|
||||
ReleaseCapture();
|
||||
HDC hDC=GetDC(hWnd);
|
||||
HDC hDC = GetDC(hWnd);
|
||||
redrawCell(gdi, hDC, highCol, highRow);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
highRow=-1;
|
||||
highRow = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Table::mouseLeftUp(gdioutput &gdi, int x, int y)
|
||||
{
|
||||
if (colSelected!=-1) {
|
||||
if (colSelected != -1) {
|
||||
|
||||
if (hdcCompatible) {
|
||||
TableCell &cell=Data[0].cells[colSelected];
|
||||
HWND hWnd=gdi.getHWNDTarget();
|
||||
HDC hDC=GetDC(hWnd);
|
||||
stopMoveCell(hDC, cell, x-startX, y-startY);
|
||||
TableCell &cell = Data[0].cells[colSelected];
|
||||
HWND hWnd = gdi.getHWNDTarget();
|
||||
HDC hDC = GetDC(hWnd);
|
||||
stopMoveCell(hDC, cell, x - startX, y - startY);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
//return true;
|
||||
}
|
||||
|
||||
if (highRow==0 && colSelected==highCol) {
|
||||
colSelected=-1;
|
||||
if (highRow == 0 && colSelected == highCol) {
|
||||
colSelected = -1;
|
||||
gdi.setWaitCursor(true);
|
||||
sort(highCol);
|
||||
sort(highCol, false);
|
||||
gdi.setWaitCursor(false);
|
||||
gdi.refresh();
|
||||
mouseMove(gdi, x, y);
|
||||
@ -685,22 +691,22 @@ bool Table::mouseLeftUp(gdioutput &gdi, int x, int y)
|
||||
else {
|
||||
moveColumn(colSelected, highCol);
|
||||
InvalidateRect(gdi.getHWNDTarget(), 0, false);
|
||||
colSelected=-1;
|
||||
colSelected = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
upperCol = getColumn(x);
|
||||
upperRow = getRow(y);
|
||||
sel.upperCol = getColumn(x), selScreen.upperCol = -1;
|
||||
sel.upperRow = getRow(y), selScreen.upperRow = -1;
|
||||
startSelect = false;
|
||||
ReleaseCapture();
|
||||
gdi.refreshFast();
|
||||
}
|
||||
colSelected=-1;
|
||||
colSelected = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
int tblSelectionCB(gdioutput *gdi, int type, void *data)
|
||||
{
|
||||
int tblSelectionCB(gdioutput *gdi, int type, void *data) {
|
||||
if (type == GUI_LISTBOX) {
|
||||
ListBoxInfo lbi = *static_cast<ListBoxInfo *>(data);
|
||||
Table &t = gdi->getTable();
|
||||
@ -744,9 +750,18 @@ bool Table::keyCommand(gdioutput &gdi, KeyCommandCode code) {
|
||||
exportClipboard(gdi);
|
||||
else if (code == KC_PASTE && hEdit == 0) {
|
||||
importClipboard(gdi);
|
||||
}else if (code == KC_DELETE && hEdit == 0) {
|
||||
}
|
||||
else if (code == KC_DELETE && hEdit == 0) {
|
||||
deleteSelection(gdi);
|
||||
}
|
||||
else if (code == KC_MARKALL && hEdit == 0) {
|
||||
markAll(true);
|
||||
gdi.refresh();
|
||||
}
|
||||
else if (code == KC_CLEARALL && hEdit == 0) {
|
||||
markAll(false);
|
||||
gdi.refresh();
|
||||
}
|
||||
else if (code == KC_REFRESH) {
|
||||
gdi.setWaitCursor(true);
|
||||
update();
|
||||
@ -858,14 +873,11 @@ bool Table::mouseLeftDown(gdioutput &gdi, int x, int y) {
|
||||
colSelected=highCol;
|
||||
startX=x;
|
||||
startY=y;
|
||||
//sort(highCol);
|
||||
//gdi.refresh();
|
||||
//mouseMove(gdi, x, y);
|
||||
}
|
||||
else if (highRow==1) {
|
||||
//filter(highCol, "lots");
|
||||
showFilter(gdi);
|
||||
/*
|
||||
RECT rc=Data[1].cells[columns[0]].absPos;
|
||||
//rc.right=rc.left+tableWidth;
|
||||
editRow=highRow;
|
||||
editCol=highCol;
|
||||
|
||||
@ -877,18 +889,158 @@ bool Table::mouseLeftDown(gdioutput &gdi, int x, int y) {
|
||||
SendMessage(hEdit, EM_SETSEL, 0, -1);
|
||||
SetFocus(hEdit);
|
||||
SendMessage(hEdit, WM_SETFONT, (WPARAM) gdi.getGUIFont(), 0);
|
||||
gdi.refresh();
|
||||
gdi.refresh();*/
|
||||
}
|
||||
else {
|
||||
SetFocus(gdi.getHWNDTarget());
|
||||
SetCapture(gdi.getHWNDTarget());
|
||||
lowerCol = getColumn(x);
|
||||
lowerRow = getRow(y);
|
||||
sel.lowerCol = getColumn(x), selScreen.lowerCol = -1;
|
||||
sel.lowerRow = getRow(y), selScreen.lowerRow = -1;
|
||||
startSelect = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Table::showFilter(gdioutput &gdi) {
|
||||
RECT rc = Data[1].cells[columns[0]].absPos;
|
||||
editRow = 1;
|
||||
editCol = highCol;
|
||||
|
||||
hEdit = CreateWindowEx(0, L"EDIT", Titles[highCol].filter.c_str(),
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | WS_BORDER,
|
||||
rc.left + 105, rc.top, tableWidth - 105, (rc.bottom - rc.top - 1), gdi.getHWNDTarget(),
|
||||
0, hInst, 0);
|
||||
drawFilterLabel = true;
|
||||
SendMessage(hEdit, EM_SETSEL, 0, -1);
|
||||
SetFocus(hEdit);
|
||||
SendMessage(hEdit, WM_SETFONT, (WPARAM)gdi.getGUIFont(), 0);
|
||||
gdi.refresh();
|
||||
|
||||
}
|
||||
|
||||
bool Table::mouseRightDown(gdioutput &gdi, int x, int y) {
|
||||
//partialCell = true;
|
||||
//clearCellSelection(&gdi);
|
||||
|
||||
if (!destroyEditControl(gdi))
|
||||
return false;
|
||||
|
||||
if (highRow == 0) {
|
||||
colSelected = highCol;
|
||||
}
|
||||
// lowerCol = getColumn(x);
|
||||
// lowerRow = getRow(y);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Table::mouseRightUp(gdioutput &gdi, int x, int y) {
|
||||
|
||||
if (highRow == 0 && colSelected == highCol) {
|
||||
colSelected = -1;
|
||||
|
||||
vector<pair<wstring, int>> menu;
|
||||
menu.emplace_back(L"Sortera stigande", 1);
|
||||
menu.emplace_back(L"Sortera fallande", 2);
|
||||
menu.emplace_back(L"", 0);
|
||||
menu.emplace_back(L"Markera kolumn", 3);
|
||||
menu.emplace_back(L"Filtrera", 5);
|
||||
menu.emplace_back(L"Dölj", 4);
|
||||
|
||||
int res = gdi.popupMenu(x, y, menu);
|
||||
|
||||
switch (res) {
|
||||
case 2: {
|
||||
sort(-(highCol+10), true);
|
||||
gdi.refresh();
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
sort(highCol, true);
|
||||
gdi.refresh();
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int col = highCol;
|
||||
if (isFullColumnSelected()) {
|
||||
sel.upperCol = max({ sel.upperCol, sel.lowerCol, col });
|
||||
sel.lowerCol = min({ sel.upperCol, sel.lowerCol, col });
|
||||
}
|
||||
else {
|
||||
sel.upperCol = sel.lowerCol = col;
|
||||
}
|
||||
if (sortIndex.size() > 2) {
|
||||
sel.upperRow = sortIndex[2].index;
|
||||
sel.lowerRow = sortIndex[sortIndex.size()-1].index;
|
||||
}
|
||||
selScreen.reset();
|
||||
gdi.refresh();
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
columns.erase(find(columns.begin(), columns.end(), highCol));
|
||||
doAutoSelectColumns = false;
|
||||
gdi.refresh();
|
||||
break;
|
||||
case 5:
|
||||
showFilter(gdi);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*POINT pt;
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
ClientToScreen(gdi.getHWNDTarget(), &pt);
|
||||
|
||||
HMENU hm = CreatePopupMenu();
|
||||
AppendMenu(hm, MF_STRING, 1, lang.tl("Sortera stigande").c_str());
|
||||
AppendMenu(hm, MF_STRING, 2, L"Select");
|
||||
int res = TrackPopupMenuEx(hm, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
|
||||
pt.x, pt.y, gdi.getHWNDTarget(), nullptr);
|
||||
|
||||
DestroyMenu(hm);*/
|
||||
}
|
||||
// lowerCol = getColumn(x);
|
||||
// lowerRow = getRow(y);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Table::isFullColumnSelected() const {
|
||||
if (sortIndex.size() < 2)
|
||||
return false;
|
||||
return (sel.upperRow == sortIndex[2].index &&
|
||||
sel.lowerRow == sortIndex[sortIndex.size() - 1].index) ||
|
||||
(sel.lowerRow == sortIndex[2].index &&
|
||||
sel.upperRow == sortIndex[sortIndex.size() - 1].index);
|
||||
}
|
||||
|
||||
void Table::markAll(bool doSelect) {
|
||||
if (doSelect) {
|
||||
sel.lowerCol = columns.front();
|
||||
sel.upperCol = columns.back();
|
||||
if (sortIndex.size() > 2) {
|
||||
sel.upperRow = sortIndex[2].index;
|
||||
sel.lowerRow = sortIndex.back().index;
|
||||
}
|
||||
selScreen.reset();
|
||||
}
|
||||
else {
|
||||
sel.reset();
|
||||
selScreen.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool Table::mouseMidDown(gdioutput &gdi, int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Table::mouseMidUp(gdioutput &gdi, int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Table::mouseLeftDblClick(gdioutput &gdi, int x, int y)
|
||||
{
|
||||
clearCellSelection(&gdi);
|
||||
@ -1061,21 +1213,21 @@ void drawSymbol(gdioutput &gdi, HDC hDC, int height,
|
||||
}
|
||||
|
||||
|
||||
void Table::highlightCell(HDC hDC, gdioutput &gdi, const TableCell &cell, DWORD color, int dx, int dy)
|
||||
void Table::highlightCell(HDC hDC, gdioutput &gdi, int col, const TableCell &cell, DWORD color, int dx, int dy)
|
||||
{
|
||||
SelectObject(hDC, GetStockObject(DC_BRUSH));
|
||||
SelectObject(hDC, GetStockObject(NULL_PEN));
|
||||
|
||||
SetDCBrushColor(hDC, color);
|
||||
|
||||
RECT rc=cell.absPos;
|
||||
rc.left+=dx;
|
||||
rc.right+=dx;
|
||||
rc.top+=dy;
|
||||
rc.bottom+=dy;
|
||||
RECT rc = cell.absPos;
|
||||
rc.left += dx;
|
||||
rc.right += dx - 1;
|
||||
rc.top += dy;
|
||||
rc.bottom += dy;
|
||||
|
||||
Rectangle(hDC, rc.left+1, rc.top,
|
||||
rc.right+2, rc.bottom);
|
||||
Rectangle(hDC, rc.left + 2, rc.top+2,
|
||||
rc.right + 1, rc.bottom-1);
|
||||
|
||||
TextInfo ti;
|
||||
|
||||
@ -1090,9 +1242,13 @@ void Table::highlightCell(HDC hDC, gdioutput &gdi, const TableCell &cell, DWORD
|
||||
else {
|
||||
gdi.formatString(ti, hDC);
|
||||
SetBkMode(hDC, TRANSPARENT);
|
||||
rc.left+=4;
|
||||
rc.top+=2;
|
||||
DrawText(hDC, cell.contents.c_str(), -1, &rc, DT_LEFT|DT_NOPREFIX);
|
||||
rc.left += 4;
|
||||
rc.top += 2;
|
||||
rc.right -= 2;
|
||||
if (Titles[col].formatRight)
|
||||
DrawText(hDC, cell.contents.c_str(), -1, &rc, DT_RIGHT | DT_NOPREFIX);
|
||||
else
|
||||
DrawText(hDC, cell.contents.c_str(), -1, &rc, DT_LEFT | DT_NOPREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1106,7 +1262,7 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
table_yp=dy-gdi.OffsetY;
|
||||
|
||||
if (currentSortColumn==-1)
|
||||
sort(0);
|
||||
sort(0, false);
|
||||
|
||||
int wi, he;
|
||||
getDimension(gdi, wi, he, true);
|
||||
@ -1129,7 +1285,7 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
xpos[0]=dx-gdi.OffsetX;
|
||||
for (size_t i=1;i<=columns.size();i++)
|
||||
xpos[i]=xpos[i-1]+Titles[columns[i-1]].width+1;
|
||||
|
||||
//xxx
|
||||
//Find first and last visible column
|
||||
while(firstCol<int(columns.size()) && xpos[firstCol+1]<=screen.left)
|
||||
firstCol++;
|
||||
@ -1219,21 +1375,29 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
rc.right=rc.left+Titles[index].width;
|
||||
rc.top=yp+1-gdi.OffsetY;
|
||||
rc.bottom=rc.top+rowHeight;
|
||||
SetDCBrushColor(hDC, RGB(200,200,200));
|
||||
|
||||
bool sortOn = index == PrevSort || PrevSort == -(10 + index);
|
||||
|
||||
SetDCBrushColor(hDC, sortOn ? RGB(207, 218, 203) : RGB(200,200,200));
|
||||
Rectangle(hDC, rc.left, rc.top-1, rc.right+2, rc.bottom);
|
||||
|
||||
if (index == PrevSort || PrevSort == -(10+index) ) {
|
||||
SetDCBrushColor(hDC, RGB(100,250,100));
|
||||
if (sortOn) {
|
||||
auto pp = GetDCPenColor(hDC);
|
||||
SetDCBrushColor(hDC, RGB(183,227,138));
|
||||
SetDCPenColor(hDC, RGB(245, 250, 240));
|
||||
|
||||
POINT pt[3];
|
||||
int r = gdi.scaleLength(4);
|
||||
int r = gdi.scaleLength(6);
|
||||
int s = rc.bottom - rc.top - r;
|
||||
int px = (rc.right + rc.left + s)/2;
|
||||
int s2 = s;
|
||||
|
||||
int px = rc.left + s2 + r;//(rc.right + rc.left + s2)/2;
|
||||
int py = rc.top + r/2;
|
||||
|
||||
pt[0].x = px - s;
|
||||
pt[1].x = px - s/2;
|
||||
pt[0].x = px - s2;
|
||||
pt[1].x = px - s2/2;
|
||||
pt[2].x = px;
|
||||
if (index == PrevSort) {
|
||||
if (index != PrevSort) {
|
||||
pt[0].y = py;
|
||||
pt[1].y = py + s;
|
||||
pt[2].y = py;
|
||||
@ -1245,6 +1409,7 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
}
|
||||
|
||||
Polygon(hDC, pt, 3);
|
||||
SetDCPenColor(hDC, pp);
|
||||
}
|
||||
|
||||
Data[0].cells[index].absPos=rc;
|
||||
@ -1300,19 +1465,62 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
}
|
||||
}
|
||||
|
||||
int rLow = -1, rHigh = -1;
|
||||
int cLow = -1, cHigh = -1;
|
||||
if (!startSelect) {
|
||||
getRowRange(rLow, rHigh);
|
||||
getColRange(cLow, cHigh);
|
||||
}
|
||||
for (size_t k1=max(2, firstRow); int(k1)<lastRow; k1++){
|
||||
int yp=dy+rowHeight*(k1+1);
|
||||
TableRow &tr=Data[sortIndex[k1].index];
|
||||
int xp=xpos[0];
|
||||
|
||||
if (k1&1)
|
||||
SetDCBrushColor(hDC, RGB(230,230, 240));
|
||||
else
|
||||
SetDCBrushColor(hDC, RGB(230,230, 250));
|
||||
|
||||
SelectObject(hDC, GetStockObject(NULL_PEN));
|
||||
Rectangle(hDC, max(xpos[firstCol], int(screen.left)), yp-gdi.OffsetY,
|
||||
min(xpos[lastCol]+1, int(screen.right+2)), yp+rowHeight-gdi.OffsetY);
|
||||
int ydraw = yp - gdi.OffsetY;
|
||||
|
||||
auto setBG = [k1, hDC](bool high) {
|
||||
if (high) {
|
||||
if (k1 & 1)
|
||||
SetDCBrushColor(hDC, RGB(230, 240, 230));
|
||||
else
|
||||
SetDCBrushColor(hDC, RGB(230, 245, 230));
|
||||
}
|
||||
else {
|
||||
if (k1 & 1)
|
||||
SetDCBrushColor(hDC, RGB(230, 230, 240));
|
||||
else
|
||||
SetDCBrushColor(hDC, RGB(230, 230, 250));
|
||||
}
|
||||
};
|
||||
|
||||
setBG(false);
|
||||
|
||||
if (rLow != -1 && k1 >= rLow && k1 <= rHigh && cLow !=-1 && cHigh != -1) {
|
||||
Rectangle(hDC, max(xpos[firstCol], int(screen.left)), ydraw,
|
||||
min(xpos[lastCol] + 1, int(screen.right + 2)), ydraw + rowHeight);
|
||||
|
||||
|
||||
//wstring w = L"cL" + itow(cLow) + L", cH" + itow(cHigh) + L"\n";
|
||||
// OutputDebugString(w.c_str());
|
||||
|
||||
int lowHLC = max(cLow, firstCol);
|
||||
int maxHLC = min(cHigh + 1, lastCol);
|
||||
if (lowHLC < maxHLC) {
|
||||
setBG(true);
|
||||
|
||||
Rectangle(hDC, max(xpos[lowHLC], int(screen.left)), ydraw,
|
||||
min(xpos[maxHLC] + 1, int(screen.right + 2)), ydraw + rowHeight);
|
||||
|
||||
setBG(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Rectangle(hDC, max(xpos[firstCol], int(screen.left)), ydraw,
|
||||
min(xpos[lastCol] + 1, int(screen.right + 2)), ydraw + rowHeight);
|
||||
}
|
||||
|
||||
SelectObject(hDC, GetStockObject(DC_PEN));
|
||||
const int cy=yp+rowHeight-gdi.OffsetY-1;
|
||||
MoveToEx(hDC, xp, cy, 0);
|
||||
@ -1351,7 +1559,6 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
LineTo(hDC, xp, may);
|
||||
}
|
||||
|
||||
|
||||
SelectObject(hDC, GetStockObject(NULL_BRUSH));
|
||||
SelectObject(hDC, GetStockObject(DC_PEN));
|
||||
SetDCPenColor(hDC, RGB(64,64,64));
|
||||
@ -1363,10 +1570,10 @@ void Table::draw(gdioutput &gdi, HDC hDC, int dx, int dy, const RECT &screen)
|
||||
SetDCPenColor(hDC, RGB(64,64,64));
|
||||
Rectangle(hDC, dx-gdi.OffsetX-2, dy-gdi.OffsetY-2,
|
||||
dx+tableWidth-gdi.OffsetX+2, dy+tableHeight-gdi.OffsetY+2);
|
||||
drawSelection(gdi, hDC, true);
|
||||
if (!startSelect)
|
||||
drawSelection(gdi, hDC, true);
|
||||
}
|
||||
|
||||
|
||||
TableCell &Table::getCell(int row, int col) const {
|
||||
if (size_t(row) >= sortIndex.size())
|
||||
throw std::exception("Index out of range");
|
||||
@ -1417,22 +1624,31 @@ void Table::restoreSelection(gdioutput &gdi, HDC hDC) {
|
||||
|
||||
void Table::drawSelection(gdioutput &gdi, HDC hDC, bool forceDraw) {
|
||||
bool modified = false;
|
||||
if (lowerColOld != lowerCol || upperCol != upperColOld ||
|
||||
lowerRow != lowerRowOld || upperRow != upperRowOld) {
|
||||
if (forceDraw) {
|
||||
partialCell = false;
|
||||
}
|
||||
else if (sel != oldSel) {
|
||||
modified = true;
|
||||
restoreSelection(gdi, hDC);
|
||||
}
|
||||
|
||||
if (lowerCol != -1 && upperCol != -1 &&
|
||||
lowerRow != -1 && upperRow != -1 &&
|
||||
(forceDraw || modified)) {
|
||||
TableCell &c1 = Data[lowerRow].cells[lowerCol];
|
||||
TableCell &c2 = Data[upperRow].cells[upperCol];
|
||||
if (!sel.empty() && (forceDraw || modified)) {
|
||||
int rh, rl, ch, cl;
|
||||
getRowRange(rl, rh);
|
||||
getColRange(cl, ch);
|
||||
rl = max(rl, 2);
|
||||
rh = max(rh, 2);
|
||||
|
||||
if (isFullColumnSelected()) {
|
||||
rl = 0;
|
||||
}
|
||||
|
||||
RECT rc;
|
||||
rc.top = min(c1.absPos.top, c2.absPos.top) + gdi.OffsetY;
|
||||
rc.left = min(c1.absPos.left, c2.absPos.left) + gdi.OffsetX;
|
||||
rc.right = max(c1.absPos.right, c2.absPos.right) + 1 + gdi.OffsetX;
|
||||
rc.bottom = max(c1.absPos.bottom, c2.absPos.bottom) + gdi.OffsetY;
|
||||
rc.left = xpos[cl] + gdi.OffsetX;
|
||||
rc.right = xpos[ch + 1] + gdi.OffsetX;
|
||||
|
||||
rc.top = table_yp + rowHeight * (rl + 1) + gdi.OffsetY;
|
||||
rc.bottom = table_yp + rowHeight * (rh + 2) + gdi.OffsetY;
|
||||
|
||||
if (modified) {
|
||||
int cx=rc.right-rc.left + 1;
|
||||
@ -1462,14 +1678,14 @@ void Table::drawSelection(gdioutput &gdi, HDC hDC, bool forceDraw) {
|
||||
|
||||
SelectObject(hDC, GetStockObject(NULL_BRUSH));
|
||||
SelectObject(hDC, GetStockObject(DC_PEN));
|
||||
SetDCPenColor(hDC, RGB(0,0, 128));
|
||||
SetDCPenColor(hDC, RGB(50, 50, 128));
|
||||
Rectangle(hDC, rc.left - gdi.OffsetX, rc.top - gdi.OffsetY,
|
||||
rc.right - gdi.OffsetX, rc.bottom - gdi.OffsetY);
|
||||
SetDCPenColor(hDC, RGB(80, 60, 170));
|
||||
Rectangle(hDC, rc.left - gdi.OffsetX+1, rc.top - gdi.OffsetY+1,
|
||||
rc.right - gdi.OffsetX-1, rc.bottom - gdi.OffsetY-1);
|
||||
|
||||
lowerColOld = lowerCol;
|
||||
upperColOld = upperCol;
|
||||
lowerRowOld = lowerRow;
|
||||
upperRowOld = upperRow;
|
||||
oldSel = sel;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1830,7 +2046,7 @@ void Table::update()
|
||||
|
||||
PrevSort = -1;
|
||||
if (oldSort != -1)
|
||||
sort(oldSort);
|
||||
sort(oldSort, false);
|
||||
commandLock = false; // Reset lock
|
||||
}
|
||||
|
||||
@ -1863,27 +2079,53 @@ void Table::getExportData(int col1, int col2, int row1, int row2, wstring &html,
|
||||
}
|
||||
|
||||
void Table::getRowRange(int &rowLo, int &rowHi) const {
|
||||
int row1 = -1, row2 = -1;
|
||||
for (size_t k = 0; k < sortIndex.size(); k++) {
|
||||
if (upperRow == sortIndex[k].index)
|
||||
row1 = k;
|
||||
if (lowerRow == sortIndex[k].index)
|
||||
row2 = k;
|
||||
if (sel.empty())
|
||||
return;
|
||||
|
||||
if (selScreen.emptyRow()) {
|
||||
if (dataRowToIndex.empty()) {
|
||||
dataRowToIndex.resize(Data.size());
|
||||
for (size_t k = 0; k < sortIndex.size(); k++) {
|
||||
dataRowToIndex[sortIndex[k].index] = k;
|
||||
}
|
||||
}
|
||||
|
||||
int row1 = -1, row2 = -1;
|
||||
row1 = dataRowToIndex[sel.upperRow];
|
||||
row2 = dataRowToIndex[sel.lowerRow];
|
||||
|
||||
rowLo = min(row1, row2);
|
||||
rowHi = max(row1, row2);
|
||||
selScreen.lowerRow = rowLo;
|
||||
selScreen.upperRow = rowHi;
|
||||
}
|
||||
else {
|
||||
rowLo = selScreen.lowerRow;
|
||||
rowHi = selScreen.upperRow;
|
||||
}
|
||||
rowLo = min(row1, row2);
|
||||
rowHi = max(row1, row2);
|
||||
}
|
||||
|
||||
void Table::getColRange(int &colLo, int &colHi) const {
|
||||
int col1 = -1, col2 = -1;
|
||||
for (size_t k = 0; k < columns.size(); k++) {
|
||||
if (upperCol == columns[k])
|
||||
col1 = k;
|
||||
if (lowerCol == columns[k])
|
||||
col2 = k;
|
||||
if (sel.empty())
|
||||
return;
|
||||
|
||||
if (selScreen.emptyCol()) {
|
||||
int col1 = -1, col2 = -1;
|
||||
for (size_t k = 0; k < columns.size(); k++) {
|
||||
if (sel.upperCol == columns[k])
|
||||
col1 = k;
|
||||
if (sel.lowerCol == columns[k])
|
||||
col2 = k;
|
||||
}
|
||||
colLo = min(col1, col2);
|
||||
colHi = max(col1, col2);
|
||||
selScreen.lowerCol = colLo;
|
||||
selScreen.upperCol = colHi;
|
||||
}
|
||||
else {
|
||||
colLo = selScreen.lowerCol;
|
||||
colHi = selScreen.upperCol;
|
||||
}
|
||||
colLo = min(col1, col2);
|
||||
colHi = max(col1, col2);
|
||||
}
|
||||
|
||||
void Table::exportClipboard(gdioutput &gdi)
|
||||
@ -2047,7 +2289,7 @@ void Table::importClipboard(gdioutput &gdi)
|
||||
if (tw > columns.size())
|
||||
throw meosException("Antalet kolumner i urklippet är större än antalet kolumner i tabellen.");
|
||||
|
||||
if (upperRow == -1) {
|
||||
if (sel.emptyRow()) {
|
||||
if (!gdi.ask(L"Vill du klistra in X nya rader i tabellen?#"+itow(table.size())))
|
||||
return;
|
||||
rowS = sortIndex.size(); // Add new rows
|
||||
|
||||
58
code/Table.h
58
code/Table.h
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -163,11 +163,13 @@ protected:
|
||||
size_t dataPointer; // Insertation pointer
|
||||
vector<TableSortIndex> sortIndex;
|
||||
vector<int> columns;
|
||||
mutable vector<int> dataRowToIndex;
|
||||
inthashmap idToRow;
|
||||
//highlight
|
||||
int highRow;
|
||||
int highCol;
|
||||
|
||||
bool isFullColumnSelected() const;
|
||||
|
||||
// Selected columns. For drag/drop and sort
|
||||
int colSelected;
|
||||
int startX;
|
||||
@ -178,16 +180,37 @@ protected:
|
||||
int editCol;
|
||||
|
||||
// Selected rectangle
|
||||
int upperRow;
|
||||
int lowerRow;
|
||||
int upperCol;
|
||||
int lowerCol;
|
||||
struct Range {
|
||||
int upperRow;
|
||||
int lowerRow;
|
||||
int upperCol;
|
||||
int lowerCol;
|
||||
void reset() {
|
||||
upperRow = -1;
|
||||
lowerRow = -1;
|
||||
upperCol = -1;
|
||||
lowerCol = -1;
|
||||
}
|
||||
bool emptyRow() const { return upperRow < 0 || lowerRow < 0; }
|
||||
bool emptyCol() const { return upperCol < 0 || lowerCol < 0; }
|
||||
bool empty() const { return emptyRow() || emptyCol(); }
|
||||
|
||||
int upperRowOld;
|
||||
Range() { reset(); }
|
||||
~Range() = default;
|
||||
bool operator!=(const Range &other) const {
|
||||
return upperRow != other.upperRow || lowerCol != other.lowerCol ||
|
||||
lowerRow != other.lowerRow || upperCol != other.upperCol;
|
||||
}
|
||||
};
|
||||
|
||||
Range sel;
|
||||
mutable Range selScreen;
|
||||
Range oldSel;
|
||||
/* int upperRowOld;
|
||||
int lowerRowOld;
|
||||
int upperColOld;
|
||||
int lowerColOld;
|
||||
|
||||
*/
|
||||
bool startSelect;
|
||||
|
||||
HWND hEdit;
|
||||
@ -205,9 +228,9 @@ protected:
|
||||
bool partialCell;
|
||||
|
||||
//static bool filterMatchString(const string &c, const char *filt);
|
||||
void highlightCell(HDC hDC, gdioutput &gdi, const TableCell &cell, DWORD color, int dx, int dy);
|
||||
void highlightCell(HDC hDC, gdioutput &gdi, int col, const TableCell &cell, DWORD color, int dx, int dy);
|
||||
|
||||
void moveCell(HDC hDC, gdioutput &gdi, const TableCell &cell, int dx, int dy);
|
||||
void moveCell(HDC hDC, gdioutput &gdi, int col, const TableCell &cell, int dx, int dy);
|
||||
void startMoveCell(HDC hDC, const TableCell &cell);
|
||||
void stopMoveCell(HDC hDC, const TableCell &cell, int dx, int dy);
|
||||
void restoreCell(HDC hDC, const TableCell &cell);
|
||||
@ -337,12 +360,20 @@ public:
|
||||
bool mouseLeftUp(gdioutput &gdi, int x, int y);
|
||||
bool mouseLeftDblClick(gdioutput &gdi, int x, int y);
|
||||
|
||||
bool mouseRightDown(gdioutput &gdi, int x, int y);
|
||||
bool mouseRightUp(gdioutput &gdi, int x, int y);
|
||||
bool mouseMidDown(gdioutput &gdi, int x, int y);
|
||||
bool mouseMidUp(gdioutput &gdi, int x, int y);
|
||||
|
||||
|
||||
bool editCell(gdioutput &gdi, int row, int col);
|
||||
|
||||
bool keyCommand(gdioutput &gdi, KeyCommandCode code);
|
||||
void sort(int col);
|
||||
void sort(int col, bool forceDirection);
|
||||
void filter(int col, const wstring &filt, bool forceFilter=false);
|
||||
|
||||
void showFilter(gdioutput &gdi);
|
||||
|
||||
int addColumn(const string &Title, int width, bool isnum, bool formatRight = false);
|
||||
int addColumn(const wstring &translatedTitle, int width, bool isnum, bool formatRight = false);
|
||||
|
||||
@ -355,6 +386,8 @@ public:
|
||||
void set(int column, oBase &owner, int id, const wstring &data,
|
||||
bool canEdit=true, CellType type=cellEdit);
|
||||
|
||||
void markAll(bool doSelect);
|
||||
|
||||
//Reload a row from data
|
||||
void reloadRow(int rowId);
|
||||
|
||||
@ -374,12 +407,9 @@ public:
|
||||
};
|
||||
|
||||
struct TableSortIndex {
|
||||
//TableSortIndex(const Table &t) : table(&t) {}
|
||||
const static Table *table;
|
||||
int index;
|
||||
bool operator<(const TableSortIndex &t) const {return table->compareRow(index,t.index);}
|
||||
//{return table->Data[index].key < table->Data[t.index].key;}
|
||||
//bool operator<=(const TableSortIndex &t) const {return table->Data[index].key <= table->Data[t.index].key;}
|
||||
};
|
||||
|
||||
enum {TID_CLASSNAME, TID_COURSE, TID_NUM, TID_ID, TID_MODIFIED,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#endif // _MSC_VER > 1000
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
BIN
code/bitmap1.bmp
BIN
code/bitmap1.bmp
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 12 KiB |
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1528,10 +1528,10 @@ Exportformat = Export format
|
||||
Filnamnsprefix = Filename prefix
|
||||
Mapp = Folder
|
||||
Mappnamnet får inte vara tomt = Folder name cannot be empty
|
||||
Onlineresultat = On-Line Results
|
||||
Onlineresultat = Online Results
|
||||
Packa stora filer (zip) = Compress large files (zip)
|
||||
Publicera resultat direkt på nätet = Publish results directly on the web
|
||||
Resultat online = Results On-Line
|
||||
Resultat online = Results OnLine
|
||||
Skicka till webben = Send to the web
|
||||
Spara på disk = Save to disk
|
||||
Till exempel X = For example X
|
||||
@ -1541,13 +1541,13 @@ URL måste anges = URL missing
|
||||
Tidsintervall (sekunder) = Time interval (seconds)
|
||||
Antal skickade uppdateringar X (Y kb) = Number of updates X (Y kb)
|
||||
Filen finns redan: X = Destination already exists: X
|
||||
Misslyckades med att ladda upp onlineresultat = Failed to upload on-line results
|
||||
Misslyckades med att ladda upp onlineresultat = Failed to upload online results
|
||||
Onlineservern svarade felaktigt = Remote server gave unexpected reply (Incorrect configuration?)
|
||||
Onlineservern svarade: ZIP stöds ej = Response from remote server: ZIP not supported.
|
||||
Onlineservern svarade: Serverfel = Response from remote server: Server error
|
||||
Onlineservern svarade: Felaktigt lösenord = Response from remote server: Wrong password
|
||||
Onlineservern svarade: Felaktigt tävlings-id = Response from remote server: Wrong competition id
|
||||
Online Results Error X = On-Line Results Error X
|
||||
Online Results Error X = Online Results Error X
|
||||
PDF = PDF
|
||||
ClassTeamLeg = Class, team, leg
|
||||
Okänd = Unknown
|
||||
@ -2534,7 +2534,7 @@ RunnerStageTimeStatus = Competitor's time or status (on stage)
|
||||
EFilterIncludeNotParticipating = Include not participating
|
||||
RunnerStageNumber = Stage number earlier stage
|
||||
Begränsa bredd (klipp text) = Limit width (crop text)
|
||||
Håll ihop med = Keep together
|
||||
Håll ihop med = Keep columns close
|
||||
Justering i sidled = Line adjustment
|
||||
Minsta blockbredd = Least width
|
||||
Relation till föregående = Relation to previous
|
||||
@ -2545,5 +2545,44 @@ prefsDatabaseEngine = Typ av databastabell för nya tävlingar (MySQL)
|
||||
Startgrupperna X och Y överlappar = Start groups X and Y are overlapping
|
||||
Batteristatus = Battery status
|
||||
Low = Low
|
||||
prefsReadVoltageExp = Read SIAC battery voltage
|
||||
Replace[battery] = Replace
|
||||
Spänning = Voltage
|
||||
(kopia) = (copy)
|
||||
Klassen använder banpool = The class has a course pool
|
||||
Filen (X) innehåller IOF-XML tävlingsdata och kan importeras i en existerande tävling = The file (X) contains IOF-XML competition data. You can import it into an existing competition.
|
||||
Filen (X) är en listdefinition = The file (X) is a list definition
|
||||
Filen (X) är en resultatmodul = The file (X) is a result module
|
||||
Filen (X) är inte en MeOS-tävling = The file (X) is not a MeOS competition
|
||||
MeOS-data = MeOS-data
|
||||
List definition = List definition
|
||||
ask:importcopy = A competition (X) with the same origin already exist. You can import the competition as a version of that competition or as a new independent copy. If it is the same event with modifications, it is best to import it as a version.\n\nWould you like to import it as a version?
|
||||
RunnerCardVoltage = Card voltage
|
||||
Applicera för specifik etapp = Apply for specific stage
|
||||
Ljud = Sound
|
||||
Ljudval = Sound selection
|
||||
Markera allt (X) = Select all (X)
|
||||
Markera inget (X) = Select none (X)
|
||||
Ny ledare i klassen = New class leader
|
||||
Sparade automater = Saved machines
|
||||
Spela upp ett ljud för att indikera resultatet av brickavläsningen = Play a sound to indicate the result of the card readout.
|
||||
Status inte OK (röd utgång) = Status not OK (red exit)
|
||||
help:selectsound = Select sounds to play. By default MeOS builtin sounds are played.
|
||||
prefsPlaySound = Play sounds
|
||||
prefsSoundAction = Sound file, action needed
|
||||
prefsSoundLeader = Sound file, class leader
|
||||
prefsSoundNotOK = Sound file, status not OK
|
||||
prefsSoundOK = Sound file, status OK.
|
||||
Åtgärd krävs = Action needed
|
||||
Alla tidigare etapper = All previous stages
|
||||
Dölj = Hide
|
||||
Exempel = Example
|
||||
Filtrera = Filter
|
||||
Markera kolumn = Select column
|
||||
Slå ihop text = Append text (share column)
|
||||
Sortera fallande = Sort decreasing
|
||||
Sortera stigande = Sort increasing
|
||||
Sök symbol = Search for symbol
|
||||
Testa = Test
|
||||
Fel: Använd X i texten där värdet (Y) ska sättas in = Error: Use X in the text where the value (Y) should be used
|
||||
info:teamcourseassignment = The imported file contains forking data for teams. To import this data you must prepare the competition to match the imported file: \n\n1. Ensure all classes are setup with the correct number of legs.\n2. Provide bib numbers in each class. Use Quick Settings on the page Classes and enter the first bib number in each class (meaning automatic bib setting). You can also import the teams first and assign bibs as usual.\n3. Import the courses. You can import this file several times if needed to update the forking.
|
||||
Försvunnen = Missing
|
||||
|
||||
2289
code/french.lng
2289
code/french.lng
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -38,6 +38,8 @@ enum KeyCommandCode {
|
||||
KC_SPEEDUP,
|
||||
KC_SLOWDOWN,
|
||||
KC_AUTOCOMPLETE,
|
||||
KC_MARKALL,
|
||||
KC_CLEARALL
|
||||
};
|
||||
|
||||
/** Enum used to stack GUI command control, "command line wizard" */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -2376,13 +2376,13 @@ void gdioutput::processListMessage(ListBoxInfo &bi, WPARAM wParam)
|
||||
|
||||
LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
{
|
||||
if (iMessage==WM_COMMAND) {
|
||||
if (iMessage == WM_COMMAND) {
|
||||
WORD hwParam = HIWORD(wParam);
|
||||
HWND hWnd=(HWND)lParam;
|
||||
if (hwParam==EN_CHANGE) {
|
||||
HWND hWnd = (HWND)lParam;
|
||||
if (hwParam == EN_CHANGE) {
|
||||
list<TableInfo>::iterator tit;
|
||||
if (useTables)
|
||||
for (tit=Tables.begin(); tit!=Tables.end(); ++tit)
|
||||
for (tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->inputChange(*this, hWnd))
|
||||
return 0;
|
||||
}
|
||||
@ -2392,8 +2392,8 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
//for (it=BI.begin(); it != BI.end(); ++it) {
|
||||
unordered_map<HWND, ButtonInfo*>::iterator it = biByHwnd.find(HWND(lParam));
|
||||
|
||||
// if (it->hWnd==hWnd) {
|
||||
if ( it != biByHwnd.end() ) {
|
||||
// if (it->hWnd==hWnd) {
|
||||
if (it != biByHwnd.end()) {
|
||||
ButtonInfo &bi = *it->second;
|
||||
processButtonMessage(bi, wParam);
|
||||
return 0;
|
||||
@ -2431,62 +2431,62 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iMessage==WM_MOUSEMOVE) {
|
||||
else if (iMessage == WM_MOUSEMOVE) {
|
||||
POINT pt;
|
||||
pt.x=(signed short)LOWORD(lParam);
|
||||
pt.y=(signed short)HIWORD(lParam);
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
list<TableInfo>::iterator tit;
|
||||
|
||||
bool GotCapture=false;
|
||||
bool GotCapture = false;
|
||||
|
||||
if (useTables)
|
||||
for (tit=Tables.begin(); tit!=Tables.end(); ++tit)
|
||||
for (tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
GotCapture = tit->table->mouseMove(*this, pt.x, pt.y) || GotCapture;
|
||||
|
||||
if (GotCapture)
|
||||
return 0;
|
||||
|
||||
list<InfoBox>::iterator it=IBox.begin();
|
||||
list<InfoBox>::iterator it = IBox.begin();
|
||||
|
||||
|
||||
while (it != IBox.end()) {
|
||||
if (PtInRect(&it->TextRect, pt) && (it->callBack || it->hasEventHandler())) {
|
||||
SetCursor(LoadCursor(NULL, IDC_HAND));
|
||||
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawBoxText(hDC, it->TextRect, *it, true);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
SetCapture(hWndTarget);
|
||||
GotCapture=true;
|
||||
it->HasTCapture=true;
|
||||
GotCapture = true;
|
||||
it->HasTCapture = true;
|
||||
}
|
||||
else {
|
||||
if (it->HasTCapture) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawBoxText(hDC, it->TextRect, *it, false);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
if (!GotCapture)
|
||||
ReleaseCapture();
|
||||
it->HasTCapture=false;
|
||||
it->HasTCapture = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->HasCapture) {
|
||||
if (GetCapture()!=hWndTarget) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
if (GetCapture() != hWndTarget) {
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawCloseBox(hDC, it->Close, false);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
if (!GotCapture) ReleaseCapture();
|
||||
it->HasCapture=false;
|
||||
it->HasCapture = false;
|
||||
}
|
||||
else if (!PtInRect(&it->Close, pt)) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawCloseBox(hDC, it->Close, false);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
}
|
||||
else {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawCloseBox(hDC, it->Close, true);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
}
|
||||
@ -2494,25 +2494,25 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
++it;
|
||||
}
|
||||
|
||||
for (size_t k=0;k<shownStrings.size();k++) {
|
||||
for (size_t k = 0; k < shownStrings.size(); k++) {
|
||||
TextInfo &ti = *shownStrings[k];
|
||||
if ((!ti.callBack && !ti.hasEventHandler()) || ti.hasTimer)
|
||||
continue;
|
||||
|
||||
if (PtInRect(&ti.textRect, pt)) {
|
||||
if (!ti.highlight){
|
||||
ti.highlight=true;
|
||||
if (!ti.highlight) {
|
||||
ti.highlight = true;
|
||||
InvalidateRect(hWndTarget, &ti.textRect, true);
|
||||
}
|
||||
|
||||
SetCapture(hWndTarget);
|
||||
GotCapture=true;
|
||||
ti.hasCapture=true;
|
||||
GotCapture = true;
|
||||
ti.hasCapture = true;
|
||||
SetCursor(LoadCursor(NULL, IDC_HAND));
|
||||
}
|
||||
else {
|
||||
if (ti.highlight) {
|
||||
ti.highlight=false;
|
||||
ti.highlight = false;
|
||||
InvalidateRect(hWndTarget, &ti.textRect, true);
|
||||
}
|
||||
|
||||
@ -2520,79 +2520,80 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
if (!GotCapture)
|
||||
ReleaseCapture();
|
||||
|
||||
ti.hasCapture=false;
|
||||
ti.hasCapture = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iMessage==WM_LBUTTONDOWN) {
|
||||
else if (iMessage == WM_LBUTTONDOWN) {
|
||||
if (autoCompleteInfo) {
|
||||
autoCompleteInfo.reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
list<InfoBox>::iterator it=IBox.begin();
|
||||
list<InfoBox>::iterator it = IBox.begin();
|
||||
|
||||
POINT pt;
|
||||
pt.x=(signed short)LOWORD(lParam);
|
||||
pt.y=(signed short)HIWORD(lParam);
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
list<TableInfo>::iterator tit;
|
||||
|
||||
if (useTables)
|
||||
for (tit=Tables.begin(); tit!=Tables.end(); ++tit)
|
||||
if (useTables) {
|
||||
for (tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseLeftDown(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(it!=IBox.end()) {
|
||||
while (it != IBox.end()) {
|
||||
if (PtInRect(&it->Close, pt)) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawCloseBox(hDC, it->Close, true);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
SetCapture(hWndTarget);
|
||||
it->HasCapture=true;
|
||||
it->HasCapture = true;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
|
||||
//Handle links
|
||||
for (size_t k=0;k<shownStrings.size();k++) {
|
||||
for (size_t k = 0; k < shownStrings.size(); k++) {
|
||||
TextInfo &ti = *shownStrings[k];
|
||||
if (!ti.callBack && !ti.hasEventHandler())
|
||||
continue;
|
||||
|
||||
if (ti.hasCapture) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
if (PtInRect(&ti.textRect, pt)) {
|
||||
ti.active=true;
|
||||
ti.active = true;
|
||||
RenderString(ti, hDC);
|
||||
}
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iMessage==WM_LBUTTONUP) {
|
||||
else if (iMessage == WM_LBUTTONUP) {
|
||||
list<TableInfo>::iterator tit;
|
||||
|
||||
list<InfoBox>::iterator it=IBox.begin();
|
||||
list<InfoBox>::iterator it = IBox.begin();
|
||||
|
||||
POINT pt;
|
||||
pt.x=(signed short)LOWORD(lParam);
|
||||
pt.y=(signed short)HIWORD(lParam);
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables)
|
||||
for (tit=Tables.begin(); tit!=Tables.end(); ++tit)
|
||||
if (useTables) {
|
||||
for (tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseLeftUp(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
|
||||
while (it!=IBox.end()) {
|
||||
}
|
||||
while (it != IBox.end()) {
|
||||
if (it->HasCapture) {
|
||||
HDC hDC=GetDC(hWndTarget);
|
||||
HDC hDC = GetDC(hWndTarget);
|
||||
drawCloseBox(hDC, it->Close, false);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
ReleaseCapture();
|
||||
it->HasCapture=false;
|
||||
it->HasCapture = false;
|
||||
|
||||
if (PtInRect(&it->Close, pt)) {
|
||||
IBox.erase(it);
|
||||
@ -2602,7 +2603,7 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
}
|
||||
else if (it->HasTCapture) {
|
||||
ReleaseCapture();
|
||||
it->HasTCapture=false;
|
||||
it->HasTCapture = false;
|
||||
|
||||
if (PtInRect(&it->TextRect, pt)) {
|
||||
if (!it->handleEvent(*this, GUI_INFOBOX) && it->callBack)
|
||||
@ -2614,12 +2615,12 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
}
|
||||
|
||||
//Handle links
|
||||
for (size_t k=0;k<shownStrings.size();k++) {
|
||||
for (size_t k = 0; k < shownStrings.size(); k++) {
|
||||
TextInfo &ti = *shownStrings[k];
|
||||
if (!ti.callBack && !ti.hasEventHandler())
|
||||
continue;
|
||||
|
||||
if (ti.hasCapture){
|
||||
if (ti.hasCapture) {
|
||||
ReleaseCapture();
|
||||
ti.hasCapture = false;
|
||||
|
||||
@ -2630,7 +2631,7 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
cmd = "click(\"" + ti.id + "\", " + itos(ti.getExtraInt()) + "); //" + toUTF8(ti.text);
|
||||
else
|
||||
cmd = "click(\"" + ti.id + "\"); //" + toUTF8(ti.text);
|
||||
ti.active=false;
|
||||
ti.active = false;
|
||||
RenderString(ti);
|
||||
if (!ti.handleEvent(*this, GUI_LINK))
|
||||
ti.callBack(this, GUI_LINK, &ti);
|
||||
@ -2639,24 +2640,68 @@ LRESULT gdioutput::ProcessMsgWrp(UINT iMessage, LPARAM lParam, WPARAM wParam)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ti.active){
|
||||
ti.active=false;
|
||||
else if (ti.active) {
|
||||
ti.active = false;
|
||||
RenderString(ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iMessage==WM_LBUTTONDBLCLK) {
|
||||
else if (iMessage == WM_LBUTTONDBLCLK) {
|
||||
list<TableInfo>::iterator tit;
|
||||
POINT pt;
|
||||
pt.x=(signed short)LOWORD(lParam);
|
||||
pt.y=(signed short)HIWORD(lParam);
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables)
|
||||
for (tit=Tables.begin(); tit!=Tables.end(); ++tit)
|
||||
for (tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseLeftDblClick(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
|
||||
}
|
||||
else if (iMessage == WM_RBUTTONDOWN) {
|
||||
POINT pt;
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables) {
|
||||
for (auto tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseRightDown(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (iMessage == WM_RBUTTONUP) {
|
||||
POINT pt;
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables) {
|
||||
for (auto tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseRightUp(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (iMessage == WM_MBUTTONDOWN) {
|
||||
POINT pt;
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables) {
|
||||
for (auto tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseMidDown(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (iMessage == WM_MBUTTONUP) {
|
||||
POINT pt;
|
||||
pt.x = (signed short)LOWORD(lParam);
|
||||
pt.y = (signed short)HIWORD(lParam);
|
||||
|
||||
if (useTables) {
|
||||
for (auto tit = Tables.begin(); tit != Tables.end(); ++tit)
|
||||
if (tit->table->mouseMidUp(*this, pt.x, pt.y))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (iMessage == WM_CHAR) {
|
||||
/*list<TableInfo>::iterator tit;
|
||||
if (useTables)
|
||||
@ -3504,6 +3549,23 @@ void gdioutput::adjustDimension(int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
// Alert from main thread (via callback)
|
||||
void gdioutput::delayAlert(const wstring& msg) {
|
||||
if (!delayedAlert.empty())
|
||||
delayedAlert += L", ";
|
||||
if (delayedAlert.length() > 1000)
|
||||
delayedAlert = L"";
|
||||
|
||||
delayedAlert += lang.tl(msg);
|
||||
PostMessage(hWndAppMain, WM_USER + 6, 0, LPARAM(this));
|
||||
}
|
||||
|
||||
wstring gdioutput::getDelayedAlert() {
|
||||
wstring out = L"#" + delayedAlert;
|
||||
delayedAlert.clear();
|
||||
return out;
|
||||
}
|
||||
|
||||
void gdioutput::alert(const string &msg) const
|
||||
{
|
||||
alert(widen(msg));
|
||||
@ -4002,6 +4064,7 @@ void gdioutput::removeString(string id)
|
||||
Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
|
||||
ReleaseDC(hWndTarget, hDC);
|
||||
TL.erase(it);
|
||||
itTL = TL.end();
|
||||
shownStrings.clear();
|
||||
return;
|
||||
}
|
||||
@ -4833,6 +4896,8 @@ bool gdioutput::removeWidget(const string &id)
|
||||
}
|
||||
++iit;
|
||||
}
|
||||
|
||||
removeString(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5757,6 +5822,12 @@ void gdioutput::tableCB(ButtonInfo &bu, Table *t)
|
||||
t->updateDimension(*this);
|
||||
refresh();
|
||||
}
|
||||
else if (bu.id == "tblMarkAll") {
|
||||
t->keyCommand(*this, KC_MARKALL);
|
||||
}
|
||||
else if (bu.id == "tblClearAll") {
|
||||
t->keyCommand(*this, KC_CLEARALL);
|
||||
}
|
||||
else if (bu.id=="tblUpdate") {
|
||||
t->keyCommand(*this, KC_REFRESH);
|
||||
}
|
||||
@ -5799,6 +5870,8 @@ void gdioutput::enableTables()
|
||||
toolbar->addButton("tblPrint", 0, STD_PRINT, "Skriv ut tabellen (X)#Ctrl+P");
|
||||
toolbar->addButton("tblUpdate", 1, 0, "Uppdatera alla värden i tabellen (X)#F5");
|
||||
toolbar->addButton("tblReset", 1, 4, "Återställ tabeldesignen och visa allt");
|
||||
toolbar->addButton("tblMarkAll", 1, 5, "Markera allt (X)#Ctrl+A");
|
||||
toolbar->addButton("tblClearAll", 1, 6, "Markera inget (X)#Ctrl+D");
|
||||
toolbar->addButton("tblCopy", 0, STD_COPY, "Kopiera selektionen till urklipp (X)#Ctrl+C");
|
||||
if (t->canPaste())
|
||||
toolbar->addButton("tblPaste", 0, STD_PASTE, "Klistra in data från urklipp (X)#Ctrl+V");
|
||||
@ -7040,7 +7113,18 @@ DWORD gdioutput::selectColor(wstring &def, DWORD input) {
|
||||
}
|
||||
|
||||
cc.lpCustColors = staticColor;
|
||||
if (ChooseColor(&cc)) {
|
||||
int res = 0;
|
||||
setCommandLock();
|
||||
try {
|
||||
res = ChooseColor(&cc);
|
||||
liftCommandLock();
|
||||
}
|
||||
catch (...) {
|
||||
liftCommandLock();
|
||||
throw;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
wstring co;
|
||||
for (int ix = 0; ix < 16; ix++) {
|
||||
wchar_t bf[16];
|
||||
@ -7053,7 +7137,6 @@ DWORD gdioutput::selectColor(wstring &def, DWORD input) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void gdioutput::setAnimationMode(shared_ptr<AnimationData> &data) {
|
||||
if (animationData && animationData->takeOver(data))
|
||||
return;
|
||||
@ -7118,3 +7201,22 @@ int gdioutput::getPageX() const {
|
||||
else
|
||||
return max(MaxX, xlimit) + scaleLength(60);
|
||||
}
|
||||
|
||||
int gdioutput::popupMenu(int x, int y, const vector<pair<wstring, int>> &menuItems) const {
|
||||
POINT pt;
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
ClientToScreen(getHWNDTarget(), &pt);
|
||||
HMENU hm = CreatePopupMenu();
|
||||
for (auto &me : menuItems) {
|
||||
if (me.first.empty())
|
||||
AppendMenu(hm, MF_SEPARATOR, me.second, L"");
|
||||
else
|
||||
AppendMenu(hm, MF_STRING, me.second, lang.tl(me.first).c_str());
|
||||
}
|
||||
int res = TrackPopupMenuEx(hm, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
|
||||
pt.x, pt.y, getHWNDTarget(), nullptr);
|
||||
|
||||
DestroyMenu(hm);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -289,6 +289,8 @@ protected:
|
||||
shared_ptr<AnimationData> animationData;
|
||||
|
||||
shared_ptr<AutoCompleteInfo> autoCompleteInfo;
|
||||
|
||||
wstring delayedAlert;
|
||||
public:
|
||||
|
||||
AutoCompleteInfo &addAutoComplete(const string &key);
|
||||
@ -571,6 +573,10 @@ public:
|
||||
|
||||
void alert(const string &msg) const;
|
||||
void alert(const wstring &msg) const;
|
||||
// Alert from main thread (via callback)
|
||||
void delayAlert(const wstring& msg);
|
||||
// Get and clear any delayed alert
|
||||
wstring getDelayedAlert();
|
||||
|
||||
void fillDown(){Direction=1;}
|
||||
void fillRight(){Direction=0;}
|
||||
@ -762,8 +768,9 @@ public:
|
||||
|
||||
void closeWindow();
|
||||
|
||||
int popupMenu(int x, int y, const vector<pair<wstring, int>> &menuItems) const;
|
||||
|
||||
void setDBErrorState(bool state);
|
||||
friend int TablesCB(gdioutput *gdi, int type, void *data);
|
||||
friend class Table;
|
||||
friend gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y, bool fixedSize);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -568,8 +568,19 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
|
||||
s = r.getTotalStatusInput();
|
||||
}
|
||||
else if (t && !isQF && r.getLegNumber() > 0) {
|
||||
legInput = t->getLegRunningTime(r.getLegNumber() - 1, true, false) * 10;
|
||||
s = t->getLegStatus(r.getLegNumber() - 1, true, false);
|
||||
int ltu = r.getLegNumber();
|
||||
pClass cls = t->getClassRef(true);
|
||||
if (cls) {
|
||||
LegTypes lt = cls->getLegType(ltu);
|
||||
while (ltu > 0 && (lt == LTParallelOptional || lt == LTParallel|| lt == LTExtra || lt == LTIgnore) ) {
|
||||
ltu--;
|
||||
lt = cls->getLegType(ltu);
|
||||
}
|
||||
}
|
||||
if (ltu > 0) {
|
||||
legInput = t->getLegRunningTime(ltu - 1, true, false) * 10;
|
||||
s = t->getLegStatus(ltu - 1, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalStatus != s) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -509,6 +509,11 @@ pCourse IOF30Interface::findCourse(gdioutput &gdi,
|
||||
|
||||
void IOF30Interface::teamCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
|
||||
const map<wstring, pCourse> &courses) {
|
||||
|
||||
gdi.dropLine();
|
||||
gdi.addString("", 10, "info:teamcourseassignment");
|
||||
gdi.dropLine();
|
||||
|
||||
vector<pTeam> allT;
|
||||
oe.getTeams(0, allT, false);
|
||||
|
||||
@ -1394,6 +1399,102 @@ void IOF30Interface::readStartList(gdioutput &gdi, xmlobject &xo, int &entRead,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void IOF30Interface::readResultList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail) {
|
||||
string ver;
|
||||
xo.getObjectString("iofVersion", ver);
|
||||
if (!ver.empty() && ver > "3.0")
|
||||
gdi.addString("", 0, "Varning, okänd XML-version X#" + ver);
|
||||
|
||||
map<int, vector<LegInfo> > teamClassConfig;
|
||||
|
||||
xmlobject xEvent = xo.getObject("Event");
|
||||
if (xEvent) {
|
||||
readEvent(gdi, xEvent, teamClassConfig);
|
||||
}
|
||||
|
||||
xmlList cResults;
|
||||
xo.getObjects("ClassResult", cResults);
|
||||
|
||||
struct RaceInfo {
|
||||
int courseId;
|
||||
int length;
|
||||
int climb;
|
||||
wstring startName;
|
||||
};
|
||||
|
||||
for (xmlobject &xClassResult : cResults) {
|
||||
|
||||
pClass pc = readClass(xClassResult.getObject("Class"),
|
||||
teamClassConfig);
|
||||
int classId = pc ? pc->getId() : 0;
|
||||
|
||||
map<int, RaceInfo> raceToInfo;
|
||||
|
||||
xmlList courses;
|
||||
xClassResult.getObjects("Course", courses);
|
||||
for (size_t k = 0; k < courses.size(); k++) {
|
||||
int raceNo = courses[k].getObjectInt("raceNumber");
|
||||
if (raceNo > 0)
|
||||
raceNo--;
|
||||
RaceInfo &raceInfo = raceToInfo[raceNo];
|
||||
|
||||
raceInfo.courseId = courses[k].getObjectInt("Id");
|
||||
raceInfo.length = courses[k].getObjectInt("Length");
|
||||
raceInfo.climb = courses[k].getObjectInt("Climb");
|
||||
}
|
||||
|
||||
if (raceToInfo.size() == 1) {
|
||||
RaceInfo &raceInfo = raceToInfo.begin()->second;
|
||||
if (raceInfo.courseId > 0) {
|
||||
if (pc->getCourse() == 0) {
|
||||
pCourse crs = oe.addCourse(pc->getName(), raceInfo.length, raceInfo.courseId);
|
||||
crs->setStart(raceInfo.startName, false);
|
||||
crs->getDI().setInt("Climb", raceInfo.climb);
|
||||
pc->setCourse(crs);
|
||||
crs->synchronize();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (raceToInfo.size() > 1) {
|
||||
}
|
||||
|
||||
xmlList xPResults;
|
||||
xClassResult.getObjects("PersonResult", xPResults);
|
||||
//map<int, pair<wstring, int> > bibPatterns;
|
||||
//oClass::extractBibPatterns(oe, bibPatterns);
|
||||
|
||||
for (size_t k = 0; k < xPResults.size(); k++) {
|
||||
if (readPersonResult(gdi, pc, xPResults[k], 0, teamClassConfig))
|
||||
entRead++;
|
||||
else
|
||||
entFail++;
|
||||
}
|
||||
xmlList tEntries;
|
||||
xClassResult.getObjects("TeamResult", tEntries);
|
||||
for (size_t k = 0; k < tEntries.size(); k++) {
|
||||
//setupClassConfig(classId, tEntries[k], teamClassConfig);
|
||||
entFail++; // Teams not supported
|
||||
}
|
||||
/*
|
||||
//setupRelayClasses(teamClassConfig);
|
||||
if (pc && teamClassConfig.count(pc->getId()) && !teamClassConfig[pc->getId()].empty()) {
|
||||
setupRelayClass(pc, teamClassConfig[pc->getId()]);
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < tEntries.size(); k++) {
|
||||
if (readTeamStart(gdi, pc, tEntries[k], bibPatterns, teamClassConfig))
|
||||
entRead++;
|
||||
else
|
||||
entFail++;
|
||||
}
|
||||
*/
|
||||
pc->synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IOF30Interface::readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail) {
|
||||
string ver;
|
||||
xo.getObjectString("iofVersion", ver);
|
||||
@ -2125,6 +2226,180 @@ pRunner IOF30Interface::readPersonStart(gdioutput &gdi, pClass pc, xmlobject &xo
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
wstring formatStatus(RunnerStatus st, bool hasTime) {
|
||||
switch (st) {
|
||||
case StatusNoTiming:
|
||||
if (!hasTime)
|
||||
break;
|
||||
case StatusOK:
|
||||
return L"OK";
|
||||
case StatusDNS:
|
||||
return L"DidNotStart";
|
||||
case StatusCANCEL:
|
||||
return L"Cancelled";
|
||||
case StatusMP:
|
||||
return L"MissingPunch";
|
||||
case StatusDNF:
|
||||
return L"DidNotFinish";
|
||||
case StatusDQ:
|
||||
return L"Disqualified";
|
||||
case StatusMAX:
|
||||
return L"OverTime";
|
||||
case StatusOutOfCompetition:
|
||||
if (!hasTime)
|
||||
break;
|
||||
case StatusNotCompetiting:
|
||||
return L"NotCompeting";
|
||||
}
|
||||
return L"Inactive";
|
||||
}
|
||||
|
||||
RunnerStatus parseStatus(const wstring &status) {
|
||||
if (status == L"OK")
|
||||
return StatusOK;
|
||||
else if (status == L"DidNotStart")
|
||||
return StatusDNS;
|
||||
else if (status == L"MissingPunch")
|
||||
return StatusMP;
|
||||
else if (status == L"Cancelled")
|
||||
return StatusCANCEL;
|
||||
else if (status == L"DidNotFinish")
|
||||
return StatusDNF;
|
||||
else if (status == L"Disqualified")
|
||||
return StatusDQ;
|
||||
else if (status == L"OverTime")
|
||||
return StatusMAX;
|
||||
else if (status == L"NotCompeting")
|
||||
return StatusOutOfCompetition;
|
||||
|
||||
return StatusUnknown;
|
||||
}
|
||||
|
||||
pRunner IOF30Interface::readPersonResult(gdioutput &gdi, pClass pc, xmlobject &xo, pTeam team,
|
||||
const map<int, vector<LegInfo> > &teamClassConfig) {
|
||||
xmlobject xPers = xo.getObject("Person");
|
||||
pRunner r = 0;
|
||||
if (xPers)
|
||||
r = readPerson(gdi, xPers);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (pc && (r->getClassId(false) == 0 || !r->hasFlag(oAbstractRunner::FlagUpdateClass)))
|
||||
r->setClassId(pc->getId(), true);
|
||||
|
||||
// Club
|
||||
pClub c = readOrganization(gdi, xo.getObject("Organisation"), false);
|
||||
if (!c)
|
||||
c = readOrganization(gdi, xo.getObject("Organization"), false);
|
||||
|
||||
if (c)
|
||||
r->setClubId(c->getId());
|
||||
|
||||
xmlList results;
|
||||
xo.getObjects("Result", results);
|
||||
|
||||
for (size_t k = 0; k < results.size(); k++) {
|
||||
int race = results[k].getObjectInt("raceNumber");
|
||||
pRunner rRace = r;
|
||||
if (race > 1 && r->getNumMulti() > 0) {
|
||||
pRunner rr = r->getMultiRunner(race - 1);
|
||||
if (rr)
|
||||
rRace = rr;
|
||||
}
|
||||
if (rRace) {
|
||||
// Card
|
||||
int cardNo = results[k].getObjectInt("ControlCard");
|
||||
if (cardNo > 0)
|
||||
rRace->setCardNo(cardNo, false);
|
||||
|
||||
wstring bib;
|
||||
results[k].getObjectString("BibNumber", bib);
|
||||
rRace->getDI().setString("Bib", bib);
|
||||
|
||||
xmlobject startTime = results[k].getObject("StartTime");
|
||||
/*
|
||||
if (team) {
|
||||
int leg = starts[k].getObjectInt("Leg");
|
||||
int legorder = starts[k].getObjectInt("LegOrder");
|
||||
int legindex = max(0, leg - 1);
|
||||
map<int, vector<LegInfo> >::const_iterator res = teamClassConfig.find(team->getClassId(false));
|
||||
if (res != teamClassConfig.end()) {
|
||||
legindex = getIndexFromLegPos(leg, legorder, res->second);
|
||||
}
|
||||
team->setRunner(legindex, rRace, false);
|
||||
if (rRace->getClubId() == 0)
|
||||
rRace->setClubId(team->getClubId());
|
||||
|
||||
if (startTime && pc) {
|
||||
pc->setStartType(legindex, STDrawn, false);
|
||||
|
||||
}
|
||||
}*/
|
||||
int st = parseISO8601Time(startTime);
|
||||
rRace->setStartTime(st, true, oBase::ChangeType::Update);
|
||||
|
||||
xmlobject finishTime = results[k].getObject("FinishTime");
|
||||
int ft = parseISO8601Time(finishTime);
|
||||
rRace->setFinishTime(ft);
|
||||
|
||||
wstring status;
|
||||
results[k].getObjectString("Status", status);
|
||||
rRace->setStatus(parseStatus(status), true, oBase::ChangeType::Update);
|
||||
|
||||
xmlList splits;
|
||||
results[k].getObjects("SplitTime", splits);
|
||||
if (!splits.empty()) {
|
||||
pCard card = oe.allocateCard(rRace);
|
||||
card->setCardNo(cardNo);
|
||||
vector<int> controls;
|
||||
wstring s;
|
||||
for (auto &split : splits) {
|
||||
int code = split.getObjectInt("ControlCode");
|
||||
int time = split.getObjectInt("Time");
|
||||
split.getObjectString("status", s);
|
||||
if (s != L"missing")
|
||||
card->addPunch(code, st + time, 0);
|
||||
|
||||
if (s != L"additional")
|
||||
controls.push_back(code);
|
||||
}
|
||||
|
||||
if (ft > 0)
|
||||
card->addPunch(oPunch::PunchFinish, ft, 0);
|
||||
|
||||
//Update to SQL-source
|
||||
card->synchronize();
|
||||
|
||||
if (!controls.empty()) {
|
||||
pCourse c = r->getCourse(true);
|
||||
if (!c)
|
||||
c = oe.addCourse(oe.getAutoCourseName());
|
||||
|
||||
if (c->getNumControls() == 0) {
|
||||
for (int ctrl : controls) {
|
||||
c->addControl(ctrl);
|
||||
}
|
||||
|
||||
c->synchronize();
|
||||
}
|
||||
|
||||
if (pc)
|
||||
pc->setCourse(c);
|
||||
else
|
||||
rRace->setCourseId(c->getId());
|
||||
}
|
||||
|
||||
vector<int> mp;
|
||||
rRace->addPunches(card, mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r->synchronize();
|
||||
return r;
|
||||
}
|
||||
|
||||
void IOF30Interface::readId(const xmlobject &person, int &pid, __int64 &extId) const {
|
||||
wstring sid;
|
||||
pid = 0;
|
||||
@ -3052,34 +3327,6 @@ void IOF30Interface::writeCourseInfo(xmlparser &xml, const oCourse &c) {
|
||||
xml.write("Climb", climb);
|
||||
}
|
||||
|
||||
wstring formatStatus(RunnerStatus st, bool hasTime) {
|
||||
switch (st) {
|
||||
case StatusNoTiming:
|
||||
if (!hasTime)
|
||||
break;
|
||||
case StatusOK:
|
||||
return L"OK";
|
||||
case StatusDNS:
|
||||
return L"DidNotStart";
|
||||
case StatusCANCEL:
|
||||
return L"Cancelled";
|
||||
case StatusMP:
|
||||
return L"MissingPunch";
|
||||
case StatusDNF:
|
||||
return L"DidNotFinish";
|
||||
case StatusDQ:
|
||||
return L"Disqualified";
|
||||
case StatusMAX:
|
||||
return L"OverTime";
|
||||
case StatusOutOfCompetition:
|
||||
if (!hasTime)
|
||||
break;
|
||||
case StatusNotCompetiting:
|
||||
return L"NotCompeting";
|
||||
}
|
||||
return L"Inactive";
|
||||
}
|
||||
|
||||
void IOF30Interface::writePersonResult(xmlparser &xml, const oRunner &r,
|
||||
bool includeCourse, bool teamMember, bool hasInputTime) {
|
||||
if (!teamMember)
|
||||
@ -4087,7 +4334,7 @@ pCourse IOF30Interface::readCourse(const xmlobject &xcrs) {
|
||||
for (size_t k = 0; k < xControls.size(); k++) {
|
||||
string type;
|
||||
xControls[k].getObjectString("type", type);
|
||||
if (type == "Start") {
|
||||
if (type == "Start" && startName.empty()) {
|
||||
wstring idStr;
|
||||
xControls[k].getObjectString("Control", idStr);
|
||||
pControl pStart = oe.getControl(getStartIndex(idStr), false);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -176,6 +176,10 @@ class IOF30Interface {
|
||||
map<int, pair<wstring, int> > &bibPatterns,
|
||||
const map<int, vector<LegInfo> > &teamClassConfig);
|
||||
|
||||
|
||||
pRunner readPersonResult(gdioutput &gdi, pClass pc, xmlobject &xo, pTeam team,
|
||||
const map<int, vector<LegInfo> > &teamClassConfig);
|
||||
|
||||
pTeam getCreateTeam(gdioutput &gdi, const xmlobject &xTeam, int expectedClassId, bool &newTeam);
|
||||
|
||||
static int getIndexFromLegPos(int leg, int legorder, const vector<LegInfo> &setup);
|
||||
@ -310,6 +314,8 @@ public:
|
||||
|
||||
void readStartList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||
|
||||
void readResultList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||
|
||||
void readServiceRequestList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||
|
||||
void readClassList(gdioutput &gdi, xmlobject &xo, int &entRead, int &entFail);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -328,20 +328,28 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
}
|
||||
else if (type == GUI_INPUTCHANGE) {
|
||||
InputInfo &ii = *(InputInfo *)(&data);
|
||||
bool show = false;
|
||||
if (ii.text.length() > 1) {
|
||||
vector<AutoCompleteRecord> rec;
|
||||
MetaList::getAutoComplete(ii.text, rec);
|
||||
if (!rec.empty()) {
|
||||
auto &ac = gdi.addAutoComplete(ii.id);
|
||||
ac.setAutoCompleteHandler(this);
|
||||
ac.setData(rec);
|
||||
ac.show();
|
||||
show = true;
|
||||
if (ii.id == "SearchText") {
|
||||
bool show = false;
|
||||
if (ii.text.length() > 1) {
|
||||
vector<AutoCompleteRecord> rec;
|
||||
MetaList::getAutoComplete(ii.text, rec);
|
||||
if (!rec.empty()) {
|
||||
auto &ac = gdi.addAutoComplete(ii.id);
|
||||
ac.setAutoCompleteHandler(this);
|
||||
ac.setData(rec);
|
||||
ac.show();
|
||||
show = true;
|
||||
}
|
||||
}
|
||||
if (!show) {
|
||||
gdi.clearAutoComplete(ii.id);
|
||||
}
|
||||
}
|
||||
if (!show) {
|
||||
gdi.clearAutoComplete(ii.id);
|
||||
}
|
||||
else if (type == GUI_INPUT) {
|
||||
InputInfo &ii = *(InputInfo *)(&data);
|
||||
if (ii.id == "Text" && ii.text != lastShownExampleText) {
|
||||
showExample(gdi);
|
||||
}
|
||||
}
|
||||
else if (type == GUI_BUTTON) {
|
||||
@ -423,7 +431,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
makeDirty(gdi, MakeDirty, MakeDirty);
|
||||
show(gdi);
|
||||
}
|
||||
else if ( bi.id == "Remove" ) {
|
||||
else if (bi.id == "Remove") {
|
||||
DWORD id;
|
||||
gdi.getData("CurrentId", id);
|
||||
getPosFromId(id, groupIx, lineIx, ix);
|
||||
@ -491,22 +499,8 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
|
||||
mlp.setColor(GDICOLOR(gdi.getExtraInt("Color")));
|
||||
|
||||
if (gdi.isChecked("UseLeg")) {
|
||||
int leg = gdi.getTextNo("Leg");
|
||||
if (newType == lResultModuleNumber || newType == lResultModuleTime ||
|
||||
newType == lResultModuleNumberTeam || newType == lResultModuleTimeTeam) {
|
||||
if (leg < 0 || leg > 1000)
|
||||
throw meosException("X är inget giltigt index#" + itos(leg));
|
||||
mlp.setLeg(leg);
|
||||
}
|
||||
else {
|
||||
if (leg < 1 || leg > 1000)
|
||||
throw meosException("X är inget giltigt sträcknummer#" + itos(leg));
|
||||
mlp.setLeg(leg - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
mlp.setLeg(-1);
|
||||
int leg = readLeg(gdi, newType, true);
|
||||
mlp.setLeg(leg);
|
||||
|
||||
if (gdi.hasWidget("UseResultModule") && gdi.isChecked("UseResultModule"))
|
||||
mlp.setResultModule(currentList->getResultModule());
|
||||
@ -625,8 +619,8 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
if (fileName.empty()) {
|
||||
int ix = 0;
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"xml-data", L"*.xml"));
|
||||
fileName = gdi.browseForSave(ext, L"xml", ix);
|
||||
ext.push_back(make_pair(L"List definition", L"*.meoslist"));
|
||||
fileName = gdi.browseForSave(ext, L"meoslist", ix);
|
||||
if (fileName.empty())
|
||||
return 0;
|
||||
}
|
||||
@ -643,8 +637,8 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
return 0;
|
||||
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
ext.push_back(make_pair(L"xml-data", L"*.xml"));
|
||||
wstring fileName = gdi.browseForOpen(ext, L"xml");
|
||||
ext.push_back(make_pair(L"List definition", L"*.meoslist;*.xml"));
|
||||
wstring fileName = gdi.browseForOpen(ext, L"meoslist");
|
||||
if (fileName.empty())
|
||||
return 0;
|
||||
|
||||
@ -822,18 +816,55 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
|
||||
else if (type==GUI_CLEAR) {
|
||||
return checkSave(gdi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListEditor::readLeg(gdioutput &gdi, EPostType newType, bool checkError) const {
|
||||
if (MetaList::isResultModuleOutput(newType)) {
|
||||
int leg = gdi.getTextNo("Leg");
|
||||
if (leg < 0 || leg > 1000) {
|
||||
if (checkError)
|
||||
throw meosException("X är inget giltigt index#" + itos(leg));
|
||||
else
|
||||
leg = -1;
|
||||
}
|
||||
return leg;
|
||||
}
|
||||
else if (MetaList::isAllStageType(newType)) {
|
||||
int leg = gdi.getSelectedItem("LegSel").first;
|
||||
if (leg >= 1)
|
||||
return leg - 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (gdi.isChecked("UseLeg")) {
|
||||
int leg = gdi.getTextNo("Leg");
|
||||
if (leg < 1 || leg > 1000) {
|
||||
if (checkError)
|
||||
throw meosException("X är inget giltigt sträcknummer#" + itos(leg));
|
||||
else
|
||||
leg = -1;
|
||||
}
|
||||
return leg - 1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void ListEditor::updateType(int iType, gdioutput & gdi) {
|
||||
EPostType type = EPostType(iType);
|
||||
gdi.setTextTranslate("TUseLeg", getIndexDescription(type), true);
|
||||
if (type == lResultModuleNumber || type == lResultModuleTime ||
|
||||
type == lResultModuleNumberTeam || type == lResultModuleTimeTeam) {
|
||||
gdi.check("UseLeg", true);
|
||||
gdi.disableInput("UseLeg");
|
||||
int leg = -1;
|
||||
if (gdi.hasWidget("leg"))
|
||||
leg = gdi.getTextNo("Leg");
|
||||
|
||||
gdi.restore("Example", false);
|
||||
|
||||
if (legStageTypeIndex(gdi, type, leg)) {
|
||||
gdi.setRestorePoint("Example");
|
||||
}
|
||||
if (MetaList::isResultModuleOutput(type)) {
|
||||
if (gdi.hasWidget("UseResultModule")) {
|
||||
gdi.check("UseResultModule", true);
|
||||
gdi.disableInput("UseResultModule");
|
||||
@ -841,10 +872,12 @@ void ListEditor::updateType(int iType, gdioutput & gdi) {
|
||||
gdi.enableInput("Leg");
|
||||
if (gdi.getText("Leg").empty())
|
||||
gdi.setText("Leg", L"0");
|
||||
}
|
||||
else if (MetaList::isAllStageType(type)) {
|
||||
|
||||
}
|
||||
else {
|
||||
gdi.enableInput("UseLeg");
|
||||
if (gdi.getTextNo("Leg") == 0) {
|
||||
if (leg == 0) {
|
||||
gdi.setText("Leg", L"");
|
||||
gdi.enableInput("UseLeg");
|
||||
gdi.enableInput("UseResultModule", true);
|
||||
@ -853,10 +886,7 @@ void ListEditor::updateType(int iType, gdioutput & gdi) {
|
||||
}
|
||||
}
|
||||
|
||||
gdi.restore("Example", false);
|
||||
int margin = gdi.scaleLength(10);
|
||||
showExample(gdi, margin, type);
|
||||
gdi.refreshFast();
|
||||
showExample(gdi, type);
|
||||
}
|
||||
|
||||
void ListEditor::checkUnsaved(gdioutput &gdi) {
|
||||
@ -886,10 +916,8 @@ void ListEditor::updateAlign(gdioutput &gdi, int val) {
|
||||
|
||||
gdi.setInputStatus("Color", val != 1);
|
||||
gdi.setInputStatus("Fonts", val != 1);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
checkUnsaved(gdi);
|
||||
gdi.restore("EditList", false);
|
||||
@ -918,7 +946,10 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
if (ix + 1 == currentList->getNumPostsOnLine(groupIx, lineIx))
|
||||
gdi.setInputStatus("MoveRight", false);
|
||||
|
||||
gdi.dropLine(3);
|
||||
gdi.dropLine(1);
|
||||
int boxY = gdi.getCY();
|
||||
gdi.dropLine(2);
|
||||
|
||||
gdi.popX();
|
||||
vector< pair<wstring, size_t> > types;
|
||||
int currentType;
|
||||
@ -940,7 +971,6 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
|
||||
sort(types.begin(), types.end());
|
||||
gdi.pushX();
|
||||
int boxY = gdi.getCY();
|
||||
gdi.fillRight();
|
||||
gdi.addString("", 0, L"Typ:");
|
||||
gdi.fillDown();
|
||||
@ -958,7 +988,8 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
gdi.dropLine(-1);
|
||||
gdi.addItem("Type", types);
|
||||
gdi.selectItemByData("Type", currentType);
|
||||
gdi.addInput("Text", mlp.getText(), 16, 0, L"Egen text:", L"Använd symbolen X där MeOS ska fylla i typens data.");
|
||||
gdi.addInput("Text", mlp.getText(), 16, editListCB,
|
||||
L"Egen text:", L"Använd symbolen X där MeOS ska fylla i typens data.");
|
||||
gdi.setInputFocus("Text", true);
|
||||
((InputInfo *)gdi.setText("SearchText", getSearchString()))->setFgColor(colorGreyBlue);
|
||||
int boxX = gdi.getCX();
|
||||
@ -972,21 +1003,28 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
gdi.popX();
|
||||
}
|
||||
|
||||
xpUseLeg = gdi.getCX();
|
||||
ypUseLeg = gdi.getCY();
|
||||
|
||||
int leg = mlp.getLeg();
|
||||
gdi.addCheckbox("UseLeg", getIndexDescription(storedType), editListCB, leg != -1);
|
||||
gdi.dropLine(-0.2);
|
||||
gdi.setCX(gdi.getCX() + gdi.getLineHeight() * 5);
|
||||
if (storedType == lResultModuleNumber || storedType == lResultModuleTime || storedType == lResultModuleTimeTeam || storedType == lResultModuleNumberTeam)
|
||||
gdi.addInput("Leg", leg >= 0 ? itow(leg) : L"0", 4);
|
||||
|
||||
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("Leg", leg >= 0 ? itow(leg + 1) : L"", 4);
|
||||
gdi.addInput(xpUseLeg + dx, ypUseLeg + dy, "Leg", leg >= 0 ? itow(leg + 1) : L"", 4);
|
||||
|
||||
gdi.enableInput("Leg", leg != -1);
|
||||
|
||||
if (storedType == lResultModuleNumber || storedType == lResultModuleTime ||
|
||||
storedType == lResultModuleTimeTeam || storedType == lResultModuleNumberTeam) {
|
||||
gdi.check("UseLeg", true);
|
||||
gdi.disableInput("UseLeg");
|
||||
gdi.setInputStatus("Leg", leg != -1);
|
||||
*/
|
||||
if (MetaList::isResultModuleOutput(storedType)) {
|
||||
//gdi.check("UseLeg", true);
|
||||
//gdi.disableInput("UseLeg");
|
||||
if (gdi.hasWidget("UseResultModule")) {
|
||||
gdi.check("UseResultModule", true);
|
||||
gdi.disableInput("UseResultModule");
|
||||
@ -1023,10 +1061,13 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
int maxY = gdi.getCY();
|
||||
gdi.popX();
|
||||
gdi.fillDown();
|
||||
int innerBoxUpperCX = boxX + gdi.scaleLength(18);
|
||||
int innerBoxUpperCY = boxY;
|
||||
|
||||
gdi.setCX(boxX + gdi.scaleLength(24));
|
||||
gdi.setCY(boxY);
|
||||
gdi.setCY(boxY + gdi.scaleLength(6));
|
||||
gdi.pushX();
|
||||
gdi.addString("", 1, "Formateringsregler");
|
||||
gdi.addString("", fontMediumPlus, "Formateringsregler");
|
||||
gdi.dropLine(0.5);
|
||||
gdi.fillRight();
|
||||
int val = 0;
|
||||
@ -1069,10 +1110,15 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
gdi.dropLine();
|
||||
gdi.addButton("Color", "Färg...", editListCB).setExtra(mlp.getColorValue());
|
||||
|
||||
|
||||
maxX = max(maxX, gdi.getCX());
|
||||
gdi.popX();
|
||||
int innerBoxLowerCX = maxX + gdi.scaleLength(6);
|
||||
maxX += gdi.scaleLength(12);
|
||||
|
||||
gdi.setCX(boxX - gdi.scaleLength(6));
|
||||
gdi.dropLine(3);
|
||||
int innerBoxLowerCY = gdi.getCY();
|
||||
|
||||
gdi.dropLine();
|
||||
|
||||
gdi.setData("CurrentId", id);
|
||||
gdi.addButton("Remove", "Radera", editListCB, "Ta bort listposten");
|
||||
@ -1086,29 +1132,63 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
|
||||
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()*4;
|
||||
|
||||
gdi.addRectangle(rc, colorLightBlue, true);
|
||||
gdi.addRectangle(rc, colorLightBlue, true, false);
|
||||
|
||||
rc.top = innerBoxUpperCY;
|
||||
rc.left = innerBoxUpperCX;
|
||||
rc.right = innerBoxLowerCX;
|
||||
rc.bottom = innerBoxLowerCY;
|
||||
|
||||
gdi.addRectangle(rc, colorLightYellow, true, false);
|
||||
|
||||
gdi.setData("IsEditing", 1);
|
||||
gdi.setCX(x1);
|
||||
gdi.setCY(maxY);
|
||||
|
||||
showExample(gdi, margin, mlp);
|
||||
gdi.scrollToBottom();
|
||||
|
||||
showExample(gdi, mlp);
|
||||
|
||||
updateAlign(gdi, val);
|
||||
gdi.scrollToBottom();
|
||||
gdi.refresh();
|
||||
}
|
||||
|
||||
void ListEditor::showExample(gdioutput &gdi, int margin, const MetaListPost &mlp) {
|
||||
void ListEditor::showExample(gdioutput &gdi, EPostType type) {
|
||||
if (type == EPostType::lLastItem) {
|
||||
type = EPostType(gdi.getSelectedItem("Type").first);
|
||||
}
|
||||
|
||||
gdi.restore("Example", false);
|
||||
|
||||
MetaListPost mlp(type);
|
||||
// Has not effect
|
||||
//mlp.setLeg(readLeg(gdi, type, false));
|
||||
mlp.setText(gdi.getText("Text", false));
|
||||
showExample(gdi, mlp);
|
||||
gdi.refreshFast();
|
||||
}
|
||||
|
||||
void ListEditor::showExample(gdioutput &gdi, const MetaListPost &mlp) {
|
||||
int x1 = gdi.getCX();
|
||||
int margin = gdi.scaleLength(10);
|
||||
|
||||
RECT rrInner;
|
||||
rrInner.left = x1 + margin;
|
||||
rrInner.top = gdi.getCY();
|
||||
bool hasSymbol;
|
||||
lastShownExampleText = mlp.getText();
|
||||
GDICOLOR color = GDICOLOR::colorLightGreen;
|
||||
wstring text = MetaList::encode(mlp.getTypeRaw(), lastShownExampleText, hasSymbol);
|
||||
if (!hasSymbol) {
|
||||
text = lang.tl("Fel: Använd X i texten där värdet (Y) ska sättas in.#X#%s");
|
||||
color = GDICOLOR::colorLightRed;
|
||||
}
|
||||
|
||||
gdi.setRestorePoint("Example");
|
||||
gdi.fillDown();
|
||||
@ -1127,6 +1207,12 @@ void ListEditor::showExample(gdioutput &gdi, int margin, const MetaListPost &mlp
|
||||
wstring s = oe->formatListString(mlp.getTypeRaw(), rr[i]);
|
||||
if (used.insert(s).second) {
|
||||
int xb = gdi.getCX();
|
||||
if (!text.empty()) {
|
||||
wchar_t st[300];
|
||||
swprintf_s(st, text.c_str(), s.c_str());
|
||||
s = st;
|
||||
}
|
||||
|
||||
gdi.addStringUT(italicText, s + L" ");
|
||||
int xa = gdi.getCX();
|
||||
int delta = xa - xb;
|
||||
@ -1142,7 +1228,7 @@ void ListEditor::showExample(gdioutput &gdi, int margin, const MetaListPost &mlp
|
||||
gdi.fillDown();
|
||||
gdi.popX();
|
||||
|
||||
gdi.addRectangle(rrInner, colorLightGreen, true);
|
||||
gdi.addRectangle(rrInner, color, true);
|
||||
}
|
||||
|
||||
const wchar_t *ListEditor::getIndexDescription(EPostType type) {
|
||||
@ -1150,10 +1236,88 @@ const wchar_t *ListEditor::getIndexDescription(EPostType type) {
|
||||
return L"Index in X[index]#OutputTimes";
|
||||
else if (type == lResultModuleNumber || type == lResultModuleNumberTeam)
|
||||
return L"Index in X[index]#OutputNumbers";
|
||||
else if (MetaList::isAllStageType(type))
|
||||
return L"Applicera för specifik etapp:";
|
||||
else
|
||||
return L"Applicera för specifik sträcka:";
|
||||
}
|
||||
|
||||
bool ListEditor::legStageTypeIndex(gdioutput &gdi, EPostType type, int leg) {
|
||||
int dx = gdi.scaleLength(250);
|
||||
int dy = -gdi.getLineHeight() / 5;
|
||||
|
||||
if (MetaList::isResultModuleOutput(type)) {
|
||||
if (gdi.hasWidget("UseLeg"))
|
||||
gdi.removeWidget("UseLeg");
|
||||
|
||||
if (gdi.hasWidget("LegSel"))
|
||||
gdi.removeWidget("LegSel");
|
||||
|
||||
if (gdi.hasWidget("TUseLeg"))
|
||||
gdi.setTextTranslate("TUseLeg", getIndexDescription(type), true);
|
||||
else
|
||||
gdi.addString("TUseLeg", ypUseLeg, xpUseLeg, 0, getIndexDescription(type));
|
||||
|
||||
wstring legW = leg >= 0 ? itow(leg) : L"0";
|
||||
if (!gdi.hasWidget("Leg"))
|
||||
gdi.addInput(xpUseLeg + dx, ypUseLeg + dy, "Leg", legW, 4, editListCB);
|
||||
else {
|
||||
if (gdi.getText("Leg").empty())
|
||||
gdi.setText("Leg", legW);
|
||||
}
|
||||
}
|
||||
else if (MetaList::isAllStageType(type)) {
|
||||
if (gdi.hasWidget("UseLeg"))
|
||||
gdi.removeWidget("UseLeg");
|
||||
|
||||
if (gdi.hasWidget("Leg"))
|
||||
gdi.removeWidget("Leg");
|
||||
|
||||
if (gdi.hasWidget("TUseLeg"))
|
||||
gdi.setTextTranslate("TUseLeg", getIndexDescription(type), true);
|
||||
else
|
||||
gdi.addString("TUseLeg", ypUseLeg, xpUseLeg, 0, getIndexDescription(type));
|
||||
|
||||
if (!gdi.hasWidget("LegSel")) {
|
||||
gdi.addSelection(xpUseLeg + dx, ypUseLeg + dy, "LegSel", 160, gdi.scaleLength(300), editListCB);
|
||||
vector<pair<wstring, size_t>> items;
|
||||
items.emplace_back(lang.tl("Alla tidigare etapper"), -2);
|
||||
for (int j = 1; j < 20; j++) {
|
||||
items.emplace_back(lang.tl("Etapp X#" + itos(j)), j);
|
||||
}
|
||||
gdi.addItem("LegSel", items);
|
||||
gdi.selectItemByData("LegSel", leg >= 0 ? leg + 1 : -2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gdi.hasWidget("LegSel"))
|
||||
gdi.removeWidget("LegSel");
|
||||
|
||||
if (!gdi.hasWidget("UseLeg")) {
|
||||
if (gdi.hasWidget("TUseLeg"))
|
||||
gdi.removeWidget("TUseLeg");
|
||||
|
||||
gdi.addCheckbox(xpUseLeg, ypUseLeg, "UseLeg", getIndexDescription(type), editListCB, leg != -1);
|
||||
|
||||
wstring ix = leg >= 0 ? itow(leg + 1) : L"";
|
||||
if (!gdi.hasWidget("Leg"))
|
||||
gdi.addInput(xpUseLeg + dx, ypUseLeg + dy, "Leg", ix, 4, editListCB);
|
||||
else {
|
||||
int leg = gdi.getTextNo("Leg");
|
||||
gdi.setText("Leg", ix);
|
||||
}
|
||||
gdi.setInputStatus("Leg", leg != -1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (MetaList::isResultModuleOutput(type)) {
|
||||
gdi.check("UseLeg", true);
|
||||
gdi.disableInput("UseLeg");
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void ListEditor::editListProp(gdioutput &gdi, bool newList) {
|
||||
checkUnsaved(gdi);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -34,6 +34,7 @@ class TabBase;
|
||||
|
||||
#include <vector>
|
||||
#include "autocompletehandler.h"
|
||||
#include "oListInfo.h"
|
||||
|
||||
class ListEditor : public AutoCompleteHandler {
|
||||
private:
|
||||
@ -47,7 +48,7 @@ private:
|
||||
bool dirtyInt;
|
||||
SaveType lastSaved;
|
||||
const wchar_t *getIndexDescription(EPostType type);
|
||||
|
||||
wstring lastShownExampleText;
|
||||
void showLine(gdioutput &gdi, const vector<MetaListPost> &line, int ix) const;
|
||||
int editList(gdioutput &gdi, int type, BaseInfo &data);
|
||||
void updateType(int iType, gdioutput &gdi);
|
||||
@ -56,7 +57,12 @@ private:
|
||||
int lineIx, int ix) const;
|
||||
|
||||
void editListPost(gdioutput &gdi, const MetaListPost &mlp, int id);
|
||||
void showExample(gdioutput &gdi, int margin, const MetaListPost &mlp);
|
||||
|
||||
void showExample(gdioutput &gdi, EPostType type = EPostType::lLastItem);
|
||||
|
||||
void showExample(gdioutput &gdi, const MetaListPost &mlp);
|
||||
|
||||
int readLeg(gdioutput &gdi, EPostType newType, bool checkError) const;
|
||||
|
||||
void editListProp(gdioutput &gdi, bool newList);
|
||||
|
||||
@ -78,6 +84,12 @@ private:
|
||||
TabBase *origin = nullptr;
|
||||
void show(gdioutput &gdi);
|
||||
|
||||
int xpUseLeg;
|
||||
int ypUseLeg;
|
||||
|
||||
bool legStageTypeIndex(gdioutput &gdi, EPostType type, int leg);
|
||||
|
||||
|
||||
public:
|
||||
ListEditor(oEvent *oe);
|
||||
virtual ~ListEditor();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/********************i****************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
202
code/machinecontainer.cpp
Normal file
202
code/machinecontainer.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "machinecontainer.h"
|
||||
#include "meos_util.h"
|
||||
#include "xmlparser.h"
|
||||
#include "gdioutput.h"
|
||||
int MachineContainer::AbstractMachine::getInt(const string &v) const {
|
||||
return _wtoi(getString(v).c_str());
|
||||
}
|
||||
|
||||
const wstring &MachineContainer::AbstractMachine::getString(const string &v) const {
|
||||
auto res = props.find(v);
|
||||
if (res != props.end())
|
||||
return res->second;
|
||||
return _EmptyWString;
|
||||
}
|
||||
|
||||
vector<int> MachineContainer::AbstractMachine::getVectorInt(const string &v) const {
|
||||
auto &s = getString(v);
|
||||
vector<wstring> sp;
|
||||
split(s, L",", sp);
|
||||
vector<int> res(sp.size());
|
||||
for (int j = 0; j < sp.size(); j++)
|
||||
res[j] = _wtoi(sp[j].c_str());
|
||||
return res;
|
||||
}
|
||||
|
||||
set<int> MachineContainer::AbstractMachine::getSetInt(const string &v) const {
|
||||
std::set<int> res;
|
||||
for (int i : getVectorInt(v)) {
|
||||
res.insert(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::set(const string &name, int v) {
|
||||
if (v != 0)
|
||||
props[name] = itow(v);
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::set(const string &name, const vector<int> &v) {
|
||||
wstring &r = props[name];
|
||||
for (int j = 0; j < v.size(); j++) {
|
||||
if (j == 0)
|
||||
r = itow(v[j]);
|
||||
else
|
||||
r += L"," + itow(v[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::load(const xmlobject &data) {
|
||||
xmlList out;
|
||||
data.getObjects(out);
|
||||
for (auto &x : out) {
|
||||
props[x.getName()] = x.getw();
|
||||
}
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::save(xmlparser &data) const {
|
||||
for (auto &p : props) {
|
||||
data.write(p.first.c_str(), p.second);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
string encode(const string &in) {
|
||||
string out;
|
||||
out.reserve(in.length());
|
||||
for (int j = 0; j < in.length(); j++) {
|
||||
if (in[j] == '|' || in[j] == '$' || in[j] == '%') {
|
||||
out.push_back('%');
|
||||
if (in[j] == '|')
|
||||
out.push_back('1');
|
||||
else if (in[j] == '$')
|
||||
out.push_back('2');
|
||||
else if (in[j] == '%')
|
||||
out.push_back('3');
|
||||
}
|
||||
else
|
||||
out.push_back(in[j]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
string decode(const string &in) {
|
||||
string out;
|
||||
out.reserve(in.length());
|
||||
for (int j = 0; j < in.length(); j++) {
|
||||
if (in[j] == '%') {
|
||||
j++;
|
||||
if (j < in.length()) {
|
||||
if (in[j] == '1')
|
||||
out.push_back('|');
|
||||
else if (in[j] == '2')
|
||||
out.push_back('§');
|
||||
else if (in[j] == '3')
|
||||
out.push_back('%');
|
||||
}
|
||||
}
|
||||
else
|
||||
out.push_back(in[j]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::load(const string &data) {
|
||||
vector<string> parts;
|
||||
split(data, "|", parts);
|
||||
for (int j = 0; j < parts.size(); j+=2) {
|
||||
const wstring &w = gdioutput::fromUTF8(decode(parts[j + 1]));
|
||||
props[parts[j]] = w;
|
||||
}
|
||||
}
|
||||
|
||||
string MachineContainer::AbstractMachine::save() const {
|
||||
string out;
|
||||
for (auto &p : props) {
|
||||
if (!out.empty())
|
||||
out += "|";
|
||||
out.append(p.first);
|
||||
out += "|";
|
||||
out.append(encode(gdioutput::toUTF8(p.second)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void MachineContainer::AbstractMachine::set(const string &name, const wstring &v) {
|
||||
if (!v.empty())
|
||||
props[name] = v;
|
||||
}
|
||||
|
||||
vector<pair<string, wstring>> MachineContainer::enumerate() const {
|
||||
vector<pair<string, wstring>> res;
|
||||
for (auto v : machines)
|
||||
res.push_back(v.first);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void MachineContainer::load(const xmlobject &data) {
|
||||
xmlList out;
|
||||
data.getObjects("Machine", out);
|
||||
|
||||
for (auto &m : out) {
|
||||
string type;
|
||||
wstring tag;
|
||||
m.getObjectString("type", type);
|
||||
m.getObjectString("name", tag);
|
||||
if (!type.empty() && !tag.empty()) {
|
||||
auto res = machines.emplace(make_pair(type, tag), MachineContainer::AbstractMachine());
|
||||
if (res.second)
|
||||
res.first->second.load(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MachineContainer::save(xmlparser &data) {
|
||||
for (auto &m : machines) {
|
||||
vector<wstring> p({ wstring(L"type"), gdioutput::widen(m.first.first),
|
||||
wstring(L"name"), m.first.second });
|
||||
data.startTag("Machine", p);
|
||||
m.second.save(data);
|
||||
data.endTag();
|
||||
}
|
||||
}
|
||||
|
||||
void MachineContainer::load(const string &data) {
|
||||
vector<string> parts;
|
||||
split(data, "$", parts);
|
||||
for (int j = 0; j + 2 < parts.size(); j++) {
|
||||
const string &type = parts[j];
|
||||
wstring tag = gdioutput::fromUTF8(decode(parts[j + 1]));
|
||||
auto res = machines.emplace(make_pair(type, tag), MachineContainer::AbstractMachine());
|
||||
if (res.second)
|
||||
res.first->second.load(parts[j+2]);
|
||||
}
|
||||
}
|
||||
|
||||
string MachineContainer::save() {
|
||||
vector<string> ml;
|
||||
ml.reserve(machines.size() * 3);
|
||||
size_t tSize = 0;
|
||||
for (auto &m : machines) {
|
||||
ml.push_back(m.first.first);
|
||||
tSize += ml.back().length() + 2;
|
||||
ml.push_back(encode(gdioutput::toUTF8(m.first.second)));
|
||||
tSize += ml.back().length() + 2;
|
||||
ml.push_back(m.second.save());
|
||||
tSize += ml.back().length() + 2;
|
||||
}
|
||||
|
||||
string out;
|
||||
out.reserve(tSize);
|
||||
|
||||
for (const string & m : ml) {
|
||||
if (!out.empty())
|
||||
out.append("$");
|
||||
out.append(m);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
79
code/machinecontainer.h
Normal file
79
code/machinecontainer.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class xmlparser;
|
||||
class xmlobject;
|
||||
using namespace std;
|
||||
|
||||
class MachineContainer {
|
||||
|
||||
public:
|
||||
|
||||
class AbstractMachine {
|
||||
map<string, wstring> props;
|
||||
public:
|
||||
void clear() {
|
||||
props.clear();
|
||||
}
|
||||
|
||||
int getInt(const string &v) const;
|
||||
const wstring &getString(const string &v) const;
|
||||
vector<int> getVectorInt(const string &v) const;
|
||||
set<int> getSetInt(const string &v) const;
|
||||
|
||||
void set(const string &name, int v);
|
||||
void set(const string &name, const vector<int> &v);
|
||||
void set(const string &name, const wstring &v);
|
||||
void set(const string &name, bool v) {
|
||||
set(name, int(v));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void set(const string &name, const T &v) {
|
||||
vector<int> vv;
|
||||
for (auto x : v)
|
||||
vv.push_back(x);
|
||||
set(name, vv);
|
||||
}
|
||||
|
||||
protected:
|
||||
void load(const xmlobject &data);
|
||||
void load(const string &data);
|
||||
void save(xmlparser &data) const;
|
||||
string save() const;
|
||||
friend class MachineContainer;
|
||||
};
|
||||
|
||||
private:
|
||||
map<pair<string, wstring>, AbstractMachine> machines;
|
||||
|
||||
public:
|
||||
const AbstractMachine *get(const string &type, const wstring &name) const {
|
||||
auto res = machines.find(make_pair(type, name));
|
||||
if (res != machines.end())
|
||||
return &res->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void erase(const string &type, const wstring &name) {
|
||||
machines.erase(make_pair(type, name));
|
||||
}
|
||||
|
||||
AbstractMachine &set(const string &type, const wstring &name) {
|
||||
auto &m = machines[make_pair(type, name)];
|
||||
m.clear();
|
||||
return m;
|
||||
}
|
||||
|
||||
vector<pair<string, wstring>> enumerate() const;
|
||||
|
||||
void load(const xmlobject &data);
|
||||
void save(xmlparser &data);
|
||||
void load(const string &data);
|
||||
string save();
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -294,7 +294,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fileExist(settings)) {
|
||||
if (fileExists(settings)) {
|
||||
gEvent->loadProperties(settings);
|
||||
}
|
||||
else {
|
||||
@ -314,13 +314,13 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
lang.get().addLangResource(L"Español", L"111");
|
||||
lang.get().addLangResource(L"Russian", L"107");
|
||||
|
||||
if (fileExist(L"extra.lng")) {
|
||||
if (fileExists(L"extra.lng")) {
|
||||
lang.get().addLangResource(L"Extraspråk", L"extra.lng");
|
||||
}
|
||||
else {
|
||||
wchar_t lpath[260];
|
||||
getUserFile(lpath, L"extra.lng");
|
||||
if (fileExist(lpath))
|
||||
if (fileExists(lpath))
|
||||
lang.get().addLangResource(L"Extraspråk", lpath);
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
// Main message loop:
|
||||
mainMessageLoop(hAccelTable, 0);
|
||||
|
||||
tabAutoRegister(0);
|
||||
TabAuto::tabAutoRegister(nullptr);
|
||||
tabList->clear();
|
||||
delete tabList;
|
||||
tabList = nullptr;
|
||||
@ -730,6 +730,14 @@ LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
gdi->keyCommand(KC_FINDBACK);
|
||||
}
|
||||
}
|
||||
else if (wParam == 'A' && ctrlPressed) {
|
||||
if (gdi)
|
||||
gdi->keyCommand(KC_MARKALL);
|
||||
}
|
||||
else if (wParam == 'D' && ctrlPressed) {
|
||||
if (gdi)
|
||||
gdi->keyCommand(KC_CLEARALL);
|
||||
}
|
||||
else if (wParam == VK_DELETE) {
|
||||
if (gdi)
|
||||
gdi->keyCommand(KC_DELETE);
|
||||
@ -1072,6 +1080,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
int wmId, wmEvent;
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
static bool connectionAlert = false;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
@ -1084,7 +1093,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TabAuto *ta = (TabAuto *)gdi_main->getTabs().get(TAutoTab);
|
||||
tabList->push_back(TabObject(ta, "Automater"));
|
||||
tabAutoRegister(ta);
|
||||
TabAuto::tabAutoRegister(ta);
|
||||
}
|
||||
tabList->push_back(TabObject(gdi_main->getTabs().get(TSpeakerTab), "Speaker"));
|
||||
tabList->push_back(TabObject(gdi_main->getTabs().get(TClassTab), "Klasser"));
|
||||
@ -1248,7 +1257,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
case WM_USER + 5:
|
||||
if (gdi_main)
|
||||
gdi_main->addInfoBox("ainfo", L"info:advanceinfo", 10000);
|
||||
break;
|
||||
|
||||
case WM_USER + 6:
|
||||
if (gdi_main && lParam) {
|
||||
gdioutput* g = (gdioutput*)lParam;
|
||||
wstring msg = g->getDelayedAlert();
|
||||
if (!connectionAlert) {
|
||||
connectionAlert = true;
|
||||
gdi_main->alert(msg);
|
||||
connectionAlert = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
||||
10
code/meos.rc
10
code/meos.rc
@ -149,8 +149,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,1,0,1
|
||||
PRODUCTVERSION 3,1,0,1
|
||||
FILEVERSION 3,8,0,1
|
||||
PRODUCTVERSION 3,8,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -167,12 +167,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Melin Software HB"
|
||||
VALUE "FileDescription", "meos"
|
||||
VALUE "FileVersion", "3.7.0.1"
|
||||
VALUE "FileVersion", "3.8.0.1"
|
||||
VALUE "InternalName", "meos"
|
||||
VALUE "LegalCopyright", "Copyright © 2007-2020"
|
||||
VALUE "LegalCopyright", "Copyright © 2007-2021"
|
||||
VALUE "OriginalFilename", "meos.exe"
|
||||
VALUE "ProductName", " meos"
|
||||
VALUE "ProductVersion", "3.7.0.1"
|
||||
VALUE "ProductVersion", "3.8.0.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -882,9 +882,9 @@ wstring trim(const wstring &s) {
|
||||
else return L"";
|
||||
}
|
||||
|
||||
bool fileExist(const wchar_t *file)
|
||||
bool fileExists(const wstring &file)
|
||||
{
|
||||
return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
|
||||
return GetFileAttributes(file.c_str()) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
bool stringMatch(const wstring &a, const wstring &b) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -158,7 +158,7 @@ int countWords(const wchar_t *p);
|
||||
wstring trim(const wstring &s);
|
||||
string trim(const string &s);
|
||||
|
||||
bool fileExist(const wchar_t *file);
|
||||
bool fileExists(const wstring &file);
|
||||
|
||||
bool stringMatch(const wstring &a, const wstring &b);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -7,6 +7,10 @@
|
||||
#define IDR_3007 109
|
||||
#define IDR_3008 110
|
||||
#define IDR_3011 111
|
||||
#define SND_OK 50
|
||||
#define SND_LEADER 51
|
||||
#define SND_NOTOK 52
|
||||
#define SND_NEEDACTION 53
|
||||
|
||||
IDR_3001 300 DISCARDABLE "swedish.lng"
|
||||
IDR_3002 300 DISCARDABLE "english.lng"
|
||||
@ -18,3 +22,7 @@ IDR_3008 300 DISCARDABLE "french.lng"
|
||||
IDR_3011 300 DISCARDABLE "spanish.lng"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SND_OK WAVE DISCARDABLE "./sound/ok.wav"
|
||||
SND_LEADER WAVE DISCARDABLE "./sound/leader.wav"
|
||||
SND_NOTOK WAVE DISCARDABLE "./sound/notok.wav"
|
||||
SND_NEEDACTION WAVE DISCARDABLE "./sound/needaction.wav"
|
||||
|
||||
@ -489,6 +489,7 @@
|
||||
<ClCompile Include="listeditor.cpp" />
|
||||
<ClCompile Include="liveresult.cpp" />
|
||||
<ClCompile Include="localizer.cpp" />
|
||||
<ClCompile Include="machinecontainer.cpp" />
|
||||
<ClCompile Include="meos.cpp">
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
@ -683,6 +684,7 @@
|
||||
<ClInclude Include="iof30interface.h" />
|
||||
<ClInclude Include="listeditor.h" />
|
||||
<ClInclude Include="liveresult.h" />
|
||||
<ClInclude Include="machinecontainer.h" />
|
||||
<ClInclude Include="meosdb\sqltypes.h" />
|
||||
<ClInclude Include="meosdb\targetver.h" />
|
||||
<ClInclude Include="meosexception.h" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -25,17 +25,17 @@
|
||||
|
||||
//ABCDEFGHIJKLMNO
|
||||
int getMeosBuild() {
|
||||
string revision("$Rev: 1081 $");
|
||||
string revision("$Rev: 1103 $");
|
||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||
}
|
||||
|
||||
wstring getMeosDate() {
|
||||
wstring date(L"$Date: 2021-07-12 17:51:51 +0200 (mån, 12 jul 2021) $");
|
||||
wstring date(L"$Date: 2021-12-11 15:54:57 +0100 (lör, 11 dec 2021) $");
|
||||
return date.substr(7,10);
|
||||
}
|
||||
|
||||
wstring getBuildType() {
|
||||
return L"Beta"; // No parantheses (...)
|
||||
return L"Beta II"; // No parantheses (...)
|
||||
}
|
||||
|
||||
wstring getMajorVersion() {
|
||||
@ -90,7 +90,6 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
||||
supp.emplace_back(L"OK Tjärnen");
|
||||
supp.emplace_back(L"Leksands OK");
|
||||
supp.emplace_back(L"O-Travel");
|
||||
supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice");
|
||||
developSupp.emplace_back(L"KOB Kysak");
|
||||
supp.emplace_back(L"Ingemar Carlsson");
|
||||
supp.emplace_back(L"Tolereds AIK");
|
||||
@ -149,6 +148,20 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
||||
supp.emplace_back(L"IFK Kiruna");
|
||||
supp.emplace_back(L"Smedjebackens OK");
|
||||
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"Simrishamns OK");
|
||||
supp.emplace_back(L"OK Fryksdalen");
|
||||
supp.emplace_back(L"Magnus Asplund, Sundbybergs IK");
|
||||
supp.emplace_back(L"Frölunda OL");
|
||||
supp.emplace_back(L"Hjobygdens OK");
|
||||
supp.emplace_back(L"OK Malmia");
|
||||
supp.emplace_back(L"Säterbygdens OK");
|
||||
supp.emplace_back(L"OK Orinto");
|
||||
supp.emplace_back(L"Trosabygdens OK");
|
||||
supp.emplace_back(L"Järla Orientering");
|
||||
supp.emplace_back(L"Hans Wilhelmsson, Säffle OK");
|
||||
supp.emplace_back(L"Cent Vallées Orientation 12 (C.V.O. 12)");
|
||||
|
||||
reverse(supp.begin(), supp.end());
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -485,16 +485,24 @@ void MetaList::initUniqueIndex() const {
|
||||
uniqueIndex = "A" + itos(ix) + "B" + itos(yx);
|
||||
}
|
||||
|
||||
bool MetaList::isBreak(int x) const {
|
||||
bool MetaList::isBreak(int x) {
|
||||
return isspace(x) || x == '.' || x == ',' ||
|
||||
x == '-' || x == ':' || x == ';' || x == '('
|
||||
|| x == ')' || x=='/' || (x>30 && x < 127 && !isalnum(x));
|
||||
}
|
||||
|
||||
wstring MetaList::encode(const wstring &input_) const {
|
||||
wstring MetaList::encode(EPostType type, const wstring &inputS, bool &foundSymbol) {
|
||||
if (inputS.empty()) {
|
||||
foundSymbol = true; // No symbol needed
|
||||
return inputS;
|
||||
}
|
||||
wstring out;
|
||||
wstring input = lang.tl(input_);
|
||||
wstring input = lang.tl(inputS);
|
||||
|
||||
out.reserve(input.length() + 5);
|
||||
int sCount = 0;
|
||||
if (type == EPostType::lString)
|
||||
sCount = 1; // No symbols expected in string
|
||||
|
||||
for (size_t k = 0; k<input.length(); k++) {
|
||||
int c = input[k];
|
||||
@ -505,20 +513,22 @@ wstring MetaList::encode(const wstring &input_) const {
|
||||
out.push_back('%');
|
||||
out.push_back('%');
|
||||
}
|
||||
else if (c == 'X' && isBreak(n) && isBreak(p) ) {
|
||||
else if (c == 'X' && isBreak(n) && isBreak(p) && sCount == 0) {
|
||||
out.push_back('%');
|
||||
out.push_back('s');
|
||||
sCount++;
|
||||
}
|
||||
else
|
||||
out.push_back(c);
|
||||
}
|
||||
|
||||
foundSymbol = sCount > 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
MetaListPost &MetaList::add(ListIndex ix, const MetaListPost &post) {
|
||||
if (data[ix].empty())
|
||||
addRow(ix);
|
||||
// data[ix].resize(1);
|
||||
|
||||
vector<MetaListPost> &d = data[ix].back();
|
||||
d.push_back(post);
|
||||
@ -636,9 +646,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
}
|
||||
|
||||
auto isAllStageType = [](const MetaListPost &mp) {
|
||||
return ((mp.type == lRunnerStagePlace || mp.type == lRunnerStageStatus
|
||||
|| mp.type == lRunnerStageTime || mp.type == lRunnerStageTimeStatus ||
|
||||
mp.type == lRunnerStagePoints || mp.type == lRunnerStageNumber) && mp.leg == -1);
|
||||
return MetaList::isAllStageType(mp.type) && mp.leg == -1;
|
||||
};
|
||||
|
||||
for (size_t j = 0; j<lines.size(); j++) {
|
||||
@ -729,12 +737,13 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
if (mp.font != formatIgnore)
|
||||
font = mp.font;
|
||||
|
||||
vector< pair<EPostType, wstring> > typeFormats;
|
||||
typeFormats.push_back(make_pair(mp.type, encode(mp.text)));
|
||||
bool dmy;
|
||||
vector<pair<EPostType, wstring>> typeFormats;
|
||||
typeFormats.push_back(make_pair(mp.type, encode(mp.type, mp.text, dmy)));
|
||||
size_t kk = k+1;
|
||||
//Add merged entities
|
||||
while (kk < cline.size() && cline[kk].mergeWithPrevious) {
|
||||
typeFormats.push_back(make_pair(cline[kk].type, encode(cline[kk].text)));
|
||||
typeFormats.push_back(make_pair(cline[kk].type, encode(cline[kk].type, cline[kk].text, dmy)));
|
||||
kk++;
|
||||
}
|
||||
|
||||
@ -838,7 +847,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
continue;
|
||||
|
||||
string label = "P" + itos(0*1000 + j*100 + k);
|
||||
wstring text = makeDash(encode(cline[k].text));
|
||||
bool dmy;
|
||||
wstring text = makeDash(encode(cline[k].type, cline[k].text, dmy));
|
||||
if (capitalizeTitle)
|
||||
capitalizeWords(text);
|
||||
|
||||
@ -899,8 +909,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
gdiFonts font = header;
|
||||
if (mp.font != formatIgnore)
|
||||
font = mp.font;
|
||||
|
||||
wstring text = encode(mp.text);
|
||||
bool dmy;
|
||||
wstring text = encode(mp.type, mp.text, dmy);
|
||||
if (capitalizeTitle)
|
||||
capitalizeWords(text);
|
||||
|
||||
@ -949,7 +959,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
font = mp.font;
|
||||
|
||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLList)]);
|
||||
oPrintPost &added = li.addListPost(oPrintPost(mp.type, encode(mp.text), font|mp.textAdjust,
|
||||
bool dmy;
|
||||
oPrintPost &added = li.addListPost(oPrintPost(mp.type, encode(mp.type, mp.text, dmy), font|mp.textAdjust,
|
||||
pos.get(label, s_factor),
|
||||
dy + list_dy, cline[k].leg == -1 ? parLegNumber : make_pair(cline[k].leg, true))).
|
||||
setFontFace(fontFaces[MLList].font,
|
||||
@ -1000,7 +1011,8 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
xp = pos.get(label, s_factor);
|
||||
|
||||
next_dy = max(next_dy, fontHeight[make_pair(font, MLSubList)]);
|
||||
oPrintPost &added = li.addSubListPost(oPrintPost(mp.type, encode(mp.text), font|mp.textAdjust,
|
||||
bool dmy;
|
||||
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))).
|
||||
setFontFace(fontFaces[MLSubList].font,
|
||||
fontFaces[MLSubList].scale);
|
||||
@ -1979,6 +1991,7 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lRunnerTimeAdjustment] = L"RunnerTimeAdjustment";
|
||||
typeToSymbol[lRunnerPointAdjustment] = L"RunnerPointAdjustment";
|
||||
typeToSymbol[lRunnerRogainingPointGross] = L"RunnerRogainingPointGross";
|
||||
typeToSymbol[lRunnerCardVoltage] = L"RunnerCardVoltage";
|
||||
|
||||
typeToSymbol[lRunnerStageTime] = L"RunnerStageTime";
|
||||
typeToSymbol[lRunnerStageStatus] = L"RunnerStageStatus";
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -50,7 +50,6 @@ class Position
|
||||
void update(int ix, const string &newname, int width, bool alignBlock, bool alignLock);
|
||||
|
||||
public:
|
||||
|
||||
int getWidth() const;
|
||||
|
||||
bool postAdjust();
|
||||
@ -207,8 +206,6 @@ private:
|
||||
enum ListIndex {MLHead = 0, MLSubHead = 1, MLList = 2, MLSubList=3};
|
||||
MetaListPost &add(ListIndex ix, const MetaListPost &post);
|
||||
void addRow(int ix);
|
||||
wstring encode(const wstring &input) const;
|
||||
bool isBreak(int x) const;
|
||||
|
||||
static map<EPostType, wstring> typeToSymbol;
|
||||
static map<wstring, EPostType> symbolToType;
|
||||
@ -237,15 +234,28 @@ private:
|
||||
int getResultModuleIndex(oEvent *oe, oListInfo &li, const MetaListPost &lp) const;
|
||||
mutable map<string, int> resultToIndex;
|
||||
|
||||
static bool isBreak(int x);
|
||||
|
||||
public:
|
||||
|
||||
static wstring encode(EPostType type, const wstring &input, bool &foundSymbol);
|
||||
|
||||
static void getAutoComplete(const wstring &w, vector<AutoCompleteRecord> &records);
|
||||
|
||||
MetaList();
|
||||
virtual ~MetaList() {}
|
||||
|
||||
bool supportClasses() const;
|
||||
static constexpr bool isAllStageType(EPostType type) {
|
||||
return type == lRunnerStagePlace || type == lRunnerStageStatus ||
|
||||
type == lRunnerStageTime || type == lRunnerStageTimeStatus ||
|
||||
type == lRunnerStagePoints || type == lRunnerStageNumber;
|
||||
}
|
||||
|
||||
static constexpr bool isResultModuleOutput(EPostType type) {
|
||||
return type == lResultModuleNumber || type == lResultModuleTime ||
|
||||
type == lResultModuleTimeTeam || type == lResultModuleNumberTeam;
|
||||
}
|
||||
bool supportClasses() const;
|
||||
const wstring &getListInfo(const oEvent &oe) const;
|
||||
void clearTag() {tag.clear();}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -971,7 +971,7 @@ bool MethodEditor::resultIsInstalled() const {
|
||||
return false; // Used in a list in this competition
|
||||
|
||||
//string path = getInternalPath(currentResult->getTag());
|
||||
return fileExist(fileNameSource.c_str());
|
||||
return fileExists(fileNameSource);
|
||||
}
|
||||
|
||||
void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
@ -86,7 +86,7 @@ unsigned __stdcall reconnectThread(void *v) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MySQLReconnect::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
void MySQLReconnect::settings(gdioutput &gdi, oEvent &oe, State state) {
|
||||
}
|
||||
|
||||
void MySQLReconnect::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
@ -111,6 +111,7 @@ void MySQLReconnect::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
gdi.setDBErrorState(false);
|
||||
gdi.setWindowTitle(oe->getTitleName());
|
||||
interval=0;
|
||||
toRemove = true;
|
||||
}
|
||||
}
|
||||
else if (mysqlStatus==-1) {
|
||||
@ -138,9 +139,7 @@ void MySQLReconnect::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
int AutomaticCB(gdioutput *gdi, int type, void *data);
|
||||
|
||||
void MySQLReconnect::status(gdioutput &gdi) {
|
||||
gdi.dropLine(0.5);
|
||||
gdi.addString("", 1, name);
|
||||
gdi.pushX();
|
||||
AutoMachine::status(gdi);
|
||||
if (interval>0){
|
||||
gdi.addStringUT(1, timeError + L": " + lang.tl("DATABASE ERROR")).setColor(colorDarkRed);
|
||||
gdi.fillRight();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
MeOS - Orienteering Software
|
||||
Copyright (C) 2009-2020 Melin Software HB
|
||||
Copyright (C) 2009-2021 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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user