Add UI for system params

Make preactivation working with the new QT UI
Make check for updates working
This commit is contained in:
Peter Sykora 2018-04-08 23:29:53 +02:00
parent 0cc651bebb
commit 5e6fc4ebee
18 changed files with 1007 additions and 322 deletions

View File

@ -52,45 +52,8 @@
<height>16</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Active</string>
<string>Unknown</string>
</property>
</widget>
<widget class="QPushButton" name="btnActivationDetail">
@ -102,11 +65,17 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show the system details&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Detail</string>
</property>
</widget>
<widget class="QPushButton" name="btnActivate">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>220</x>
@ -115,6 +84,9 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Run the activation procedure of your copy of Catalogue of Curencies&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Activate</string>
</property>
@ -157,14 +129,23 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Port where the HTTP server listens on&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="inputMask">
<string notr="true"/>
<string notr="true">99999</string>
</property>
<property name="text">
<string>8080</string>
</property>
<property name="maxLength">
<number>5</number>
</property>
</widget>
<widget class="QPushButton" name="btnOpenBrowser">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
@ -173,6 +154,9 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open default browser to browse the content of Catalogue of Currencies&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Open browser</string>
</property>
@ -205,48 +189,14 @@
<height>16</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Running</string>
<string>Stopped</string>
</property>
</widget>
<widget class="QPushButton" name="btnRestartServer">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
@ -255,6 +205,9 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Restarts the HTTP server that serves the content of Catalogue of currencies&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Restart</string>
</property>
@ -300,48 +253,17 @@
<height>16</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Indicates whether your application and data is up to date or there are some updates pending&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Up to date</string>
<string>Unknown</string>
</property>
</widget>
<widget class="QPushButton" name="btnUpdatesCheck">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>240</x>
@ -350,11 +272,17 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Checks for updates of the application and the content. Please note that internet connection is required.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Check for updates</string>
</property>
</widget>
<widget class="QPushButton" name="btnUpdate">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>240</x>
@ -363,6 +291,9 @@
<height>20</height>
</rect>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Runs update procedure in order to update application or the content&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Update</string>
</property>
@ -389,45 +320,8 @@
<height>16</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>150</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>0</string>
<string>N/A</string>
</property>
</widget>
</widget>

View File

@ -68,9 +68,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WIN32;_SCL_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libLicenseClient\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libLicenseClient\api;.\GeneratedFiles;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpplatest</LanguageStandard>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@ -80,6 +80,10 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<QtMoc>
<IncludePath>$(ProjectDir)..\..\libLicenseClient\api;.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtWidgets;$(CRYPTOPP_ROOT_DIR)include;$(LIBZIP_ROOT_DIR)include;$(ZLIB_ROOT_DIR)include;$(LIBCURL_ROOT_DIR)include;$(BOOST_ROOT_DIR)\.</IncludePath>
<Define>_WIN32_WINNT=0x0601;WIN32;_SCL_SECURE_NO_WARNINGS;_DEBUG;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;CURL_STATICLIB;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING;_MBCS</Define>
</QtMoc>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -87,9 +91,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WIN32;NDEBUG;%(PreprocessorDefinitions);BOOST_EXCEPTION_DISABLE</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WIN32;_SCL_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions);BOOST_EXCEPTION_DISABLE</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libLicenseClient\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\libLicenseClient\api;.\GeneratedFiles;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
@ -102,35 +106,45 @@
<FullProgramDatabaseFile>false</FullProgramDatabaseFile>
</Link>
<QtMoc>
<Define>WIN32;_MBCS;CURL_STATICLIB;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING;%(Define)</Define>
<IncludePath>$(BOOST_ROOT_DIR);%(IncludePath)</IncludePath>
<Define>_WIN32_WINNT=0x0601;WIN32;_SCL_SECURE_NO_WARNINGS;NDEBUG;BOOST_EXCEPTION_DISABLE;QT_NO_DEBUG;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;CURL_STATICLIB;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING;_MBCS</Define>
<IncludePath>$(ProjectDir)..\..\libLicenseClient\api;.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtWidgets;$(CRYPTOPP_ROOT_DIR)include;$(LIBZIP_ROOT_DIR)include;$(ZLIB_ROOT_DIR)include;$(LIBCURL_ROOT_DIR)include;$(BOOST_ROOT_DIR)\.</IncludePath>
</QtMoc>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\CCEngine.cpp" />
<ClCompile Include="src\CCLicenseController.cpp" />
<ClCompile Include="src\CCServer.cpp" />
<ClCompile Include="src\CCServerManager.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\ProcessUtils.cpp" />
<ClCompile Include="src\SystemParamsDlg.cpp" />
<ClCompile Include="src\SystemParamsModel.cpp" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\SystemParamsModel.h" />
<QtMoc Include="src\SystemParamsDlg.h" />
<QtMoc Include="src\CCEngine.h" />
<QtMoc Include="src\CCLicenseController.h" />
<ClInclude Include="src\CCServer.h" />
<QtMoc Include="src\CCServerManager.h" />
<ClInclude Include="src\PlatformInit.h" />
<ClInclude Include="src\ProcessUtils.h" />
</ItemGroup>
<ItemGroup>
<QtUic Include="CCEngine.ui" />
<QtUic Include="SystemParameters.ui" />
</ItemGroup>
<ItemGroup>
<QtRcc Include="CCEngine.qrc" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="CCEngine.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libLicenseClient\libLicenseClient.vcxproj">
<Project>{51345e59-83e5-4389-93a9-0131b40522b7}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />

