forked from MrBesen/lolautoaccept
305 lines
7.9 KiB
C++
305 lines
7.9 KiB
C++
#include "runepagelist.h"
|
|
#include "ui_runepagelist.h"
|
|
|
|
#include <QDebug>
|
|
#include <QDropEvent>
|
|
#include <QMenu>
|
|
#include <QMimeData>
|
|
#include <QTextStream>
|
|
|
|
#include "clipboardpopup.h"
|
|
#include "runeeditor.h"
|
|
|
|
RunePageList::RunePageList(QWidget* parent) : QListWidget(parent), ui(new Ui::RunePageList) {
|
|
ui->setupUi(this);
|
|
|
|
QObject::connect(this, &QListWidget::itemChanged, this, &RunePageList::itemChangedCallback);
|
|
QObject::connect(this, &QListWidget::customContextMenuRequested, this, &RunePageList::openContextMenu);
|
|
}
|
|
|
|
RunePageList::~RunePageList() {
|
|
delete this->ui;
|
|
}
|
|
|
|
void RunePageList::loadRunePages(const std::vector<ClientAPI::RunePage>& pages) {
|
|
clearItems();
|
|
for(const ClientAPI::RunePage& rp : pages) {
|
|
addRunepageItem(rp.name, rp.id, rp.runepage, rp.isCurrent);
|
|
}
|
|
}
|
|
|
|
void RunePageList::loadRunePages(const std::vector<std::shared_ptr<Config::RunePageConfig>>& pages) {
|
|
clearItems();
|
|
for(size_t i = 0; i < pages.size(); ++i) {
|
|
std::shared_ptr<Config::RunePageConfig> rp = pages.at(i);
|
|
addRunepageItem(rp->name, i, rp->runepage);
|
|
}
|
|
}
|
|
|
|
void RunePageList::setRuneInfos(const std::vector<RuneAspekt>& runeInfo, const std::vector<RuneStyle>& runeStyles) {
|
|
this->runeInfo = &runeInfo;
|
|
this->runeStyles = &runeStyles;
|
|
}
|
|
|
|
void RunePageList::dropEvent(QDropEvent* event) {
|
|
if(event->source() == nullptr || event->source() != other) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
|
|
auto selected = other->selectedItems();
|
|
if(selected.size() != 1) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
QListWidgetItem* item = selected.at(0);
|
|
|
|
// compare rune pages for duplicates?
|
|
|
|
// QListWidget::dropEvent(event);
|
|
|
|
// save change
|
|
QString name = item->text();
|
|
const RunePage* oldPage = (RunePage*) item->data(RolePointer).toULongLong();
|
|
|
|
emit runepageChanged(-1, name, *oldPage);
|
|
}
|
|
|
|
void RunePageList::itemChangedCallback(QListWidgetItem* item) {
|
|
int pageId = item->data(RunePageList::RoleId).toUInt();
|
|
QString newName = item->text();
|
|
const ::RunePage* page = (::RunePage*) item->data(RunePageList::RolePointer).toULongLong();
|
|
emit runepageChanged(pageId, newName, *page);
|
|
}
|
|
|
|
void RunePageList::openContextMenu(const QPoint& pos) {
|
|
QPoint globalPos = mapToGlobal(pos);
|
|
|
|
QMenu menu;
|
|
menu.addAction(QIcon(":/icons/edit.svg"), RunePageList::tr("Edit (Beta)"), this, &RunePageList::editCurrentItem);
|
|
menu.addAction(QIcon(":/icons/duplicate.svg"), RunePageList::tr("Duplicate"), this, &RunePageList::duplicateCurrentItem);
|
|
menu.addAction(QIcon(":/icons/export.svg"), RunePageList::tr("Export"), this, &RunePageList::exportCurrentItem);
|
|
menu.addAction(QIcon(":/icons/import.svg"), RunePageList::tr("Import"), this, &RunePageList::importItem);
|
|
menu.addAction(QIcon(":/icons/delete.svg"), RunePageList::tr("Delete"), this, &RunePageList::deleteCurrentItem);
|
|
|
|
menu.exec(globalPos);
|
|
}
|
|
|
|
void RunePageList::deleteCurrentItem() {
|
|
QListWidgetItem* item = currentItem();
|
|
if (item) {
|
|
uint32_t id = item->data(RoleId).toUInt();
|
|
RunePage* page = (RunePage*) item->data(RolePointer).toULongLong();
|
|
removeItemWidget(item);
|
|
|
|
delete item;
|
|
delete page;
|
|
|
|
emit runepageDeleted(id);
|
|
}
|
|
}
|
|
|
|
void RunePageList::editCurrentItem() {
|
|
QListWidgetItem* item = currentItem();
|
|
if(!item) return;
|
|
|
|
RunePage* rp = (RunePage*) item->data(RolePointer).toULongLong();
|
|
const uint32_t id = item->data(RoleId).toUInt();
|
|
|
|
RuneEditor re;
|
|
|
|
re.setName(item->text());
|
|
re.setClient(*client);
|
|
re.setRunepage(*rp);
|
|
|
|
int result = re.exec();
|
|
|
|
// check result - save
|
|
if(result == QDialog::Accepted) {
|
|
|
|
// update config
|
|
emit runepageChanged(id, re.getName(), re.getRunepage());
|
|
}
|
|
}
|
|
|
|
void RunePageList::duplicateCurrentItem() {
|
|
QListWidgetItem* item = currentItem();
|
|
if(!item) return;
|
|
|
|
const RunePage* rp = (RunePage*) item->data(RolePointer).toULongLong();
|
|
|
|
QString name = item->text();
|
|
|
|
static const QRegularExpression regex(".*(\\d)+$");
|
|
QRegularExpressionMatchIterator regexIt = regex.globalMatch(name);
|
|
int num = 0;
|
|
if(regexIt.hasNext()) {
|
|
QRegularExpressionMatch match = regexIt.next();
|
|
QStringRef ref = match.capturedRef(1);
|
|
name.chop(ref.size());
|
|
num = ref.toInt();
|
|
}
|
|
name += QString::number(num+1);
|
|
|
|
emit runepageChanged(-1, name, *rp);
|
|
}
|
|
|
|
void RunePageList::exportCurrentItem() {
|
|
QListWidgetItem* item = currentItem();
|
|
if(!item) return;
|
|
|
|
const RunePage* rp = (RunePage*) item->data(RolePointer).toULongLong();
|
|
|
|
Config::RunePageConfig rpc;
|
|
rpc.name = item->text();
|
|
rpc.runepage = *rp;
|
|
|
|
QJsonDocument rpcDoc(rpc); // cast to QJsonObject
|
|
QByteArray jsonBytes = rpcDoc.toJson(QJsonDocument::Compact).toBase64();
|
|
QString runePageString = QString::fromLocal8Bit(jsonBytes);
|
|
|
|
ClipboardPopup popup(ClipboardPopup::Direction::Copy);
|
|
popup.setText(runePageString);
|
|
popup.exec();
|
|
}
|
|
|
|
void RunePageList::importItem() {
|
|
ClipboardPopup popup(ClipboardPopup::Direction::Paste);
|
|
if(popup.exec() != QDialog::Accepted) {
|
|
return;
|
|
}
|
|
|
|
QString text = popup.getText();
|
|
QByteArray jsonBytes = QByteArray::fromBase64(text.toLocal8Bit());
|
|
QJsonDocument rpcDoc = QJsonDocument::fromJson(jsonBytes);
|
|
if(rpcDoc.isObject()) {
|
|
QJsonObject rpcJson = rpcDoc.object();
|
|
Config::RunePageConfig rpc = rpcJson; // implicit cast
|
|
|
|
if(rpc.name.isEmpty() || !rpc.runepage) {
|
|
// invalid
|
|
return;
|
|
}
|
|
|
|
emit runepageChanged(-1, rpc.name, rpc.runepage);
|
|
}
|
|
}
|
|
|
|
void RunePageList::clearItems() {
|
|
while(count()) {
|
|
QListWidgetItem* item = takeItem(0);
|
|
delete (RunePage*) item->data(RolePointer).toULongLong();
|
|
delete item;
|
|
}
|
|
|
|
clear();
|
|
}
|
|
|
|
void RunePageList::addRunepageItem(QString name, int id, const ::RunePage& rp, bool isCurrent) {
|
|
QListWidgetItem* item = new QListWidgetItem(name);
|
|
item->setData(RoleId, (uint) id);
|
|
item->setData(RolePointer, (qulonglong) new ::RunePage(rp));
|
|
|
|
const DataDragon::ChampData& champData = findChamp(name);
|
|
if(champData.key != -1) {
|
|
QPixmap iamge = dd->getImage(champData.id);
|
|
item->setIcon(iamge);
|
|
}
|
|
|
|
QString tooltipStr;
|
|
if(id != -1) {
|
|
tooltipStr = QString("id: %0\n").arg(id);
|
|
}
|
|
tooltipStr += getRuneDescription(rp);
|
|
item->setToolTip(tooltipStr);
|
|
|
|
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
|
if(isCurrent) {
|
|
item->setSelected(true);
|
|
}
|
|
addItem(item);
|
|
}
|
|
|
|
const DataDragon::ChampData& RunePageList::findChamp(const QString& name) {
|
|
if(!dd) {
|
|
return DataDragon::EMPTYCHAMP;
|
|
}
|
|
|
|
// try direct
|
|
int count = 0;
|
|
const DataDragon::ChampData& directChampData = dd->getBestMatchingChamp(name, &count);
|
|
if(directChampData.key != -1) {
|
|
return directChampData;
|
|
}
|
|
|
|
// not specific
|
|
if(count > 1) {
|
|
return DataDragon::EMPTYCHAMP;
|
|
}
|
|
|
|
// try for substrings
|
|
static const QRegularExpression splittingRegex("\\W+");
|
|
QStringList list = name.split(splittingRegex, QString::SplitBehavior::SkipEmptyParts);
|
|
QSet<int> matchedIds;
|
|
const DataDragon::ChampData* lastMatched = nullptr;
|
|
for(const QString& entry : list) {
|
|
count = 0;
|
|
const DataDragon::ChampData& splitChampData = dd->getBestMatchingChamp(entry, &count);
|
|
if(count == 1) {
|
|
matchedIds.insert(splitChampData.key);
|
|
lastMatched = &splitChampData;
|
|
} else if(count > 1) {
|
|
// not specific
|
|
return DataDragon::EMPTYCHAMP;
|
|
}
|
|
}
|
|
|
|
if(lastMatched && matchedIds.size() == 1) {
|
|
return *lastMatched;
|
|
}
|
|
|
|
// not specific or not found
|
|
return DataDragon::EMPTYCHAMP;
|
|
}
|
|
|
|
QString RunePageList::getRuneDescription(const ::RunePage& runepage) {
|
|
QString outStr;
|
|
outStr.reserve(100);
|
|
QTextStream out(&outStr);
|
|
|
|
if(! (bool) runepage) {
|
|
return {};
|
|
}
|
|
|
|
out << getRuneStyleByID(runepage.primaryStyle) << ' ' << RunePageList::tr("with") << ' ' << getRuneStyleByID(runepage.secondaryStyle);
|
|
|
|
for(uint32_t rune : runepage.selectedAspects) {
|
|
out << '\n' << getRuneText(rune);
|
|
}
|
|
return outStr;
|
|
}
|
|
|
|
QString RunePageList::getRuneText(uint32_t id) {
|
|
if(runeInfo != nullptr) {
|
|
for(const RuneAspekt& ra : *runeInfo) {
|
|
if(ra.id == id) {
|
|
return ra.name;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QString("(%0)").arg(id);
|
|
}
|
|
|
|
QString RunePageList::getRuneStyleByID(uint32_t id) {
|
|
if(runeStyles != nullptr) {
|
|
auto it = std::find_if(runeStyles->begin(), runeStyles->end(), [id](const RuneStyle& rs) { return rs.id == id; });
|
|
|
|
if(it != runeStyles->end()) {
|
|
return it->name;
|
|
}
|
|
}
|
|
|
|
return QString("(%0)").arg(id);
|
|
}
|