{
m_Log=log;
}GSModulesManager::init()
{QSettings params;
params.beginGroup(m_ModulesSection);
m_MainModuleName=params.value("main_module", "MainWindow").toString();
m_AutoDownload=params.value("auto_download", true).toBool();
m_CheckUpdates=params.value("check_updates",
true).toBool();
params.setValue("main_module", m_MainModuleName);
params.setValue("auto_download", m_AutoDownload);
params.setValue("check_updates", m_CheckUpdates);
params.endGroup();
}GSModulesManager::onEvent(const QString &event, char param)
{GSModule* module=Q_NULLPTR;
for(int i=0; i<m_lModules.size(); i++){
module=m_lModules.at(i);
if(module->onEvent(event, param))
gsInfo(m_Log, 9)<<" Событие "<<event<<" обработано в модуле "<<module->objectName()<<"."<<endl;
}
}* GSModulesManager::getWidget(const QString &widgetID)
{void *widget=Q_NULLPTR;
for(int i=0; i<m_lModules.size(); i++){
module=m_lModules.at(i);
widget=module->getWidget(widgetID);
if(widget)
return widget;
}
gsInfo(m_Log,9)<<" Элемент графического интерфейса: "<<widgetID<<" не найден!"<<endl;
return Q_NULLPTR;
}GSModulesManager::checkUpdates(const QString &listFileName, bool forceUpdate)
{
if(!m_CheckUpdates && !forceUpdate)
return 0x02;
GSUpdateFiles updateFiles;
updateFiles.setObjectName("updateFiles");
connect(&updateFiles, SIGNAL(exeUpdated(QString)), this,
SLOT(exeUpdated(QString)));
connect(&updateFiles, SIGNAL(instReceived(QString)), this,
SLOT(instReceived(QString)));
updateFiles.setLog(m_Log);
updateFiles.init(m_ModulesSection);
updateFiles.getUpdatesList(listFileName);
updateFiles.buildUpdatesTree(listFileName, m_ModulesSection);
return 0x01;
}&GSModulesManager::getNewExeName()
{
return m_newExeName;
}&GSModulesManager::getInstName()
{
return m_instReceivedName;
}GSModulesManager::exeUpdated(const QString fileName)
{
m_newExeName=fileName;
}GSModulesManager::instReceived(const QString fileName)
{
m_instReceivedName=fileName;
}
Исходный код подсистемы работы с параметрами
#include "GSApplication.h"* GSApplication::theApplication()
{ return (GSApplication *)qApp;}GSApplication::saveParams()
{QSettings params;
params.setValue("version",applicationVersion());
}GSApplication::readParams()
{}* GSApplication::createAppLog(const QString &objectName)
{
if(!m_AppLog)
m_AppLog=new GSLog(this, objectName);
return m_AppLog;
}*GSApplication::getAppLog()
{ return m_AppLog;}* GSApplication::createModulesManager(const QString &objectName)
{
if(!m_ModulesManager)
m_ModulesManager=new GSModulesManager(objectName,this);
return m_ModulesManager;
}GSApplication::getAppUID()
{ return m_Uuid;}::GSApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
m_AppLog=Q_NULLPTR;
m_ModulesManager=Q_NULLPTR;
m_Uuid=QUuid::createUuid();
}::~GSApplication()
{
delete m_ModulesManager;
delete m_AppLog;
}GSApplication::isWow64(QString *appDigits)
{LPFN_ISWOW64PROCESS fnIsWow64Process=Q_NULLPTR;
BOOL bIsWow64=false, ok=false;
*appDigits="_Wx32";
fnIsWow64Process=(LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if(fnIsWow64Process){
if(fnIsWow64Process(GetCurrentProcess(),&bIsWow64)){
ok=true;
if(!bIsWow64)
*appDigits="_Wx64";
}
}
if(!ok)
gsInfo(m_AppLog,9)<<" Не удалось определить разрядность приложения!"<<endl;
}
Исходный код подсистемы логирования
#include "GSLog.h"::GSLog(QObject *pobj, const QString &objectName):QObject(pobj)
{
m_LogFile.setObjectName("LogFile");
m_LogFile.setParent(this);
setObjectName(objectName);
}::~GSLog()
{
m_LogFile.close();
}GSLog::init(const QString ¶msSection)
{QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
m_ParamsSection=paramsSection;
setLogFileName();
setLogLevel(getLogLevel());
m_OutStream.setCodec(codec);
m_currentLogMessagesLevel=0;
return true;
}GSLog::setLogFileName(QString &value)
{
if(value.isEmpty()){
value=m_Params.value(m_ParamsSection+"/log_path",::writableLocation(QStandardPaths::AppLocalDataLocation)+
QString("/")+qApp->applicationName()+".log").toString();
}
if(m_LogFile.fileName()==value)
return true;
m_LogFile.close();
m_LogFile.setFileName(value);
if(!m_LogFile.exists()){
QFileInfo fileInfo(m_LogFile);
fileInfo.absoluteDir().mkpath(fileInfo.absolutePath());
}
if(!m_LogFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
return false;
m_OutStream.setDevice(&m_LogFile);
m_Params.setValue(m_ParamsSection+"/log_path",value);
return true;
}GSLog::getLogFileName()
{
return m_LogFile.fileName();
}GSLog::setLogLevel(int value)
{
m_Params.setValue(m_ParamsSection+"/log_level", value);
}GSLog::getLogLevel()
{
return m_Params.value(m_ParamsSection+"/log_level", -1).toInt();
}GSLog::setlogMessagesLevel(int value)
{
m_currentLogMessagesLevel=value;
}&GSLog::toLog(int level, QObject *pobj)
{
m_currentLogMessagesLevel=level;
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<level)
return *this;
m_OutStream<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ")
<<QString("%1 [").arg(level,2);
if(pobj){
m_OutStream<<pobj->objectName();
}
m_OutStream<<"] "<<endl;
// m_OutStream<<" ";
return *this;
}&GSLog::operator <<(QString &value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<value;
return *this;
}&GSLog::operator <<(const QString &value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<value;
return *this;
}&GSLog::operator <<(char *value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<QString(value).toLocal8Bit();
return *this;
}&GSLog::operator <<(const char *value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<QString(value).toLocal8Bit();
return *this;
}&GSLog::operator <<(bool value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
if(value)
m_OutStream<<"Yes";
else
m_OutStream<<"No";
return *this;
}&GSLog::operator <<(int value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<value;
return *this;
}&GSLog::operator <<(QTextStream &(__cdecl *)(QTextStream &))
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<endl;
return *this;
}&GSLog::operator <<(QEvent::Type value)
{QString event_type;
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
switch (value) {
case QEvent::ActionAdded:
event_type="A new action has been added";
break;
case QEvent::ApplicationActivate:
event_type="Application activated.";
break;
case QEvent::ApplicationDeactivate:
event_type="Application deactivated.";
break;
case QEvent::ApplicationStateChange:
event_type="The state of the application has changed.";
break;
case QEvent::MetaCall:
event_type="An asynchronous method invocation via QMetaObject::invokeMethod().";
break;
case QEvent::Timer:
event_type="Regular timer events.";
break;
default:
event_type=QString("Unknown(")+QString().number(value)+")";
break;
}
m_OutStream<<event_type;
return *this;
}
Исходный код подсистемы обновлений
#include "GSUpdateFiles.h"
GSUpdateFiles::GSUpdateFiles(QWidget *parent):QDialog(parent)
{QStringList headers;
// QPushButton* button;
m_UpdatesTree=new QTreeWidget(this);
headers<<tr("Модуль")<<tr("Версия")<<tr("Тип")
<<tr("Путь на сервере")<<tr("Локальный путь")<<tr("Локальное имя")
<<tr("Локальная версия")<<tr("Принудительно")<<tr("Обновить")
<<tr("Прогресс");
m_UpdatesTree->setColumnCount(headers.count());
m_UpdatesTree->setHeaderLabels(headers);
m_UpdatesTree->setColumnHidden(2, true);
m_UpdatesTree->setColumnHidden(3, true);
m_UpdatesTree->setColumnHidden(4, true);
m_UpdatesTree->setColumnHidden(5, true);
m_UpdatesTree->setColumnHidden(6, true);
m_UpdatesTree->setColumnHidden(7, true);
m_UpdatesTree->setItemDelegateForColumn(9,new ProgressBarDelegate(m_UpdatesTree));
m_UpdatesTree->setColumnWidth(0,300);
QVBoxLayout *vLayout= new QVBoxLayout(this);
vLayout->addWidget(m_UpdatesTree);
QHBoxLayout *hLayout= new QHBoxLayout(this);
hLayout->addStretch(10);
m_Button=new QPushButton(this);
m_Button->setText("Закрыть");
m_Button->setFocus();
connect(m_Button, SIGNAL(clicked(bool)), this, SLOT(close()));
hLayout->addWidget(m_Button);
m_Button->setVisible(false);
vLayout->addLayout(hLayout);
resize(700,300);
setWindowTitle("Доступные обновления");
m_Log=Q_NULLPTR;
}::~GSUpdateFiles()
{
delete m_UpdatesTree;
m_Log=Q_NULLPTR;
}GSUpdateFiles::getUpdatesList(const QString &listFileName)
{QUrl src, dst;
src.setUrl(m_UpdateConnectString+listFileName);
gsInfo(m_Log, 9)<<" Получаем файл списка обновлений "<<src.toDisplayString()<<endl;
src.setUserName(m_UpdateUser);
src.setPassword(m_UpdatePasswd);
dst.setUrl(QString("file:///")+QDir::current().absolutePath()+
"/"+listFileName);
m_ShowDialog="0";
loadUpdate(src, dst);
m_ShowDialog="1";
}GSUpdateFiles::buildUpdatesTree(const QString &listFileName,
const QString &modulesSection,
TUpdatePolicy updatePolicy)
{QFile file(QDir::current().absolutePath()+"/"+listFileName);
QDomDocument updatesDoc;
QString tmpStr;
int errorLine;
int errorColumn;
QTreeWidgetItem *rootItem, *currentItem, *childItem;
QSettings moduleParams;
if(m_NetworkError)
return;
m_ModulesSection=modulesSection;
gsInfo(m_Log, 9)<<" Заполняем список обновлений из файла "<<listFileName<<endl;
if(!file.open(QFile::ReadOnly | QFile::Text)){
tmpStr=" Не удалось открыть файл списка обновлений ";
gsInfo(m_Log, 9)<<tmpStr<<listFileName<<endl;
QMessageBox::critical(0, QString("Ошибка!"), tmpStr, QMessageBox::Ok);
return;
}
if(!updatesDoc.setContent(&file, true, &tmpStr, &errorLine, &errorColumn)){
tmpStr=QString(" Ошибка формата в строке %1, столбец %2:\n%3")
.arg(errorLine)
.arg(errorColumn)
.arg(tmpStr);
gsInfo(m_Log, 9)<<tmpStr<<endl;
QMessageBox::critical(0, QString("Ошибка!"), tmpStr, QMessageBox::Ok);
return;
}
QDomElement root=updatesDoc.documentElement();
if(root.tagName()!="updxml"){
tmpStr=" Формат файла обновлений неизвестен.";
gsInfo(m_Log, 9)<<tmpStr<<endl;
QMessageBox::critical(0, QString("Ошибка!"), tmpStr, QMessageBox::Ok);
return;
}
else
if(root.hasAttribute("version")
&& root.attribute("version") != "1.0"){
tmpStr=" Версия формата файла обновлений не поддерживается.";
gsInfo(m_Log, 9)<<tmpStr<<endl;
QMessageBox::critical(0, QString("Ошибка!"), tmpStr, QMessageBox::Ok);
return;
}
QDomElement moduleElement=root.firstChildElement("module");
rootItem=m_UpdatesTree->invisibleRootItem();
currentItem=Q_NULLPTR;
while(!moduleElement.isNull()){
currentItem=new QTreeWidgetItem(rootItem, currentItem);
currentItem->setText(0, moduleElement.attribute("name"));
currentItem->setText(1, moduleElement.attribute("version"));
currentItem->setText(2, moduleElement.attribute("type"));
currentItem->setText(7, moduleElement.attribute("force"));
currentItem->setText(8, "Да");
if(moduleElement.attribute("type")=="exe")
moduleParams.beginGroup("");
else.beginGroup(modulesSection+"/"+moduleElement.attribute("name"));
currentItem->setText(6, moduleParams.value("version", "").toString());
currentItem->setExpanded(true);
QDomElement child=moduleElement.firstChildElement();
childItem=Q_NULLPTR;
while(!child.isNull()){
childItem=new QTreeWidgetItem(currentItem, childItem);
childItem->setText(0, child.text());
childItem->setText(3, child.attribute("path"));
childItem->setText(4,"file:///"+moduleParams.value("module_path",
QDir::current().absolutePath()+"/").toString());
if(child.tagName()=="file"){
childItem->setText(5, moduleParams.value("module_file", child.text()).toString());
childItem->setText(2, "Основной");
}
else{
childItem->setText(5, child.text());
childItem->setText(2, "Необходимый");
}
child=child.nextSiblingElement();
}
moduleParams.endGroup();
moduleElement=moduleElement.nextSiblingElement("module");
}
checkItemForUpdate(updatePolicy);
}GSUpdateFiles::checkItemForUpdate(TUpdatePolicy updatePolicy)
{QTreeWidgetItem *rootItem, *currentItem;
int updateVersion, localVersion, modulesCount;
QString message;
rootItem=m_UpdatesTree->invisibleRootItem();
modulesCount=rootItem->childCount();
for(int index=0; index<rootItem->childCount(); index++){
currentItem=rootItem->child(index);
update=true;
if(!currentItem->text(6).isEmpty()){
updateVersion=currentItem->text(1).section(".",0,0).toInt()*10000;
localVersion=currentItem->text(6).section(".",0,0).toInt()*10000;
updateVersion=currentItem->text(1).section(".",1,1).toInt()*100;
localVersion=currentItem->text(6).section(".",1,1).toInt()*100;
updateVersion=currentItem->text(1).section(".",2,2).toInt();
localVersion=currentItem->text(6).section(".",2,2).toInt();
update=updateVersion>localVersion;
}
if(update){
currentItem->setText(8,"Да");
currentItem->setText(5, currentItem->text(0));
}
else{
message=" Модуль "+currentItem->text(0)+" "+currentItem->text(1)+
".\n Установлена версия "+currentItem->text(6)+
".\n В обновлении не нуждается.";
gsInfo(m_Log, 9)<<message<<endl;
currentItem->setText(8,message);
if(updatePolicy==newOnly){
currentItem->setHidden(true);
modulesCount--;
}
}
}
if(updatePolicy==newOnly)
m_UpdatesTree->setColumnHidden(8, true);
if(modulesCount){
if(QMessageBox::information(0, QString("Клиент МИС \"Интерин\"."), "Доступны обновления программы.\nОбновление может занять несколько минут. В процессе обновления программа может перезапуститься.\nОбновить сейчас?",
QMessageBox::Ok|QMessageBox::Cancel)==QMessageBox::Ok){
setModal(true);
show();
startTransfer(true);
}
}
}GSUpdateFiles::loadUpdate(const QUrl &src, const QUrl &dst, const QString &type)
{QNetworkReply* networkReply;
QNetworkAccessManager networkAccessManager;
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
gsInfo(m_Log,9)<<" Обновляем файл\n src="<<src.toDisplayString()<<
"\n dst="<<dst.toDisplayString()<<"\n type="<<type<<endl;
networkReply=networkAccessManager.get(QNetworkRequest(src));
connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(loadError(QNetworkReply::NetworkError)));
if(m_ShowDialog=="1")
connect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(transferProgress(qint64,qint64)));
connect(networkReply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(&timer, SIGNAL(timeout()), networkReply, SLOT(abort()));
m_NetworkError=false;
timer.start(m_TimeOut);
loop.exec();
if(!m_NetworkError){
QFile file(dst.toLocalFile());
QFileInfo fileInfo(file);
if(!fileInfo.absoluteDir().exists())
fileInfo.absoluteDir().mkpath(fileInfo.absolutePath());
file.open(QIODevice::WriteOnly);
file.write(networkReply->readAll());
if(type=="exe/Основной")
emit exeUpdated(fileInfo.absoluteFilePath());
if(type=="inst/Основной")
emit instReceived(fileInfo.absoluteFilePath());
}
networkReply->deleteLater();
}GSUpdateFiles::showEvent(QShowEvent *event)
{}GSUpdateFiles::setLog(GSLog *log)
{
m_Log=log;
}GSUpdateFiles::init(const QString ¶mSectionName)
{QSettings params;
params.beginGroup(paramSectionName);
m_UpdateConnectString=params.value("update_connect_str", "ftp://interin.rk35.ru/updates/").toString();
m_UpdateUser=params.value("update_user", "interin").toString();
m_UpdatePasswd=params.value("update_passwd", "www.gslobod.ru").toString();
m_BackupDir=params.value("backup_dir",
QDir::current().absolutePath()+"/backup/").toString();
m_ShowDialog=params.value("show_dialog", "1").toString();
m_MaxDownloads=params.value("max_downloads", "5").toString();