[impl] Logging, Better progress tracking

This commit is contained in:
Peter Sykora 2018-05-01 16:31:07 +02:00
parent 5e6fc4ebee
commit 3bf1971395
11 changed files with 206 additions and 18 deletions

View File

@ -59,7 +59,7 @@
<widget class="QPushButton" name="btnActivationDetail">
<property name="geometry">
<rect>
<x>140</x>
<x>160</x>
<y>20</y>
<width>70</width>
<height>20</height>
@ -78,7 +78,7 @@
</property>
<property name="geometry">
<rect>
<x>220</x>
<x>240</x>
<y>20</y>
<width>70</width>
<height>20</height>
@ -148,7 +148,7 @@
</property>
<property name="geometry">
<rect>
<x>140</x>
<x>160</x>
<y>50</y>
<width>101</width>
<height>20</height>
@ -199,7 +199,7 @@
</property>
<property name="geometry">
<rect>
<x>140</x>
<x>160</x>
<y>20</y>
<width>101</width>
<height>20</height>

View File

@ -144,6 +144,9 @@
<ProjectReference Include="..\..\libLicenseClient\libLicenseClient.vcxproj">
<Project>{51345e59-83e5-4389-93a9-0131b40522b7}</Project>
</ProjectReference>
<ProjectReference Include="..\CCEngineLoader\CCEngineLoader.vcxproj">
<Project>{b12702ad-abfb-343a-a199-8e24837244a3}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">

View File

@ -7,7 +7,8 @@
#include <QtWidgets/QMessageBox>
#include <QtGui/QCloseEvent>
#include <QtGui/QDesktopServices>
#include <QtCore/QTimer.h>
#include <QtWidgets/QInputDialog>
#include <QtCore/QTimer>
#include <future>
@ -40,10 +41,12 @@ CCEngine::CCEngine(
timer->start(0);
// Connect UI
connect(ui.btnActivate, SIGNAL(clicked(bool)), this, SLOT(onActivate(bool)));
connect(ui.btnActivationDetail, SIGNAL(clicked(bool)), this, SLOT(onActivationDetail(bool)));
connect(ui.btnRestartServer, SIGNAL(clicked(bool)), this, SLOT(onRestartServer(bool)));
connect(ui.btnOpenBrowser, SIGNAL(clicked(bool)), this, SLOT(onOpenBrowser(bool)));
connect(ui.btnUpdatesCheck, SIGNAL(clicked(bool)), this, SLOT(onCheckForUpdates(bool)));
connect(ui.btnUpdate, SIGNAL(clicked(bool)), this, SLOT(onInstallUpdates(bool)));
}
CCEngine::~CCEngine()
@ -96,6 +99,18 @@ void CCEngine::onLoad()
m_licenseController.init(m_appPath);
}
void CCEngine::onActivate(bool)
{
bool ok;
QString text = QInputDialog::getText(this, tr("Enter license number"),
tr("License number (example. ABC1-DEF2-GHI3-JKL4-MNO5-PQR6):"), QLineEdit::Normal, QString(), &ok,Qt::WindowFlags(), Qt::ImhPreferUppercase | Qt::ImhNoPredictiveText);
if (ok && !text.isEmpty())
{
m_licenseController.activate(text);
}
}
void CCEngine::onRestartServer(bool)
{
if (m_licenseController.isActivated())
@ -131,6 +146,19 @@ void CCEngine::onCheckForUpdates(bool)
}
}
void CCEngine::onInstallUpdates(bool)
{
if (m_licenseController.isActivated())
{
auto reply = QMessageBox::question(this, "Confirm", "Are you sure to download and install updates?<br>After the downloades are updated the application might need to be restarted. Please confirm to continue.",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes)
{
m_licenseController.installUpdates(m_appPath);
}
}
}
void CCEngine::onParamsLoaded(SystemParams hashedParams, SystemParams origParams)
{
@ -147,11 +175,11 @@ void CCEngine::onActivationStatusChanged(ActivationStatus activationStatus)
color = "green";
break;
case ActivationStatus::checkingPreactivation:
textStatus = tr("Checking");
textStatus = tr("Checking...");
color = "orange";
break;
case ActivationStatus::checkingActivation:
textStatus = tr("Verifying license");
textStatus = tr("Verifying license...");
color = "orange";
break;
case ActivationStatus::notActive:
@ -199,7 +227,7 @@ void CCEngine::onUpdatesStatusChanged(UpdatesStatus updatesStatus)
color = "green";
break;
case UpdatesStatus::checking:
textStatus = tr("Checking");
textStatus = tr("Checking...");
color = "orange";
break;
case UpdatesStatus::updatesAvailable:
@ -207,6 +235,14 @@ void CCEngine::onUpdatesStatusChanged(UpdatesStatus updatesStatus)
color = "orange";
updateEnabled = true;
break;
case UpdatesStatus::downloadingUpdates:
textStatus = tr("Downloading...");
color = "orange";
break;
case UpdatesStatus::installingUpdates:
textStatus = tr("Installing...");
color = "orange";
break;
default:
textStatus = tr("Unknown");
color = "black";
@ -220,6 +256,19 @@ void CCEngine::onUpdates(int count, bool restartRequired)
{
ui.lblUpdatesPendingVal->setText(QString("%1").arg(count));
ui.lblUpdatesPendingVal->setStyleSheet(QString("QLabel { color: %1; }").arg((count > 0) ? "orange" : "green"));
if (count > 0)
{
if (qApp->activeWindow() == nullptr && qApp->focusWidget() == nullptr)
{
trayIcon->showMessage("CCEngine", tr("Updates found. Please open the application and click \"Update\" to install them."));
}
}
}
void CCEngine::onShutdownRequest()
{
qApp->quit();
}
void CCEngine::iconActivated(QSystemTrayIcon::ActivationReason reason)
@ -280,4 +329,7 @@ void CCEngine::connectLicenseController()
connect(
&m_licenseController, SIGNAL(updates(int, bool)),
this, SLOT(onUpdates(int, bool)));
connect(
&m_licenseController, SIGNAL(shutdownRequest()),
this, SLOT(onShutdownRequest()));
}

