diff --git a/include/clientapi.h b/include/clientapi.h index 4171f79..8c415a6 100644 --- a/include/clientapi.h +++ b/include/clientapi.h @@ -2,6 +2,7 @@ #include "clientaccess.h" #include "restclient.h" +#include "position.h" class ClientAPI : public RestClient { public: @@ -41,16 +42,6 @@ public: }; static ChampSelectPhase toChampSelectPhase(const std::string& str); - enum class Position : uint32_t { - INVALID = 0, - TOP, - MIDDLE, - BOTTOM, - JUNGLE, - UTILITY - }; - static Position toPosition(const std::string& str); - enum class ChampSelectActionType : uint32_t { INVALID = 0, BAN, @@ -165,5 +156,4 @@ private: std::ostream& operator<<(std::ostream&, const ClientAPI::ReadyCheckState&); std::ostream& operator<<(std::ostream&, const ClientAPI::GameflowPhase&); std::ostream& operator<<(std::ostream&, const ClientAPI::ChampSelectPhase&); -std::ostream& operator<<(std::ostream&, const ClientAPI::Position&); std::ostream& operator<<(std::ostream&, const ClientAPI::ChampSelectActionType&); diff --git a/include/config.h b/include/config.h index 58e494a..a047a85 100644 --- a/include/config.h +++ b/include/config.h @@ -2,6 +2,8 @@ #include +#include "position.h" + class Config { public: struct StageConfig { @@ -13,14 +15,26 @@ public: bool enabled; }; + struct PositionConfig { + PositionConfig(); + PositionConfig(const QJsonObject&); + operator QJsonObject() const; + + Position position; // top, bot, sup,... + + StageConfig ban; + StageConfig pick; + }; + struct RootConfig { RootConfig(); RootConfig(const QJsonObject&); operator QJsonObject() const; - StageConfig prepick; - StageConfig ban; - StageConfig pick; + PositionConfig& getPositionConfig(Position position); + + std::vector positionConfigs; + bool enabledAutoAccept; }; diff --git a/include/lolautoaccept.h b/include/lolautoaccept.h index 97d9e49..df288fe 100644 --- a/include/lolautoaccept.h +++ b/include/lolautoaccept.h @@ -2,6 +2,7 @@ #include #include +#include #include "clientapi.h" @@ -16,6 +17,7 @@ protected: uint32_t currentOffset = 0; }; + std::mutex stagesMutex; // protects stagesvector std::vector stages; bool shouldrun = false; @@ -28,10 +30,8 @@ protected: public: enum class State { LOBBY = 0, - PREPICK = 1, - BAN = 2, - PICK = 3, - GAME = 4 + BAN = 1, + PICK = 2, }; LolAutoAccept(); diff --git a/include/mainwindow.h b/include/mainwindow.h index c206b6a..57afc16 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -26,12 +26,9 @@ protected: private slots: void toggleMainswitch(bool); void aatoggled(bool); - void pptoggled(bool); - void ppedited(); - void bantoggled(bool); - void banedited(); - void picktoggled(bool); - void pickedited(); + + void tabtoggled(Position, LolAutoAccept::State, bool); + void tabchanged(Position, LolAutoAccept::State); private: // returns empty string on no match diff --git a/include/position.h b/include/position.h new file mode 100644 index 0000000..941aa4b --- /dev/null +++ b/include/position.h @@ -0,0 +1,19 @@ +#pragma once + +#include + + +enum class Position : uint32_t { + INVALID = 0, + TOP, + JUNGLE, + MIDDLE, + BOTTOM, + UTILITY +}; +Position toPosition(const std::string& str); +std::string toString(Position p); + +std::ostream& operator<<(std::ostream&, const Position&); + +Q_DECLARE_METATYPE(Position); diff --git a/include/settingstab.h b/include/settingstab.h new file mode 100644 index 0000000..8f2203d --- /dev/null +++ b/include/settingstab.h @@ -0,0 +1,53 @@ +#ifndef SETTINGSTAB_H +#define SETTINGSTAB_H + +#include + +#include "config.h" +#include "datadragon.h" +#include "lolautoaccept.h" +#include "stagesettings.h" + +namespace Ui { + class SettingsTab; +} + +class SettingsTab : public QWidget { + Q_OBJECT + + Q_PROPERTY(Position position MEMBER position READ getPosition) + +public: + explicit SettingsTab(QWidget *parent = nullptr); + ~SettingsTab(); + + void setup(Config::PositionConfig& conf, DataDragon* dd = nullptr); + + std::vector getChamps(LolAutoAccept::State s) const; + bool getState(LolAutoAccept::State s) const; + void setChamps(LolAutoAccept::State s, const std::vector&); + void setState(LolAutoAccept::State s, bool b); + + Position getPosition() const; + +private slots: + void banToggled(bool); + void banChampsChanged(); + void pickToggled(bool); + void pickChampsChanged(); + +signals: + void changed(Position p, LolAutoAccept::State s); + void toggled(Position p, LolAutoAccept::State s, bool newstate); + +private: + StageSettings* getStage(LolAutoAccept::State s) const; + + Ui::SettingsTab *ui; + + Config::PositionConfig* conf; + DataDragon* dd = nullptr; + Position position; +}; + +#endif // SETTINGSTAB_H diff --git a/lolautoaccept.pro b/lolautoaccept.pro index e4435c0..389f95d 100644 --- a/lolautoaccept.pro +++ b/lolautoaccept.pro @@ -39,6 +39,7 @@ SOURCES += \ src/mainwindow.cpp \ src/memoryimagecache.cpp \ src/restclient.cpp \ + src/settingstab.cpp \ src/stagesettings.cpp \ thirdparty/Log/Log.cpp @@ -59,6 +60,7 @@ HEADERS += \ include/mainwindow.h \ include/memoryimagecache.h \ include/restclient.h \ + include/settingstab.h \ include/stagesettings.h \ thirdparty/Log/Log.h @@ -71,6 +73,7 @@ OBJECTS_DIR = build/ FORMS += \ ui/championsearch.ui \ ui/mainwindow.ui \ + ui/settingstab.ui \ ui/stagesettings.ui INCLUDEPATH += $$PWD/include/ \ diff --git a/src/clientapi_json.cpp b/src/clientapi_json.cpp index 929be55..f94dd6e 100644 --- a/src/clientapi_json.cpp +++ b/src/clientapi_json.cpp @@ -16,7 +16,7 @@ ARR(ReadyCheckState, "Invalid", "None", "InProgress", "Accepted", "Declined"); ARR(GameflowPhase, "None", "Lobby", "Matchmaking", "CheckedIntoTournament", "ReadyCheck", "ChampSelect", "GameStart", "FailedToLaunch", "InProgress", "Reconnect", "WaitingForStats", "PreEndOfGame", "EndOfGame", "TerminatedInError"); ARR(ChampSelectPhase, "Invalid", "PLANNING", "BAN_PICK", "FINALIZATION"); -ARR(Position, "Invalid", "top", "middle", "bottom", "jungle", "utility"); +ARR(Position, "Invalid", "top", "jungle", "middle", "bottom", "utility"); ARR(ChampSelectActionType, "Invalid", "ban", "pick", "ten_bans_reveal"); template @@ -60,8 +60,12 @@ ClientAPI::ChampSelectPhase ClientAPI::toChampSelectPhase(const std::string& str return MAPENUM(str, ChampSelectPhase, INVALID); } -ClientAPI::Position ClientAPI::toPosition(const std::string& str) { - return MAPENUM(str, Position, INVALID); +Position toPosition(const std::string& str) { + return mapEnum(str, PositionNames, PositionNamesCount, Position::INVALID); +} + +std::string toString(Position p) { + return PositionNames[(int) p]; } ClientAPI::ChampSelectActionType ClientAPI::toChampSelectActionType(const std::string& str) { @@ -177,5 +181,9 @@ ClientAPI::ChampSelectSession::operator bool() { PRINTENUM(ReadyCheckState) PRINTENUM(GameflowPhase) PRINTENUM(ChampSelectPhase) -PRINTENUM(Position) PRINTENUM(ChampSelectActionType) + +std::ostream& operator<<(std::ostream& str, const Position & state) { \ + assert(((int) state) < PositionNamesCount); \ + return str << PositionNames[(int) state] << " (" << (int) state << ')'; \ +} diff --git a/src/config.cpp b/src/config.cpp index 7c6f1fa..23eb48b 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -45,26 +45,71 @@ Config::StageConfig::operator QJsonObject() const { return out; } +Config::PositionConfig::PositionConfig() {} +Config::PositionConfig::PositionConfig(const QJsonObject& j) { + ban = getValue(j, "ban"); + pick = getValue(j, "pick"); + position = toPosition(getValue(j, "position")); + if((int) position < 0 || position > Position::UTILITY) { + Log::warn << "invalid config value \"position\""; + position = Position::MIDDLE; + } +} +Config::PositionConfig::operator QJsonObject() const { + QJsonObject out; + + out["ban"] = (QJsonObject) ban; + out["pick"] = (QJsonObject) pick; + out["position"] = QString::fromStdString(toString(position)); + + return out; +} + Config::RootConfig::RootConfig() {} Config::RootConfig::RootConfig(const QJsonObject& j) { - prepick = getValue(j, "prepick"); - ban = getValue(j, "ban"); - pick = getValue(j, "pick"); - enabledAutoAccept = getValue(j, "enabledAutoAccept", false); + auto jposref = j["positions"]; + if(jposref.isArray()) { + QJsonArray jpos = jposref.toArray(); + + positionConfigs.reserve(jpos.size()); + for(QJsonValue val : jpos) { + if(val.isObject()) { + positionConfigs.emplace_back(val.toObject()); // implicit cast to PositionConfig + } + } + } + + enabledAutoAccept = getValue(j, "enabledAutoAccept", true); } Config::RootConfig::operator QJsonObject() const { QJsonObject out; - out.insert("prepick", (QJsonObject) prepick); - out.insert("ban", (QJsonObject) ban); - out.insert("pick", (QJsonObject) pick); + QJsonArray positionarr; + for(const PositionConfig& pos : positionConfigs) { + positionarr.push_back((QJsonObject) pos); + } + + out["positions"] = positionarr; out.insert("enabledAutoAccept", enabledAutoAccept); return out; } +Config::PositionConfig& Config::RootConfig::getPositionConfig(Position position) { + for(uint32_t i = 0; i < positionConfigs.size(); ++i) { + if(positionConfigs.at(i).position == position) { + return positionConfigs.at(i); + } + } + + // add a new config + positionConfigs.emplace_back(); + positionConfigs.back().position = position; + return positionConfigs.back(); +} + Config::Config() { configFolderPath = getHome() + ".config/lolautoaccept/"; configFilePath = configFolderPath + "config.json"; diff --git a/src/lolautoaccept.cpp b/src/lolautoaccept.cpp index ef106f5..317c990 100644 --- a/src/lolautoaccept.cpp +++ b/src/lolautoaccept.cpp @@ -8,9 +8,9 @@ LolAutoAccept::Stage::Stage() {} LolAutoAccept::Stage::~Stage() {} LolAutoAccept::LolAutoAccept() { - stages.reserve(4); + std::lock_guard lock(stagesMutex); + stages.reserve(3); stages.push_back(new Stage()); // accept - stages.push_back(new Stage()); // prepick stages.push_back(new Stage()); // ban stages.push_back(new Stage()); // pick } @@ -18,28 +18,32 @@ LolAutoAccept::LolAutoAccept() { LolAutoAccept::~LolAutoAccept() { stopJoinThread(); + std::lock_guard lock(stagesMutex); for(auto s : stages) { delete s; } } void LolAutoAccept::setChamps(const std::vector& champs, State s) { - if(s == State::LOBBY || s >= State::GAME) { + if(s == State::LOBBY || s >= State::PICK) { Log::warn << "setChamps() called on invalid State"; return; } - - stages.at((int) s)->champids = champs; - stages.at((int) s)->currentOffset = 0; + { + std::lock_guard lock(stagesMutex); + stages.at((int) s)->champids = champs; + stages.at((int) s)->currentOffset = 0; + } Log::info << "set champs on state: " << (int) s << " count: " << champs.size(); } void LolAutoAccept::setEnabled(bool b, State s) { - if(s >= State::GAME) { + if(s >= State::PICK) { Log::warn << "setEnabled() called on invalid State"; return; } + std::lock_guard lock(stagesMutex); stages.at((int) s)->enabled = b; } @@ -83,6 +87,7 @@ void LolAutoAccept::innerRun() { shouldrun = true; while(shouldrun) { + uint32_t extrasleep = 800; auto start = std::chrono::high_resolution_clock::now(); auto phase = clientapi->getGameflowPhase(); @@ -100,8 +105,20 @@ void LolAutoAccept::innerRun() { } } resetAllOffsets(); + extrasleep = 0; // no extra sleep } else if(phase == ClientAPI::GameflowPhase::CHAMPSELECT) { champSelect(); + extrasleep = 0; // no extra sleep + } else if(phase == ClientAPI::GameflowPhase::INPROGRESS) { + extrasleep = 30000; // 30s bonus sleep + } else if(phase == ClientAPI::GameflowPhase::ENDOFGAME) { + extrasleep = 2000; // 2 s bonus sleep + } else if(phase == ClientAPI::GameflowPhase::PREENDOFGAME) { + extrasleep = 4000; // 4 s bonus sleep + } else if(phase == ClientAPI::GameflowPhase::WAITINGFORSTATS) { + extrasleep = 4000; // 4 s bonus sleep + } else if(phase == ClientAPI::GameflowPhase::NONE) { + extrasleep = 30000; // 30 s bonus sleep - no lobby } auto end = std::chrono::high_resolution_clock::now(); @@ -109,7 +126,7 @@ void LolAutoAccept::innerRun() { //if(dur.count() > 1e-5) Log::note << "iteration took: " << (dur.count() * 1000) << " ms"; - std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + std::this_thread::sleep_for(std::chrono::milliseconds(400 + extrasleep)); } } @@ -176,7 +193,7 @@ LolAutoAccept::ownactions_t LolAutoAccept::getOwnActions(int32_t cellid, const s } void LolAutoAccept::prepickPhase(const ownactions_t& ownactions) { - phase(ownactions, ClientAPI::ChampSelectActionType::PICK, State::PREPICK, false); + phase(ownactions, ClientAPI::ChampSelectActionType::PICK, State::PICK, false); } void LolAutoAccept::banPhase(const ownactions_t& ownactions, const ClientAPI::ChampSelectSession& session) { @@ -229,7 +246,7 @@ void LolAutoAccept::champSelect() { } } - ClientAPI::Position pos = me ? me->position : ClientAPI::Position::INVALID; + Position pos = me ? me->position : Position::INVALID; Log::debug << "cellid: " << cellid << " position: " << pos << " counter: " << session.counter << " timer: timeleftip: " << session.timer.adjustedTimeLeftInPhase << " totaltimephase: " << session.timer.totalTimeInPhase; @@ -239,6 +256,8 @@ void LolAutoAccept::champSelect() { // try to prepick champ Log::info << "champselectphase: " << session.timer.phase; + + std::lock_guard lock(stagesMutex); if(session.timer.phase == ClientAPI::ChampSelectPhase::PLANNING) { prepickPhase(ownactions); } else if(session.timer.phase == ClientAPI::ChampSelectPhase::BAN_PICK) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4bf593d..66a5d38 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3,26 +3,23 @@ #include -static void applySetting(const Config::StageConfig& sc, StageSettings* ss) { - ss->setState(sc.enabled); - ss->setChampions(sc.champs); -} - MainWindow::MainWindow(LolAutoAccept& lolaa, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), lolaa(lolaa), dd(QLocale().name().toStdString()) { ui->setupUi(this); conf.load(); - ui->prepickstage->setDataDragon(&dd); - ui->banstage->setDataDragon(&dd); - ui->pickstage->setDataDragon(&dd); + // for all tabs - set their config and datadragon + Config::RootConfig& rc = conf.getConfig(); + for(int32_t tabnr = 0; tabnr < ui->tabWidget->count(); ++tabnr) { + SettingsTab* tab = (SettingsTab*) ui->tabWidget->widget(tabnr); + tab->setup(rc.getPositionConfig(tab->getPosition()), &dd); + + QObject::connect(tab, SIGNAL( changed(Position, LolAutoAccept::State) ), this, SLOT( tabchanged(Position, LolAutoAccept::State) )); + QObject::connect(tab, SIGNAL( toggled(Position, LolAutoAccept::State, bool) ), this, SLOT( tabtoggled(Position, LolAutoAccept::State, bool) )); + } - const Config::RootConfig& rc = conf.getConfig(); ui->enableAll->setChecked(rc.enabledAutoAccept); lolaa.setEnabled(rc.enabledAutoAccept, LolAutoAccept::State::LOBBY); - applySetting(rc.prepick, ui->prepickstage); - applySetting(rc.ban, ui->banstage); - applySetting(rc.pick, ui->pickstage); resizeEvent(nullptr); } @@ -70,16 +67,6 @@ void MainWindow::aatoggled(bool state) { conf.getConfig().enabledAutoAccept = state; } -static std::vector toChampionNameList(const std::vector& scs) { - std::vector out; - - for(const StageSettings::SelectedChamp& sc : scs) { - out.push_back(sc.name); - } - - return out; -} - static std::vector toChampionIDList(const std::vector& scs) { std::vector out; @@ -90,41 +77,16 @@ static std::vector toChampionIDList(const std::vectorprepickstage->getChampions(); - lolaa.setChamps(toChampionIDList(champs), LolAutoAccept::State::PREPICK); - conf.getConfig().prepick.champs = toChampionNameList(champs); -} +void MainWindow::tabchanged(Position p, LolAutoAccept::State s) { + Log::info << "prepick edited position: " << p << " state: " << (int) s; -void MainWindow::bantoggled(bool state) { - Log::info << "enableBan checkbox toggled " << state; - lolaa.setEnabled(state, LolAutoAccept::State::BAN); - conf.getConfig().ban.enabled = state; -} - -void MainWindow::banedited() { - Log::info << "ban edited"; - auto champs = ui->banstage->getChampions(); - lolaa.setChamps(toChampionIDList(champs), LolAutoAccept::State::BAN); - conf.getConfig().ban.champs = toChampionNameList(champs); -} - -void MainWindow::picktoggled(bool state) { - Log::info << "enablePick checkbox toggled " << state; - lolaa.setEnabled(state, LolAutoAccept::State::PICK); - conf.getConfig().pick.enabled = state; -} - -void MainWindow::pickedited() { - Log::info << "pick edited"; - auto champs = ui->pickstage->getChampions(); - lolaa.setChamps(toChampionIDList(champs), LolAutoAccept::State::PICK); - conf.getConfig().pick.champs = toChampionNameList(champs); + SettingsTab* tab = (SettingsTab*) ui->tabWidget->widget((int) p -1); + auto champs = tab->getChamps(s); + lolaa.setChamps(toChampionIDList(champs), s); } diff --git a/src/settingstab.cpp b/src/settingstab.cpp new file mode 100644 index 0000000..8c11987 --- /dev/null +++ b/src/settingstab.cpp @@ -0,0 +1,81 @@ +#include "settingstab.h" +#include "ui_settingstab.h" + +#include + +static std::vector toChampionNameList(const std::vector& scs) { + std::vector out; + out.reserve(scs.size()); + + std::transform(scs.begin(), scs.end(), std::insert_iterator(out, out.begin()), [](const StageSettings::SelectedChamp& sc) { return sc.name; }); + + return out; +} + +SettingsTab::SettingsTab(QWidget *parent) : QWidget(parent), ui(new Ui::SettingsTab) { + ui->setupUi(this); +} + +SettingsTab::~SettingsTab() { + delete ui; +} + +void SettingsTab::setup(Config::PositionConfig& conf, DataDragon* dd) { + this->conf = &conf; + this->dd = dd; + + ui->banstage->setDataDragon(dd); + ui->pickstage->setDataDragon(dd); +} + +std::vector SettingsTab::getChamps(LolAutoAccept::State s) const { + return getStage(s)->getChampions(); +} + +bool SettingsTab::getState(LolAutoAccept::State s) const { + auto stage = getStage(s); + return stage->getState(); +} + +void SettingsTab::setChamps(LolAutoAccept::State s, const std::vector& c) { + getStage(s)->setChampions(c); +} + +void SettingsTab::setState(LolAutoAccept::State s, bool b) { + auto stage = getStage(s); + return stage->setState(b); +} + +Position SettingsTab::getPosition() const { + return position; +} + +void SettingsTab::banToggled(bool b) { + conf->ban.enabled = b; + emit toggled(position, LolAutoAccept::State::BAN, b); +} + +void SettingsTab::banChampsChanged() { + conf->ban.champs = toChampionNameList(ui->banstage->getChampions()); + emit changed(position, LolAutoAccept::State::BAN); +} + +void SettingsTab::pickToggled(bool b) { + conf->pick.enabled = b; + emit toggled(position, LolAutoAccept::State::PICK, b); +} + +void SettingsTab::pickChampsChanged() { + conf->pick.champs = toChampionNameList(ui->pickstage->getChampions()); + emit changed(position, LolAutoAccept::State::BAN); +} + +StageSettings* SettingsTab::getStage(LolAutoAccept::State s) const { + switch(s) { + case LolAutoAccept::State::BAN: return ui->banstage; + case LolAutoAccept::State::PICK: return ui->pickstage; + default: break; + } + assert(false); // "invalid" stage (Lobby or Game) + return nullptr; +} \ No newline at end of file diff --git a/ui/championsearch.ui b/ui/championsearch.ui index 6c469f6..961ae75 100644 --- a/ui/championsearch.ui +++ b/ui/championsearch.ui @@ -89,6 +89,38 @@ + + championList + doubleClicked(QModelIndex) + ChampionSearch + accept() + + + 182 + 169 + + + 396 + 188 + + + + + championList + itemActivated(QListWidgetItem*) + ChampionSearch + accept() + + + 324 + 106 + + + 396 + 116 + + + searchChanged(QString) diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index ac67dfd..9615d68 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -54,72 +54,65 @@ - - - true + + + QTabWidget::North - - - 0 - 0 - + + QTabWidget::Rounded - - - 100 - 10 - + + 4 - - Pre Pick + + Qt::ElideNone - + false - - - - - - - 0 - 0 - - - - - 100 - 10 - - - - Ban - - - false - - - - - - - - 0 - 0 - - - - - 100 - 10 - - - - Pick - - + false + + + 1 + + + Top + + + + + 2 + + + Jungle + + + + + 3 + + + Middle + + + + + 4 + + + Bottom + + + + + 5 + + + Support + + @@ -139,13 +132,10 @@ - StageSettings + SettingsTab QWidget -
stagesettings.h
- - toggled(bool) - championsChanged() - +
settingstab.h
+ 1
@@ -170,38 +160,6 @@ - - prepickstage - toggled(bool) - MainWindow - pptoggled(bool) - - - 253 - 254 - - - 296 - 309 - - - - - banstage - toggled(bool) - MainWindow - bantoggled(bool) - - - 227 - 413 - - - 265 - 390 - - - mainswitch clicked(bool) @@ -218,79 +176,11 @@ - - pickstage - toggled(bool) - MainWindow - picktoggled(bool) - - - 201 - 489 - - - 265 - 476 - - - - - pickstage - championsChanged() - MainWindow - pickedited() - - - 172 - 498 - - - 122 - 473 - - - - - banstage - championsChanged() - MainWindow - banedited() - - - 149 - 418 - - - 111 - 379 - - - - - prepickstage - championsChanged() - MainWindow - ppedited() - - - 185 - 254 - - - 122 - 308 - - - aatoggled(bool) - pptoggled(bool) - ppedited() - bantoggled(bool) - picktoggled(bool) - banedited() - pickedited() + tabtoggled(Position, LolAutoAccept::State, bool) + tabchanged(Position, LolAutoAccept::State) toggleMainswitch(bool) diff --git a/ui/settingstab.ui b/ui/settingstab.ui new file mode 100644 index 0000000..e6697fe --- /dev/null +++ b/ui/settingstab.ui @@ -0,0 +1,147 @@ + + + SettingsTab + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + 0 + 0 + + + + + 100 + 10 + + + + Ban + + + false + + + + + + + + 0 + 0 + + + + + 100 + 10 + + + + Pick + + + false + + + + + + + + StageSettings + QWidget +
stagesettings.h
+ + toggled(bool) + championsChanged() + +
+
+ + + + banstage + championsChanged() + SettingsTab + banChampsChanged() + + + 179 + 78 + + + 398 + 86 + + + + + banstage + toggled(bool) + SettingsTab + banToggled(bool) + + + 329 + 124 + + + 397 + 123 + + + + + pickstage + championsChanged() + SettingsTab + pickChampsChanged() + + + 284 + 220 + + + 400 + 200 + + + + + pickstage + toggled(bool) + SettingsTab + pickToggled(bool) + + + 344 + 257 + + + 400 + 257 + + + + + + banToggled(bool) + banChampsChanged() + pickToggled(bool) + pickChampsChanged() + +