diff --git a/libquickevent/libquickeventgui/libquickeventgui-cs_CZ.ts b/libquickevent/libquickeventgui/libquickeventgui-cs_CZ.ts index b247e5efd..748bc99f7 100644 --- a/libquickevent/libquickeventgui/libquickeventgui-cs_CZ.ts +++ b/libquickevent/libquickeventgui/libquickeventgui-cs_CZ.ts @@ -109,6 +109,21 @@ Print vacants Tisknout vakanty + + + Only runners + Pouze závodníci + + + + Include vacants with time + Včetně vakantů s časem + + + + Include all vacants + Včetně všech vakantů + Print start numbers @@ -172,7 +187,7 @@ Use only class from selected start - Pooužít pouze kategorie z vybraného startu + Použít pouze kategorie z vybraného startu diff --git a/libquickevent/libquickeventgui/src/reportoptionsdialog.cpp b/libquickevent/libquickeventgui/src/reportoptionsdialog.cpp index 0c1ed71c8..55dbc47df 100644 --- a/libquickevent/libquickeventgui/src/reportoptionsdialog.cpp +++ b/libquickevent/libquickeventgui/src/reportoptionsdialog.cpp @@ -54,7 +54,7 @@ ReportOptionsDialog::ReportOptionsDialog(QWidget *parent) connect(this, &ReportOptionsDialog::startListOptionsVisibleChanged, ui->grpStartOptions, &QGroupBox::setVisible); connect(this, &ReportOptionsDialog::classFilterVisibleChanged, ui->grpClassFilter, &QGroupBox::setVisible); connect(this, &ReportOptionsDialog::startersOptionsVisibleChanged, ui->grpStartersOptions, &QGroupBox::setVisible); - connect(this, &ReportOptionsDialog::vacantsVisibleChanged, ui->chkStartOpts_PrintVacants, &QCheckBox::setVisible); + connect(this, &ReportOptionsDialog::vacantsVisibleChanged, ui->cbxStartOpts_PrintVacants, &QComboBox::setVisible); connect(this, &ReportOptionsDialog::stagesOptionVisibleChanged, ui->grpStages, &QGroupBox::setVisible); connect(this, &ReportOptionsDialog::legsOptionVisibleChanged, ui->grpLegs, &QGroupBox::setVisible); connect(this, &ReportOptionsDialog::pageLayoutVisibleChanged, ui->grpPageLayout, &QGroupBox::setVisible); @@ -117,9 +117,11 @@ ReportOptionsDialog::BreakType ReportOptionsDialog::breakType() const return static_cast(ui->cbxBreakAfterClassType->currentIndex()); } -bool ReportOptionsDialog::isStartListPrintVacants() const +ReportOptionsDialog::VacantsOption ReportOptionsDialog::startListPrintVacantsOption() const { - return ui->chkStartOpts_PrintVacants->isChecked(); + int ix = ui->cbxStartOpts_PrintVacants->currentIndex(); + if (ix < 0) ix = 0; + return static_cast(ix); } bool ReportOptionsDialog::isStartListPrintStartNumbers() const @@ -207,8 +209,8 @@ int ReportOptionsDialog::exec() void ReportOptionsDialog::setStartListPrintVacantsVisible(bool b) { if(!b) - ui->chkStartOpts_PrintVacants->setChecked(b); - ui->chkStartOpts_PrintVacants->setVisible(b); + ui->cbxStartOpts_PrintVacants->setCurrentIndex(0); + ui->cbxStartOpts_PrintVacants->setVisible(b); } void ReportOptionsDialog::setOptions(const ReportOptionsDialog::Options &options) @@ -232,7 +234,7 @@ void ReportOptionsDialog::setOptions(const ReportOptionsDialog::Options &options ui->btClassNames->setChecked(filter_type == FilterType::ClassName); auto index = ui->cbxStartNumber->findData(options.startNumber()); ui->cbxStartNumber->setCurrentIndex(index); - ui->chkStartOpts_PrintVacants->setChecked(options.isStartListPrintVacants()); + ui->cbxStartOpts_PrintVacants->setCurrentIndex(options.startListPrintVacantsOption()); ui->chkStartOpts_PrintStartNumbers->setChecked(options.isStartListPrintStartNumbers()); ui->edStartersOptionsLineSpacing->setValue(options.startersOptionsLineSpacing()); ui->edNumPlaces->setValue(options.resultNumPlaces()); @@ -268,7 +270,7 @@ ReportOptionsDialog::Options ReportOptionsDialog::options() const opts.setStartNumber(ui->cbxStartNumber->currentData().toInt()); FilterType filter_type = ui->btWildCard->isChecked()? FilterType::WildCard: ui->btRegExp->isChecked()? FilterType::RegExp: FilterType::ClassName; opts.setClassFilterType((int)filter_type); - opts.setStartListPrintVacants(isStartListPrintVacants()); + opts.setStartListPrintVacantsOption((int)startListPrintVacantsOption()); opts.setStartListPrintStartNumbers(isStartListPrintStartNumbers()); opts.setStartersOptionsLineSpacing(ui->edStartersOptionsLineSpacing->value()); opts[QStringLiteral("isBreakAfterEachClass")] = isBreakAfterEachClass(); @@ -379,7 +381,7 @@ void ReportOptionsDialog::setStartListForRelays() void ReportOptionsDialog::setCurrentStageId(int stageId) { ui->cbxStartNumber->clear(); - ui->cbxStartNumber->addItem(QString("All"), 0); + ui->cbxStartNumber->addItem(tr("All"), 0); QString query_str; if (stageId > 0) { query_str = QString("SELECT DISTINCT codes.code FROM codes, coursecodes, classdefs" @@ -394,7 +396,7 @@ void ReportOptionsDialog::setCurrentStageId(int stageId) while (q.next()) { auto code = q.value(0).toInt(); if(auto n = core::CodeDef::codeToStartNumber(code); n.has_value()) { - ui->cbxStartNumber->addItem(QString("Start %1").arg(n.value()), n.value()); + ui->cbxStartNumber->addItem(tr("Start %1").arg(n.value()), n.value()); } } } diff --git a/libquickevent/libquickeventgui/src/reportoptionsdialog.h b/libquickevent/libquickeventgui/src/reportoptionsdialog.h index 0780f1db1..e25ef7ee2 100644 --- a/libquickevent/libquickeventgui/src/reportoptionsdialog.h +++ b/libquickevent/libquickeventgui/src/reportoptionsdialog.h @@ -54,6 +54,7 @@ class QUICKEVENTGUI_DECL_EXPORT ReportOptionsDialog : public QDialog, public qf: enum class FilterType : int {WildCard = 0, RegExp, ClassName}; enum class StartTimeFormat : int {RelativeToClassStart = 0, DayTime}; enum class StartlistOrderFirstBy : int { ClassName = 0, StartTime, Names }; + enum class VacantsOption : int { OnlyRunners = 0, RegularVacants = 1, AllVacants = 2 }; class Options : public QVariantMap { @@ -69,7 +70,7 @@ class QUICKEVENTGUI_DECL_EXPORT ReportOptionsDialog : public QDialog, public qf: QF_VARIANTMAP_FIELD2(int, c, setC, lassFilterType, 0) QF_VARIANTMAP_FIELD(bool, is, set, UseClassFilter) QF_VARIANTMAP_FIELD(bool, is, set, InvertClassFilter) - QF_VARIANTMAP_FIELD(bool, is, set, StartListPrintVacants) + QF_VARIANTMAP_FIELD2(int, s, setS, tartListPrintVacantsOption, 0) QF_VARIANTMAP_FIELD(bool, is, set, StartListPrintStartNumbers) QF_VARIANTMAP_FIELD2(int, s, setS, tagesCount, 1) QF_VARIANTMAP_FIELD2(int, l, setL, egsCount, 1) @@ -119,7 +120,7 @@ class QUICKEVENTGUI_DECL_EXPORT ReportOptionsDialog : public QDialog, public qf: StartTimeFormat startTimeFormat() const; StartlistOrderFirstBy startlistOrderFirstBy() const; BreakType breakType() const; - Q_INVOKABLE bool isStartListPrintVacants() const; + Q_INVOKABLE VacantsOption startListPrintVacantsOption() const; Q_INVOKABLE bool isStartListPrintStartNumbers() const; Q_INVOKABLE bool isBreakAfterEachClass() const {return breakType() != BreakType::None;} Q_INVOKABLE bool isColumnBreak() const {return breakType() == BreakType::Column;} diff --git a/libquickevent/libquickeventgui/src/reportoptionsdialog.ui b/libquickevent/libquickeventgui/src/reportoptionsdialog.ui index b8b94c412..adf57d9d1 100644 --- a/libquickevent/libquickeventgui/src/reportoptionsdialog.ui +++ b/libquickevent/libquickeventgui/src/reportoptionsdialog.ui @@ -349,10 +349,22 @@ 5 - - - Print vacants - + + + + Only runners + + + + + Include vacants with time + + + + + Include all vacants + + @@ -567,7 +579,7 @@ chkExcludeDisq edStartersOptionsLineSpacing cbxStartNumber - chkStartOpts_PrintVacants + cbxStartOpts_PrintVacants chkStartOpts_PrintStartNumbers btStartTimes1 btStartTimes2 diff --git a/quickevent/app/quickevent/plugins/Event/src/services/emmaclient.cpp b/quickevent/app/quickevent/plugins/Event/src/services/emmaclient.cpp index 06819359e..308cba100 100644 --- a/quickevent/app/quickevent/plugins/Event/src/services/emmaclient.cpp +++ b/quickevent/app/quickevent/plugins/Event/src/services/emmaclient.cpp @@ -217,7 +217,7 @@ void EmmaClient::exportStartListIofXml3() QString str = is_relays ? getPlugin()->startListIofXml30() - : getPlugin()->startListStageIofXml30(current_stage, false); + : getPlugin()->startListStageIofXml30(current_stage, quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners); QFile f(file_name); if(f.open(QFile::WriteOnly)) { diff --git a/quickevent/app/quickevent/plugins/Event/src/services/ofeed/ofeedclient.cpp b/quickevent/app/quickevent/plugins/Event/src/services/ofeed/ofeedclient.cpp index 667b37943..1be9a08d0 100644 --- a/quickevent/app/quickevent/plugins/Event/src/services/ofeed/ofeedclient.cpp +++ b/quickevent/app/quickevent/plugins/Event/src/services/ofeed/ofeedclient.cpp @@ -163,7 +163,7 @@ void OFeedClient::exportStartListIofXml3(std::function on_success) QString str = is_relays ? getPlugin()->startListIofXml30() - : getPlugin()->startListStageIofXml30(current_stage, false); + : getPlugin()->startListStageIofXml30(current_stage, quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners); sendFile(tr("start list upload"), "/rest/v1/upload/iof", str, on_success); } diff --git a/quickevent/app/quickevent/plugins/Event/src/services/oresultsclient.cpp b/quickevent/app/quickevent/plugins/Event/src/services/oresultsclient.cpp index af54621c3..61c99f7fb 100644 --- a/quickevent/app/quickevent/plugins/Event/src/services/oresultsclient.cpp +++ b/quickevent/app/quickevent/plugins/Event/src/services/oresultsclient.cpp @@ -76,7 +76,7 @@ void OResultsClient::exportStartListIofXml3(std::function on_success) QString str = is_relays ? getPlugin()->startListIofXml30() - : getPlugin()->startListStageIofXml30(current_stage, false); + : getPlugin()->startListStageIofXml30(current_stage, quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners); sendFile("start list upload", "/start-lists", str, on_success); } diff --git a/quickevent/app/quickevent/plugins/Event/src/services/qx/qxclientservice.cpp b/quickevent/app/quickevent/plugins/Event/src/services/qx/qxclientservice.cpp index 502483522..e80607c83 100644 --- a/quickevent/app/quickevent/plugins/Event/src/services/qx/qxclientservice.cpp +++ b/quickevent/app/quickevent/plugins/Event/src/services/qx/qxclientservice.cpp @@ -203,7 +203,7 @@ void QxClientService::postStartListIofXml3(QObject *context, std::functioncurrentStageId(); bool is_relays = ep->eventConfig()->isRelays(); if (!is_relays) { - auto xml = getPlugin()->startListStageIofXml30(current_stage, false); + auto xml = getPlugin()->startListStageIofXml30(current_stage, quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners); uploadSpecFile(SpecFile::StartListIofXml3, xml.toUtf8(), context, call_back); } } diff --git a/quickevent/app/quickevent/plugins/Relays/src/relayswidget.cpp b/quickevent/app/quickevent/plugins/Relays/src/relayswidget.cpp index 02cfe3ffa..f128fb23e 100644 --- a/quickevent/app/quickevent/plugins/Relays/src/relayswidget.cpp +++ b/quickevent/app/quickevent/plugins/Relays/src/relayswidget.cpp @@ -454,7 +454,7 @@ void RelaysWidget::print_start_list_classes() if(!dlg.exec()) return; QVariantMap props = dlg.reportProperties(); - bool vacants = dlg.isStartListPrintVacants(); + bool vacants = dlg.startListPrintVacantsOption() != quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners; QVariant td = getPlugin()->startListByClassesTableData(dlg.sqlWhereExpression(), vacants); auto report_name = (dlg.options().isRelayShowLegsDetails()) ? "startList_classes.qml" : "startList_classes_condensed.qml"; qf::gui::reports::ReportViewWidget::showReport(this @@ -477,7 +477,7 @@ void RelaysWidget::print_start_list_clubs() if(!dlg.exec()) return; QVariantMap props = dlg.reportProperties(); - bool vacants = dlg.isStartListPrintVacants(); + bool vacants = dlg.startListPrintVacantsOption() != quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners; QVariant td = startListByClubsTableData(vacants); auto report_name = (dlg.options().isRelayShowLegsDetails()) ? "startList_clubs.qml" : "startList_clubs_condensed.qml"; qf::gui::reports::ReportViewWidget::showReport(this, diff --git a/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp b/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp index 743ba5f4c..56589663c 100644 --- a/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp +++ b/quickevent/app/quickevent/plugins/Runs/src/runsplugin.cpp @@ -44,6 +44,8 @@ #include #include +#include +#include namespace qff = qf::gui::framework; namespace qfu = qf::core::utils; @@ -60,6 +62,7 @@ QString datetime_to_string(const QDateTime &dt) { return quickevent::core::Utils::dateTimeToIsoStringWithUtcOffset(dt); } +const auto vacant_name_sentinel = QStringLiteral("---"); } RunsPlugin::RunsPlugin(QObject *parent) : Super("Runs", parent) @@ -1379,7 +1382,7 @@ void RunsPlugin::setRunsRecord(int run_id, const QVariant &rec) qf::core::sql::QueryBuilder RunsPlugin::startListQuery() { qfs::QueryBuilder qb; - qb.select2("competitors", "lastName, firstName, registration, iofId, startNumber, country, club") + qb.select2("competitors", "id, lastName, firstName, registration, iofId, startNumber, country, club") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .select2("runs", "id, stageId, siId, startTimeMs") .select2("classes","name") @@ -1406,14 +1409,14 @@ QVariantMap RunsPlugin::startListRecord(int run_id) return {}; } -qf::core::utils::TreeTable RunsPlugin::startListClassesTable(const QString &where_expr, const bool insert_vacants, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format) +qf::core::utils::TreeTable RunsPlugin::startListClassesTable(const QString &where_expr, const quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format) { int stage_id = selectedStageId(); auto start00_epoch_sec = getPlugin()->stageStartDateTime(stage_id).toSecsSinceEpoch(); qfs::QueryBuilder qb; qb.select2("classes", "id, name") - .select2("classdefs", "startTimeMin, lastStartTimeMin, startIntervalMin") + .select2("classdefs", "startTimeMin, lastStartTimeMin, startIntervalMin, vacantsBefore, vacantEvery, vacantsAfter, mapCount") .select2("courses", "length, climb, id") .from("classes") .joinRestricted("classes.id", "classdefs.classId", "classdefs.stageId={{stage_id}}") @@ -1435,7 +1438,7 @@ qf::core::utils::TreeTable RunsPlugin::startListClassesTable(const QString &wher tt.appendColumn("courses.startNumber", QMetaType(QMetaType::Int)); qfs::QueryBuilder qb2; - qb2.select2("competitors", "lastName, firstName, registration, iofId, startNumber, country, club") + qb2.select2("competitors", "id, lastName, firstName, registration, iofId, startNumber, country, club") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") .select2("runs", "id, siId, startTimeMs") .select2("clubs","name, abbr, importId") @@ -1487,10 +1490,11 @@ qf::core::utils::TreeTable RunsPlugin::startListClassesTable(const QString &wher m2.setQueryParameters(qpm); m2.reload(); auto tt2 = m2.toTreeTable(); + // TODO: extract to method (leaving here to minimize PR diffs). int start_time_0 = tt_row.value(QStringLiteral("startTimeMin")).toInt() * 60 * 1000; int start_time_last = tt_row.value(QStringLiteral("lastStartTimeMin")).toInt() * 60 * 1000; int start_interval = tt_row.value(QStringLiteral("startIntervalMin")).toInt() * 60 * 1000; - if(start_interval > 0 && insert_vacants) { + if(start_interval > 0 && vacants_option != quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners) { for(int j=0; j()->stageStartDateTime(stage_id).toSecsSinceEpoch(); + // 1. Fetch real runners natively (zero mapping boilerplate) qfs::QueryBuilder qb; qb.select2("competitors", "registration, id, startNumber, country") .select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName") @@ -1620,10 +1640,12 @@ qf::core::utils::TreeTable RunsPlugin::startListStartersTable(const QString &whe .select2("classes", "name") .from("competitors") .joinRestricted("competitors.id", "runs.competitorId", "runs.stageId={{stage_id}} AND runs.isRunning", "INNER JOIN") - .join("competitors.classId", "classes.id") - .orderBy("runs.startTimeMs, classes.name, competitors.lastName");//.limit(1); - if(!where_expr.isEmpty()) + .join("competitors.classId", "classes.id"); + + if(!where_expr.isEmpty()) { qb.where(where_expr); + } + QVariantMap qpm; qpm["stage_id"] = stage_id; qf::gui::model::SqlTableModel m; @@ -1631,10 +1653,83 @@ qf::core::utils::TreeTable RunsPlugin::startListStartersTable(const QString &whe m.setQueryParameters(qpm); m.reload(); auto tt = m.toTreeTable(); - addStartTimeTextToClass(tt,start00_epoch_sec, quickevent::gui::ReportOptionsDialog::StartTimeFormat::DayTime); + + // 2. Extract and append vacants + if (vacants_option != quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners) { + auto tt_classes = startListClassesTable(where_expr, vacants_option, quickevent::gui::ReportOptionsDialog::StartTimeFormat::DayTime); + + for(int i=0; i start_list; + start_list.reserve(tt.rowCount()); + for(int i=0; i::max(); + } + if (tB == 0) { + tB = std::numeric_limits::max(); + } + + if (tA != tB) { + return tA < tB; + } + + bool a_is_vacant = a.value("competitorName").toString() == vacant_name_sentinel; + bool b_is_vacant = b.value("competitorName").toString() == vacant_name_sentinel; + if (a_is_vacant != b_is_vacant) { + return !a_is_vacant; // Real runners before vacants + } + + QString cA = a.value("classes.name").toString(); + QString cB = b.value("classes.name").toString(); + if (cA != cB) { + return cA < cB; + } + + return a.value("competitorName").toString() < b.value("competitorName").toString(); + }); + + QVariantMap map = tt.toVariant().toMap(); + QVariantList sorted_rows; + sorted_rows.reserve(start_list.size()); + for(const auto &r : start_list) { + sorted_rows.append(r.row()); + } + map[qf::core::utils::TreeTable::KEY_ROWS] = sorted_rows; + tt = qf::core::utils::TreeTable(map); + + // 4. Format time text globally + addStartTimeTextToClass(tt, start00_epoch_sec, quickevent::gui::ReportOptionsDialog::StartTimeFormat::DayTime); + tt.setValue("stageId", stage_id); tt.setValue("event", getPlugin()->eventConfig()->value("event")); tt.setValue("stageStart", getPlugin()->stageStartDateTime(stage_id)); + return tt; } @@ -1771,7 +1866,7 @@ void RunsPlugin::report_startListClasses() dlg.setPageLayoutVisible(true); dlg.setStartTimeFormatVisible(true); if(dlg.exec()) { - auto tt = startListClassesTable(dlg.sqlWhereExpression(getPlugin()->currentStageId()), dlg.isStartListPrintVacants(), dlg.startTimeFormat()); + auto tt = startListClassesTable(dlg.sqlWhereExpression(getPlugin()->currentStageId()), dlg.startListPrintVacantsOption(), dlg.startTimeFormat()); auto opts = dlg.optionsMap(); QVariantMap props; props["options"] = opts; @@ -1795,7 +1890,7 @@ void RunsPlugin::report_startListClubs() dlg.setCurrentStageId(getPlugin()->currentStageId()); dlg.setClassFilterVisible(false); dlg.setStartListOptionsVisible(true); - dlg.setStartListPrintVacantsVisible(false); + dlg.setStartListPrintVacantsVisible(true); dlg.setPageLayoutVisible(true); dlg.setStartTimeFormatVisible(true); dlg.setStartlistOrderFirstByVisible(true); @@ -1823,10 +1918,10 @@ void RunsPlugin::report_startListStarters() dlg.setCurrentStageId(getPlugin()->currentStageId()); dlg.setClassFilterVisible(true); dlg.setStartListOptionsVisible(true); - dlg.setStartListPrintVacantsVisible(false); + dlg.setStartListPrintVacantsVisible(true); dlg.setStartersOptionsVisible(true); if(dlg.exec()) { - auto tt = startListStartersTable(dlg.sqlWhereExpression(getPlugin()->currentStageId())); + auto tt = startListStartersTable(dlg.sqlWhereExpression(getPlugin()->currentStageId()), dlg.startListPrintVacantsOption()); auto opts = dlg.optionsMap(); QVariantMap props; props["options"] = opts; @@ -2061,7 +2156,7 @@ void append_list(QVariantList &lst, const QVariantList &new_lst) } void RunsPlugin::export_startListClassesHtml() { - qf::core::utils::TreeTable tt1 = startListClassesTable("", false, quickevent::gui::ReportOptionsDialog::StartTimeFormat::DayTime); + qf::core::utils::TreeTable tt1 = startListClassesTable("", quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners, quickevent::gui::ReportOptionsDialog::StartTimeFormat::DayTime); QVariantList body{QStringLiteral("body")}; QString h1_str = "{{documentTitle}}"; QVariantMap event = tt1.value("event").toMap(); @@ -2458,7 +2553,7 @@ void RunsPlugin::export_resultsHtmlNStages() append_list(table, trr); auto time_to_str = [](int msec) { if(msec == UNREAL_TIME_MSEC) - return QStringLiteral("---"); + return vacant_name_sentinel; quickevent::core::og::TimeMs t(msec); return t.toString(); }; @@ -2655,12 +2750,12 @@ QString RunsPlugin::getClubAbbrFromName(QString name) return ""; } -QString RunsPlugin::startListStageIofXml30(int stage_id, bool with_vacants) +QString RunsPlugin::startListStageIofXml30(int stage_id, quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option) { QDateTime start00 = getPlugin()->stageStartDateTime(stage_id); Event::EventConfig *event_config = getPlugin()->eventConfig(); //console.debug("print_vacants", print_vacants); - auto tt1 = startListClassesTable("", with_vacants, quickevent::gui::ReportOptionsDialog::StartTimeFormat::RelativeToClassStart); + auto tt1 = startListClassesTable("", vacants_option, quickevent::gui::ReportOptionsDialog::StartTimeFormat::RelativeToClassStart); bool is_iof_race = event_config->isIofRace(); int iof_xml_race_number = event_config->iofXmlRaceNumber(); @@ -2731,64 +2826,72 @@ QString RunsPlugin::startListStageIofXml30(int stage_id, bool with_vacants) qf::core::utils::TreeTable tt2 = tt1_row.table(); if (tt2.rowCount() == 0 && is_iof_race) continue; // not save empty class - bool has_fixed_start_time = tt1_row.value(QStringLiteral("classdefs.startIntervalMin")).toInt() > 0 - || event_config->discipline() == Event::EventConfig::Discipline::MassStart; for(int j=0; j #include +#include namespace qf { namespace core { namespace utils { class Table; class TreeTable; + class TreeTableRow; } } namespace gui { @@ -74,7 +76,7 @@ class RunsPlugin : public qf::gui::framework::Plugin Q_INVOKABLE QVariantMap printAwardsOptionsWithDialog(const QVariantMap &opts); - bool exportStartListStageIofXml30(int stage_id, const QString &file_name, bool with_vacants); + bool exportStartListStageIofXml30(int stage_id, const QString &file_name, quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option); bool exportStartListCurrentStageCsvSime(const QString &file_name, bool bibs, QString sql_where); bool exportStartListCurrentStageTvGraphics(const QString &file_name); @@ -93,9 +95,9 @@ class RunsPlugin : public qf::gui::framework::Plugin qf::core::sql::QueryBuilder startListQuery(); QVariantMap startListRecord(int run_id); - qf::core::utils::TreeTable startListClassesTable(const QString &where_expr, const bool insert_vacants, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format); + qf::core::utils::TreeTable startListClassesTable(const QString &where_expr, const quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format); qf::core::utils::TreeTable startListClubsTable(const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format, const quickevent::gui::ReportOptionsDialog::StartlistOrderFirstBy order_first_by); - qf::core::utils::TreeTable startListStartersTable(const QString &where_expr); + qf::core::utils::TreeTable startListStartersTable(const QString &where_expr, quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option); qf::core::utils::TreeTable startListClassesNStagesTable(const int stages_count, const QString &where_expr, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format); qf::core::utils::TreeTable startListClubsNStagesTable(const int stages_count, const quickevent::gui::ReportOptionsDialog::StartTimeFormat start_time_format); @@ -121,7 +123,7 @@ class RunsPlugin : public qf::gui::framework::Plugin QString export_resultsHtmlStage(bool with_laps = false); void export_resultsHtmlStageWithLaps(); void export_resultsHtmlNStages(); - QString startListStageIofXml30(int stage_id, bool with_vacants); + QString startListStageIofXml30(int stage_id, quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option); QString resultsIofXml30Stage(int stage_id); int competitorForRun(int run_id); int runForCompetitorStage(int competitor_id, int stage_id); @@ -150,3 +152,4 @@ class RunsPlugin : public qf::gui::framework::Plugin } #endif // RUNS_RUNSPLUGIN_H + diff --git a/quickevent/app/quickevent/plugins/Runs/src/runswidget.cpp b/quickevent/app/quickevent/plugins/Runs/src/runswidget.cpp index 557f46fbe..7405398df 100644 --- a/quickevent/app/quickevent/plugins/Runs/src/runswidget.cpp +++ b/quickevent/app/quickevent/plugins/Runs/src/runswidget.cpp @@ -283,13 +283,18 @@ void RunsWidget::settleDownInPartWidget(::PartWidget *part_widget) auto *m_export_stlist_xml = m_stlist->addMenuInto("xml", tr("&XML")); { { - auto *a = new qfw::Action(tr("&IOF-XML 3.0")); - connect(a, &qfw::Action::triggered, this, [this]() { export_startList_stage_iofxml30(false); }); + auto *a = new qfw::Action(tr("&IOF-XML 3.0 only runners")); + connect(a, &qfw::Action::triggered, this, [this]() { export_startList_stage_iofxml30(quickevent::gui::ReportOptionsDialog::VacantsOption::OnlyRunners); }); m_export_stlist_xml->addActionInto(a); } { - auto *a = new qfw::Action(tr("IOF-XML 3.0 with &vacants")); - connect(a, &qfw::Action::triggered, this, [this]() { export_startList_stage_iofxml30(true); }); + auto *a = new qfw::Action(tr("IOF-XML 3.0 with &vacants with time")); + connect(a, &qfw::Action::triggered, this, [this]() { export_startList_stage_iofxml30(quickevent::gui::ReportOptionsDialog::VacantsOption::RegularVacants); }); + m_export_stlist_xml->addActionInto(a); + } + { + auto *a = new qfw::Action(tr("IOF-XML 3.0 with &all vacants")); + connect(a, &qfw::Action::triggered, this, [this]() { export_startList_stage_iofxml30(quickevent::gui::ReportOptionsDialog::VacantsOption::AllVacants); }); m_export_stlist_xml->addActionInto(a); } } @@ -977,13 +982,13 @@ int RunsWidget::selectedStageId() return getPlugin()->selectedStageId(); } -void RunsWidget::export_startList_stage_iofxml30(bool with_vacants) +void RunsWidget::export_startList_stage_iofxml30(quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option) { int stage_id = selectedStageId(); QString fn = getSaveFileName(Event::START_LIST_IOFXML3_FILE, stage_id); if(fn.isEmpty()) return; - getPlugin()->exportStartListStageIofXml30(stage_id, fn, with_vacants); + getPlugin()->exportStartListStageIofXml30(stage_id, fn, vacants_option); } diff --git a/quickevent/app/quickevent/plugins/Runs/src/runswidget.h b/quickevent/app/quickevent/plugins/Runs/src/runswidget.h index 9be9da658..b090a1a8a 100644 --- a/quickevent/app/quickevent/plugins/Runs/src/runswidget.h +++ b/quickevent/app/quickevent/plugins/Runs/src/runswidget.h @@ -4,6 +4,7 @@ #include #include "partwidget.h" +#include class QComboBox; class QCheckBox; @@ -47,7 +48,7 @@ class RunsWidget : public QFrame Q_INVOKABLE int selectedStageId(); public: - void export_startList_stage_iofxml30(bool with_vacants); + void export_startList_stage_iofxml30(quickevent::gui::ReportOptionsDialog::VacantsOption vacants_option); void export_startList_stage_csv_sime(); void export_startList_stage_tv_graphics(); diff --git a/quickevent/app/quickevent/quickevent-cs_CZ.ts b/quickevent/app/quickevent/quickevent-cs_CZ.ts index ccec2eb30..ee77fa757 100644 --- a/quickevent/app/quickevent/quickevent-cs_CZ.ts +++ b/quickevent/app/quickevent/quickevent-cs_CZ.ts @@ -6896,13 +6896,18 @@ Stskněte tlačítko pro obnovení pro zobrazení importovaných dat. - &IOF-XML 3.0 - &IOF XML 3.0 + &IOF-XML 3.0 only runners + &IOF XML 3.0 pouze závodníci - IOF-XML 3.0 with &vacants - IOF XML 3.0 s &vakanty + IOF-XML 3.0 with &vacants with time + IOF XML 3.0 s &vakanty s časem + + + + IOF-XML 3.0 with &all vacants + IOF XML 3.0 se &všemi vakanty