forked from MrBesen/lolautoaccept
Compare commits
10 Commits
42ff827caf
...
12a2d71762
Author | SHA1 | Date |
---|---|---|
Oliver | 12a2d71762 | |
mrbesen | 01e9a42482 | |
mrbesen | e7a10f2921 | |
mrbesen | 7d5f61dba8 | |
mrbesen | df78570e51 | |
mrbesen | a9fa26346f | |
mrbesen | 201f3665b3 | |
mrbesen | 61c64def43 | |
mrbesen | adcf715694 | |
mrbesen | b919a64ae6 |
|
@ -21,4 +21,4 @@ lolautoaccept (0.0.5) unstable; urgency=medium
|
|||
|
||||
* Initial release.
|
||||
|
||||
-- Oliver <oliver@oliver-pc> Mon, 05 Sep 2022 01:42:50 +0200
|
||||
-- Oliver <git@oliver-kaestner.de> Mon, 05 Sep 2022 01:42:50 +0200
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "position.h"
|
||||
|
||||
class BlitzAPI : public RestClient {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BlitzAPI();
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ class ChampCache {
|
|||
public:
|
||||
ChampCache();
|
||||
|
||||
std::string getVersion();
|
||||
QString getVersion();
|
||||
|
||||
QJsonDocument getChamps();
|
||||
void saveChamps(QJsonDocument doc, const std::string& version);
|
||||
void saveChamps(QJsonDocument doc, const QString& version);
|
||||
|
||||
private:
|
||||
std::string basefolder;
|
||||
QString basefolder;
|
||||
uint64_t maxage = 86400; // is in seconds
|
||||
};
|
|
@ -1,25 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <QString>
|
||||
|
||||
class ClientAccess {
|
||||
ClientAccess();
|
||||
public:
|
||||
ClientAccess(const std::string& token, uint16_t port);
|
||||
ClientAccess(const QString& token, uint16_t port);
|
||||
static std::shared_ptr<ClientAccess> find();
|
||||
|
||||
public:
|
||||
std::string getBasicAuth() const;
|
||||
QString getBasicAuth() const;
|
||||
uint16_t getPort() const;
|
||||
|
||||
std::string getURL() const;
|
||||
QString getURL() const;
|
||||
|
||||
private:
|
||||
|
||||
std::string authcode;
|
||||
QString authcode;
|
||||
uint16_t port = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "runestyle.h"
|
||||
|
||||
class ClientAPI : public RestClient {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class ReadyCheckState : uint32_t {
|
||||
INVALID = 0,
|
||||
|
@ -37,7 +39,7 @@ public:
|
|||
ENDOFGAME,
|
||||
TERMINATEDINERROR,
|
||||
};
|
||||
static GameflowPhase toGameflowPhase(const std::string&);
|
||||
static GameflowPhase toGameflowPhase(const QString&);
|
||||
|
||||
enum class ChampSelectPhase : uint32_t {
|
||||
INVALID = 0,
|
||||
|
@ -46,7 +48,7 @@ public:
|
|||
BAN_PICK,
|
||||
FINALIZATION
|
||||
};
|
||||
static ChampSelectPhase toChampSelectPhase(const std::string& str);
|
||||
static ChampSelectPhase toChampSelectPhase(const QString& str);
|
||||
|
||||
enum class ChampSelectActionType : uint32_t {
|
||||
INVALID = 0,
|
||||
|
@ -54,7 +56,7 @@ public:
|
|||
PICK,
|
||||
TEN_BANS_REVEAL,
|
||||
};
|
||||
static ChampSelectActionType toChampSelectActionType(const std::string& str);
|
||||
static ChampSelectActionType toChampSelectActionType(const QString& str);
|
||||
|
||||
struct TimerInfo {
|
||||
int64_t adjustedTimeLeftInPhase = 0;
|
||||
|
@ -71,12 +73,12 @@ public:
|
|||
|
||||
struct PlayerInfo {
|
||||
int64_t summonerid = 0; // to test validity -> test if this is not null
|
||||
std::string gameName;
|
||||
std::string name;
|
||||
std::string statusMessage;
|
||||
QString gameName;
|
||||
QString name;
|
||||
QString statusMessage;
|
||||
|
||||
// lol specific
|
||||
std::string puuid;
|
||||
QString puuid;
|
||||
uint32_t level = 0;
|
||||
};
|
||||
|
||||
|
@ -139,7 +141,7 @@ public:
|
|||
struct RunePage {
|
||||
uint64_t id = 0;
|
||||
uint64_t lastmodified = 0;
|
||||
std::string name;
|
||||
QString name;
|
||||
bool isDeleteable = true;
|
||||
bool isEditable = true;
|
||||
bool isActive = false; // what is the difference between active and current????
|
||||
|
@ -153,30 +155,30 @@ public:
|
|||
};
|
||||
|
||||
struct Message {
|
||||
std::string body;
|
||||
std::string fromId;
|
||||
std::string fromPid;
|
||||
QString body;
|
||||
QString fromId;
|
||||
QString fromPid;
|
||||
int64_t fromSummonerId;
|
||||
std::string id;
|
||||
QString id;
|
||||
bool isHistorical;
|
||||
std::string timestamp;
|
||||
std::string type; // known types: chat (1:1), customGame, championSelect, groupchat
|
||||
QString timestamp;
|
||||
QString type; // known types: chat (1:1), customGame, championSelect, groupchat
|
||||
|
||||
Message();
|
||||
explicit Message(const QJsonObject& json);
|
||||
};
|
||||
|
||||
struct Conversation {
|
||||
std::string gameName;
|
||||
std::string gameTag;
|
||||
std::string id;
|
||||
QString gameName;
|
||||
QString gameTag;
|
||||
QString id;
|
||||
bool isMuted;
|
||||
std::shared_ptr<Message> lastMessage;
|
||||
std::string name;
|
||||
std::string password;
|
||||
std::string pid;
|
||||
std::string targetRegion;
|
||||
std::string type;
|
||||
QString name;
|
||||
QString password;
|
||||
QString pid;
|
||||
QString targetRegion;
|
||||
QString type;
|
||||
int64_t unreadMessageCount;
|
||||
|
||||
Conversation();
|
||||
|
@ -201,7 +203,7 @@ public:
|
|||
|
||||
// chats
|
||||
std::vector<Conversation> getAllConversations();
|
||||
Message sendMessage(const std::string& chatid, const std::string& messagebody);
|
||||
Message sendMessage(const QString& chatid, const QString& messagebody);
|
||||
|
||||
// rune stuff
|
||||
RunePage getCurrentRunePage();
|
||||
|
@ -214,7 +216,7 @@ public:
|
|||
std::vector<RuneAspekt> getAllRuneAspekts();
|
||||
std::vector<RuneStyle> getAllRuneStyles();
|
||||
|
||||
const std::string& getRuneStyleByID(uint32_t id);
|
||||
const QString& getRuneStyleByID(uint32_t id);
|
||||
|
||||
QPixmap getImageResource(QString path);
|
||||
|
||||
|
@ -225,7 +227,13 @@ private:
|
|||
DataDragonImageCache imageCache;
|
||||
};
|
||||
|
||||
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::ChampSelectActionType&);
|
||||
#define DEFINEOPERATOR(CLASS) \
|
||||
std::ostream& operator<<(std::ostream&, const ClientAPI::CLASS&); \
|
||||
QDebug operator<<(QDebug, const ClientAPI::CLASS&);
|
||||
|
||||
DEFINEOPERATOR(ReadyCheckState);
|
||||
DEFINEOPERATOR(GameflowPhase);
|
||||
DEFINEOPERATOR(ChampSelectPhase);
|
||||
DEFINEOPERATOR(ChampSelectActionType);
|
||||
|
||||
#undef DEFINEOPERATOR
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
StageConfig(const QJsonObject&);
|
||||
operator QJsonObject() const;
|
||||
|
||||
std::vector<std::string> champs;
|
||||
std::vector<QString> champs;
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
RootConfig& getConfig();
|
||||
private:
|
||||
std::string configFolderPath;
|
||||
std::string configFilePath;
|
||||
QString configFolderPath;
|
||||
QString configFilePath;
|
||||
RootConfig root;
|
||||
};
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
#include <QPixmap>
|
||||
|
@ -15,11 +14,15 @@
|
|||
#include "memoryimagecache.h"
|
||||
#include "restclient.h"
|
||||
|
||||
class QThread;
|
||||
|
||||
class DataDragon : public RestClient {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using notifyImgfunc_t = std::function<void(QPixmap)>;
|
||||
|
||||
DataDragon(const std::string& locale);
|
||||
DataDragon(const QString& locale);
|
||||
~DataDragon();
|
||||
DataDragon(const DataDragon&) = delete;
|
||||
DataDragon& operator=(const DataDragon&) = delete;
|
||||
|
@ -29,11 +32,11 @@ public:
|
|||
ChampData();
|
||||
ChampData(const QJsonObject& source);
|
||||
|
||||
std::string name;
|
||||
std::string id;
|
||||
QString name;
|
||||
QString id;
|
||||
int key = 0;
|
||||
std::string partype;
|
||||
std::string title;
|
||||
QString partype;
|
||||
QString title;
|
||||
};
|
||||
|
||||
enum class ImageType {
|
||||
|
@ -43,42 +46,54 @@ public:
|
|||
};
|
||||
|
||||
// might block until version is available
|
||||
const std::string& getVersion();
|
||||
const QString& getVersion();
|
||||
// might block until champ data is available
|
||||
const std::vector<ChampData>& getChamps();
|
||||
// might block until image is downloaded
|
||||
QPixmap getImage(const std::string& champid, ImageType imgtype = ImageType::SQUARE, bool writeMemcache = true);
|
||||
void getImageAsnyc(const std::string& champid, notifyImgfunc_t func, ImageType imgtype = ImageType::SQUARE);
|
||||
QPixmap getImage(const QString& champid, ImageType imgtype = ImageType::SQUARE, bool writeMemcache = true);
|
||||
void getImageAsnyc(const QString& 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);
|
||||
const ChampData& getBestMatchingChamp(const QString& name, int* count = nullptr);
|
||||
std::vector<const ChampData*> getMatchingChamp(const QString& name, uint32_t limit = 25);
|
||||
const ChampData* getChampByID(uint32_t id);
|
||||
|
||||
std::vector<uint32_t> resolveChampIDs(const std::vector<std::string>& champnames);
|
||||
std::vector<uint32_t> resolveChampIDs(const std::vector<QString>& champnames);
|
||||
|
||||
void startThread();
|
||||
|
||||
static const ChampData EMPTYCHAMP;
|
||||
protected:
|
||||
std::string getImageUrl(const std::string& champid, ImageType type);
|
||||
std::string getCDNString() const;
|
||||
|
||||
void prefetchChampImage(const std::string& champid, ImageType imgtype = ImageType::SQUARE);
|
||||
public slots:
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
// loading progress in 0.0 - 1.0
|
||||
void loading(float);
|
||||
|
||||
// which champion is currently prefretched
|
||||
void fetchingChamp(QString);
|
||||
|
||||
protected:
|
||||
QString getImageUrl(const QString& champid, ImageType type);
|
||||
QString getCDNString() const;
|
||||
|
||||
void prefetchChampImage(const QString& champid, ImageType imgtype = ImageType::SQUARE);
|
||||
void getVersionInternal();
|
||||
void getChampsInternal();
|
||||
void startThread();
|
||||
void stopThread();
|
||||
void stopAndJoinThread();
|
||||
void threadLoop();
|
||||
|
||||
std::string locale;
|
||||
std::string version;
|
||||
QString locale;
|
||||
QString version;
|
||||
std::vector<ChampData> champs;
|
||||
std::mutex cachedatamutex;
|
||||
std::condition_variable cachedatacv;
|
||||
std::set<std::string> notDownloadedImages; // the champions of which the square image is not downloaded yet. Is used to download them on idle
|
||||
std::set<QString> notDownloadedImages; // the champions of which the square image is not downloaded yet. Is used to download them on idle
|
||||
|
||||
private:
|
||||
struct Task {
|
||||
std::string champid;
|
||||
QString champid;
|
||||
notifyImgfunc_t func;
|
||||
ImageType type;
|
||||
};
|
||||
|
@ -90,7 +105,7 @@ private:
|
|||
std::list<Task> tasks;
|
||||
std::mutex tasksmutex;
|
||||
std::condition_variable tasksnotemptycv;
|
||||
std::thread bgthread;
|
||||
QThread* bgthread;
|
||||
bool shouldrun = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QPixmap>
|
||||
|
||||
class DataDragonImageCache {
|
||||
public:
|
||||
DataDragonImageCache(const std::string& folderextra, const std::string& imageext = ".jpg");
|
||||
DataDragonImageCache(const QString& folderextra, const QString& imageext = ".jpg");
|
||||
~DataDragonImageCache();
|
||||
|
||||
bool hasImage(const std::string& name);
|
||||
QPixmap getImage(const std::string& name);
|
||||
void addImageRaw(const QByteArray& arr, const std::string& name);
|
||||
bool hasImage(const QString& name);
|
||||
QPixmap getImage(const QString& name);
|
||||
void addImageRaw(const QByteArray& arr, const QString& name);
|
||||
private:
|
||||
std::string getFilepath(const std::string& name) const;
|
||||
QString getFilepath(const QString& name) const;
|
||||
|
||||
std::string cacheDir;
|
||||
std::string imageext; // file extention including dot
|
||||
QString cacheDir;
|
||||
QString imageext; // file extention including dot
|
||||
};
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
// stuff required for file handling
|
||||
|
||||
#include <string>
|
||||
#include <QString>
|
||||
|
||||
// create a directory and its parents
|
||||
bool mkdirs(const std::string& path);
|
||||
bool mkdirs(const QString& path);
|
||||
|
||||
// get $HOME or a useful default value
|
||||
std::string getHome();
|
||||
QString getHome();
|
||||
|
||||
// folder for caching example: $HOME/.cache/lolautoaccept/
|
||||
std::string getCache();
|
||||
QString getCache();
|
||||
|
|
|
@ -22,7 +22,7 @@ template<>
|
|||
uint64_t convert(const QJsonValue& val);
|
||||
|
||||
template<>
|
||||
std::string convert(const QJsonValue& val);
|
||||
QString convert(const QJsonValue& val);
|
||||
|
||||
template<>
|
||||
bool convert(const QJsonValue& val);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef LOADINGWINDOW_H
|
||||
#define LOADINGWINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QCloseEvent;
|
||||
|
||||
namespace Ui {
|
||||
class LoadingWindow;
|
||||
}
|
||||
|
||||
class LoadingWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LoadingWindow( QWidget* parent = nullptr );
|
||||
~LoadingWindow();
|
||||
|
||||
public slots:
|
||||
void setChampion(QString championName);
|
||||
void setText(QString text);
|
||||
|
||||
// should be 0.0 to 1.0
|
||||
void setProgress(float val);
|
||||
|
||||
signals:
|
||||
void closed();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent*) override;
|
||||
|
||||
private:
|
||||
Ui::LoadingWindow* ui;
|
||||
};
|
||||
|
||||
#endif // LOADINGWINDOW_H
|
|
@ -16,8 +16,6 @@
|
|||
class LolAutoAccept : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using onruneschange_func = std::function<void(const RunePage&)>;
|
||||
protected:
|
||||
struct Stage {
|
||||
Stage();
|
||||
|
@ -33,10 +31,10 @@ protected:
|
|||
Position currentPosition = Position::INVALID;
|
||||
bool currentPositionSet = false;
|
||||
uint32_t lastPickedChamp = 0;
|
||||
int32_t lastCellId = -1; // last cellid -> if changed -> reset
|
||||
|
||||
Config::RootConfig& config;
|
||||
DataDragon& dd;
|
||||
onruneschange_func onRuneschange;
|
||||
|
||||
bool shouldrun = false;
|
||||
std::thread lolaathread;
|
||||
|
@ -51,9 +49,9 @@ protected:
|
|||
bool smiteWarnEnabled = true;
|
||||
bool autoWriteTextEnabled = false;
|
||||
bool autoWriteTextDone = false;
|
||||
std::string autoWriteText;
|
||||
QString autoWriteText;
|
||||
|
||||
std::string chatid; // the chatid of the chat from the champselect
|
||||
QString chatid; // the chatid of the chat from the champselect
|
||||
std::chrono::time_point<std::chrono::system_clock> lastMessageSent;
|
||||
|
||||
public:
|
||||
|
@ -70,7 +68,7 @@ public:
|
|||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
LolAutoAccept(Config::RootConfig& config, DataDragon& dd, onruneschange_func = {}, QObject* parent = nullptr);
|
||||
LolAutoAccept(Config::RootConfig& config, DataDragon& dd, QObject* parent = nullptr);
|
||||
virtual ~LolAutoAccept();
|
||||
|
||||
void setChamps(const std::vector<uint32_t>& champs, State s);
|
||||
|
@ -86,9 +84,7 @@ public:
|
|||
|
||||
const std::vector<RuneAspekt>& getRuneAspekts();
|
||||
const std::vector<RuneStyle>& getRuneStyles();
|
||||
void applyRunes();
|
||||
void setOnRuneChangeFunc(onruneschange_func on);
|
||||
void setAutoWriteText(bool enabled, const std::string& text = {});
|
||||
void setAutoWriteText(bool enabled, const QString& text = {});
|
||||
|
||||
signals:
|
||||
void statusChanged(LolAutoAccept::Status); // new status: 0 = off, 1 = on, 2 = failed
|
||||
|
@ -97,8 +93,8 @@ signals:
|
|||
private:
|
||||
void stopJoinThread();
|
||||
void innerRun();
|
||||
void resetPickOffsets();
|
||||
void resetAllOffsets();
|
||||
void resetRunes(); // when there is no option to push runes, make sure there is an update to trigger that, there are no runes showed
|
||||
void applyConfigToStage(Stage& stage, const Config::StageConfig& stageconf);
|
||||
void loadPosition(Position pos);
|
||||
|
||||
|
@ -118,8 +114,7 @@ private:
|
|||
static int32_t getMatchingRunePage(const RunePage& rp, const std::vector<ClientAPI::RunePage>& allpages);
|
||||
void champSelect();
|
||||
void smiteWarning(const std::vector<ClientAPI::ChampSelectCell>& cells);
|
||||
const std::string& getChatid();
|
||||
void applyRunes_internal(uint32_t champid, Position pos);
|
||||
const QString& getChatid();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(LolAutoAccept::Status)
|
||||
|
|
|
@ -14,6 +14,8 @@ QT_END_NAMESPACE
|
|||
|
||||
class QTimer;
|
||||
|
||||
class LoadingWindow;
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
@ -32,6 +34,8 @@ public slots:
|
|||
void resetSaveTimer();
|
||||
|
||||
private slots:
|
||||
void loadingStatus(float);
|
||||
|
||||
void toggleMainswitch(bool);
|
||||
void aatoggled(bool);
|
||||
void smitewarntoggled(bool);
|
||||
|
@ -39,7 +43,6 @@ private slots:
|
|||
void tabtoggled(Position, LolAutoAccept::State, bool);
|
||||
void tabchanged(Position, LolAutoAccept::State);
|
||||
|
||||
void applyRunes();
|
||||
void autoWriteChanged();
|
||||
|
||||
void saveConfig();
|
||||
|
@ -53,11 +56,11 @@ private:
|
|||
bool loading;
|
||||
Ui::MainWindow *ui;
|
||||
QTimer* saveTimer;
|
||||
QTimer* initDoneTimer;
|
||||
std::thread lolaathread;
|
||||
DataDragon dd;
|
||||
Config conf;
|
||||
LolAutoAccept lolaa;
|
||||
LoadingWindow* lwin;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
|
||||
class MemoryImageCache {
|
||||
public:
|
||||
MemoryImageCache(size_t maxsize = 25);
|
||||
|
||||
void addImage(QPixmap, const std::string& title, int type);
|
||||
QPixmap getImage(const std::string& title, int type);
|
||||
void addImage(QPixmap, const QString& title, int type);
|
||||
QPixmap getImage(const QString& title, int type);
|
||||
private:
|
||||
void cleanUp();
|
||||
|
||||
struct CachedImage {
|
||||
time_t lastaccessed = 0;
|
||||
QPixmap imageref;
|
||||
std::string title;
|
||||
QString title;
|
||||
int type;
|
||||
|
||||
bool operator<(const CachedImage& other) const;
|
||||
};
|
||||
static std::function<bool(const CachedImage&)> getImageMatcher(const std::string& title, int type);
|
||||
static std::function<bool(const CachedImage&)> getImageMatcher(const QString& title, int type);
|
||||
|
||||
std::list<CachedImage> cache;
|
||||
size_t maxsize;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QVariant>
|
||||
|
||||
|
||||
enum class Position : uint32_t {
|
||||
INVALID = 0,
|
||||
TOP,
|
||||
|
@ -11,10 +11,11 @@ enum class Position : uint32_t {
|
|||
BOTTOM,
|
||||
UTILITY
|
||||
};
|
||||
Position toPosition(const std::string& str);
|
||||
std::string toString(Position p);
|
||||
std::string toShortString(Position p);
|
||||
Position toPosition(const QString& str);
|
||||
QString toString(Position p);
|
||||
QString toShortString(Position p);
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const Position&);
|
||||
QDebug operator<<(QDebug , const Position&);
|
||||
|
||||
Q_DECLARE_METATYPE(Position);
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <QJsonDocument>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QString>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#undef DELETE
|
||||
#endif
|
||||
|
||||
|
||||
class RestClient {
|
||||
class RestClient : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RestClient(const std::string& base);
|
||||
RestClient(const QString& base);
|
||||
RestClient(const RestClient&) = delete;
|
||||
virtual ~RestClient();
|
||||
|
||||
|
@ -30,19 +34,21 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
QByteArray requestRaw(const std::string& url, Method m = Method::GET, const std::string& data = {});
|
||||
QJsonDocument request(const std::string& url, Method m = Method::GET, const std::string& data = {});
|
||||
QByteArray requestRaw(const QString& url, Method m = Method::GET, const QString& data = {});
|
||||
QJsonDocument request(const QString& url, Method m = Method::GET, const QString& data = {});
|
||||
void enableDebugging(bool enabled = true);
|
||||
std::string escape(const std::string& in) const;
|
||||
QString escape(const QString& in) const;
|
||||
|
||||
std::string baseurl;
|
||||
QString baseurl;
|
||||
|
||||
CURL* curl = nullptr; // the curl (does curling)
|
||||
|
||||
std::string basicauth; // basic auth code (user:pw) or empty string to disable
|
||||
QString basicauth; // basic auth code (user:pw) or empty string to disable
|
||||
#ifdef WIN32
|
||||
bool disableCertCheck = true;
|
||||
#else
|
||||
bool disableCertCheck = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
const char* toString(RestClient::Method);
|
||||
|
|
|
@ -7,11 +7,11 @@ class QJsonObject;
|
|||
|
||||
struct RuneAspekt {
|
||||
uint32_t id = 0;
|
||||
std::string name;
|
||||
std::string shortDesc;
|
||||
std::string longDesc;
|
||||
std::string tooltip;
|
||||
std::string iconPath;
|
||||
QString name;
|
||||
QString shortDesc;
|
||||
QString longDesc;
|
||||
QString tooltip;
|
||||
QString iconPath;
|
||||
|
||||
RuneAspekt();
|
||||
explicit RuneAspekt(const QJsonObject& json);
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Ui {
|
|||
class RuneAspektButton;
|
||||
}
|
||||
|
||||
class RuneAspektButtonGroup;
|
||||
class RuneAspektButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -15,29 +16,27 @@ public:
|
|||
explicit RuneAspektButton(QWidget* parent = nullptr);
|
||||
~RuneAspektButton();
|
||||
|
||||
void setAspektsVector(std::vector<uint32_t>& aspekts);
|
||||
void setAspketSlot(int slot);
|
||||
void setAspektId(uint32_t id);
|
||||
void setButtonGroup(RuneAspektButtonGroup* group);
|
||||
|
||||
bool isSelected() const;
|
||||
|
||||
signals:
|
||||
void aspektToggled(bool newState);
|
||||
void aspektToggled(int aspekt);
|
||||
|
||||
public slots:
|
||||
void buttonPressed();
|
||||
void dataChanged();
|
||||
void dataChanged(); // triggers a refresh
|
||||
void checkSelection(uint32_t aspekt); // only used for rune styles
|
||||
|
||||
private slots:
|
||||
void setShowSelection(bool selected); // show/hide the red border
|
||||
|
||||
public:
|
||||
uint32_t aspektId = 0;
|
||||
int aspektSlot = -1;
|
||||
|
||||
private:
|
||||
Ui::RuneAspektButton* ui;
|
||||
|
||||
std::vector<uint32_t>* aspekts = nullptr;
|
||||
RuneAspektButtonGroup* group = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
class RuneAspektButton;
|
||||
class RuneAspektButtonGroup : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RuneAspektButtonGroup(QObject* parent, uint32_t size);
|
||||
virtual ~RuneAspektButtonGroup();
|
||||
|
||||
void addButton(RuneAspektButton* button);
|
||||
void setSelectedRunes(const QVector<int>& newRunes);
|
||||
|
||||
constexpr const QVector<int>& getSelectedRunes() const { return selectedRune; }
|
||||
constexpr uint32_t getSize() const { return size; }
|
||||
|
||||
void setSubgroups(const QVector<QVector<int>>& newSubgroups);
|
||||
|
||||
static const int INVALID_ASPEKT_ID;
|
||||
signals:
|
||||
void changed(); // signal that the group was changed -> all buttons should refresh
|
||||
|
||||
private slots:
|
||||
void buttonPressed(int aspektId);
|
||||
|
||||
private:
|
||||
// try to fetch a aspektId, that is in selectedRune and in the same subgroup as aspektId
|
||||
// return 0 when no suitable candidate is found
|
||||
int getOtherSubgroupMemeber(int aspketId);
|
||||
|
||||
QVector<int> selectedRune;
|
||||
QVector<QVector<int>> subgroups; // might be empty
|
||||
uint32_t size = 0;
|
||||
};
|
|
@ -29,8 +29,8 @@ signals:
|
|||
|
||||
private:
|
||||
void updateText();
|
||||
std::string getRuneText(uint32_t id);
|
||||
std::string getRuneStyleByID(uint32_t id);
|
||||
QString getRuneText(uint32_t id);
|
||||
QString getRuneStyleByID(uint32_t id);
|
||||
|
||||
Ui::RuneDisplay *ui;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QVector>
|
||||
|
||||
#include "runeaspekt.h"
|
||||
#include "runepage.h"
|
||||
|
@ -14,6 +15,7 @@ namespace Ui {
|
|||
|
||||
class ClientAPI;
|
||||
class RuneAspektButton;
|
||||
class RuneAspektButtonGroup;
|
||||
class QGridLayout;
|
||||
|
||||
class RuneEditor : public QDialog {
|
||||
|
@ -34,20 +36,20 @@ public:
|
|||
void setName(QString text);
|
||||
QString getName() const;
|
||||
|
||||
constexpr const RunePage& getRunepage() const { return runepage; }
|
||||
const RunePage& getRunepage();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private slots:
|
||||
void aspectCliecked();
|
||||
void selectPrimary(int aspektId);
|
||||
void selectSecondary(int aspektId);
|
||||
|
||||
private:
|
||||
const RuneStyle* getRuneStyle(uint32_t id) const;
|
||||
RuneAspektButton* createStyleButton(const RuneStyle& rs, bool selected);
|
||||
RuneAspektButton* createAspektButton(const RuneAspekt& ra);
|
||||
RuneAspektButton* createAspektButton(uint32_t perk);
|
||||
RuneAspektButton* createButtonFromResource(QString resource);
|
||||
void fillRuneStyle(QGridLayout* target, const RuneStyle& rs, bool subRunes = false);
|
||||
void fillRuneStyle(QGridLayout* target, const RuneStyle& rs);
|
||||
QString fixString(QString text);
|
||||
|
||||
Ui::RuneEditor* ui;
|
||||
|
@ -56,4 +58,8 @@ private:
|
|||
::RunePage runepage;
|
||||
std::vector<RuneAspekt> aspekts;
|
||||
std::vector<RuneStyle> styles;
|
||||
|
||||
|
||||
// 0 = keystone, 1-3 = main runes, 4 = sub runes (2), 5-7 = stats
|
||||
QVector<RuneAspektButtonGroup*> groups;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
// represents a runepage
|
||||
struct RunePage {
|
||||
|
@ -22,3 +23,4 @@ public:
|
|||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const RunePage&);
|
||||
QDebug operator<<(QDebug, const RunePage&);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "clientapi.h"
|
||||
#include "config.h"
|
||||
#include "datadragon.h"
|
||||
#include "runeaspekt.h"
|
||||
#include "runestyle.h"
|
||||
|
||||
|
@ -13,7 +14,6 @@ namespace Ui {
|
|||
class RunePageList;
|
||||
}
|
||||
|
||||
class DataDragon;
|
||||
class DropEvent;
|
||||
class ClientAPI;
|
||||
|
||||
|
@ -56,6 +56,7 @@ private slots:
|
|||
private:
|
||||
void clearItems();
|
||||
void addRunepageItem(QString name, int id, const ::RunePage& rp, bool isCurrent = false);
|
||||
const DataDragon::ChampData& findChamp(const QString& name);
|
||||
|
||||
QString getRuneDescription(const ::RunePage& runepage);
|
||||
QString getRuneText(uint32_t id);
|
||||
|
|
|
@ -18,9 +18,9 @@ struct RuneStyleSlot {
|
|||
|
||||
struct RuneStyle {
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
std::string iconPath;
|
||||
std::string tooltip;
|
||||
QString name;
|
||||
QString iconPath;
|
||||
QString tooltip;
|
||||
|
||||
std::vector<int> allowedSubStyles;
|
||||
QString idName;
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
std::vector<StageSettings::SelectedChamp> getChamps(LolAutoAccept::State s) const;
|
||||
bool getState(LolAutoAccept::State s) const;
|
||||
void setChamps(LolAutoAccept::State s, const std::vector<std::string>&);
|
||||
void setChamps(LolAutoAccept::State s, const std::vector<QString>&);
|
||||
void setState(LolAutoAccept::State s, bool b);
|
||||
|
||||
Position getPosition() const;
|
||||
|
|
|
@ -27,13 +27,13 @@ public:
|
|||
void setState(bool);
|
||||
|
||||
struct SelectedChamp {
|
||||
SelectedChamp(std::string name, uint32_t id);
|
||||
std::string name;
|
||||
SelectedChamp(QString name, uint32_t id);
|
||||
QString name;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
std::vector<SelectedChamp> getChampions() const;
|
||||
void setChampions(const std::vector<std::string>& champs);
|
||||
void setChampions(const std::vector<QString>& champs);
|
||||
|
||||
void setDataDragon(DataDragon* dd);
|
||||
void addChamp(const DataDragon::ChampData& cd, QPixmap icon);
|
||||
|
@ -52,7 +52,7 @@ signals:
|
|||
|
||||
private:
|
||||
// delete all items
|
||||
void resolveAndAddChamp(const std::string& name, bool emitchange = false);
|
||||
void resolveAndAddChamp(const QString& name, bool emitchange = false);
|
||||
void clear();
|
||||
void updateEnabled();
|
||||
|
||||
|
|
|
@ -49,12 +49,14 @@ SOURCES += \
|
|||
src/datadragonimagecache.cpp \
|
||||
src/files.cpp \
|
||||
src/json.cpp \
|
||||
src/loadingwindow.cpp \
|
||||
src/lolautoaccept.cpp \
|
||||
src/main.cpp \
|
||||
src/mainwindow.cpp \
|
||||
src/memoryimagecache.cpp \
|
||||
src/restclient.cpp \
|
||||
src/runeaspektbutton.cpp \
|
||||
src/runeaspektbuttongroup.cpp \
|
||||
src/runedisplay.cpp \
|
||||
src/runeeditor.cpp \
|
||||
src/runemanager.cpp \
|
||||
|
@ -83,11 +85,13 @@ HEADERS += \
|
|||
include/defer.h \
|
||||
include/files.h \
|
||||
include/json.h \
|
||||
include/loadingwindow.h \
|
||||
include/lolautoaccept.h \
|
||||
include/mainwindow.h \
|
||||
include/memoryimagecache.h \
|
||||
include/restclient.h \
|
||||
include/runeaspektbutton.h \
|
||||
include/runeaspektbuttongroup.h \
|
||||
include/runedisplay.h \
|
||||
include/runeeditor.h \
|
||||
include/runemanager.h \
|
||||
|
@ -100,6 +104,7 @@ HEADERS += \
|
|||
FORMS += \
|
||||
ui/championsearch.ui \
|
||||
ui/clipboardpopup.ui \
|
||||
ui/loadingwindow.ui \
|
||||
ui/mainwindow.ui \
|
||||
ui/runeaspektbutton.ui \
|
||||
ui/runedisplay.ui \
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// query=query ChampionBuilds($championId:Int!,$queue:Queue!,$role:Role,$opponentChampionId:Int,$key:ChampionBuildKey){championBuildStats(championId:$championId,queue:$queue,role:$role,opponentChampionId:$opponentChampionId,key:$key){championId opponentChampionId queue role builds{completedItems{games index averageIndex itemId wins}games mythicId mythicAverageIndex primaryRune runes{games index runeId wins treeId}skillOrders{games skillOrder wins}startingItems{games startingItemIds wins}summonerSpells{games summonerSpellIds wins}wins}}}
|
||||
// &variables={"championId":25,"role":"SUPPORT","queue":"RANKED_SOLO_5X5","opponentChampionId":null,"key":"PUBLIC"}
|
||||
|
||||
static const std::string POSITIONNAMES[] = {"INVALID", "TOP", "JUNGLE", "MIDDLE", "BOTTOM", "SUPPORT"};
|
||||
static const QString POSITIONNAMES[] = {"INVALID", "TOP", "JUNGLE", "MIDDLE", "BOTTOM", "SUPPORT"};
|
||||
|
||||
BlitzAPI::BlitzAPI() : RestClient("https://league-champion-aggregate.iesdev.com/graphql?") {}
|
||||
|
||||
|
@ -58,7 +58,7 @@ BlitzAPI::ChampionInfo::ChampionInfo(const QJsonObject& json) {
|
|||
auto runeid = rune["runeId"];
|
||||
if(runeid.isDouble()) {
|
||||
runes.at(index+1) = runeid.toDouble();
|
||||
Log::debug << "found rune: index: " << index << " +1 set to: " << runes.at(index+1);
|
||||
qDebug() << "found rune: index: " << index << " +1 set to: " << runes.at(index+1);
|
||||
|
||||
if(index == 0) {
|
||||
runepage.primaryStyle = rune["treeId"].toInt();
|
||||
|
@ -80,7 +80,7 @@ BlitzAPI::ChampionInfo BlitzAPI::getChampionInfo(uint32_t championID, Position p
|
|||
|
||||
vars["championId"] = (int) championID;
|
||||
if(p != Position::INVALID) {
|
||||
vars["role"] = QString::fromStdString(POSITIONNAMES[(int) p]);
|
||||
vars["role"] = POSITIONNAMES[(int) p];
|
||||
}
|
||||
vars["queue"] = "RANKED_SOLO_5X5";
|
||||
|
||||
|
@ -91,10 +91,10 @@ BlitzAPI::ChampionInfo BlitzAPI::getChampionInfo(uint32_t championID, Position p
|
|||
vars["key"] = "PUBLIC"; // ? what does this do?
|
||||
|
||||
QJsonDocument jvars(vars);
|
||||
const std::string variables = jvars.toJson(QJsonDocument::Compact).toStdString();
|
||||
const std::string query = "query ChampionBuilds($championId:Int!,$queue:Queue!,$role:Role,$opponentChampionId:Int,$key:ChampionBuildKey){championBuildStats(championId:$championId,queue:$queue,role:$role,opponentChampionId:$opponentChampionId,key:$key){championId opponentChampionId queue role builds{completedItems{games index averageIndex itemId wins}games mythicId mythicAverageIndex primaryRune runes{games index runeId wins treeId}skillOrders{games skillOrder wins}startingItems{games startingItemIds wins}summonerSpells{games summonerSpellIds wins}wins}}}";
|
||||
const std::string requeststr = "query=" + escape(query) + "&variables=" + escape(variables);
|
||||
Log::debug << "GetChampionInfo requestVariables: " << variables << " requeststr: " << requeststr;
|
||||
const QString variables = jvars.toJson(QJsonDocument::Compact);
|
||||
const QString query = "query ChampionBuilds($championId:Int!,$queue:Queue!,$role:Role,$opponentChampionId:Int,$key:ChampionBuildKey){championBuildStats(championId:$championId,queue:$queue,role:$role,opponentChampionId:$opponentChampionId,key:$key){championId opponentChampionId queue role builds{completedItems{games index averageIndex itemId wins}games mythicId mythicAverageIndex primaryRune runes{games index runeId wins treeId}skillOrders{games skillOrder wins}startingItems{games startingItemIds wins}summonerSpells{games summonerSpellIds wins}wins}}}";
|
||||
const QString requeststr = "query=" + escape(query) + "&variables=" + escape(variables);
|
||||
qDebug() << "GetChampionInfo requestVariables: " << variables << " requeststr: " << requeststr;
|
||||
|
||||
QJsonDocument doc;
|
||||
try {
|
||||
|
@ -105,11 +105,11 @@ BlitzAPI::ChampionInfo BlitzAPI::getChampionInfo(uint32_t championID, Position p
|
|||
|
||||
if(!doc.isObject()) {
|
||||
// error
|
||||
Log::error << "could not get ChampionInfo. Returned Response: " << doc.toJson().toStdString();
|
||||
qCritical() << "could not get ChampionInfo. Returned Response: " << doc.toJson();
|
||||
return {};
|
||||
}
|
||||
|
||||
Log::debug << "championinfo Response: " << doc.toJson().trimmed().toStdString();
|
||||
qDebug() << "championinfo Response: " << doc.toJson().trimmed();
|
||||
|
||||
QJsonObject obj = doc.object();
|
||||
QJsonValueRef dataref = obj["data"];
|
||||
|
|
|
@ -18,17 +18,17 @@ static qint64 ageOfFile(QFile& f) {
|
|||
return info.lastModified().secsTo(QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
std::string ChampCache::getVersion() {
|
||||
QFile versionfile(QString::fromStdString(basefolder + "version"));
|
||||
QString ChampCache::getVersion() {
|
||||
QFile versionfile(basefolder + "version");
|
||||
if(ageOfFile(versionfile) < (qint64) maxage) {
|
||||
versionfile.open(QFile::ReadOnly);
|
||||
return versionfile.readAll().toStdString();
|
||||
return versionfile.readAll();
|
||||
}
|
||||
return {}; // empty string
|
||||
}
|
||||
|
||||
QJsonDocument ChampCache::getChamps() {
|
||||
QFile champsfile(QString::fromStdString(basefolder + "champs.json"));
|
||||
QFile champsfile(basefolder + "champs.json");
|
||||
|
||||
if(ageOfFile(champsfile) < (qint64) maxage) {
|
||||
champsfile.open(QFile::ReadOnly);
|
||||
|
@ -39,16 +39,16 @@ QJsonDocument ChampCache::getChamps() {
|
|||
return {}; // empty document
|
||||
}
|
||||
|
||||
void ChampCache::saveChamps(QJsonDocument doc, const std::string& version) {
|
||||
void ChampCache::saveChamps(QJsonDocument doc, const QString& version) {
|
||||
QByteArray arr = doc.toJson();
|
||||
QFile champsfile(QString::fromStdString(basefolder + "champs.json"));
|
||||
QFile champsfile(basefolder + "champs.json");
|
||||
champsfile.open(QFile::WriteOnly | QFile::Truncate);
|
||||
champsfile.write(arr);
|
||||
|
||||
QFile versionfile(QString::fromStdString(basefolder + "version"));
|
||||
QFile versionfile(basefolder + "version");
|
||||
versionfile.open(QFile::WriteOnly | QFile::Truncate);
|
||||
versionfile.write(version.c_str());
|
||||
versionfile.write(version.toLocal8Bit());
|
||||
versionfile.close();
|
||||
|
||||
Log::info << "saved Champs and version Cache";
|
||||
qInfo() << "saved Champs and version Cache";
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ ChampRow* ChampionSearch::getSearchResult() {
|
|||
}
|
||||
|
||||
void ChampionSearch::searchChanged(QString str) {
|
||||
Log::info << "champion search: " << str.toStdString();
|
||||
qInfo() << "champion search: " << str;
|
||||
|
||||
const std::vector<const DataDragon::ChampData*> champs = dd->getMatchingChamp(str.toStdString());
|
||||
Log::info << "found " << champs.size() << " champs";
|
||||
const std::vector<const DataDragon::ChampData*> champs = dd->getMatchingChamp(str);
|
||||
qInfo() << "found " << champs.size() << " champs";
|
||||
|
||||
clear();
|
||||
|
||||
|
|
|
@ -7,14 +7,12 @@ ChampRow::~ChampRow() {
|
|||
}
|
||||
|
||||
void ChampRow::setChamp(const DataDragon::ChampData& cd, QPixmap icon) {
|
||||
setText(QString::fromStdString(cd.name));
|
||||
setText(cd.name);
|
||||
champid = cd.key;
|
||||
this->icon = icon;
|
||||
setIcon(QIcon(icon));
|
||||
|
||||
#define QS(A) arg(QString::fromStdString(A))
|
||||
setToolTip(QWidget::tr("Champion: %1\nType: %2\nTitle: %3\nID: %4").QS(cd.name).QS(cd.partype).QS(cd.title).arg(cd.key));
|
||||
#undef QS
|
||||
setToolTip(QWidget::tr("Champion: %1\nType: %2\nTitle: %3\nID: %4").arg(cd.name).arg(cd.partype).arg(cd.title).arg(cd.key));
|
||||
}
|
||||
|
||||
QString ChampRow::getChamp() const {
|
||||
|
|
|
@ -2,39 +2,39 @@
|
|||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <Log.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
|
||||
ClientAccess::ClientAccess() {}
|
||||
|
||||
ClientAccess::ClientAccess(const std::string& token, uint16_t port) : authcode(token), port(port) {}
|
||||
ClientAccess::ClientAccess(const QString& token, uint16_t port) : authcode(token), port(port) {}
|
||||
|
||||
std::shared_ptr<ClientAccess> createFromLockfile(std::istream& lockfile) {
|
||||
std::vector<std::string> parts;
|
||||
|
||||
std::string content;
|
||||
while(std::getline(lockfile, content, ':')) {
|
||||
parts.push_back(content);
|
||||
}
|
||||
std::getline(lockfile, content);
|
||||
QStringList parts = QString::fromStdString(content).split(':');
|
||||
|
||||
if(parts.size() != 5) {
|
||||
Log::error << "lockfile contained " << parts.size() << " parts, expected 5";
|
||||
qCritical() << "lockfile contained " << parts.size() << " parts, expected 5";
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string portstr = parts.at(2);
|
||||
const std::string token = parts.at(3);
|
||||
const QString portstr = parts.at(2);
|
||||
const QString token = parts.at(3);
|
||||
|
||||
// try to parse port
|
||||
try {
|
||||
uint16_t port = std::stoi(portstr);
|
||||
|
||||
return std::shared_ptr<ClientAccess>(new ClientAccess(token, port));
|
||||
} catch(std::exception& e) {
|
||||
Log::error << "could not parse port: " << std::quoted(portstr);
|
||||
bool success = false;
|
||||
uint16_t port = portstr.toUInt(&success);
|
||||
if(!success) {
|
||||
qCritical() << "could not parse port: " << portstr;
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
return std::shared_ptr<ClientAccess>(new ClientAccess(token, port));
|
||||
}
|
||||
|
||||
std::string ClientAccess::getBasicAuth() const {
|
||||
QString ClientAccess::getBasicAuth() const {
|
||||
return "riot:" + authcode;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,6 @@ uint16_t ClientAccess::getPort() const {
|
|||
return port;
|
||||
}
|
||||
|
||||
std::string ClientAccess::getURL() const {
|
||||
return "https://127.0.0.1:" + std::to_string(port) + "/";
|
||||
QString ClientAccess::getURL() const {
|
||||
return "https://127.0.0.1:" + QString::number(port) + "/";
|
||||
}
|
||||
|
|
|
@ -19,27 +19,29 @@
|
|||
|
||||
#include "defer.h"
|
||||
|
||||
static const std::string CLIENTNAME = "LeagueClientUx.exe"; // returns the name and value of a argument or empty string if it could not be parsed
|
||||
static const QString CLIENTNAME = "LeagueClientUx.exe"; // returns the name and value of a argument or empty string if it could not be parsed
|
||||
|
||||
static std::shared_ptr<ClientAccess> findUsingLockfile(const std::vector<std::string>& cmdline, pid_t pid);
|
||||
|
||||
static bool endsWith(const std::string& all, const std::string& end) {
|
||||
return all.size() >= end.size() && all.rfind(end) == all.size() - end.size();
|
||||
}
|
||||
static std::shared_ptr<ClientAccess> findUsingLockfile(const std::vector<QString>& cmdline, pid_t pid);
|
||||
|
||||
// reads a procfile into a vector (strings are \0 seperated)
|
||||
static std::vector<std::string> readProcFile(const std::string& path) {
|
||||
std::ifstream in(path);
|
||||
std::vector<std::string> out;
|
||||
static std::vector<QString> readProcFile(const QString& path) {
|
||||
std::ifstream in(path.toStdString());
|
||||
std::vector<QString> out;
|
||||
std::string line;
|
||||
while(std::getline(in, line, '\0')) {
|
||||
if(!line.empty()) {
|
||||
out.push_back(line);
|
||||
out.push_back(QString::fromStdString(line));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// test server
|
||||
#if 0
|
||||
std::shared_ptr<ClientAccess> ClientAccess::find() {
|
||||
return std::make_shared<ClientAccess>("password", 4443);
|
||||
}
|
||||
#else
|
||||
std::shared_ptr<ClientAccess> ClientAccess::find() {
|
||||
|
||||
DIR* procdir = opendir("/proc");
|
||||
|
@ -51,27 +53,27 @@ std::shared_ptr<ClientAccess> ClientAccess::find() {
|
|||
while ((entry = readdir(procdir)) != NULL) {
|
||||
if (entry->d_type != DT_DIR) continue;
|
||||
|
||||
std::string name(entry->d_name);
|
||||
QString name(entry->d_name);
|
||||
|
||||
pid_t pid = -1;
|
||||
try {
|
||||
pid = std::stoi(name);
|
||||
} catch(std::exception& e) {
|
||||
bool success = false;
|
||||
pid = name.toULong(&success);
|
||||
if(!success) {
|
||||
// could not parse -> not a pid
|
||||
continue;
|
||||
}
|
||||
|
||||
// get info on the exe
|
||||
std::string cmdfile = "/proc/" + std::to_string(pid) + "/cmdline";
|
||||
std::vector<std::string> args = readProcFile(cmdfile);
|
||||
QString cmdfile = "/proc/" + QString::number(pid) + "/cmdline";
|
||||
std::vector<QString> args = readProcFile(cmdfile);
|
||||
|
||||
// Log::debug << "process: " << pid << " has " << args.size() << " args";
|
||||
// qDebug() << "process: " << pid << " has " << args.size() << " args";
|
||||
|
||||
if(args.empty()) continue;
|
||||
|
||||
std::string& exename = args.at(0);
|
||||
if(endsWith(exename, CLIENTNAME)) {
|
||||
Log::info << CLIENTNAME << " found: " << exename;
|
||||
QString& exename = args.at(0);
|
||||
if(exename.endsWith(CLIENTNAME)) {
|
||||
qInfo() << CLIENTNAME << " found: " << exename;
|
||||
|
||||
std::shared_ptr<ClientAccess> out;
|
||||
|
||||
|
@ -85,33 +87,34 @@ std::shared_ptr<ClientAccess> ClientAccess::find() {
|
|||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::shared_ptr<ClientAccess> findUsingLockfile(const std::vector<std::string>& cmdline, pid_t pid) {
|
||||
std::shared_ptr<ClientAccess> findUsingLockfile(const std::vector<QString>& cmdline, pid_t pid) {
|
||||
// get WINEPREFIX env
|
||||
std::vector<std::string> envs = readProcFile("/proc/" + std::to_string(pid) + "/environ");
|
||||
std::vector<QString> envs = readProcFile("/proc/" + QString::number(pid) + "/environ");
|
||||
|
||||
const static std::string WINEPREFIX = "WINEPREFIX=";
|
||||
const static QString WINEPREFIX = "WINEPREFIX=";
|
||||
|
||||
// find WINEPREFIX
|
||||
auto found = std::find_if(envs.begin(), envs.end(), [](const std::string& s) {
|
||||
return s.find(WINEPREFIX) == 0;
|
||||
auto found = std::find_if(envs.begin(), envs.end(), [](const QString& s) {
|
||||
return s.startsWith(WINEPREFIX);
|
||||
});
|
||||
|
||||
// WINEPREFIX env not present
|
||||
if(found == envs.end()) {
|
||||
Log::debug << "WINEPREFIX environment variable not set";
|
||||
qDebug() << "WINEPREFIX environment variable not set";
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string wineprefix = found->substr(WINEPREFIX.size());
|
||||
const std::string binarypath = cmdline.at(0);
|
||||
std::string gamefolder = binarypath.substr(2, binarypath.rfind('/')-1); // remove the "C:" and the name of the binary
|
||||
const QString wineprefix = found->remove(0, WINEPREFIX.size());
|
||||
const QString binarypath = cmdline.at(0);
|
||||
QString gamefolder = binarypath.mid(2, binarypath.lastIndexOf('/')-1); // remove the "C:" and the name of the binary
|
||||
// TODO: gamefoldre could contain '\' so replacing every occurance with '/' would be a good idea
|
||||
const std::string lockfilepath = wineprefix + "/drive_c/" + gamefolder + "/lockfile";
|
||||
const QString lockfilepath = wineprefix + "/drive_c/" + gamefolder + "/lockfile";
|
||||
|
||||
Log::debug << "lockfilepath: " << std::quoted(lockfilepath);
|
||||
qDebug() << "lockfilepath: " << lockfilepath;
|
||||
|
||||
// read lockfile
|
||||
std::ifstream lockfile(lockfilepath);
|
||||
std::ifstream lockfile(lockfilepath.toStdString());
|
||||
return createFromLockfile(lockfile);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
#include "defer.h"
|
||||
|
||||
static const std::string CLIENTNAME = "LeagueClientUx.exe";
|
||||
static const QString CLIENTNAME = "LeagueClientUx.exe";
|
||||
|
||||
static std::string narrow(WCHAR* str, size_t len) {
|
||||
std::string out;
|
||||
static QString narrow(WCHAR* str, size_t len) {
|
||||
QString out;
|
||||
out.reserve(len);
|
||||
for(uint32_t i = 0; i < len && str[i]; ++i) {
|
||||
out.append(1, (char) str[i]);
|
||||
|
@ -27,11 +27,11 @@ static std::string narrow(WCHAR* str, size_t len) {
|
|||
return out;
|
||||
}
|
||||
|
||||
static std::string getProcessPath(DWORD dwPID) {
|
||||
static QString getProcessPath(DWORD dwPID) {
|
||||
// Take a snapshot of all modules in the specified process.
|
||||
HANDLE hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
|
||||
if(hModuleSnap == INVALID_HANDLE_VALUE) {
|
||||
Log::error << "CreateToolhelp32Snapshot (of modules) failed";
|
||||
qCritical() << "CreateToolhelp32Snapshot (of modules) failed";
|
||||
return {}; // empty string
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ static std::string getProcessPath(DWORD dwPID) {
|
|||
// Retrieve information about the first module,
|
||||
// and exit if unsuccessful
|
||||
if( !Module32First( hModuleSnap, &me32 ) ) {
|
||||
Log::error << "Module32First";
|
||||
qCritical() << "Module32First";
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -52,15 +52,15 @@ static std::string getProcessPath(DWORD dwPID) {
|
|||
}
|
||||
|
||||
static std::shared_ptr<ClientAccess> findUsingLockfile(PROCESSENTRY32& proc) {
|
||||
const std::string exepath = getProcessPath(proc.th32ProcessID);
|
||||
const QString exepath = getProcessPath(proc.th32ProcessID);
|
||||
Log::note << "exepath: " << exepath;
|
||||
|
||||
// lockfile path
|
||||
const std::string lockfilepath = exepath.substr(0, exepath.rfind('\\')+1) + "lockfile"; // possible out of bounds
|
||||
Log::debug << "Lockfile: " << lockfilepath;
|
||||
const QString lockfilepath = exepath.substr(0, exepath.rfind('\\')+1) + "lockfile"; // possible out of bounds
|
||||
qDebug() << "Lockfile: " << lockfilepath;
|
||||
std::ifstream lockfile(lockfilepath);
|
||||
if(!lockfile) {
|
||||
Log::error << "lockfile could not be opend";
|
||||
qCritical() << "lockfile could not be opend";
|
||||
return nullptr;
|
||||
}
|
||||
return createFromLockfile(lockfile);
|
||||
|
@ -72,7 +72,7 @@ std::shared_ptr<ClientAccess> ClientAccess::find() {
|
|||
// Take a snapshot of all processes in the system.
|
||||
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hProcessSnap == INVALID_HANDLE_VALUE) {
|
||||
Log::error << "CreateToolhelp32Snapshot (of processes) failed";
|
||||
qCritical() << "CreateToolhelp32Snapshot (of processes) failed";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -85,18 +85,18 @@ std::shared_ptr<ClientAccess> ClientAccess::find() {
|
|||
// Retrieve information about the first process,
|
||||
// and exit if unsuccessful
|
||||
if (!Process32First(hProcessSnap, &pe32)) {
|
||||
Log::error << "Process32First failed"; // show cause of failure
|
||||
qCritical() << "Process32First failed"; // show cause of failure
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Now walk the snapshot of processes, and
|
||||
// display information about each process in turn
|
||||
do {
|
||||
std::string exename = narrow((WCHAR*) pe32.szExeFile, sizeof(pe32.szExeFile));
|
||||
QString exename = narrow((WCHAR*) pe32.szExeFile, sizeof(pe32.szExeFile));
|
||||
// Log::note << "found process: " << exename;
|
||||
|
||||
if(exename == CLIENTNAME) {
|
||||
Log::info << CLIENTNAME << " found";
|
||||
qInfo() << CLIENTNAME << " found";
|
||||
|
||||
std::shared_ptr<ClientAccess> out;
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ ClientAPI::GameflowPhase ClientAPI::getGameflowPhase() {
|
|||
// it is just a json-string no object
|
||||
QByteArray data = requestRaw("lol-gameflow/v1/gameflow-phase");
|
||||
|
||||
std::string datastr = data.toStdString();
|
||||
QString datastr = QString::fromLocal8Bit(data);
|
||||
if (data.size() > 2) {
|
||||
datastr = datastr.substr(1, datastr.size() -2);
|
||||
datastr = datastr.mid(1, datastr.size() -2);
|
||||
|
||||
return toGameflowPhase(datastr);
|
||||
}
|
||||
|
@ -63,25 +63,25 @@ bool ClientAPI::setChampSelectAction(int32_t actionid, int32_t champid, bool com
|
|||
requestj["completed"] = completed;
|
||||
requestj["id"] = actionid;
|
||||
QJsonDocument requestdoc(requestj);
|
||||
const std::string requeststr = requestdoc.toJson(QJsonDocument::JsonFormat::Compact).toStdString();
|
||||
Log::debug << "requeststr: " << requeststr;
|
||||
QJsonDocument doc = request("lol-champ-select/v1/session/actions/" + std::to_string(actionid), Method::PATCH, requeststr);
|
||||
const QString requeststr = QString::fromLocal8Bit(requestdoc.toJson(QJsonDocument::JsonFormat::Compact));
|
||||
qDebug().noquote() << "requeststr: " << requeststr;
|
||||
QJsonDocument doc = request("lol-champ-select/v1/session/actions/" + QString::number(actionid), Method::PATCH, requeststr);
|
||||
|
||||
std::string error;
|
||||
QString error;
|
||||
if(doc.isObject()) {
|
||||
QJsonObject obj = doc.object();
|
||||
auto errref = obj["errorCode"];
|
||||
auto msgref = obj["message"];
|
||||
if(errref.isString()) {
|
||||
error = errref.toString().toStdString() + " ";
|
||||
error = errref.toString() + " ";
|
||||
}
|
||||
if(msgref.isString()) {
|
||||
error += msgref.toString().toStdString();
|
||||
error += msgref.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Log::note << "patching action: " << actionid << " error: " << error;
|
||||
return error.empty();
|
||||
qDebug() << "patching action: " << actionid << " error: " << error;
|
||||
return error.isEmpty();
|
||||
}
|
||||
|
||||
ClientAPI::PlayerInfo ClientAPI::getSelf() {
|
||||
|
@ -91,15 +91,15 @@ ClientAPI::PlayerInfo ClientAPI::getSelf() {
|
|||
QJsonObject obj = doc.object();
|
||||
|
||||
PlayerInfo info;
|
||||
info.gameName = getValue<std::string>(obj, "gameName");
|
||||
info.name = getValue<std::string>(obj, "name");
|
||||
info.statusMessage = getValue<std::string>(obj, "statusMessage", "");
|
||||
info.gameName = getValue<QString>(obj, "gameName");
|
||||
info.name = getValue<QString>(obj, "name");
|
||||
info.statusMessage = getValue<QString>(obj, "statusMessage", "");
|
||||
info.summonerid = getValue<uint64_t>(obj, "summonerId");
|
||||
|
||||
auto lolref = obj["lol"];
|
||||
if(lolref.isObject()) {
|
||||
QJsonObject lol = lolref.toObject();
|
||||
info.puuid = getValue<std::string>(lol, "puuid");
|
||||
info.puuid = getValue<QString>(lol, "puuid");
|
||||
info.level = getValue<int32_t>(lol, "level");
|
||||
}
|
||||
|
||||
|
@ -165,32 +165,32 @@ std::vector<ClientAPI::Conversation> ClientAPI::getAllConversations() {
|
|||
return out;
|
||||
}
|
||||
|
||||
ClientAPI::Message ClientAPI::sendMessage(const std::string& chatid, const std::string& messagebody) {
|
||||
ClientAPI::Message ClientAPI::sendMessage(const QString& chatid, const QString& messagebody) {
|
||||
QJsonObject requestj;
|
||||
requestj["body"] = QString::fromStdString(messagebody);
|
||||
requestj["body"] = messagebody;
|
||||
QJsonDocument requestdoc(requestj);
|
||||
const std::string requeststr = requestdoc.toJson(QJsonDocument::JsonFormat::Compact).toStdString();
|
||||
Log::debug << "requeststr: " << requeststr;
|
||||
const QString requeststr = QString::fromLocal8Bit(requestdoc.toJson(QJsonDocument::JsonFormat::Compact));
|
||||
qDebug().noquote() << "requeststr: " << requeststr;
|
||||
QJsonDocument doc = request("lol-chat/v1/conversations/" + chatid + "/messages", Method::POST, requeststr);
|
||||
|
||||
std::string error;
|
||||
QString error;
|
||||
if(doc.isObject()) {
|
||||
QJsonObject obj = doc.object();
|
||||
auto errref = obj["errorCode"];
|
||||
auto msgref = obj["message"];
|
||||
if(errref.isString()) {
|
||||
error = errref.toString().toStdString() + " ";
|
||||
error = errref.toString() + " ";
|
||||
}
|
||||
if(msgref.isString()) {
|
||||
error += msgref.toString().toStdString();
|
||||
error += msgref.toString();
|
||||
}
|
||||
|
||||
if(error.empty()) {
|
||||
if(error.isEmpty()) {
|
||||
return (Message) obj;
|
||||
}
|
||||
}
|
||||
|
||||
Log::note << "send message error: " << error;
|
||||
qDebug() << "send message error: " << error;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -220,12 +220,12 @@ std::vector<ClientAPI::RunePage> ClientAPI::getAllRunePages() {
|
|||
}
|
||||
|
||||
bool ClientAPI::selectRunePage(uint64_t id) {
|
||||
QJsonDocument doc = request("lol-perks/v1/currentpage", Method::PUT, std::to_string(id));
|
||||
QJsonDocument doc = request("lol-perks/v1/currentpage", Method::PUT, QString::number(id));
|
||||
|
||||
if(doc.isEmpty()) return true; // ok
|
||||
|
||||
// error
|
||||
qWarning() << "error selecting runepage: " << id << " " << doc.toJson().toStdString();
|
||||
qWarning() << "error selecting runepage: " << id << " " << doc.toJson();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ bool ClientAPI::selectRunePage(uint64_t id) {
|
|||
bool ClientAPI::editRunePage(const RunePage& page) {
|
||||
QJsonObject pagereq;
|
||||
|
||||
pagereq["name"] = QString::fromStdString(page.name);
|
||||
pagereq["name"] = page.name;
|
||||
pagereq["primaryStyleId"] = (int) page.runepage.primaryStyle;
|
||||
pagereq["subStyleId"] = (int) page.runepage.secondaryStyle;
|
||||
|
||||
|
@ -245,14 +245,14 @@ bool ClientAPI::editRunePage(const RunePage& page) {
|
|||
pagereq["selectedPerkIds"] = selected;
|
||||
|
||||
QJsonDocument reqdoc(pagereq);
|
||||
const std::string requestdocstr = reqdoc.toJson(QJsonDocument::JsonFormat::Compact).toStdString();
|
||||
qInfo() << "requeststr: " << requestdocstr;
|
||||
QJsonDocument doc = request("lol-perks/v1/pages/" + std::to_string(page.id), Method::PUT, requestdocstr);
|
||||
const QString requestdocstr = QString::fromLocal8Bit(reqdoc.toJson(QJsonDocument::JsonFormat::Compact));
|
||||
qInfo().noquote() << "requeststr: " << requestdocstr;
|
||||
QJsonDocument doc = request("lol-perks/v1/pages/" + QString::number(page.id), Method::PUT, requestdocstr);
|
||||
|
||||
if(doc.isEmpty()) return true; // ok
|
||||
|
||||
// error
|
||||
qWarning() << "error editing runepage: " << page.id << " " << doc.toJson().toStdString();
|
||||
qWarning() << "error editing runepage: " << page.id << " " << doc.toJson();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ bool ClientAPI::editRunePage(const RunePage& page) {
|
|||
bool ClientAPI::createRunePage(const RunePage& page) {
|
||||
QJsonObject pagereq;
|
||||
|
||||
pagereq["name"] = QString::fromStdString(page.name);
|
||||
pagereq["name"] = page.name;
|
||||
pagereq["primaryStyleId"] = (int) page.runepage.primaryStyle;
|
||||
pagereq["subStyleId"] = (int) page.runepage.secondaryStyle;
|
||||
|
||||
|
@ -272,25 +272,25 @@ bool ClientAPI::createRunePage(const RunePage& page) {
|
|||
pagereq["selectedPerkIds"] = selected;
|
||||
|
||||
QJsonDocument reqdoc(pagereq);
|
||||
const std::string requestdocstr = reqdoc.toJson(QJsonDocument::JsonFormat::Compact).toStdString();
|
||||
const QString requestdocstr = reqdoc.toJson(QJsonDocument::JsonFormat::Compact);
|
||||
qInfo() << "requeststr: " << requestdocstr;
|
||||
QJsonDocument doc = request("lol-perks/v1/pages/", Method::POST, requestdocstr);
|
||||
|
||||
if(doc.isEmpty()) return true; // ok
|
||||
|
||||
// error
|
||||
qWarning() << "error creating runepage: " << page.name << " " << doc.toJson().toStdString();
|
||||
qWarning() << "error creating runepage: " << page.name << " " << doc.toJson();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientAPI::deleteRunePage(uint64_t id) {
|
||||
QJsonDocument doc = request("lol-perks/v1/pages/" + std::to_string(id), Method::DELETE);
|
||||
QJsonDocument doc = request("lol-perks/v1/pages/" + QString::number(id), Method::DELETE);
|
||||
|
||||
if(doc.isEmpty()) return true; // ok
|
||||
|
||||
// error
|
||||
qWarning() << "error deleteing runepage: " << id << " " << doc.toJson().toStdString();
|
||||
qWarning() << "error deleteing runepage: " << id << " " << doc.toJson();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -336,26 +336,26 @@ std::vector<RuneStyle> ClientAPI::getAllRuneStyles() {
|
|||
QPixmap ClientAPI::getImageResource(QString path) {
|
||||
if(path.isEmpty()) return {};
|
||||
|
||||
std::string simplePath;
|
||||
QString simplePath;
|
||||
{
|
||||
QString simplePathQ = path;
|
||||
simplePath = simplePathQ.replace('/', '_').toStdString();
|
||||
simplePath = simplePathQ.replace('/', '_');
|
||||
}
|
||||
|
||||
// query mem cache
|
||||
QPixmap img = memImageCache.getImage(path.toStdString(), 0);
|
||||
QPixmap img = memImageCache.getImage(path, 0);
|
||||
if(!img.isNull()) return img;
|
||||
|
||||
// query HDD cache
|
||||
img = imageCache.getImage(simplePath);
|
||||
if(!img.isNull()) {
|
||||
// update mem cache
|
||||
memImageCache.addImage(img, path.toStdString(), 0);
|
||||
memImageCache.addImage(img, path, 0);
|
||||
return img;
|
||||
}
|
||||
|
||||
qInfo() << "requesting: " << path;
|
||||
QByteArray arr = requestRaw(path.toStdString());
|
||||
QByteArray arr = requestRaw(path);
|
||||
QPixmap out;
|
||||
out.loadFromData(arr);
|
||||
|
||||
|
@ -363,7 +363,7 @@ QPixmap ClientAPI::getImageResource(QString path) {
|
|||
imageCache.addImageRaw(arr, simplePath);
|
||||
|
||||
// store memchache
|
||||
memImageCache.addImage(out, path.toStdString(), 0);
|
||||
memImageCache.addImage(out, path, 0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "clientapi.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
@ -10,7 +9,7 @@
|
|||
|
||||
// calculate the size of a constant sized array
|
||||
#define ARRSIZE(ARRNAME) (sizeof(ARRNAME) / sizeof(ARRNAME[0]))
|
||||
#define ARR(NAME, ...) static const std::string NAME ## Names[] = {__VA_ARGS__}; \
|
||||
#define ARR(NAME, ...) static const QString NAME ## Names[] = {__VA_ARGS__}; \
|
||||
static const uint32_t NAME ## NamesCount = ARRSIZE(NAME ## Names);
|
||||
|
||||
ARR(ReadyCheckState, "Invalid", "None", "InProgress", "Accepted", "Declined");
|
||||
|
@ -21,8 +20,8 @@ ARR(ShortPosition, "", "Top", "Jgl", "Mid", "Bot", "Sup");
|
|||
ARR(ChampSelectActionType, "Invalid", "ban", "pick", "ten_bans_reveal");
|
||||
|
||||
template<typename T>
|
||||
static T mapEnum(const std::string& input, const std::string* names, uint32_t count, T defaul) {
|
||||
if(input.empty()) return defaul;
|
||||
static T mapEnum(const QString& input, const QString* names, uint32_t count, T defaul) {
|
||||
if(input.isEmpty()) return defaul;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (names[i] == input) {
|
||||
|
@ -30,7 +29,7 @@ static T mapEnum(const std::string& input, const std::string* names, uint32_t co
|
|||
}
|
||||
}
|
||||
|
||||
Log::warn << "no mapping of enum-string: " << std::quoted(input) << " using default: " << defaul << " type: " << typeid(T).name();
|
||||
qWarning() << "no mapping of enum-string: " << input << " using default: " << defaul << " type: " << typeid(T).name();
|
||||
return defaul;
|
||||
}
|
||||
|
||||
|
@ -50,8 +49,8 @@ static std::vector<T> readVector(QJsonArray arr) {
|
|||
}
|
||||
|
||||
ClientAPI::ReadyCheckState ClientAPI::toReadyCheckState(const QJsonObject& obj) {
|
||||
std::string searchState = getValue<std::string>(obj, "state", "Invalid");
|
||||
std::string playerresponse = getValue<std::string>(obj, "playerResponse", "None");
|
||||
QString searchState = getValue<QString>(obj, "state", "Invalid");
|
||||
QString playerresponse = getValue<QString>(obj, "playerResponse", "None");
|
||||
|
||||
ClientAPI::ReadyCheckState response = MAPENUM(playerresponse, ReadyCheckState, NONE);
|
||||
|
||||
|
@ -65,27 +64,27 @@ ClientAPI::ReadyCheckState ClientAPI::toReadyCheckState(const QJsonObject& obj)
|
|||
return response;
|
||||
}
|
||||
|
||||
ClientAPI::GameflowPhase ClientAPI::toGameflowPhase(const std::string& str) {
|
||||
ClientAPI::GameflowPhase ClientAPI::toGameflowPhase(const QString& str) {
|
||||
return MAPENUM(str, GameflowPhase, NONE);
|
||||
}
|
||||
|
||||
ClientAPI::ChampSelectPhase ClientAPI::toChampSelectPhase(const std::string& str) {
|
||||
ClientAPI::ChampSelectPhase ClientAPI::toChampSelectPhase(const QString& str) {
|
||||
return MAPENUM(str, ChampSelectPhase, INVALID);
|
||||
}
|
||||
|
||||
Position toPosition(const std::string& str) {
|
||||
Position toPosition(const QString& str) {
|
||||
return mapEnum(str, PositionNames, PositionNamesCount, Position::INVALID);
|
||||
}
|
||||
|
||||
std::string toString(Position p) {
|
||||
QString toString(Position p) {
|
||||
return PositionNames[(int) p];
|
||||
}
|
||||
|
||||
std::string toShortString(Position p) {
|
||||
QString toShortString(Position p) {
|
||||
return ShortPositionNames[(int) p];
|
||||
}
|
||||
|
||||
ClientAPI::ChampSelectActionType ClientAPI::toChampSelectActionType(const std::string& str) {
|
||||
ClientAPI::ChampSelectActionType ClientAPI::toChampSelectActionType(const QString& str) {
|
||||
return MAPENUM(str, ChampSelectActionType, INVALID);
|
||||
}
|
||||
|
||||
|
@ -95,7 +94,7 @@ ClientAPI::TimerInfo::TimerInfo(const QJsonObject& obj) {
|
|||
internalNowInEpochMs = getValue<int64_t>(obj, "internalNowInEpochMs", 0);
|
||||
isefinite = getValue<bool>(obj, "isefinite", 0);
|
||||
|
||||
phase = MAPENUM(getValue<std::string>(obj, "phase", "Invalid"), ChampSelectPhase, INVALID);
|
||||
phase = MAPENUM(getValue<QString>(obj, "phase", "Invalid"), ChampSelectPhase, INVALID);
|
||||
|
||||
totalTimeInPhase = getValue<int64_t>(obj, "totalTimeInPhase", 0);
|
||||
}
|
||||
|
@ -108,13 +107,13 @@ ClientAPI::ChampSelectAction::ChampSelectAction(const QJsonObject& json) {
|
|||
id = getValue<int32_t>(json, "id");
|
||||
isAllyAction = getValue<bool>(json, "isAllyAction");
|
||||
isInProgress = getValue<bool>(json, "isInProgress");
|
||||
const std::string typestr = getValue<std::string>(json, "type", "Invalid");
|
||||
const QString typestr = getValue<QString>(json, "type", "Invalid");
|
||||
type = toChampSelectActionType(typestr);
|
||||
}
|
||||
|
||||
ClientAPI::ChampSelectCell::ChampSelectCell() {}
|
||||
ClientAPI::ChampSelectCell::ChampSelectCell(const QJsonObject& json) {
|
||||
position = toPosition(getValue<std::string>(json, "assignedPosition"));
|
||||
position = toPosition(getValue<QString>(json, "assignedPosition"));
|
||||
cellID = getValue<int32_t>(json, "cellId");
|
||||
championID = getValue<int32_t>(json, "championId");
|
||||
championPickIntentID = getValue<int32_t>(json, "championPickIntent");
|
||||
|
@ -195,7 +194,7 @@ ClientAPI::RunePage::RunePage(const QJsonObject& json) {
|
|||
lastmodified = getValue<int64_t>(json, "lastModified", 0);
|
||||
runepage.primaryStyle = getValue<int32_t>(json, "primaryStyleId", 0);
|
||||
runepage.secondaryStyle = getValue<int32_t>(json, "subStyleId", 0);
|
||||
name = getValue<std::string>(json, "name");
|
||||
name = getValue<QString>(json, "name");
|
||||
isDeleteable = getValue<bool>(json, "isDeletable", false);
|
||||
isEditable = getValue<bool>(json, "isEditable", false);
|
||||
isActive = getValue<bool>(json, "isActive", false);
|
||||
|
@ -222,9 +221,9 @@ RuneStyleSlot::RuneStyleSlot(const QJsonObject& json) {
|
|||
RuneStyle::RuneStyle() {}
|
||||
RuneStyle::RuneStyle(const QJsonObject& json) {
|
||||
id = getValue<int32_t>(json, "id", 0);
|
||||
name = getValue<std::string>(json, "name");
|
||||
iconPath = getValue<std::string>(json, "iconPath");
|
||||
tooltip = getValue<std::string>(json, "tooltip");
|
||||
name = getValue<QString>(json, "name");
|
||||
iconPath = getValue<QString>(json, "iconPath");
|
||||
tooltip = getValue<QString>(json, "tooltip");
|
||||
idName = getValue<QString>(json, "idName");
|
||||
|
||||
auto subStylesRef = json["allowedSubStyles"];
|
||||
|
@ -242,36 +241,36 @@ RuneStyle::RuneStyle(const QJsonObject& json) {
|
|||
RuneAspekt::RuneAspekt() {}
|
||||
RuneAspekt::RuneAspekt(const QJsonObject& json) {
|
||||
id = getValue<int32_t>(json, "id", 0);
|
||||
name = getValue<std::string>(json, "name");
|
||||
shortDesc = getValue<std::string>(json, "shortDesc");
|
||||
longDesc = getValue<std::string>(json, "longDesc");
|
||||
tooltip = getValue<std::string>(json, "tooltip");
|
||||
iconPath = getValue<std::string>(json, "iconPath");
|
||||
name = getValue<QString>(json, "name");
|
||||
shortDesc = getValue<QString>(json, "shortDesc");
|
||||
longDesc = getValue<QString>(json, "longDesc");
|
||||
tooltip = getValue<QString>(json, "tooltip");
|
||||
iconPath = getValue<QString>(json, "iconPath");
|
||||
}
|
||||
|
||||
ClientAPI::Message::Message() {}
|
||||
ClientAPI::Message::Message(const QJsonObject& json) {
|
||||
body = getValue<std::string>(json, "body");
|
||||
fromId = getValue<std::string>(json, "fromId");
|
||||
fromPid = getValue<std::string>(json, "fromPid");
|
||||
body = getValue<QString>(json, "body");
|
||||
fromId = getValue<QString>(json, "fromId");
|
||||
fromPid = getValue<QString>(json, "fromPid");
|
||||
fromSummonerId = getValue<int64_t>(json, "fromSummonerId");
|
||||
id = getValue<std::string>(json, "id");
|
||||
id = getValue<QString>(json, "id");
|
||||
isHistorical = getValue<bool>(json, "isHistorical", true);
|
||||
timestamp = getValue<std::string>(json, "timestamp");
|
||||
type = getValue<std::string>(json, "type");
|
||||
timestamp = getValue<QString>(json, "timestamp");
|
||||
type = getValue<QString>(json, "type");
|
||||
}
|
||||
|
||||
ClientAPI::Conversation::Conversation() {}
|
||||
ClientAPI::Conversation::Conversation(const QJsonObject& json) : lastMessage(nullptr) {
|
||||
gameName = getValue<std::string>(json, "gameName");
|
||||
gameTag = getValue<std::string>(json, "gameTag");
|
||||
id = getValue<std::string>(json, "id");
|
||||
gameName = getValue<QString>(json, "gameName");
|
||||
gameTag = getValue<QString>(json, "gameTag");
|
||||
id = getValue<QString>(json, "id");
|
||||
isMuted = getValue<bool>(json, "isMuted");
|
||||
name = getValue<std::string>(json, "name");
|
||||
password = getValue<std::string>(json, "password");
|
||||
pid = getValue<std::string>(json, "pid");
|
||||
targetRegion = getValue<std::string>(json, "targetRegion");
|
||||
type = getValue<std::string>(json, "type");
|
||||
name = getValue<QString>(json, "name");
|
||||
password = getValue<QString>(json, "password");
|
||||
pid = getValue<QString>(json, "pid");
|
||||
targetRegion = getValue<QString>(json, "targetRegion");
|
||||
type = getValue<QString>(json, "type");
|
||||
unreadMessageCount = getValue<int64_t>(json, "unreadMessageCount");
|
||||
|
||||
auto msgref = json["lastMessage"];
|
||||
|
@ -283,6 +282,11 @@ ClientAPI::Conversation::Conversation(const QJsonObject& json) : lastMessage(nul
|
|||
|
||||
#define PRINTENUM(ENUMNAME) \
|
||||
std::ostream& operator<<(std::ostream& str, const ClientAPI:: ENUMNAME & state) { \
|
||||
assert(((uint32_t) state) < ENUMNAME ## NamesCount); \
|
||||
return str << ENUMNAME ## Names[(uint32_t) state].toStdString() << " (" << (uint32_t) state << ')'; \
|
||||
} \
|
||||
\
|
||||
QDebug operator<<(QDebug str, const ClientAPI:: ENUMNAME & state) { \
|
||||
assert(((uint32_t) state) < ENUMNAME ## NamesCount); \
|
||||
return str << ENUMNAME ## Names[(uint32_t) state] << " (" << (uint32_t) state << ')'; \
|
||||
}
|
||||
|
@ -295,6 +299,11 @@ PRINTENUM(ChampSelectActionType)
|
|||
|
||||
// not using macro because its not in ClientAPI
|
||||
std::ostream& operator<<(std::ostream& str, const Position & state) {
|
||||
assert(((uint32_t) state) < PositionNamesCount);
|
||||
return str << PositionNames[(uint32_t) state].toStdString() << " (" << (uint32_t) state << ')';
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug str, const Position & state) {
|
||||
assert(((uint32_t) state) < PositionNamesCount);
|
||||
return str << PositionNames[(uint32_t) state] << " (" << (uint32_t) state << ')';
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ Config::StageConfig::StageConfig() : enabled(false) {}
|
|||
|
||||
Config::StageConfig::StageConfig(const QJsonObject& j) {
|
||||
if(j["champ"].isString()) {
|
||||
champs.push_back(getValue<std::string>(j, "champ"));
|
||||
champs.push_back(getValue<QString>(j, "champ"));
|
||||
}
|
||||
if(j["champs"].isArray()) {
|
||||
QJsonArray jchamps = j["champs"].toArray();
|
||||
|
@ -27,7 +27,7 @@ Config::StageConfig::StageConfig(const QJsonObject& j) {
|
|||
if(jchamp.isString()) {
|
||||
QString jchampstr = jchamp.toString();
|
||||
if(!jchampstr.isEmpty()) {
|
||||
champs.push_back(jchampstr.toStdString());
|
||||
champs.push_back(jchampstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ Config::StageConfig::operator QJsonObject() const {
|
|||
QJsonObject out;
|
||||
|
||||
QJsonArray jchamps;
|
||||
for(const std::string& champ : champs) {
|
||||
if(!champ.empty()) {
|
||||
jchamps.push_back(QString::fromStdString(champ));
|
||||
for(const QString& champ : champs) {
|
||||
if(!champ.isEmpty()) {
|
||||
jchamps.push_back(champ);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,9 +55,9 @@ Config::PositionConfig::PositionConfig() {}
|
|||
Config::PositionConfig::PositionConfig(const QJsonObject& j) {
|
||||
ban = getValue<Config::StageConfig>(j, "ban");
|
||||
pick = getValue<Config::StageConfig>(j, "pick");
|
||||
position = toPosition(getValue<std::string>(j, "position"));
|
||||
position = toPosition(getValue<QString>(j, "position"));
|
||||
if((int) position < 0 || position > Position::UTILITY) {
|
||||
Log::warn << "invalid config value \"position\"";
|
||||
qWarning() << "invalid config value \"position\"";
|
||||
position = Position::MIDDLE;
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ Config::PositionConfig::operator QJsonObject() const {
|
|||
|
||||
out["ban"] = (QJsonObject) ban;
|
||||
out["pick"] = (QJsonObject) pick;
|
||||
out["position"] = QString::fromStdString(toString(position));
|
||||
out["position"] = toString(position);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ Config::Config() {
|
|||
Config::~Config() {}
|
||||
|
||||
bool Config::load() {
|
||||
QFile conffile(QString::fromStdString(configFilePath));
|
||||
QFile conffile(configFilePath);
|
||||
if(!conffile.open(QIODevice::ReadOnly)) {
|
||||
qCritical() << "could not open configfile: " << configFilePath;
|
||||
return false;
|
||||
|
@ -221,9 +221,9 @@ bool Config::load() {
|
|||
void Config::save() {
|
||||
mkdirs(configFolderPath);
|
||||
|
||||
QFile conffile(QString::fromStdString(configFilePath));
|
||||
QFile conffile(configFilePath);
|
||||
if(!conffile.open(QIODevice::WriteOnly)) {
|
||||
Log::error << "could not open configfile: " << configFilePath;
|
||||
qCritical() << "could not open configfile: " << configFilePath;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,18 +6,20 @@
|
|||
#include <curl/easy.h>
|
||||
#include <Log.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QThread>
|
||||
|
||||
#include <algorithm> // std::max, champ matching
|
||||
|
||||
#include "json.h"
|
||||
|
||||
static const std::string BASEURL = "https://ddragon.leagueoflegends.com/";
|
||||
static const QString BASEURL = "https://ddragon.leagueoflegends.com/";
|
||||
const DataDragon::ChampData DataDragon::EMPTYCHAMP;
|
||||
|
||||
DataDragon::DataDragon(const std::string& locale) : RestClient(BASEURL), locale(locale), cache({{"square", ".png"}, {"loading", "_0.jpg"}, {"splash", "_0.jpg"}}) {
|
||||
startThread();
|
||||
DataDragon::DataDragon(const QString& locale) : RestClient(BASEURL), locale(locale), cache({{"square", ".png"}, {"loading", "_0.jpg"}, {"splash", "_0.jpg"}}) {
|
||||
this->setObjectName("DataDragon");
|
||||
}
|
||||
|
||||
DataDragon::~DataDragon() {
|
||||
|
@ -27,16 +29,16 @@ DataDragon::~DataDragon() {
|
|||
DataDragon::ChampData::ChampData() : key(-1) {}
|
||||
|
||||
DataDragon::ChampData::ChampData(const QJsonObject& source) {
|
||||
name = getValue<std::string>(source, "name", "");
|
||||
id = getValue<std::string>(source, "id", "");
|
||||
name = getValue<QString>(source, "name", "");
|
||||
id = getValue<QString>(source, "id", "");
|
||||
key = getValue<int>(source, "key", -1);
|
||||
partype = getValue<std::string>(source, "partype", "");
|
||||
title = getValue<std::string>(source, "title", "");
|
||||
partype = getValue<QString>(source, "partype", "");
|
||||
title = getValue<QString>(source, "title", "");
|
||||
}
|
||||
|
||||
const std::string& DataDragon::getVersion() {
|
||||
const QString& DataDragon::getVersion() {
|
||||
std::unique_lock lock(cachedatamutex);
|
||||
while(version.empty() && shouldrun) {
|
||||
while(version.isEmpty() && shouldrun) {
|
||||
cachedatacv.wait(lock);
|
||||
}
|
||||
return version;
|
||||
|
@ -50,8 +52,8 @@ const std::vector<DataDragon::ChampData>& DataDragon::getChamps() {
|
|||
return champs;
|
||||
}
|
||||
|
||||
QPixmap DataDragon::getImage(const std::string& champid, ImageType imgtype, bool writeMemcache) {
|
||||
if(champid.empty()) return {};
|
||||
QPixmap DataDragon::getImage(const QString& champid, ImageType imgtype, bool writeMemcache) {
|
||||
if(champid.isEmpty()) return {};
|
||||
|
||||
// query mem cache
|
||||
QPixmap img = memcache.getImage(champid, (int) imgtype);
|
||||
|
@ -65,8 +67,8 @@ QPixmap DataDragon::getImage(const std::string& champid, ImageType imgtype, bool
|
|||
return img;
|
||||
}
|
||||
|
||||
const std::string url = getImageUrl(champid, imgtype);
|
||||
if(url.empty()) return {};
|
||||
const QString url = getImageUrl(champid, imgtype);
|
||||
if(url.isEmpty()) return {};
|
||||
|
||||
|
||||
QByteArray arr;
|
||||
|
@ -74,14 +76,14 @@ QPixmap DataDragon::getImage(const std::string& champid, ImageType imgtype, bool
|
|||
arr = requestRaw(url);
|
||||
} catch(RestClient::WebException& e) {}
|
||||
if(arr.isEmpty()) {
|
||||
Log::error << "image could not be loaded";
|
||||
qCritical() << "image could not be loaded";
|
||||
return {};
|
||||
}
|
||||
|
||||
// propably an error
|
||||
if(arr.size() < 1000) {
|
||||
Log::info << "small icon url: " << url;
|
||||
Log::info << "content: " << std::string(arr.data(), arr.size());
|
||||
qInfo() << "small icon url: " << url;
|
||||
qInfo() << "content: " << QString::fromLocal8Bit(arr);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -102,7 +104,7 @@ QPixmap DataDragon::getImage(const std::string& champid, ImageType imgtype, bool
|
|||
return decodedImage;
|
||||
}
|
||||
|
||||
void DataDragon::getImageAsnyc(const std::string& champid, notifyImgfunc_t func, ImageType imgtype) {
|
||||
void DataDragon::getImageAsnyc(const QString& champid, notifyImgfunc_t func, ImageType imgtype) {
|
||||
if(!func) return;
|
||||
|
||||
{
|
||||
|
@ -112,44 +114,40 @@ void DataDragon::getImageAsnyc(const std::string& champid, notifyImgfunc_t func,
|
|||
tasksnotemptycv.notify_one();
|
||||
}
|
||||
|
||||
static std::string toLower(const std::string& in) {
|
||||
return QString::fromStdString(in).toLower().toStdString();
|
||||
}
|
||||
|
||||
static size_t startinglength(const std::string& original, const std::string& prefix) {
|
||||
size_t i = 0;
|
||||
static int startinglength(const QString& original, const QString& prefix) {
|
||||
int i = 0;
|
||||
for(; i < original.size() && i < prefix.size(); ++i) {
|
||||
if(original.substr(0, i+1) != prefix.substr(0, i+1)) {
|
||||
if(original.left(i+1) != prefix.left(i+1)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t matchChamp(const DataDragon::ChampData& champ, const std::string& lower) {
|
||||
std::string lowerid = toLower(champ.id);
|
||||
std::string lowername = toLower(champ.name);
|
||||
static size_t matchChamp(const DataDragon::ChampData& champ, const QString& lower) {
|
||||
QString lowerid = champ.id.toLower();
|
||||
QString lowername = champ.name.toLower();
|
||||
if(lowerid == lower || lowername == lower) {
|
||||
return lower.size();
|
||||
}
|
||||
|
||||
size_t lengtha = startinglength(lowerid, lower);
|
||||
size_t lengthb = startinglength(lowername, lower);
|
||||
int lengtha = startinglength(lowerid, lower);
|
||||
int lengthb = startinglength(lowername, lower);
|
||||
|
||||
return std::max(lengtha, lengthb);
|
||||
return qMax(lengtha, lengthb);
|
||||
}
|
||||
|
||||
const DataDragon::ChampData& DataDragon::getBestMatchingChamp(const std::string& name, int* count) {
|
||||
const DataDragon::ChampData& DataDragon::getBestMatchingChamp(const QString& name, int* count) {
|
||||
getChamps();
|
||||
// for now: just check for a perfect hit
|
||||
std::string lower = toLower(name);
|
||||
QString lower = name.toLower();
|
||||
int bestmatchingoffset = -1;
|
||||
size_t bestmatchinglength = 0;
|
||||
int bestmatchinglength = 0;
|
||||
uint32_t bestmatchingcount = 0;
|
||||
for(size_t offset = 0; offset < champs.size(); ++offset) {
|
||||
const ChampData& it = champs.at(offset);
|
||||
|
||||
size_t match = matchChamp(it, lower);
|
||||
int match = matchChamp(it, lower);
|
||||
if(match > bestmatchinglength) {
|
||||
bestmatchinglength = match;
|
||||
bestmatchingcount = 1;
|
||||
|
@ -171,12 +169,12 @@ const DataDragon::ChampData& DataDragon::getBestMatchingChamp(const std::string&
|
|||
return EMPTYCHAMP;
|
||||
}
|
||||
|
||||
std::vector<const DataDragon::ChampData*> DataDragon::getMatchingChamp(const std::string& name, uint32_t limit) {
|
||||
std::vector<const DataDragon::ChampData*> DataDragon::getMatchingChamp(const QString& name, uint32_t limit) {
|
||||
if(limit == 0) return {};
|
||||
if(name.empty()) return {};
|
||||
if(name.isEmpty()) return {};
|
||||
|
||||
getChamps();
|
||||
std::string lower = toLower(name);
|
||||
QString lower = name.toLower();
|
||||
|
||||
std::vector<size_t> matches;
|
||||
matches.resize(champs.size());
|
||||
|
@ -212,11 +210,11 @@ const DataDragon::ChampData* DataDragon::getChampByID(uint32_t id) {
|
|||
return &*it;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> DataDragon::resolveChampIDs(const std::vector<std::string>& champnames) {
|
||||
std::vector<uint32_t> DataDragon::resolveChampIDs(const std::vector<QString>& champnames) {
|
||||
std::vector<uint32_t> out;
|
||||
out.reserve(champnames.size());
|
||||
|
||||
std::transform(champnames.begin(), champnames.end(), std::insert_iterator(out, out.begin()), [this](const std::string& champname) {
|
||||
std::transform(champnames.begin(), champnames.end(), std::insert_iterator(out, out.begin()), [this](const QString& champname) {
|
||||
auto cd = getBestMatchingChamp(champname);
|
||||
return cd.key; // might be 0 (invalid)
|
||||
});
|
||||
|
@ -224,10 +222,27 @@ std::vector<uint32_t> DataDragon::resolveChampIDs(const std::vector<std::string>
|
|||
return out;
|
||||
}
|
||||
|
||||
std::string DataDragon::getImageUrl(const std::string& champid, ImageType type) {
|
||||
void DataDragon::startThread() {
|
||||
shouldrun = true;
|
||||
bgthread = QThread::create(&DataDragon::threadLoop, this);
|
||||
bgthread->setObjectName("DataDragonThread");
|
||||
bgthread->start();
|
||||
this->moveToThread(bgthread);
|
||||
}
|
||||
|
||||
void DataDragon::stop() {
|
||||
qDebug() << "stop DataDragon";
|
||||
shouldrun = false;
|
||||
std::unique_lock lock(tasksmutex);
|
||||
|
||||
tasks.clear();
|
||||
notDownloadedImages.clear(); // this is a possible race condition!
|
||||
}
|
||||
|
||||
QString DataDragon::getImageUrl(const QString& champid, ImageType type) {
|
||||
switch(type) {
|
||||
case ImageType::SQUARE: {
|
||||
if(getVersion().empty()) {
|
||||
if(getVersion().isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -244,13 +259,13 @@ std::string DataDragon::getImageUrl(const std::string& champid, ImageType type)
|
|||
return {};
|
||||
}
|
||||
|
||||
std::string DataDragon::getCDNString() const {
|
||||
QString DataDragon::getCDNString() const {
|
||||
return "cdn/" + version + "/";
|
||||
}
|
||||
|
||||
void DataDragon::prefetchChampImage(const std::string& champid, ImageType imgtype) {
|
||||
void DataDragon::prefetchChampImage(const QString& champid, ImageType imgtype) {
|
||||
if(!cache[(int) imgtype].hasImage(champid)) {
|
||||
Log::debug << "prefetch " << champid << " type: " << (int) imgtype;
|
||||
qDebug() << "prefetch " << champid << " type: " << (int) imgtype;
|
||||
getImage(champid, imgtype, false);
|
||||
}
|
||||
}
|
||||
|
@ -258,31 +273,31 @@ void DataDragon::prefetchChampImage(const std::string& champid, ImageType imgtyp
|
|||
void DataDragon::getVersionInternal() {
|
||||
std::unique_lock lock(cachedatamutex);
|
||||
|
||||
if(!version.empty()) return;
|
||||
if(!version.isEmpty()) return;
|
||||
|
||||
version = champCache.getVersion();
|
||||
if(!version.empty()) return;
|
||||
if(!version.isEmpty()) return;
|
||||
|
||||
try {
|
||||
QJsonDocument jversions = request("api/versions.json");
|
||||
if(jversions.isArray()) {
|
||||
QJsonArray jverarr = jversions.array();
|
||||
if(!jverarr.empty()) {
|
||||
version = jverarr.at(0).toString().toStdString();
|
||||
Log::info << "got League version: " << version;
|
||||
version = jverarr.at(0).toString();
|
||||
qInfo() << "got League version: " << version;
|
||||
|
||||
lock.unlock();
|
||||
cachedatacv.notify_all();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log::error << "error parsing version object";
|
||||
qCritical() << "error parsing version object";
|
||||
} catch(RestClient::WebException& e) {}
|
||||
}
|
||||
|
||||
void DataDragon::getChampsInternal() {
|
||||
std::unique_lock lock(cachedatamutex);
|
||||
if(!champs.empty() && version.empty()) {
|
||||
if(!champs.empty() && version.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -316,16 +331,11 @@ void DataDragon::getChampsInternal() {
|
|||
}
|
||||
}
|
||||
}
|
||||
Log::info << "loaded " << champs.size() << " champs from cache: " << cacheSuccessfull;
|
||||
qInfo() << "loaded " << champs.size() << " champs from cache: " << cacheSuccessfull;
|
||||
lock.unlock();
|
||||
cachedatacv.notify_all();
|
||||
}
|
||||
|
||||
void DataDragon::startThread() {
|
||||
shouldrun = true;
|
||||
bgthread = std::thread(&DataDragon::threadLoop, this);
|
||||
}
|
||||
|
||||
void DataDragon::stopThread() {
|
||||
shouldrun = false;
|
||||
tasksnotemptycv.notify_all();
|
||||
|
@ -334,11 +344,12 @@ void DataDragon::stopThread() {
|
|||
void DataDragon::stopAndJoinThread() {
|
||||
stopThread();
|
||||
|
||||
if(bgthread.joinable())
|
||||
bgthread.join();
|
||||
bgthread->wait();
|
||||
}
|
||||
|
||||
void DataDragon::threadLoop() {
|
||||
QEventLoop loop;
|
||||
|
||||
// init version and champ list
|
||||
getVersionInternal();
|
||||
getChampsInternal();
|
||||
|
@ -354,15 +365,18 @@ void DataDragon::threadLoop() {
|
|||
} else {
|
||||
Log::note << "DataDragon background thread is idleing - prefetching champion images TODO: " << notDownloadedImages.size();
|
||||
|
||||
while(!notDownloadedImages.empty() && tasks.empty()) {
|
||||
while(shouldrun && !notDownloadedImages.empty() && tasks.empty()) {
|
||||
lock.unlock();
|
||||
|
||||
auto it = notDownloadedImages.begin();
|
||||
std::string champid = *it;
|
||||
QString champid = *it;
|
||||
notDownloadedImages.erase(it);
|
||||
|
||||
prefetchChampImage(champid, ImageType::SQUARE);
|
||||
|
||||
emit this->loading(1.0 - (notDownloadedImages.size() / (float) champs.size()));
|
||||
emit this->fetchingChamp(champid);
|
||||
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
|
@ -372,24 +386,29 @@ void DataDragon::threadLoop() {
|
|||
if(!once) {
|
||||
once = true;
|
||||
Log::note << "all champs are prefetched now";
|
||||
emit this->loading( 1.0 );
|
||||
}
|
||||
|
||||
tasksnotemptycv.wait(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(tasks.empty()) continue;
|
||||
|
||||
t = tasks.front();
|
||||
tasks.pop_front();
|
||||
}
|
||||
|
||||
loop.processEvents();
|
||||
|
||||
QPixmap img = getImage(t.champid, t.type);
|
||||
t.func(img);
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "DataDragon Thread terminated";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& str, const DataDragon::ChampData& cd) {
|
||||
return str << "[n: " << cd.name << " " << " k: " << cd.key << " id: " << cd.id << "]";
|
||||
return str << "[n: " << cd.name.toStdString() << " " << " k: " << cd.key << " id: " << cd.id.toStdString() << "]";
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "files.h"
|
||||
|
||||
DataDragonImageCache::DataDragonImageCache(const std::string& folderextra, const std::string& imageext) : imageext(imageext) {
|
||||
DataDragonImageCache::DataDragonImageCache(const QString& folderextra, const QString& imageext) : imageext(imageext) {
|
||||
// init cache dir
|
||||
cacheDir = getCache() + folderextra + "/";
|
||||
|
||||
|
@ -15,21 +15,21 @@ DataDragonImageCache::DataDragonImageCache(const std::string& folderextra, const
|
|||
}
|
||||
DataDragonImageCache::~DataDragonImageCache() {}
|
||||
|
||||
bool DataDragonImageCache::hasImage(const std::string& name) {
|
||||
QFile file(QString::fromStdString(getFilepath(name)));
|
||||
bool DataDragonImageCache::hasImage(const QString& name) {
|
||||
QFile file(getFilepath(name));
|
||||
return file.size() > 1024; // a image with less than 1KiB? assume it would be readable (r-Permissions)
|
||||
}
|
||||
|
||||
QPixmap DataDragonImageCache::getImage(const std::string& name) {
|
||||
return QPixmap(QString::fromStdString(getFilepath(name)));
|
||||
QPixmap DataDragonImageCache::getImage(const QString& name) {
|
||||
return QPixmap(getFilepath(name));
|
||||
}
|
||||
|
||||
void DataDragonImageCache::addImageRaw(const QByteArray& arr, const std::string& name) {
|
||||
QFile file(QString::fromStdString(getFilepath(name)));
|
||||
void DataDragonImageCache::addImageRaw(const QByteArray& arr, const QString& name) {
|
||||
QFile file(getFilepath(name));
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(arr);
|
||||
}
|
||||
|
||||
std::string DataDragonImageCache::getFilepath(const std::string& name) const {
|
||||
QString DataDragonImageCache::getFilepath(const QString& name) const {
|
||||
return cacheDir + name + imageext;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <Log.h>
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -11,45 +13,31 @@
|
|||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <QDir>
|
||||
|
||||
bool mkdirs(const std::string& path) {
|
||||
return QDir::root().mkpath(QString::fromStdString(path));
|
||||
}
|
||||
|
||||
std::string getHome() {
|
||||
QString getHome() {
|
||||
const char* homevar = getenv("appdata");
|
||||
if(homevar == nullptr) {
|
||||
Log::warn << "%appdata% is not set! Defaulting to ./";
|
||||
qWarning() << "%appdata% is not set! Defaulting to ./";
|
||||
return "./";
|
||||
}
|
||||
return std::string(homevar) + "/";
|
||||
return QString(homevar) + "/";
|
||||
}
|
||||
#else
|
||||
bool mkdirs(const std::string& path) {
|
||||
size_t offset = 0;
|
||||
while(offset < path.size()) {
|
||||
offset = path.find('/', offset+1);
|
||||
int res = mkdir(path.substr(0, offset).c_str(), S_IRWXU | S_IRWXG); // 770
|
||||
if(res == -1 && errno != EEXIST) {
|
||||
// mkdirs failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string getHome() {
|
||||
QString getHome() {
|
||||
const char* homevar = getenv("HOME");
|
||||
if(homevar == nullptr) {
|
||||
Log::warn << "$HOME is not set! Defaulting to ./";
|
||||
qWarning() << "$HOME is not set! Defaulting to ./";
|
||||
return "./";
|
||||
}
|
||||
return std::string(homevar) + "/";
|
||||
return QString(homevar) + "/";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string getCache() {
|
||||
bool mkdirs(const QString& path) {
|
||||
return QDir::root().mkpath(path);
|
||||
}
|
||||
|
||||
QString getCache() {
|
||||
return getHome() + CACHEPATH;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#include "loadingwindow.h"
|
||||
#include "ui_loadingwindow.h"
|
||||
|
||||
LoadingWindow::LoadingWindow(QWidget* parent) : QWidget(parent), ui(new Ui::LoadingWindow) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
LoadingWindow::~LoadingWindow() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LoadingWindow::setChampion(QString championName) {
|
||||
this->setText(LoadingWindow::tr("Loading Champion: %0").arg(championName));
|
||||
}
|
||||
|
||||
void LoadingWindow::setText(QString text) {
|
||||
ui->label->setText(text);
|
||||
}
|
||||
|
||||
void LoadingWindow::setProgress(float val) {
|
||||
ui->progressBar->setValue(val * 100);
|
||||
}
|
||||
|
||||
void LoadingWindow::closeEvent(QCloseEvent* event) {
|
||||
QWidget::closeEvent(event);
|
||||
emit this->closed();
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
LolAutoAccept::Stage::Stage() {}
|
||||
LolAutoAccept::Stage::~Stage() {}
|
||||
|
||||
LolAutoAccept::LolAutoAccept(Config::RootConfig& config, DataDragon& dd, onruneschange_func onrunch, QObject* parent) : QObject(parent), config(config), dd(dd), onRuneschange(onrunch) {
|
||||
LolAutoAccept::LolAutoAccept(Config::RootConfig& config, DataDragon& dd, QObject* parent) : QObject(parent), config(config), dd(dd) {
|
||||
qRegisterMetaType<LolAutoAccept::Status>();
|
||||
|
||||
std::lock_guard lock(stagesMutex);
|
||||
|
@ -22,22 +22,22 @@ LolAutoAccept::~LolAutoAccept() {
|
|||
|
||||
void LolAutoAccept::setChamps(const std::vector<uint32_t>& champs, State s) {
|
||||
if(s == State::LOBBY || s >= State::PICK) {
|
||||
Log::warn << "setChamps() called on invalid State";
|
||||
qWarning() << "setChamps() called on invalid State";
|
||||
return;
|
||||
}
|
||||
Log::debug << "LolAutoAccept::setChamps";
|
||||
qDebug() << "LolAutoAccept::setChamps";
|
||||
|
||||
{
|
||||
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();
|
||||
qInfo() << "set champs on state: " << (int) s << " count: " << champs.size();
|
||||
}
|
||||
|
||||
void LolAutoAccept::setEnabled(bool b, State s) {
|
||||
if(s > State::PICK) {
|
||||
Log::warn << "setEnabled() called on invalid State";
|
||||
qWarning() << "setEnabled() called on invalid State";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ bool LolAutoAccept::init() {
|
|||
if(ca) {
|
||||
clientapi = std::make_shared<ClientAPI>(*ca.get());
|
||||
auto selfinfo = clientapi->getSelf();
|
||||
Log::info << "selfinfo: gameName: " << selfinfo.gameName << " name: " << selfinfo.name << " summonerid: " << selfinfo.summonerid << " statusMessage: " << selfinfo.statusMessage << " puuid: " << selfinfo.puuid << " level: " << selfinfo.level;
|
||||
qInfo() << "selfinfo: gameName: " << selfinfo.gameName << " name: " << selfinfo.name << " summonerid: " << selfinfo.summonerid << " statusMessage: " << selfinfo.statusMessage << " puuid: " << selfinfo.puuid << " level: " << selfinfo.level;
|
||||
}
|
||||
|
||||
return (bool) clientapi;
|
||||
|
@ -89,7 +89,7 @@ const std::vector<RuneAspekt>& LolAutoAccept::getRuneAspekts() {
|
|||
if(runeaspekts.empty()) {
|
||||
if(clientapi) {
|
||||
runeaspekts = clientapi->getAllRuneAspekts();
|
||||
Log::info << "Loaded " << runeaspekts.size() << " rune aspekts";
|
||||
qInfo() << "Loaded " << runeaspekts.size() << " rune aspekts";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,22 +100,14 @@ const std::vector<RuneStyle>& LolAutoAccept::getRuneStyles() {
|
|||
if(runestyles.empty()) {
|
||||
if(clientapi) {
|
||||
runestyles = clientapi->getAllRuneStyles();
|
||||
Log::info << "Loaded " << runestyles.size() << " rune styles";
|
||||
qInfo() << "Loaded " << runestyles.size() << " rune styles";
|
||||
}
|
||||
}
|
||||
|
||||
return runestyles;
|
||||
}
|
||||
|
||||
void LolAutoAccept::applyRunes() {
|
||||
nextApplyRunes = true;
|
||||
}
|
||||
|
||||
void LolAutoAccept::setOnRuneChangeFunc(onruneschange_func on) {
|
||||
onRuneschange = on;
|
||||
}
|
||||
|
||||
void LolAutoAccept::setAutoWriteText(bool enabled, const std::string& text) {
|
||||
void LolAutoAccept::setAutoWriteText(bool enabled, const QString& text) {
|
||||
if ( enabled && !autoWriteTextEnabled ) {
|
||||
// only re-write on rising edge
|
||||
autoWriteTextDone = false;
|
||||
|
@ -138,7 +130,7 @@ void LolAutoAccept::innerRun() {
|
|||
|
||||
try {
|
||||
auto convs = clientapi->getAllConversations();
|
||||
Log::info << "got " << convs.size() << " conversations";
|
||||
qInfo() << "got " << convs.size() << " conversations";
|
||||
|
||||
emit statusChanged(Status::Running);
|
||||
while(shouldrun) {
|
||||
|
@ -146,23 +138,21 @@ void LolAutoAccept::innerRun() {
|
|||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto phase = clientapi->getGameflowPhase();
|
||||
Log::info << "current Gameflowphase: " << phase;
|
||||
qInfo() << "current Gameflowphase: " << phase;
|
||||
|
||||
// do processing
|
||||
if(phase == ClientAPI::GameflowPhase::LOBBY) {
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::MATCHMAKING) {
|
||||
extrasleep = 200;
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::READYCHECK) {
|
||||
if(stages.at(0).enabled) { // auto accept enabled
|
||||
auto state = clientapi->getReadyCheckState();
|
||||
|
||||
Log::info << "readychack state: " << state;
|
||||
qInfo() << "readychack state: " << state;
|
||||
if(state == ClientAPI::ReadyCheckState::INPROGRESS) {
|
||||
Log::info << "auto accepting";
|
||||
qInfo() << "auto accepting";
|
||||
clientapi->acceptMatch();
|
||||
}
|
||||
}
|
||||
|
@ -174,23 +164,18 @@ void LolAutoAccept::innerRun() {
|
|||
} else if(phase == ClientAPI::GameflowPhase::INPROGRESS) {
|
||||
extrasleep = 30000; // 30s bonus sleep
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::ENDOFGAME) {
|
||||
extrasleep = 2000; // 2 s bonus sleep
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::PREENDOFGAME) {
|
||||
extrasleep = 4000; // 4 s bonus sleep
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::WAITINGFORSTATS) {
|
||||
extrasleep = 4000; // 4 s bonus sleep
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
} else if(phase == ClientAPI::GameflowPhase::NONE) {
|
||||
extrasleep = 10000; // 10 s bonus sleep - no lobby
|
||||
resetAllOffsets();
|
||||
resetRunes();
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
@ -202,7 +187,7 @@ void LolAutoAccept::innerRun() {
|
|||
}
|
||||
emit statusChanged(Status::Off);
|
||||
} catch(RestClient::WebException& e) {
|
||||
Log::error << "WebException catched: " << e.curlresponse;
|
||||
qCritical() << "WebException catched: " << e.curlresponse;
|
||||
if(e.curlresponse == CURLE_COULDNT_CONNECT) {
|
||||
// free clientapi
|
||||
clientapi.reset();
|
||||
|
@ -216,22 +201,19 @@ void LolAutoAccept::innerRun() {
|
|||
}
|
||||
}
|
||||
|
||||
void LolAutoAccept::resetAllOffsets() {
|
||||
void LolAutoAccept::resetPickOffsets() {
|
||||
for(Stage& stage : stages) {
|
||||
stage.currentOffset = 0;
|
||||
}
|
||||
currentPosition = Position::INVALID;
|
||||
currentPositionSet = false;
|
||||
lastPickedChamp = 0;
|
||||
chatid.clear();
|
||||
autoWriteTextDone = false;
|
||||
}
|
||||
|
||||
void LolAutoAccept::resetRunes() {
|
||||
if(onRuneschange) {
|
||||
onRuneschange({});
|
||||
}
|
||||
nextApplyRunes = false;
|
||||
void LolAutoAccept::resetAllOffsets() {
|
||||
resetPickOffsets();
|
||||
currentPosition = Position::INVALID;
|
||||
currentPositionSet = false;
|
||||
chatid.clear();
|
||||
autoWriteTextDone = false;
|
||||
}
|
||||
|
||||
void LolAutoAccept::applyConfigToStage(Stage& stage, const Config::StageConfig& stageconf) {
|
||||
|
@ -264,8 +246,8 @@ uint32_t LolAutoAccept::getChampOfState(State s) {
|
|||
uint32_t size = stage.champids.size();
|
||||
if(stage.currentOffset >= size) {
|
||||
// no champ to try left
|
||||
Log::warn << "no champ left at stage: " << (int) s;
|
||||
Log::warn << "stage size: " << stage.champids.size();
|
||||
qWarning() << "no champ left at stage: " << (int) s;
|
||||
qWarning() << "stage size: " << stage.champids.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -282,8 +264,8 @@ void LolAutoAccept::nextChampOfState(State s) {
|
|||
|
||||
if(stage.currentOffset >= size) {
|
||||
// no champ to try left
|
||||
Log::warn << "no champ left at stage: " << (int) s;
|
||||
Log::warn << "stage size: " << stage.champids.size();
|
||||
qWarning() << "no champ left at stage: " << (int) s;
|
||||
qWarning() << "stage size: " << stage.champids.size();
|
||||
|
||||
stage.currentOffset = 0;
|
||||
return;
|
||||
|
@ -293,7 +275,7 @@ void LolAutoAccept::nextChampOfState(State s) {
|
|||
bool LolAutoAccept::isChampIntentofTeammate(uint32_t champid, const ClientAPI::ChampSelectSession& session) {
|
||||
for(const ClientAPI::ChampSelectCell& player : session.myTeam) {
|
||||
if(player.championID == (int32_t) champid || player.championPickIntentID == (int32_t) champid) {
|
||||
Log::info << "player " << player.cellID << " @ " << player.position << " wants to play " << champid;
|
||||
qInfo() << "player " << player.cellID << " @ " << toString(player.position) << " wants to play " << champid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +295,7 @@ LolAutoAccept::ownactions_t LolAutoAccept::getOwnActions(int32_t cellid, const s
|
|||
ownactions_t out;
|
||||
for(const auto& it : actions) {
|
||||
if(it.actorCellID == cellid) {
|
||||
Log::debug << "ownaction: id: " << it.id << " champid: " << it.championID << " completed: " << it.completed << " type: " << it.type;
|
||||
qDebug() << "ownaction: id: " << it.id << " champid: " << it.championID << " completed: " << it.completed << " type: " << it.type;
|
||||
if(!it.completed) { // completed cant be interacted anyways, so just ignore them.
|
||||
out.push_back(it);
|
||||
}
|
||||
|
@ -344,7 +326,7 @@ void LolAutoAccept::phase(const ownactions_t& ownactions, ClientAPI::ChampSelect
|
|||
|
||||
for(auto it : ownactions) {
|
||||
if(it.type == type) {
|
||||
Log::info << type << " action anvailable: " << it.id << " champid: " << it.championID;
|
||||
qInfo() << type << " action anvailable: " << it.id << " champid: " << it.championID;
|
||||
uint32_t champid = getChampOfState(s);
|
||||
|
||||
if(filter) {
|
||||
|
@ -358,7 +340,7 @@ void LolAutoAccept::phase(const ownactions_t& ownactions, ClientAPI::ChampSelect
|
|||
|
||||
if((it.championID != (int32_t) champid || !it.completed) && champid != 0) {
|
||||
// try to prepick a champion
|
||||
Log::info << "try to pick champ: " << champid;
|
||||
qInfo() << "try to pick champ: " << champid;
|
||||
|
||||
if(!clientapi->setChampSelectAction(it.id, champid, complete)) {
|
||||
nextChampOfState(s);
|
||||
|
@ -370,15 +352,15 @@ void LolAutoAccept::phase(const ownactions_t& ownactions, ClientAPI::ChampSelect
|
|||
}
|
||||
|
||||
int32_t LolAutoAccept::getBestRunePage(const std::vector<ClientAPI::RunePage>& pages) {
|
||||
Log::debug << "searching RunePages: " << pages.size();
|
||||
qDebug() << "searching RunePages: " << pages.size();
|
||||
for(uint32_t i = 0; i < pages.size(); ++i) {
|
||||
Log::debug << i << ": " << pages[i].id << " " << pages[i].name << " " << pages[i].isCurrent;
|
||||
qDebug() << i << ": " << pages[i].id << " " << pages[i].name << " " << pages[i].isCurrent;
|
||||
}
|
||||
|
||||
// search for a rune page with a name that starts with "AA: "
|
||||
for(uint32_t i = 0; i < pages.size(); ++i) {
|
||||
const ClientAPI::RunePage& rp = pages.at(i);
|
||||
if(rp.name.size() >= 4 && rp.name.substr(0, 4) == "AA: ") {
|
||||
if(rp.name.size() >= 4 && rp.name.left(4) == "AA: ") {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +383,12 @@ int32_t LolAutoAccept::getMatchingRunePage(const RunePage& rp, const std::vector
|
|||
|
||||
void LolAutoAccept::champSelect() {
|
||||
auto session = clientapi->getChampSelectSession();
|
||||
int32_t cellid = session.localPlayerCellId;
|
||||
const int32_t cellid = session.localPlayerCellId;
|
||||
|
||||
if(cellid != lastCellId && lastCellId != -1) {
|
||||
resetPickOffsets();
|
||||
}
|
||||
lastCellId = cellid;
|
||||
|
||||
// find own cellid info
|
||||
const ClientAPI::ChampSelectCell* me = nullptr;
|
||||
|
@ -418,16 +405,8 @@ void LolAutoAccept::champSelect() {
|
|||
|
||||
// check if runes need adjustment
|
||||
if(pickedChamp != lastPickedChamp) {
|
||||
Log::info << "picked champ changed from: " << lastPickedChamp << " to: " << pickedChamp;
|
||||
qInfo() << "picked champ changed from: " << lastPickedChamp << " to: " << pickedChamp;
|
||||
lastPickedChamp = pickedChamp;
|
||||
|
||||
// update runes
|
||||
if(onRuneschange) {
|
||||
auto champinfo = blitzapi.getChampionInfo(pickedChamp, pos); // TODO: add detection for enemy champ
|
||||
Log::info << "champinfo aquired: " << champinfo.runepage;
|
||||
|
||||
onRuneschange(champinfo.runepage);
|
||||
}
|
||||
}
|
||||
|
||||
// reload config based on position if changed
|
||||
|
@ -438,13 +417,13 @@ void LolAutoAccept::champSelect() {
|
|||
emit positionChanged(pos);
|
||||
}
|
||||
|
||||
Log::debug << "cellid: " << cellid << " position: " << pos << " counter: " << session.counter << " timer: timeleftip: " << session.timer.adjustedTimeLeftInPhase << " totaltimephase: " << session.timer.totalTimeInPhase;
|
||||
qDebug() << "cellid: " << cellid << " position: " << toString(pos) << " counter: " << session.counter << " timer: timeleftip: " << session.timer.adjustedTimeLeftInPhase << " totaltimephase: " << session.timer.totalTimeInPhase;
|
||||
// find actions for own cell
|
||||
auto ownactions = getOwnActions(cellid, session.actions);
|
||||
Log::debug << "ownactions: " << ownactions.size();
|
||||
qDebug() << "ownactions: " << ownactions.size();
|
||||
|
||||
// try to prepick champ
|
||||
Log::info << "champselectphase: " << session.timer.phase;
|
||||
qInfo() << "champselectphase: " << session.timer.phase;
|
||||
|
||||
std::lock_guard lock(stagesMutex);
|
||||
if(session.timer.phase == ClientAPI::ChampSelectPhase::PLANNING) {
|
||||
|
@ -461,14 +440,10 @@ void LolAutoAccept::champSelect() {
|
|||
}
|
||||
}
|
||||
|
||||
if(nextApplyRunes) {
|
||||
applyRunes_internal(pickedChamp, pos);
|
||||
}
|
||||
|
||||
// check for autowriteText
|
||||
if(autoWriteTextEnabled && !autoWriteTextDone && !autoWriteText.empty()) {
|
||||
const std::string& chatid = getChatid();
|
||||
if(!chatid.empty()) {
|
||||
if(autoWriteTextEnabled && !autoWriteTextDone && !autoWriteText.isEmpty()) {
|
||||
const QString& chatid = getChatid();
|
||||
if(!chatid.isEmpty()) {
|
||||
clientapi->sendMessage(chatid, autoWriteText);
|
||||
autoWriteTextDone = true;
|
||||
}
|
||||
|
@ -478,7 +453,7 @@ void LolAutoAccept::champSelect() {
|
|||
void LolAutoAccept::smiteWarning(const std::vector<ClientAPI::ChampSelectCell>& cells) {
|
||||
uint32_t smiteCount = 0;
|
||||
for(const ClientAPI::ChampSelectCell& member : cells) {
|
||||
Log::info << "position: " << member.position << " spells: " << member.spell1Id << " " << member.spell2Id;
|
||||
qInfo() << "position: " << toString(member.position) << " spells: " << member.spell1Id << " " << member.spell2Id;
|
||||
smiteCount += (member.spell1Id == 11 || member.spell2Id == 11);
|
||||
}
|
||||
|
||||
|
@ -489,24 +464,24 @@ void LolAutoAccept::smiteWarning(const std::vector<ClientAPI::ChampSelectCell>&
|
|||
return;
|
||||
}
|
||||
|
||||
Log::info << "smite warning: " << smiteCount;
|
||||
const std::string& chatid = getChatid();
|
||||
if(!chatid.empty()) {
|
||||
qInfo() << "smite warning: " << smiteCount;
|
||||
const QString& chatid = getChatid();
|
||||
if(!chatid.isEmpty()) {
|
||||
clientapi->sendMessage(chatid, "smite");
|
||||
lastMessageSent = currenttime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& LolAutoAccept::getChatid() {
|
||||
if(chatid.empty()) {
|
||||
const QString& LolAutoAccept::getChatid() {
|
||||
if(chatid.isEmpty()) {
|
||||
std::vector<ClientAPI::Conversation> convs = clientapi->getAllConversations();
|
||||
Log::info << "got " << convs.size() << " conversations";
|
||||
qInfo() << "got " << convs.size() << " conversations";
|
||||
|
||||
for(const ClientAPI::Conversation& conv : convs) {
|
||||
Log::info << " id: " << conv.id << " type: " << conv.type << " name: " << conv.name << " gameName: " << conv.gameName;
|
||||
if(conv.type == "championSelect" && conv.name.empty()) {
|
||||
Log::info << "groupchat found";
|
||||
qInfo() << " id: " << conv.id << " type: " << conv.type << " name: " << conv.name << " gameName: " << conv.gameName;
|
||||
if(conv.type == "championSelect" && conv.name.isEmpty()) {
|
||||
qInfo() << "groupchat found";
|
||||
chatid = conv.id;
|
||||
return chatid;
|
||||
}
|
||||
|
@ -514,56 +489,3 @@ const std::string& LolAutoAccept::getChatid() {
|
|||
}
|
||||
return chatid; //might be empty string
|
||||
}
|
||||
|
||||
void LolAutoAccept::applyRunes_internal(uint32_t champid, Position pos) {
|
||||
nextApplyRunes = false;
|
||||
Log::note << "apply runes";
|
||||
|
||||
// get recommended runes and stuff
|
||||
auto champinfo = blitzapi.getChampionInfo(champid, pos);
|
||||
Log::info << "fetched champion info runes: " << champinfo.runepage;
|
||||
|
||||
// choose page
|
||||
auto pages = clientapi->getAllRunePages();
|
||||
|
||||
// check for page that allready contains the settings
|
||||
int32_t choosepage = getMatchingRunePage(champinfo.runepage, pages);
|
||||
if(choosepage != -1) {
|
||||
ClientAPI::RunePage& page = pages.at(choosepage);
|
||||
Log::info << "matching runepage found, selecting: " << page.id << " " << page.name;
|
||||
if(clientapi->selectRunePage(page.id)) {
|
||||
return;
|
||||
}
|
||||
Log::warn << "selecting runepage failed";
|
||||
}
|
||||
|
||||
// find page to replace
|
||||
int32_t pageoffset = getBestRunePage(pages);
|
||||
|
||||
if(pageoffset < 0) {
|
||||
Log::warn << "no rune page found!";
|
||||
return;
|
||||
}
|
||||
|
||||
// replace the page
|
||||
ClientAPI::RunePage& rp = pages.at(pageoffset);
|
||||
Log::info << "replace runepage id: " << rp.id << " old-name: " << rp.name;
|
||||
|
||||
// resolve champion name for the runepage name
|
||||
ClientAPI::RunePage newpage;
|
||||
auto champ = dd.getChampByID(champid);
|
||||
const std::string champname = champ ? champ->name : std::to_string(champid);
|
||||
|
||||
newpage.id = rp.id;
|
||||
newpage.name = "AA: " + champname + " " + toShortString(pos); // TODO: make role "Utility" resolve to "Support"?
|
||||
newpage.runepage = champinfo.runepage;
|
||||
clientapi->editRunePage(newpage);
|
||||
|
||||
//select runepage
|
||||
if(!rp.isCurrent) {
|
||||
Log::info << "page is not selected, selecting now (id: " << newpage.id << ')';
|
||||
clientapi->selectRunePage(newpage.id);
|
||||
}
|
||||
|
||||
Log::info << "runepage done";
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#include <QDebug>
|
||||
|
||||
#include "arg.h"
|
||||
#include "mainwindow.h"
|
||||
#include "clientaccess.h"
|
||||
#include "clientapi.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Log::init();
|
||||
|
@ -40,10 +40,7 @@ int main(int argc, char** argv) {
|
|||
qWarning() << "translation not found";
|
||||
}
|
||||
MainWindow win;
|
||||
QIcon icon(":/lolautoaccept.png");
|
||||
win.setWindowIcon(icon);
|
||||
|
||||
win.show();
|
||||
int ret = app.exec();
|
||||
|
||||
Log::stop();
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
|
||||
#include <Log.h>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), loading(true), ui(new Ui::MainWindow), saveTimer(new QTimer(this)), dd(QLocale().name().toStdString()),
|
||||
lolaa(conf.getConfig(), dd) {
|
||||
#include "loadingwindow.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), loading(true), ui(new Ui::MainWindow), saveTimer(new QTimer(this)), dd(QLocale().name()),
|
||||
lolaa(conf.getConfig(), dd), lwin(new LoadingWindow(nullptr)) {
|
||||
ui->setupUi(this);
|
||||
|
||||
QObject::connect(&dd, &DataDragon::fetchingChamp, lwin, &LoadingWindow::setChampion);
|
||||
QObject::connect(&dd, &DataDragon::loading, lwin, &LoadingWindow::setProgress);
|
||||
QObject::connect(&dd, &DataDragon::loading, this, &MainWindow::loadingStatus);
|
||||
QObject::connect(lwin, &LoadingWindow::closed, &dd, &DataDragon::stop);
|
||||
QObject::connect(lwin, &LoadingWindow::closed, qApp, &QCoreApplication::quit, Qt::ConnectionType::QueuedConnection);
|
||||
dd.startThread();
|
||||
|
||||
QObject::connect(&lolaa, &LolAutoAccept::statusChanged, this, &MainWindow::lolaaStatusChanged);
|
||||
QObject::connect(&lolaa, &LolAutoAccept::positionChanged, this, &MainWindow::onPosChange);
|
||||
|
||||
|
@ -19,19 +29,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), loading(true), ui
|
|||
ui->copyrightlabel->setText(ui->copyrightlabel->text().arg(LOLAA_VERSION));
|
||||
|
||||
conf.load();
|
||||
|
||||
// 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, &SettingsTab::changed, this, &MainWindow::tabchanged);
|
||||
QObject::connect(tab, &SettingsTab::toggled, this, &MainWindow::tabtoggled);
|
||||
}
|
||||
|
||||
ui->runesPage->setDataDragon(dd);
|
||||
ui->runesPage->setConfig(conf);
|
||||
|
||||
ui->enableAll->setChecked(rc.enabledAutoAccept);
|
||||
lolaa.setEnabled(rc.enabledAutoAccept, LolAutoAccept::State::LOBBY);
|
||||
|
@ -41,16 +39,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), loading(true), ui
|
|||
|
||||
ui->enableAutoWrite->setChecked(rc.enabledAutoWrite);
|
||||
ui->autoWriteText->setText(rc.autoWriteText);
|
||||
lolaa.setAutoWriteText(rc.enabledAutoWrite, rc.autoWriteText.toStdString());
|
||||
lolaa.setAutoWriteText(rc.enabledAutoWrite, rc.autoWriteText);
|
||||
|
||||
resizeEvent(nullptr);
|
||||
|
||||
// a timer to delay the loading flag a short time until all other signals are processed
|
||||
initDoneTimer = new QTimer(this);
|
||||
initDoneTimer->setSingleShot(true);
|
||||
initDoneTimer->setInterval(std::chrono::milliseconds(1)); // schedule for first event loop
|
||||
QObject::connect(initDoneTimer, &QTimer::timeout, this, &MainWindow::initDone, Qt::QueuedConnection);
|
||||
initDoneTimer->start();
|
||||
lwin->show();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
|
@ -70,6 +63,35 @@ void MainWindow::resetSaveTimer() {
|
|||
qDebug() << "resetTimer";
|
||||
}
|
||||
|
||||
void MainWindow::loadingStatus(float f) {
|
||||
if(f >= 1.0 && lwin) {
|
||||
// loading complete
|
||||
|
||||
// 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, &SettingsTab::changed, this, &MainWindow::tabchanged);
|
||||
QObject::connect(tab, &SettingsTab::toggled, this, &MainWindow::tabtoggled);
|
||||
}
|
||||
|
||||
// load runepage images
|
||||
ui->runesPage->setDataDragon(dd);
|
||||
ui->runesPage->setConfig(conf);
|
||||
|
||||
// switch from loading window to main window
|
||||
lwin->hide();
|
||||
this->show();
|
||||
lwin->deleteLater();
|
||||
lwin = nullptr;
|
||||
|
||||
// a timer to delay the loading flag a short time until all other signals are processed
|
||||
QTimer::singleShot(std::chrono::milliseconds(1), this, &MainWindow::initDone);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::toggleMainswitch(bool state) {
|
||||
qDebug() << "mainswitch toggled: " << state;
|
||||
|
||||
|
@ -82,7 +104,7 @@ void MainWindow::toggleMainswitch(bool state) {
|
|||
|
||||
// TODO: make this non blocking
|
||||
if(!lolaa.init()) {
|
||||
Log::error << "League Client not found!";
|
||||
qCritical() << "League Client not found!";
|
||||
ui->statusbar->showMessage(tr("League of Legends Client not found!"));
|
||||
ui->mainswitch->setCheckState(Qt::CheckState::Unchecked);
|
||||
ui->mainswitch->setEnabled(true);
|
||||
|
@ -136,19 +158,13 @@ void MainWindow::tabchanged(Position p, LolAutoAccept::State s) {
|
|||
resetSaveTimer();
|
||||
}
|
||||
|
||||
void MainWindow::applyRunes() {
|
||||
qDebug() << "applyRunes pressed";
|
||||
|
||||
lolaa.applyRunes();
|
||||
}
|
||||
|
||||
void MainWindow::autoWriteChanged() {
|
||||
if( loading ) return;
|
||||
|
||||
bool enabled = ui->enableAutoWrite->isChecked();
|
||||
const QString text = ui->autoWriteText->toPlainText();
|
||||
|
||||
lolaa.setAutoWriteText(enabled, text.toStdString());
|
||||
lolaa.setAutoWriteText(enabled, text);
|
||||
|
||||
conf.getConfig().enabledAutoWrite = enabled;
|
||||
conf.getConfig().autoWriteText = text;
|
||||
|
@ -162,8 +178,6 @@ void MainWindow::saveConfig() {
|
|||
|
||||
void MainWindow::initDone() {
|
||||
loading = false;
|
||||
initDoneTimer->deleteLater();
|
||||
initDoneTimer = nullptr;
|
||||
qDebug() << "loading done";
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
MemoryImageCache::MemoryImageCache(size_t maxsize) : maxsize(maxsize) {}
|
||||
|
||||
void MemoryImageCache::addImage(QPixmap img, const std::string& title, int type) {
|
||||
void MemoryImageCache::addImage(QPixmap img, const QString& title, int type) {
|
||||
auto it = std::find_if(cache.begin(), cache.end(), getImageMatcher(title, type));
|
||||
if(it == cache.end()) {
|
||||
// insert new
|
||||
|
@ -19,7 +19,7 @@ void MemoryImageCache::addImage(QPixmap img, const std::string& title, int type)
|
|||
it->imageref = img;
|
||||
}
|
||||
|
||||
QPixmap MemoryImageCache::getImage(const std::string& title, int type) {
|
||||
QPixmap MemoryImageCache::getImage(const QString& title, int type) {
|
||||
auto it = std::find_if(cache.begin(), cache.end(), getImageMatcher(title, type));
|
||||
if(it == cache.end()) {
|
||||
return {};
|
||||
|
@ -40,7 +40,7 @@ bool MemoryImageCache::CachedImage::operator<(const MemoryImageCache::CachedImag
|
|||
return lastaccessed < other.lastaccessed;
|
||||
}
|
||||
|
||||
std::function<bool(const MemoryImageCache::CachedImage&)> MemoryImageCache::getImageMatcher(const std::string& title, int type) {
|
||||
std::function<bool(const MemoryImageCache::CachedImage&)> MemoryImageCache::getImageMatcher(const QString& title, int type) {
|
||||
return [title, type](const MemoryImageCache::CachedImage& img) -> bool {
|
||||
return img.type == type && img.title == title;
|
||||
};
|
||||
|
|
|
@ -63,7 +63,7 @@ static int my_trace(CURL* handle, curl_infotype type, char* data, size_t size, v
|
|||
return 0;
|
||||
}
|
||||
|
||||
RestClient::RestClient(const std::string& base) : baseurl(base) {
|
||||
RestClient::RestClient(const QString& base) : baseurl(base) {
|
||||
curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, arrayWriteCallback);
|
||||
|
@ -77,13 +77,15 @@ RestClient::~RestClient() {
|
|||
RestClient::WebException::WebException(CURLcode c) : curlresponse(c) {
|
||||
}
|
||||
|
||||
QByteArray RestClient::requestRaw(const std::string& url, Method m, const std::string& data) {
|
||||
QByteArray RestClient::requestRaw(const QString& url, Method m, const QString& data) {
|
||||
if (!curl) return {};
|
||||
|
||||
std::string requrl = baseurl + url;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, requrl.c_str());
|
||||
QString requrl = baseurl + url;
|
||||
const QByteArray reqArr = requrl.toLocal8Bit();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, reqArr.data());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, basicauth.c_str());
|
||||
const QByteArray basicArr = basicauth.toLocal8Bit();
|
||||
curl_easy_setopt(curl, CURLOPT_USERPWD, basicArr.data());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
if (disableCertCheck) {
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
@ -99,6 +101,7 @@ QByteArray RestClient::requestRaw(const std::string& url, Method m, const std::s
|
|||
struct curl_slist* headerlist = NULL;
|
||||
|
||||
headerlist = curl_slist_append(headerlist, "Accept: application/json");
|
||||
const QByteArray dataArr = data.toLocal8Bit();
|
||||
|
||||
switch (m) {
|
||||
default:
|
||||
|
@ -106,22 +109,14 @@ QByteArray RestClient::requestRaw(const std::string& url, Method m, const std::s
|
|||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); break;
|
||||
case Method::POST:
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, dataArr.data());
|
||||
headerlist = curl_slist_append(headerlist, "Content-Type: application/json");
|
||||
break;
|
||||
case Method::PUT:
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); // to use the POSTFIELDS (do not use CURLOPT_PUT, it does not support POSTFIELDS)
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
headerlist = curl_slist_append(headerlist, "Content-Type: application/json");
|
||||
break;
|
||||
case Method::PATCH:
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
headerlist = curl_slist_append(headerlist, "Content-Type: application/json");
|
||||
break;
|
||||
case Method::DELETE:
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, toString(m)); // to use the POSTFIELDS (do not use CURLOPT_PUT, it does not support POSTFIELDS)
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, dataArr.data());
|
||||
headerlist = curl_slist_append(headerlist, "Content-Type: application/json");
|
||||
break;
|
||||
}
|
||||
|
@ -141,9 +136,9 @@ QByteArray RestClient::requestRaw(const std::string& url, Method m, const std::s
|
|||
if (res == CURLE_HTTP_RETURNED_ERROR) {
|
||||
long responsecode = -1;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responsecode);
|
||||
Log::warn << "API request failed: " << baseurl << " " << url << " -> " << responsecode;
|
||||
qWarning() << "API request failed: " << baseurl << " " << url << " -> " << responsecode;
|
||||
} else {
|
||||
Log::warn << "API request failed: " << baseurl << " " << url << " " << curl_easy_strerror(res);
|
||||
qWarning() << "API request failed: " << baseurl << " " << url << " " << curl_easy_strerror(res);
|
||||
if(res == CURLE_COULDNT_CONNECT) {
|
||||
throw WebException(res);
|
||||
}
|
||||
|
@ -153,14 +148,14 @@ QByteArray RestClient::requestRaw(const std::string& url, Method m, const std::s
|
|||
return ba;
|
||||
}
|
||||
|
||||
QJsonDocument RestClient::request(const std::string& url, Method m, const std::string& data) {
|
||||
QJsonDocument RestClient::request(const QString& url, Method m, const QString& data) {
|
||||
QByteArray arr = requestRaw(url, m, data);
|
||||
if (arr.isEmpty()) return {};
|
||||
|
||||
QJsonParseError err;
|
||||
QJsonDocument parsed = QJsonDocument::fromJson(arr, &err);
|
||||
if (parsed.isNull() || err.error != QJsonParseError::NoError) {
|
||||
Log::error << "API Json parse error " << err.errorString().toStdString() << " offset: " << err.offset;
|
||||
qCritical() << "API Json parse error " << err.errorString() << " offset: " << err.offset;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -178,9 +173,15 @@ void RestClient::enableDebugging(bool enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string RestClient::escape(const std::string& in) const {
|
||||
char* e = curl_easy_escape(curl, in.c_str(), in.length());
|
||||
std::string esc(e);
|
||||
QString RestClient::escape(const QString& in) const {
|
||||
char* e = curl_easy_escape(curl, in.toLocal8Bit().data(), in.length());
|
||||
QString esc(e);
|
||||
curl_free(e);
|
||||
return esc;
|
||||
}
|
||||
|
||||
const char* toString(RestClient::Method m) {
|
||||
static const char* MethodNames[] = {"GET", "POST", "PUT", "PATCH", "DELETE"};
|
||||
|
||||
return MethodNames[(int) m];
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
#include "runeaspektbuttongroup.h"
|
||||
|
||||
RuneAspektButton::RuneAspektButton(QWidget* parent) : QPushButton(parent), ui(new Ui::RuneAspektButton) {
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -13,45 +15,25 @@ RuneAspektButton::~RuneAspektButton() {
|
|||
delete this->ui;
|
||||
}
|
||||
|
||||
void RuneAspektButton::setAspektsVector(std::vector<uint32_t>& aspekts) {
|
||||
this->aspekts = &aspekts;
|
||||
|
||||
dataChanged();
|
||||
}
|
||||
|
||||
void RuneAspektButton::setAspketSlot(int slot) {
|
||||
aspektSlot = slot;
|
||||
|
||||
dataChanged();
|
||||
}
|
||||
|
||||
void RuneAspektButton::setAspektId(uint32_t id) {
|
||||
aspektId = id;
|
||||
|
||||
dataChanged();
|
||||
}
|
||||
|
||||
void RuneAspektButton::setButtonGroup(RuneAspektButtonGroup* group) {
|
||||
this->group = group;
|
||||
}
|
||||
|
||||
bool RuneAspektButton::isSelected() const {
|
||||
return (aspektSlot >= 0 // aspektSlot is valid
|
||||
&& (int) aspekts->size() > aspektSlot // aspektSlot is valid
|
||||
&& aspektId != 0 // aspektId is valid
|
||||
&& aspekts->at(aspektSlot) == aspektId); // aspekt is selected
|
||||
return group && group->getSelectedRunes().contains(aspektId);
|
||||
}
|
||||
|
||||
void RuneAspektButton::buttonPressed() {
|
||||
if(Q_UNLIKELY(!(aspekts && aspektSlot >= 0))) return;
|
||||
|
||||
// toggle
|
||||
bool oldState = isSelected();
|
||||
int newValue = (oldState ? 0 : aspektId);
|
||||
aspekts->at(aspektSlot) = newValue;
|
||||
|
||||
emit aspektToggled(!oldState);
|
||||
emit aspektToggled(aspektId);
|
||||
}
|
||||
|
||||
void RuneAspektButton::dataChanged() {
|
||||
if(!aspekts) return;
|
||||
|
||||
bool selection = isSelected();
|
||||
|
||||
qDebug() << text() << " datachanged - isSelected: " << selection;
|
||||
|
@ -59,10 +41,15 @@ void RuneAspektButton::dataChanged() {
|
|||
setShowSelection(selection);
|
||||
}
|
||||
|
||||
void RuneAspektButton::checkSelection(uint32_t aspekt) {
|
||||
qDebug() << "checkSelection: " << text() << aspekt << aspektId;
|
||||
setShowSelection(aspekt == this->aspektId);
|
||||
}
|
||||
|
||||
void RuneAspektButton::setShowSelection(bool selected) {
|
||||
if(selected) {
|
||||
setStyleSheet("border: 1px solid red;");
|
||||
} else {
|
||||
setStyleSheet("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
#include "runeaspektbuttongroup.h"
|
||||
|
||||
#include "runeaspektbutton.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
const int RuneAspektButtonGroup::INVALID_ASPEKT_ID = 0;
|
||||
|
||||
RuneAspektButtonGroup::RuneAspektButtonGroup(QObject* parent, uint32_t size) : QObject(parent), selectedRune(), size(size) {
|
||||
selectedRune.reserve(size*2);
|
||||
}
|
||||
|
||||
RuneAspektButtonGroup::~RuneAspektButtonGroup() {}
|
||||
|
||||
void RuneAspektButtonGroup::addButton(RuneAspektButton* button) {
|
||||
QObject::connect(this, &RuneAspektButtonGroup::changed, button, &RuneAspektButton::dataChanged);
|
||||
QObject::connect(button, &RuneAspektButton::aspektToggled, this, &RuneAspektButtonGroup::buttonPressed);
|
||||
|
||||
button->setButtonGroup(this);
|
||||
}
|
||||
|
||||
void RuneAspektButtonGroup::setSelectedRunes(const QVector<int>& newRunes) {
|
||||
selectedRune = newRunes;
|
||||
|
||||
qDebug() << "selectedRunes changed to: " << selectedRune << " refesching buttons";
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void RuneAspektButtonGroup::setSubgroups(const QVector<QVector<int>>& newSubgroups) {
|
||||
subgroups = newSubgroups;
|
||||
}
|
||||
|
||||
void RuneAspektButtonGroup::buttonPressed(int aspektId) {
|
||||
if(selectedRune.contains(aspektId)) {
|
||||
selectedRune.removeAll(aspektId);
|
||||
} else {
|
||||
// check subgroups first
|
||||
int otherSubgroupMember = getOtherSubgroupMemeber(aspektId);
|
||||
if(otherSubgroupMember != INVALID_ASPEKT_ID) {
|
||||
// collision in subgroup -> remove other member
|
||||
selectedRune.removeAll(otherSubgroupMember);
|
||||
}
|
||||
|
||||
selectedRune.push_back(aspektId);
|
||||
|
||||
if((uint32_t) selectedRune.size() > size) {
|
||||
selectedRune.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
int RuneAspektButtonGroup::getOtherSubgroupMemeber(int aspektId) {
|
||||
if(subgroups.empty()) {
|
||||
return INVALID_ASPEKT_ID;
|
||||
}
|
||||
|
||||
for(const QVector<int>& subgroup : subgroups) {
|
||||
if(subgroup.contains(aspektId)) {
|
||||
for(const int& subgroupMember : subgroup) {
|
||||
if(aspektId != subgroupMember && selectedRune.contains(subgroupMember)) {
|
||||
return subgroupMember;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_ASPEKT_ID;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
#include "runedisplay.h"
|
||||
#include "ui_runedisplay.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <QTextStream>
|
||||
|
||||
const static std::string EMPTY;
|
||||
const static QString EMPTY;
|
||||
|
||||
RuneDisplay::RuneDisplay(QWidget *parent) : QWidget(parent), ui(new Ui::RuneDisplay) {
|
||||
ui->setupUi(this);
|
||||
|
@ -32,10 +32,11 @@ void RuneDisplay::applyRunesClicked() {
|
|||
}
|
||||
|
||||
void RuneDisplay::updateText() {
|
||||
std::ostringstream out;
|
||||
QString outStr;
|
||||
QTextStream out(&outStr);
|
||||
|
||||
if(! (bool) runepage) {
|
||||
ui->runetext->setText(QString::fromStdString(""));
|
||||
ui->runetext->setText("");
|
||||
ui->applyRunesBtn->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
@ -45,24 +46,24 @@ void RuneDisplay::updateText() {
|
|||
for(uint32_t rune : runepage.selectedAspects) {
|
||||
out << getRuneText(rune) << '\n';
|
||||
}
|
||||
ui->runetext->setText(QString::fromStdString(out.str()));
|
||||
ui->runetext->setText(outStr);
|
||||
ui->applyRunesBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
std::string RuneDisplay::getRuneText(uint32_t id) {
|
||||
QString RuneDisplay::getRuneText(uint32_t id) {
|
||||
for(const RuneAspekt& ra : runeinfo) {
|
||||
if(ra.id == id) {
|
||||
return ra.name;
|
||||
}
|
||||
}
|
||||
|
||||
return "(" + std::to_string(id) + ")";
|
||||
return "(" + QString::number(id) + ")";
|
||||
}
|
||||
|
||||
std::string RuneDisplay::getRuneStyleByID(uint32_t id) {
|
||||
QString RuneDisplay::getRuneStyleByID(uint32_t id) {
|
||||
auto it = std::find_if(runestyles.begin(), runestyles.end(), [id](const RuneStyle& rs) { return rs.id == id; });
|
||||
if(it == runestyles.end()) {
|
||||
return '(' + std::to_string(id) + ')';
|
||||
return '(' + QString::number(id) + ')';
|
||||
}
|
||||
|
||||
return it->name;
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
|
||||
#include "clientapi.h"
|
||||
#include "runeaspektbutton.h"
|
||||
#include "runeaspektbuttongroup.h"
|
||||
|
||||
RuneEditor::RuneEditor(QWidget* parent) : QDialog(parent), ui(new Ui::RuneEditor) {
|
||||
RuneEditor::RuneEditor(QWidget* parent) : QDialog(parent), ui(new Ui::RuneEditor), groups(8, nullptr) {
|
||||
ui->setupUi(this);
|
||||
|
||||
QObject::connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &RuneEditor::accept);
|
||||
|
@ -32,13 +33,14 @@ void RuneEditor::setClient(ClientAPI& client) {
|
|||
styles = client.getAllRuneStyles();
|
||||
|
||||
for(const RuneStyle& rs : styles) {
|
||||
QPushButton* runeStyleBtn = createStyleButton(rs, rs.id == runepage.primaryStyle);
|
||||
RuneAspektButton* runeStyleBtn = createStyleButton(rs, rs.id == runepage.primaryStyle);
|
||||
|
||||
if(!runeStyleBtn) continue;
|
||||
|
||||
QObject::connect(runeStyleBtn, &QPushButton::pressed, [this, id = rs.id](){
|
||||
selectStyle(id);
|
||||
});
|
||||
QObject::connect(this, &RuneEditor::selectPrimary, runeStyleBtn, &RuneAspektButton::checkSelection);
|
||||
|
||||
ui->style->addWidget(runeStyleBtn);
|
||||
}
|
||||
|
@ -58,6 +60,17 @@ void RuneEditor::setRunepage(const ::RunePage& rp) {
|
|||
selectSubStyle(rp.secondaryStyle);
|
||||
|
||||
runepage = rp;
|
||||
uint32_t offset = 0;
|
||||
for(RuneAspektButtonGroup* group : groups) {
|
||||
if(!group) continue;
|
||||
|
||||
QVector<int> selected(group->getSize(), 0);
|
||||
for(uint32_t i = 0; i < group->getSize(); ++i) {
|
||||
selected.replace(i, rp.selectedAspects.at(offset));
|
||||
offset++;
|
||||
}
|
||||
group->setSelectedRunes(selected);
|
||||
}
|
||||
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
@ -73,6 +86,8 @@ void RuneEditor::selectStyle(uint32_t id) {
|
|||
runepage.selectedAspects.clear();
|
||||
runepage.selectedAspects.resize(9, 0);
|
||||
|
||||
emit selectPrimary(id);
|
||||
|
||||
clearLayout(ui->substyle);
|
||||
clearLayout(ui->stylePerks);
|
||||
clearLayout(ui->substylePerks);
|
||||
|
@ -80,7 +95,7 @@ void RuneEditor::selectStyle(uint32_t id) {
|
|||
// populate substyles
|
||||
for(int subStyleId : style->allowedSubStyles) {
|
||||
const RuneStyle* substyle = getRuneStyle(subStyleId);
|
||||
QPushButton* subStyleBtn = createStyleButton(*substyle, false);
|
||||
RuneAspektButton* subStyleBtn = createStyleButton(*substyle, false);
|
||||
|
||||
if(!subStyleBtn) continue;
|
||||
|
||||
|
@ -88,6 +103,8 @@ void RuneEditor::selectStyle(uint32_t id) {
|
|||
selectSubStyle(subStyleId);
|
||||
});
|
||||
|
||||
QObject::connect(this, &RuneEditor::selectSecondary, subStyleBtn, &RuneAspektButton::checkSelection);
|
||||
|
||||
ui->substyle->addWidget(subStyleBtn);
|
||||
}
|
||||
|
||||
|
@ -104,10 +121,39 @@ void RuneEditor::selectSubStyle(uint32_t id) {
|
|||
if(substyle) {
|
||||
runepage.secondaryStyle = id;
|
||||
|
||||
emit selectSecondary(id);
|
||||
|
||||
clearLayout(ui->substylePerks);
|
||||
delete groups.at(4);
|
||||
|
||||
QVector<QVector<int>> subgroups;
|
||||
subgroups.reserve(substyle->runeSlots.size());
|
||||
|
||||
// populate perks
|
||||
fillRuneStyle(ui->substylePerks, *substyle, true);
|
||||
RuneAspektButtonGroup* group = new RuneAspektButtonGroup(this, 2);
|
||||
for(size_t idx = 0; idx < substyle->runeSlots.size(); ++idx) {
|
||||
const RuneStyleSlot& rss = substyle->runeSlots.at(idx);
|
||||
QVector<int> subgroup;
|
||||
subgroup.reserve(rss.perks.size());
|
||||
|
||||
if(rss.type != "kMixedRegularSplashable") continue;
|
||||
|
||||
for(int perkNr = 0; perkNr < (int) rss.perks.size(); ++perkNr) {
|
||||
uint32_t perk = rss.perks.at(perkNr);
|
||||
subgroup.append((int) perk);
|
||||
|
||||
RuneAspektButton* aspektBtn = createAspektButton(perk);
|
||||
if(!aspektBtn) continue;
|
||||
|
||||
group->addButton(aspektBtn);
|
||||
|
||||
ui->substylePerks->addWidget(aspektBtn, idx, perkNr);
|
||||
}
|
||||
|
||||
subgroups.append(subgroup);
|
||||
}
|
||||
group->setSubgroups(subgroups);
|
||||
groups.replace(4, group);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,8 +173,20 @@ QString RuneEditor::getName() const {
|
|||
return ui->runepageName->text();
|
||||
}
|
||||
|
||||
void RuneEditor::aspectCliecked() {
|
||||
// do something?
|
||||
const RunePage& RuneEditor::getRunepage() {
|
||||
runepage.selectedAspects.clear();
|
||||
runepage.selectedAspects.resize(9, 0);
|
||||
|
||||
for(const RuneAspektButtonGroup* group : groups) {
|
||||
if(!group) continue;
|
||||
|
||||
const QVector<int>& selected = group->getSelectedRunes();
|
||||
for(uint32_t i = 0; i < group->getSize(); ++i) {
|
||||
runepage.selectedAspects.push_back(selected.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
return runepage;
|
||||
}
|
||||
|
||||
const RuneStyle* RuneEditor::getRuneStyle(uint32_t id) const {
|
||||
|
@ -140,12 +198,14 @@ const RuneStyle* RuneEditor::getRuneStyle(uint32_t id) const {
|
|||
}
|
||||
|
||||
RuneAspektButton* RuneEditor::createStyleButton(const RuneStyle& rs, bool selected) {
|
||||
RuneAspektButton* styleBtn = createButtonFromResource(QString::fromStdString(rs.iconPath));
|
||||
RuneAspektButton* styleBtn = createButtonFromResource(rs.iconPath);
|
||||
|
||||
if(!styleBtn) return nullptr;
|
||||
|
||||
styleBtn->setText(QString::fromStdString(rs.name));
|
||||
styleBtn->setToolTip(QString::fromStdString(rs.tooltip));
|
||||
styleBtn->setText(rs.name);
|
||||
styleBtn->setToolTip(rs.tooltip);
|
||||
|
||||
styleBtn->setAspektId(rs.id);
|
||||
|
||||
if(selected) {
|
||||
styleBtn->setStyleSheet("border: 1px solid red;");
|
||||
|
@ -154,16 +214,20 @@ RuneAspektButton* RuneEditor::createStyleButton(const RuneStyle& rs, bool select
|
|||
return styleBtn;
|
||||
}
|
||||
|
||||
RuneAspektButton* RuneEditor::createAspektButton(const RuneAspekt& ra) {
|
||||
RuneAspektButton* aspektBtn = createButtonFromResource(QString::fromStdString(ra.iconPath));
|
||||
RuneAspektButton* RuneEditor::createAspektButton(uint32_t perk) {
|
||||
auto itFound = std::find_if(aspekts.cbegin(), aspekts.cend(), [perk](const RuneAspekt& ra) {
|
||||
return ra.id == perk;
|
||||
});
|
||||
|
||||
if(!aspektBtn) return nullptr;
|
||||
if(itFound == aspekts.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
RuneAspektButton* aspektBtn = createButtonFromResource(itFound->iconPath);
|
||||
|
||||
aspektBtn->setText(QString::fromStdString(ra.name));
|
||||
aspektBtn->setToolTip(QString::fromStdString(ra.tooltip));
|
||||
aspektBtn->setText(itFound->name);
|
||||
aspektBtn->setToolTip(itFound->tooltip);
|
||||
|
||||
aspektBtn->setAspektsVector(runepage.selectedAspects);
|
||||
aspektBtn->setAspektId(ra.id);
|
||||
aspektBtn->setAspektId(itFound->id);
|
||||
|
||||
return aspektBtn;
|
||||
}
|
||||
|
@ -187,51 +251,26 @@ RuneAspektButton* RuneEditor::createButtonFromResource(QString resource) {
|
|||
RuneAspektButton* rab = new RuneAspektButton(this);
|
||||
rab->setIcon(icon);
|
||||
|
||||
QObject::connect(this, &RuneEditor::selectionChanged, rab, &RuneAspektButton::dataChanged);
|
||||
QObject::connect(rab, &RuneAspektButton::aspektToggled, this, &RuneEditor::aspectCliecked);
|
||||
QObject::connect(rab, &RuneAspektButton::aspektToggled, this, &RuneEditor::selectionChanged);
|
||||
|
||||
return rab;
|
||||
}
|
||||
|
||||
void RuneEditor::fillRuneStyle(QGridLayout* target, const RuneStyle& rs, bool subRunes) {
|
||||
int row = 0;
|
||||
void RuneEditor::fillRuneStyle(QGridLayout* target, const RuneStyle& rs) {
|
||||
for(size_t idx = 0; idx < rs.runeSlots.size(); ++idx) {
|
||||
const RuneStyleSlot& rss = rs.runeSlots.at(idx);
|
||||
|
||||
if(subRunes && rss.type != "kMixedRegularSplashable") continue;
|
||||
|
||||
int rowOffset = 0;
|
||||
if(subRunes) {
|
||||
rowOffset = 4;
|
||||
if(row > 0) {
|
||||
rowOffset = 3;
|
||||
}
|
||||
} else {
|
||||
if(row >= 4) {
|
||||
rowOffset = 2;
|
||||
}
|
||||
}
|
||||
RuneAspektButtonGroup* group = new RuneAspektButtonGroup(this, 1);
|
||||
|
||||
for(int perkNr = 0; perkNr < (int) rss.perks.size(); ++perkNr) {
|
||||
uint32_t perk = rss.perks.at(perkNr);
|
||||
auto itFound = std::find_if(aspekts.cbegin(), aspekts.cend(), [perk](const RuneAspekt& ra) {
|
||||
return ra.id == perk;
|
||||
});
|
||||
|
||||
if(itFound == aspekts.cend()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RuneAspektButton* aspektBtn = createAspektButton(*itFound);
|
||||
RuneAspektButton* aspektBtn = createAspektButton(perk);
|
||||
if(!aspektBtn) continue;
|
||||
|
||||
aspektBtn->setAspketSlot(row + rowOffset);
|
||||
group->addButton(aspektBtn);
|
||||
|
||||
target->addWidget(aspektBtn, row, perkNr);
|
||||
target->addWidget(aspektBtn, idx, perkNr);
|
||||
}
|
||||
|
||||
++ row;
|
||||
groups.replace(idx + (idx > 3), group);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ void RuneManager::setRunesEnabled(bool enabled) {
|
|||
void RuneManager::saveRunePageClient(int id, QString name, const RunePage& rp) {
|
||||
if(client) {
|
||||
ClientAPI::RunePage newPage;
|
||||
newPage.name = name.toStdString();
|
||||
newPage.name = name;
|
||||
newPage.runepage = rp;
|
||||
newPage.id = id;
|
||||
|
||||
|
|
|
@ -53,3 +53,7 @@ RunePage::RunePage(const QJsonObject& obj) :
|
|||
std::ostream& operator<<(std::ostream& str, const RunePage& rp) {
|
||||
return str << "Primary: " << rp.primaryStyle << " Secondary: " << rp.secondaryStyle << " aspects: " << rp.selectedAspects.size();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug str, const RunePage& rp) {
|
||||
return str << "Primary: " << rp.primaryStyle << " Secondary: " << rp.secondaryStyle << " aspects: " << rp.selectedAspects.size();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <QTextStream>
|
||||
|
||||
#include "clipboardpopup.h"
|
||||
#include "datadragon.h"
|
||||
#include "runeeditor.h"
|
||||
|
||||
RunePageList::RunePageList(QWidget* parent) : QListWidget(parent), ui(new Ui::RunePageList) {
|
||||
|
@ -25,7 +24,7 @@ RunePageList::~RunePageList() {
|
|||
void RunePageList::loadRunePages(const std::vector<ClientAPI::RunePage>& pages) {
|
||||
clearItems();
|
||||
for(const ClientAPI::RunePage& rp : pages) {
|
||||
addRunepageItem(QString::fromStdString(rp.name), rp.id, rp.runepage, rp.isCurrent);
|
||||
addRunepageItem(rp.name, rp.id, rp.runepage, rp.isCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,12 +200,10 @@ void RunePageList::addRunepageItem(QString name, int id, const ::RunePage& rp, b
|
|||
item->setData(RoleId, (uint) id);
|
||||
item->setData(RolePointer, (qulonglong) new ::RunePage(rp));
|
||||
|
||||
if(dd) {
|
||||
const DataDragon::ChampData& champData = dd->getBestMatchingChamp(name.toStdString());
|
||||
if(champData.key != -1) {
|
||||
QPixmap iamge = dd->getImage(champData.id);
|
||||
item->setIcon(iamge);
|
||||
}
|
||||
const DataDragon::ChampData& champData = findChamp(name);
|
||||
if(champData.key != -1) {
|
||||
QPixmap iamge = dd->getImage(champData.id);
|
||||
item->setIcon(iamge);
|
||||
}
|
||||
|
||||
QString tooltipStr;
|
||||
|
@ -223,6 +220,48 @@ void RunePageList::addRunepageItem(QString name, int id, const ::RunePage& rp, b
|
|||
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);
|
||||
|
@ -244,7 +283,7 @@ QString RunePageList::getRuneText(uint32_t id) {
|
|||
if(runeInfo != nullptr) {
|
||||
for(const RuneAspekt& ra : *runeInfo) {
|
||||
if(ra.id == id) {
|
||||
return QString::fromStdString(ra.name);
|
||||
return ra.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +296,7 @@ QString RunePageList::getRuneStyleByID(uint32_t id) {
|
|||
auto it = std::find_if(runeStyles->begin(), runeStyles->end(), [id](const RuneStyle& rs) { return rs.id == id; });
|
||||
|
||||
if(it != runeStyles->end()) {
|
||||
return QString::fromStdString(it->name);
|
||||
return it->name;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include <algorithm>
|
||||
#include <Log.h>
|
||||
|
||||
static std::vector<std::string> toChampionNameList(const std::vector<StageSettings::SelectedChamp>& scs) {
|
||||
std::vector<std::string> out;
|
||||
static std::vector<QString> toChampionNameList(const std::vector<StageSettings::SelectedChamp>& scs) {
|
||||
std::vector<QString> out;
|
||||
out.reserve(scs.size());
|
||||
|
||||
std::transform(scs.begin(), scs.end(), std::insert_iterator(out, out.begin()), [](const StageSettings::SelectedChamp& sc) { return sc.name; });
|
||||
|
@ -42,7 +42,7 @@ bool SettingsTab::getState(LolAutoAccept::State s) const {
|
|||
return stage->getState();
|
||||
}
|
||||
|
||||
void SettingsTab::setChamps(LolAutoAccept::State s, const std::vector<std::string>& c) {
|
||||
void SettingsTab::setChamps(LolAutoAccept::State s, const std::vector<QString>& c) {
|
||||
getStage(s)->setChampions(c);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,23 +39,23 @@ void StageSettings::setState(bool b) {
|
|||
updateEnabled();
|
||||
}
|
||||
|
||||
StageSettings::SelectedChamp::SelectedChamp(std::string name, uint32_t id) : name(name), id(id) {}
|
||||
StageSettings::SelectedChamp::SelectedChamp(QString 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());
|
||||
out.emplace_back(cr->getChamp(), cr->getChampID());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void StageSettings::setChampions(const std::vector<std::string>& champs) {
|
||||
void StageSettings::setChampions(const std::vector<QString>& champs) {
|
||||
clear();
|
||||
|
||||
// add new champs
|
||||
for(const std::string& champ : champs) {
|
||||
for(const QString& champ : champs) {
|
||||
resolveAndAddChamp(champ, champ == champs.back());
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ void StageSettings::addChamp() {
|
|||
// popup with champion search
|
||||
ChampionSearch cs(dd, this);
|
||||
int res = cs.exec();
|
||||
Log::info << "championsearch result: " << res;
|
||||
qInfo() << "championsearch result: " << res;
|
||||
if(res == QDialog::Accepted) {
|
||||
auto cr = cs.getSearchResult();
|
||||
if(cr) {
|
||||
|
@ -110,7 +110,7 @@ void StageSettings::moved() {
|
|||
emit championsChanged();
|
||||
}
|
||||
|
||||
void StageSettings::resolveAndAddChamp(const std::string& name, bool emitchange) {
|
||||
void StageSettings::resolveAndAddChamp(const QString& name, bool emitchange) {
|
||||
if(dd) {
|
||||
int count = 0;
|
||||
auto cd = dd->getBestMatchingChamp(name, &count);
|
||||
|
@ -122,7 +122,7 @@ void StageSettings::resolveAndAddChamp(const std::string& name, bool emitchange)
|
|||
}
|
||||
});
|
||||
} else {
|
||||
Log::error << __PRETTY_FUNCTION__ << " Datadragon not set!";
|
||||
qCritical() << __PRETTY_FUNCTION__ << " Datadragon not set!";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoadingWindow</class>
|
||||
<widget class="QWidget" name="LoadingWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>739</width>
|
||||
<height>176</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>LoL-Auto-Accept</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/lolautoaccept.svg</normaloff>:/lolautoaccept.svg</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/res.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -19,6 +19,10 @@
|
|||
<property name="windowTitle">
|
||||
<string>LoL-Auto-Accept</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../resources/res.qrc">
|
||||
<normaloff>:/lolautoaccept.svg</normaloff>:/lolautoaccept.svg</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="centralGridLayout">
|
||||
<property name="sizeConstraint">
|
||||
|
|
Loading…
Reference in New Issue