View File

@ -33,10 +33,12 @@ private slots:
void iconActivated(QSystemTrayIcon::ActivationReason reason);
void onCCServerStatusUpdate(CCServerStatus serverStatus);
void onLoad();
void onActivate(bool);
void onActivationDetail(bool);
void onRestartServer(bool);
void onOpenBrowser(bool);
void onCheckForUpdates(bool);
void onInstallUpdates(bool);
// License controller signal handlers
void onParamsLoaded(SystemParams hashedParams, SystemParams origParams);
@ -45,6 +47,7 @@ private slots:
void onActivated(QString activationNumber);
void onUpdatesStatusChanged(UpdatesStatus updatesStatus);
void onUpdates(int count, bool restartRequired);
void onShutdownRequest();
private:
void createActions();

View File

@ -1,9 +1,17 @@
#include "CCLicenseController.h"
#include "CachedDownloader.h"
#include "JSONModuleDatabase.h"
#include "JSONSerialization.h"
#include "ProcessUtils.h"
#include <boost/log/trivial.hpp>
namespace
{
static const std::string updateCacheFolder = ".upd";
}
CCLicenseController::CCLicenseController()
{}
@ -21,7 +29,7 @@ void CCLicenseController::init(const boost::filesystem::path& appDir)
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
m_workerThread = std::thread([this, appDir]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
try
@ -69,7 +77,7 @@ void CCLicenseController::activate(const QString &licenseNumber)
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
m_workerThread = std::thread([this, licenseNumber]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
@ -116,7 +124,7 @@ void CCLicenseController::checkForUpdates()
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
m_workerThread = std::thread([this]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
@ -145,7 +153,83 @@ void CCLicenseController::checkForUpdates()
catch (CouldNotConnectException&)
{
BOOST_LOG_TRIVIAL(error) << "The application could not check for updates. Probably the computer is offline";
emit updatesStatusChanged(UpdatesStatus::unknown);
emit errorMessage("Could not check for updates as the computer seem offline. Please try again later.");
}
catch (std::runtime_error& e)
{
BOOST_LOG_TRIVIAL(error) << "Error during checking for updates: " << e.what();
emit updatesStatusChanged(UpdatesStatus::unknown);
emit errorMessage("Could not check for updates. Please contact support!");
}
});
}
void CCLicenseController::installUpdates(const boost::filesystem::path& appDir)
{
if (m_workerThread.joinable())
{
m_workerThread.join();
}
m_workerThread = std::thread([this, appDir]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
if (m_moduleUpdates.size() < 0)
{
return;
}
emit updatesStatusChanged(UpdatesStatus::downloadingUpdates);
try
{
CachedDownloader cachedDownloader(appDir / updateCacheFolder, m_httpClient);
for (const auto& update : m_moduleUpdates)
{
cachedDownloader.download(update.updateUri);
}
BOOST_LOG_TRIVIAL(info) << "Updates downloaded successfully";
}
catch (CouldNotConnectException&)
{
BOOST_LOG_TRIVIAL(error) << "Could not download updates. Probably the computer is offline";
emit errorMessage("The updates could not be downloaded probably due to not working internet connection!");
}
{
emit updatesStatusChanged(UpdatesStatus::installingUpdates);
{
std::ofstream os((appDir / updateCacheFolder / ".updates.json").native());
::serialize(os, m_moduleUpdates);
}
std::ostringstream command;
command << (appDir / "CCEngineLoader.exe") << " " << getCurrentProcessId();
auto stdOutPipe = createAnonymousPipe(false, true);
auto updProcess = createPipedProcess(command.str(), nullptr, std::move(stdOutPipe));
while (!updProcess.processHandle->waitForExit(std::chrono::milliseconds(0)))
{
auto line = updProcess.readLine();
std::cout << line << std::endl;
if (line == "RestartRequired")
{
emit shutdownRequest();
}
if (line == "Done")
{
BOOST_LOG_TRIVIAL(info) << "The system has been updated successfully";
emit updatesStatusChanged(UpdatesStatus::upToDate);
emit updates(0, false);
updProcess.processHandle->waitForExit();
return;
}
}
emit updatesStatusChanged(UpdatesStatus::unknown);
BOOST_LOG_TRIVIAL(error) << "Failure happend during updates installation";
}
});
}