View File

@ -9,6 +9,9 @@
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Form Files">
<UniqueIdentifier>{60322e81-4907-489e-87af-66b7f5778503}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CCEngine.cpp">
@ -20,6 +23,21 @@
<ClCompile Include="src\ProcessUtils.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\CCServerManager.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\SystemParamsDlg.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\SystemParamsModel.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="src\CCLicenseController.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CCServer.h">
@ -28,5 +46,43 @@
<ClInclude Include="src\ProcessUtils.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="src\PlatformInit.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="CCEngine.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<QtRcc Include="CCEngine.qrc">
<Filter>Resource Files</Filter>
</QtRcc>
</ItemGroup>
<ItemGroup>
<QtUic Include="CCEngine.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="SystemParameters.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\CCEngine.h">
<Filter>src</Filter>
</QtMoc>
<QtMoc Include="src\CCServerManager.h">
<Filter>src</Filter>
</QtMoc>
<QtMoc Include="src\SystemParamsDlg.h">
<Filter>src</Filter>
</QtMoc>
<QtMoc Include="src\SystemParamsModel.h">
<Filter>src</Filter>
</QtMoc>
<QtMoc Include="src\CCLicenseController.h">
<Filter>src</Filter>
</QtMoc>
</ItemGroup>
</Project>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SystemParametersDialog</class>
<widget class="QDialog" name="SystemParametersDialog">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>616</width>
<height>293</height>
</rect>
</property>
<property name="windowTitle">
<string>System parameters</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,1">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<widget class="QTableView" name="tblSystemParams">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; The above parameters works as system fingerprint for licensing purposes. For privacy reasons only the hashed values are shared with the application vendor. The original values are not shared with anybody.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SystemParametersDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SystemParametersDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,187 +1,283 @@
#include "CachedDownloader.h"
#include "SystemParamsProvider_win.h"
#include "HTTPClient.h"
#include "LicenseClient.h"
#include "CCServer.h"
#include "ModuleManager.h"
#include "JSONModuleDatabase.h"
#include "ProcessUtils.h"
#include "CCEngine.h"
#include <boost/filesystem.hpp>
#include "SystemParamsProvider.h"
#include "SystemParamsDlg.h"
#include <iostream>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>
#include <QtGui/QCloseEvent>
#include <QtGui/QDesktopServices>
#include <QtCore/QTimer.h>
//------------------------------------------------------------------------------
#include <future>
namespace
CCEngine::CCEngine(
const boost::filesystem::path& appPath,
bool justUpdated,
QWidget *parent)
: QMainWindow(parent)
, m_appPath(appPath)
{
static const std::string updateCacheFolder = ".upd";
qRegisterMetaType<CCServerStatus>();
qRegisterMetaType<ActivationStatus>();
qRegisterMetaType<UpdatesStatus>();
ui.setupUi(this);
createActions();
createTrayIcon();
trayIcon->show();
setFixedSize(QSize(400, 300));
setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
connectLicenseController();
connectServerManager();
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, SIGNAL(timeout()), this, SLOT(onLoad()), Qt::ConnectionType::QueuedConnection);
timer->start(0);
// Connect UI
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)));
}
int main(int argc, char* argv[])
CCEngine::~CCEngine()
{
auto appDir = boost::filesystem::system_complete(argv[0]).parent_path();
SystemParamsProvider_win idProvider;
}
HTTPClient httpClient;
LicenseClient licenseClient(idProvider, (appDir / "license.dat").string());
licenseClient.init();
void CCEngine::closeEvent(QCloseEvent * event)
{
hide();
trayIcon->showMessage("CCEngine", tr("The program will keep running in the "
"system tray. To terminate the program, "
"choose \"Quit\" in the context menu "
"of the system tray entry."));
event->ignore();
}
if (!licenseClient.isActivated())
void CCEngine::onCCServerStatusUpdate(CCServerStatus serverStatus)
{
QString textStatus;
QString color;
bool dataBrowsable = false;
switch (serverStatus)
{
try
{
if (!licenseClient.tryPreactivate(httpClient))
{
std::string licenseKey;
std::cout << "Your installation is not yet activated." << std::endl <<
"Please enter license key: ";
std::getline(std::cin, licenseKey);
auto validLicenseKey = validateLicenseKey(licenseKey);
if (!validLicenseKey)
{
throw std::runtime_error("Invalid license key. Please try again.");
}
else if (!licenseClient.activate(httpClient, validLicenseKey.value()))
{
throw std::runtime_error("Activation failed. Please try again.");
}
}
}
catch (CouldNotConnectException&)
{
std::cerr << "Error: The system could not be activated since your system seems offline. Please check your internet connection!" << std::endl;
throw;
}
case CCServerStatus::serving:
textStatus = tr("Serving");
color = "green";
dataBrowsable = true;
break;
case CCServerStatus::starting:
textStatus = tr("Starting");
color = "orange";
break;
case CCServerStatus::stopped:
textStatus = tr("Stopped");
color = "red";
break;
case CCServerStatus::unknown:
default:
textStatus = tr("Unknown");
color = "black";
}
JSONModuleDatabase moduleDatabase((appDir / ".inst").string());
auto currentModules = moduleDatabase.listModules();
std::vector<ModuleUpdate> moduleUpdates;
try
ui.lblHttpServerStatusVal->setText(textStatus);
ui.lblHttpServerStatusVal->setStyleSheet(QString("QLabel { color: %1; }").arg(color));
ui.btnOpenBrowser->setEnabled(dataBrowsable);
}
void CCEngine::onLoad()
{
m_licenseController.init(m_appPath);
}
void CCEngine::onRestartServer(bool)
{
if (m_licenseController.isActivated())
{
moduleUpdates = licenseClient.checkForUpdates(httpClient, currentModules);
m_port = ui.txtPort->text().toUShort();
m_ccServerManager.listen("127.0.0.1", m_port, (boost::filesystem::path(m_appPath) / "data").string(), 4);
}
catch (CouldNotConnectException&)
}
void CCEngine::onActivationDetail(bool)
{
auto result = std::async([]()
{
std::cout << "Warning: Could not check for udates since your system looks offlince" << std::endl;
}
bool restartRequired = false;
if (!moduleUpdates.empty())
{
char what;
std::cout << "Updates available. Do you want to update now? [yn]: ";
std::cin >> what;
if (what == 'y')
{
{
CachedDownloader cachedDownloader(appDir / updateCacheFolder, httpClient);
for (const auto& update : moduleUpdates)
{
cachedDownloader.download(update.updateUri);
}
std::ofstream os((appDir / updateCacheFolder / ".updates.json").native());
::serialize(os, moduleUpdates);
}
std::ostringstream command;
command << (appDir / "CCEngineLoader.exe") << " " << getCurrentProcessId();
auto stdOutPipe = createAnonymousPipe(false, true);
auto updProcess = createPipedProcess(command.str(), nullptr, std::move(stdOutPipe));
while (1)
{
auto line = updProcess.readLine();
std::cout << line << std::endl;
if (line == "RestartRequired")
{
// Exit the current application to allow updater to continue
return 0;
}
}
// ModuleManager moduleManager(appDir.string(), moduleDatabase, httpClient);
// for (const auto& update : moduleUpdates)
// {
// restartRequired = restartRequired || (update.flag & static_cast<uint32_t>(ModuleUpdateFlags::restartRequired));
// moduleManager.applyUpdate(update.moduleId, update);
// }
}
}
auto docRoot = appDir / "data";
CCServer server("127.0.0.1", 8080, docRoot.string(), 4);
server.run();
char c = 0;
while (c != 'q')
{
std::cin >> c;
}
server.shutdown();
/* if (!licenseManager->isActivated())
{
activate(systemId);
}
if (!licenseManager->checkActivation(systemId))
{
throw std::runtime_error("Integrity error. Please contact support.");
} */
// Check command line arguments.
/*
if (argc != 5)
{
std::cerr <<
"Usage: ccengine <address> <port> <doc_root> <threads>\n" <<
"Example:\n" <<
" advanced-server 0.0.0.0 8080 . 1\n";
return EXIT_FAILURE;
}
auto const address = boost::asio::ip::make_address(argv[1]);
auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
std::string const doc_root = argv[3];
auto const threads = std::max<int>(1, std::atoi(argv[4]));
// The io_context is required for all I/O
boost::asio::io_context ioc{ threads };
// Create and launch a listening port
std::make_shared<listener>(
ioc,
tcp::endpoint{ address, port },
doc_root)->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> v;
v.reserve(threads);
for (auto i = threads - 1; i >= 0; --i)
v.emplace_back(
[&ioc]
{
ioc.run();
SystemParamsProvider p;
return p.retrieveSystemParams();
});
SystemParamsDlg d(result.get());
d.exec();
}
void CCEngine::onOpenBrowser(bool)
{
QDesktopServices::openUrl(QUrl(QString("http://127.0.0.1:%1/").arg(m_port)));
}
void CCEngine::onCheckForUpdates(bool)
{
if (m_licenseController.isActivated())
{
HTTPClient httpClient;
std::ofstream os("testfile.txt", std::ofstream::binary);
m_licenseController.checkForUpdates();
}
}
httpClient.downloadFile("https://github.com/cpp-netlib/cpp-netlib/raw/master/libs/network/example/http_client.cpp", os);
void CCEngine::onParamsLoaded(SystemParams hashedParams, SystemParams origParams)
{
}
void CCEngine::onActivationStatusChanged(ActivationStatus activationStatus)
{
QString textStatus;
QString color;
bool activationEnabled = false;
switch (activationStatus)
{
case ActivationStatus::active:
textStatus = tr("Active");
color = "green";
break;
case ActivationStatus::checkingPreactivation:
textStatus = tr("Checking");
color = "orange";
break;
case ActivationStatus::checkingActivation:
textStatus = tr("Verifying license");
color = "orange";
break;
case ActivationStatus::notActive:
textStatus = tr("Not active");
color = "red";
activationEnabled = true;
break;
default:
textStatus = tr("Unknown");
color = "black";
}
ui.lblActivationStatusVal->setText(textStatus);
ui.lblActivationStatusVal->setStyleSheet(QString("QLabel { color: %1; }").arg(color));
ui.btnActivate->setEnabled(activationEnabled);
}
void CCEngine::onErrorMessage(QString errorStr)
{
QMessageBox::critical(nullptr, "Error", errorStr);
}
void CCEngine::onActivated(QString activationNumber)
{
if (!activationNumber.isEmpty())
{
LicenseClient licenseClient(idProvider, "license.dat");
licenseClient.init();
} */
ui.btnRestartServer->setEnabled(true);
ui.btnUpdatesCheck->setEnabled(true);
onRestartServer(true);
}
else
{
ui.btnRestartServer->setEnabled(false);
ui.btnUpdatesCheck->setEnabled(false);
}
}
void CCEngine::onUpdatesStatusChanged(UpdatesStatus updatesStatus)
{
QString textStatus;
QString color;
bool updateEnabled = false;
bool checkForUpdateEnabled = false;
switch (updatesStatus)
{
case UpdatesStatus::upToDate:
textStatus = tr("Up to date");
color = "green";
break;
case UpdatesStatus::checking:
textStatus = tr("Checking");
color = "orange";
break;
case UpdatesStatus::updatesAvailable:
textStatus = tr("Updates available");
color = "orange";
updateEnabled = true;
break;
default:
textStatus = tr("Unknown");
color = "black";
}
return EXIT_SUCCESS;
}
ui.lblUpdateStatusVal->setText(textStatus);
ui.lblUpdateStatusVal->setStyleSheet(QString("QLabel { color: %1; }").arg(color));
ui.btnUpdate->setEnabled(updateEnabled);
}
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"));
}
void CCEngine::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason)
{
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick:
showNormal();
}
}
void CCEngine::createActions()
{
restoreAction = new QAction(tr("&Open"), this);
connect(restoreAction, &QAction::triggered, this, &QWidget::showNormal);
quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
}
void CCEngine::createTrayIcon()
{
trayIconMenu = new QMenu(this);
trayIconMenu->addAction(restoreAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
trayIcon = new QSystemTrayIcon(this);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon(":/Resources/iconmonstr-banknote-multi-6-icon-256.png"));
connect(trayIcon, &QSystemTrayIcon::activated, this, &CCEngine::iconActivated);
}
void CCEngine::connectServerManager()
{
connect(&m_ccServerManager, SIGNAL(statusChanged(CCServerStatus)), this, SLOT(onCCServerStatusUpdate(CCServerStatus)));
}
void CCEngine::connectLicenseController()
{
connect(
&m_licenseController, SIGNAL(paramsLoaded(SystemParams, SystemParams)),
this, SLOT(onParamsLoaded(SystemParams, SystemParams)));
connect(
&m_licenseController, SIGNAL(activationStatusChanged(ActivationStatus)),
this, SLOT(onActivationStatusChanged(ActivationStatus)), Qt::ConnectionType::QueuedConnection);
connect(
&m_licenseController, SIGNAL(errorMessage(QString)),
this, SLOT(onErrorMessage(QString)));
connect(
&m_licenseController, SIGNAL(activated(QString)),
this, SLOT(onActivated(QString)));
connect(
&m_licenseController, SIGNAL(updatesStatusChanged(UpdatesStatus)),
this, SLOT(onUpdatesStatusChanged(UpdatesStatus)));
connect(
&m_licenseController, SIGNAL(updates(int, bool)),
this, SLOT(onUpdates(int, bool)));
}

