Разработка и реализация программных средств для работы с веб-контентом в рамках проекта INTERIN PROMIS
Расширение возможностей браузера плагинами. Создание собственного веб-клиента. Разработка главной функции ядра системы. Основание подсистемы загрузки файлов. Формирование инсталлятора программной концепции. Тестирование функциональной части программы.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 12.08.2017 |
Размер файла | 2,4 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Рисунок 4.1 - Снимок экрана процесса установки клиента.
В процессе установки клиента, инсталлятор создает ветвь (\HKEY_CURRENT_USER\Software\Interin) в реестре операционной систем, а в выбранную директорию распаковываются исполняемый файл системы (InterinClient.exe), а так же все необходимые для его работы библиотеки и модули.
4.2 Тестирование функциональной части программы
Функциональное тестирование - процесс проверки соответствия поведения системы первоначально заявленным функциональным требованиям [15].
Цель тестирования: Подтвердить, что система реализована в соответствии с предъявленными к ней функциональными требованиями и полностью готова к работе, при этом система воспринимается как единый «чёрный ящик».
Главное преимущества такого тестирования - это имитация фактического использования системы, однако есть и недостатки, такие как возможность упущения логических ошибок в программном обеспечении и вероятность избыточного тестирования.
Исходные данные и результаты тестирования приведены в Таблице 4.1. Графа оценка определяет соответствие результатов ожидаемым («+» - соответствуют, «-» - нет).
Таблица 4.1 - Исходные данные и результаты тестирования программной системы
Исходные данные |
Результат |
Оценка |
|
Запуск инсталлятора |
Запускается установка клиента,по результатам ее выполнения пользователю предлагается ознакомится с основными ее результатами |
+ |
|
Запук исполняемого файла клиента |
Открывается приложения и начинается проверка обновлений, по ее завершению запускается главное окно |
+ |
|
Нажатие на пунк меню |
Открывается выбранное подменю |
+ |
|
Изменение параметро системы |
После сохранения именений результат успешно применяется |
+ |
|
Запуск обновления |
Запускается подсистема обновлений |
+ |
|
Измнение размеров окна программы |
Изменения применяются, пропорции отображаемого материала сохраняются |
+ |
|
Нажатие на попункт меню "Печать в PDF" |
Открывается диалоговое окно печати с возможностью выбора параметров |
+ |
|
Нажатие на понкт меню "Помощ" |
Открывается информационное окно "О программе" |
+ |
|
Изменение адреса получения обновлений на локальный |
Программа меняет протокол обмена данными и получает обновления из локальной папки |
+ |
|
Переход по ссылке в МИС на открытие тектового файла |
Идет загрузка фала, затем его открытие в выбранном тектовом редакторе. |
+ |
|
Переход по ссылке в МИС на прямую печать тектового файла |
Идет загрузка фала, затем его преобразование в pdf формат и отправка на принтер. От пользователя скрыт весь процесс. |
||
Нажание на подпунк меню "Выход" |
Программа закрывается |
+ |
4.3 Тестирование модульной расширяемости
Для изменения логики работы всей системы достаточно в ее параметрах указать название другого модуля главного окна. На рисунке 4.2 представлен пример работы главного модуля, которы имеет название "InterinClntMainWnd_2.0.10.dll ".
Рисунок 4.2 - Пример работы модуля "InterinClntMainWnd_2.0.10.dll"
На рисунке 4.3 представлен процесс изменения главного исполнемого модуля на "InterinClntMainWnd_2.0.4.dll".
Рисунок 4.3 - Пример изменения главного исполняемого модуля
После применения измений и перезапуска программы можно увидеть, что система успешно запустилась, однако функционал сущеественно ограничен, поскольку был подключен устаревший модуль.
На рисунке 4.4 представлен пример работы главного модуля, которы имеет название "InterinClntMainWnd_2.0.4.dll ".
Рисунок 4.4 - Пример работы модуля "InterinClntMainWnd_2.0.4.dll"
Для расширения функиционала системы путем добавления бибилотек, а не их изменения потребуется в реестре операционной системы, в ветви "ModulesManeger" создать раздел. В нем разделе необхоимо создать такие параметры как module_path,module_name и version. В module_path необходимо указать полный путь до ибилотеки, а в module_name её полное наименование. После перезапуска программы, функционал реалиованный в данной бибилотеке будет доступен.
5. ВНЕДРЕНИЕ
Для внедрения клиента корпоративной информационной системы необходимо происталлировать програмный продукт на все необходимые рабочие места и насроить адрес домашней страницы. Далее, при необходимости, нужно установить программы для работы с тектовыми документами, а так же выбрать нужную в настройках. Для этого в настройках системы, в пункте "Редактор выходных форм" необходимо выбрать исполняемый файл тектового редактора. Данный процесс представлен на рисунке 5.1.
Рисунок 5.1 - Пример выбора редактора выходны фаорм
Вторым этапом внедрения является создание общего ресурса, на котором будет рассположены файлы обновления с их описанием. Разработанная подсистема обновлений позволяет без изменений использовать раличные протоколы обмена данными, такие как ftp,smb,file. Таким образом, необходимо только указать в настройках путь до папки с обновлениями.
На рисунке 5.2 представлен пример отображения медицинской информационной системы Interin PROMIS ALPHA на реализованном в данной работе клиенском приложениии.
Рисунок 5.2 - Вид типовой МИС
ЗАКЛЮЧЕНИЕ
В данной магистерской диссертации была проведена работа по анализу методов реализации клиента информационной веб-системы, а так же выбран оптимальный способ его реализации. Была представлена и реализована идея интеграции информационных решений, для получения многофункционального, конкурентноспособного программного продукта. Разработана модульная структура, которая отражена на функциональной и структурной схемах. Она позволяет обеспечить легкое обновление, тиражируемость и масштабируемость всей системы без изменения основных компонент.
Реализованы основные модули системы, такие как ее ядро и главное окно. Реализованный метод интеграции предполагает обязательное наличие в системе только этих двух компонент, а остальные исключительно для наращивания функционала. Для расширения возможностей был разработан модуль печати, который основан на сторонней библиотеке, что показывает интеграционные способности всей системы, а подсистема обновлений предоставляет широкий выбор настроек для поддержания всех модулей в актуальном состоянии. Так же продемонстрирована стабильная работоспособность всей системы и возможность изменения ее функционирования путем подключения или отключения бибилотек.
Полученный программный продукт полностью удовлетворяет всем исходным требования и используется в качестве клиента медицинской информационной системы «Interin PROMIS ALPHA» в двух медицинских организацияхж
Результаты работы представляют высокую практическую значимость, поскольку разработанный клиент предоставляет возможность быстрой адаптации к различным информационным системам, путем изменения отдельных библиотек, что позволяет не просто расширять его функционал, а полностью изменять логику работы системы.
ПРИЛОЖЕНИЕ
(Обязательное)
Исходный код функции main ядра системы
#include "../src/InterinClntApp/interinclntapp.h"
int main(int argc, char **argv)
{InterinClntApp *app=Q_NULLPTR;
QString execAfterExit="";
char initRez;
bool done=false;
app=new InterinClntApp(argc, argv);
while(!done){
initRez=app->init();
if(!initRez){
execAfterExit=" Не удалось выполнить инициализацию параметров приложения.\n"
" Работа будет завершена. Обратитесь в техподдержку!";
if(app->getAppLog())
app->getAppLog()->toLog(0)<<execAfterExit<<endl;
QMessageBox::critical(0, QString(" Клиент МИС \"Интерин\" версия ")+
app->applicationVersion(), execAfterExit,
QMessageBox::Ok);
delete app;
return 1;
}
if(initRez==0x01){
if(app->loadMainModule()){
app->exec();
execAfterExit=app->getUpdateCommand();
if(!execAfterExit.isEmpty()){
app->getAppLog()->toLog(9)<<" Перезапускаемся для проверки обновлений.\n "<<execAfterExit<<endl;
initRez=0x02;
}
done=true;
}
else{
execAfterExit=" Не удалось загрузить основной модуль программы.\n"
" Нажмите Ок для загрузки основного модуля с сервера обновлений.\n"
" Нажмите Cancel для завершения работы и обратитесь в техподдержку!.";
if(app->getAppLog())
app->getAppLog()->toLog(0)<<execAfterExit<<endl;
if(QMessageBox::critical(0, QString(" Клиент МИС \"Интерин\" версия ")+
app->applicationVersion(), execAfterExit,
QMessageBox::Ok|QMessageBox::Cancel)!=QMessageBox::Ok)
done=true;
}
}
else{ execAfterExit=app->getUpdateCommand();
app->getAppLog()->toLog(9)<<" Обновились. После завершения выполняем команду\n "<<execAfterExit<<endl;
done=true;
}
}app->saveParams();
delete app;
if(!execAfterExit.isEmpty() && initRez==0x02)
QProcess(0).startDetached(execAfterExit);
return 0;
}
Исходный код менеджера модулей
#include "gsmodule.h"
GSModule::GSModule(const QString &moduleName, const QString &modulesSection,
QObject *parent):
QObject(parent)
{
setObjectName(moduleName);
m_DllInit=Q_NULLPTR;
m_DllStart=Q_NULLPTR;
m_DllStop=Q_NULLPTR;
m_DllAbout=Q_NULLPTR;
m_HandlersArray=Q_NULLPTR;
m_WidgetsArray=Q_NULLPTR;
m_Log=Q_NULLPTR;
m_ModuleParamsSection=modulesSection+"/"+objectName()+"/";
// load();
}
GSModule::~GSModule()
{
unload();
m_Log=Q_NULLPTR;
}
char GSModule::init(void *abstractInterface)
{TGetEventsHandlers getHandlers=Q_NULLPTR;
TGetWidgetsList getWidgets=Q_NULLPTR;
QSettings objectParams;
objectParams.setValue(m_ModuleParamsSection+"version", about(ABOUT_VER));
if(!m_DllInit)
return 0x00;
if(!m_DllInit(abstractInterface, &m_ModuleParamsSection))
return 0x00;
getHandlers=(TGetEventsHandlers) m_Library.resolve("getEventsHandlers");
if(getHandlers)
m_HandlersArray=(THandlersArray *)getHandlers();
getWidgets=(TGetWidgetsList) m_Library.resolve("getWidgetsList");
if(getWidgets)
m_WidgetsArray=(TWidgetsArray *)getWidgets();
return 0x01;
}
char GSModule::start()
{QSettings objectParams;
if(!m_DllStart)
return 0x00;
// objectParams.setValue(m_ModuleParamsSection+"version", about(ABOUT_VER));
return m_DllStart();
}
char GSModule::stop()
{
m_HandlersArray=Q_NULLPTR;
m_WidgetsArray=Q_NULLPTR;
if(!m_DllStop)
return 0x00;
return m_DllStop();
}
QString GSModule::about(char content)
{QString mess;
if(!m_DllAbout)
return "";
m_DllAbout(content, &mess);
return mess;
}
bool GSModule::isLoaded()
{
return m_Library.isLoaded();
}
bool GSModule::load()
{QSettings objectParams;
if(m_Library.isLoaded())
unload();
m_Library.setFileName(objectParams.value(m_ModuleParamsSection+"module_path","").toString()+
objectParams.value(m_ModuleParamsSection+"module_file","").toString());
gsInfo(m_Log,9)<<" Загружаем файл\n "<<m_Library.fileName()<<"\n из секции\n "<<m_ModuleParamsSection<<endl;
if(!m_Library.load()){
objectParams.setValue(m_ModuleParamsSection+"version","");
return false;
}
m_DllInit= (TModuleInit) m_Library.resolve("init");
m_DllStart= (TModuleStart) m_Library.resolve("start");
m_DllStop= (TModuleStop) m_Library.resolve("stop");
m_DllAbout= (TModuleAbout) m_Library.resolve("about");
return true;
}
bool GSModule::unload()
{
if(!m_Library.isLoaded()){
stop();
m_DllInit=Q_NULLPTR;
m_DllStart=Q_NULLPTR;
m_DllStop=Q_NULLPTR;
m_DllAbout=Q_NULLPTR;
return m_Library.unload();
}
return true;
}
char GSModule::onEvent(const QString &event, char param)
{TEventHandler eventHandler;
if(m_HandlersArray){
eventHandler=m_HandlersArray->value(event,Q_NULLPTR);
if(eventHandler){
eventHandler(param);
return 0x01;
}
}
return 0x00;
}
void *GSModule::getWidget(const QString &widgetId)
{
if(m_WidgetsArray)
return m_WidgetsArray->value(widgetId,Q_NULLPTR);
return Q_NULLPTR;
}
void GSModule::setLog(GSLog *log)
{
m_Log=log;
}
GSModulesManager::GSModulesManager(const QString &objectName, QObject *parent)
: QObject(parent)
{
m_ModulesSection=objectName;
setObjectName(objectName);
m_Log=Q_NULLPTR;
m_newExeName="";
m_instReceivedName="";
}
GSModulesManager::~GSModulesManager()
{
unloadAllModules();
m_Log=Q_NULLPTR;
}
GSModule* GSModulesManager::loadModule(const QString &moduleName)
{GSModule* module=Q_NULLPTR;
if(moduleName.isEmpty())
return loadModule(m_MainModuleName);
gsInfo(m_Log,9)<<" Загружаем модуль "<<moduleName<<endl;
for(int i=0; i<m_lModules.size(); i++){
module=m_lModules.at(i);
if(module->objectName() == moduleName){
if(module->isLoaded())
return module;
else{
module->load();
break;
}
}
module=Q_NULLPTR;
}
if(!module){
module=new GSModule(moduleName, m_ModulesSection, this);
module->setLog(m_Log);
module->load();
m_lModules.append(module);
}
return module;
}
void GSModulesManager::loadAllModules(void *abstractInterface, bool doInit)
{QSettings params;
GSModule* module=Q_NULLPTR;
QStringList modules;
params.beginGroup(m_ModulesSection);
modules=params.childGroups();
int index=modules.indexOf(m_MainModuleName);
if(index>0){
modules[index]=modules[0];
modules[0]=m_MainModuleName;
}
gsInfo(m_Log, 9)<<" Загружаем все модули."<<endl;
for(int i=0; i<modules.size(); ++i){
module=loadModule(modules.at(i));
if(!module->isLoaded()){
gsInfo(m_Log, 9)<<" Модуль "<<modules.at(i)<<" не загружен. Необходимо получить обновление."<<endl;
continue;
}
if(doInit)
if(!module->init((void *)this))
gsInfo(m_Log,0)<<" Не удалось проинициализировать модуль: "<<module->objectName()<<endl;
}
}
void GSModulesManager::unloadModule(GSModule *module)
{
for(int i = 0; i<m_lModules.size(); ++i){
if(module == m_lModules.at(i)){
module=m_lModules.takeAt(i);
delete module;
return;
}
}
}
void GSModulesManager::unloadAllModules()
{GSModule *module;
bool ok=false;
gsInfo(m_Log, 9)<<" Выгружаем все модули. Общее число загруженных модулей "<<m_lModules.size()<<"."<<endl;
while(!m_lModules.isEmpty())
delete m_lModules.takeFirst();
}
void GSModulesManager::setLog(GSLog *log)
{
m_Log=log;
}
void 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();
}
void 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;
}
}
void* GSModulesManager::getWidget(const QString &widgetID)
{void *widget=Q_NULLPTR;
GSModule* module=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;
}
char 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;
}
QString &GSModulesManager::getNewExeName()
{
return m_newExeName;
}
QString &GSModulesManager::getInstName()
{
return m_instReceivedName;
}
void GSModulesManager::exeUpdated(const QString fileName)
{
m_newExeName=fileName;
}
void GSModulesManager::instReceived(const QString fileName)
{
m_instReceivedName=fileName;
}
Исходный код подсистемы работы с параметрами
#include "GSApplication.h"
GSApplication* GSApplication::theApplication()
{ return (GSApplication *)qApp;}
void GSApplication::saveParams()
{QSettings params;
params.setValue("version",applicationVersion());
}
void GSApplication::readParams()
{}
GSLog * GSApplication::createAppLog(const QString &objectName)
{
if(!m_AppLog)
m_AppLog=new GSLog(this, objectName);
return m_AppLog;
}
GSLog *GSApplication::getAppLog()
{ return m_AppLog;}
GSModulesManager* GSApplication::createModulesManager(const QString &objectName)
{
if(!m_ModulesManager)
m_ModulesManager=new GSModulesManager(objectName,this);
return m_ModulesManager;
}
QUuid GSApplication::getAppUID()
{ return m_Uuid;}
GSApplication::GSApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
m_AppLog=Q_NULLPTR;
m_ModulesManager=Q_NULLPTR;
m_Uuid=QUuid::createUuid();
}
GSApplication::~GSApplication()
{
delete m_ModulesManager;
delete m_AppLog;
}
void 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::GSLog(QObject *pobj, const QString &objectName):QObject(pobj)
{
m_LogFile.setObjectName("LogFile");
m_LogFile.setParent(this);
setObjectName(objectName);
}
GSLog::~GSLog()
{
m_LogFile.close();
}
bool 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;
}
bool GSLog::setLogFileName(QString &value)
{
if(value.isEmpty()){
value=m_Params.value(m_ParamsSection+"/log_path",
QStandardPaths::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;
}
QString GSLog::getLogFileName()
{
return m_LogFile.fileName();
}
void GSLog::setLogLevel(int value)
{
m_Params.setValue(m_ParamsSection+"/log_level", value);
}
int GSLog::getLogLevel()
{
return m_Params.value(m_ParamsSection+"/log_level", -1).toInt();
}
void GSLog::setlogMessagesLevel(int value)
{
m_currentLogMessagesLevel=value;
}
GSLog &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 &GSLog::operator <<(QString &value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<value;
return *this;
}
GSLog &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 &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 &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 &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 &GSLog::operator <<(int value)
{
if(m_Params.value(m_ParamsSection+"/log_level", -1).toInt()<m_currentLogMessagesLevel)
return *this;
m_OutStream<<value;
return *this;
}
GSLog &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 &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::~GSUpdateFiles()
{
delete m_UpdatesTree;
m_Log=Q_NULLPTR;
}
void 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";
}
void 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
moduleParams.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);
}
void GSUpdateFiles::checkItemForUpdate(TUpdatePolicy updatePolicy)
{QTreeWidgetItem *rootItem, *currentItem;
int updateVersion, localVersion, modulesCount;
bool update;
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);
}
}
}
void 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();
}
void GSUpdateFiles::showEvent(QShowEvent *event)
{}
void GSUpdateFiles::setLog(GSLog *log)
{
m_Log=log;
}
void 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();
m_TimeOut=params.value("time_out", "60000").toLongLong();
params.setValue("update_connect_str", m_UpdateConnectString);
params.setValue("update_user", m_UpdateUser);
params.setValue("update_passwd", m_UpdatePasswd);
params.setValue("backup_dir", m_BackupDir);
params.setValue("show_dialog", m_ShowDialog);
params.setValue("max_downloads", m_MaxDownloads);
params.setValue("time_out", m_TimeOut);
params.endGroup();
}
void GSUpdateFiles::transferProgress(qint64 bytesReceived, qint64 bytesTotal)
{int childProgressData=0;
if(bytesTotal)
childProgressData=(float(bytesReceived)/bytesTotal*100);
m_DownloadingItem->setText(9, QString::number(childProgressData));
}
void GSUpdateFiles::startTransfer(bool value)
{QTreeWidgetItem *rootItem, *currentItem, *childItem;
QUrl src, dst;
QSettings moduleParams;
bool hasErrors=false;
QTime timer;
gsInfo(m_Log, 9)<<" Загружаем обновления."<<endl;
m_NetworkError=false;
rootItem=m_UpdatesTree->invisibleRootItem();
for(int index=0; index<rootItem->childCount(); index++){
currentItem=rootItem->child(index);
if(currentItem->isHidden())
continue;
for(int childIndex=0; childIndex<currentItem->childCount(); childIndex++){
childItem=currentItem->child(childIndex);
src.setUrl(childItem->text(3)+childItem->text(0));
src.setUserName(m_UpdateUser);
src.setPassword(m_UpdatePasswd);
dst.setUrl(childItem->text(4)+childItem->text(5));
m_DownloadingItem=childItem;
currentItem->setText(9,"Загружаем обновление.");
loadUpdate(src, dst, currentItem->text(2)+"/"+childItem->text(2));
hasErrors|=m_NetworkError;
if(!m_NetworkError)
currentItem->setText(9,"Обновление загружено.");
if(currentItem->text(2)+"/"+childItem->text(2)=="dll/Основной"){
moduleParams.beginGroup(m_ModulesSection+"/"+currentItem->text(0));
moduleParams.setValue("module_path",childItem->text(4).mid(8));
moduleParams.setValue("module_file",childItem->text(0));
moduleParams.endGroup();
}
}
}
if(!hasErrors){
timer.start();
while(timer.elapsed()<2000)
qApp->processEvents();
close();
}
else{
m_Button->setVisible(true);
exec();
}
}
void GSUpdateFiles::loadError(QNetworkReply::NetworkError error)
{
gsInfo(m_Log,0)<<" Превышен интервал выполнения запроса!"<<endl;
if(m_ShowDialog=="1")
m_DownloadingItem->parent()->setText(9, "Ошибка!");
m_NetworkError=true;
}
void GSUpdateFiles::loadTimeOut()
{}
ProgressBarDelegate::ProgressBarDelegate(QObject *parent)
: QItemDelegate(parent)
{}
void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QStyleOptionProgressBar progressBarOption;
if(index.parent()==QModelIndex()){
QItemDelegate::paint(painter, option, index);
return;
}
progressBarOption.state = QStyle::State_Enabled;
progressBarOption.direction = QApplication::layoutDirection();
progressBarOption.rect = option.rect;
progressBarOption.fontMetrics = QApplication::fontMetrics();
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.textAlignment = Qt::AlignCenter;
progressBarOption.textVisible = true;
int progress=index.data().toInt();
progressBarOption.progress = progress < 0 ? 0 : progress;
progressBarOption.text = index.data().toString()+" %";
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}
Исходный код подсистемы загрузки файлов
#include "headers/downloadmanager.h"
#include "headers/autosaver.h"
#include "headers/browserapplication.h"
#include <math.h>
#include <QtCore/QMetaEnum>
#include <QtCore/QSettings>
#include <QtGui/QDesktopServices>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QFileIconProvider>
#include <QtCore/QDebug>
#include <QWebEngineSettings>
#include <QWebEngineDownloadItem>
#include <QMessageBox>
#include "../../Libs/src/WithQT/DebenuPdfLib/DebenuPDFLibraryDLLQt1113.h"
DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent)
: QWidget(parent)
, m_bytesReceived(0)
, m_download(download)
{
setupUi(this);
QPalette p = downloadInfoLabel->palette();
p.setColor(QPalette::Text, Qt::darkGray);
downloadInfoLabel->setPalette(p);
progressBar->setMaximum(0);
connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
connect(printButton, SIGNAL(clicked()), this, SLOT(print()));
if (download) {
m_file.setFile(download->path());
m_url = download->url();
}
init();
}
void DownloadWidget::init()
{
if (m_download) {
connect(m_download.data(), SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(downloadProgress(qint64,qint64)));
connect(m_download.data(), SIGNAL(finished()),
this, SLOT(finished()));
}
downloadInfoLabel->clear();
progressBar->setValue(0);
getFileName();
// start timer for the download estimation
m_downloadTime.start();
}
bool DownloadWidget::getFileName(bool promptForFileName)
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
QString defaultLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
if (m_file.absoluteDir().exists())
defaultLocation = m_file.absolutePath();
QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString();
if (!downloadDirectory.isEmpty())
downloadDirectory += QLatin1Char('/');
QString defaultFileName = QFileInfo(downloadDirectory, m_file.fileName()).absoluteFilePath();
QString fileName = defaultFileName;
if (promptForFileName) {
fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName);
if (fileName.isEmpty()) {
if (m_download)
m_download->cancel();
fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName()));
return false;
}
}
m_file.setFile(fileName);
if (m_download && m_download->state() == QWebEngineDownloadItem::DownloadRequested)
m_download->setPath(m_file.absoluteFilePath());
fileNameLabel->setText(m_file.fileName());
return true;
}
void DownloadWidget::stop()
{
setUpdatesEnabled(false);
stopButton->setEnabled(false);
stopButton->hide();
setUpdatesEnabled(true);
if (m_download)
m_download->cancel();
emit statusChanged();
}
void DownloadWidget::open()
{QString strCommand = "cmd /C ", default_editor="";
QSettings params;
QUrl url = QUrl::fromLocalFile(m_file.absoluteFilePath());
default_editor=params.value("default_editor", "").toString();
if(default_editor.isEmpty()){
QMessageBox::critical(0, "Внимание!", "Не настроен редактор документов.\n Редактирование невозможно.",
QMessageBox::Ok);
return;
}
strCommand+=QString("\"")+default_editor+QString("\" ")+url.toString();
m_process.start(strCommand);
}
void DownloadWidget::print()
{DebenuPDFLibraryDLLQt1113 pdfTest(QString("DebenuPDFLibraryDLL1113.dll"));
int iOptions;
QString pdfFileName, customPrinter;
QStringList printParams;
QSettings moduleParams;
if(!pdfTest.LibraryLoaded()){
QMessageBox::critical(0, "Печать PDF", "Библиотека не загружена!", QMessageBox::Ok);
return;
}
if(pdfTest.UnlockKey("j39163i38a653748u9f66rb5y")!=1){
QMessageBox::critical(0, "Печать PDF", "Ошибка инициализации!", QMessageBox::Ok);
return;
}
pdfFileName=m_file.absoluteFilePath();
printParams=m_download->url().toDisplayString().section("?",1,1).split("&", QString::SkipEmptyParts);
pdfTest.LoadFromFile(pdfFileName, QString(""));
iOptions=printParams.indexOf("printerName=*");
if(iOptions>-1)
customPrinter=moduleParams.value("Printers/"+printParams.at(iOptions).section("=",1,1),pdfTest.GetDefaultPrinterName()).toString();
else
customPrinter=pdfTest.GetDefaultPrinterName();
customPrinter=pdfTest.NewCustomPrinter(customPrinter);
pdfTest.SetupCustomPrinter(customPrinter,1,9);
pdfTest.SetupCustomPrinter(customPrinter,4,1);
pdfTest.SetupCustomPrinter(customPrinter,7,1);
pdfTest.SetupCustomPrinter(customPrinter,11,1);
for(int i=0; i<printParams.size(); i++){
if(printParams.at(i).contains("copies="))
pdfTest.SetupCustomPrinter(customPrinter,4,printParams.at(i).section("=",1,1).toInt());//Количество копий
if(printParams.at(i).contains("format=")){
if(printParams.at(i).section("=",1,1)=="A5")
pdfTest.SetupCustomPrinter(customPrinter,1,11);
}
if(printParams.at(i).contains("duplex=")){
if(printParams.at(i).section("=",1,1)=="vertical")
pdfTest.SetupCustomPrinter(customPrinter,7,2);
if(printParams.at(i).section("=",1,1)=="horizontal")
pdfTest.SetupCustomPrinter(customPrinter,7,3);
}
if(printParams.at(i).contains("orientation=")){
if(printParams.at(i).section("=",1,1)=="landscape")
pdfTest.SetupCustomPrinter(customPrinter,11,2);
}
}
iOptions=pdfTest.PrintOptions(0, 0, "PDF_MIS");
pdfTest.PrintDocument(customPrinter,1,pdfTest.PageCount(),iOptions);
}
void DownloadWidget::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
m_bytesReceived = bytesReceived;
if (bytesTotal == -1) {
progressBar->setValue(0);
progressBar->setMaximum(0);
} else {
progressBar->setValue(bytesReceived);
progressBar->setMaximum(bytesTotal);
}
updateInfoLabel();
}
void DownloadWidget::updateInfoLabel()
{
qint64 bytesTotal = progressBar->maximum();
double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed;
QString timeRemainingString = tr("seconds");
if (timeRemaining > 60) {
timeRemaining = timeRemaining / 60;
timeRemainingString = tr("minutes");
}
timeRemaining = floor(timeRemaining);
// When downloading the eta should never be 0
if (timeRemaining == 0)
timeRemaining = 1;
QString info;
if (!downloadedSuccessfully()) {
QString remaining;
if (bytesTotal != 0)
remaining = tr("- %4 %5 remaining")
.arg(timeRemaining)
.arg(timeRemainingString);
info = tr("%1 of %2 (%3/sec) %4")
.arg(dataString(m_bytesReceived))
.arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal))
.arg(dataString((int)speed))
.arg(remaining);
} else {
if (m_bytesReceived != bytesTotal) {
info = tr("%1 of %2 - Stopped")
.arg(dataString(m_bytesReceived))
.arg(dataString(bytesTotal));
} else
info = dataString(m_bytesReceived);
}
downloadInfoLabel->setText(info);
}
QString DownloadWidget::dataString(int size) const
{
QString unit;
if (size < 1024) {
unit = tr("bytes");
} else if (size < 1024*1024) {
size /= 1024;
unit = tr("kB");
} else {
size /= 1024*1024;
unit = tr("MB");
}
return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
}
bool DownloadWidget::downloading() const
{
return (progressBar->isVisible());
}
bool DownloadWidget::downloadedSuccessfully() const
{
bool completed = m_download
&& m_download->isFinished()
&& m_download->state() == QWebEngineDownloadItem::DownloadCompleted;
return completed || !stopButton->isVisible();
}
void DownloadWidget::finished()
{QString url;
if (m_download) {
QWebEngineDownloadItem::DownloadState state = m_download->state();
QString message;
bool interrupted = false;
switch (state) {
case QWebEngineDownloadItem::DownloadRequested: // Fall-through.
case QWebEngineDownloadItem::DownloadInProgress:
Q_UNREACHABLE();
break;
case QWebEngineDownloadItem::DownloadCompleted:
break;
case QWebEngineDownloadItem::DownloadCancelled:
message = QStringLiteral("Download cancelled");
interrupted = true;
break;
case QWebEngineDownloadItem::DownloadInterrupted:
message = QStringLiteral("Download interrupted");
interrupted = true;
break;
}
if (interrupted) {
downloadInfoLabel->setText(message);
return;
}
}
progressBar->hide();
stopButton->setEnabled(false);
stopButton->hide();
updateInfoLabel();
url=m_download->url().toDisplayString();
if(url.contains("fn=open"))
open();
if(url.contains("fn=print"))
print();
emit statusChanged();
}
/*!
DownloadManager is a Dialog that contains a list of DownloadWidgets
It is a basic download manager. It only downloads the file, doesn't do BitTorrent,
extract zipped files or anything fancy.
*/
DownloadManager::DownloadManager(QWidget *parent)
: QDialog(parent)
, m_autoSaver(new AutoSaver(this))
, m_iconProvider(0)
, m_removePolicy(Never)
{
setupUi(this);
downloadsView->setShowGrid(false);
downloadsView->verticalHeader()->hide();
downloadsView->horizontalHeader()->hide();
downloadsView->setAlternatingRowColors(true);
downloadsView->horizontalHeader()->setStretchLastSection(true);
m_model = new DownloadModel(this);
downloadsView->setModel(m_model);
connect(cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup()));
load();
}
DownloadManager::~DownloadManager()
{
m_autoSaver->changeOccurred();
m_autoSaver->saveIfNeccessary();
if (m_iconProvider)
delete m_iconProvider;
}
int DownloadManager::activeDownloads() const
{
int count = 0;
for (int i = 0; i < m_downloads.count(); ++i) {
if (m_downloads.at(i)->stopButton->isEnabled())
++count;
}
return count;
}
void DownloadManager::download(QWebEngineDownloadItem *download)
{
DownloadWidget *widget = new DownloadWidget(download, this);
addItem(widget);
}
void DownloadManager::addItem(DownloadWidget *widget)
{
connect(widget, SIGNAL(statusChanged()), this, SLOT(updateRow()));
int row = m_downloads.count();
m_model->beginInsertRows(QModelIndex(), row, row);
m_downloads.append(widget);
m_model->endInsertRows();
updateItemCount();
downloadsView->setIndexWidget(m_model->index(row, 0), widget);
QIcon icon = style()->standardIcon(QStyle::SP_FileIcon);
widget->fileIcon->setPixmap(icon.pixmap(48, 48));
downloadsView->setRowHeight(row, widget->sizeHint().height());
}
void DownloadManager::updateRow()
{
DownloadWidget *widget = qobject_cast<DownloadWidget*>(sender());
int row = m_downloads.indexOf(widget);
if (-1 == row)
return;
if (!m_iconProvider)
m_iconProvider = new QFileIconProvider();
QIcon icon = m_iconProvider->icon(widget->m_file);
if (icon.isNull())
icon = style()->standardIcon(QStyle::SP_FileIcon);
widget->fileIcon->setPixmap(icon.pixmap(48, 48));
downloadsView->setRowHeight(row, widget->minimumSizeHint().height());
bool remove = false;
if (!widget->downloading()
&& BrowserApplication::instance()->privateBrowsing())
remove = true;
if (widget->downloadedSuccessfully()
&& removePolicy() == DownloadManager::SuccessFullDownload) {
remove = true;
}
if (remove)
m_model->removeRow(row);
cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
}
DownloadManager::RemovePolicy DownloadManager::removePolicy() const
{
return m_removePolicy;
}
void DownloadManager::setRemovePolicy(RemovePolicy policy)
{
if (policy == m_removePolicy)
return;
m_removePolicy = policy;
m_autoSaver->changeOccurred();
}
void DownloadManager::save() const
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy)));
settings.setValue(QLatin1String("size"), size());
if (m_removePolicy == Exit)
return;
for (int i = 0; i < m_downloads.count(); ++i) {
QString key = QString(QLatin1String("download_%1_")).arg(i);
settings.setValue(key + QLatin1String("url"), m_downloads[i]->m_url);
settings.setValue(key + QLatin1String("location"), m_downloads[i]->m_file.filePath());
settings.setValue(key + QLatin1String("done"), m_downloads[i]->downloadedSuccessfully());
}
int i = m_downloads.count();
QString key = QString(QLatin1String("download_%1_")).arg(i);
while (settings.contains(key + QLatin1String("url"))) {
settings.remove(key + QLatin1String("url"));
settings.remove(key + QLatin1String("location"));
settings.remove(key + QLatin1String("done"));
key = QString(QLatin1String("download_%1_")).arg(++i);
}
}
void DownloadManager::load()
{
QSettings settings;
settings.beginGroup(QLatin1String("downloadmanager"));
QSize size = settings.value(QLatin1String("size")).toSize();
if (size.isValid())
resize(size);
QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray();
QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ?
Never :
static_cast<RemovePolicy>(removePolicyEnum.keyToValue(value));
int i = 0;
QString key = QString(QLatin1String("download_%1_")).arg(i);
while (settings.contains(key + QLatin1String("url"))) {
QUrl url = settings.value(key + QLatin1String("url")).toUrl();
QString fileName = settings.value(key + QLatin1String("location")).toString();
bool done = settings.value(key + QLatin1String("done"), true).toBool();
if (done && !url.isEmpty() && !fileName.isEmpty()) {
DownloadWidget *widget = new DownloadWidget(0, this);
widget->m_file.setFile(fileName);
widget->fileNameLabel->setText(widget->m_file.fileName());
widget->m_url = url;
widget->stopButton->setVisible(false);
widget->stopButton->setEnabled(false);
widget->progressBar->hide();
addItem(widget);
}
key = QString(QLatin1String("download_%1_")).arg(++i);
}
cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0);
}
void DownloadManager::cleanup()
{
if (m_downloads.isEmpty())
return;
m_model->removeRows(0, m_downloads.count());
updateItemCount();
if (m_downloads.isEmpty() && m_iconProvider) {
delete m_iconProvider;
m_iconProvider = 0;
}
m_autoSaver->changeOccurred();
}
void DownloadManager::updateItemCount()
{
int count = m_downloads.count();
itemCount->setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count));
}
DownloadModel::DownloadModel(DownloadManager *downloadManager, QObject *parent)
: QAbstractListModel(parent)
, m_downloadManager(downloadManager)
{}
QVariant DownloadModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= rowCount(index.parent()))
return QVariant();
if (role == Qt::ToolTipRole)
if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully())
return m_downloadManager->m_downloads.at(index.row())->downloadInfoLabel->text();
return QVariant();
}
int DownloadModel::rowCount(const QModelIndex &parent) const
{ return (parent.isValid()) ? 0 : m_downloadManager->m_downloads.count();}
bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (parent.isValid())
return false;
int lastRow = row + count - 1;
for (int i = lastRow; i >= row; --i) {
if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully()) {
beginRemoveRows(parent, i, i);
m_downloadManager->m_downloads.takeAt(i)->deleteLater();
endRemoveRows();
}
}
m_downloadManager->m_autoSaver->changeOccurred();
return true;
}
Исходный код диалогового окона печати в pdf
#include "headers/printtopdfdialog.h"
#include "ui_printtopdfdialog.h"
#include <QtCore/QDir>
#ifndef QT_NO_PRINTER
#include <QtPrintSupport/QPageSetupDialog>
#include <QtPrintSupport/QPrinter>
#endif // QT_NO_PRINTER
#include <QtWidgets/QFileDialog>
PrintToPdfDialog::PrintToPdfDialog(const QString &filePath, QWidget *parent) :
QDialog(parent),
currentPageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0))),
ui(new Ui::PrintToPdfDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(ui->chooseFilePathButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChooseFilePathButtonClicked);
#ifndef QT_NO_PRINTER
connect(ui->choosePageLayoutButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChoosePageLayoutButtonClicked);
#else
ui->choosePageLayoutButton->hide();
#endif // QT_NO_PRINTER
updatePageLayoutLabel();
setFilePath(filePath);
Подобные документы
Разработка собственного алгоритма сжатия и восстановления данных с использованием возможностей языка C++ в рамках программного продукта "Архиватор". Разработка алгоритма программы, ее первый запуск и тестирование. Проверка работы архивации файлов.
курсовая работа [325,7 K], добавлен 13.10.2015Организация входных и выходных данных. Выбор состава технических и программных средств. Функционал для заполнения заявки для постоянно клиента. Форма вывода справки по программе. Таблица файлов, входящих в проект. Тестирование программы, ее листинг.
курсовая работа [2,5 M], добавлен 25.05.2014Выбор инструментальных и программных средств для создания сайта. Структура программного продукта. Создание сайта при помощи программы WordPress. Тестирование разработанной программы. Разработка структуры и дизайна сайта. Наполнение сайта контентом.
курсовая работа [1,0 M], добавлен 09.01.2014Анализ функциональной структуры и обеспечивающей части АСУ. Проектирование функциональной структуры подсистемы управления проблемами, разработка модели в среде CPN Tools и алгоритма работы. Описание программного и технического обеспечения проекта.
дипломная работа [5,6 M], добавлен 26.06.2011Функциональные характеристики программы форматирования текстовых файлов, требования к ее интерфейсу и данным. Схема взаимодействия компонентов системы, выбор среды исполнения и программная реализация алгоритмов. Тестирование и оценка качества программы.
курсовая работа [61,1 K], добавлен 25.07.2012Обзор существующих аналогов программных средств, предназначенных для построения генеалогических деревьев, их достоинства и недостатки. Выбор программных средств, разработка и реализация архитектуры системы хранения данных, отладка и тестирование сервиса.
дипломная работа [177,1 K], добавлен 24.06.2012Формат звукового файла wav, способ его кодирования. Реализация возможностей воспроизведения звука в среде программирования MATLAB. Составление функциональной схемы программы. Апробирование информационной технологии воспроизведения звуковых файлов.
курсовая работа [1,2 M], добавлен 13.02.2016Диагностический анализ системы управления предприятия, его организационной и функциональной структуры. Разработка проекта подсистемы учёта средств вычислительной техники, описание технического обеспечения базы данных. Характеристика программного продукта.
дипломная работа [7,2 M], добавлен 28.06.2011Разработка эскизного и технического проектов программы, ее назначение и область применения, технические характеристики. Организация входных и выходных данных, выбор состава технических и программных средств. Текст программы, ее описание и тестирование.
курсовая работа [1,3 M], добавлен 15.11.2009Исследование алгоритмов и характеристик существующих программных систем аналогов для проверки знаний: Aму Life Test Gold, SunRav TestOfficePro. Разработка архитектуры программной системы. Проверка программы в нормальных условиях, руководство пользователя.
курсовая работа [2,5 M], добавлен 17.06.2012