View File

@ -27,7 +27,9 @@ enum class UpdatesStatus
unknown,
checking,
upToDate,
updatesAvailable
updatesAvailable,
downloadingUpdates,
installingUpdates
};
Q_DECLARE_METATYPE(UpdatesStatus);
@ -45,6 +47,7 @@ public:
void activate(const QString& licenseNumber);
bool isActivated();
void checkForUpdates();
void installUpdates(const boost::filesystem::path& appDir);
public:
signals:
@ -54,6 +57,7 @@ signals:
void activated(QString activationNumber);
void updatesStatusChanged(UpdatesStatus updatesStatus);
void updates(int count, bool restartRequired);
void shutdownRequest();
private:
std::unique_ptr<SystemParamsProvider> m_systemParamsProvider;

View File

@ -1,9 +1,38 @@
#include "CCEngine.h"
#include "PlatformInit.h"
#include "OSUtils.h"
#include <QtWidgets/QApplication>
#include <boost/filesystem.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
namespace fs = boost::filesystem;
namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;
void initLogging()
{
auto logPath = ensureLogFolder("CCEngine");
logging::add_file_log(
keywords::file_name = (logPath / "CCEngine.log").native(),
keywords::format = (
expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
<< ": <" << logging::trivial::severity
<< "> " << expr::smessage)
);
logging::core::get()->set_filter
(
logging::trivial::severity >= logging::trivial::info
);
logging::add_common_attributes();
}
int main(int argc, char *argv[])
{
@ -11,6 +40,8 @@ int main(int argc, char *argv[])
auto appDir = fs::system_complete(a.arguments().at(0).toStdString()).parent_path();
initLogging();
bool justUpdated = false;
for (int i = 1; i < a.arguments().size(); ++i)
{

View File

@ -25,9 +25,14 @@ CCEngineLoader::CCEngineLoader(
timer->start(0);
}
void CCEngineLoader::onProgressChanged(QString info)
void CCEngineLoader::onProgressChanged(UpdateStatus status, QString info)
{
ui.lblInformation->setText(info);
if (status == UpdateStatus::done)
{
qApp->quit();
}
}
void CCEngineLoader::onStartWorker()

View File

@ -16,7 +16,7 @@ public:
QWidget *parent = Q_NULLPTR);
private slots:
void onProgressChanged(QString info);
void onProgressChanged(UpdateStatus, QString info);
void onStartWorker();
private:

View File

@ -90,7 +90,9 @@ namespace
UpdateWorkerThread::UpdateWorkerThread(const boost::filesystem::path& appDir, unsigned parentProcessId)
: m_appDir(appDir)
, m_parentProcessId(parentProcessId)
{}
{
qRegisterMetaType<UpdateStatus>();
}
void UpdateWorkerThread::run()
{
@ -119,10 +121,11 @@ void UpdateWorkerThread::run()
}
std::cout << "Done" << std::endl;
emit progressChanged(UpdateStatus::updatesInstalled, QString("Updated successfully"));
if (isRestartRequired)
{
emit progressChanged(UpdateStatus::restartingApp, QString("Restarting application"));
runApp((m_appDir / "CCEngine.exe").string() + " --updated", false);
}
emit progressChanged(UpdateStatus::done, QString("Updated successfully"));
}

View File

@ -9,9 +9,12 @@ enum class UpdateStatus
loadingUpdateDefinitions,
installingUpdates,
waitingForAppToExit,
updatesInstalled,
restartingApp,
done
};
Q_DECLARE_METATYPE(UpdateStatus);
class UpdateWorkerThread : public QThread
{
Q_OBJECT