69
CCEngine/src/CCEngine.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include "CCLicenseController.h"
#include "CCServerManager.h"
#include "ui_CCEngine.h"
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QSystemTrayIcon>
#include <boost/filesystem/path.hpp>
struct UpdatesInfo
{
UpdatesStatus status;
int updateCount;
};
class CCEngine : public QMainWindow
{
Q_OBJECT
public:
CCEngine(
const boost::filesystem::path& appPath,
bool justUpdated,
QWidget *parent = Q_NULLPTR);
virtual ~CCEngine();
private:
void closeEvent(QCloseEvent *event) override;
private slots:
void iconActivated(QSystemTrayIcon::ActivationReason reason);
void onCCServerStatusUpdate(CCServerStatus serverStatus);
void onLoad();
void onActivationDetail(bool);
void onRestartServer(bool);
void onOpenBrowser(bool);
void onCheckForUpdates(bool);
// License controller signal handlers
void onParamsLoaded(SystemParams hashedParams, SystemParams origParams);
void onActivationStatusChanged(ActivationStatus activationStatus);
void onErrorMessage(QString errorStr);
void onActivated(QString activationNumber);
void onUpdatesStatusChanged(UpdatesStatus updatesStatus);
void onUpdates(int count, bool restartRequired);
private:
void createActions();
void createTrayIcon();
void connectServerManager();
void connectLicenseController();
private:
Ui::CCEngineClass ui;
private:
QAction* restoreAction;
QAction* quitAction;
QSystemTrayIcon* trayIcon;
QMenu* trayIconMenu;
private:
const boost::filesystem::path& m_appPath;
CCLicenseController m_licenseController;
CCServerManager m_ccServerManager;
uint16_t m_port;
};

