X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=mainwindow.cpp;h=254e62ddf6ccd66b844ccc186f024d953fd33453;hb=a4bdd6452d857ddf4c4d755988b64121b7e73faf;hp=05c5d7120628af341fffb2d13b75597eaf7710ac;hpb=72afdc62f4ea865bdf7a3f316ec96bcb932c9d0a;p=pkanalytics diff --git a/mainwindow.cpp b/mainwindow.cpp index 05c5d71..254e62d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -67,6 +67,37 @@ string get_video_filename(sqlite3 *db, int match_id) return filename; } +bool get_match_property(sqlite3 *db, int match_id, const string &prop_name) +{ + sqlite3_stmt *stmt; + + int ret = sqlite3_prepare_v2(db, ("SELECT " + prop_name + " FROM match WHERE match=?").c_str(), -1, &stmt, 0); + if (ret != SQLITE_OK) { + fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db)); + abort(); + } + + sqlite3_bind_int64(stmt, 1, match_id); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + fprintf(stderr, "SELECT step: %s\n", sqlite3_errmsg(db)); + abort(); + } + + if (sqlite3_column_type(stmt, 0) != SQLITE_INTEGER) { + return ""; + } + bool value = sqlite3_column_int(stmt, 0); + + ret = sqlite3_finalize(stmt); + if (ret != SQLITE_OK) { + fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db)); + abort(); + } + return value; +} + void save_video_filename(sqlite3 *db, int match_id, const string &filename) { sqlite3_stmt *stmt; @@ -82,7 +113,33 @@ void save_video_filename(sqlite3 *db, int match_id, const string &filename) ret = sqlite3_step(stmt); if (ret == SQLITE_ROW) { - fprintf(stderr, "INSERT step: %s\n", sqlite3_errmsg(db)); + fprintf(stderr, "UPDATE step: %s\n", sqlite3_errmsg(db)); + abort(); + } + + ret = sqlite3_finalize(stmt); + if (ret != SQLITE_OK) { + fprintf(stderr, "SELECT finalize: %s\n", sqlite3_errmsg(db)); + abort(); + } +} + +void save_match_property(sqlite3 *db, int match_id, const string &prop_name, bool value) +{ + sqlite3_stmt *stmt; + + int ret = sqlite3_prepare_v2(db, ("UPDATE match SET " + prop_name + "=? WHERE match=?").c_str(), -1, &stmt, 0); + if (ret != SQLITE_OK) { + fprintf(stderr, "SELECT prepare: %s\n", sqlite3_errmsg(db)); + abort(); + } + + sqlite3_bind_int64(stmt, 1, value); + sqlite3_bind_int64(stmt, 2, match_id); + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + fprintf(stderr, "UPDATE step: %s\n", sqlite3_errmsg(db)); abort(); } @@ -162,22 +219,22 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, // It's not really clear whether PgUp should be forwards or backwards, // but mpv does at least up = forwards, so that's probably standard. QShortcut *pgdown = new QShortcut(QKeySequence(Qt::Key_PageDown), this); - connect(pgdown, &QShortcut::activated, [this]() { ui->video->seek(-120000); }); + connect(pgdown, &QShortcut::activated, [this] { ui->video->seek(-120000); }); QShortcut *pgup = new QShortcut(QKeySequence(Qt::Key_PageUp), this); - connect(pgup, &QShortcut::activated, [this]() { ui->video->seek(120000); }); + connect(pgup, &QShortcut::activated, [this] { ui->video->seek(120000); }); - connect(ui->minus10s, &QPushButton::clicked, [this]() { ui->video->seek(-10000); }); - connect(ui->plus10s, &QPushButton::clicked, [this]() { ui->video->seek(10000); }); + connect(ui->minus10s, &QPushButton::clicked, [this] { ui->video->seek(-10000); }); + connect(ui->plus10s, &QPushButton::clicked, [this] { ui->video->seek(10000); }); - connect(ui->minus2s, &QPushButton::clicked, [this]() { ui->video->seek(-2000); }); - connect(ui->plus2s, &QPushButton::clicked, [this]() { ui->video->seek(2000); }); - connect(ui->video, &VideoWidget::mouse_back_clicked, [this]() { ui->video->seek(-2000); }); - connect(ui->video, &VideoWidget::mouse_forward_clicked, [this]() { ui->video->seek(2000); }); + connect(ui->minus2s, &QPushButton::clicked, [this] { ui->video->seek(-2000); }); + connect(ui->plus2s, &QPushButton::clicked, [this] { ui->video->seek(2000); }); + connect(ui->video, &VideoWidget::mouse_back_clicked, [this] { ui->video->seek(-2000); }); + connect(ui->video, &VideoWidget::mouse_forward_clicked, [this] { ui->video->seek(2000); }); - connect(ui->minus1f, &QPushButton::clicked, [this]() { ui->video->seek_frames(-1); }); - connect(ui->plus1f, &QPushButton::clicked, [this]() { ui->video->seek_frames(1); }); + connect(ui->minus1f, &QPushButton::clicked, [this] { ui->video->seek_frames(-1); }); + connect(ui->plus1f, &QPushButton::clicked, [this] { ui->video->seek_frames(1); }); - connect(ui->play_pause, &QPushButton::clicked, [this]() { + connect(ui->play_pause, &QPushButton::clicked, [this] { if (playing) { ui->video->pause(); ui->play_pause->setText("Play (space)"); @@ -191,18 +248,18 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, ui->play_pause->setShortcut(QCoreApplication::translate("MainWindow", "Space", nullptr)); }); - connect(ui->player_1, &QPushButton::clicked, [this]() { insert_player_event(0); }); - connect(ui->player_2, &QPushButton::clicked, [this]() { insert_player_event(1); }); - connect(ui->player_3, &QPushButton::clicked, [this]() { insert_player_event(2); }); - connect(ui->player_4, &QPushButton::clicked, [this]() { insert_player_event(3); }); - connect(ui->player_5, &QPushButton::clicked, [this]() { insert_player_event(4); }); - connect(ui->player_6, &QPushButton::clicked, [this]() { insert_player_event(5); }); - connect(ui->player_7, &QPushButton::clicked, [this]() { insert_player_event(6); }); + connect(ui->player_1, &QPushButton::clicked, [this] { insert_player_event(0); }); + connect(ui->player_2, &QPushButton::clicked, [this] { insert_player_event(1); }); + connect(ui->player_3, &QPushButton::clicked, [this] { insert_player_event(2); }); + connect(ui->player_4, &QPushButton::clicked, [this] { insert_player_event(3); }); + connect(ui->player_5, &QPushButton::clicked, [this] { insert_player_event(4); }); + connect(ui->player_6, &QPushButton::clicked, [this] { insert_player_event(5); }); + connect(ui->player_7, &QPushButton::clicked, [this] { insert_player_event(6); }); // Offensive events - connect(ui->offense_label, &ClickableLabel::clicked, [this]() { insert_noplayer_event("set_offense"); }); - connect(ui->catch_, &QPushButton::clicked, [this]() { set_current_event_type("catch"); }); - connect(ui->throwaway, &QPushButton::clicked, [this, events]() { + connect(ui->offense_label, &ClickableLabel::clicked, [this] { insert_noplayer_event("set_offense"); }); + connect(ui->catch_, &QPushButton::clicked, [this] { set_current_event_type("catch"); }); + connect(ui->throwaway, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.attack_state == EventsModel::Status::DEFENSE && s.pull_state == EventsModel::Status::PULL_IN_AIR) { insert_noplayer_event("pull_oob"); @@ -210,10 +267,10 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, set_current_event_type("throwaway"); } }); - connect(ui->drop, &QPushButton::clicked, [this]() { set_current_event_type("drop"); }); - connect(ui->goal, &QPushButton::clicked, [this]() { set_current_event_type("goal"); }); - connect(ui->stallout, &QPushButton::clicked, [this]() { set_current_event_type("stallout"); }); - connect(ui->soft_plus, &QPushButton::clicked, [this, events]() { + connect(ui->drop, &QPushButton::clicked, [this] { set_current_event_type("drop"); }); + connect(ui->goal, &QPushButton::clicked, [this] { set_current_event_type("goal"); }); + connect(ui->stallout, &QPushButton::clicked, [this] { set_current_event_type("stallout"); }); + connect(ui->soft_plus, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.attack_state == EventsModel::Status::OFFENSE) { set_current_event_type("offensive_soft_plus"); @@ -221,7 +278,7 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, set_current_event_type("defensive_soft_plus"); } }); - connect(ui->soft_minus, &QPushButton::clicked, [this, events]() { + connect(ui->soft_minus, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.attack_state == EventsModel::Status::OFFENSE) { set_current_event_type("offensive_soft_minus"); @@ -229,7 +286,7 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, set_current_event_type("defensive_soft_minus"); } }); - connect(ui->pull_or_was_d, &QPushButton::clicked, [this, events]() { + connect(ui->pull_or_was_d, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.pull_state == EventsModel::Status::SHOULD_PULL || events->get_status_at(ui->video->get_position() - 1).pull_state == EventsModel::Status::SHOULD_PULL) { @@ -241,25 +298,25 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, } }); - // Defensive events (TODO add more) - connect(ui->interception, &QPushButton::clicked, [this]() { set_current_event_type("interception"); }); - connect(ui->defense_label, &ClickableLabel::clicked, [this]() { insert_noplayer_event("set_defense"); }); - connect(ui->their_throwaway, &QPushButton::clicked, [this]() { insert_noplayer_event("their_throwaway"); }); - connect(ui->their_goal, &QPushButton::clicked, [this]() { insert_noplayer_event("their_goal"); }); - connect(ui->their_pull, &QPushButton::clicked, [this, events]() { + // Defensive events. + connect(ui->interception, &QPushButton::clicked, [this] { set_current_event_type("interception"); }); + connect(ui->defense_label, &ClickableLabel::clicked, [this] { insert_noplayer_event("set_defense"); }); + connect(ui->their_throwaway, &QPushButton::clicked, [this] { insert_noplayer_event("their_throwaway"); }); + connect(ui->their_goal, &QPushButton::clicked, [this] { insert_noplayer_event("their_goal"); }); + connect(ui->their_pull, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.pull_state == EventsModel::Status::SHOULD_PULL) { insert_noplayer_event("their_pull"); } }); - connect(ui->our_defense, &QPushButton::clicked, [this]() { set_current_event_type("defense"); }); + connect(ui->our_defense, &QPushButton::clicked, [this] { set_current_event_type("defense"); }); - connect(ui->offensive_formation, &QPushButton::clicked, [this]() { insert_or_change_formation(/*offense=*/true); }); - connect(ui->defensive_formation, &QPushButton::clicked, [this]() { insert_or_change_formation(/*offense=*/false); }); + connect(ui->offensive_formation, &QPushButton::clicked, [this] { insert_or_change_formation(/*offense=*/true); }); + connect(ui->defensive_formation, &QPushButton::clicked, [this] { insert_or_change_formation(/*offense=*/false); }); // Misc. events - connect(ui->substitution, &QPushButton::clicked, [this]() { make_substitution(); }); - connect(ui->stoppage, &QPushButton::clicked, [this, events]() { + connect(ui->substitution, &QPushButton::clicked, [this] { make_substitution(); }); + connect(ui->stoppage, &QPushButton::clicked, [this, events] { EventsModel::Status s = events->get_status_at(ui->video->get_position()); if (s.stoppage) { insert_noplayer_event("restart"); @@ -267,11 +324,24 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players, insert_noplayer_event("stoppage"); } }); - connect(ui->unknown, &QPushButton::clicked, [this]() { insert_noplayer_event("unknown"); }); + connect(ui->unknown, &QPushButton::clicked, [this] { insert_noplayer_event("unknown"); }); QShortcut *key_delete = new QShortcut(QKeySequence(Qt::Key_Delete), this); - connect(key_delete, &QShortcut::activated, [this]() { ui->delete_->animateClick(); }); - connect(ui->delete_, &QPushButton::clicked, [this]() { delete_current_event(); }); + connect(key_delete, &QShortcut::activated, [this] { ui->delete_->animateClick(); }); + connect(ui->delete_, &QPushButton::clicked, [this] { delete_current_event(); }); + + // Menus. + connect(ui->action_exit, &QAction::triggered, [this] { close(); }); + connect(ui->action_export_json, &QAction::triggered, [db] { export_to_json(db, "ultimate.json"); }); + + ui->action_gender_rule_a->setChecked(get_match_property(db, match_id, "gender_rule_a")); + ui->action_gender_pull_rule->setChecked(get_match_property(db, match_id, "gender_pull_rule")); + connect(ui->action_gender_rule_a, &QAction::toggled, [this, db, match_id] { + save_match_property(db, match_id, "gender_rule_a", ui->action_gender_rule_a->isChecked()); + }); + connect(ui->action_gender_pull_rule, &QAction::toggled, [this, db, match_id] { + save_match_property(db, match_id, "gender_pull_rule", ui->action_gender_pull_rule->isChecked()); + }); } void MainWindow::position_changed(uint64_t pos) @@ -352,7 +422,7 @@ void MainWindow::insert_or_change_formation(bool offense) QItemSelectionModel *select = ui->event_view->selectionModel(); if (select->hasSelection()) { int row = select->selectedRows().front().row(); // Should only be one, due to our selection behavior. - string expected_type = offense ? "formation_offense" : "formation_defense"; + EventType expected_type = offense ? EventType::FORMATION_OFFENSE : EventType::FORMATION_DEFENSE; if (events->get_event_type(row) == expected_type) { events->set_event_formation(row, formation_id); update_ui_from_time(ui->video->get_position()); @@ -418,7 +488,7 @@ void MainWindow::update_status(uint64_t t) snprintf(buf, sizeof(buf), "%d–%d | %s | %d passes, %d sec possession", s.our_score, s.their_score, formation.c_str(), s.num_passes, s.possession_sec); if (s.stoppage_sec > 0) { - char buf2[256]; + char buf2[512]; snprintf(buf2, sizeof(buf2), "%s (plus %d sec stoppage)", buf, s.stoppage_sec); ui->status->setText(buf2); } else {