MeOS, version 4.0 BETA 1

This commit is contained in:
Erik Melin 2024-03-19 08:51:20 +01:00
parent 16272ffa20
commit 11942302fa
205 changed files with 11350 additions and 3589 deletions

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -41,28 +41,30 @@ extern Image image;
#include <sstream>
#include <iomanip>
using namespace std;
double getLocalScale(const wstring &fontName, wstring &faceName);
wstring getMeosCompectVersion();
map <string, shared_ptr<HTMLWriter>> HTMLWriter::tCache;
extern wchar_t exePath[MAX_PATH];
static void generateStyles(const gdioutput &gdi, ostream &fout, double scale, bool withTbl, const list<TextInfo> &TL,
static void generateStyles(const gdioutput &gdi, std::ostream &fout, double scale, bool withTbl, const list<TextInfo> &TL,
map< pair<gdiFonts, string>, pair<string, string> > &styles) {
fout << "<style type=\"text/css\">\n";
fout << "body {background-color: rgb(250,250,255)}\n";
fout << "h1 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 24 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h2 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 20 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h3 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 16 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "p {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal}\n";
fout << "div {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h1 {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 24 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h2 {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 20 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h3 {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 16 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "p {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal}\n";
fout << "div {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
if (withTbl) {
fout << "td {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "td {font-family:arial,sans-serif;font-size:" << std::fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "td.e0 {background-color: rgb(238,238,255)}\n";
fout << "td.e1 {background-color: rgb(245,245,255)}\n";
fout << "td.header {line-height:" << fixed << std::setprecision(2) << 1.8 * scale << ";height:" << fixed << std::setprecision(2) << 40 * scale << "px}\n";
fout << "td.freeheader {line-height:" << fixed << std::setprecision(2) << 1.2 * scale << "}\n";
fout << "td.header {line-height:" << std::fixed << std::setprecision(2) << 1.8 * scale << ";height:" << std::fixed << std::setprecision(2) << 40 * scale << "px}\n";
fout << "td.freeheader {line-height:" << std::fixed << std::setprecision(2) << 1.2 * scale << "}\n";
}
list<TextInfo>::const_iterator it=TL.begin();
int styleList = 1;

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -49,11 +49,11 @@ class HTMLWriter {
ImageWriter(const wstring& dst, bool writeImages) : destination(dst), writeImages(writeImages) {}
void write(ostream &fout, const string &xp, const string &yp, const wstring &img, int width, int height);
void write(std::ostream &fout, const string &xp, const string &yp, const wstring &img, int width, int height);
};
template<typename T, typename TI>
static void formatTL(ostream& fout,
static void formatTL(std::ostream& fout,
ImageWriter& imageWriter,
const map< pair<gdiFonts, string>, pair<string, string> >& styles,
const T& tl,
@ -87,7 +87,7 @@ public:
void read(const wstring &fileName);
void generate(gdioutput &gdi,
ostream &fout,
std::ostream &fout,
const wstring &title,
const wstring &contentDescription,
bool respectPageBreak,
@ -99,12 +99,12 @@ public:
void getPage(const oEvent &oe, string &out) const;
static void writeHTML(gdioutput &gdi, ostream &dout, const wstring &title,
static void writeHTML(gdioutput &gdi, std::ostream &dout, const wstring &title,
bool includeImages,
const wstring& imageDirectoryDestination,
int refreshTimeOut, double scale);
static void writeTableHTML(gdioutput &gdi, ostream &fout,
static void writeTableHTML(gdioutput &gdi, std::ostream &fout,
const wstring &title,
bool includeImages,
const wstring &imageDirectoryDestination,
@ -121,13 +121,13 @@ public:
const wstring &title, int refreshTimeOut, double scale);
static void write(gdioutput& gdi, const wstring& file, const wstring& title, int refresh, oListParam& param, const oEvent& oe);
static void write(gdioutput& gdi, ostream& fout, const wstring& title, int refresh, oListParam& param, const oEvent& oe);
static void write(gdioutput& gdi, std::ostream& fout, const wstring& title, int refresh, oListParam& param, const oEvent& oe);
static void write(gdioutput& gdi, const wstring& file, const wstring& title, const wstring& contentsDescription,
bool respectPageBreak, const string& typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale);
static void write(gdioutput& gdi, ostream& fout, const wstring& title,
static void write(gdioutput& gdi, std::ostream& fout, const wstring& title,
bool includeImages,
const wstring& imageDirectoryDestination,
const wstring& contentsDescription,

31
code/MeOS.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeOS", "MeOS.vcxproj", "{60BC59CB-8987-4A39-B866-403066F59B0F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{60BC59CB-8987-4A39-B866-403066F59B0F}.Debug|x64.ActiveCfg = Debug|x64
{60BC59CB-8987-4A39-B866-403066F59B0F}.Debug|x64.Build.0 = Debug|x64
{60BC59CB-8987-4A39-B866-403066F59B0F}.Debug|x86.ActiveCfg = Debug|Win32
{60BC59CB-8987-4A39-B866-403066F59B0F}.Debug|x86.Build.0 = Debug|Win32
{60BC59CB-8987-4A39-B866-403066F59B0F}.Release|x64.ActiveCfg = Release|x64
{60BC59CB-8987-4A39-B866-403066F59B0F}.Release|x64.Build.0 = Release|x64
{60BC59CB-8987-4A39-B866-403066F59B0F}.Release|x86.ActiveCfg = Release|Win32
{60BC59CB-8987-4A39-B866-403066F59B0F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0AA159AF-578B-49E9-8D52-50F9272169DB}
EndGlobalSection
EndGlobal

379
code/MeOS.vcxproj Normal file
View File

@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{60BC59CB-8987-4A39-B866-403066F59B0F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<CopyCppRuntimeToOutputDir>false</CopyCppRuntimeToOutputDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<LanguageStandard>stdcpp17</LanguageStandard>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>./libharu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4267;4244;4018</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>./lib_db</AdditionalLibraryDirectories>
<AdditionalDependencies>Msimg32.lib;comctl32.lib;odbc32.lib;odbccp32.lib;winmm.lib;ws2_32.lib;wininet.lib;zlibstat_vc15.lib;libmysql.lib;libhpdf.lib;RestBed.lib;libpng.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>meos_dpi_manifest.xml %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<LanguageStandard>stdcpp17</LanguageStandard>
<DisableSpecificWarnings>4267;4244;4018</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>./libharu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>Msimg32.lib;comctl32.lib;odbc32.lib;odbccp32.lib;winmm.lib;ws2_32.lib;wininet.lib;zlibstat.lib;libharu.lib;RestBed.lib;libpng.lib;libmysql.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>./lib64_db</AdditionalLibraryDirectories>
</Link>
<Manifest>
<AdditionalManifestFiles>meos_dpi_manifest.xml %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpp17</LanguageStandard>
<DisableSpecificWarnings>4267;4244;4018</DisableSpecificWarnings>
<AdditionalIncludeDirectories>./libharu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>./lib</AdditionalLibraryDirectories>
<AdditionalDependencies>Msimg32.lib;comctl32.lib;odbc32.lib;odbccp32.lib;winmm.lib;ws2_32.lib;wininet.lib;zlibstat_vc15.lib;libmysql.lib;libhpdf.lib;RestBed.lib;libpng.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>meos_dpi_manifest.xml %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DisableSpecificWarnings>4267;4244;4018</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalIncludeDirectories>./libharu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Msimg32.lib;comctl32.lib;odbc32.lib;odbccp32.lib;winmm.lib;ws2_32.lib;wininet.lib;zlibstat.lib;libharu.lib;RestBed.lib;libpng.lib;libmysql.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>./lib64</AdditionalLibraryDirectories>
</Link>
<Manifest>
<AdditionalManifestFiles>meos_dpi_manifest.xml %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="animationdata.cpp" />
<ClCompile Include="autocomplete.cpp" />
<ClCompile Include="autotask.cpp" />
<ClCompile Include="binencoder.cpp" />
<ClCompile Include="classconfiginfo.cpp" />
<ClCompile Include="csvparser.cpp" />
<ClCompile Include="download.cpp" />
<ClCompile Include="gdioutput.cpp" />
<ClCompile Include="generalresult.cpp" />
<ClCompile Include="HTMLWriter.cpp" />
<ClCompile Include="image.cpp" />
<ClCompile Include="importformats.cpp" />
<ClCompile Include="infoserver.cpp" />
<ClCompile Include="iof30interface.cpp" />
<ClCompile Include="listeditor.cpp" />
<ClCompile Include="liveresult.cpp" />
<ClCompile Include="localizer.cpp" />
<ClCompile Include="machinecontainer.cpp" />
<ClCompile Include="meos.cpp" />
<ClCompile Include="MeOSFeatures.cpp" />
<ClCompile Include="MeosSQL.cpp" />
<ClCompile Include="meosversion.cpp" />
<ClCompile Include="meos_util.cpp" />
<ClCompile Include="metalist.cpp" />
<ClCompile Include="methodeditor.cpp" />
<ClCompile Include="mysqldaemon.cpp" />
<ClCompile Include="mysqlwrapper.cpp" />
<ClCompile Include="newcompetition.cpp" />
<ClCompile Include="oBase.cpp" />
<ClCompile Include="oCard.cpp" />
<ClCompile Include="oClass.cpp" />
<ClCompile Include="oClub.cpp" />
<ClCompile Include="oControl.cpp" />
<ClCompile Include="oCourse.cpp" />
<ClCompile Include="oDataContainer.cpp" />
<ClCompile Include="oEvent.cpp" />
<ClCompile Include="oEventDraw.cpp" />
<ClCompile Include="oEventResult.cpp" />
<ClCompile Include="oEventSpeaker.cpp" />
<ClCompile Include="oEventSQL.cpp" />
<ClCompile Include="oevent_transfer.cpp" />
<ClCompile Include="oFreeImport.cpp" />
<ClCompile Include="oFreePunch.cpp" />
<ClCompile Include="oImportExport.cpp" />
<ClCompile Include="oListInfo.cpp" />
<ClCompile Include="onlineinput.cpp" />
<ClCompile Include="onlineresults.cpp" />
<ClCompile Include="oPunch.cpp" />
<ClCompile Include="oReport.cpp" />
<ClCompile Include="oRunner.cpp" />
<ClCompile Include="oTeam.cpp" />
<ClCompile Include="oTeamEvent.cpp" />
<ClCompile Include="parser.cpp" />
<ClCompile Include="pdfwriter.cpp" />
<ClCompile Include="prefseditor.cpp" />
<ClCompile Include="printer.cpp" />
<ClCompile Include="progress.cpp" />
<ClCompile Include="qf_editor.cpp" />
<ClCompile Include="qualification_final.cpp" />
<ClCompile Include="random.cpp" />
<ClCompile Include="recorder.cpp" />
<ClCompile Include="restserver.cpp" />
<ClCompile Include="RestService.cpp" />
<ClCompile Include="RunnerDB.cpp" />
<ClCompile Include="socket.cpp" />
<ClCompile Include="speakermonitor.cpp" />
<ClCompile Include="SportIdent.cpp" />
<ClCompile Include="StdAfx.cpp" />
<ClCompile Include="TabAuto.cpp" />
<ClCompile Include="TabBase.cpp" />
<ClCompile Include="TabClass.cpp" />
<ClCompile Include="TabClub.cpp" />
<ClCompile Include="TabCompetition.cpp" />
<ClCompile Include="TabControl.cpp" />
<ClCompile Include="TabCourse.cpp" />
<ClCompile Include="Table.cpp" />
<ClCompile Include="TabList.cpp" />
<ClCompile Include="TabMulti.cpp" />
<ClCompile Include="TabRunner.cpp" />
<ClCompile Include="TabSI.cpp" />
<ClCompile Include="TabSpeaker.cpp" />
<ClCompile Include="TabTeam.cpp" />
<ClCompile Include="testmeos.cpp" />
<ClCompile Include="tests.cpp" />
<ClCompile Include="TimeStamp.cpp" />
<ClCompile Include="toolbar.cpp" />
<ClCompile Include="xmlparser.cpp" />
<ClCompile Include="zip.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="animationdata.h" />
<ClInclude Include="autocomplete.h" />
<ClInclude Include="autocompletehandler.h" />
<ClInclude Include="autotask.h" />
<ClInclude Include="binencoder.h" />
<ClInclude Include="classconfiginfo.h" />
<ClInclude Include="csvparser.h" />
<ClInclude Include="download.h" />
<ClInclude Include="gdiconstants.h" />
<ClInclude Include="gdifonts.h" />
<ClInclude Include="gdiimpl.h" />
<ClInclude Include="gdioutput.h" />
<ClInclude Include="gdistructures.h" />
<ClInclude Include="generalresult.h" />
<ClInclude Include="guihandler.h" />
<ClInclude Include="HTMLWriter.h" />
<ClInclude Include="image.h" />
<ClInclude Include="importformats.h" />
<ClInclude Include="infoserver.h" />
<ClInclude Include="inthashmap.h" />
<ClInclude Include="intkeymap.hpp" />
<ClInclude Include="intkeymapimpl.hpp" />
<ClInclude Include="iof30interface.h" />
<ClInclude Include="listeditor.h" />
<ClInclude Include="liveresult.h" />
<ClInclude Include="localizer.h" />
<ClInclude Include="machinecontainer.h" />
<ClInclude Include="meos.h" />
<ClInclude Include="meosexception.h" />
<ClInclude Include="MeOSFeatures.h" />
<ClInclude Include="MeosSQL.h" />
<ClInclude Include="meos_util.h" />
<ClInclude Include="metalist.h" />
<ClInclude Include="methodeditor.h" />
<ClInclude Include="mysqlwrapper.h" />
<ClInclude Include="oBase.h" />
<ClInclude Include="oCard.h" />
<ClInclude Include="oClass.h" />
<ClInclude Include="oClub.h" />
<ClInclude Include="oControl.h" />
<ClInclude Include="oCourse.h" />
<ClInclude Include="oDataContainer.h" />
<ClInclude Include="oEvent.h" />
<ClInclude Include="oEventDraw.h" />
<ClInclude Include="oFreeImport.h" />
<ClInclude Include="oFreePunch.h" />
<ClInclude Include="oListInfo.h" />
<ClInclude Include="onlineinput.h" />
<ClInclude Include="onlineresults.h" />
<ClInclude Include="oPunch.h" />
<ClInclude Include="oRunner.h" />
<ClInclude Include="ospeaker.h" />
<ClInclude Include="oTeam.h" />
<ClInclude Include="parser.h" />
<ClInclude Include="pdfwriter.h" />
<ClInclude Include="prefseditor.h" />
<ClInclude Include="Printer.h" />
<ClInclude Include="progress.h" />
<ClInclude Include="qf_editor.h" />
<ClInclude Include="qualification_final.h" />
<ClInclude Include="random.h" />
<ClInclude Include="recorder.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="restserver.h" />
<ClInclude Include="RestService.h" />
<ClInclude Include="RunnerDB.h" />
<ClInclude Include="socket.h" />
<ClInclude Include="speakermonitor.h" />
<ClInclude Include="SportIdent.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="subcommand.h" />
<ClInclude Include="TabAuto.h" />
<ClInclude Include="TabBase.h" />
<ClInclude Include="TabClass.h" />
<ClInclude Include="TabClub.h" />
<ClInclude Include="TabCompetition.h" />
<ClInclude Include="TabControl.h" />
<ClInclude Include="TabCourse.h" />
<ClInclude Include="Table.h" />
<ClInclude Include="TabList.h" />
<ClInclude Include="TabMulti.h" />
<ClInclude Include="TabRunner.h" />
<ClInclude Include="TabSI.h" />
<ClInclude Include="TabSpeaker.h" />
<ClInclude Include="TabTeam.h" />
<ClInclude Include="testmeos.h" />
<ClInclude Include="timeconstants.hpp" />
<ClInclude Include="TimeStamp.h" />
<ClInclude Include="toolbar.h" />
<ClInclude Include="xmlparser.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="meos.rc" />
<ResourceCompile Include="meoslang.rc" />
</ItemGroup>
<ItemGroup>
<None Include="html1.htm" />
</ItemGroup>
<ItemGroup>
<Image Include="announcer24.png" />
<Image Include="bitmap1.bmp" />
<Image Include="bmp00001.bmp" />
<Image Include="class24.png" />
<Image Include="clubs24.png" />
<Image Include="competition24.png" />
<Image Include="course24.png" />
<Image Include="ctrl24.png" />
<Image Include="edit.png" />
<Image Include="info24.png" />
<Image Include="lists24.png" />
<Image Include="meos.ICO" />
<Image Include="meos.png" />
<Image Include="readout24.png" />
<Image Include="runner24.png" />
<Image Include="services24.png" />
<Image Include="team24.png" />
<Image Include="title.png" />
<Image Include="warn24.png" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -470,6 +470,12 @@ void MeosSQL::upgradeDB(const string &db, oDataContainer const * dc) {
sql = sql.substr(0, sql.length() - 2);
query.execute(sql);
}
if (!eCol.count("Origin")) {
string sql = "ALTER TABLE " + db + " ";
sql += "ADD COLUMN " + C_INT("Origin");
sql = sql.substr(0, sql.length() - 2);
query.execute(sql);
}
}
if (dc) {
// Ugrade table
@ -700,7 +706,8 @@ bool MeosSQL::openDB(oEvent *oe)
<< C_INT("CardNo")
<< C_INT("Time")
<< C_INT("Type")
<< C_INT("Unit") << C_END();
<< C_INT("Unit")
<< C_INT("Origin") << C_END();
query.execute();
upgradeDB("oPunch", nullptr);
@ -1622,6 +1629,8 @@ void MeosSQL::storePunch(const RowWrapper &row, oFreePunch &p, bool rehash)
p.type = row["Type"];
}
p.punchUnit = row["Unit"];
p.origin = row["Origin"];
p.sqlUpdated = row["Modified"];
p.counter = row["Counter"];
p.Removed = row["Removed"];
@ -2953,6 +2962,7 @@ OpFailStatus MeosSQL::syncUpdate(oFreePunch *c, bool forceWriteAll)
queryset << " CardNo=" << c->CardNo << ", "
<< " Type=" << c->type << ","
<< " Time=" << c->punchTime << ","
<< " Origin=" << c->origin << ","
<< " Unit=" << c->punchUnit;
return syncUpdate(queryset, "oPunch", c);

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,7 +28,7 @@
#include <ShellAPI.h>
int AutomaticCB(gdioutput *gdi, int type, void *data);
int AutomaticCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
RestService::RestService() : AutoMachine("Informationsserver", Machines::mInfoService), port(-1) {
}
@ -88,12 +88,12 @@ void RestService::settings(gdioutput &gdi, oEvent &oe, State state) {
gdi.pushX();
gdi.addCheckbox("AllowEntry", "Tillåt anmälan", 0, false).setHandler(this);
gdi.addSelection("PermissionPerson", 180, 200, 0, L"Vem får anmäla sig:");
gdi.addItem("PermissionPerson", RestServer::getPermissionsPersons());
gdi.setItems("PermissionPerson", RestServer::getPermissionsPersons());
gdi.autoGrow("PermissionPerson");
gdi.selectFirstItem("PermissionPerson");
gdi.fillDown();
gdi.addSelection("PermissionClass", 180, 200, 0, L"Till vilka klasser:");
gdi.addItem("PermissionClass", RestServer::getPermissionsClass());
gdi.setItems("PermissionClass", RestServer::getPermissionsClass());
gdi.autoGrow("PermissionClass");
gdi.selectFirstItem("PermissionClass");
bool disablePermisson = true;

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -464,7 +464,7 @@ void RunnerDB::compactifyClubs()
ba=nba;
}
}
swap(ref, *best);
std::swap(ref, *best);
//Update map
for (size_t j=0;j<compacted.size();j++) {
@ -789,7 +789,7 @@ string RunnerDB::getDataDate() const
void RunnerDB::setDataDate(const string &date)
{
int d = convertDateYMS(date.substr(0, 10), false);
int d = convertDateYMD(date.substr(0, 10), false);
int t = date.length()>11 ? convertAbsoluteTimeHMS(date.substr(11), -1) : 0;
if (d<=0)
@ -1960,7 +1960,7 @@ const wstring& RunnerDBEntry::getBirthDate() const {
void RunnerDBEntry::setBirthDate(const wstring& in) {
SYSTEMTIME st;
if (convertDateYMS(in, st, true) > 0) {
if (convertDateYMD(in, st, true) > 0) {
setBirthYear(st.wYear);
setBirthMonth(st.wMonth);
setBirthDay(st.wDay);

View File

@ -11,7 +11,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -385,7 +385,7 @@ private:
protected:
/** Get internal data buffers for DI */
oDataContainer &getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const;
int getDISize() const {return 0;}
int getDISize() const final {return 0;}
void changedObject() {}
public:
void merge(const oBase &input, const oBase * base) final {}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1858,7 +1858,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
}
string2Wide(lastNameByte, lastName);
wcsncpy(card.lastName, lastName.c_str(), 20);
wcsncpy_s(card.lastName, lastName.c_str(), 20);
card.lastName[20] = 0;
memcpy(firstNameByte, data+32+20, 20);
@ -1869,7 +1869,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
}
string2Wide(firstNameByte, firstName);
wcsncpy(card.firstName, firstName.c_str(), 20);
wcsncpy_s(card.firstName, firstName.c_str(), 20);
card.firstName[20] = 0;
data+=128-16;

View File

@ -9,7 +9,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -96,6 +96,9 @@ struct SICard
int relativeFinishTime;
bool statusOK;
bool statusDNF;
//
bool isDebugCard = false;
vector<string> codeLogData(gdioutput &converter, int row) const;
static vector<string> logHeader();

View File

@ -1,9 +1,13 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define NOMINMAX
#include <winsdkver.h>
#define WINVER 0x0A00
#define _WIN32_WINNT 0x0601 // Target Windows 7.
#include <sdkddkver.h>
#include <windows.h>
#include <commctrl.h>
#include "timeconstants.hpp"
@ -20,8 +24,34 @@
#include <string>
#include <fstream>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <deque>
#include <algorithm>
using std::shared_ptr;
using std::string;
using std::wstring;
using std::vector;
using std::list;
using std::map;
using std::set;
using std::pair;
using std::make_pair;
using std::make_shared;
using std::unordered_set;
using std::unordered_map;
using std::min;
using std::max;
using std::numeric_limits;
using std::multimap;
using std::unique_ptr;
using std::deque;
using std::tuple;
using namespace std;
bool getUserFile(wchar_t *fileNamePath, const wchar_t *fileName);
bool getDesktopFile(wchar_t *fileNamePath, const wchar_t *fileName, const wchar_t *subFolder = 0);
bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -163,8 +163,7 @@ void tabForceSync(gdioutput &gdi, pEvent oe) {
tabAuto->syncCallback(gdi);
}
int AutomaticCB(gdioutput *gdi, int type, void *data)
{
int AutomaticCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
if (!tabAuto)
throw std::exception("tabAuto undefined.");
@ -178,6 +177,10 @@ int AutomaticCB(gdioutput *gdi, int type, void *data)
ListBoxInfo lbi=*static_cast<ListBoxInfo *>(data);
return tabAuto->processListBox(*gdi, lbi);
}
case GuiEventType::GUI_POSTCLEAR:
case GuiEventType::GUI_CLEAR:
return tabAuto->clearPage(*gdi, type == GUI_POSTCLEAR);
}
return 0;
}
@ -289,11 +292,47 @@ void TabAuto::setTimer(AutoMachine *am)
}
}
bool TabAuto::clearPage(gdioutput &gdi, bool postClear) {
if (!postClear) {
if (wasSaved) {
AutoMachine* sm = getMachine(currentMachineEditId);
if (sm && wasCreated)
stopMachine(sm);
}
else {
auto ans = gdi.askCancel(wasCreated ? L"Vill du starta automaten?" : L"Vill du spara ändringar?");
if (ans == gdioutput::AskAnswer::AnswerCancel)
return false;
else {
AutoMachine* sm = getMachine(currentMachineEditId);
if (sm) {
if (ans == gdioutput::AskAnswer::AnswerYes) {
sm->save(*oe, gdi, true);
setTimer(sm);
updateSyncInfo();
}
else {
if (wasCreated)
stopMachine(sm);
}
}
return true;
}
}
}
else {
currentMachineEditId = -1;
wasSaved = false;
wasCreated = false;
}
return true;
}
int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
{
if (bu.id=="GenerateCMP") {
#ifndef MEOSDB
int nClass=gdi.getTextNo("nClass");
int nRunner=gdi.getTextNo("nRunner");
@ -303,7 +342,6 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.getTabs().get(TCmpTab)->loadPage(gdi);
return 0;
}
#endif
}
else if (bu.id == "BrowseFolder") {
const wchar_t *edit = bu.getExtra();
@ -399,6 +437,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
if (gdi.hasWidget("Interval"))
iv = gdi.getText("Interval");
sm->saveMachine(*oe, iv);
wasSaved = true;
oe->updateChanged();
oe->synchronize(false);
}
@ -531,11 +570,15 @@ void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, AutoMachine::State state
rc.left = cx - d;
rc.right = w + d;
gdi.addRectangle(rc, colorLightBlue, true, true);
gdi.setOnClearCb(AutomaticCB);
gdi.setPostClearCb(AutomaticCB);
currentMachineEditId = sm->getId();
wasCreated = (state == AutoMachine::State::Create) || (state == AutoMachine::State::Load);
wasSaved = false;
gdi.refresh();
}
void TabAuto::killMachines()
{
void TabAuto::killMachines() {
while(!machines.empty()) {
machines.back()->stop();
delete machines.back();
@ -544,8 +587,7 @@ void TabAuto::killMachines()
AutoMachine::resetGlobalId();
}
bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
{
bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast) {
oe->checkDB();
oe->synchronize();
tabAuto=this;
@ -773,7 +815,7 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
gdi.pushX();
gdi.fillDown();
vector< pair<wstring, size_t> > d;
gdi.addItem("Classes", oe.fillClasses(d, oEvent::extraNone, oEvent::filterNone));
gdi.setItems("Classes", oe.fillClasses(d, oEvent::extraNone, oEvent::filterNone));
gdi.setSelection("Classes", classesToPrint);
gdi.addSelection("ListType", 200, 100, 0, L"Lista");
@ -797,7 +839,7 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
set<int> clsUnused;
vector< pair<wstring, size_t> > out;
oe.fillLegNumbers(clsUnused, listInfo.isTeamList(), true, out);
gdi.addItem("LegNumber", out);
gdi.setItems("LegNumber", out);
gdi.selectItemByData("LegNumber", listInfo.getLegNumberCoded());
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, pageBreak);
@ -981,7 +1023,7 @@ void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, State state) {
gdi.fillDown();
vector< pair<wstring, size_t> > d;
oe.fillControls(d, oEvent::ControlType::CourseControl);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
gdi.setSelection("Controls", controls);
gdi.popX();
gdi.addButton("SelectAll", "Välj alla", AutomaticCB, "").setExtra(L"Controls");
@ -1205,7 +1247,7 @@ void SplitsMachine::save(oEvent &oe, gdioutput &gdi, bool doProcess) {
if (doProcess) {
//Try exporting.
oe.exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
set<int>(), -1, false, true, true, false, false);
set<int>(), make_pair("",""), -1, false, true, true, false, false);
interval = iv;
synchronize = true;
}
@ -1244,7 +1286,8 @@ void SplitsMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
{
if ((interval>0 && ast==SyncTimer) || (interval==0 && ast==SyncDataUp)) {
if (!file.empty())
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false, classes,
oe->exportIOFSplits(oEvent::IOF20, file.c_str(),
true, false, classes, make_pair("", ""),
leg, false, true, true, false, false);
}
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -311,12 +311,12 @@ class TabAuto :
public TabBase
{
private:
//DWORD printResultIntervalSec;
//DWORD printResultTimeOut;
bool editMode;
bool synchronize;
bool synchronizePunches;
bool editMode = false;
int currentMachineEditId = -1;
bool wasCreated = false;
bool wasSaved = false;
bool synchronize = false;
bool synchronizePunches = false;
void updateSyncInfo();
list<AutoMachine *> machines;
@ -336,6 +336,7 @@ public:
AutoMachine *getMachine(int id);
bool stopMachine(AutoMachine *am);
void killMachines();
bool clearPage(gdioutput &gdi, bool postClear);
AutoMachine &addMachine(const AutoMachine &am) {
machines.push_back(am.clone());

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -190,19 +190,6 @@ void FixedTabs::clearCompetitionData() {
tabs[k]->clearCompetitionData();
}
TabObject::TabObject(TabBase *t)
{
tab = t;
tab->tabId = id;
}
TabObject::~TabObject()
{
//delete tab;
}
bool TabObject::loadPage(gdioutput &gdi)
{
if (tab)

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -74,42 +74,23 @@ public:
class TabObject
{
protected:
mutable TabBase *tab;
TabBase * const tab = nullptr;
public:
string name;
int id;
const string name;
const int imageId = -1;
int id = -1;
TabObject(TabBase *t, string n):name(n),tab(t) {}
TabObject(TabBase *t, string n, int imageId) : name(n), tab(t), imageId(imageId) {}
void setId(int i){id=i; if (tab) tab->tabId=id;}
void setPage(TabBase *tb){delete tab; tab=tb;}
const type_info &getType() const {return typeid(*tab);}
const TabBase &getTab() const {return *tab;}
TabObject(const TabObject &t)
{
if (&t!=this) {
name=t.name;
id=t.id;
tab=t.tab;
//t.tab=0;
}
}
TabObject &operator=(TabObject &t)
{
if (&t!=this) {
delete tab;
name=t.name;
id=t.id;
tab=t.tab;
//t.tab=0;
}
}
TabObject(TabBase *t);
~TabObject();
TabObject(const TabObject& t) = delete;
TabObject& operator=(TabObject& t) = delete;
~TabObject() = default;
bool loadPage(gdioutput &gdi);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,6 +24,8 @@
#include "tabbase.h"
#include "oEventDraw.h"
class QFEditor;
class TabClass :
public TabBase
{
@ -45,7 +47,6 @@ class TabClass :
double pTimeScaling;
int pInterval;
class HandleCloseWindow : public GuiHandler {
TabClass *tabClass;
HandleCloseWindow(const HandleCloseWindow&);
@ -57,7 +58,6 @@ class TabClass :
};
HandleCloseWindow handleCloseWindow;
bool EditChanged;
int ClassId;
int currentStage;
@ -72,6 +72,8 @@ class TabClass :
vector<ClassInfo> cInfo;
void saveDrawSettings() const;
void dynamicStart(gdioutput& gdi);
map<int, ClassInfo> cInfoCache;
DrawInfo drawInfo;
@ -120,9 +122,6 @@ class TabClass :
void showClassSelection(gdioutput &gdi, int &bx, int &by, GUICALLBACK classesCB) const;
// Set simultaneous start in a class
void simultaneous(int classId, const wstring &time, int nVacant);
void updateFairForking(gdioutput &gdi, pClass pc) const;
void selectCourses(gdioutput &gdi, int legNo);
bool showMulti(bool singleOnly) const;
@ -168,11 +167,15 @@ class TabClass :
void fillResultModules(gdioutput &gdi, pClass pc);
shared_ptr<GuiHandler> startGroupHandler;
shared_ptr<QFEditor> qfEditor;
public:
void loadStartGroupSettings(gdioutput &gdi, bool reload);
void drawStartGroups(gdioutput &gdi);
// Set simultaneous start in a class
static void simultaneous(oEvent &oe, int classId, const wstring& time, int nVacant);
void clearCompetitionData();
void closeWindow(gdioutput &gdi);
@ -182,14 +185,14 @@ public:
bool loadPage(gdioutput &gdi);
void selectClass(gdioutput &gdi, int cid);
int classCB(gdioutput &gdi, int type, void *data);
int multiCB(gdioutput &gdi, int type, void *data);
int classCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
int multiCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
const char * getTypeStr() const {return "TClassTab";}
TabType getType() const {return TClassTab;}
friend int DrawClassesCB(gdioutput *gdi, int type, void *data);
friend int DrawClassesCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
TabClass(oEvent *oe);
~TabClass(void);
~TabClass();
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -108,14 +108,12 @@ void ageFilter(gdioutput &gdi, bool on, bool use) {
gdi.setInputStatus("FilterAge", use);
}
int ClubsCB(gdioutput *gdi, int type, void *data)
{
int ClubsCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabClub &tc = dynamic_cast<TabClub &>(*gdi->getTabs().get(TClubTab));
return tc.clubCB(*gdi, type, data);
}
int TabClub::clubCB(gdioutput &gdi, int type, void *data)
{
int TabClub::clubCB(gdioutput &gdi, GuiEventType type, BaseInfo* data) {
if (type==GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data;
@ -414,7 +412,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
oe->fillClassTypes(types);
oe->fillClasses(classes, oEvent::extraNone, oEvent::filterNone);
types.insert(types.end(), classes.begin(), classes.end());
gdi.addItem("ClassType", types);
gdi.setItems("ClassType", types);
gdi.addItem("ClassType", lang.tl("Alla typer"), -5);
gdi.selectItemByData("ClassType", -5);

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@
class TabClub :
public TabBase
{
int clubCB(gdioutput &gdi, int type, void *data);
int clubCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
wstring firstDate;
wstring lastDate;
@ -59,5 +59,5 @@ public:
TabClub(oEvent *oe);
~TabClub(void);
friend int ClubsCB(gdioutput *gdi, int type, void *data);
friend int ClubsCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,7 +67,7 @@ void exportSetup();
void resetSaveTimer();
extern bool enableTests;
int ListsCB(gdioutput *gdi, int type, void *data);
int ListsCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
TabCompetition::TabCompetition(oEvent *poe):TabBase(poe)
{
@ -198,7 +198,7 @@ bool TabCompetition::exportFileAs(HWND hWnd, gdioutput &gdi)
return true;
}
int CompetitionCB(gdioutput *gdi, int type, void *data)
int CompetitionCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi->getTabs().get(TCmpTab));
@ -206,8 +206,7 @@ int CompetitionCB(gdioutput *gdi, int type, void *data)
}
int restoreCB(gdioutput *gdi, int type, void *data)
{
int restoreCB(gdioutput *gdi, GuiEventType type, BaseInfo *data) {
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi->getTabs().get(TCmpTab));
return tc.restoreCB(*gdi, type, data);
@ -359,7 +358,7 @@ bool TabCompetition::checkEventor(gdioutput &gdi, ButtonInfo &bi) {
return false;
}
int eventorServer(gdioutput *gdi, int type, void *data) {
int eventorServer(gdioutput *gdi, GuiEventType type, BaseInfo *data) {
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi->getTabs().get(TCmpTab));
if (type == GUI_COMBO) {
const ListBoxInfo &lbi = *((ListBoxInfo *)data);
@ -390,8 +389,7 @@ bool TabCompetition::useEventorUTC() const {
enum StartMethod {SMCommon = 1, SMDrawn, SMFree, SMCustom};
int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
{
int TabCompetition::competitionCB(gdioutput &gdi, GuiEventType type, BaseInfo *data) {
if (type == GUI_LINK) {
TextInfo ti = *(TextInfo *)data;
if (ti.id == "link") {
@ -569,10 +567,10 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.addButton("Cancel", "Återgå", CompetitionCB);
gdi.dropLine();
if (prefsEditor.empty())
prefsEditor.push_back(PrefsEditor(oe));
if (!prefsEditor)
prefsEditor = make_shared<PrefsEditor>(oe);
prefsEditor->showPrefs(gdi);
prefsEditor.back().showPrefs(gdi);
gdi.refresh();
}
else if (bi.id=="Test") {
@ -1143,7 +1141,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
wstring startlist = getTempFile();
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
oe->exportIOFStartlist(oEvent::IOF30, startlist.c_str(), eventorUTC,
set<int>(), false, false, true, true);
set<int>(), make_pair("",""), false, false, true, true);
vector<wstring> fileList;
fileList.push_back(startlist);
@ -1236,7 +1234,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
set<int> classes;
bool eventorUTC = oe->getPropertyInt("UseEventorUTC", 0) != 0;
oe->exportIOFSplits(oEvent::IOF30, resultlist.c_str(), false,
eventorUTC, classes, -1, false, true,
eventorUTC, classes, make_pair("", ""), -1, false, true,
false, true, true);
vector<wstring> fileList;
fileList.push_back(resultlist);
@ -1531,7 +1529,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.dropLine();
gdi.addString("", 1, "Behandlar tävlingsdata").setColor(colorGreen);
set<int> noFilter;
string noType;
pair<string, string> noType;
if (createNew && id>0) {
gdi.addString("", 1, "Skapar ny tävling");
@ -1559,9 +1557,12 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
removeTempFile(tClass);
set<int> stageFilter;
string preferredIdType;
pair<string, string> preferredIdType;
checkStageFilter(gdi, tEntry, stageFilter, preferredIdType);
oe->importXML_EntryData(gdi, tEntry.c_str(), false, removeRemoved, stageFilter, 0, 0, preferredIdType);
if (!preferredIdType.second.empty())
oe->setRunnerIdTypes(preferredIdType);
removeTempFile(tEntry);
if (!course.empty()) {
@ -1791,6 +1792,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->setProperty("ExpWithRaceNo", includeStage);
}
auto preferredIdTypes = getPreferredIdTypes(gdi);
gdi.getSelection("ClassNewEntries", allTransfer);
ImportFormats::ExportFormats filterIndex = ImportFormats::setExportFormat(*oe, gdi.getSelectedItem("Type").first);
int cSVLanguageHeaderIndex = gdi.getSelectedItem("LanguageType").first;
@ -1800,7 +1803,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (filterIndex == ImportFormats::IOF30 || filterIndex == ImportFormats::IOF203) {
bool useUTC = oe->getDCI().getInt("UTC") != 0;
oe->exportIOFStartlist(filterIndex == ImportFormats::IOF30 ? oEvent::IOF30 : oEvent::IOF20,
save.c_str(), useUTC, allTransfer, individual, includeStage, false, false);
save.c_str(), useUTC, allTransfer, preferredIdTypes, individual, includeStage, false, false);
}
else if (filterIndex == ImportFormats::OE) {
oe->exportOECSV(save.c_str(), allTransfer, cSVLanguageHeaderIndex, false);
@ -1849,6 +1852,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->setProperty("ExpWithRaceNo", includeStage);
}
auto preferredIdTypes = getPreferredIdTypes(gdi);
gdi.setWaitCursor(true);
if (filterIndex == ImportFormats::IOF30 || filterIndex == ImportFormats::IOF203) {
oEvent::IOFVersion ver = filterIndex == ImportFormats::IOF30 ? oEvent::IOF30 : oEvent::IOF20;
@ -1858,7 +1863,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (!gdi.hasWidget("LegType")) {
oe->exportIOFSplits(ver, save.c_str(), true, useUTC,
allTransfer, -1, false, unroll, includeStage, false, false);
allTransfer, preferredIdTypes, -1, false, unroll, includeStage, false, false);
}
else {
ListBoxInfo leglbi;
@ -1880,16 +1885,16 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
for (int leg = 0; leg<legMax; leg++) {
file = fileBase + L"_" + itow(leg+1) + fileEnd;
oe->exportIOFSplits(ver, file.c_str(), true, useUTC,
allTransfer, leg, false, unroll, includeStage, false, false);
allTransfer, preferredIdTypes, leg, false, unroll, includeStage, false, false);
}
}
else if (leglbi.data == 3) {
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer, preferredIdTypes,
-1, true, unroll, includeStage, false, false);
}
else {
int leg = leglbi.data == 1 ? -1 : leglbi.data - 10;
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer,
oe->exportIOFSplits(ver, file.c_str(), true, useUTC, allTransfer, preferredIdTypes,
leg, false, unroll, includeStage, false, false);
}
}
@ -2202,6 +2207,14 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
else if (type==GUI_LISTBOX) {
ListBoxInfo lbi=*(ListBoxInfo *)data;
if (lbi.id == "DataFields") {
oEvent::ExtraFieldContext context = oEvent::ExtraFieldContext(gdi.getDataInt("DataFieldsContext"));
saveExtraFields(gdi, context);
oe->synchronize(true);
oEvent::ExtraFieldContext contextNew = oEvent::ExtraFieldContext(lbi.data);
showExtraFields(gdi, contextNew);
}
if (lbi.id=="LocalCmp") {
gdi.selectItemByData("ServerCmp", -1);
gdi.disableInput("Repair", true);
@ -2302,7 +2315,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
gdi.setData("RunnerIx", ix);
gdi.dropLine();
gdi.addSelection("Classes", 200, 300, 0, L"Klasser:");
oe->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterOnlySingle);
oe->fillClasses(gdi, "Classes", {}, oEvent::extraNone, oEvent::filterOnlySingle);
if (lastSelectedClass == -1 || !gdi.selectItemByData("Classes", lastSelectedClass))
gdi.selectFirstItem("Classes");
@ -2357,8 +2370,8 @@ void TabCompetition::openCompetition(gdioutput &gdi, int id) {
}
}
int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
TextInfo &ti = *(TextInfo *)data;
int TabCompetition::restoreCB(gdioutput &gdi, GuiEventType type, BaseInfo *data) {
TextInfo &ti = dynamic_cast<TextInfo&>(*data);
int id = ti.getExtraInt();
const BackupInfo &bi = oe->getBackup(id);
@ -2417,7 +2430,7 @@ void TabCompetition::copyrightLine(gdioutput &gdi) const
gdi.dropLine(0.4);
gdi.fillDown();
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2023 Melin Software HB"));
gdi.addString("", 0, makeDash(L"#Copyright © 2007-2024 Melin Software HB"));
gdi.dropLine(1);
gdi.popX();
@ -2447,12 +2460,9 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
gdi.dropLine(1.5);
gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2023 Melin Software HB"));
gdi.addStringUT(1, makeDash(L"Copyright © 2007-2024 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,"
"\nand (c) 2004-2007 by Educational Technology Resources, Inc.\n"
"The database used is MySQL, Copyright (c) 2008-2017 Oracle, Inc."
gdi.addStringUT(10, "The database used is MySQL, Copyright (c) 2008-2024 Oracle, Inc."
"\n\nGerman Translation by Erik Nilsson-Simkovics"
"\n\nDanish Translation by Michael Leth Jess and Chris Bagge"
"\n\nRussian Translation by Paul A. Kazakov and Albert Salihov"
@ -2462,8 +2472,10 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
"\n\nCzech Translation by Marek Kustka"
"\n\nSpanish Translation by Manuel Pedre"
"\n\nUkranian Translation by Oleg Rozhko"
"\n\nPortuguese Translation by Bruno Santos"
"\n\nHelp with English documentation: Torbjörn Wikström");
gdi.dropLine();
gdi.addString("", 0, "Det här programmet levereras utan någon som helst garanti. Programmet är ");
gdi.addString("", 0, "fritt att använda och du är välkommen att distribuera det under vissa villkor,");
@ -2519,6 +2531,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
gdi.fillDown();
if (oe->empty()) {
gdi.selectTab(tabId);
gdi.addString("", 2, "Välkommen till MeOS");
gdi.addString("", 1, makeDash(L"#- ")+ lang.tl("ett Mycket Enkelt OrienteringsSystem")).setColor(colorDarkBlue);
gdi.dropLine();
@ -2578,7 +2591,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
vector< pair<wstring, size_t> > tests;
TestMeOS tm(oe, "ALL");
tm.getTests(tests);
gdi.addItem("Tests", tests);
gdi.setItems("Tests", tests);
gdi.selectFirstItem("Tests");
gdi.addButton("RunSpecificTest", "#Run", CompetitionCB);
@ -3011,7 +3024,7 @@ void TabCompetition::getEventorCompetitions(gdioutput &gdi,
eBreak.getObjectString("Date", breakDate);
SYSTEMTIME st;
convertDateYMS(breakDate, st, false);
convertDateYMD(breakDate, st, false);
__int64 time = SystemTimeToInt64TenthSecond(st) - 10;
breakDate = convertSystemDate(Int64TenthSecondToSystemTime(time));
@ -3319,6 +3332,7 @@ void TabCompetition::loadRunnerDB(gdioutput &gdi, int tableToShow, bool updateTa
void TabCompetition::welcomeToMeOS(gdioutput &gdi) {
gdi.clearPage(false, false);
gdi.selectTab(tabId);
gdi.scaleSize(1.4*gdi.getScale());
gdi.dropLine(5);
gdi.setCX(gdi.getCX() + 5*gdi.getLineHeight());
@ -3372,7 +3386,7 @@ void TabCompetition::selectTransferClasses(gdioutput &gdi, bool expand) {
if (expand) {
gdi.fillDown();
gdi.addListBox("ClassNewEntries", 200, 400, 0, L"Klasser där nyanmälningar ska överföras:", L"", true);
oe->fillClasses(gdi, "ClassNewEntries", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "ClassNewEntries", {}, oEvent::extraNone, oEvent::filterNone);
gdi.setSelection("ClassNewEntries", allTransfer);
gdi.pushX();
@ -3396,14 +3410,14 @@ void TabCompetition::selectTransferClasses(gdioutput &gdi, bool expand) {
gdi.refresh();
}
static int ClearFeaturesCB(gdioutput *gdi, int type, void *data)
static int ClearFeaturesCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi->getTabs().get(TCmpTab));
tc.saveMeosFeatures(*gdi, true);
return 1;
}
static int CheckFeaturesCB(gdioutput *gdi, int type, void *data)
static int CheckFeaturesCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
TabCompetition &tc = dynamic_cast<TabCompetition &>(*gdi->getTabs().get(TCmpTab));
tc.saveMeosFeatures(*gdi, false);
@ -3653,13 +3667,16 @@ FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool removeRemoved, in
}
else {
set<int> stageFilter;
string preferredIdType;
pair<string, string> preferredIdType;
FlowOperation res = checkStageFilter(gdi, filename[i], stageFilter, preferredIdType);
if (res != FlowContinue)
return res;
if (!preferredIdType.second.empty())
oe->setRunnerIdTypes(preferredIdType);
const int courseIdOffset = 0;
oe->importXML_EntryData(gdi, filename[i], false, removeRemoved, stageFilter,
classOffset, courseIdOffset, preferredIdType);
@ -3687,10 +3704,10 @@ FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool removeRemoved, in
return FlowContinue;
}
int stageInfoCB(gdioutput *gdi, int type, void *data)
int stageInfoCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
if (type == GUI_BUTTON) {
ButtonInfo &bi = *(ButtonInfo *)data;
ButtonInfo &bi = dynamic_cast<ButtonInfo &>(*data);
bi.setExtra(1);
}
return 0;
@ -3702,12 +3719,12 @@ FlowOperation importFilterGUI(oEvent *oe,
const set<int>& stages,
const vector<string> &idProviders,
set<int> & filter,
string &preferredIdProvider);
pair<string, string>&preferredIdProvider);
FlowOperation TabCompetition::checkStageFilter(gdioutput & gdi,
const wstring & fname,
set<int>& filter,
string &preferredIdProvider) {
pair<string, string> &preferredIdProvider) {
xmlparser xml;
xml.read(fname);
xmlobject xo = xml.getObject("EntryList");
@ -3728,7 +3745,7 @@ FlowOperation importFilterGUI(oEvent *oe,
const set<int>& stages,
const vector<string> &idProviders,
set<int> & filter,
string &preferredIdProvider) {
pair<string, string> &preferredIdProvider) {
auto &scanFilter = stages;
bool stageFilter = scanFilter.size() > 1;
bool idtype = idProviders.size() > 1;
@ -3748,6 +3765,7 @@ FlowOperation importFilterGUI(oEvent *oe,
gdi.fillRight();
gdi.addSelection("Stage", 150, 200, stageInfoCB, L"Välj etapp att importera:");
gdi.addItem("Stage", lang.tl("Alla"), 0);
gdi.fillDown();
for (int sn : scanFilter) {
if (sn > 0)
gdi.addItem("Stage", lang.tl("Etapp X#" + itos(sn)), sn);
@ -3757,14 +3775,12 @@ FlowOperation importFilterGUI(oEvent *oe,
gdi.selectItemByData("Stage", cn);
else
gdi.selectItemByData("Stage", 0);
gdi.popX();
gdi.dropLine(3.5);
}
if (idtype) {
if (stageFilter) {
gdi.popX();
gdi.dropLine(2);
}
gdi.dropLine(0.5);
gdi.addString("", 0, "Det finns multiplia Id-nummer för personer");
gdi.dropLine(0.5);
gdi.fillRight();
@ -3773,9 +3789,12 @@ FlowOperation importFilterGUI(oEvent *oe,
for (const string &sn : idProviders) {
gdi.addItem("IdType", gdi.widen(sn), i++);
}
gdi.popX();
gdi.dropLine(3.6);
}
if (needUseInput) {
gdi.fillRight();
gdi.dropLine();
gdi.addButton("OK_Stage", "OK", stageInfoCB);
gdi.fillDown();
@ -3817,7 +3836,14 @@ FlowOperation importFilterGUI(oEvent *oe,
if (idProviders.size() > 1) {
ListBoxInfo lbi;
if (gdi.getSelectedItem("IdType", lbi)) {
preferredIdProvider = gdi.narrow(lbi.text);
preferredIdProvider.first = gdi.narrow(lbi.text);
}
// Auto select secondary type. TODO: Manually select if not unique...
for (const string& sn : idProviders) {
if (preferredIdProvider.first != sn) {
preferredIdProvider.second = sn;
}
}
}
@ -3837,7 +3863,7 @@ void TabCompetition::selectStartlistOptions(gdioutput &gdi) {
gdi.addString("", boldLarge, "Exportera startlista");
gdi.pushY();
gdi.addListBox("ClassNewEntries", 250, 400, 0, L"Klassval:", L"", true);
oe->fillClasses(gdi, "ClassNewEntries", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "ClassNewEntries", {}, oEvent::extraNone, oEvent::filterNone);
gdi.setSelection("ClassNewEntries", allTransfer);
gdi.pushX();
@ -3854,7 +3880,7 @@ void TabCompetition::selectStartlistOptions(gdioutput &gdi) {
vector< pair<wstring, size_t> > types;
ImportFormats::getExportFormats(types, false);
gdi.addItem("Type", types);
gdi.setItems("Type", types);
ImportFormats::ExportFormats format = ImportFormats::getDefaultExportFormat(*oe);
gdi.selectItemByData("Type", format);
@ -3862,7 +3888,7 @@ void TabCompetition::selectStartlistOptions(gdioutput &gdi) {
ImportFormats::getOECSVLanguage(typeLanguages);
gdi.addSelection("LanguageType", 250, 200, CompetitionCB, L"Export language:");
gdi.addItem("LanguageType", typeLanguages);
gdi.setItems("LanguageType", typeLanguages);
gdi.selectItemByData("LanguageType", ImportFormats::getDefaultCSVLanguage(*oe));
@ -3878,6 +3904,9 @@ void TabCompetition::selectStartlistOptions(gdioutput &gdi) {
gdi.addCheckbox("IncludeRaceNumber", "Inkludera information om flera lopp per löpare", nullptr,
oe->getPropertyInt("ExpWithRaceNo", true) != 0);
pair<bool, bool> priSecondId = hasPersonExtId();
showSelectId(priSecondId, gdi);
wstring fn = oe->getPropertyString("ExpStaFilename", L"");
gdi.addInput("Filename", fn,
48, CompetitionCB, L"Filnamn:").setExtra(L"DoSaveStartlist");
@ -3892,13 +3921,34 @@ void TabCompetition::selectStartlistOptions(gdioutput &gdi) {
gdi.refresh();
}
pair<bool, bool> TabCompetition::hasPersonExtId() const {
vector<pRunner> runners;
oe->getRunners(-1, -1, runners, false);
pair<bool, bool> res(false, false);
for (pRunner r : runners) {
if (!res.first && r->getExtIdentifier() != 0) {
res.first = true;
if (res.second)
break;
}
if (!res.second && r->getExtIdentifier2() != 0) {
res.second = true;
if (res.first)
break;
}
}
return res;
}
void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
gdi.clearPage(false);
gdi.addString("", boldLarge, "Export av resultat/sträcktider");
gdi.dropLine();
gdi.pushY();
gdi.addListBox("ClassNewEntries", 250, 400, 0, L"Klassval:", L"", true);
oe->fillClasses(gdi, "ClassNewEntries", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "ClassNewEntries", {}, oEvent::extraNone, oEvent::filterNone);
gdi.setSelection("ClassNewEntries", allTransfer);
gdi.pushX();
@ -3915,7 +3965,7 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
vector<pair<wstring, size_t>> types;
ImportFormats::getExportFormats(types, true);
gdi.addItem("Type", types);
gdi.setItems("Type", types);
ImportFormats::ExportFormats format = ImportFormats::getDefaultExportFormat(*oe);
gdi.selectItemByData("Type", format);
@ -3923,7 +3973,7 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
ImportFormats::getOECSVLanguage(typeLanguages);
gdi.addSelection("LanguageType", 250, 200, CompetitionCB, L"Export language:");
gdi.addItem("LanguageType", typeLanguages);
gdi.setItems("LanguageType", typeLanguages);
gdi.selectItemByData("LanguageType", ImportFormats::getDefaultCSVLanguage(*oe));
@ -3933,7 +3983,8 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
oe->getClassConfigurationInfo(cnf);
if (cnf.hasTeamClass() || cnf.hasQualificationFinal()) {
gdi.addSelection("LegType", 300, 100, 0, L"Exportval, IOF-XML");
gdi.dropLine(0.2);
gdi.addSelection("LegType", 300, 100, 0, L"Exportval, IOF-XML:");
gdi.addItem("LegType", lang.tl("Totalresultat"), 1);
gdi.addItem("LegType", lang.tl("Alla lopp som individuella"), 3);
if (cnf.hasTeamClass()) {
@ -3961,6 +4012,9 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
gdi.addCheckbox("IncludeRaceNumber", "Inkludera information om flera lopp per löpare", 0,
oe->getPropertyInt("ExpWithRaceNo", true) != 0);
pair<bool, bool> priSecondId = hasPersonExtId();
showSelectId(priSecondId, gdi);
wstring fn = oe->getPropertyString("ExpResFilename", L"");
gdi.addInput("Filename", fn, 48, CompetitionCB, L"Filnamn:").setExtra(L"DoSaveSplits");
setExportOptionsStatus(gdi, format);
@ -3975,6 +4029,60 @@ void TabCompetition::selectExportSplitOptions(gdioutput &gdi) {
gdi.refresh();
}
void TabCompetition::showSelectId(std::pair<bool, bool>& priSecondId, gdioutput& gdi) {
class IdType : public GuiHandler {
void handle(gdioutput& gdi, BaseInfo& info, GuiEventType type) final {
string baseType = info.id.substr(0, info.id.length() - 2);
gdi.setInputStatus(baseType + "Type", gdi.isChecked(info.id));
}
};
if (priSecondId.first && priSecondId.second) {
auto idTypes = oe->getRunnerIdTypes();
gdi.dropLine(0.5);
gdi.addString("", 0, "Välj typ av ID att exportera:");
gdi.dropLine(0.3);
gdi.fillRight();
const int baseX = gdi.getCX();
gdi.addCheckbox("PrimaryId", "Primärt").setHandler(make_shared<IdType>());
const int idx = baseX + (3 * (gdi.getCX() - baseX)) / 2;
gdi.setCX(idx);
gdi.addInput("PrimaryType", idTypes.first);
gdi.popX();
gdi.dropLine(2);
gdi.fillRight();
gdi.addCheckbox("SecondaryId", "Sekundärt").setHandler(make_shared<IdType>());
gdi.setCX(max(idx, gdi.getCX()));
gdi.addInput("SecondaryType", idTypes.second);
gdi.popX();
gdi.dropLine(2);
gdi.fillDown();
}
}
pair<string, string> TabCompetition::getPreferredIdTypes(gdioutput& gdi) {
pair<string, string> preferredIdTypes;
if (gdi.hasWidget("PrimaryId")) {
if (gdi.isChecked("PrimaryId")) {
wstring pt = gdi.getText("PrimaryType");
preferredIdTypes.first = gdioutput::narrow(pt);
if (preferredIdTypes.first.empty())
preferredIdTypes.first = "PRIMARY";
}
if (gdi.isChecked("SecondaryId")) {
wstring st = gdi.getText("SecondaryType");
preferredIdTypes.second = gdioutput::narrow(st);
if (preferredIdTypes.second.empty())
preferredIdTypes.second = "SECONDARY";
}
}
return preferredIdTypes;
}
void TabCompetition::setExportOptionsStatus(gdioutput &gdi, int format) const {
if (gdi.hasWidget("LegType")) {
gdi.setInputStatus("LegType", format == ImportFormats::IOF30 || format == ImportFormats::IOF203); // Enable on IOF-XML
@ -3993,6 +4101,17 @@ void TabCompetition::setExportOptionsStatus(gdioutput &gdi, int format) const {
gdi.setInputStatus("IncludeRaceNumber", format == ImportFormats::IOF30); // Enable on IOF-XML
}
if (gdi.hasWidget("PrimaryId")) {
for (auto s : {"Primary", "Secondary" }) {
bool enable = format == ImportFormats::IOF30;
string ss = s;
string ids = ss + "Id";
// Enable on IOF-XML
gdi.setInputStatus(ids, enable);
gdi.setInputStatus(ss + "Type", enable && gdi.isChecked(ids));
}
}
gdi.setInputStatus("LanguageType", format == ImportFormats::OE);
if (gdi.hasWidget("Filename")) {
@ -4064,10 +4183,25 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
oe->getDI().buildDataFields(gdi, fields, 10);
gdi.popX();
gdi.dropLine(3);
gdi.fillDown();
gdi.addString("", gdi.getCY(), gdi.getCX(), 10| breakLines,
L"help_second_fee",
gdi.scaleLength(250));
gdi.fillRight();;
fields.clear();
fields.push_back("SecondEntryDate");
fields.push_back("SecondEntryFactor");
oe->getDI().buildDataFields(gdi, fields, 10);
gdi.fillDown();
gdi.popX();
gdi.dropLine(3);
gdi.addString("", 1, "Åldersgränser, reducerad anmälningsavgift");
gdi.addString("", 0, "Ungdomar och äldre kan få reducerad avgift");
gdi.dropLine(0.5);
@ -4199,8 +4333,21 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
gdi.dropLine(2.5);
gdi.popX();
}
bottom = max(bottom, gdi.getCY());
gdi.fillDown();
gdi.addString("", 1, "Extra datafält");
gdi.dropLine(0.2);
gdi.addSelection("DataFields", 200, 200, CompetitionCB, L"Sida:");
gdi.addItem("DataFields", lang.tl("Deltagare"), 0);
gdi.addItem("DataFields", lang.tl("Lag"), 1);
gdi.addItem("DataFields", lang.tl("Klass"), 2);
gdi.addItem("DataFields", lang.tl("Direktanmälan"), 3);
gdi.selectFirstItem("DataFields");
gdi.setData("FieldX", gdi.getCX());
gdi.setData("FieldY", gdi.getCY());
bottom = max(bottom, gdi.getCY());
gdi.popX();
gdi.setCY(bottom);
gdi.fillRight();
@ -4208,8 +4355,133 @@ void TabCompetition::loadSettings(gdioutput &gdi) {
gdi.addButton("Cancel", "Avbryt", CompetitionCB).setCancel();
gdi.dropLine(2);
gdi.setOnClearCb(CompetitionCB);
gdi.refresh();
showExtraFields(gdi, oEvent::ExtraFieldContext::Runner);
}
void TabCompetition::showExtraFields(gdioutput& gdi, oEvent::ExtraFieldContext type) {
gdi.restore("ExtraFields", false);
gdi.setRestorePoint("ExtraFields");
gdi.setData("DataFieldsContext", int(type));
auto ef = oe->getExtraFields(type);
auto efNames = oe->getExtraFieldNames();
auto getName = [&ef, &efNames](oEvent::ExtraFields field) -> wstring {
auto res = ef.find(field);
if (res != ef.end() && !res->second.empty())
return res->second;
res = efNames.find(field);
if (res != efNames.end() && !res->second.empty())
return res->second;
return L"";
};
gdi.setCX(gdi.getDataInt("FieldX"));
gdi.setCY(gdi.getDataInt("FieldY"));
gdi.dropLine(0.5);
gdi.pushX();
gdi.fillRight();
auto dataA = ef.find(oEvent::ExtraFields::DataA);
gdi.dropLine(-0.2);
gdi.addCheckbox("DataA", L"Extra data X:#(A)", nullptr, dataA != ef.end());
gdi.addInput("DataAName", getName(oEvent::ExtraFields::DataA), 16);
gdi.dropLine(2.5);
gdi.popX();
auto dataB = ef.find(oEvent::ExtraFields::DataB);
gdi.addCheckbox("DataB", L"Extra data X:#(B)", nullptr, dataB != ef.end());
gdi.dropLine(-0.2);
gdi.addInput("DataBName", getName(oEvent::ExtraFields::DataB), 16);
gdi.dropLine(2.5);
gdi.popX();
auto textA = ef.find(oEvent::ExtraFields::TextA);
gdi.addCheckbox("TextA", L"Text:", nullptr, textA != ef.end());
gdi.dropLine(-0.2);
gdi.addInput("TextAName", getName(oEvent::ExtraFields::TextA), 16);
gdi.dropLine(2.5);
gdi.popX();
if (type == oEvent::ExtraFieldContext::DirectEntry) {
gdi.addCheckbox("StartTime", L"Starttid", nullptr, ef.count(oEvent::ExtraFields::StartTime));
gdi.addCheckbox("Bib", L"Nummerlapp", nullptr, ef.count(oEvent::ExtraFields::Bib));
}
if (type != oEvent::ExtraFieldContext::Class)
gdi.addCheckbox("Nationality", L"Nationalitet", nullptr, ef.count(oEvent::ExtraFields::Nationality));
if (type == oEvent::ExtraFieldContext::DirectEntry) {
gdi.dropLine(2.5);
gdi.popX();
}
if (type == oEvent::ExtraFieldContext::Runner || type == oEvent::ExtraFieldContext::DirectEntry) {
gdi.addCheckbox("Sex", L"Kön", nullptr, ef.count(oEvent::ExtraFields::Sex));
gdi.addCheckbox("BirthDate", L"Födelsedatum", nullptr, ef.count(oEvent::ExtraFields::BirthDate));
gdi.addCheckbox("Rank", L"Ranking", nullptr, ef.count(oEvent::ExtraFields::Rank));
gdi.addCheckbox("Phone", L"Telefon", nullptr, ef.count(oEvent::ExtraFields::Phone));
}
gdi.refresh();
}
void TabCompetition::saveExtraFields(gdioutput& gdi, oEvent::ExtraFieldContext type) {
map<oEvent::ExtraFields, wstring> fields;
if (gdi.isChecked("DataA")) {
wstring name = gdi.getText("DataAName");
if (trim(name).empty())
name = L"Data A";
fields[oEvent::ExtraFields::DataA] = name;
}
if (gdi.isChecked("DataB")) {
wstring name = gdi.getText("DataBName");
if (trim(name).empty())
name = L"Data B";
fields[oEvent::ExtraFields::DataB] = name;
}
if (gdi.isChecked("TextA")) {
wstring name = gdi.getText("TextAName");
if (trim(name).empty())
name = L"Text";
fields[oEvent::ExtraFields::TextA] = name;
}
if (gdi.isChecked("Nationality"))
fields[oEvent::ExtraFields::Nationality] = L"";
if (gdi.isChecked("Sex"))
fields[oEvent::ExtraFields::Sex] = L"";
if (gdi.isChecked("BirthDate"))
fields[oEvent::ExtraFields::BirthDate] = L"";
if (gdi.isChecked("Rank"))
fields[oEvent::ExtraFields::Rank] = L"";
if (gdi.isChecked("Phone"))
fields[oEvent::ExtraFields::Phone] = L"";
if (gdi.isChecked("Sex"))
fields[oEvent::ExtraFields::Sex] = L"";
if (gdi.isChecked("StartTime"))
fields[oEvent::ExtraFields::StartTime] = L"";
if (gdi.isChecked("Bib"))
fields[oEvent::ExtraFields::Bib] = L"";
if (gdi.isChecked("Sex"))
fields[oEvent::ExtraFields::Sex] = L"";
oe->updateExtraFields(type, fields);
}
void TabCompetition::saveSettings(gdioutput &gdi) {
@ -4220,6 +4492,8 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
fees[k] = oe->getDCI().getInt(fields[k]);
wstring factor = oe->getDCI().getString("LateEntryFactor");
wstring factor2 = oe->getDCI().getString("SecondEntryFactor");
bool useFactor2 = oe->getDCI().getInt("SecondEntryDate") > 0;
set<string> modified;
oe->getDI().saveDataFields(gdi, modified);
@ -4241,6 +4515,13 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
if (factor != oe->getDCI().getString("LateEntryFactor"))
changedFee = true;
if (factor2 != oe->getDCI().getString("SecondEntryFactor"))
changedFee = true;
bool useFactor2Now = oe->getDCI().getInt("SecondEntryDate") > 0;
if (useFactor2 != useFactor2Now)
changedFee = true;
if (oe->getDI().setInt("UTC", gdi.isChecked("UTC") ? 1 : 0))
setEventorUTC(gdi.isChecked("UTC"));
@ -4284,33 +4565,11 @@ void TabCompetition::saveSettings(gdioutput &gdi) {
throw std::exception();
}
}
//oe->setProperty("PayModes", oe->getDCI().getString("PayModes"));
/*oe->setProperty("Organizer", oe->getDCI().getString("Organizer"));
oe->setProperty("Street", oe->getDCI().getString("Street"));
oe->setProperty("Address", oe->getDCI().getString("Address"));
oe->setProperty("EMail", oe->getDCI().getString("EMail"));
oe->setProperty("Homepage", oe->getDCI().getString("Homepage"));
oe->setProperty("CardFee", oe->getDCI().getInt("CardFee"));
oe->setProperty("EliteFee", oe->getDCI().getInt("EliteFee"));
oe->setProperty("EntryFee", oe->getDCI().getInt("EntryFee"));
oe->setProperty("YouthFee", oe->getDCI().getInt("YouthFee"));
oe->setProperty("YouthAge", oe->getDCI().getInt("YouthAge"));
oe->setProperty("SeniorAge", oe->getDCI().getInt("SeniorAge"));
oe->setProperty("Account", oe->getDCI().getString("Account"));
oe->setProperty("LateEntryFactor", oe->getDCI().getString("LateEntryFactor"));
oe->setProperty("CurrencySymbol", oe->getDCI().getString("CurrencySymbol"));
oe->setProperty("CurrencyFactor", oe->getDCI().getInt("CurrencyFactor"));
oe->setProperty("CurrencyPreSymbol", oe->getDCI().getInt("CurrencyPreSymbol"));
oe->setProperty("CurrencySeparator", oe->getDCI().getString("CurrencySeparator"));
*/
//oe->setProperty("PayModes", oe->getDCI().getString("PayModes"));
}
oEvent::ExtraFieldContext context = oEvent::ExtraFieldContext(gdi.getSelectedItem("DataFields").first);
saveExtraFields(gdi, context);
oe->synchronize(true);
set<int> dummy;
if (changedFee && oe->getNumClasses() > 0) {

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -45,7 +45,7 @@ class TabCompetition :
// Events from Eventor
vector<CompetitionInfo> events;
list<PrefsEditor> prefsEditor;
shared_ptr<PrefsEditor> prefsEditor;
oFreeImport fi;
wstring entryText;
@ -83,7 +83,6 @@ class TabCompetition :
vector<CompetitionInfo> &events) const;
void saveSettings(gdioutput &gdi);
void loadSettings(gdioutput &gdi);
void getEventorCmpData(gdioutput &gdi, int id,
const wstring &eventFile,
@ -98,6 +97,8 @@ class TabCompetition :
string eventorOrigin; // The command used when checking eventor
bool checkEventor(gdioutput &gdi, ButtonInfo &bi);
pair<bool, bool> hasPersonExtId() const;
bool useEventor() const;
bool useEventorUTC() const;
@ -125,13 +126,18 @@ class TabCompetition :
void entryForm(gdioutput &gdi, bool isGuide);
FlowOperation saveEntries(gdioutput &gdi, bool removeRemoved, int classOffset, bool isGuide);
FlowOperation checkStageFilter(gdioutput &gdi, const wstring &fname, set<int> &filter, string &preferredIdProvider);
FlowOperation checkStageFilter(gdioutput &gdi, const wstring &fname, set<int> &filter, pair<string, string> &preferredIdProvider);
void setExportOptionsStatus(gdioutput &gdi, int format) const;
void selectStartlistOptions(gdioutput &gdi);
void selectExportSplitOptions(gdioutput &gdi);
void showSelectId(std::pair<bool, bool>& priSecondId, gdioutput& gdi);
pair<string, string> TabCompetition::getPreferredIdTypes(gdioutput& gdi);
void saveExtraFields(gdioutput& gdi, oEvent::ExtraFieldContext type);
void entryChoice(gdioutput &gdi);
void createCompetition(gdioutput &gdi);
@ -149,6 +155,9 @@ protected:
void clearCompetitionData();
public:
void loadSettings(gdioutput& gdi);
void showExtraFields(gdioutput& gdi, oEvent::ExtraFieldContext type);
const char * getTypeStr() const {return "TCmpTab";}
TabType getType() const {return TCmpTab;}
@ -158,9 +167,9 @@ public:
void setEventorServer(const wstring &server);
void setEventorUTC(bool useUTC);
int competitionCB(gdioutput &gdi, int type, void *data);
int restoreCB(gdioutput &gdi, int type, void *data);
int newGuideCB(gdioutput &gdi, int type, void *data);
int competitionCB(gdioutput &gdi, GuiEventType type, BaseInfo *data);
int restoreCB(gdioutput &gdi, GuiEventType type, BaseInfo *data);
int newGuideCB(gdioutput &gdi, GuiEventType type, BaseInfo *data);
bool loadPage(gdioutput &gdi);
TabCompetition(oEvent *oe);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -151,8 +151,7 @@ void TabControl::selectControl(gdioutput &gdi, pControl pc)
}
}
int ControlsCB(gdioutput *gdi, int type, void *data)
{
int ControlsCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabControl &tc = dynamic_cast<TabControl &>(*gdi->getTabs().get(TControlTab));
return tc.controlCB(*gdi, type, data);
}
@ -278,7 +277,7 @@ void TabControl::save(gdioutput &gdi) {
vector<pair<wstring, size_t>> d;
oe->fillControls(d, oEvent::ControlType::All);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
oe->reEvaluateAll(set<int>(), true);
@ -402,8 +401,7 @@ void TabControl::visitorTable(Table &table) const {
}
}
int TabControl::controlCB(gdioutput &gdi, int type, void *data)
{
int TabControl::controlCB(gdioutput &gdi, GuiEventType type, BaseInfo* data) {
if (type==GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data;
@ -431,7 +429,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
pc->synchronize();
vector< pair<wstring, size_t> > d;
oe->fillControls(d, oEvent::ControlType::All);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
selectControl(gdi, pc);
}
else if (bi.id=="Remove") {
@ -449,7 +447,7 @@ int TabControl::controlCB(gdioutput &gdi, int type, void *data)
vector< pair<wstring, size_t> > d;
oe->fillControls(d, oEvent::ControlType::All);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
selectControl(gdi, 0);
}
else if (bi.id=="SwitchMode") {
@ -565,7 +563,7 @@ bool TabControl::loadPage(gdioutput &gdi)
vector< pair<wstring, size_t> > d;
oe->fillControls(d, oEvent::ControlType::All);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
gdi.newColumn();
gdi.fillDown();

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@
class TabControl :
public TabBase
{
int controlCB(gdioutput &gdi, int type, void *data);
int controlCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
bool tableMode;
int controlId;
@ -48,5 +48,5 @@ public:
TabControl(oEvent *oe);
~TabControl(void);
friend int ControlsCB(gdioutput *gdi, int type, void *data);
friend int ControlsCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -179,9 +179,13 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
if (cc) {
gdi.selectItemByData("CommonControl", cc);
}
fillOtherCourses(gdi, *pc, cc != 0);
auto sh = pc->getShorterVersion();
if (sh.first)
fillOtherCourses(gdi, *pc, cc != 0);
else
gdi.selectItemByData("ShortCourse", -1);
gdi.check("Shorten", sh.first);
gdi.setInputStatus("ShortCourse", sh.first);
gdi.selectItemByData("ShortCourse", sh.second ? sh.second->getId() : 0);
@ -216,7 +220,7 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.setInputStatus("DrawCourse", pc != 0, true);
}
int CourseCB(gdioutput *gdi, int type, void *data) {
int CourseCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabCourse &tc = dynamic_cast<TabCourse &>(*gdi->getTabs().get(TCourseTab));
return tc.courseCB(*gdi, type, data);
}
@ -307,7 +311,7 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode) {
pc->synchronize();//Update SQL
oe->fillCourses(gdi, "Courses");
oe->fillCourses(gdi, "Courses", {}, false);
oe->reEvaluateCourse(pc->getId(), true);
if (canSwitchViewMode != 2 && changedCourse && pc->getLegLengths().size() > 2) {
@ -331,8 +335,7 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode) {
selectCourse(gdi, pc);
}
int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
{
int TabCourse::courseCB(gdioutput &gdi, GuiEventType type, BaseInfo* data) {
if (type==GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data;
@ -448,9 +451,13 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
bool w = gdi.isChecked(bi.id);
gdi.setInputStatus("ShortCourse", w);
if (w) {
pCourse pc = oe->getCourse(courseId);
if (pc) {
fillOtherCourses(gdi, *pc, gdi.isChecked("WithLoops"));
}
ListBoxInfo clb;
if (!gdi.getSelectedItem("ShortCoursse", clb) || clb.data <= 0)
gdi.selectFirstItem("CommonControl");
if (!gdi.getSelectedItem("ShortCourse", clb) || clb.data <= 0)
gdi.selectFirstItem("ShortCourse");
}
}
else if (bi.id == "ExportCourses") {
@ -621,7 +628,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
}
pCourse pc = oe->addCourse(oe->getAutoCourseName());
pc->synchronize();
oe->fillCourses(gdi, "Courses");
oe->fillCourses(gdi, "Courses", {}, false);
selectCourse(gdi, pc);
gdi.setInputFocus("Name", true);
addedCourse = true;
@ -636,7 +643,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
else
oe->removeCourse(cid);
oe->fillCourses(gdi, "Courses");
oe->fillCourses(gdi, "Courses", {}, false);
selectCourse(gdi, 0);
}
@ -757,7 +764,7 @@ bool TabCourse::loadPage(gdioutput &gdi) {
gdi.addListBox("Courses", 250, 360, CourseCB, L"Banor (antal kontroller)").isEdit(false).ignore(true);
gdi.setTabStops("Courses", 240);
oe->fillCourses(gdi, "Courses");
oe->fillCourses(gdi, "Courses", {}, false);
gdi.dropLine(0.7);
gdi.pushX();
@ -911,7 +918,7 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
gdi.fillDown();
}
else if (filename.find(L".txt") != wstring::npos || filename.find(L".TXT") != wstring::npos) {
ifstream fin(filename);
std::ifstream fin(filename);
if (!fin.good())
throw meosException(L"Cannot read " + filename);
@ -970,7 +977,7 @@ void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
}
else {
set<int> noFilter;
string noType;
pair<string, string> noType;
int classIdOffset = 0;
int courseIdOffset = 0;
oe->importXML_EntryData(gdi, filename.c_str(), addToClasses, false,
@ -1174,7 +1181,7 @@ void TabCourse::fillCourseControls(gdioutput &gdi, const wstring &ctrl) {
}
gdi.clearList("CommonControl");
gdi.addItem("CommonControl", item);
gdi.setItems("CommonControl", item);
}
void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops) {
@ -1198,8 +1205,7 @@ void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops) {
out.push_back(ac[k]);
}
gdi.clearList("ShortCourse");
gdi.addItem("ShortCourse", out);
gdi.setItems("ShortCourse", out);
}
void TabCourse::saveLegLengths(gdioutput &gdi) {

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -31,7 +31,7 @@ class TabCourse :
int courseId;
/** canSwitchViewMode: 0 = no, 1 = yes, 2 = switching to legs */
void save(gdioutput &gdi, int canSwitchViewMode);
int courseCB(gdioutput &gdi, int type, void *data);
int courseCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
bool addedCourse;
wstring time_limit;
@ -74,5 +74,5 @@ public:
static void setupCourseImport(gdioutput& gdi, GUICALLBACK cb);
friend int CourseCB(gdioutput *gdi, int type, void *data);
friend int CourseCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -80,10 +80,9 @@ TabList::~TabList(void)
liveResults.clear();
}
int ListsCB(gdioutput *gdi, int type, void *data);
int ListsCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
int ListsEventCB(gdioutput *gdi, int type, void *data)
{
int ListsEventCB(gdioutput *gdi, GuiEventType type, BaseInfo *data) {
if (type!=GUI_EVENT)
return -1;
@ -105,10 +104,10 @@ void TabList::rebuildList(gdioutput &gdi)
}
}
int openRunnerTeamCB(gdioutput *gdi, int type, void *data)
int openRunnerTeamCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
if (type==GUI_LINK && data) {
TextInfo *ti = static_cast<TextInfo *>(data);
TextInfo *ti = dynamic_cast<TextInfo *>(data);
int id = ti->getExtraInt();
if (id != 0 && ti->id == "T" && gdi->canClear()) {
@ -123,11 +122,9 @@ int openRunnerTeamCB(gdioutput *gdi, int type, void *data)
return 0;
}
int NoStartRunnerCB(gdioutput *gdi, int type, void *data)
{
if (type==GUI_LINK)
{
TextInfo *ti=(TextInfo *)data;
int NoStartRunnerCB(gdioutput* gdi, GuiEventType type, BaseInfo* data) {
if (type == GUI_LINK) {
TextInfo* ti = dynamic_cast<TextInfo*>(data);
int id = atoi(ti->id.c_str());
TabList& tc = dynamic_cast<TabList&>(*gdi->getTabs().get(TListTab));
@ -146,8 +143,7 @@ int NoStartRunnerCB(gdioutput *gdi, int type, void *data)
return 0;
}
int ListsCB(gdioutput *gdi, int type, void *data)
{
int ListsCB(gdioutput *gdi, GuiEventType type, BaseInfo *data) {
TabList &tc = dynamic_cast<TabList &>(*gdi->getTabs().get(TListTab));
return tc.listCB(*gdi, type, data);
@ -218,7 +214,7 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
}
gdi.setRestorePoint("GeneralList");
currentList.setCallback(ownWindow ? 0 : openRunnerTeamCB);
currentList.setCallback(ownWindow ? nullptr : openRunnerTeamCB);
const auto &par = currentList.getParam();
int bgColor = par.bgColor;
@ -276,7 +272,7 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
gdi.addButton(gdi.getWidth() + 20, baseY, gdi.scaleLength(baseButtonWidth),
"ListDesign", "Utseende...", ListsCB, "Justera visningsinställningar", true, false);
if (!currentList.getParam().saved && !oe->isReadOnly()) {
if (!currentList.getParam().saved && !oe->isKiosk()) {
baseY += 3 + gdi.getButtonHeight();
gdi.addButton(gdi.getWidth()+20, baseY, gdi.scaleLength(baseButtonWidth),
"Remember", "Kom ihåg listan...", ListsCB, "Spara den här listan som en favoritlista", true, false);
@ -300,19 +296,18 @@ void TabList::generateList(gdioutput &gdi, bool forceUpdate)
}
}
int TabList::listCB(gdioutput &gdi, int type, void *data)
{
int TabList::listCB(gdioutput &gdi, GuiEventType type, BaseInfo *data) {
int index;
if (type==GUI_BUTTON || type==GUI_EVENT) {
BaseInfo *tbi = 0;
ButtonInfo button;
EventInfo evnt;
if (type == GUI_BUTTON) {
button = *(ButtonInfo *)data;
button = dynamic_cast<ButtonInfo &>(*data);
tbi = &button;
}
else if (type == GUI_EVENT) {
evnt = *(EventInfo *)data;
evnt = dynamic_cast<EventInfo&>(*data);
tbi = &evnt;
}
else
@ -490,7 +485,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
gdi.addListBox("Merge", 350, 250, 0, L"Slå ihop med:");
vector < pair<wstring, size_t> > cand;
oe->getListContainer().getMergeCandidates(lbi.data, cand);
gdi.addItem("Merge", cand);
gdi.setItems("Merge", cand);
gdi.addCheckbox("ShowTitle", "Visa rubrik mellan listorna", 0, false);
gdi.fillRight();
gdi.addButton("DoMerge", "Slå ihop", ListsCB).setDefault();
@ -1230,6 +1225,7 @@ int TabList::listCB(gdioutput &gdi, int type, void *data)
else if (lbi.id == "ListSelection") {
gdi.getSelection(lbi.id, lastClassSelection);
if (gdi.hasWidget("ResultType")) {
lastResultClassSelection = lastClassSelection;
ListBoxInfo entry;
gdi.getSelectedItem("ResultType", entry);
gdi.setInputStatus("Generate", !lastClassSelection.empty() && int(entry.data) >= 0);
@ -1348,7 +1344,7 @@ void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) {
vector< pair<wstring, size_t> > ds;
ds.push_back(make_pair(lang.tl("Start"), 0));
ds.insert(ds.end(), d.begin(), d.end());
gdi.addItem("ResultSpecialFrom", ds);
gdi.setItems("ResultSpecialFrom", ds);
if (!gdi.selectItemByData("ResultSpecialFrom", oe.getPropertyInt("ControlFrom", 0))) {
gdi.selectItemByData("ResultSpecialFrom", 0); // Fallback
}
@ -1360,7 +1356,7 @@ void TabList::enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to) {
if (to) {
gdi.enableInput("ResultSpecialTo");
gdi.addItem("ResultSpecialTo", d);
gdi.setItems("ResultSpecialTo", d);
gdi.addItem("ResultSpecialTo", lang.tl("Mål"), 0);
if (!gdi.selectItemByData("ResultSpecialTo", oe.getPropertyInt("ControlTo", 0))) {
gdi.selectItemByData("ResultSpecialTo", 0); // Fallback
@ -1379,7 +1375,7 @@ void TabList::selectGeneralList(gdioutput &gdi, EStdListType type)
oe->setProperty("ListType", type);
if (li.supportClasses) {
gdi.enableInput("ListSelection");
oe->fillClasses(gdi, "ListSelection", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "ListSelection", {}, oEvent::extraNone, oEvent::filterNone);
if (lastClassSelection.empty())
lastClassSelection.insert(-1);
gdi.setSelection("ListSelection", lastClassSelection);
@ -1404,7 +1400,7 @@ void TabList::selectGeneralList(gdioutput &gdi, EStdListType type)
set<int> clsUnused;
vector< pair<wstring, size_t> > out;
oe->fillLegNumbers(clsUnused, li.isTeamList(), true, out);
gdi.addItem("LegNumber", out);
gdi.setItems("LegNumber", out);
gdi.setInputStatus("LegNumber", !out.empty());
}
else {
@ -1654,7 +1650,7 @@ void TabList::loadRememberList(gdioutput &gdi, string targetTag) {
gdi.addListBox("Merge", 350, 250);
vector < pair<wstring, size_t> > cand;
oe->getListContainer().getMergeCandidates(-1, cand);
gdi.addItem("Merge", cand);
gdi.setItems("Merge", cand);
gdi.dropLine(-0.2);
gdi.addCheckbox("ShowTitle", "Visa rubrik mellan listorna", 0, false);
gdi.dropLine(0.5);
@ -2025,7 +2021,7 @@ void TabList::htmlSettings(gdioutput &gdi, string targetTag) {
if (!htmlTemplateTag2Id.count(tmpSettingsParam.htmlTypeTag))
tmpSettingsParam.htmlTypeTag = "free";
gdi.addItem("Format", items);
gdi.setItems("Format", items);
int tid = htmlTemplateTag2Id[tmpSettingsParam.htmlTypeTag];
gdi.selectItemByData("Format", tid);
@ -2174,7 +2170,7 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
oEvent::ClassFilter ct = currentList.isTeamList() ? oEvent::filterOnlyMulti : oEvent::filterNone;
oe->fillClasses(gdi, "ListSelection", oEvent::extraNone, ct);
oe->fillClasses(gdi, "ListSelection", {}, oEvent::extraNone, ct);
gdi.setSelection("ListSelection", currentList.getParam().selection);
gdi.dropLine(2.5);
@ -2184,14 +2180,15 @@ void TabList::loadClassSettings(gdioutput &gdi, string targetTag) {
ages.emplace_back(lang.tl("Alla"), size_t(oListParam::AgeFilter::All));
ages.emplace_back(lang.tl("Ungdom"), size_t(oListParam::AgeFilter::OnlyYouth));
ages.emplace_back(lang.tl("Vuxna"), size_t(oListParam::AgeFilter::ExludeYouth));
gdi.addItem("AgeFilter", ages);
gdi.setItems("AgeFilter", ages);
gdi.selectItemByData("AgeFilter", int(currentList.getParam().ageFilter));
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, currentList.getParam().pageBreak).setHandler(&settingsClassSelection);
gdi.addCheckbox("ShowHeader", "Visa rubrik", 0, currentList.getParam().showHeader).setHandler(&settingsClassSelection);
gdi.dropLine(-0.3);
gdi.addInput("Heading", currentList.getParam().getCustomTitle(wstring(L"")), 28, 0, L"Egen listrubrik:");
wstring hdr;
gdi.addInput("Heading", currentList.getParam().getCustomTitle(hdr), 28, 0, L"Egen listrubrik:");
gdi.setInputStatus("Heading", currentList.getParam().showHeader);
gdi.dropLine(0.5);
gdi.fillRight();
@ -2305,7 +2302,7 @@ void TabList::settingsResultList(gdioutput &gdi)
}
sort(lists.begin() + startIx, lists.end());
gdi.addItem("ResultType", lists);
gdi.setItems("ResultType", lists);
gdi.autoGrow("ResultType");
int lastSelectedResultListOK = -1;
@ -2615,7 +2612,7 @@ bool TabList::loadPage(gdioutput &gdi)
gdi.pushX();
gdi.addSelection("SavedInstance", 250, 200, ListsCB);
gdi.addItem("SavedInstance", savedParams);
gdi.setItems("SavedInstance", savedParams);
gdi.autoGrow("SavedInstance");
gdi.selectFirstItem("SavedInstance");
gdi.addButton("ShowSaved", "Visa", ListsCB);
@ -2796,7 +2793,7 @@ void TabList::splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter,
lists.insert(lists.begin(), make_pair(lang.tl("Standard"), -10));
lists.insert(lists.begin(), make_pair(lang.tl("Automatisk"), -11));
gdi.addItem("SplitPrintList", lists);
gdi.setItems("SplitPrintList", lists);
gdi.autoGrow("SplitPrintList");
gdi.dropLine(0.8);
@ -2870,7 +2867,7 @@ void TabList::splitPrintSettings(oEvent &oe, gdioutput &gdi, bool setupPrinter,
for (size_t j = 1; j < 8; j++)
nsp.push_back(make_pair(itow(j), j));
gdi.addSelection("NumPerPage", 90, 200, ListsCB, L"Max antal brickor per sida");
gdi.addItem("NumPerPage", nsp);
gdi.setItems("NumPerPage", nsp);
gdi.selectItemByData("NumPerPage", printLen);
int maxWait = oe.getPropertyInt("SplitPrintMaxWait", 60);
@ -2924,7 +2921,7 @@ void TabList::customTextLines(oEvent &oe, const char *dataField, bool withSymbol
gdi.addInput(row, L"", 24);
string key = "font"+itos(k);
gdi.addSelection(key, 100, 100);
gdi.addItem(key, fonts);
gdi.setItems(key, fonts);
if (lines.size() > size_t(k)) {
gdi.selectItemByData(key.c_str(), lines[k].second);
gdi.setText(row, lines[k].first);
@ -2947,7 +2944,7 @@ void TabList::customTextLines(oEvent &oe, const char *dataField, bool withSymbol
gdi.setTabStops("Symbols", 300);
vector < pair<wstring, size_t>> symb;
MetaList::fillSymbols(symb);
gdi.addItem("Symbols", symb);
gdi.setItems("Symbols", symb);
gdi.popX();
gdi.popY();
}
@ -3011,37 +3008,28 @@ void TabList::setResultOptionsFromType(gdioutput &gdi, int data) {
gdi.setInputStatus("ShowInterResults", builtIn);
gdi.setInputStatus("ShowSplits", builtIn);
set<int> clsUnused;
vector< pair<wstring, size_t> > out;
oe->fillLegNumbers(clsUnused, li.isTeamList(), true, out);
gdi.addItem("LegNumber", out);
gdi.setItems("LegNumber", out);
gdi.setInputStatus("LegNumber", !out.empty());
if (!out.empty() && lastLeg >= 0)
gdi.selectItemByData("LegNumber", lastLeg);
//oe->fillLegNumbers(gdi, "LegNumber", li.isTeamList(), true);
gdi.setInputStatus("InputNumber", false);
}
else {
gdi.setInputStatus("UseLargeSize", li.supportLarge);
gdi.setInputStatus("InputNumber", li.supportParameter);
//gdi.setInputStatus("SplitAnalysis", li.supportSplitAnalysis);
//gdi.setInputStatus("ShowInterResults", li.supportInterResults);
//gdi.setInputStatus("PageBreak", li.supportPageBreak);
//gdi.setInputStatus("ClassLimit", li.supportClassLimit);
if (li.supportLegs) {
gdi.enableInput("LegNumber");
//oe->fillLegNumbers(gdi, "LegNumber", li.isTeamList(), true);
set<int> clsUnused;
vector< pair<wstring, size_t> > out;
oe->fillLegNumbers(clsUnused, li.isTeamList(), true, out);
gdi.addItem("LegNumber", out);
gdi.setItems("LegNumber", out);
if (!out.empty() && lastLeg >= 0)
gdi.selectItemByData("LegNumber", lastLeg);
gdi.setInputStatus("LegNumber", !out.empty());
@ -3091,16 +3079,23 @@ void TabList::setResultOptionsFromType(gdioutput &gdi, int data) {
if (lastFilledResultClassType != ct) {
lastFilledResultClassType = ct;
lastResultClassSelection.insert(curSel.begin(), curSel.end());
oe->fillClasses(gdi, "ListSelection", oEvent::extraNone, ct);
oe->fillClasses(gdi, "ListSelection", {}, oEvent::extraNone, ct);
gdi.setSelection("ListSelection", lastResultClassSelection);
}
gdi.setInputStatus("Generate", data >= 0 && !lastResultClassSelection.empty());
gdi.setInputStatus("Generate", data >= 0 && hasSelectedClass(gdi));
}
bool TabList::hasSelectedClass(gdioutput& gdi) {
set<int> sel;
gdi.getSelection("ListSelection", sel);
return !sel.empty();
}
void TabList::clearCompetitionData() {
SelectedList = "";
lastResultClassSelection.clear();
lastClassSelection.clear();
ownWindow = false;
hideButtons = false;

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -49,6 +49,8 @@ protected:
static void createListButtons(gdioutput &gdi);
static bool hasSelectedClass(gdioutput& gdi);
void generateList(gdioutput &gdi, bool forceUpdate = false);
void selectGeneralList(gdioutput &gdi, EStdListType type);
@ -124,7 +126,7 @@ public:
static void enableFromTo(oEvent &oe, gdioutput &gdi, bool from, bool to);
void liveResult(gdioutput &gdi, oListInfo &currentList);
int listCB(gdioutput &gdi, int type, void *data);
int listCB(gdioutput &gdi, GuiEventType type, BaseInfo *data);
void loadGeneralList(gdioutput &gdi);
void rebuildList(gdioutput &gdi);
void settingsResultList(gdioutput &gdi);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -23,6 +23,7 @@
#include "tabbase.h"
#include "Printer.h"
#include "autocompletehandler.h"
#include <deque>
class Table;
struct AutoCompleteRecord;
@ -43,15 +44,27 @@ private:
void selectRunner(gdioutput &gdi, pRunner r);
void updateCardStatus(const pCard& pc, gdioutput& gdi);
void updatePunchStatus(const pPunch& punch, InputInfo* bb, gdioutput& gdi);
int numReportRow = 1;
int numReportColumn = 1;
bool hideReportControls = false;
bool showReportHeader = true;
void addToReport(int cardNo, bool punchForShowReport);
void addToReport(int id);
string computeKeyForReport();
wstring lastSearchExpr;
unordered_set<int> lastFilter;
DWORD timeToFill;
int inputId;
int searchCB(gdioutput &gdi, int type, void *data);
int runnerCB(gdioutput &gdi, int type, void *data);
int punchesCB(gdioutput &gdi, int type, void *data);
int vacancyCB(gdioutput &gdi, int type, void *data);
int searchCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
int runnerCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
int punchesCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
int vacancyCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
int currentMode;
pRunner save(gdioutput &gdi, int runnerId, bool dontReloadRunners);
@ -64,7 +77,7 @@ private:
int runnerId;
bool ownWindow;
bool listenToPunches;
vector< pair<int, bool> > runnersToReport;
deque<pair<int, bool>> runnersToReport;
vector<pRunner> unknown_dns;
vector<pRunner> known_dns;
@ -76,7 +89,19 @@ private:
PrinterObject splitPrinter;
void showRunnerReport(gdioutput &gdi);
static void runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compactReport);
static void runnerReport(oEvent &oe, gdioutput &gdi,
int id, bool compactReport,
int maxWidth,
RECT& rc);
static void teamReport(oEvent& oe, gdioutput& gdi,
const oTeam *team,
bool onlySelectedRunner,
const deque<pair<int, bool>> &runners,
int maxWidth,
RECT &rc);
void showVacancyList(gdioutput &gdi, const string &method="", int classId=0);
void showCardsList(gdioutput &gdi);
@ -100,20 +125,35 @@ private:
oEvent *oe;
oRunner &getRunner() const;
void updateColor(gdioutput& gdi);
public:
void init(oRunner& r);
public:
EconomyHandler(oRunner& r) { init(r); }
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
void save(gdioutput &gdi);
};
shared_ptr<EconomyHandler> ecoHandler;
EconomyHandler *getEconomyHandler(oRunner &r);
class CommentHandler : public GuiHandler {
int runnerId;
bool isTeam = false;
oEvent* oe;
oAbstractRunner& getRunner() const;
public:
CommentHandler(oAbstractRunner& r) : oe(r.getEvent()) {
runnerId = r.getId(); isTeam = r.isTeam();
}
void handle(gdioutput& gdi, BaseInfo& info, GuiEventType type);
void save(gdioutput& gdi);
};
void getAutoCompleteUnpairedCards(gdioutput &gdi, const wstring& w, vector<AutoCompleteRecord>& records);
protected:
void clearCompetitionData();
public:
static void renderComments(gdioutput& gdi, oAbstractRunner& r);
static void loadComments(gdioutput& gdi, oAbstractRunner& r);
static pClub extractClub(oEvent *oe, gdioutput &gdi);
void handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) override;
@ -126,13 +166,21 @@ public:
bool loadPage(gdioutput &gdi);
bool loadPage(gdioutput &gdi, int runnerId);
static void generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport);
static int addExtraFields(const oEvent &oe, gdioutput& gdi, oEvent::ExtraFieldContext context);
static void saveExtraFields(gdioutput& gdi, oBase &r);
static void loadExtraFields(gdioutput& gdi, const oBase* r);
static void generateRunnerReport(oEvent &oe,
gdioutput &gdi,
int numX, int numY,
bool onlySelectedRunner,
const deque<pair<int, bool>> &runnersToReport);
TabRunner(oEvent *oe);
~TabRunner(void);
friend int runnerSearchCB(gdioutput *gdi, int type, void *data);
friend int RunnerCB(gdioutput *gdi, int type, void *data);
friend int PunchesCB(gdioutput *gdi, int type, void *data);
friend int VacancyCB(gdioutput *gdi, int type, void *data);
friend int runnerSearchCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
friend int RunnerCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
friend int PunchesCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
friend int VacancyCB(gdioutput *gdi, GuiEventType type, BaseInfo *data);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -39,6 +39,7 @@ public:
ModeEntry,
ModeCardData,
ModeRegisterCards,
ModeRequestStartTime,
};
map<SIMode, string> modeName;
@ -94,6 +95,10 @@ private:
shared_ptr<GuiHandler> resetHiredCardHandler;
GuiHandler *getResetHiredCardHandler();
shared_ptr<GuiHandler> requestStartTimeHandler;
SortOrder sortAssignCards = SortOrder::Custom;
int runnerMatchedId;
bool printErrorShown;
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
@ -110,6 +115,7 @@ private:
void assignCard(gdioutput &gdi, const SICard &sic);
void entryCard(gdioutput &gdi, const SICard &sic);
void requestStartTime(gdioutput& gdi, const SICard& sic);
void updateEntryInfo(gdioutput &gdi);
void generateEntryLine(gdioutput &gdi, pRunner r);
@ -120,6 +126,7 @@ private:
int numSavedCardsOnCmpOpen = 0;
void showCheckCardStatus(gdioutput &gdi, const string &cmd);
void showRegisterHiredCards(gdioutput &gdi);
void showRequestStartTime(gdioutput &gdi);
wstring getCardInfo(bool param, vector<int> &count) const;
// Formatting for card tick off
@ -185,17 +192,32 @@ private:
static int analyzePunch(SIPunch &p, int &start, int &accTime, int &days);
void createCompetitionFromCards(gdioutput &gdi);
int NC;
int NC = 8;
int testType = 0;
bool showTestingPanel = false;
wstring testStartTime;
bool useTestStart = true;
wstring testFinishTime;
bool useTestFinish = true;
wstring testCheckTime;
bool useTestCheck = false;
int testRadioNumber = 50;
wstring testPunchTime;
vector<int> testControls;
int testCardNumber = 0;
void readTestData(gdioutput& gdi);
class EditCardData : public GuiHandler {
TabSI *tabSI;
EditCardData(const EditCardData&);
EditCardData &operator=(const EditCardData&);
public:
EditCardData() : tabSI(0) {}
EditCardData(const EditCardData&) = delete;
EditCardData& operator=(const EditCardData&) = delete;
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
friend class TabSI;
};
@ -235,7 +257,8 @@ private:
Manual,
SeveralTurns,
AutoTie,
AutoTieRent
AutoTieRent,
ExtraDataFields
};
void checkBoxToolBar(gdioutput& gdi, const set<CheckBox> &items) const;
@ -252,6 +275,7 @@ private:
vector<int> MP;
GDICOLOR color;
bool rentCard = false;
int runnerId = 0;
RECT computeRC(gdioutput &gdi) const;
void render(gdioutput &gdi, const RECT &rc) const;
@ -286,6 +310,15 @@ public:
wstring storedFee;
wstring storedPhone;
wstring storedStartTime;
wstring dataA;
wstring dataB;
wstring textA;
wstring nationality;
int sex = 2;
wstring birthDate;
wstring rank;
bool allStages;
bool rentState;
bool hasPaid;
@ -305,11 +338,11 @@ public:
static SportIdent &getSI(const gdioutput &gdi);
void printerSetup(gdioutput &gdi);
void generateStartInfo(gdioutput &gdi, const oRunner &r);
void generateStartInfo(gdioutput &gdi, const oRunner &r, bool includeEconomy);
bool hasPrintStartInfo() const {return printStartInfo;}
void setPrintStartInfo(bool info) {printStartInfo = info;}
int siCB(gdioutput &gdi, int type, void *data);
int siCB(gdioutput &gdi, GuiEventType type, BaseInfo *data);
void writeDefaultHiredCards();
@ -327,6 +360,7 @@ public:
void insertSICard(gdioutput &gdi, SICard &sic);
void clearQueue() { CardQueue.clear(); }
void refillComPorts(gdioutput &gdi);
bool anyActivePort() const;
bool loadPage(gdioutput &gdi) final;
void showReadoutMode(gdioutput & gdi);

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,8 +67,7 @@ TabSpeaker::~TabSpeaker()
}
int tabSpeakerCB(gdioutput *gdi, int type, void *data)
{
int tabSpeakerCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabSpeaker &ts = dynamic_cast<TabSpeaker &>(*gdi->getTabs().get(TSpeakerTab));
switch(type){
@ -165,7 +164,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.addButton("AllClass", "Alla", tabSpeakerCB);
gdi.addButton("NoClass", "Inga", tabSpeakerCB);
oe->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "Classes", {}, oEvent::extraNone, oEvent::filterNone);
gdi.setSelection("Classes", classesToWatch);
gdi.fillRight();
@ -177,7 +176,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
vector< pair<wstring, size_t> > d;
oe->fillControls(d, oEvent::ControlType::CourseControl);
gdi.addItem("Controls", d);
gdi.setItems("Controls", d);
gdi.setSelection("Controls", controlsToWatch);
@ -241,11 +240,11 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.dropLine(3);
gdi.popX();
gdi.registerEvent("DataUpdate", tabSpeakerCB);
vector<pair<int, bool>> runnersToReport;
deque<pair<int, bool>> runnersToReport;
if (runnerId > 0) {
runnersToReport.emplace_back(runnerId, false);
}
TabRunner::generateRunnerReport(*oe, gdi, runnersToReport);
TabRunner::generateRunnerReport(*oe, gdi, 1, 1, false, runnersToReport);
gdi.refresh();
}
else if (bu.id == "Priority") {
@ -257,7 +256,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.pushX();
gdi.addString("", 0, "Klass:");
gdi.addSelection("Class", 200, 200, tabSpeakerCB, L"", L"Välj klass");
oe->fillClasses(gdi, "Class", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(gdi, "Class", {}, oEvent::extraNone, oEvent::filterNone);
gdi.addButton("ClosePri", "Stäng", tabSpeakerCB);
gdi.dropLine(2);
gdi.popX();
@ -278,7 +277,7 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi_new->pushX();
TabList::makeClassSelection(*gdi_new);
oe->fillClasses(*gdi_new, "ListSelection", oEvent::extraNone, oEvent::filterNone);
oe->fillClasses(*gdi_new, "ListSelection", {}, oEvent::extraNone, oEvent::filterNone);
gdi_new->popY();
gdi_new->setCX(gdi_new->getCX() + gdi_new->scaleLength(280));
@ -1223,7 +1222,7 @@ void TabSpeaker::storeManualTime(gdioutput &gdi)
throw std::exception(bf);
}
oe->addFreePunch(itime, punch, 0, sino, true);
oe->addFreePunch(itime, punch, 0, sino, true, false);
gdi.restore("manual", false);
gdi.addString("", 0, L"Löpare: X, kontroll: Y, kl Z#" + Name + L"#" + oPunch::getType(punch) + L"#" + oe->getAbsTime(itime));

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -46,26 +46,19 @@
#include "TabSI.h"
TabTeam::TabTeam(oEvent *poe):TabBase(poe)
{
TabTeam::TabTeam(oEvent *poe):TabBase(poe) {
clearCompetitionData();
}
TabTeam::~TabTeam(void)
{
}
TabTeam::~TabTeam(void) = default;
int TeamCB(gdioutput *gdi, int type, void *data)
{
int TeamCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabTeam &tt = dynamic_cast<TabTeam &>(*gdi->getTabs().get(TTeamTab));
return tt.teamCB(*gdi, type, data);
}
int teamSearchCB(gdioutput *gdi, int type, void *data)
{
int teamSearchCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
TabTeam &tc = dynamic_cast<TabTeam &>(*gdi->getTabs().get(TTeamTab));
return tc.searchCB(*gdi, type, data);
}
@ -134,7 +127,7 @@ int TabTeam::searchCB(gdioutput &gdi, int type, void *data) {
if (filter.empty()) {
vector< pair<wstring, size_t> > runners;
runners.push_back(make_pair(lang.tl(L"Ingen matchar 'X'#" + expr), -1));
gdi.addItem("Teams", runners);
gdi.setItems("Teams", runners);
}
else
gdi.filterOnData("Teams", filter);
@ -164,7 +157,7 @@ int TabTeam::searchCB(gdioutput &gdi, int type, void *data) {
runners.swap(runners2);
}
gdi.addItem("Teams", runners);
gdi.setItems("Teams", runners);
}
if (type == GUI_TIMER)
@ -187,8 +180,9 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.enableInput("Save");
gdi.enableInput("Undo");
gdi.enableInput("Remove");
gdi.enableInput("EditAnnotation");
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterOnlyMulti);
oe->fillClasses(gdi, "RClass", {}, oEvent::extraNone, oEvent::filterOnlyMulti);
gdi.selectItemByData("RClass", t->getClassId(false));
gdi.selectItemByData("Teams", t->getId());
@ -209,6 +203,8 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.check("NoRestart", t->preventRestart());
}
TabRunner::loadExtraFields(gdi, t);
loadTeamMembers(gdi, 0, 0, t);
}
else {
@ -218,6 +214,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.disableInput("Save");
gdi.disableInput("Undo");
gdi.disableInput("Remove");
gdi.disableInput("EditAnnotation");
ListBoxInfo lbi;
gdi.getSelectedItem("RClass", lbi);
@ -342,6 +339,8 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (gdi.hasWidget("NoRestart"))
t->preventRestart(gdi.isChecked("NoRestart"));
TabRunner::saveExtraFields(gdi, *t);
t->apply(oBase::ChangeType::Quiet, nullptr);
if (gdi.hasWidget("Club")) {
@ -404,6 +403,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
}
t->setClassId(classId, true);
t->adjustMultiRunners();
if (gdi.hasWidget("TimeAdjust")) {
int time = convertAbsoluteTimeMS(gdi.getText("TimeAdjust"));
@ -552,14 +552,14 @@ wstring getForking(pClass pc, int key, int maxLen) {
return crsList;
}
int TabTeam::teamCB(gdioutput &gdi, int type, void *data) {
int TabTeam::teamCB(gdioutput &gdi, GuiEventType type, BaseInfo* data) {
if (type==GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data;
if (bi.id=="Save") {
return save(gdi, false);
}
if (bi.id == "Cancel") {
else if (bi.id == "Cancel") {
loadPage(gdi);
return 0;
}
@ -582,6 +582,15 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data) {
selectTeam(gdi, t);
return 0;
}
else if (bi.id == "EditAnnotation") {
if (!teamId)
return 0;
pTeam t = oe->getTeam(teamId);
if (t && getExtraWindow("comments", true) == nullptr) {
gdioutput* settings = createExtraWindow("comments", L"Kommentarer", gdi.scaleLength(550), gdi.scaleLength(350), true);
TabRunner::loadComments(*settings, *t);
}
}
else if (bi.id=="Search") {
ListBoxInfo lbi;
gdi.getSelectedItem("Teams", lbi);
@ -744,7 +753,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data) {
keys.push_back(make_pair(itow(f+1) + L": " + getForking(pc, f+1, 30), f));
}
int currentKey = max(t->getStartNo()-1, 0) % nf;
gdi.addItem("ForkKey", keys);
gdi.setItems("ForkKey", keys);
gdi.autoGrow("ForkKey");
gdi.selectItemByData("ForkKey", currentKey);
@ -911,7 +920,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data) {
gdi.fillDown();
gdi.addButton("Cancel", "Avbryt", TeamCB);
gdi.addItem("SelectR", otherR);
gdi.setItems("SelectR", otherR);
}
else {
gdi.addButton("Cancel", "Avbryt", TeamCB);
@ -1265,7 +1274,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
int yp = gdi.getCY();
int numberPos = xp;
xp += gdi.scaleLength(25);
const int dxIn[6] = {0, 184, 220, 300, 326, 374};
const int dxIn[6] = {0, 184, 220, 300, 326, 364};
int dx[6];
dx[0] = 0;
@ -1292,7 +1301,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.addStringUT(yp + textOffY, numberPos, 0, pc->getLegNumber(i) + L".");
if (pc->getLegRunner(i) == i) {
gdi.addInput(xp + dx[0], yp, bf, L"", 18, TeamCB);//Name
gdi.addButton(xp + dx[1], yp - 2, gdi.scaleLength(28), "DR" + itos(i), "<>", TeamCB, "Knyt löpare till sträckan.", false, false); // Change
gdi.addButton(xp + dx[1], yp - 2, gdi.scaleLength(28), "DR" + itos(i), L"\u21C6", TeamCB, L"Knyt löpare till sträckan.", false, false); // Change
sprintf_s(bf_si, "SI%d", i);
hasSI = true;
gdi.addInput(xp + dx[2], yp, bf_si, L"", 7, TeamCB).setExtra(i); //Si
@ -1302,7 +1311,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.addInput(xp + dx[0], yp, bf, L"", 18, 0);//Name
gdi.disableInput(bf);
}
gdi.addButton(xp + dx[4], yp - 2, gdi.scaleLength(38), "MR" + itos(i), "...", TeamCB, "Redigera deltagaren.", false, false); // Change
gdi.addButton(xp + dx[4], yp - 2, gdi.scaleLength(28), "MR" + itos(i), L"\u21BA", TeamCB, L"Redigera deltagaren.", false, false); // Change
gdi.addString(("STATUS" + itos(i)).c_str(), yp + textOffY, xp + dx[5], 0, "#MMMMMMMMMMMMMMMM");
gdi.setText("STATUS" + itos(i), L"", false);
@ -1335,38 +1344,29 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
}
}
}
if (t)
forkingKey(gdi, t);
gdi.refresh();
}
void TabTeam::forkingKey(gdioutput& gdi, pTeam t) {
pClass pc = t->getClassRef(false);
int cx = gdi.getCX();
int cy = gdi.getCY();
TabRunner::renderComments(gdi, *t);
gdi.setCX(cx);
gdi.setCY(cy);
gdi.pushX();
gdi.setRestorePoint("SelectR");
gdi.addString("", 1, "help:7618");
gdi.addString("", 0, "help:7618");
gdi.dropLine();
int numF = pc->getNumForks();
if (numF > 1 && t) {
gdi.addString("", 1, "Gafflingsnyckel X#" + itos(1 + (max(t->getStartNo() - 1, 0) % numF))).setColor(colorGreen);
wstring crsList = getForking(pc, t->getStartNo(), 50);
/*bool hasCrs = false;
for (size_t k = 0; k < pc->getNumStages(); k++) {
pCourse crs = pc->getCourse(k, t->getStartNo());
wstring cS;
if (crs != 0) {
cS = crs->getName();
hasCrs = true;
}
else
cS = makeDash(L"-");
if (!crsList.empty())
crsList += L", ";
crsList += cS;
if (hasCrs && crsList.length() > 50) {
gdi.addStringUT(0, crsList);
crsList.clear();
}
}
if (hasCrs && !crsList.empty()) {
gdi.addStringUT(0, crsList);
}*/
if (!crsList.empty()) {
gdi.addStringUT(0, crsList);
@ -1375,7 +1375,6 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.addButton("ChangeKey", "Ändra lagets gaffling", TeamCB);
}
}
gdi.refresh();
}
void TabTeam::enableRunner(gdioutput& gdi, int index, bool enable) {
@ -1456,8 +1455,7 @@ bool TabTeam::loadPage(gdioutput &gdi)
}
gdi.addSelection("RClass", 170, 300, TeamCB, L"Klass:");
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterOnlyMulti);
gdi.addItem("RClass", lang.tl("Ny klass"), 0);
oe->fillClasses(gdi, "RClass", {make_pair(lang.tl("Ny klass"), 0)}, oEvent::extraNone, oEvent::filterOnlyMulti);
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy))
gdi.addInput("Fee", L"", 5, 0, L"Avgift:");
@ -1517,11 +1515,11 @@ bool TabTeam::loadPage(gdioutput &gdi)
}
gdi.addString("TeamInfo", 0, " ").setColor(colorRed);
gdi.dropLine(1.5);
const bool multiDay = oe->hasPrevStage();
if (multiDay) {
gdi.dropLine(1.5);
int xx = gdi.getCX();
int yy = gdi.getCY();
gdi.dropLine(0.5);
@ -1552,10 +1550,14 @@ bool TabTeam::loadPage(gdioutput &gdi)
rc.bottom = gdi.getCY();
gdi.addRectangle(rc, colorLightGreen, true, false);
gdi.dropLine(1.5);
gdi.popX();
}
TabRunner::addExtraFields(*oe, gdi, oEvent::ExtraFieldContext::Team);
gdi.dropLine(0.5);
gdi.popX();
gdi.fillRight();
gdi.addButton("Save", "Spara", TeamCB, "help:save");
gdi.disableInput("Save");
@ -1568,6 +1570,10 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.disableInput("Remove");
gdi.addButton("Add", "Nytt lag", TeamCB);
gdi.popX();
gdi.dropLine(2.2);
gdi.addButton("EditAnnotation", L"Kommentar >>", TeamCB, L"Lägg till eller redigera kommentarer om laget.");
gdi.setOnClearCb(TeamCB);
addToolbar(gdi);
@ -1880,7 +1886,13 @@ void TabTeam::showRunners(gdioutput &gdi, const char *title,
usedR.insert(it->second);
if (!any) {
gdi.addString("", boldText, title);
gdi.dropLine(0.2);
int YC = gdi.getCY() + gdi.getLineHeight() / 2;
int CX = gdi.getCX();
int hy = gdi.scaleLength(2);
RECT rc = { CX, YC-hy, CX + gdi.getLineHeight(), YC + hy };
gdi.addRectangle(rc, GDICOLOR::colorMediumDarkRed, false);
gdi.addString("", boldText|Capitalize, title);
gdi.dropLine(1.2);
gdi.popX();
any = true;
@ -1891,7 +1903,7 @@ void TabTeam::showRunners(gdioutput &gdi, const char *title,
gdi.popX();
}
gdi.addString("SelectR", 0, L"#" + it->first, TeamCB).setExtra(it->second);
gdi.addString("SelectR", 0, L"#" + it->first, TeamCB).setColor(colorRed).setExtra(it->second);
}
if (any) {
@ -1906,6 +1918,7 @@ void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
gdioutput::AskAnswer ans = gdioutput::AskAnswer::AnswerNo;
if (r == oldR) {
gdi.restore("SelectR");
forkingKey(gdi, t);
return;
}
else if (oldR) {
@ -1975,6 +1988,7 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
}
otherTeam->checkValdParSetup();
otherTeam->apply(oBase::ChangeType::Update, nullptr);
otherTeam->adjustMultiRunners();
otherTeam->synchronize(true);
}
else if (oldR) {
@ -1995,6 +2009,7 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
r->evaluateCard(true, mp, 0, oBase::ChangeType::Update);
t->checkValdParSetup();
t->apply(oBase::ChangeType::Update, nullptr);
t->adjustMultiRunners();
t->synchronize(true);
if (removeAnnonumousTeamMember)
@ -2042,7 +2057,7 @@ bool TabTeam::warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r) {
}
void TabTeam::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
auto bi = gdi.setText(info.getTarget(), info.getCurrent().c_str());
auto bi = gdi.setText(info.getTarget().c_str(), info.getCurrent(), false, -1, false);
if (bi) {
int ix = info.getCurrentInt();
bi->setExtra(ix);
@ -2053,10 +2068,10 @@ void TabTeam::handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) {
if (runner && gdi.hasWidget("Club") && gdi.getText("Club").empty()) {
pClub club = db.getClub(runner->dbe().clubNo);
if (club)
gdi.setText("Club", club->getName());
gdi.setText("Club", club->getName(), false, -1, false);
}
if (runner && runner->dbe().cardNo > 0 && gdi.hasWidget("DirCard") && gdi.getText("DirCard").empty()) {
gdi.setText("DirCard", runner->dbe().cardNo);
gdi.setText("DirCard", itow(runner->dbe().cardNo), false, -1, false);
}
}
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -77,6 +77,8 @@ private:
/** Enable or disable edit for a team runner*/
void enableRunner(gdioutput &gdi, int index, bool enable);
/// Show forking key in the window
void forkingKey(gdioutput& gdi, pTeam t);
protected:
void clearCompetitionData();
@ -87,12 +89,12 @@ public:
const char * getTypeStr() const {return "TTeamTab";}
TabType getType() const {return TTeamTab;}
int teamCB(gdioutput &gdi, int type, void *data);
int teamCB(gdioutput &gdi, GuiEventType type, BaseInfo* data);
bool loadPage(gdioutput &gdi, int id);
bool loadPage(gdioutput &gdi);
TabTeam(oEvent *oe);
~TabTeam(void);
friend int teamSearchCB(gdioutput *gdi, int type, void *data);
friend int teamSearchCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
};

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -274,7 +274,7 @@ void Table::filter(int col, const wstring &filt, bool forceFilter)
wchar_t filt_lc[1024];
wcscpy_s(filt_lc, filt.c_str());
CharLowerBuff(filt_lc, filt.length());
prepareMatchString(filt_lc, filt.length());
sortIndex.resize(2);
for (size_t k=2;k<baseIndex.size();k++) {
@ -707,7 +707,7 @@ bool Table::mouseLeftUp(gdioutput &gdi, int x, int y)
return false;
}
int tblSelectionCB(gdioutput *gdi, int type, void *data) {
int tblSelectionCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
if (type == GUI_LISTBOX) {
ListBoxInfo lbi = *static_cast<ListBoxInfo *>(data);
Table &t = gdi->getTable();
@ -1104,7 +1104,7 @@ bool Table::editCell(gdioutput &gdi, int row, int col) {
max<int>(int((rc.right-rc.left+1)/gdi.scale), width), (rc.bottom-rc.top)*10,
tblSelectionCB).setExtra(id);
}
gdi.addItem(tId, out);
gdi.setItems(tId, out);
gdi.selectItemByData(tId, selected);
return true;
}

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,6 +26,7 @@
#include <set>
#include "oBase.h"
#include "inthashmap.h"
#include "guihandler.h"
#define TableXMargin 40
#define TableYMargin 30
@ -62,7 +63,7 @@ class TableCell
friend class TableRow;
friend class Table;
friend int tblSelectionCB(gdioutput *gdi, int type, void *data);
friend int tblSelectionCB(gdioutput *gdi, GuiEventType type, BaseInfo* data);
public:
void update(CellType t, const wstring &str) {

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -10,7 +10,7 @@
#endif // _MSC_VER > 1000
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -39,14 +39,14 @@ class AnimationData : public GuiHandler {
DWORD nextTime;
DWORD timeOut;
bool doAnimation;
atomic_bool errorState;
std::atomic_bool errorState;
gdioutput *gdiRef;
void renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, int x, int y, int animationDelay);
void doRender(HDC hDC, gdioutput &gdi, size_t sp, int delay);
shared_ptr<thread> animationThread;
shared_ptr<std::thread> animationThread;
shared_ptr<AnimationData> delayedTakeOver;
void takeOverInternal(const shared_ptr<AnimationData> &other);

BIN
code/announcer24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,6 +26,8 @@
#include <cassert>
#include "binencoder.h"
using namespace std;
Encoder92::Encoder92() {
int d = 32;
fill(reverse_table, reverse_table + 128, 0);

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

BIN
code/class24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

BIN
code/clubs24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

BIN
code/competition24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

BIN
code/course24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -35,13 +35,7 @@
#include "meosexception.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include <vector>
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
@ -216,7 +210,7 @@ bool csvparser::importOS_CSV(oEvent &oe, const wstring &file) {
DI.setString("Nationality", sp[OSnat]);
if (sp[rindex + OSRrentcard].length() > 0)
DI.setInt("CardFee", oe.getDCI().getInt("CardFee"));
r->setRentalCard(true);
//r->setCardNo(atoi(sp[rindex+OSRcard]), false);
r->setStartTime(oe.convertAbsoluteTime(sp[rindex + OSRstart]), true, oBase::ChangeType::Update);
@ -383,7 +377,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
oDataInterface DI=pr->getDI();
pr->setSex(interpretSex(sp[OEsex]));
DI.setInt("BirthYear", extendYear(wtoi(sp[OEbirth])));
pr->setBirthDate(sp[OEbirth]);
DI.setString("Nationality", sp[OEnat]);
if (sp.size()>OEbib && needBib)
@ -391,7 +385,9 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
if (sp.size()>=38) {//ECO
DI.setInt("Fee", wtoi(sp[OEfee]));
DI.setInt("CardFee", wtoi(sp[OErent]));
if (wtoi(sp[OErent]))
pr->setRentalCard(true);
DI.setInt("Paid", wtoi(sp[OEpaid]));
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -61,8 +61,8 @@ struct TeamLineup {
class csvparser
{
protected:
ofstream fout;
ifstream fin;
std::ofstream fout;
std::ifstream fin;
int LineNumber;
string ErrorMessage;

BIN
code/ctrl24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -205,9 +205,9 @@ void Download::downloadFile(const wstring &url, const wstring &file, const vecto
}
}
fileno=_wopen(file.c_str(), O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
if (fileno==-1) {
//fileno=_wopen(file.c_str(), O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
errno_t err = _wsopen_s(&fileno, file.c_str(), _O_BINARY | _O_CREAT | _O_WRONLY | _O_TRUNC, _SH_DENYWR ,_S_IREAD | _S_IWRITE);
if (err != 0) {
fileno = 0;
endDownload();
wchar_t bf[256];
@ -463,7 +463,13 @@ bool Download::httpSendReqEx(HINTERNET hConnect, bool https, const wstring &dest
}
}
int rfileno = _wopen(outFile.c_str(), O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
// int rfileno = _wopen(outFile.c_str(), O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE);
int rfileno;
errno_t err = _wsopen_s(&rfileno, outFile.c_str(), _O_BINARY | _O_CREAT | _O_WRONLY | _O_TRUNC, _SH_DENYWR, _S_IREAD | _S_IWRITE);
if (err != 0) {
InternetCloseHandle(hRequest);
throw meosException(L"Failed to open + " + outFile);
}
do {
dwBytesRead=0;

View File

@ -7,7 +7,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

BIN
code/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

View File

@ -130,7 +130,7 @@ Automater = Services
Automatic rogaining point reduction = Automatic rogaining point reduction
Automatisera = Automatize
Automatisk = Automatic
Automatisk hyrbrickshantering genom registrerade hyrbrickor = Automatic handling of hired cards using pre-registered card numbers
Automatisk hyrbrickshantering genom registrerade hyrbrickor = Automatic handling of rental cards using pre-registered card numbers
Automatisk lottning = Draw Automatically
Automatisk omladdning = Automatic update
Automatisk skroll = Automatic Scroll
@ -161,7 +161,7 @@ Avmarkera 'X' för att hantera alla bricktildelningar samtidigt = Uncheck 'X' to
Avmarkera allt = Deselect all
Avrundad tävlingsavgift = Competition fee, rounded
Avsluta = Exit
Avstämning hyrbrickor = Count returned hired cards
Avstämning hyrbrickor = Count returned rental cards
Avstånd = Distance
Bad file format = Bad file format
Bakgrund = Background
@ -256,7 +256,7 @@ Checkenhet = Check unit
Choose result module = Choose result module
ClassAvailableMaps = Available maps for class
ClassCourseResult = Class, course, result
ClassDefaultResult = Class, Default result
ClassDefaultResult = Class, default result
ClassFinishTime = Class, finish time
ClassKnockoutTotalResult = Class, knock-out total result
ClassLength = Course length for class
@ -681,8 +681,8 @@ Hoppar över stafettklass: X = Skipping relay class: X
Huvudlista = Main list
Hyravgift = Card hire
Hyrbricka = Hired card
Hyrbricksrapport = Report with Hired Cards
Hyrbricksrapport - %s = Hired Cards - %s
Hyrbricksrapport = Report with Rental Cards
Hyrbricksrapport - %s = Rental Cards - %s
Hyrd = Hired
Hämta (efter)anmälningar från Eventor = Fetch (late) entries from Eventor
Hämta data från Eventor = Fetch Data from Eventor
@ -795,7 +795,7 @@ Inget filter = No filter
Inget nummer = No number
Inkludera bana = Include course
Inkludera bomanalys = Include analysis of lost time
Inkludera individuellt resultat = Include indiviual result
Inkludera individuellt resultat = Include individual result
Inkludera information om flera lopp per löpare = Include information about multiple races for a single runner.
Inkludera resultat från tidigare etapper = Include results from all stages
Inkludera sträcktider = Include splits
@ -856,7 +856,7 @@ Klassen X är individuell = The class X is individual
Klassen X är listad flera gånger = The class X is listed several times
Klassen använder banpool = The class has a course pool
Klassen används och kan inte tas bort = The class is in use and cannot be removed
Klassen lottas inte, startstämpling = Use only start punch
Klassen lottas inte, startstämpling = Start list not drawn, use start punch
Klassen måste ha ett namn = The class must have a name
Klassen saknas = Missing class
Klassen är full = The class is full
@ -1941,12 +1941,12 @@ Tillagda: X = Added: X
Tilldela = Assign
Tilldela avgifter = Assign Fees
Tilldela endast avgift till deltagare utan avgift = Assign fee only to competitors without fee
Tilldela hyrbrickor = Assign cards
Tilldela hyrbrickor = Assign rental cards
Tilldela nummerlappar = Assign bibs
Tilldela nya fakturanummer till alla klubbar? = Assign new invoice numbers to all clubs?
Tilldela starttider = Assign start times
Tilldelad = Assigned
Tilldelning av hyrbrickor = Assign Cards
Tilldelning av hyrbrickor = Assign Rental Cards
Tillgängliga automater = Available services
Tillgängliga filer installerades. Starta om MeOS. = Settings was installed. Please restart MeOS.
Tillgängliga listor = Available lists
@ -2122,7 +2122,7 @@ Vi stöder MeOS = We Support MeOS
Viktiga händelser = Important events
Vill du använda den nya brickan till alla etapper? = Do you want to use the new card for all stages?
Vill du att X går in i laget? = Do you want to put X in the team?
Vill du att X och Y byter sträcka? = Do you want X and Y to switch leg?
Vill du att X och Y byter sträcka? = Do you want X and Y to swap legs?
Vill du att X tar sträckan istället för Y? = Do you want X to run the leg instead of Y?
Vill du dumpa aktuellt tävling och skapa en testtävling? = Do you want to dump the current competition and create a test competition?
Vill du flytta löpare från X till Y och ta bort Z? = Do you want to move runners from X to Y and remove Z?
@ -2230,7 +2230,7 @@ X (Saknar e-post) = X (Has no e-mail)
X (Y deltagare, grupp Z, W) = X (Y competitors, group Z, W)
X (press Ctrl+Space to confirm) = X (press <Ctrl>+<Space> to confirm)
X anmälda = X entries
X går vidare, klass enligt ranking = X qualified, class by ranking
X går vidare, klass enligt ranking = X qualifies, class by ranking
X har en tid (Y) som inte är kompatibel med förändringen = X has a time (Y) that is incompatible with this change
X har redan bricknummer Y. Vill du ändra det? = X already has card number Y. Do you want to change it?
X har redan ett resultat. Vi du fortsätta? = X already has a result. Do you wish to continue?
@ -2294,7 +2294,6 @@ edit_in_forest = Manage\nRemaining Runners
ej aktiv = not active
elfte = eleventh
elva = eleventh
encoding = ANSI
error:invalidmethod = The selected method gave no distribution. Source data is insufficient.
ett Mycket Enkelt OrienteringsSystem = a Much Easier Orienteering System
eventor:help = If you use MeOS for orienteering in Sweden, we recommend that you use MeOS's Eventor connection.
@ -2375,8 +2374,8 @@ help:restore_backup = Choose a backup to restore by clicking the time when the b
help:runnerdatabase = By importing a runner and club database, MeOS will automatically recognize unknown runners (by card number), and you will get addresses and phone numbers to clubs.
help:save = MeOS automatically saves all settings when needed.
help:seeding_info = Seeded start time allocation means that an earlier result or ranking controls the process in part. In the field seeding groups you may either enter a single group size, meaning that the entire class is partitioned into groups of this size. The group size "1" means that the seeding order is strictly used. You can also specify several group sizes. "15, 1000" would mean a seeded group with the 15 highest ranked runners and the remaining (at most 1000) runners are placed in a non-seeded group.
help:selectsound = Select sounds to play. By default MeOS built-in sounds are played.
help:simulate = This service lets you simulate readout of SI cards. Times and punches are generated for all runners. Also radio contol punches can be simulated.\n\nWARNING: Use for testing only. If you use this on a real event, it will be corrupted.
help:selectsound = Select sounds to play. By default, MeOS built-in sounds are played.
help:simulate = This service lets you simulate readout of SI cards. Times and punches are generated for all runners. Also radio control punches can be simulated.\n\nWARNING: Use for testing only. If you use this on a real event, it will be corrupted.
help:speaker_setup = Choose which classes and courses you want to watch.
help:speakerprio = Check those runners/teams you wish to watch from start, and as long as the runner/team is doing well. Put two checks to watch even if the result is not so good. No check means monitoring only if the runner/team is doing well (not from start).
help:splitexport = Decide if you want to export total results, or individual results for each race. If you choose to export all races, numbered files will be created.
@ -2476,7 +2475,7 @@ prefsOrganizer = Organizer
prefsPayModes = Modes of payment
prefsPlaySound = Play sounds
prefsPort = MySQL network port
prefsRentCard = Rent card
prefsRentCard = Rent cards by default
prefsSeniorAge = Upper (pensioner) age limit
prefsServer = Default network server
prefsServicePort = Default service port
@ -2672,5 +2671,131 @@ Välj bild = Select image
Välj bland befintliga bilder = Select existing image
Bevara höjd/bredd-relationen = Preserve aspect ratio
RunnerLegTeamLeaderName = First competitor in team to finish leg
info:offsetclassid = If you import entries and classes from different sources to the same competition, it might happen that there are clashes in the Id numbers of the classes. To separate the classes, you may enter an offset for the Class Id when working with files from a particular source; this will be added to the Id numbers.\n\nYou must specify the same offset each time you import from that source.\n\n A suitble number could be1000 (which will work as long as every Id is less that 1000).
info:offsetclassid = If you import entries and classes from different sources to the same competition, it might happen that there are clashes in the Id numbers of the classes. To separate the classes, you may enter an offset for the Class Id when working with files from a particular source; this will be added to the Id numbers.\n\nYou must specify the same offset each time you import from that source.\n\n A suitable number could be 1000 (which will work as long as every Id is less that 1000).
Förskjutning av klassers Id = Offset Class ID
Tilldela nummerlapp till vakanter = Assign bibs to vacancies
Avläsning = Readout
Inmatning Testning = Input Testing
Testning = Testing
CourseNumControls = Number of controls
PunchControlPlaceTeamAcc = Total team place at control
PunchTeamTime = Team total time and split at control
PunchTeamTotalNamedTime = Total team named split time
PunchTeamTotalTime = Total team running time to control
PunchTeamTotalTimeAfter = Team's time after at control
Aktivera kioskläge = Activate kiosk mode
Avstånd mellan förslag (minuter) = Distance between suggestions (minutes)
Boka starttid = Request start time
Ingen ledig starttid kunde hittas = No free start time was found
Minsta tid till start (minuter) = Least time to start (minutes)
Sista starttid = Last start time
Startintervall (minuter) = Start interval (minutes)
Tillåt klass med samma bana på samma starttid = Allow class with same course on same start time
Tillåt klass med samma bana på stattid före/efter = Allow class with same course before and after
Tillåt klass med samma första kontroll vid samma starttid = Allow class with same first control at the same time
Tiden har passerat sista tillåtna starttid = Time has passed last allowed start time
Starttiden är låst = The start time is locked
Starttiden är redan tilldelad = The start time is already assigned
Klassen tillåter ej val av starttid = The class does not allow request of start time
Klassen lottas inte, boka starttid = Start list not drawn, request start time on the page SportIdent
Simulerar starttidstilldelning för X deltagare = Simulating start time assignments for X competitors
Simulering = Simulation
Välj från flera förslag = Choose start time
Välj starttid för X = Choose start time for X
X: Startid för Y kl Z = X: Start time for Y at Z
Önskad starttid = Desired start time
ask:startkiosk = If you start a start time reservation kiosk, MeOS enters a state where no other operations are supported or settings can be changed. You need a connected and activated SI unit.\n\nYou should consider password protecting the database if you are exposing a kiosk.\n\nDo you want to start the kiosk mode?
ask:simulatestart = Carry out a simulation with the settings you have made (classes, starting depth, distance, rules) and with the registered participants who are in the classes. The competition is not affected. The result shows whether it is reasonable that everyone has time to start within the set start depth and how long extra waiting time to start may be required in different classes.\n\nAfterwards, you can also save a copy of the competition with simulated start times to study e.g. minute start list.\n\nDo you want to run the simulation?
help:requeststart = Requesting start time is something in between free and drawn start time. By requesting a start time, MeOS ensures that there is a certain distance between participants in the same class or on the same course. If you have a requested start time, it is not necessary to use a start punch.\n\nSet parameters for start depth and how many/who are allowed to start at the same time. How far it is from the place where the booking is made to the start determines what is an appropriate minimum time to start value.\n\nYou can let the participants automatically get the first possible available start time after the minimum time to start, or let them choose from a number possible start times. It is possible and appropriate to print out a start certificate to take with you to the start.\n\nIf you are using a live results service, the start time will probably be displayed there when booked.
Anslut en SI-enhet och aktivera den = Connect and activate a SI unit
Manuellt startönskemål = Manual start request
Stämpla för välja starttid = Punch to choose a start time
Tillåt deltagare med samma klubb och klass på närliggande starttid = Allow competitors from the same club and class on next start time
prevsExpResFilename = Export results
prefsExpStaFilename = Export start list
prefsRequestClubNeighbour = Request start: Allow same club neighbour
prefsRequestLastStart = Request start: Last start
prefsRequestMaxParallel = Request start: Max parallel starts
prefsRequestMinTime = Request start: Time to start
prefsRequestProvideSuggestion = Request start: Make suggestions
prefsRequestSameCourse = Request start: Same course
prefsRequestSameCourseNeighbour = Request start: Same course for neighbour
prefsRequestSameFirstControl = Request start: Samma first control
prefsRequestStartInterval = Request start: Interval
prefsRequestSuggestInterval = Request start: Time between suggestions
Omstart: X = Restart: X
Reptid: X = Rope time: X
Datortid = Computer time
Start på signal = Start on signal
Sätt tiden = Set time
Välj vilken tid du vill sätta = Select which time to set
Starta nu = Start now
Alla okvalificerade = Any unqualified
Antal nivåer = Number of levels
Använd ranking istället för placering i kval för att placera kvalificerade löpare i klasser = Use ranking instead of placement to distribute qualified runners into classes
Bästa tid = Best time
Final = Final
Klass / placering = Class / place
Klass X (namnsuffix) = Class X (name suffix)
Klass efter ranking = Select class by ranking
Kval = Qualification
Kvalificeringsregler för X = Qualification Rules for X
Kvalklass = Qualification class
Ladda = Load
N bästa = N best
Nivå X = Level X
Placeringar = Placements
Regler = Rules
Tidsgräns X = Time limit X
Tidskval = Time qualification
Use in X = Use in X
X bästa okvalificerade = X best unqualified
X kvalificerade = X qualified
Övriga okvalificerade = Remaining unqualified
Lägg till regler = Add rules
Placering X kvalificerar till Y = Place X qualifies for Y
X bästa = X best
Alla övriga = All remaining
Vill du starta automaten? = Do you want to start the service?
För kommunikationstest kan man använda en separat testtävling = To test communication, you can use a separate test competition
Observera att stämplingar före tävlingens nolltid inte kan hämtas = Note MeOS cannot fetch punches preceding the competition zero time
Individual Rogaining Split Print = Individual Rogaining Split Print
Lap Count = Lap count
Lap count with extra punch = Lap count with extra punch
Live results, radio = Live results, radio
Patrol results = Patrol results
Patrol, start list = Patrol, start list
Resultatlista, Rogaining, lag = Results, Rogaining, team
Startlista, lag = Start list, team
Team Rogaining Split Print = Team Rogaining Split Print
RunnerRentalCard = Rental card
Primärt = Primary
Sekundärt = Secondary
Välj typ av ID att exportera = Select ID types to export
Ursprunglig tid: X = Original time: X
Manuellt ändrad stämpling = Manually changed data
help_second_fee = Use a second raised fee for direct entry at the competition day (for example). The higher fee is applied starting from and including the specified day. The specified percentage is relative the original fee.
Avgiftshöjning två (procent) = Second fee increase (percent)
ClassDataA = Class data A
ClassDataB = Class data B
ClassTextA = Class text
Extra data X = Extra data X
Extra datafält = Extra data fields
Kommentarer = Comments
Oförändrad brickdata = Original card data
Okänd ursprungsstatus = Unknown data origin status
RunnerDataA = Competitor data A
RunnerDataB = Competitor data B
RunnerTextA = Competitor text
Sida = Page
Stoppdatum två = Second stop date
TeamDataA = Team data A
TeamDataB = Team data B
TeamTextA = Team text
Födelsedatum = Birth date
Kommentar = Comment
Lägg till eller redigera kommentarer om deltagaren = Add or edit a comment about the competitor
Lägg till eller redigera kommentarer om deltagaren = Add or edit a comment about the team
Manuellt ändrad brickdata = Manually modified card data
Efteranmälan = Late entry
Reducerad = Reduced

View File

@ -214,7 +214,9 @@ Bevakar händelser i X = Moniteur d'évènement X
Bevakningsprioritering = Sélectionner le coureur à surveiller
Bevara höjd/bredd-relationen = Conserver les proportions
Bibs = Dossards
Bild = Image
Bild under text = Mettre l'image sous le texte
Bilder = Images
Block = Bloc
Blockbredd = Largeur de bloc
Bläddra = Parcourir
@ -265,7 +267,7 @@ ClassKnockoutTotalResult = Class, knock-out total result
ClassLength = Longueur du circuit pour la catégorie
ClassLiveResult = Live results (temps radios), par catégorie
ClassName = Catégorie
ClassNumEntries = Nombre d'inscrits
ClassNumEntries = Nombre d'inscrits dans la catégorie
ClassPoints = Catégorie, points
ClassResult = Catégorie, résultat
ClassResultFraction = Pourcentage de la catégorie ayant terminé
@ -422,6 +424,7 @@ Elektronisk godkänd = Accepté électroniquement
Elit = Élite
Elitavgift = Frais élites
Elitklasser = Catégorie élite
Empty Results Split Print = Temps intermédiaires sans résultats
En bana med slingor tillåter deltagaren att ta slingorna i valfri ordning = Un circuit avec des boucles autorise le coureur à effectuer les boucles dans n'importe quel ordre.
En gafflad sträcka = Circuit avec variations
En klass kan inte slås ihop med sig själv = Vous ne pouvez pas fusionner une catégorie avec elle-même
@ -621,6 +624,7 @@ Förhindra att laget deltar i någon omstart = Permet à l'équipe de ne pas pre
Förhindra omstart = Refuser le départ des attardés
Förhöjd avgift = Frais supplémentaires
Förskjutning = Déplacement
Förskjutning av klassers Id = Décalage de l'identifiant de catégorie
Först = En premier
Först-i-mål, gemensam = Du premier au dernier, commun
Först-i-mål, klassvis = Du premier au dernier, par catégorie
@ -685,6 +689,7 @@ Hittar inte hjälpfilen, X = Documentation introuvable, X
Hittar inte klass X = Impossible de trouver la catégorie X
Hjälp = Aide
Hoppar över stafettklass: X = Sauter la catégorie de relais: X
Horisontell = Horizontal
Horizontell = Horizontalement
Huvudlista = Liste principale
Hyravgift = Tarif de location
@ -763,6 +768,8 @@ Inconsistent qualification rule, X = Règle de qualification incohérente, X
Index = Index
Index in X[index] = Index en X[index]
Individual Example = Exemple de course individuelle
Individual Results Split Print = Avec résultats individuels
Individual Rogaining Split Print = Avec résultats de la course au score
Individual result by finish time = Résultat individuel sur l'heure d'arrivée
Individual results in a club = Résultats individuel au sein du club
Individuell = par catégorie
@ -1009,6 +1016,7 @@ Liveresultat, radiotider = Résultats en direct avec radios
Ljud = Son
Ljudfiler, baskatalog = Répertoire de base des fichiers sonores
Ljudval = Sélection des sons
Lokal kopia från X = Copie locale de X
Lokalt = Localement
Long = Longue
Longitud = Longitude
@ -1402,6 +1410,8 @@ Relation till föregående = Lien avec le précédent
Relativ skalfaktor för typsnittets storlek i procent = Facteur d'échelle pour la police (pourcentage)
Relay Example = Exemple de relais
Relay Example (Lokal kopia från: localhost) = Exemple de relais (Copie locale depuis : localhost)
Relay Results Split Print = Avec résultats du relais
Relay/Team Results Split Print = Avec résultats du relais/de l'équipe
Relays = Relais
Rep = Arrêt attardés
Reparera vald tävling = Réparer la compétition sélectionnée
@ -1526,6 +1536,7 @@ RunnerId = Licence/ID
RunnerLeg = Concurrent (variation spécifique)
RunnerLegNumber = Numéro de relais groupé du coureur
RunnerLegNumberAlpha = Numéro de relais exact du coureur
RunnerLegTeamLeaderName = Premier membre de l'équipe à terminer son circuit
RunnerName = Nom du coureur
RunnerNationality = Nationalité du coureur
RunnerPaid = Payé
@ -1888,6 +1899,7 @@ Tabelläge = Mode table
Tar bort X = Retrait de X
Team = Équipe
Team Rogaining = Course au score en équipe
Team Rogaining Split Print = Avec résultats de la course au score en équipe
TeamBib = Dossard de l'équipe
TeamClub = Club de l'équipe
TeamCourseName = Nom du circuit pour l'équipe/la branche
@ -2217,6 +2229,7 @@ Välj alla klasser = Sélectionner toutes les catégories
Välj allt = Sélectionner tout
Välj automatiskt = Sélection automatique
Välj bild = Choisir une image
Välj bland befintliga bilder = Sélectionner une image existante
Välj deltagare för förhandsgranskning = Sélectionner un coureur pour prévisualisation
Välj den etapp som föregår denna tävling = Sélectionner l'étape précédente
Välj den etapp som kommer efter denna tävling = Sélectionner l'étape suivante
@ -2428,11 +2441,12 @@ info:mapcontrol = MeOS ne sait pas déterminer la fonction d'un boîtier s'il n'
info:multieventnetwork = Pour prendre en charge plus d'une étape vous devez travailler localement. Faite une copie de sauvegarde de la compétition, ouvrez-la en local et transférez les résultats à l'étape suivante. Enfin, remontez l'étape suivante sur le serveur.
info:multiple_start = Un coureur peut faire plusieurs fois le même circuit. Une nouvelle inscription est créée à chaque lecture de la puce
info:nosplitprint = Chargement de la liste personnalisée impossible\n\nCelle par défaut la remplace
info:offsetclassid = Si vous importez des inscrits et des catégories depuis des sources différentes dans la même compétition, il peut y avoir des conflits entre les numéros d'identifiant des catégories. Pour différencier les catégories, vous pouvez entrer un décalage de la valeur de l'identifiant des catégorires pour chacune des sources. Celui-ci sera ajouté à l'identifiant existant.\n\nVous pouvez par exemple entrer 1000 (si aucune catégorie n'a déjà un identifiant supérieur à 1000).
info:pageswithcolumns = Montrer la liste page par page, avec un nombre spécifié de colonnes. Les infos sont mises à jour à chaque bouclage.
info:readout_action = X: Puce no. Y lue.\nDes actions manuelles sont requises.
info:readout_queue = X: Puce no. Y lue.\nLa puce a été mise en file d'attente.
info:readoutbase = Activez le boîtier SI en sélectionnant son port COM ou en recherchant les boîtiers SI installés. Appuyez sur Information pour obtenir le statut du port sélectionné.\n\nLecture Interactive vous permet de gérer directement les problèmes tels qu'un numéro de puce erroné. N'utilisez pas cette possibilité quand les coureurs ayant des problèmes sont pris en charge séparément.\n\nLa base de données des coureurs est utilisée si vous voulez ajouter automatiquement de nouveaux coureurs. Les poinçons sont utilisés pour trouver (détecter) la bonne catégorie.
info:readoutmore = Verrouillez la fonction pour éviter toute modification accidentelle.\n\nSélection des sons vous permet de lancer différents sons lors de la lecture des puces pour être plus facilement informé des problèmes.\n\n"Fenêtre de prévisualisation coureur" affiche une nouvelle fenêtre destinée au coureur qui lit sa puce, regroupant les informations principales de sa course.\n\nPlusieurs courses pour un coureur est utile si un coureur est autorisé a faire plusieurs fois son circuit. Une nouvelle inscriprion est créée à chaque lecture de la puce.
info:readoutmore = Verrouillez la fonction pour éviter toute modification accidentelle.\n\nSélection des sons vous permet de lancer différents sons lors de la lecture des puces pour être plus facilement informé des problèmes.\n\n"Fenêtre de prévisualisation coureur" affiche une nouvelle fenêtre destinée au coureur qui lit sa puce, regroupant les informations principales de sa course.\n\nPlusieurs courses pour un coureur est utile si un coureur est autorisé a faire plusieurs fois son circuit. Une nouvelle inscription est créée à chaque lecture de la puce.
info:readoutwindow = Cette fenêtre affiche les informations principales de chaque lecture de puce
info:runnerdbonline = Comme vous êtes connecté à un serveur, il n'est pas possible d'éditer les bases de données club et coureurs manuellement. Effectuez les changements avant d'uploader la compétition sur un serveur. Il est également possible de remplacer la base de données existante sur le serveur en important une nouvelle base (à partir de IOF XML).
info:teamcourseassignment = Le fichier des circuits IOF XML 3.0 contient les variations des équipes. Pour importer ces données, vous devez préparer la compétition en fonction des données du fichier :\n\n1.Assurez-vous que les catégories de relais ont le bon nombre de branches.\n2. Affectez les dossards à chaque catégorie. Passez par la Configuration Rapide dans l'onglet Catégories et renseignez le premier dossard de chaque catégorie (avec la répartition automatique des dossards). Vous pouvez aussi importer les équipes et leur attribuer des dossards comme d'habitude.\n\n\n3. Importez les circuits. Vous pouvez importer plusieurs fois ce fichier si nécessaire pour mettre à jour les variations.

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -62,6 +62,7 @@ constexpr int skipBoundingBox = 1 << 18;
constexpr int hiddenText = 1 << 19;
constexpr int textLimitEllipsis = 1 << 20;
constexpr int imageNoUpdatePos = 1 << 21;
constexpr int time24HourClock = 1 << 22;
enum GDICOLOR {
colorBlack = RGB(0, 0, 0),

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -59,8 +59,8 @@ public:
class GDIImplFontEnum {
private:
int width;
int height;
int width = 0;
int height = 0;
double relScale;
wstring face;
public:

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -320,6 +320,18 @@ void gdioutput::initCommon(double _scale, const wstring &font)
fontHeightCache.clear();
fonts[currentFont].init(scale, currentFont, L"");
updateTabFont();
}
void gdioutput::updateTabFont() {
if (this == gdi_main && hWndTab) {
HFONT gui = fonts[currentFont].getGUIFont();
SendMessage(hWndTab, WM_SETFONT, WPARAM(gui), TRUE);
RECT rc;
GetClientRect(hWndAppMain, &rc);
SendMessage(hWndAppMain, WM_SIZE, 0, MAKELONG(rc.right, rc.bottom));
}
}
double getLocalScale(const wstring &fontName, wstring &faceName) {
@ -888,6 +900,7 @@ TextInfo& gdioutput::addImage(const string& id, int yp, int xp, int format,
imageReferences.push_back(&TI);
TI.id = id;
TI.format = format | textImage;
TI.xp = xp;
TI.yp = yp;
@ -1043,9 +1056,14 @@ TextInfo& gdioutput::addString(const char* id, int yp, int xp, int format, const
TI.format = format;
TI.xp = xp;
TI.yp = yp;
if ((format & 0xFF) != textImage) {
TI.text = lang.tl(text);
if ((format & Capitalize) == Capitalize && lang.capitalizeWords())
capitalizeWords(TI.text);
}
else {
TI.text = text;
}
TI.id = id;
TI.xlimit = xlimit;
TI.callBack = cb;
@ -1201,7 +1219,7 @@ void ButtonInfo::moveButton(gdioutput &gdi, int nxp, int nyp) {
gdi.updatePos(xp, yp, w, h);
}
void ButtonInfo::getDimension(gdioutput &gdi, int &w, int &h) {
void ButtonInfo::getDimension(const gdioutput &gdi, int &w, int &h) const {
RECT rc;
GetWindowRect(hWnd, &rc);
w = rc.right - rc.left + gdi.scaleLength(GDI_BUTTON_SPACING);
@ -1215,9 +1233,18 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
}
ButtonInfo& gdioutput::addButton(int x, int y, int w, const string& id,
const wstring &text, GUICALLBACK cb, const wstring &tooltip,
bool AbsPos, bool hasState)
{
const wstring& text, GUICALLBACK cb, const wstring& toolTip,
bool absPos, bool hasState) {
return addButton(x, y, w, getButtonHeight(), id, text,
gdiFonts::normalText, cb, toolTip, absPos, hasState);
}
ButtonInfo& gdioutput::addButton(int x, int y, int width, int height,
const string& id, const wstring& text,
gdiFonts font, GUICALLBACK cb,
const wstring& tooltip,
bool absPos, bool hasState) {
int style = hasState ? BS_CHECKBOX | BS_PUSHLIKE : BS_PUSHBUTTON;
if (text[0] == '@')
@ -1234,34 +1261,36 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
}
if (lang.capitalizeWords())
capitalizeWords(ttext);
int height = getButtonHeight();
if (AbsPos){
if (ttext.find_first_of('\n') != string::npos) { //WCS
if (absPos) {
if (ttext.find_first_of('\n') != string::npos) {
style |= BS_MULTILINE;
height *= 2;
}
bi.hWnd = CreateWindow(L"BUTTON", ttext.c_str(), WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | style | BS_NOTIFY,
x-OffsetX, y, w, height, hWndTarget, NULL,
x - OffsetX, y, width, height, hWndTarget, NULL,
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
}
else {
bi.hWnd = CreateWindow(L"BUTTON", ttext.c_str(), WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | style | BS_NOTIFY,
x-OffsetX, y-OffsetY-1, w, height, hWndTarget, NULL,
x - OffsetX, y - OffsetY - 1, width, height, hWndTarget, NULL,
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
}
if (font == gdiFonts::normalText)
SendMessage(bi.hWnd, WM_SETFONT, (WPARAM)getGUIFont(), 0);
else
SendMessage(bi.hWnd, WM_SETFONT, (WPARAM)getCurrentFont().getFont(font), 0);
if (!AbsPos)
updatePos(x, y, w+scaleLength(GDI_BUTTON_SPACING), height+5);
if (!absPos)
updatePos(x, y, width + scaleLength(GDI_BUTTON_SPACING), height + 5);
bi.xp = x;
bi.yp=y;
bi.width = w;
bi.yp = y - 1;
bi.width = width;
bi.text = ttext;
bi.id = id;
bi.callBack = cb;
bi.AbsPos=AbsPos;
bi.AbsPos = absPos;
if (tooltip.length() > 0)
addToolTip(id, tooltip, bi.hWnd);
@ -1273,7 +1302,7 @@ ButtonInfo &gdioutput::addButton(int x, int y, int w, const string &id,
return BI.back();
}
static int checkBoxCallback(gdioutput *gdi, int type, void *data) {
static int checkBoxCallback(gdioutput *gdi, GuiEventType type, BaseInfo *data) {
if (type == GUI_LINK) {
TextInfo *ti = (TextInfo *)data;
string cid = ti->id.substr(1);
@ -1345,9 +1374,10 @@ ButtonInfo &gdioutput::addCheckbox(int x, int y, const string &id, const wstring
GetTextExtentPoint32(hDC, ttext.c_str(), ttext.length(), &size);
ReleaseDC(hWndTarget, hDC);
int cbY = y + (size.cy - h) / 2;
bi.hWnd = CreateWindowEx(0, L"BUTTON", L"", WS_TABSTOP | WS_VISIBLE |
WS_CHILD | WS_CLIPSIBLINGS | BS_AUTOCHECKBOX | BS_NOTIFY,
x-ox, y-oy + (size.cy-h)/2, h, h, hWndTarget, NULL,
x - ox, cbY - oy, h, h, hWndTarget, NULL,
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
TextInfo& desc = addStringUT(y, x + (3 * h) / 2, 0, ttext, 0, checkBoxCallback);
@ -1372,7 +1402,7 @@ ButtonInfo &gdioutput::addCheckbox(int x, int y, const string &id, const wstring
}
bi.isCheckbox = true;
bi.xp = x;
bi.yp=y;
bi.yp = cbY;
bi.width = desc.textRect.right - (x - ox);
bi.text = ttext;
bi.id = id;
@ -1514,14 +1544,15 @@ InputInfo &gdioutput::addInputBox(const string &id, int width, int height, const
return addInputBox(id, CurrentX, CurrentY, width, height, text, cb, explanation);
}
InputInfo &gdioutput::addInputBox(const string &id, int x, int y, int width, int height,
const wstring &text, GUICALLBACK cb, const wstring &Explanation)
InputInfo &gdioutput::addInputBox(const string &id, int x, int y, int widthIn, int heightIn,
const wstring &text, GUICALLBACK cb, const wstring &explanation)
{
if (Explanation.length()>0) {
addString("", y, x, 0, Explanation);
if (explanation.length()>0) {
addString("", y, x, 0, explanation);
y+=lineHeight;
}
int width = scaleLength(widthIn);
int height = scaleLength(heightIn);
InputInfo ii;
int ox=OffsetX;
@ -1532,7 +1563,7 @@ InputInfo &gdioutput::addInputBox(const string &id, int x, int y, int width, int
x-ox, y-oy, width, height, hWndTarget, NULL,
(HINSTANCE)GetWindowLongPtr(hWndTarget, GWLP_HINSTANCE), NULL);
updatePos(x, y, width, height);
updatePos(x, y, width, height + scaleLength(5));
SendMessage(ii.hWnd, WM_SETFONT, (WPARAM) getGUIFont(), 0);
@ -1545,12 +1576,9 @@ InputInfo &gdioutput::addInputBox(const string &id, int x, int y, int width, int
ii.focusText = text;
ii.id=id;
ii.callBack=cb;
II.push_back(ii);
iiByHwnd[ii.hWnd] = &II.back();
//if (Help.length() > 0)
// addToolTip(Help, ii.hWnd);
FocusList.push_back(ii.hWnd);
return II.back();
@ -1775,8 +1803,7 @@ ListBoxInfo &gdioutput::addCombo(int x, int y, const string &id, int width, int
return LBI.back();
}
bool gdioutput::addItem(const string &id, const wstring &text, size_t data)
{
bool gdioutput::addItem(const string &id, const wstring &text, size_t data) {
list<ListBoxInfo>::reverse_iterator it;
for (it=LBI.rbegin(); it != LBI.rend(); ++it) {
if (it->id==id) {
@ -1784,11 +1811,13 @@ bool gdioutput::addItem(const string &id, const wstring &text, size_t data)
LRESULT index=SendMessage(it->hWnd, CB_ADDSTRING, 0, LPARAM(text.c_str()));
SendMessage(it->hWnd, CB_SETITEMDATA, index, data);
it->data2Index[data] = int(index);
it->computed_hash = 0;
}
else {
LRESULT index=SendMessage(it->hWnd, LB_INSERTSTRING, -1, LPARAM(text.c_str()));
SendMessage(it->hWnd, LB_SETITEMDATA, index, data);
it->data2Index[data] = int(index);
it->computed_hash = 0;
}
return true;
}
@ -1796,12 +1825,35 @@ bool gdioutput::addItem(const string &id, const wstring &text, size_t data)
return false;
}
bool gdioutput::addItem(const string& id, const vector< pair<wstring, size_t> >& items)
{
list<ListBoxInfo>::reverse_iterator it;
for (it = LBI.rbegin(); it != LBI.rend(); ++it) {
bool gdioutput::modifyItemDescription(const string& id, size_t itemData, const wstring &description) {
for (auto it = LBI.rbegin(); it != LBI.rend(); ++it) {
if (it->id == id) {
int ix = it->data2Index[itemData];
// It is intentioal that the hash is not modified. This method allows "customization" of
// some description without reloading a complete listbox
if (it->IsCombo) {
SendMessage(it->hWnd, CB_DELETESTRING, ix, 0);
SendMessage(it->hWnd, CB_INSERTSTRING, ix, LPARAM(description.c_str()));
SendMessage(it->hWnd, CB_SETITEMDATA, ix, itemData);
}
else {
SendMessage(it->hWnd, LB_DELETESTRING, ix, 0);
SendMessage(it->hWnd, LB_INSERTSTRING, ix, LPARAM(description.c_str()));
SendMessage(it->hWnd, LB_SETITEMDATA, ix, itemData);
}
return true;
}
}
return false;
}
bool gdioutput::setItems(const string& id, const vector<pair<wstring, size_t>>& items) {
auto hash = ListBoxInfo::computeItemHash(items);
for (auto it = LBI.rbegin(); it != LBI.rend(); ++it) {
if (it->id == id) {
if (it->IsCombo) {
if (it->computed_hash == 0 || it->computed_hash != hash) {
SendMessage(it->hWnd, CB_RESETCONTENT, 0, 0);
SendMessage(it->hWnd, CB_INITSTORAGE, items.size(), 48);
SendMessage(it->hWnd, WM_SETREDRAW, FALSE, 0);
@ -1814,8 +1866,11 @@ bool gdioutput::addItem(const string& id, const vector< pair<wstring, size_t> >&
}
SendMessage(it->hWnd, WM_SETREDRAW, TRUE, 0);
RedrawWindow(it->hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
it->computed_hash = hash;
}
}
else {
if (it->computed_hash == 0 || it->computed_hash != hash) {
SendMessage(it->hWnd, LB_RESETCONTENT, 0, 0);
SendMessage(it->hWnd, LB_INITSTORAGE, items.size(), 48);
SendMessage(it->hWnd, WM_SETREDRAW, FALSE, 0);
@ -1829,6 +1884,8 @@ bool gdioutput::addItem(const string& id, const vector< pair<wstring, size_t> >&
SendMessage(it->hWnd, WM_SETREDRAW, TRUE, 0);
RedrawWindow(it->hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
it->computed_hash = hash;
}
}
return true;
}
@ -1843,6 +1900,7 @@ void gdioutput::filterOnData(const string &id, const unordered_set<int> &filter)
if (it->IsCombo) {
}
else {
it->computed_hash = 0;
const HWND &hWnd = it->hWnd;
LRESULT count = SendMessage(hWnd, LB_GETCOUNT, 0, 0);
for (intptr_t ix = count - 1; ix>=0; ix--) {
@ -1857,13 +1915,14 @@ void gdioutput::filterOnData(const string &id, const unordered_set<int> &filter)
assert(false);
}
bool gdioutput::clearList(const string &id)
{
list<ListBoxInfo>::iterator it;
for(it=LBI.begin(); it != LBI.end(); ++it){
bool gdioutput::clearList(const string& id) {
for (auto it = LBI.begin(); it != LBI.end(); ++it) {
if (it->id == id) {
it->original = L"";
it->originalIdx = -1;
it->computed_hash = 0;
it->data2Index.clear();
if (it->IsCombo)
SendMessage(it->hWnd, CB_RESETCONTENT, 0, 0);
else
@ -1908,6 +1967,17 @@ void ListBoxInfo::copyUserData(ListBoxInfo &dest) const {
dest.IsCombo = IsCombo;
}
uint64_t ListBoxInfo::computeItemHash(const vector<pair<wstring, size_t>>& items) {
uint64_t res = 1;
for (auto& it : items) {
res = res * 997 + it.second;
for (auto ch : it.first)
res = res * 2003 + ch;
}
return res;
}
bool gdioutput::getSelectedItem(ListBoxInfo &lbi) {
if (lbi.IsCombo) {
LRESULT index=SendMessage(lbi.hWnd, CB_GETCURSEL, 0, 0);
@ -2240,7 +2310,7 @@ void gdioutput::processButtonMessage(ButtonInfo &bi, WPARAM wParam)
if (bi.isCheckbox)
bi.checked = SendMessage(bi.hWnd, BM_GETCHECK, 0, 0)==BST_CHECKED;
bi.synchData();
if (bi.callBack || bi.handler) {
if (bi.callBack || bi.hasEventHandler()) {
setWaitCursor(true);
if (!bi.handleEvent(*this, GUI_BUTTON) && bi.callBack)
bi.callBack(this, GUI_BUTTON, &bi); //it may be destroyed here...
@ -3027,10 +3097,8 @@ void gdioutput::doEnter() {
HWND hWnd=GetFocus();
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it)
if (it->isDefaultButton() && (it->callBack || it->handler)) {
if (it->handler)
it->handleEvent(*this, GUI_BUTTON);
else
if (it->isDefaultButton()) {
if (!it->handleEvent(*this, GUI_BUTTON) && it->callBack)
it->callBack(this, GUI_BUTTON, &*it);
return;
}
@ -3038,13 +3106,11 @@ void gdioutput::doEnter() {
list<InputInfo>::iterator it;
for(it=II.begin(); it != II.end(); ++it)
if (it->hWnd==hWnd && (it->callBack || it->handler)){
if (it->hWnd==hWnd && (it->hasEventHandler() || it->callBack)){
TCHAR bf[1024];
GetWindowText(hWnd, bf, 1024);
it->text = bf;
if (it->handler)
it->handleEvent(*this, GUI_INPUT);
else
if (!it->handleEvent(*this, GUI_INPUT))
it->callBack(this, GUI_INPUT, &*it);
return;
}
@ -3139,10 +3205,8 @@ void gdioutput::doEscape()
tit->table->escape(*this);
for (list<ButtonInfo>::iterator it=BI.begin(); it!=BI.end(); ++it) {
if (it->isCancelButton() && (it->callBack || it->handler) ) {
if (it->handler)
it->handleEvent(*this, GUI_BUTTON);
else
if (it->isCancelButton() && (it->callBack || it->hasEventHandler()) ) {
if (!it->handleEvent(*this, GUI_BUTTON))
it->callBack(this, GUI_BUTTON, &*it);
return;
}
@ -3263,7 +3327,7 @@ void gdioutput::clearPage(bool autoRefresh, bool keepToolbar) {
try {
if (postClear)
postClear(this, GUI_POSTCLEAR, 0);
postClear->makeEvent(*this, GUI_POSTCLEAR);
}
catch (const meosCancel&) {
}
@ -3458,7 +3522,7 @@ BaseInfo *gdioutput::setTextZeroBlank(const char *id, int number, bool Update)
}
BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool Update, int requireExtraMatch)
BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool update, int requireExtraMatch, bool updateOriginal)
{
for (auto it = II.begin(); it != II.end(); ++it) {
if (it->id == id && it->matchExtra(requireExtraMatch)) {
@ -3468,6 +3532,7 @@ BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool Update, i
it->writeLock = oldWR;
it->text = text;
it->synchData();
if (updateOriginal)
it->original = text;
it->focusText = text;
return &*it;
@ -3478,6 +3543,7 @@ BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool Update, i
if (it->id == id && it->IsCombo && it->matchExtra(requireExtraMatch)) {
SetWindowText(it->hWnd, text.c_str());
it->text = text;
if (updateOriginal)
it->original = text;
return &*it;
}
@ -3503,7 +3569,7 @@ BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool Update, i
bool changed = updatePos(0, 0, it->textRect.right, it->textRect.bottom);
if (Update && hWndTarget) {
if (update && hWndTarget) {
if (changed)
InvalidateRect(hWndTarget, 0, true);
else
@ -3512,7 +3578,7 @@ BaseInfo *gdioutput::setText(const char *id, const wstring &text, bool Update, i
return &*it;
}
}
return 0;
return nullptr;
}
bool gdioutput::insertText(const string &id, const wstring &text)
@ -3523,7 +3589,7 @@ bool gdioutput::insertText(const string &id, const wstring &text)
SetWindowText(it->hWnd, text.c_str());
it->text = text;
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_INPUT);
else if (it->callBack)
it->callBack(this, GUI_INPUT, &*it);
@ -3651,7 +3717,6 @@ bool gdioutput::updatePosTight(int x, int y, int width, int height, int marginx,
bool gdioutput::updatePos(int x, int y, int width, int height) {
return updatePosTight(x, y, width, height, 0, 0);
}
void gdioutput::adjustDimension(int width, int height)
@ -4385,9 +4450,6 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC) {
h = ti.textRect.bottom - ti.textRect.top;
image.drawImage(imgId, Image::ImageMethod::Default, hDC, rc.left, rc.top, w, h);
//width = image.getWidth(imgId);
//height = image.getHeight(imgId);
}
}
if (!fixedRect) {
@ -4450,7 +4512,7 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC) {
memset(&rc, 0, sizeof(rc));
int width = scaleLength( (breakLines&ti.format) ? ti.xlimit : 450 );
rc.right = width;
int dx = (breakLines&ti.format) ? 0 : scaleLength(20);
int dx = format != 10 ? 0 : scaleLength(20);
ti.realWidth = width + dx;
DrawText(hDC, ti.text.c_str(), ti.text.length(), &rc, DT_CALCRECT|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
ti.textRect=rc;
@ -4459,7 +4521,7 @@ void gdioutput::RenderString(TextInfo &ti, HDC hDC) {
ti.textRect.top+=ti.yp;
ti.textRect.bottom+=ti.yp+dx;
if (ti.format == 10) {
if (format == 10) {
DWORD c = colorLightYellow;// GetSysColor(COLOR_INFOBK);
double red=GetRValue(c);
double green=GetGValue(c);
@ -4715,7 +4777,7 @@ void gdioutput::calcStringSize(TextInfo &ti, HDC hDC_in) const {
else {
memset(&rc, 0, sizeof(rc));
rc.right = scaleLength( (breakLines&ti.format) ? ti.xlimit : 450 );
int dx = (breakLines&ti.format) ? 0 : scaleLength(20);
int dx = format != 10 ? 0 : scaleLength(20);
ti.realWidth = rc.right + dx;
DrawText(hDC, ti.text.c_str(), ti.text.length(), &rc, DT_CALCRECT|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
ti.textRect=rc;
@ -4943,6 +5005,8 @@ wstring gdioutput::getTimerText(TextInfo *tit, DWORD T)
int t=abs(rt);
wchar_t bf[16];
if ((tit->format & time24HourClock) != 0 && t > 0)
t = t % (24 * timeConstSecPerHour);
if (tit->format & timeSeconds) {
if (tit->format & timeWithTenth)
@ -5431,30 +5495,75 @@ void gdioutput::restoreInternal(const RestoreInfo &ri)
}
}
void gdioutput::restore(const string &id, bool DoRefresh)
{
if (restorePoints.count(id)==0)
void gdioutput::restore(const string &restorePointId, bool doRefresh) {
auto rp = restorePoints.find(restorePointId);
if (rp == restorePoints.end())
return;
const RestoreInfo &ri=restorePoints[id];
const RestoreInfo& ri = rp->second;
restoreInternal(ri);
MaxX=ri.sMX;
MaxY=ri.sMY;
if (DoRefresh)
if (doRefresh)
refresh();
setOffset(ri.sOY, ri.sOY, false);
}
void gdioutput::restoreNoUpdate(const string &id)
{
if (restorePoints.count(id)==0)
RECT gdioutput::getDimensionSince(const string& restorePointId) const {
auto rp = restorePoints.find(restorePointId);
if (rp == restorePoints.end())
throw meosException("Internal error: " + restorePointId);
const RestoreInfo& ri = rp->second;
RECT out = {numeric_limits<int>::max(), numeric_limits<int>::max(), 0, 0};
auto grow = [&out](int x, int y, int w, int h) {
out.left = min<int>(out.left, x);
out.right = max<int>(out.right, x + w);
out.top = min<int>(out.top, y);
out.bottom = max<int>(out.bottom, y + h);
};
int lbiRemove = LBI.size() - ri.nLBI;
for (auto it = LBI.rbegin(); lbiRemove > 0; lbiRemove--, ++it) {
grow(it->getX(), it->getY(), it->getWidth(), it->getHeight());
}
int tlRemove = TL.size() - ri.nTL;
for (auto it = TL.rbegin(); tlRemove > 0; tlRemove--, ++it) {
grow(it->getX(), it->getY(), it->getWidth(), it->getHeight());
}
int biRemove = BI.size() - ri.nBI;
for (auto it = BI.rbegin(); biRemove > 0; biRemove--, ++it) {
int w, h;
it->getDimension(*this, w, h);
grow(it->getX(), it->getY(), w, h);
}
int iiRemove = II.size() - ri.nII;
for (auto it = II.rbegin(); iiRemove > 0; iiRemove--, ++it) {
grow(it->getX(), it->getY(), it->getWidth(), it->getHeight());
}
int rectRemove = Rectangles.size() - ri.nRect;
for (auto it = Rectangles.rbegin(); rectRemove > 0; rectRemove--, ++it) {
auto& rc = it->getRect();
grow(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
}
return out;
}
void gdioutput::restoreNoUpdate(const string &restorePointId) {
auto rp = restorePoints.find(restorePointId);
if (rp == restorePoints.end())
return;
const RestoreInfo &ri=restorePoints[id];
const RestoreInfo& ri = rp->second;
MaxX=ri.sMX;
MaxY=ri.sMY;
@ -5462,24 +5571,13 @@ void gdioutput::restoreNoUpdate(const string &id)
restoreInternal(ri);
}
void gdioutput::setPostClearCb(GUICALLBACK cb)
{
postClear=cb;
}
void gdioutput::setOnClearCb(GUICALLBACK cb)
{
onClear=cb;
}
bool gdioutput::canClear()
{
if (!onClear)
return true;
try {
return onClear(this, GUI_CLEAR, 0)!=0;
return onClear->makeEvent(*this, GUI_CLEAR)!=0;
}
catch (const meosCancel&) {
return false;
@ -5503,7 +5601,7 @@ int gdioutput::sendCtrlMessage(const string &id)
{
for (list<ButtonInfo>::iterator it=BI.begin(); it != BI.end(); ++it) {
if (id==it->id) {
if (it->handler)
if (it->hasEventHandler())
return it->handleEvent(*this, GUI_BUTTON);
else if (it->callBack)
return it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
@ -6065,6 +6163,7 @@ ToolInfo &gdioutput::updateToolTip(const string &id, const wstring &tip) {
for (ToolList::reverse_iterator it = toolTips.rbegin(); it != toolTips.rend(); ++it) {
if (it->name == id && hWndToolTip) {
it->tip = lang.tl(tip);
it->ti.lpszText = (LPWSTR)it->tip.c_str();
SendMessage(hWndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM) &it->ti);
return *it;
}
@ -6100,11 +6199,10 @@ Table &gdioutput::getTable() const {
return *const_cast<Table *>(Tables.back().table.get());
}
static int gdiTableCB(gdioutput *gdi, int type, void *data)
static int gdiTableCB(gdioutput *gdi, GuiEventType type, BaseInfo *data)
{
if (type == GUI_BUTTON) {
ButtonInfo bi = *static_cast<ButtonInfo *>(data);
//gdi->tableCB(bi, static_cast<Table *>(bi.getExtra()));
gdi->tableCB(bi, &gdi->getTable());
}
return 0;
@ -6112,8 +6210,6 @@ static int gdiTableCB(gdioutput *gdi, int type, void *data)
void gdioutput::tableCB(ButtonInfo &bu, Table *t)
{
#ifndef MEOSDB
if (bu.id=="tblPrint") {
t->keyCommand(*this, KC_PRINT);
}
@ -6212,8 +6308,6 @@ void gdioutput::tableCB(ButtonInfo &bu, Table *t)
else if (bu.id == "tblInsert") {
t->keyCommand(*this, KC_INSERT);
}
#endif
}
void gdioutput::enableTables()
@ -7084,7 +7178,7 @@ void gdioutput::copyToClipboard(const string &html, const wstring &txt) const {
}
else {
// HTML table to text
ostringstream result;
std::ostringstream result;
bool started = false;
bool newline = false;
bool dowrite = false;
@ -7201,11 +7295,11 @@ string gdioutput::dbPress(const string &id, int extra) {
if (it->isCheckbox) {
check(id, !isChecked(id));
}
else if(!it->callBack && !it->handler)
else if(!it->callBack && !it->hasEventHandler())
throw meosException("Button " + id + " is not active.");
wstring val = it->text;
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_BUTTON);
else if (it->callBack)
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
@ -7229,11 +7323,11 @@ string gdioutput::dbPress(const string &id, const char *extra) {
if (it->isCheckbox) {
check(id, !isChecked(id));
}
else if(!it->callBack && !it->handler)
else if(!it->callBack && !it->hasEventHandler())
throw meosException("Button " + id + " is not active.");
wstring val = it->text;
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_BUTTON);
else if (it->callBack)
it->callBack(this, GUI_BUTTON, &*it); //it may be destroyed here...
@ -7272,12 +7366,12 @@ string gdioutput::dbSelect(const string &id, int data) {
void gdioutput::internalSelect(ListBoxInfo &bi) {
bi.syncData();
if (bi.callBack || bi.handler) {
if (bi.callBack || bi.handler || bi.managedHandler) {
setWaitCursor(true);
hasCleared = false;
try {
bi.writeLock = true;
if (bi.handler)
if (bi.hasEventHandler())
bi.handleEvent(*this, GUI_LISTBOX);
else
bi.callBack(this, GUI_LISTBOX, &bi); //it may be destroyed here... Then hasCleared is set.
@ -7304,7 +7398,7 @@ void gdioutput::dbInput(const string &id, const string &text) {
SetWindowText(it->hWnd, widen(text).c_str());
it->text = widen(text);
it->data = -1;
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_COMBO);
else if (it->callBack)
it->callBack(this, GUI_COMBO, &*it); //it may be destroyed here...
@ -7319,7 +7413,7 @@ void gdioutput::dbInput(const string &id, const string &text) {
it->text = widen(text);
SetWindowText(it->hWnd, widen(text).c_str());
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_INPUT);
else if (it->callBack)
it->callBack(this, GUI_INPUT, &*it);
@ -7357,7 +7451,7 @@ void gdioutput::dbDblClick(const string &id, int data) {
if (!IsWindowEnabled(it->hWnd))
throw meosException("Selection " + id + " is not active.");
selectItemByData(id, data);
if (it->handler)
if (it->hasEventHandler())
it->handleEvent(*this, GUI_LISTBOXSELECT);
else if (it->callBack)
it->callBack(this, GUI_LISTBOXSELECT, &*it); //it may be destroyed here...

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -24,25 +24,14 @@
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GDIOUTPUT_H__396F60F8_679F_498A_B759_DF8F6F346A4A__INCLUDED_)
#define AFX_GDIOUTPUT_H__396F60F8_679F_498A_B759_DF8F6F346A4A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <set>
#include <map>
#include <vector>
#ifdef OLD
#include <hash_set>
#include <hash_map>
#else
#include <unordered_map>
#include <unordered_set>
#endif
#include <algorithm>
#include "subcommand.h"
@ -65,8 +54,6 @@ struct PageInfo;
struct RenderedPage;
class AnimationData;
typedef int (*GUICALLBACK)(gdioutput *gdi, int type, void *data);
enum GDICOLOR;
enum KeyCommandCode;
enum gdiFonts;
@ -81,13 +68,7 @@ constexpr int baseButtonWidth = 150;
constexpr int GDI_BUTTON_SPACING = 8;
typedef list<ToolInfo> ToolList;
/*
enum FontEncoding {
ANSI, Russian, EastEurope, Hebrew
};*/
/*
FontEncoding interpetEncoding(const string &enc);
*/
struct FontInfo {
const wstring *name;
HFONT normal;
@ -171,8 +152,8 @@ protected:
map<string, RestoreInfo> restorePoints;
GUICALLBACK onClear;
GUICALLBACK postClear;
shared_ptr<GuiEvent> onClear;
shared_ptr<GuiEvent> postClear;
list<InfoBox> IBox;
@ -365,8 +346,8 @@ public:
static const string& toUTF8(const wstring& input);
static const wstring& fromUTF8(const string& input);
//void setEncoding(FontEncoding encoding);
//FontEncoding getEncoding() const;
void updateTabFont();
void getFontInfo(const TextInfo& ti, FontInfo& fi) const;
@ -487,14 +468,32 @@ public:
int sendCtrlMessage(const string& id);
bool canClear();
void setOnClearCb(GUICALLBACK cb);
void setPostClearCb(GUICALLBACK cb);
void restore(const string& id = "", bool DoRefresh = true);
template<typename H>
void setPostClearCb(H cb) {
postClear = make_shared<GuiEvent>(cb);
}
template<typename H>
void setOnClearCb(H cb) {
onClear = make_shared<GuiEvent>(cb);
}
void clearPostClearCb() {
postClear.reset();
}
void clearOnClearCb() {
onClear.reset();
}
void restore(const string& restorePointId = "", bool doRefresh = true);
/// Restore, but do not update client area size,
/// position, zoom, scrollbars, and do not refresh
void restoreNoUpdate(const string& id);
void restoreNoUpdate(const string& restorePointId);
RECT getDimensionSince(const string& restorePointId) const;
void setRestorePoint();
void setRestorePoint(const string& id);
@ -644,7 +643,8 @@ public:
pair<int, bool> getSelectedItem(const char* id);
bool addItem(const string& id, const wstring& text, size_t data = 0);
bool addItem(const string& id, const vector< pair<wstring, size_t> >& items);
bool setItems(const string& id, const vector< pair<wstring, size_t> >& items);
bool modifyItemDescription(const string& id, size_t itemData, const wstring &description);
void filterOnData(const string& id, const unordered_set<int>& filter);
@ -687,7 +687,7 @@ public:
BaseInfo* setTextTranslate(const string& id, const wstring& text, bool update = false);
BaseInfo* setText(const char* id, const wstring& text, bool update = false, int requireExtraMatch = -1);
BaseInfo* setText(const char* id, const wstring& text, bool update = false, int requireExtraMatch = -1, bool updateOriginal = true);
BaseInfo* setText(const wchar_t* id, const wstring& text, bool update = false) {
return setText(narrow(id), text, update);
}
@ -728,7 +728,13 @@ public:
GUICALLBACK cb = nullptr, const wstring& tooltop = L"");
ButtonInfo& addButton(int x, int y, int w, const string& id, const wstring& text,
GUICALLBACK cb, const wstring& tooltop, bool absPos, bool hasState);
GUICALLBACK cb, const wstring& tooltip, bool absPos, bool hasState);
ButtonInfo& addButton(int x, int y, int width, int height,
const string& id, const wstring& text,
gdiFonts font, GUICALLBACK cb,
const wstring& tooltip,
bool absPos, bool hasState);
ButtonInfo& addCheckbox(const string& id, const wstring& text, GUICALLBACK cb = nullptr,
bool Checked = true, const wstring& tooltip = L"");
@ -838,4 +844,3 @@ public:
virtual ~gdioutput();
};
#endif // !defined(AFX_GDIOUTPUT_H__396F60F8_679F_498A_B759_DF8F6F346A4A__INCLUDED_)

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,15 +20,13 @@
************************************************************************/
#ifndef GDI_STRUCTURES
#define GDI_STRUCTURES
#pragma once
#include <cassert>
#include "guihandler.h"
#include "gdifonts.h"
class BaseInfo
{
class BaseInfo {
protected:
void *extra;
GuiHandler *handler;
@ -88,8 +86,33 @@ public:
}
};
class RestoreInfo : public BaseInfo
{
class GuiEvent final : public BaseInfo {
GUICALLBACK callback = nullptr;
public:
bool makeEvent(gdioutput &gdi, GuiEventType type) {
if (callback)
return callback(&gdi, type, this) != 0;
else
return handleEvent(gdi, type);
return true;
}
GuiEvent(GUICALLBACK callback) : callback(callback) {}
GuiEvent(const shared_ptr<GuiHandler> &h) {
setHandler(h);
}
GuiEvent(const GuiHandler *h) {
setHandler(h);
}
HWND getControlWindow() const final { throw std::exception("Unsupported"); }
};
class RestoreInfo final : public BaseInfo {
public:
int nLBI;
int nBI;
@ -109,8 +132,8 @@ public:
int nTooltip;
int nTables;
GUICALLBACK onClear;
GUICALLBACK postClear;
shared_ptr<GuiEvent> onClear;
shared_ptr<GuiEvent> postClear;
set<string> restorePoints;
@ -118,11 +141,10 @@ public:
return nLBI < r.nLBI || nBI < r.nBI || nII < r.nII || nTL < r.nTL || nRect < r.nRect || nData < r.nData;
}
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
};
class RectangleInfo : public BaseInfo
{
class RectangleInfo final : public BaseInfo {
private:
DWORD color;
DWORD color2;
@ -143,23 +165,20 @@ public:
RectangleInfo &changeDimension(gdioutput &gdi, int dx, int dy);
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
};
class TableInfo : public BaseInfo
{
class TableInfo final: public BaseInfo {
public:
TableInfo():xp(0), yp(0), table(0) {}
int xp;
int yp;
shared_ptr<Table> table;
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
};
class TextInfo : public BaseInfo
class TextInfo final: public BaseInfo
{
public:
@ -178,7 +197,11 @@ public:
bool isFormatInfo() const { return format == pageNewPage || format == pagePageInfo || format == pageNewChapter; }
int getHeight() {return int(textRect.bottom-textRect.top);}
int getHeight() const { return int(textRect.bottom - textRect.top); }
int getWidth() const { return realWidth; }
int getX() const { return xp; }
int getY() const { return yp; }
gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);}
// Sets absolute print coordinates in [mm]
TextInfo &setAbsPrintPos(int x, int y) {
@ -209,13 +232,12 @@ public:
bool active;
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
friend class gdioutput;
};
class ButtonInfo : public BaseInfo
{
class ButtonInfo final : public BaseInfo {
private:
bool originalState;
bool isEditControl;
@ -245,9 +267,11 @@ public:
ButtonInfo& setSynchData(bool* variable) { updateLastData = variable; return *this; }
int getX() const { return xp; }
int getY() const { return yp; }
void moveButton(gdioutput& gdi, int xp, int yp);
void getDimension(gdioutput &gdi, int &w, int &h);
void getDimension(const gdioutput& gdi, int& w, int& h) const;
ButtonInfo& setDefault();
ButtonInfo& setCancel() { flags |= 2, storedFlags |= 2; return *this; }
@ -255,12 +279,11 @@ public:
GUICALLBACK callBack;
friend class gdioutput;
HWND getControlWindow() const {return hWnd;}
HWND getControlWindow() const final { return hWnd; }
};
enum gdiFonts;
class InputInfo : public BaseInfo
{
class InputInfo final: public BaseInfo {
public:
InputInfo();
wstring text;
@ -278,13 +301,15 @@ public:
bool changedInput() const { return text != focusText; }
InputInfo &setPassword(bool pwd);
HWND getControlWindow() const {return hWnd;}
HWND getControlWindow() const final {return hWnd;}
InputInfo &setSynchData(wstring *variable) {updateLastData = variable; return *this;}
int getX() const {return xp;}
int getY() const {return yp;}
int getWidth() const {return int(width);}
int getHeight() const { return int(height); }
private:
HWND hWnd;
GUICALLBACK callBack;
@ -305,8 +330,7 @@ private:
friend class gdioutput;
};
class ListBoxInfo : public BaseInfo
{
class ListBoxInfo final : public BaseInfo {
public:
ListBoxInfo() : hWnd(0), callBack(0), IsCombo(false), index(-1),
writeLock(false), ignoreCheck(false), isEditControl(true),
@ -321,11 +345,12 @@ public:
bool changed() const { return text != original; }
void ignore(bool ig) { ignoreCheck = ig; }
ListBoxInfo& isEdit(bool e) { isEditControl = e; return *this; }
HWND getControlWindow() const {return hWnd;}
HWND getControlWindow() const final { return hWnd; }
void copyUserData(ListBoxInfo& userLBI) const;
ListBoxInfo& setSynchData(int* variable) { updateLastData = variable; return *this; }
int getWidth() const { return int(width); }
int getHeight() const { return int(height); }
int getX() const { return xp; }
int getY() const { return yp; }
bool isCombo() const { return IsCombo; }
@ -350,7 +375,10 @@ private:
size_t originalIdx;
bool ignoreCheck; // True if changed-state should be ignored
map<size_t, int> data2Index;
unordered_map<size_t, int> data2Index;
uint64_t computed_hash = 0;
static uint64_t computeItemHash(const vector<pair<wstring, size_t>>& items);
// Synchronize with other list box
WNDPROC originalProc;
@ -360,8 +388,7 @@ private:
friend class gdioutput;
};
class DataStore
{
class DataStore {
public:
DataStore() {
data = 0;
@ -371,8 +398,7 @@ public:
string sdata;
};
class EventInfo : public BaseInfo
{
class EventInfo final: public BaseInfo {
private:
string origin;
DWORD data;
@ -386,11 +412,10 @@ public:
EventInfo();
GUICALLBACK callBack;
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
};
class TimerInfo : public BaseInfo
{
class TimerInfo final : public BaseInfo {
private:
static int globalTimerId;
int timerId;
@ -419,12 +444,10 @@ public:
friend class gdioutput;
friend void CALLBACK gdiTimerProc(HWND hWnd, UINT a, UINT_PTR ptr, DWORD b);
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final { throw std::exception("Unsupported"); }
};
class InfoBox : public BaseInfo
{
class InfoBox final: public BaseInfo {
public:
InfoBox() : callBack(0), HasCapture(0), HasTCapture(0), TimeOut(0) {}
wstring text;
@ -439,7 +462,7 @@ public:
DWORD TimeOut;
HWND getControlWindow() const {throw std::exception("Unsupported");}
HWND getControlWindow() const final {throw std::exception("Unsupported");}
};
typedef list<TextInfo> TIList;
@ -450,6 +473,3 @@ struct ToolInfo {
wstring tip;
uintptr_t id;
};
#endif

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1007,6 +1007,12 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("InputNumber", "User input number", false);
parser.declareSymbol("Shorten", "Number of shortenings", false);
parser.declareSymbol("DataA", "Extra assigned data (A)", false);
parser.declareSymbol("DataB", "Extra assigned data (B)", false);
parser.declareSymbol("ClassDataA", "Extra assigned class data (A)", false);
parser.declareSymbol("ClassDataB", "Extra assigned class data (B)", false);
if (isRunner) {
parser.declareSymbol("CardPunches", "Runner's card, punch codes", true);
parser.declareSymbol("CardTimes", "Runner's card, punch times", true);
@ -1040,6 +1046,9 @@ void DynamicResult::declareSymbols(DynamicMethods m, bool clear) const {
parser.declareSymbol("RunnerCardTimes", "Punch times for each team member", true, true);
parser.declareSymbol("RunnerCardControls", "Matched control ids (-1 for unmatched) for each team member", true, true);
parser.declareSymbol("RunnerDataA", "Extra assigned data (A) for each team member", true);
parser.declareSymbol("RunnerDataB", "Extra assigned data (B) for each team member", true);
parser.declareSymbol("RunnerCourse", "Runner's course", true, true);
parser.declareSymbol("RunnerSplitTimes", "Runner's split times", true, true);
@ -1182,6 +1191,19 @@ void DynamicResult::prepareCommon(oAbstractRunner &runner, bool classResult) con
parser.addSymbol("InputPoints", runner.getInputPoints());
parser.addSymbol("Shorten", runner.getNumShortening());
parser.addSymbol("DataA", runner.getDCI().getInt("DataA"));
parser.addSymbol("DataB", runner.getDCI().getInt("DataB"));
pClass cls = runner.getClassRef(true);
if (cls) {
parser.addSymbol("ClassDataA", cls->getDCI().getInt("DataA"));
parser.addSymbol("ClassDataB", cls->getDCI().getInt("DataB"));
}
else {
parser.addSymbol("ClassDataA", 0);
parser.addSymbol("ClassDataB", 0);
}
vector<RunnerStatus> inst;
vector<int> times;
vector<int> points;
@ -1222,7 +1244,7 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
GeneralResult::prepareCalculations(team, classResult);
prepareCommon(team, classResult);
int nr = team.getNumRunners();
vector<int> status(nr), time(nr), start(nr), finish(nr), points(nr);
vector<int> status(nr), time(nr), start(nr), finish(nr), points(nr), dataA(nr), dataB(nr);
vector< vector<int> > runnerOutputTimes(nr);
vector< vector<int> > runnerOutputNumbers(nr);
@ -1243,6 +1265,8 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
runnerOutputTimes[k] = res.outputTimes;
runnerOutputNumbers[k] = res.outputNumbers;
dataA[k] = r->getDCI().getInt("DataA");
dataB[k] = r->getDCI().getInt("DataB");
}
}
parser.removeSymbol("CardControls");
@ -1270,6 +1294,9 @@ void DynamicResult::prepareCalculations(oTeam &team, bool classResult) const {
parser.addSymbol("RunnerFinish", finish);
parser.addSymbol("RunnerPoints", points);
parser.addSymbol("RunnerDataA", dataA);
parser.addSymbol("RunnerDataB", dataB);
parser.addSymbol("PatrolRogainingScore", team.getRogainingPatrolPoints(false));
parser.addSymbol("PatrolRogainingReduction", team.getRogainingPatrolReduction());
parser.addSymbol("PatrolRogainingOvertime", team.getRogainingPatrolOvertime());
@ -1416,7 +1443,7 @@ void DynamicResult::prepareCalculations(oRunner &runner, bool classResult) const
parser.addSymbol("AgeLowLimit", lowAgeLimit);
parser.addSymbol("AgeHighLimit", highAgeLimit);
parser.addSymbol("CheckTime", runner.getCheckTime());
parser.addSymbol("CheckTime", runner.getCheckTime() / timeConstSecond);
}
void DynamicResult::storeOutput(vector<int> &times, vector<int> &numbers) const {

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,8 +22,7 @@
************************************************************************/
#ifndef MEOS_GUI_HANDLER
#define MEOS_GUI_HANDLER
#pragma once
enum GuiEventType {GUI_BUTTON=1, GUI_INPUT=2, GUI_LISTBOX=3,
GUI_INFOBOX=4, GUI_CLEAR=5, GUI_INPUTCHANGE=6,
@ -34,6 +33,7 @@ enum GuiEventType {GUI_BUTTON=1, GUI_INPUT=2, GUI_LISTBOX=3,
class gdioutput;
class BaseInfo;
typedef int (*GUICALLBACK)(gdioutput* gdi, GuiEventType type, BaseInfo* data);
class GuiHandler {
public:
@ -41,5 +41,3 @@ public:
virtual ~GuiHandler() = 0 {}
virtual void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) = 0;
};
#endif

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -230,11 +230,11 @@ uint64_t Image::computeHash(const vector<uint8_t>& data) {
}
void Image::read_file(const wstring& filename, vector<uint8_t>& data) {
ifstream fin;
fin.open(filename, ios::binary);
fin.seekg(0, ios::end);
std::ifstream fin;
fin.open(filename, std::ios::binary);
fin.seekg(0, std::ios::end);
int p2 = (int)fin.tellg();
fin.seekg(0, ios::beg);
fin.seekg(0, std::ios::beg);
data.resize(p2);
fin.read((char*)data.data(), data.size());
fin.close();

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -99,7 +99,7 @@ wstring ImportFormats::getExtension(ExportFormats fm) {
case HTML:
return L"html";
}
throw exception();
throw std::exception();
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -35,6 +35,8 @@
#include "meosException.h"
#include "localizer.h"
using namespace std;
wstring &getFirst(wstring &inout, int maxNames);
wstring getMeosCompectVersion();
@ -2160,7 +2162,6 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
di.setInt("Paid", oe.interpretCurrency(paid, currency));
di.setInt("Taxable", oe.interpretCurrency(fee, currency));
// StartTimeAllocationRequest
xmlobject sar = xo.getObject("StartTimeAllocationRequest");
if (sar) {
@ -2171,7 +2172,7 @@ pRunner IOF30Interface::readPersonEntry(gdioutput &gdi, xmlobject &xo, pTeam tea
if (pRef) {
wstring sid;
pRef.getObjectString("Id", sid);
__int64 extId = oBase::converExtIdentifierString(sid);
int64_t extId = oBase::converExtIdentifierString(sid);
int pid = oBase::idFromExtId(extId);
pRunner rRef = oe.getRunner(pid, 0);
if (rRef && rRef->getExtIdentifier() == extId) {
@ -2417,17 +2418,20 @@ pRunner IOF30Interface::readPersonResult(gdioutput &gdi, pClass pc, xmlobject &x
wstring s;
for (auto &split : splits) {
int code = split.getObjectInt("ControlCode");
int time = split.getObjectInt("Time");
wstring out;
split.getObjectString("Time", out);
double t = _wtof(out.c_str());
int time = int(t * timeConstSecond);
split.getObjectString("status", s);
if (s != L"missing")
card->addPunch(code, st + time, 0, 0);
card->addPunch(code, st + time, 0, 0, oCard::PunchOrigin::Original);
if (s != L"additional")
controls.push_back(code);
}
if (ft > 0)
card->addPunch(oPunch::PunchFinish, ft, 0, 0);
card->addPunch(oPunch::PunchFinish, ft, 0, 0, oCard::PunchOrigin::Original);
//Update to SQL-source
card->synchronize();
@ -2461,25 +2465,35 @@ pRunner IOF30Interface::readPersonResult(gdioutput &gdi, pClass pc, xmlobject &x
return r;
}
void IOF30Interface::readId(const xmlobject &person, int &pid, __int64 &extId) const {
void IOF30Interface::readId(const xmlobject &person, int &pid, int64_t& extId, int64_t& extId2) const {
wstring sid;
pid = 0;
extId = 0;
if (preferredIdProvider.empty()) {
extId2 = 0;
if (preferredIdProvider.first.empty()) {
person.getObjectString("Id", sid);
}
else {
xmlList sids;
wstring bsid;
wstring bsid, sid2;
person.getObjects("Id", sids);
for (auto &x : sids) {
auto type = x.getAttrib("type");
if (type && type.getPtr() == preferredIdProvider) {
if (type && type.getPtr() == preferredIdProvider.first) {
sid = x.getWStr();
}
else if (type && type.getPtr() == preferredIdProvider.second) {
sid2 = x.getWStr();
if (!sid2.empty())
bsid = sid2;
}
else if (bsid.empty())
bsid = x.getWStr();
}
if (!sid2.empty())
extId2 = oBase::converExtIdentifierString(sid2);
if (sid.empty())
pid = oBase::idFromExtId(oBase::converExtIdentifierString(bsid));
}
@ -2504,34 +2518,8 @@ pRunner IOF30Interface::readPerson(gdioutput &gdi, const xmlobject &person) {
name = lang.tl("N.N.");
}
int pid = 0;
__int64 extId = 0;
readId(person, pid, extId);
/*
wstring sid;
int pid = 0;
__int64 extId = 0;
if (preferredIdProvider.empty()) {
person.getObjectString("Id", sid);
}
else {
xmlList sids;
wstring bsid;
person.getObjects("Id", sids);
for (auto &x : sids) {
auto type = x.getAttrib("type");
if (type && type.get() == preferredIdProvider) {
sid = x.getw();
}
else if (bsid.empty())
bsid = x.getw();
}
if (sid.empty())
pid = oBase::idFromExtId(oBase::converExtIdentifierString(bsid));
}
if (!sid.empty()) {
extId = oBase::converExtIdentifierString(sid);
pid = oBase::idFromExtId(extId);
}*/
int64_t extId = 0, extId2 = 0;
readId(person, pid, extId, extId2);
pRunner r = 0;
if (pid) {
@ -2580,6 +2568,8 @@ pRunner IOF30Interface::readPerson(gdioutput &gdi, const xmlobject &person) {
}
r->setExtIdentifier(extId);
if (extId2 != 0)
r->setExtIdentifier2(extId2);
oDataInterface DI=r->getDI();
wstring tmp;
@ -2602,7 +2592,7 @@ pClub IOF30Interface::readOrganization(gdioutput &gdi, const xmlobject &xclub, b
return 0;
wstring clubIdS;
xclub.getObjectString("Id", clubIdS);
__int64 extId = oBase::converExtIdentifierString(clubIdS);
int64_t extId = oBase::converExtIdentifierString(clubIdS);
int clubId = oBase::idFromExtId(extId);
wstring name, shortName;
xclub.getObjectString("Name", name);
@ -2870,7 +2860,7 @@ void IOF30Interface::getAgeLevels(const vector<FeeInfo> &fees, const vector<int>
int getAgeFromDate(const wstring &date) {
int y = getThisYear();
SYSTEMTIME st;
convertDateYMS(date, st, false);
convertDateYMD(date, st, false);
if (st.wYear > 1900)
return y - st.wYear;
else
@ -2887,8 +2877,8 @@ void IOF30Interface::FeeInfo::add(IOF30Interface::FeeInfo &fi) {
fi.toTime = fromTime;
if (!fi.toTime.empty()) {
SYSTEMTIME st;
convertDateYMS(fi.toTime, st, false);
__int64 sec = SystemTimeToInt64TenthSecond(st);
convertDateYMD(fi.toTime, st, false);
int64_t sec = SystemTimeToInt64TenthSecond(st);
sec -= timeConstHour;
fi.toTime = convertSystemDate(Int64TenthSecondToSystemTime(sec));
}
@ -3183,7 +3173,7 @@ void IOF30Interface::getLocalDateTime(const string &date, const string &time,
memset(&st, 0, sizeof(SYSTEMTIME));
int atime = convertAbsoluteTimeISO(wTime);
int idate = convertDateYMS(date, st, true);
int idate = convertDateYMD(date, st, true);
if (idate != -1) {
if (zone == "Z" || zone == "z") {
st.wHour = atime / timeConstHour;
@ -3246,7 +3236,7 @@ void IOF30Interface::getLocalDateTime(const wstring &date, const wstring &time,
memset(&st, 0, sizeof(SYSTEMTIME));
const int atime = convertAbsoluteTimeISO(wTime);
int idate = convertDateYMS(date, st, true);
int idate = convertDateYMD(date, st, true);
if (idate != -1) {
if (zone == L"Z" || zone == L"z") {
st.wHour = atime / timeConstHour;
@ -3665,7 +3655,7 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
}
void IOF30Interface::writeFees(xmlparser &xml, const oRunner &r) const {
int cardFee = max(0, r.getDCI().getInt("CardFee"));
int cardFee = r.getRentalCardFee(false);
bool paidCard = r.getDCI().getInt("Paid") >= cardFee;
writeAssignedFee(xml, r, paidCard ? cardFee : 0);
@ -3777,10 +3767,25 @@ void IOF30Interface::writeEvent(xmlparser &xml) {
void IOF30Interface::writePerson(xmlparser &xml, const oRunner &r) {
xml.startTag("Person");
if (externalIdTypes.empty()) {
if (r.getExtIdentifier() != 0)
xml.write("Id", r.getExtIdentifierString());
else if (r.getMainRunner()->getExtIdentifier() != 0)
xml.write("Id", r.getMainRunner()->getExtIdentifierString());
}
else if (!externalIdTypes[0].empty()) {
if (r.getExtIdentifier() != 0)
xml.write("Id", externalIdTypes[0], r.getExtIdentifierString());
else if (r.getMainRunner()->getExtIdentifier() != 0)
xml.write("Id", externalIdTypes[0], r.getMainRunner()->getExtIdentifierString());
}
if (externalIdTypes.size()>1 && !externalIdTypes[1].empty()) {
if (r.getExtIdentifier2() != 0)
xml.write("Id", externalIdTypes[1], r.getExtIdentifierString2());
else if (r.getMainRunner()->getExtIdentifier2() != 0)
xml.write("Id", externalIdTypes[1], r.getMainRunner()->getExtIdentifierString2());
}
xml.startTag("Name");
xml.write("Family", r.getFamilyName());
@ -3804,7 +3809,7 @@ void IOF30Interface::writeClub(xmlparser &xml, const oClub &c, bool writeExtende
else {
xml.startTag("Organisation");
}
__int64 id = c.getExtIdentifier();
int64_t id = c.getExtIdentifier();
if (id != 0)
xml.write("Id", c.getExtIdentifierString());
@ -4143,8 +4148,9 @@ bool IOF30Interface::readXMLCompetitorDB(const xmlobject &xCompetitor,
if (!person) return false;
int pidI;
long long pid;
readId(person, pidI, pid);
int64_t pid;
int64_t ext2; // Ignored
readId(person, pidI, pid, ext2);
xmlobject pname = person.getObject("Name");
if (!pname) return false;
@ -4693,6 +4699,19 @@ void IOF30Interface::getIdTypes(vector<string> &types) {
types.insert(types.begin(), idProviders.begin(), idProviders.end());
}
void IOF30Interface::setPreferredIdType(const string &type) {
void IOF30Interface::setPreferredIdType(const pair<string, string> &type) {
preferredIdProvider = type;
externalIdTypes.clear();
if (!type.first.empty() || !type.second.empty()) {
string stype = "type";
if (!type.first.empty())
externalIdTypes.emplace_back(vector<pair<string, wstring>>({
make_pair(stype, gdioutput::widen(type.first)) }));
else
externalIdTypes.emplace_back();
if (!type.second.empty())
externalIdTypes.emplace_back(vector<pair<string, wstring>>({
make_pair(stype, gdioutput::widen(type.second)) }));
}
}

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -155,7 +155,8 @@ class IOF30Interface {
bool matchStageFilter(const set<int> &stageFilter, const xmlList &races);
set<string> idProviders;
string preferredIdProvider;
pair<string, string> preferredIdProvider;
vector<vector<pair<string, wstring>>> externalIdTypes;
void readEvent(gdioutput &gdi, const xmlobject &xo,
map<int, vector<LegInfo> > &teamClassConfig);
@ -259,7 +260,7 @@ class IOF30Interface {
bool readXMLCompetitorDB(const xmlobject &xCompetitor,
bool onlyWithClub,
unordered_multimap<size_t, int> &duplicateCheck,
std::unordered_multimap<size_t, int> &duplicateCheck,
int &duplicateCount);
void writeXMLCompetitorDB(xmlparser &xml, const RunnerDB &db, const RunnerWDBEntry &rde) const;
@ -297,7 +298,7 @@ class IOF30Interface {
void writeFullCourse(xmlparser &xml, const oCourse &c,
const map<int, wstring> &ctrlId2ExportId);
void readId(const xmlobject &person, int &pid, __int64 &extId) const;
void readId(const xmlobject &person, int &pid, int64_t &extId, int64_t& extId2) const;
set<int> readCrsIds;
@ -322,7 +323,7 @@ public:
string &dateOut, string &timeOut);
void getIdTypes(vector<string> &types);
void setPreferredIdType(const string &type);
void setPreferredIdType(const pair<string, string>&type);
void readEventList(gdioutput &gdi, xmlobject &xo);

Binary file not shown.

BIN
code/lib64_db/RestBed.lib Normal file

Binary file not shown.

BIN
code/lib64_db/libharu.lib Normal file

Binary file not shown.

BIN
code/lib64_db/libmysql.lib Normal file

Binary file not shown.

BIN
code/lib64_db/libpng.lib Normal file

Binary file not shown.

BIN
code/lib64_db/zlibstat.lib Normal file

Binary file not shown.

Binary file not shown.

View File

@ -7,7 +7,7 @@ Third Party Code. Additional copyright notices and license terms applicable to p
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
------------------------------------
Copyright 2007-2023 Melin Software HB.
Copyright 2007-2024 Melin Software HB.
------------------------------------

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -99,7 +99,7 @@ void ListEditor::show(TabBase *dst, gdioutput &gdi) {
show(gdi);
}
int editListCB(gdioutput* gdi, int type, void* data);
int editListCB(gdioutput* gdi, GuiEventType type, BaseInfo* data);
void ListEditor::show(gdioutput &gdi) {
@ -319,8 +319,7 @@ void ListEditor::renderListPreview(gdioutput &gdi) {
}
}
int editListCB(gdioutput *gdi, int type, void *data)
{
int editListCB(gdioutput *gdi, GuiEventType type, BaseInfo* data) {
void *clz = gdi->getData("ListEditorClz");
ListEditor *le = (ListEditor *)clz;
BaseInfo *bi = (BaseInfo *)data;
@ -393,7 +392,7 @@ static void getPosFromId(int id, int &groupIx, int &lineIx, int &ix) {
lineIx = lineIx % 100;
}
int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
int ListEditor::editList(gdioutput &gdi, GuiEventType type, BaseInfo &data) {
int lineIx, groupIx, ix;
if (type == GUI_EVENT) {
@ -778,7 +777,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
gdi.fillRight();
gdi.addSelection("OpenList", 250, 400, editListCB, L"Välj lista:");
gdi.addItem("OpenList", lists);
gdi.setItems("OpenList", lists);
gdi.selectFirstItem("OpenList");
@ -907,7 +906,7 @@ int ListEditor::editList(gdioutput &gdi, int type, BaseInfo &data) {
gdi.getSelectedItem("SortOrder", mlbi);
currentType = mlbi.data;
}
gdi.addItem("SortOrder", types);
gdi.setItems("SortOrder", types);
gdi.selectItemByData("SortOrder", currentType);
}
else if (lbi.id == "OpenList") {
@ -1170,7 +1169,7 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
gdi.fillRight();
gdi.addSelection("Type", 290, 500, editListCB);
gdi.dropLine(-1);
gdi.addItem("Type", types);
gdi.setItems("Type", types);
gdi.selectItemByData("Type", currentType);
gdi.addInput("Text", mlp.getText(), 16, editListCB,
L"Egen text:", L"Använd symbolen X där MeOS ska fylla i typens data.");
@ -1205,7 +1204,7 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
currentList->getAlignTypes(mlp, types, currentType);
sort(types.begin(), types.end());
gdi.addSelection("AlignType", 290, 500, editListCB, L"Justera mot:");
gdi.addItem("AlignType", types);
gdi.setItems("AlignType", types);
gdi.selectItemByData("AlignType", currentType);
gdi.addInput("AlignText", mlp.getAlignText(), 16, 0, L"Text:");
@ -1259,7 +1258,7 @@ void ListEditor::editListPost(gdioutput &gdi, const MetaListPost &mlp, int id) {
mlp.getFonts(fonts, currentFont);
gdi.addSelection("Fonts", 200, 500, 0, L"Format:");
gdi.addItem("Fonts", fonts);
gdi.setItems("Fonts", fonts);
gdi.selectItemByData("Fonts", currentFont);
maxX = max(maxX, gdi.getCX());
@ -1473,7 +1472,7 @@ int ListEditor::selectImage(gdioutput &gdi, uint64_t imgId) {
vector<pair<wstring, size_t>> img;
image.enumerateImages(img);
img.emplace(img.begin(), lang.tl("Ingen[bild]"), -2);
gdi.addItem("Image", img);
gdi.setItems("Image", img);
int ix = image.getEnumerationIxFromId(imgId);
if (ix >= 0)
@ -1665,7 +1664,7 @@ bool ListEditor::legStageTypeIndex(gdioutput &gdi, EPostType type, int leg) {
for (int j = 1; j <= 50; j++) {
items.emplace_back(lang.tl("Sträcka X#" + itos(j)), j);
}
gdi.addItem("LegSel", items);
gdi.setItems("LegSel", items);
if (leg >= -1)
gdi.selectItemByData("LegSel", leg + 1);
else if (leg == -2)
@ -1676,7 +1675,7 @@ bool ListEditor::legStageTypeIndex(gdioutput &gdi, EPostType type, int leg) {
for (int j = 1; j < 20; j++) {
items.emplace_back(lang.tl("Etapp X#" + itos(j)), j);
}
gdi.addItem("LegSel", items);
gdi.setItems("LegSel", items);
gdi.selectItemByData("LegSel", leg >= 0 ? leg + 1 : -2);
}
}
@ -1754,26 +1753,26 @@ void ListEditor::editListProp(gdioutput &gdi, bool newList) {
list.getBaseType(types, currentType);
gdi.addSelection("BaseType", 150, 400, 0, L"Listtyp:");
gdi.addItem("BaseType", types);
gdi.setItems("BaseType", types);
gdi.selectItemByData("BaseType", currentType);
gdi.autoGrow("BaseType");
list.getResultModule(*oe, types, currentType);
gdi.addSelection("ResultType", 150, 400, editListCB, L"Resultatuträkning:");
gdi.addItem("ResultType", types);
gdi.setItems("ResultType", types);
gdi.autoGrow("ResultType");
gdi.selectItemByData("ResultType", currentType);
list.getSortOrder(false, types, currentType);
gdi.addSelection("SortOrder", 170, 400, 0, L"Global sorteringsordning:");
gdi.addItem("SortOrder", types);
gdi.setItems("SortOrder", types);
gdi.autoGrow("SortOrder");
gdi.selectItemByData("SortOrder", currentType);
list.getSubType(types, currentType);
gdi.addSelection("SubType", 150, 400, editListCB, L"Sekundär typ:");
gdi.addItem("SubType", types);
gdi.setItems("SubType", types);
gdi.selectItemByData("SubType", currentType);
oListInfo::EBaseType subType = oListInfo::EBaseType(currentType);
@ -1849,7 +1848,7 @@ void ListEditor::editListProp(gdioutput &gdi, bool newList) {
for (int k = 0; k < 4; k++) {
string id("Font" + itos(k));
gdi.addCombo(id, 200, 300, 0, expl[k]);
gdi.addItem(id, fonts);
gdi.setItems(id, fonts);
gdi.setText(id, list.getFontFace(k));
gdi.setCX(gdi.getCX()+20);
@ -1961,7 +1960,7 @@ void ListEditor::splitPrintList(gdioutput& gdi) {
for (int i = 60; i <= 100; i += 10)
items.emplace_back(itow(i), i);
items.emplace_back(lang.tl("Alla"), 1000);
gdi.addItem("NumResult", items);
gdi.setItems("NumResult", items);
gdi.selectItemByData("NumResult", isSP ? sp->numClassResults : 3);
statusSplitPrint(gdi, isSP);

View File

@ -2,7 +2,7 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2023 Melin Software HB
Copyright (C) 2009-2024 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -51,7 +51,7 @@ private:
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);
int editList(gdioutput &gdi, GuiEventType type, BaseInfo &data);
void updateType(int iType, gdioutput &gdi);
bool saveListPost(gdioutput &gdi, MetaListPost &mlp);
@ -118,5 +118,5 @@ public:
MetaList *getCurrentList() const {return currentList;};
void handleAutoComplete(gdioutput &gdi, AutoCompleteInfo &info) final;
friend int editListCB(gdioutput*, int, void *);
friend int editListCB(gdioutput*, GuiEventType type, BaseInfo* data);
};

BIN
code/lists24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

Some files were not shown because too many files have changed in this diff Show More