View File

@ -0,0 +1,151 @@
#include "CCLicenseController.h"
#include "JSONModuleDatabase.h"
#include <boost/log/trivial.hpp>
CCLicenseController::CCLicenseController()
{}
CCLicenseController::~CCLicenseController()
{
if (m_workerThread.joinable())
{
m_workerThread.join();
}
}
void CCLicenseController::init(const boost::filesystem::path& appDir)
{
if (m_workerThread.joinable())
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
try
{
m_systemParamsProvider = std::make_unique<SystemParamsProvider>();
m_ccLicenseClient = std::make_unique<LicenseClient>(*m_systemParamsProvider, (appDir / "license.dat").string());
m_ccLicenseClient->init();
m_moduleDatabase = std::make_unique<JSONModuleDatabase>((appDir / ".inst").string());
if (m_ccLicenseClient->isActivated())
{
emit activationStatusChanged(ActivationStatus::active);
emit activated(QString::fromStdString(m_ccLicenseClient->activationNumber().value()));
return;
}
emit activationStatusChanged(ActivationStatus::checkingPreactivation);
bool result = m_ccLicenseClient->tryPreactivate(m_httpClient);
if (result)
{
auto activationNumber = m_ccLicenseClient->activationNumber();
BOOST_LOG_TRIVIAL(info) << "The system has been preactivated successfully with activation number \"" << activationNumber.value() << "\".";
emit activated(QString::fromStdString(activationNumber.value()));
emit activationStatusChanged(ActivationStatus::active);
}
else
{
BOOST_LOG_TRIVIAL(info) << "Preactivation attempt failed. The user will be prompted to enter license key.";
emit activated("");
emit activationStatusChanged(ActivationStatus::notActive);
}
}
catch (CouldNotConnectException&)
{
BOOST_LOG_TRIVIAL(error) << "The application could not connect to the license server. Probably the computer is offline";
emit activationStatusChanged(ActivationStatus::notActive);
emit errorMessage("The system could not be activated since your system seems offline. Please check your internet connection!");
}
});
}
void CCLicenseController::activate(const QString &licenseNumber)
{
if (m_workerThread.joinable())
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
emit activationStatusChanged(ActivationStatus::checkingActivation);
try
{
bool result = m_ccLicenseClient->activate(m_httpClient, licenseNumber.toStdString());
if (result)
{
auto activationNumber = m_ccLicenseClient->activationNumber();
BOOST_LOG_TRIVIAL(info) << "The system has been activated successfully with activation number \"" << activationNumber.value() << "\".";
emit activated(QString::fromStdString(activationNumber.value()));
emit activationStatusChanged(ActivationStatus::active);
}
else
{
BOOST_LOG_TRIVIAL(error) << "Activation attempt failed";
emit activated("");
emit activationStatusChanged(ActivationStatus::notActive);
emit errorMessage("Could not activate. Please check your license key and try again!");
}
}
catch (CouldNotConnectException&)
{
BOOST_LOG_TRIVIAL(error) << "The application could not connect to the license server. Probably the computer is offline";
emit errorMessage("The system could not be activated since your system seems offline. Please check your internet connection!");
emit activationStatusChanged(ActivationStatus::notActive);
}
});
}
bool CCLicenseController::isActivated()
{
if (m_ccLicenseClient)
{
return m_ccLicenseClient->isActivated();
}
return false;
}
void CCLicenseController::checkForUpdates()
{
if (m_workerThread.joinable())
{
m_workerThread.join();
}
m_workerThread = std::thread([&]()
{
std::lock_guard<std::mutex> lockGuard(m_exclusiveWorkerMutex);
if (!m_ccLicenseClient->isActivated())
{
throw std::runtime_error("Not active");
}
try
{
emit updatesStatusChanged(UpdatesStatus::checking);
auto modules = m_moduleDatabase->listModules();
m_moduleUpdates = m_ccLicenseClient->checkForUpdates(m_httpClient, modules);
if (m_moduleUpdates.size() > 0)
{
BOOST_LOG_TRIVIAL(info) << "System found " << m_moduleUpdates.size() << " updates";
emit updatesStatusChanged(UpdatesStatus::updatesAvailable);
emit updates(m_moduleUpdates.size(), false);
}
else
{
BOOST_LOG_TRIVIAL(info) << "No updates found. System is up to date";
emit updatesStatusChanged(UpdatesStatus::upToDate);
emit updates(0, false);
}
}
catch (CouldNotConnectException&)
{
BOOST_LOG_TRIVIAL(error) << "The application could not check for updates. Probably the computer is offline";
emit errorMessage("Could not check for updates as the computer seem offline. Please try again later.");
}
});
}

