champion search and ordering basic ui working

This commit is contained in:
mrbesen 2022-07-02 22:25:20 +02:00
parent ffb980e672
commit f35b8d6719
Signed by untrusted user: MrBesen
GPG Key ID: 596B2350DCD67504
16 changed files with 501 additions and 89 deletions

32
include/championsearch.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef CHAMPIONSEARCH_H
#define CHAMPIONSEARCH_H
#include <QDialog>
#include "datadragon.h"
#include "champrow.h"
namespace Ui {
class ChampionSearch;
}
class ChampionSearch : public QDialog {
Q_OBJECT
public:
explicit ChampionSearch(DataDragon* dd, QWidget *parent = nullptr);
~ChampionSearch();
// does not return the same result on multiple calls! awsner needs to be deleted
ChampRow* getSearchResult();
private slots:
void searchChanged(QString);
private:
void clear();
Ui::ChampionSearch *ui;
DataDragon* dd;
};
#endif // CHAMPIONSEARCH_H

20
include/champrow.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <QListWidgetItem>
#include "datadragon.h"
class ChampRow : public QListWidgetItem {
public:
explicit ChampRow(QListWidget *parent = nullptr);
~ChampRow();
void setChamp(const std::string& name, uint32_t id, QPixmap icon);
QString getChamp() const;
uint32_t getChampID() const;
QPixmap getIcon();
private:
uint32_t champid = -1;
QPixmap icon;
};

View File

@ -9,7 +9,7 @@ public:
StageConfig(const QJsonObject&);
operator QJsonObject() const;
std::string champ;
std::vector<std::string> champs;
bool enabled;
};

View File

@ -49,6 +49,7 @@ public:
void getImageAsnyc(const std::string& champid, notifyImgfunc_t func, ImageType imgtype = ImageType::SQUARE);
// might block until champ data is available
const ChampData& getBestMatchingChamp(const std::string& name, int* count = nullptr);
std::vector<const ChampData*> getMatchingChamp(const std::string& name, uint32_t limit = 25);
static const ChampData EMPTYCHAMP;
protected:

View File

@ -11,9 +11,8 @@ protected:
Stage();
virtual ~Stage();
uint32_t champid = 0; // not every stage has a champ
std::vector<uint32_t> champids; // not every stage has a champ
bool enabled = false;
virtual void action(LolAutoAccept& lolaa);
};
std::vector<Stage*> stages;
@ -37,7 +36,7 @@ public:
LolAutoAccept();
~LolAutoAccept();
void setChamp(uint32_t champ, State s);
void setChamps(std::vector<uint32_t> champs, State s);
void setEnabled(bool b, State s);
bool init(); // returns true on success

View File

@ -14,7 +14,6 @@ class StageSettings : public QWidget {
Q_PROPERTY(QString name READ getName WRITE setName)
Q_PROPERTY(bool state READ getState WRITE setState NOTIFY toggled)
Q_PROPERTY(QString champion READ getChampion WRITE setChampion NOTIFY championChanged)
public:
explicit StageSettings(QWidget *parent = nullptr);
@ -26,29 +25,37 @@ public:
bool getState() const;
void setState(bool);
QString getChampion() const;
void setChampion(const QString& str);
struct SelectedChamp {
SelectedChamp(std::string name, uint32_t id);
std::string name;
uint32_t id;
};
std::vector<SelectedChamp> getChampions() const;
void setChampions(const std::vector<std::string>& champs);
void setDataDragon(DataDragon* dd);
void resizeEvent(QResizeEvent *event) override;
void addChamp(const std::string& champname, uint32_t id, QPixmap icon);
private slots:
void championChangedinternal(const QString& str);
void toggledinternal(int state);
void addChamp();
void removeChamp();
void moveUp();
void moveDown();
signals:
void toggled(bool);
void championChanged(const QString&);
void championChanged(int position, const QString&);
private:
void rescaleImage();
void applyChampion(const DataDragon::ChampData& cd);
// delete all items
void resolveAndAddChamp(const std::string& name);
void clear();
void updateEnabled();
Ui::StageSettings *ui;
DataDragon* dd = nullptr;
int currentdisplayedChampKey = -1;
QPixmap img;
};
#endif // STAGESETTINGS_H

View File

