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

View File

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

View File

@ -7,7 +7,8 @@
#include <QtWidgets/QMessageBox> #include <QtWidgets/QMessageBox>
#include <QtGui/QCloseEvent> #include <QtGui/QCloseEvent>
#include <QtGui/QDesktopServices> #include <QtGui/QDesktopServices>
#include <QtCore/QTimer.h> #include <QtWidgets/QInputDialog>
#include <QtCore/QTimer>
#include <future> #include <future>
@ -40,10 +41,12 @@ CCEngine::CCEngine(
timer->start(0); timer->start(0);
// Connect UI // Connect UI
connect(ui.btnActivate, SIGNAL(clicked(bool)), this, SLOT(onActivate(bool)));
connect(ui.btnActivationDetail, SIGNAL(clicked(bool)), this, SLOT(onActivationDetail(bool))); connect(ui.btnActivationDetail, SIGNAL(clicked(bool)), this, SLOT(onActivationDetail(bool)));
connect(ui.btnRestartServer, SIGNAL(clicked(bool)), this, SLOT(onRestartServer(bool))); connect(ui.btnRestartServer, SIGNAL(clicked(bool)), this, SLOT(onRestartServer(bool)));
connect(ui.btnOpenBrowser, SIGNAL(clicked(bool)), this, SLOT(onOpenBrowser(bool))); connect(ui.btnOpenBrowser, SIGNAL(clicked(bool)), this, SLOT(onOpenBrowser(bool)));
connect(ui.btnUpdatesCheck, SIGNAL(clicked(bool)), this, SLOT(onCheckForUpdates(bool))); connect(ui.btnUpdatesCheck, SIGNAL(clicked(bool)), this, SLOT(onCheckForUpdates(bool)));
connect(ui.btnUpdate, SIGNAL(clicked(bool)), this, SLOT(onInstallUpdates(bool)));
} }
CCEngine::~CCEngine() CCEngine::~CCEngine()
@ -96,6 +99,18 @@ void CCEngine::onLoad()
m_licenseController.init(m_appPath); 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) void CCEngine::onRestartServer(bool)
{ {
if (m_licenseController.isActivated()) 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) void CCEngine::onParamsLoaded(SystemParams hashedParams, SystemParams origParams)
{ {
@ -147,11 +175,11 @@ void CCEngine::onActivationStatusChanged(ActivationStatus activationStatus)
color = "green"; color = "green";
break; break;
case ActivationStatus::checkingPreactivation: case ActivationStatus::checkingPreactivation:
textStatus = tr("Checking"); textStatus = tr("Checking...");
color = "orange"; color = "orange";
break; break;
case ActivationStatus::checkingActivation: case ActivationStatus::checkingActivation:
textStatus = tr("Verifying license"); textStatus = tr("Verifying license...");
color = "orange"; color = "orange";
break; break;
case ActivationStatus::notActive: case ActivationStatus::notActive:
@ -199,7 +227,7 @@ void CCEngine::onUpdatesStatusChanged(UpdatesStatus updatesStatus)
color = "green"; color = "green";
break; break;
case UpdatesStatus::checking: case UpdatesStatus::checking:
textStatus = tr("Checking"); textStatus = tr("Checking...");
color = "orange"; color = "orange";
break; break;
case UpdatesStatus::updatesAvailable: case UpdatesStatus::updatesAvailable:
@ -207,6 +235,14 @@ void CCEngine::onUpdatesStatusChanged(UpdatesStatus updatesStatus)
color = "orange"; color = "orange";
updateEnabled = true; updateEnabled = true;
break; break;
case UpdatesStatus::downloadingUpdates:
textStatus = tr("Downloading...");
color = "orange";
break;
case UpdatesStatus::installingUpdates:
textStatus = tr("Installing...");
color = "orange";
break;
default: default:
textStatus = tr("Unknown"); textStatus = tr("Unknown");
color = "black"; color = "black";
@ -220,6 +256,19 @@ void CCEngine::onUpdates(int count, bool restartRequired)
{ {
ui.lblUpdatesPendingVal->setText(QString("%1").arg(count)); ui.lblUpdatesPendingVal->setText(QString("%1").arg(count));
ui.lblUpdatesPendingVal->setStyleSheet(QString("QLabel { color: %1; }").arg((count > 0) ? "orange" : "green")); 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) void CCEngine::iconActivated(QSystemTrayIcon::ActivationReason reason)
@ -280,4 +329,7 @@ void CCEngine::connectLicenseController()
connect( connect(
&m_licenseController, SIGNAL(updates(int, bool)), &m_licenseController, SIGNAL(updates(int, bool)),
this, SLOT(onUpdates(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 iconActivated(QSystemTrayIcon::ActivationReason reason);
void onCCServerStatusUpdate(CCServerStatus serverStatus); void onCCServerStatusUpdate(CCServerStatus serverStatus);
void onLoad(); void onLoad();
void onActivate(bool);
void onActivationDetail(bool); void onActivationDetail(bool);
void onRestartServer(bool); void onRestartServer(bool);
void onOpenBrowser(bool); void onOpenBrowser(bool);
void onCheckForUpdates(bool); void onCheckForUpdates(bool);
void onInstallUpdates(bool);
// License controller signal handlers // License controller signal handlers
void onParamsLoaded(SystemParams hashedParams, SystemParams origParams); void onParamsLoaded(SystemParams hashedParams, SystemParams origParams);
@ -45,6 +47,7 @@ private slots:
void onActivated(QString activationNumber); void onActivated(QString activationNumber);
void onUpdatesStatusChanged(UpdatesStatus updatesStatus); void onUpdatesStatusChanged(UpdatesStatus updatesStatus);
void onUpdates(int count, bool restartRequired); void onUpdates(int count, bool restartRequired);
void onShutdownRequest();
private: private:
void createActions(); void createActions();

View File

@ -1,9 +1,17 @@
#include "CCLicenseController.h" #include "CCLicenseController.h"
#include "CachedDownloader.h"
#include "JSONModuleDatabase.h" #include "JSONModuleDatabase.h"
#include "JSONSerialization.h"
#include "ProcessUtils.h"
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
namespace
{
static const std::string updateCacheFolder = ".upd";
}
CCLicenseController::CCLicenseController() CCLicenseController::CCLicenseController()
{} {}
@ -21,7 +29,7 @@ void CCLicenseController::init(const boost::filesystem::path& appDir)
{ {
m_workerThread.join(); m_workerThread.join();
} }
m_workerThread = std::thread([&]() m_workerThread = std::thread([this, appDir]()
{ {
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex); std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
try try
@ -69,7 +77,7 @@ void CCLicenseController::activate(const QString &licenseNumber)
{ {
m_workerThread.join(); m_workerThread.join();
} }
m_workerThread = std::thread([&]() m_workerThread = std::thread([this, licenseNumber]()
{ {
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex); std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
@ -116,7 +124,7 @@ void CCLicenseController::checkForUpdates()
{ {
m_workerThread.join(); m_workerThread.join();
} }
m_workerThread = std::thread([&]() m_workerThread = std::thread([this]()
{ {
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex); std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
@ -145,7 +153,83 @@ void CCLicenseController::checkForUpdates()
catch (CouldNotConnectException&) catch (CouldNotConnectException&)
{ {
BOOST_LOG_TRIVIAL(error) << "The application could not check for updates. Probably the computer is offline"; 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."); 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, unknown,
checking, checking,
upToDate, upToDate,
updatesAvailable updatesAvailable,
downloadingUpdates,
installingUpdates
}; };
Q_DECLARE_METATYPE(UpdatesStatus); Q_DECLARE_METATYPE(UpdatesStatus);
@ -45,6 +47,7 @@ public:
void activate(const QString& licenseNumber); void activate(const QString& licenseNumber);
bool isActivated(); bool isActivated();
void checkForUpdates(); void checkForUpdates();
void installUpdates(const boost::filesystem::path& appDir);
public: public:
signals: signals:
@ -54,6 +57,7 @@ signals:
void activated(QString activationNumber); void activated(QString activationNumber);
void updatesStatusChanged(UpdatesStatus updatesStatus); void updatesStatusChanged(UpdatesStatus updatesStatus);
void updates(int count, bool restartRequired); void updates(int count, bool restartRequired);
void shutdownRequest();
private: private:
std::unique_ptr<SystemParamsProvider> m_systemParamsProvider; std::unique_ptr<SystemParamsProvider> m_systemParamsProvider;

View File

@ -1,9 +1,38 @@
#include "CCEngine.h" #include "CCEngine.h"
#include "PlatformInit.h" #include "PlatformInit.h"
#include "OSUtils.h"
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <boost/filesystem.hpp> #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 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[]) 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(); auto appDir = fs::system_complete(a.arguments().at(0).toStdString()).parent_path();
initLogging();
bool justUpdated = false; bool justUpdated = false;
for (int i = 1; i < a.arguments().size(); ++i) for (int i = 1; i < a.arguments().size(); ++i)
{ {

View File

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

View File

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

View File

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