View File

@ -0,0 +1,66 @@
#pragma once
#include "LicenseClient.h"
#include "HTTPClient.h"
#include "IModuleDatabase.h"
#include <QObject>
#include <boost/filesystem/path.hpp>
#include <mutex>
#include <thread>
enum class ActivationStatus
{
unknown,
checkingPreactivation,
notActive,
checkingActivation,
active,
};
Q_DECLARE_METATYPE(ActivationStatus);
enum class UpdatesStatus
{
unknown,
checking,
upToDate,
updatesAvailable
};
Q_DECLARE_METATYPE(UpdatesStatus);
class CCLicenseController : public QObject
{
Q_OBJECT;
public:
CCLicenseController();
virtual ~CCLicenseController();
public:
void init(const boost::filesystem::path& appDir);
void activate(const QString& licenseNumber);
bool isActivated();
void checkForUpdates();
public:
signals:
void paramsLoaded(SystemParams hashedParams, SystemParams origParams);
void activationStatusChanged(ActivationStatus activationStatus);
void errorMessage(QString errorStr);
void activated(QString activationNumber);
void updatesStatusChanged(UpdatesStatus updatesStatus);
void updates(int count, bool restartRequired);
private:
std::unique_ptr<SystemParamsProvider> m_systemParamsProvider;
std::unique_ptr<LicenseClient> m_ccLicenseClient;
std::unique_ptr<IModuleDatabase> m_moduleDatabase;
std::vector<ModuleUpdate> m_moduleUpdates;
HTTPClient m_httpClient;
std::mutex m_exclusiveWorkerMutex;
std::thread m_workerThread;
};