@ -24,6 +24,8 @@ defineReplace(prependAll) {
SOURCES += \
src/arg.cpp \
src/championsearch.cpp \
src/champrow.cpp \
src/clientaccess.cpp \
src/clientapi_json.cpp \
src/clientapi.cpp \
@ -44,6 +46,8 @@ SOURCES += \
HEADERS += \
include/arg.h \
include/championsearch.h \
include/champrow.h \
include/clientaccess.h \
include/clientapi.h \
include/config.h \
@ -65,6 +69,7 @@ UI_DIR = ui/
OBJECTS_DIR = build/
FORMS += \
ui/championsearch.ui \
ui/mainwindow.ui \
ui/stagesettings.ui

40
src/championsearch.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "championsearch.h"
#include "ui_championsearch.h"
#include <Log.h>
ChampionSearch::ChampionSearch(DataDragon* dd, QWidget *parent) : QDialog(parent), ui(new Ui::ChampionSearch), dd(dd) {
ui->setupUi(this);
}
ChampionSearch::~ChampionSearch() {
delete ui;
}
ChampRow* ChampionSearch::getSearchResult() {
int row = ui->championList->currentRow();
return (ChampRow*) ui->championList->takeItem(row);
}
void ChampionSearch::searchChanged(QString str) {
Log::info << "champion search: " << str.toStdString();
auto champs = dd->getMatchingChamp(str.toStdString());
Log::info << "found " << champs.size() << " champs";
clear();
for(auto it : champs) {
dd->getImageAsnyc(it->id, [this, it](QPixmap img) {
auto cr = new ChampRow();
cr->setChamp(it->name, it->key, img);
ui->championList->addItem(cr);
});
}
}
void ChampionSearch::clear() {
while(ui->championList->count()) {
delete ui->championList->takeItem(0);
}
}

26
src/champrow.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "champrow.h"
ChampRow::ChampRow(QListWidget* parent) : QListWidgetItem(parent) {
}
ChampRow::~ChampRow() {
}
void ChampRow::setChamp(const std::string& name, uint32_t id, QPixmap icon) {
setText(QString::fromStdString(name));
champid = id;
this->icon = icon;
setIcon(QIcon(icon));
}
QString ChampRow::getChamp() const {
return text();
}
uint32_t ChampRow::getChampID() const {
return champid;
}
QPixmap ChampRow::getIcon() {
return icon;
}

View File

@ -3,6 +3,7 @@
#include "files.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <Log.h>
@ -11,14 +12,34 @@
Config::StageConfig::StageConfig() : enabled(false) {}
Config::StageConfig::StageConfig(const QJsonObject& j) {
champ = getValue<std::string>(j, "champ", "");
if(j["champ"].isString()) {
champs.push_back(getValue<std::string>(j, "champ", ""));
}
if(j["champs"].isArray()) {
QJsonArray jchamps = j["champs"].toArray();
for(auto jchamp : jchamps) {
if(jchamp.isString()) {
QString jchampstr = jchamp.toString();
if(!jchampstr.isEmpty()) {
champs.push_back(jchampstr.toStdString());
}
}
}
}
enabled = getValue(j, "enabled", false);
}
Config::StageConfig::operator QJsonObject() const {
QJsonObject out;
out.insert("champ", QString::fromStdString(champ));
QJsonArray jchamps;
for(const std::string& champ : champs) {
if(!champ.empty()) {
jchamps.push_back(QString::fromStdString(champ));
}
}
out.insert("champs", jchamps);
out.insert("enabled", enabled);
return out;

View File

@ -9,7 +9,7 @@
#include <QJsonArray>
#include <QJsonObject>
#include <algorithm> // std::max
#include <algorithm> // std::max, champ matching
#include "json.h"
@ -162,6 +162,51 @@ const DataDragon::ChampData& DataDragon::getBestMatchingChamp(const std::string&
return EMPTYCHAMP;
}
std::vector<const DataDragon::ChampData*> DataDragon::getMatchingChamp(const std::string& name, uint32_t limit) {
if(limit == 0) return {};
if(name.empty()) return {};
getChamps();
std::string lower = toLower(name);
std::vector<size_t> matches;
matches.resize(champs.size());
std::transform(champs.begin(), champs.end(), std::insert_iterator(matches, matches.begin()), std::bind(&matchChamp, std::placeholders::_1, lower));
{
Log::Entry e = Log::info << "matches content: ";
for(size_t m : matches) {
e << m << " ";
}
}
// find smallest element
std::vector<size_t> matches_sort = matches;
std::nth_element(matches_sort.begin(), matches_sort.begin(), matches_sort.end(), [](size_t a, size_t b) { return b < a; });
size_t border = matches_sort.at(0);
{
Log::Entry e = Log::info << "matches_sort content: ";
for(size_t m : matches_sort) {
e << m << " ";
}
}
Log::trace << "border: " << border;
std::vector<const ChampData*> out;
out.reserve(limit);
// take all with a match higher than that
for(uint32_t i = 0; i < matches.size() && out.size() < limit; ++i) {
if(matches[i] >= border) {
out.push_back(&champs[i]);
}
}
return out;
}
std::string DataDragon::getImageUrl(const std::string& champid, ImageType type) {
switch(type) {
case ImageType::SQUARE: {

View File

@ -7,8 +7,6 @@
LolAutoAccept::Stage::Stage() {}
LolAutoAccept::Stage::~Stage() {}
void LolAutoAccept::Stage::action(LolAutoAccept& lolaa) {}
LolAutoAccept::LolAutoAccept() {
stages.reserve(4);
stages.push_back(new Stage()); // accept
@ -25,14 +23,14 @@ LolAutoAccept::~LolAutoAccept() {
}
}
void LolAutoAccept::setChamp(uint32_t champ, State s) {
void LolAutoAccept::setChamps(std::vector<uint32_t> champs, State s) {
if(s == State::LOBBY || s >= State::GAME) {
Log::warn << "setChamp() called on invalid State";
Log::warn << "setChamps() called on invalid State";
return;
}
stages.at((int) s)->champid = champ;
Log::info << "set state: " << (int) s << " to " << champ;
stages.at((int) s)->champids = champs;
Log::info << "set champs on state: " << (int) s;
}
void LolAutoAccept::setEnabled(bool b, State s) {
@ -132,7 +130,7 @@ void LolAutoAccept::prepickPhase(const ownactions_t& ownactions) {
Log::info << "pre-pick action anvailable: " << it.id << " champid: " << it.championID;
if(it.championID == 0) {
// try to prepick a champion
uint32_t champid = stages.at((int) State::PREPICK)->champid;
uint32_t champid = stages.at((int) State::PREPICK)->champids.at(0); // TODO: do on multi selection
Log::info << "try to prepick champ: " << champid;
clientapi->setChampSelectAction(it.id, champid, false);
break;
@ -149,7 +147,7 @@ void LolAutoAccept::banPhase(const ownactions_t& ownactions) {
Log::info << "ban action anvailable: " << it.id << " champid: " << it.championID;
if(it.championID == 0) {
// try to ban a champion
uint32_t champid = stages.at((int) State::BAN)->champid;
uint32_t champid = stages.at((int) State::BAN)->champids.at(0); // TODO
Log::info << "try to ban champ: " << champid;
clientapi->setChampSelectAction(it.id, champid, true);
return;
@ -164,7 +162,7 @@ void LolAutoAccept::pickPhase(const ownactions_t& ownactions) {
for(auto it : ownactions) {
if(it.type == ClientAPI::ChampSelectActionType::PICK) {
Log::info << "pick action anvailable: " << it.id << " champid: " << it.championID;
uint32_t champid = stages.at((int) State::PICK)->champid;
uint32_t champid = stages.at((int) State::PICK)->champids.at(0); // TODO
if(it.championID != champid || !it.completed) {
// try to prepick a champion
Log::info << "try to pick champ: " << champid;

View File

@ -5,7 +5,7 @@
static void applySetting(const Config::StageConfig& sc, StageSettings* ss) {
ss->setState(sc.enabled);
ss->setChampion(QString::fromStdString(sc.champ));
ss->setChampions(sc.champs);
}
MainWindow::MainWindow(LolAutoAccept& lolaa, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), lolaa(lolaa), dd(QLocale().name().toStdString()) {
@ -61,6 +61,16 @@ void MainWindow::aatoggled(bool state) {
conf.getConfig().enabledAutoAccept = state;
}
static std::vector<std::string> toChampionNameList(const std::vector<StageSettings::SelectedChamp>& scs) {
std::vector<std::string> out;
for(const StageSettings::SelectedChamp& sc : scs) {
out.push_back(sc.name);
}
return out;
}
void MainWindow::pptoggled(bool state) {
Log::info << "enablePrePick checkbox toggled " << state;
lolaa.setEnabled(state, LolAutoAccept::State::PREPICK);
@ -69,8 +79,8 @@ void MainWindow::pptoggled(bool state) {
void MainWindow::ppedited(const QString& b) {
Log::info << "prepick edited: " << b.toStdString();
lolaa.setChamp(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::PREPICK);
conf.getConfig().prepick.champ = b.toStdString();
//lolaa.setChamps(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::PREPICK);
conf.getConfig().prepick.champs = toChampionNameList(ui->prepickstage->getChampions());
}
void MainWindow::bantoggled(bool state) {
@ -81,8 +91,8 @@ void MainWindow::bantoggled(bool state) {
void MainWindow::banedited(const QString& b) {
Log::info << "ban edited: " << b.toStdString();
lolaa.setChamp(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::BAN);
conf.getConfig().ban.champ = b.toStdString();
//lolaa.setChamp(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::BAN);
conf.getConfig().ban.champs = toChampionNameList(ui->banstage->getChampions());
}
void MainWindow::picktoggled(bool state) {
@ -93,6 +103,6 @@ void MainWindow::picktoggled(bool state) {
void MainWindow::pickedited(const QString& b) {
Log::info << "pick edited: " << b.toStdString();
lolaa.setChamp(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::PICK);
conf.getConfig().pick.champ = b.toStdString();
//lolaa.setChamp(dd.getBestMatchingChamp(b.toStdString()).key, LolAutoAccept::State::PICK);
conf.getConfig().pick.champs = toChampionNameList(ui->pickstage->getChampions());
}

View File

@ -5,11 +5,13 @@
#include <Log.h>
#include "championsearch.h"
#include "champrow.h"
StageSettings::StageSettings(QWidget *parent) : QWidget(parent), ui(new Ui::StageSettings) {
ui->setupUi(this);
setMinimumSize(ui->gridLayout->minimumSize());
rescaleImage();
}
StageSettings::~StageSettings() {
@ -32,76 +34,112 @@ bool StageSettings::getState() const {
void StageSettings::setState(bool b) {
ui->checkBox->setCheckState(b ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
emit toggled(b);
updateEnabled();
}
QString StageSettings::getChampion() const {
return ""; // ui->lineEdit->text();
StageSettings::SelectedChamp::SelectedChamp(std::string name, uint32_t id) : name(name), id(id) {}
std::vector<StageSettings::SelectedChamp> StageSettings::getChampions() const {
std::vector<SelectedChamp> out;
out.reserve(ui->championList->count());
for(int32_t i = 0; i < ui->championList->count(); ++i) {
ChampRow* cr = (ChampRow*) ui->championList->item(i);
out.emplace_back(cr->getChamp().toStdString(), cr->getChampID());
}
return out;
}
void StageSettings::setChampion(const QString& str) {
// ui->lineEdit->setText(str);
championChangedinternal(str);
void StageSettings::setChampions(const std::vector<std::string>& champs) {
clear();
// add new champs
for(const std::string& champ : champs) {
auto champr = new ChampRow();
ui->championList->addItem(champr);
champr->setChamp(champ, 0, QPixmap("/home/yannis/.cache/lolautoaccept/square/Orianna.png")); // TODO
}
}
void StageSettings::setDataDragon(DataDragon* dd_) {
dd = dd_;
}
void StageSettings::resizeEvent([[maybe_unused]] QResizeEvent* event) {
rescaleImage();
}
void StageSettings::addChamp(const std::string& champname, uint32_t id, QPixmap icon) {
auto champr = new ChampRow();
ui->championList->addItem(champr);
void StageSettings::championChangedinternal(const QString& str) {
if(dd) {
int count = 0;
const DataDragon::ChampData& cd = dd->getBestMatchingChamp(str.toStdString(), &count);
if(cd.key != currentdisplayedChampKey) {
applyChampion(cd);
}
//ui->champcount->setText(tr("Champions matched: %1").arg(QString::fromStdString(std::to_string(count))));
} else {
emit championChanged(str);
}
champr->setChamp(champname, id, icon); // TODO
}
void StageSettings::toggledinternal(int state) {
emit toggled(state == Qt::CheckState::Checked);
updateEnabled();
}
void StageSettings::rescaleImage() {
if(img.isNull()) {
//ui->champImg->setPixmap(QPixmap());
return;
}
void StageSettings::addChamp() {
Log::trace << "add champ";
// TODO: popup with champion search
//auto qimg = QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
// auto p = QPixmap::fromImage(qimg);
// get label dimensions
//int w = ui->champImg->width();
//int h = ui->champImg->height();
// set a scaled pixmap to a w x h window keeping its aspect ratio
//ui->champImg->setPixmap(p.scaled(w, h, Qt::KeepAspectRatio)); //
}
void StageSettings::applyChampion(const DataDragon::ChampData& cd) {
dd->getImageAsnyc(cd.id, [this, cd](QPixmap img) {
this->img = img;
currentdisplayedChampKey = cd.key;
rescaleImage();
QIcon icon(this->img);
ui->championList->addItem(new QListWidgetItem(icon, "Champ", nullptr, 0));
emit championChanged(QString::fromStdString(cd.name));
});
if(cd.key >= 0) {
#define QS(A) arg(QString::fromStdString(A))
//ui->champImg->setToolTip(tr("Champion: %1\nType: %2\nTitle: %3\nID: %4").QS(cd.name).QS(cd.partype).QS(cd.title).arg(cd.key));
#undef QS
ChampionSearch cs(dd, this);
int res = cs.exec();
Log::info << "championsearch result: " << res;
if(res == QDialog::Accepted) {
auto cr = cs.getSearchResult();
if(cr) {
ui->championList->addItem(cr);
// TODO: emit value changed something
}
} else {
//ui->champImg->setToolTip("");
// not accepted
}
}
void StageSettings::removeChamp() {
Log::trace << "remove champ";
int row = ui->championList->currentRow(); // what if no row is selected?
delete ui->championList->takeItem(row);
}
void StageSettings::moveUp() {
Log::trace << "move up";
if(ui->championList->selectedItems().isEmpty()) return;
auto selection = ui->championList->selectedItems().at(0);
ui->championList->removeItemWidget(selection);
ui->championList->insertItem(0, selection);
}
void StageSettings::moveDown() {
Log::trace << "move down";
}
void StageSettings::resolveAndAddChamp(const std::string& name) {
if(dd) {
int count = 0;
auto cd = dd->getBestMatchingChamp(name, &count);
dd->getImageAsnyc(cd.id, [this, name, cd](QPixmap img) {
addChamp(name, cd.key, img);
emit championChanged(0, QString::fromStdString(cd.name));
});
} else {
Log::error << __PRETTY_FUNCTION__ << " Datadragon not set!";
}
}
void StageSettings::clear() {
while(ui->championList->count()) {
delete ui->championList->takeItem(0);
}
}
void StageSettings::updateEnabled() {
bool active = ui->checkBox->isChecked();
ui->championList->setEnabled(active);
ui->addChampion->setEnabled(active);
ui->moveup->setEnabled(active);
ui->movedown->setEnabled(active);
ui->removeChampion->setEnabled(active);
}

96
ui/championsearch.ui Normal file
View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChampionSearch</class>
<widget class="QDialog" name="ChampionSearch">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Champion Search</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Champion:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="searchbox"/>
</item>
<item row="2" column="1" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QListWidget" name="championList"/>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ChampionSearch</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>304</x>
<y>290</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ChampionSearch</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>372</x>
<y>290</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>searchbox</sender>
<signal>textChanged(QString)</signal>
<receiver>ChampionSearch</receiver>
<slot>searchChanged(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>218</x>
<y>21</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>28</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>searchChanged(QString)</slot>
</slots>
</ui>

View File

@ -65,6 +65,12 @@
<height>150</height>
</size>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
</widget>
</item>
<item row="1" column="1">
@ -116,8 +122,8 @@
<slot>toggledinternal(int)</slot>
<hints>
<hint type="sourcelabel">
<x>79</x>
<y>109</y>
<x>100</x>
<y>57</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
@ -125,11 +131,79 @@
</hint>
</hints>
</connection>
<connection>
<sender>addChampion</sender>
<signal>clicked()</signal>
<receiver>StageSettings</receiver>
<slot>addChamp()</slot>
<hints>
<hint type="sourcelabel">
<x>643</x>
<y>209</y>
</hint>
<hint type="destinationlabel">
<x>757</x>
<y>291</y>
</hint>
</hints>
</connection>
<connection>
<sender>moveup</sender>
<signal>clicked()</signal>
<receiver>StageSettings</receiver>
<slot>moveUp()</slot>
<hints>
<hint type="sourcelabel">
<x>683</x>
<y>371</y>
</hint>
<hint type="destinationlabel">
<x>758</x>
<y>401</y>
</hint>
</hints>
</connection>
<connection>
<sender>movedown</sender>
<signal>clicked()</signal>
<receiver>StageSettings</receiver>
<slot>moveDown()</slot>
<hints>
<hint type="sourcelabel">
<x>702</x>
<y>526</y>
</hint>
<hint type="destinationlabel">
<x>758</x>
<y>536</y>
</hint>
</hints>
</connection>
<connection>
<sender>removeChampion</sender>
<signal>clicked()</signal>
<receiver>StageSettings</receiver>
<slot>removeChamp()</slot>
<hints>
<hint type="sourcelabel">
<x>717</x>
<y>691</y>
</hint>
<hint type="destinationlabel">
<x>758</x>
<y>697</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<signal>championChanged(QString)</signal>
<signal>toggled(bool)</signal>
<slot>championChangedinternal(QString)</slot>
<slot>toggledinternal(int)</slot>
<slot>addChamp()</slot>
<slot>removeChamp()</slot>
<slot>moveUp()</slot>
<slot>moveDown()</slot>
</slots>
</ui>