Skip to content
This repository has been archived by the owner on Jun 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #24 from r52/client-log
Browse files Browse the repository at this point in the history
Client log features
  • Loading branch information
r52 authored Jan 28, 2020
2 parents 96cfbb7 + c099cda commit df00a57
Show file tree
Hide file tree
Showing 17 changed files with 423 additions and 40 deletions.
2 changes: 2 additions & 0 deletions PTA/PTA.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
</QtRcc>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="clientmonitor.cpp" />
<ClCompile Include="configdialog.cpp" />
<ClCompile Include="configpages.cpp" />
<ClCompile Include="itemapi.cpp" />
Expand Down Expand Up @@ -137,6 +138,7 @@
</ItemGroup>
<ItemGroup>
<QtMoc Include="macrohandler.h" />
<QtMoc Include="clientmonitor.h" />
<ClInclude Include="putil.h" />
<ClInclude Include="version.h" />
<QtMoc Include="statdialog.h">
Expand Down
6 changes: 6 additions & 0 deletions PTA/PTA.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
<ClCompile Include="putil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="clientmonitor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="pta.h">
Expand All @@ -87,6 +90,9 @@
<QtMoc Include="macrohandler.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="clientmonitor.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<QtUic Include="pta.ui">
Expand Down
Binary file added PTA/Resources/client.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
179 changes: 179 additions & 0 deletions PTA/clientmonitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#include "clientmonitor.h"

#include "pta_types.h"

#include <QDebug>
#include <QFileInfo>
#include <QRegularExpression>
#include <QSettings>
#include <QTimer>

using namespace std::chrono_literals;

const std::chrono::milliseconds ClientMonitor::polling_rate = 350ms;

ClientMonitor::ClientMonitor(QObject* parent) : QObject(parent), m_enabled(false), m_last_whisper(QString())
{
QSettings settings;

QString logpath = settings.value(PTA_CONFIG_CLIENTLOG_PATH, QString()).toString();

if (logpath.isEmpty())
{
qInfo() << "Client.txt path not set. Client features disabled.";
}
else
{
setPath(logpath);
}
}

ClientMonitor::~ClientMonitor()
{
m_watcher.reset();
}

void ClientMonitor::setPath(QString logpath)
{
if (logpath.isEmpty())
{
// If empty path, disable monitor
m_enabled = false;

// Clear file watcher
if (m_watcher)
{
m_watcher.reset();
}

m_logpath.clear();

return;
}

if (!QFileInfo::exists(logpath))
{
qWarning() << "Client log file not found at" << logpath;
return;
}

if (m_logpath == logpath)
{
// Same file
return;
}

m_logpath = logpath;

// Pre-read size
QFile log(m_logpath);

if (!log.open(QIODevice::ReadOnly | QIODevice::Text))
{
qWarning() << "Cannot process client log file found at" << m_logpath;
return;
}

m_lastpos = log.size();

log.close();

m_watcher.reset(new QTimer(this));

connect(m_watcher.get(), &QTimer::timeout, this, &ClientMonitor::processLogChange);
m_watcher->start(polling_rate);

m_enabled = true;

qInfo() << "Client.txt set to" << m_logpath;
}

bool ClientMonitor::enabled()
{
return m_enabled;
}

QString ClientMonitor::getLastWhisperer()
{
return m_last_whisper;
}

void ClientMonitor::processLogLine(QString line)
{
auto parts = line.splitRef("] ", QString::SkipEmptyParts);

if (parts.size() < 2)
{
// If not a game info line, skip
return;
}

// Get last part
auto ltxt = parts[parts.size() - 1].trimmed().toString();

if (ltxt.startsWith('@'))
{
// Whisper

// Remove whisper tags
ltxt.remove(QRegularExpression("^@(From|To) (<\\S+> )?"));

auto msgparts = ltxt.splitRef(": ", QString::SkipEmptyParts);

if (msgparts.size() < 1)
{
qWarning() << "Error parsing whisper text:" << ltxt;
return;
}

auto pname = msgparts[0].toString();

m_last_whisper = pname;
}
}

void ClientMonitor::processLogChange()
{
if (!enabled())
{
// Shouldn't ever get here
return;
}

QFile log(m_logpath);

if (!log.open(QIODevice::ReadOnly | QIODevice::Text))
{
qWarning() << "Cannot process client log file found at" << m_logpath;
return;
}

qint64 lastpos = log.size();

if (lastpos < m_lastpos)
{
// File got reset, so reset our position too
m_lastpos = lastpos;
return;
}

if (lastpos == m_lastpos)
{
// No change
return;
}

// Start reading from
log.seek(m_lastpos);

QTextStream in(&log);
while (!in.atEnd())
{
QString line = in.readLine();
processLogLine(line);
}

m_lastpos = lastpos;

log.close();
}
41 changes: 41 additions & 0 deletions PTA/clientmonitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <chrono>