View File

@ -13,6 +13,7 @@
#include <boost/crc.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/filesystem.hpp>
#include <boost/signals2.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <cstdlib>
@ -761,6 +762,10 @@ public:
m_threads.emplace_back([&]()
{
m_ioc.run();
if (i == 0)
{
m_onStopped();
}
});
}
}
@ -786,6 +791,11 @@ public:
m_etagCache.clear();
}
boost::signals2::connection connectOnStopped(const boost::signals2::signal<void()>::slot_type& slot)
{
return m_onStopped.connect(slot);
}
private:
mutable std::mutex m_mutex;
int m_maxThreads;
@ -794,6 +804,7 @@ private:
tcp::endpoint m_endpoint;
boost::asio::io_context m_ioc;
std::vector<std::thread> m_threads;
boost::signals2::signal<void()> m_onStopped;
};
}
@ -816,6 +827,11 @@ void CCServer::clearCache()
m_impl->clearCache();
}
boost::signals2::connection CCServer::connectOnStopped(const boost::signals2::signal<void()>::slot_type & slot)
{
return m_impl->connectOnStopped(slot);
}
void CCServer::run()
{
m_impl->run();

View File

@ -1,5 +1,6 @@
#pragma once
#include <boost/signals2.hpp>
#include <memory>
#include <string>
@ -19,6 +20,7 @@ public:
bool isRunning() const;
void shutdown();
void clearCache();
boost::signals2::connection connectOnStopped(const boost::signals2::signal<void()>::slot_type& slot);
private:
std::unique_ptr<detail::CCServerImpl> m_impl;

View File

@ -0,0 +1,19 @@
#include "CCServerManager.h"
void CCServerManager::listen(const std::string& addressToListen, uint16_t portToListen, const std::string& docRoot, int threads)
{
m_ccServer.reset();
emit statusChanged(CCServerStatus::starting);
m_ccServer = std::make_unique<CCServer>(addressToListen, portToListen, docRoot, threads);
m_ccServer->connectOnStopped([this]()
{
emit statusChanged(CCServerStatus::stopped);
});
m_ccServer->run();
emit statusChanged(CCServerStatus::serving);
}
void CCServerManager::shutdown()
{
m_ccServer.reset();
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "CCServer.h"
#include <QObject>
enum class CCServerStatus
{
unknown,
stopped,
starting,
serving
};
Q_DECLARE_METATYPE(CCServerStatus);
class CCServerManager : public QObject
{
Q_OBJECT;
public:
CCServerManager()
{}
public:
void listen(const std::string& addressToListen, uint16_t portToListen, const std::string& docRoot, int threads);
void shutdown();
public:
signals:
void statusChanged(CCServerStatus status);
private:
std::unique_ptr<CCServer> m_ccServer;
};

View File

@ -0,0 +1,12 @@
#include "SystemParamsDlg.h"
SystemParamsDlg::SystemParamsDlg(
const SystemParams& systemParams,
QWidget *parent)
: QDialog(parent)
, model(systemParams)
{
ui.setupUi(this);
ui.tblSystemParams->setModel(&model);
ui.tblSystemParams->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <QtWidgets/QDialog>
#include "ui_SystemParameters.h"
#include "SystemParamsModel.h"
class SystemParamsDlg : public QDialog
{
Q_OBJECT
public:
SystemParamsDlg(
const SystemParams& systemParams,
QWidget *parent = Q_NULLPTR);
private:
SystemParamsModel model;
private:
Ui::SystemParametersDialog ui;
};

View File

@ -0,0 +1,74 @@
#include "SystemParamsModel.h"
#include <QtGui/QFont>
SystemParamsModel::SystemParamsModel(const SystemParams& params, QObject *parent)
: QAbstractTableModel(parent)
{
std::vector<Record> records(params.size());
std::transform(params.begin(), params.end(), records.begin(), [](const auto& elm)
{
return std::make_tuple(QString(elm.first.c_str()), QString(elm.second.c_str()), QString(elm.second.c_str()));
});
m_data = std::move(records);
}
int SystemParamsModel::rowCount(const QModelIndex & parent) const
{
return m_data.size();
}
int SystemParamsModel::columnCount(const QModelIndex & parent) const
{
return std::tuple_size<Record>::value;
}
QVariant SystemParamsModel::data(const QModelIndex & index, int role) const
{
int row = index.row();
int col = index.column();
if (role == Qt::DisplayRole)
{
switch (col)
{
case 0:
return std::get<0>(m_data[row]);
case 1:
return std::get<1>(m_data[row]);
case 2:
return std::get<2>(m_data[row]);
}
}
else if (role == Qt::FontRole)
{
if (col == 0)
{
QFont boldFont;
boldFont.setBold(true);
return boldFont;
}
}
return QVariant{};
}
QVariant SystemParamsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole)
{
if (orientation == Qt::Horizontal) {
switch (section)
{
case 0:
return QString("Parameter type");
case 1:
return QString("Reported hash value");
case 2:
return QString("Original value*");
}
}
}
return QVariant();
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "SystemParams.h"
#include <QAbstractTableModel>
#include <tuple>
class SystemParamsModel : public QAbstractTableModel
{
Q_OBJECT
public:
SystemParamsModel(const SystemParams& params, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
private:
typedef std::tuple<QString, QString, QString> Record;
private:
std::vector<Record> m_data;
};

26
CCEngine/src/main.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "CCEngine.h"
#include "PlatformInit.h"
#include <QtWidgets/QApplication>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto appDir = fs::system_complete(a.arguments().at(0).toStdString()).parent_path();
bool justUpdated = false;
for (int i = 1; i < a.arguments().size(); ++i)
{
if (a.arguments().at(i) == "--updated")
{
justUpdated = true;
}
}
CCEngine w(appDir, justUpdated);
w.show();
return a.exec();
}

View File

@ -79,6 +79,9 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<QtMoc>
<IncludePath>$(BOOST_ROOT_DIR);%(IncludePath)</IncludePath>
</QtMoc>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>