#include <QObject>

class QTimer;

class ClientMonitor : public QObject
{
Q_OBJECT

public:
ClientMonitor(QObject* parent = nullptr);
~ClientMonitor();

void setPath(QString logpath);

bool enabled();

QString getLastWhisperer();

private slots:
void processLogChange();
void processLogLine(QString line);

private:
static const std::chrono::milliseconds polling_rate;

// We are FORCED to use a polling technique for Client.txt because it doesn't flush AT ALL
// unless the file is accessed externally. This renders functions like QFileSystemWatcher and
// even the WinAPI ReadDirectoryChangesW UNUSABLE for our purposes :(.
std::unique_ptr<QTimer> m_watcher;

QString m_logpath;

bool m_enabled;
qint64 m_lastpos = -1;

QString m_last_whisper;
};
7 changes: 7 additions & 0 deletions PTA/configdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ConfigDialog::ConfigDialog(ItemAPI* api)
pagesWidget->addWidget(new HotkeyPage(results));
pagesWidget->addWidget(new PriceCheckPage(results, api));
pagesWidget->addWidget(new MacrosPage(results));
pagesWidget->addWidget(new ClientPage(results));

QPushButton* saveButton = new QPushButton(tr("Save"));
QPushButton* closeButton = new QPushButton(tr("Close"));
Expand Down Expand Up @@ -86,6 +87,12 @@ void ConfigDialog::createIcons()
macroButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
macroButton->setIcon(QIcon(":/Resources/macros.png"));

QListWidgetItem* clientButton = new QListWidgetItem(contentsWidget);
clientButton->setText(tr("Client"));
clientButton->setTextAlignment(Qt::AlignHCenter);
clientButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
clientButton->setIcon(QIcon(":/Resources/client.png"));

connect(contentsWidget, &QListWidget::currentItemChanged, this, &ConfigDialog::changePage);
}

Expand Down
56 changes: 54 additions & 2 deletions PTA/configpages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ PriceCheckPage::PriceCheckPage(json& set, ItemAPI* api, QWidget* parent) : QWidg

QStringList leagues;

for (auto& league : api->getLeagues())
for (const auto& league : api->getLeagues())
{
leagues << QString::fromStdString(league.get<std::string>());
}
Expand Down Expand Up @@ -611,7 +611,7 @@ MacrosPage::MacrosPage(json& set, QWidget* parent) : QWidget(parent)

set[PTA_CONFIG_CUSTOM_MACROS] = macrolist;

for (auto& [k, v] : macrolist.items())
for (const auto& [k, v] : macrolist.items())
{
auto key = QString::fromStdString(k);
auto seq = QString::fromStdString(v["sequence"].get<std::string>());
Expand Down Expand Up @@ -747,4 +747,56 @@ MacrosPage::MacrosPage(json& set, QWidget* parent) : QWidget(parent)
layout->addLayout(buttonLayout);
layout->addStretch(1);
setLayout(layout);
}

ClientPage::ClientPage(json& set, QWidget* parent) : QWidget(parent)
{
QSettings settings;

QGroupBox* configGroup = new QGroupBox(tr("Game Client"));

// ------------------Client Log
QLabel* cliLabel = new QLabel(tr("Client Log location:"));

QLineEdit* fedit = new QLineEdit;
fedit->setText(settings.value(PTA_CONFIG_CLIENTLOG_PATH, QString()).toString());

connect(fedit, &QLineEdit::textChanged, [=, &set](const QString& text) {
if (!text.isEmpty())
{
set[PTA_CONFIG_CLIENTLOG_PATH] = text.toStdString();
}
});

QPushButton* browseButton = new QPushButton(tr("Browse"));
connect(browseButton, &QAbstractButton::clicked, [=]() {
QString defpath = QDir::currentPath();

QString fname = QFileDialog::getOpenFileName(this, tr("Load Client.txt"), defpath, tr("Client.txt (Client.txt)"));

if (!fname.isNull())
{
QFileInfo info(fname);

if (info.exists())
{
fedit->setText(info.absoluteFilePath());
}
}
});

QHBoxLayout* cliLayout = new QHBoxLayout;
cliLayout->addWidget(cliLabel);
cliLayout->addWidget(fedit);
cliLayout->addWidget(browseButton);

QVBoxLayout* configLayout = new QVBoxLayout;
configLayout->addLayout(cliLayout);

configGroup->setLayout(configLayout);

QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addWidget(configGroup);
mainLayout->addStretch(1);
setLayout(mainLayout);
}
8 changes: 8 additions & 0 deletions PTA/configpages.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ class MacrosPage : public QWidget
public:
MacrosPage(json& set, QWidget* parent = 0);
};

class ClientPage : public QWidget
{
Q_OBJECT

public:
ClientPage(json& set, QWidget* parent = 0);
};
Loading

0 comments on commit df00a57

Please sign in to comment.