Разработка идеи объединения сторонних решений и реализация многофункционального, легко масштабируемого приложения
Разработка функциональной и структурной схемы программного средства. Реализация основного модуля программы. Реализация модуля печати и модуля обновлений. Изучение взаимодействия информационных технологий, методов их интеграции и обмена данными.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 27.10.2017 |
Размер файла | 3,2 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
5) void finished().
На рисунке 3.11 изображен снимок экрана реализованной подсистемы печати, вынесенной в файл gsUpdateFiles.cpp.
Рисунок 3.11 Снимок экрана реализованной подсистемы загрузки файлов
Исходный код подсистемы загрузки файлов представлен в приложении Е.
3.3.2 Разработка подсистемы печати
Модуль печати состоит из сторонней библиотеки, над которой сделана надстройка, где прописаны все функции этой библиотеки, а так же вызовы этих функций приведены к стандартному виду qt. Таким образом скрыто низкоуровневое обращение к функциям сторонней библиотеки. Основной функцией модуля печати является получение файла, затем, в зависимости от параметра в адресе страницы, либо сразу отправляется на печать, либо открывается предустановленным в ОС программным обеспечением. Перед отправкой на печать (прозрачной), этот модуль может указать размер бумаги, ее ориентацию, дуплекс и количество копий.
На рисунке 3.12 изображен снимок экрана реализованного диалогового окна печати в файл формата pdf, вынесенного в файл printtopdfdialog.cpp.
Рисунок 3.12 Снимок экрана реализованного диалогового окна печати в файл формата pdf
Исходный код реализованного диалогового окна печати в файл формата pdf представлен в приложении Ж.
3.3.3 Разработка подсистемы настроек
Настройки всей системы реализованы в реестре операционной системы. Они позволяют не просто настроить систему, но полностью изменить логику ее работы, путем изменения или добавления библиотек.
На рисунке 3.13 изображен снимок экрана реализованной подсистемы настроек вынесенной в файл settings.cpp.
Рисунок 3.13 Снимок экрана реализованной подсистемы настроек системы
3.3.4 Создание инсталлятора программной системы
Для создания инсталлятора целесообразно воспользоваться готовыми программными средствами, например, Inno Setup. Для работы системы необходим следующий набор компонент:
1. Исполняемый файл ядра системы.
2. Модуль главного окна системы.
3. Функциональные библиотеки.
Скрипт Inno Setup, который содержит свойства дистрибутива и набор производимых действий при установке и удалении представлен в приложении З.
4. Тестирование системы
4.1 Инсталяция программы
Инстлятор клиента представляет собой исполняемый файл с раширением.exe. Его название имеет следующий вид: InterinClient_XX_setup, где XX - версия инсталятора. В процессе установки пользователю предлагается прочесть лицензионное соглашение, выбрать директурю для установки, а так же у пользователя есть возможность вобора название приложения в меню пуск, и необходимость создания ярлыка на рабочем столе. На рисунке 4.1 представлен снимок экрана процесса установки клиента.
Рисунок 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» в двух медицинских организациях.
Результаты работы представляют высокую практическую значимость, поскольку разработанный клиент предоставляет возможность быстрой адаптации к различным информационным системам, путем изменения отдельных библиотек, что позволяет не просто расширять его функционал, а полностью изменять логику работы системы.
Список использованных источников
1. Интернет-портал «О хостинге» [Электронный ресурс]. Режим доступа: http://ohostinge.com/dictionary/proxy-server.
2. Энциклопедия «Wikipedia» [Электронный ресурс]. Режим доступа: https://ru.wikipedia.org/wiki/Браузер.
3. Интернет-портал «Opensuse» [Электронный ресурс]. Режим доступа: https://ru.opensuse.org/Библиотека_Qt.
4. Интернет-портал «СITForum» [Электронный ресурс]. Режим доступа: http://citforum.ru/programming/cpp_march/cpp_013.shtml.
5. Интернет-портал «1С:ИТС» [Электронный ресурс]. Режим доступа: https://its.1c.ru/db/metod8dev#content:3221:hdoc.
6. Интернет-портал «Introligator» [Электронный ресурс]. Режим доступа: http://www.introligator.org/articles/1/36.
7. Интернет-портал «Java-course» [Электронный ресурс]. Режим доступа: http://java-course.ru/begin/abstract/.
8. Интернет-портал «DOC.QT» [Электронный ресурс]. Режим доступа: https://doc.qt.io/qt-5/qtwebenginewidgets-module.html.
9. Интернет-портал «Habrhabr» [Электронный ресурс]. Режим доступа: https://habrahabr.ru/post/152637/.
10. Интернет-портал «Легион.net» [Электронный ресурс]. Режим доступа: http://xn--c1adkjnf.net/debenu-quick-pdf-library/.
11. Интернет-портал «Crossplatform.ru» [Электронный ресурс]. Режим доступа: http://doc.crossplatform.ru/qtcreator/2.0.1/creator-overview.html.
12. Интернет-портал «IBM» [Электронный ресурс]. Режим доступа: https://www.ibm.com/developerworks/ru/library/l-qt_1/index.html.
13. Интернет-портал «Habrhabr» [Электронный ресурс]. Режим доступа: https://habrahabr.ru/post/110544/.
14. Интернет-портал «Сppreference.com» [Электронный ресурс]. Режим доступа: http://ru.cppreference.com/w/cpp/language/main_function.
15. Интернет-портал «ММТР технологии» [Электронный ресурс]. Режим доступа: http://mmtr.ru/fun_testing.html.
Приложение А
(Обязательное)
Исходный код функции 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();
Подобные документы
Структурная диаграмма программного модуля. Разработка схемы программного модуля и пользовательского интерфейса. Реализация программного модуля: код программы; описание использованных операторов и функций. Вид пользовательской формы с заполненной матрицей.
курсовая работа [215,3 K], добавлен 01.09.2010Разработка концептуальной модели базы данных. Реализация алгоритмов и разработка управляющей программы. Разработка структуры системы управления данными. Методика проведения и результаты тестирования. Функционирование разработанного программного модуля.
курсовая работа [550,5 K], добавлен 08.06.2023Проектирование программного модуля: сбор исходных материалов; описание входных и выходных данных; выбор программного обеспечения. Описание типов данных и реализация интерфейса программы. Тестирование программного модуля и разработка справочной системы.
курсовая работа [81,7 K], добавлен 18.08.2014Структурная диаграмма программного модуля. Нахождение суммы элементов, находящихся над главной диагональю. Реализация программного модуля: код программы; описание использованных операторов и функций. Особенности тестирования программного модуля.
курсовая работа [146,6 K], добавлен 01.09.2010Реализация программного средства "Действия над матрицами". Разработка кода программного продукта на основе готовой спецификации на уровне модуля. Использование инструментальных средств на этапе отладки программного модуля. Выбор стратегии тестирования.
отчет по практике [296,1 K], добавлен 19.04.2015Разработка структурной диаграммы программного модуля. Представление схемы для основных расчетов выбранного приложения для создания прямоугольной матрицы. Особенности создания пользовательского интерфейса. Тестирование и отладка спроектированного модуля.
курсовая работа [648,4 K], добавлен 27.05.2015Разработка и реализация программы расчета заданных функций на языке программирования VBA. Математическая модель, параметры и характеристики задачи, критерии оценки эффективности созданного модуля. Разработка алгоритма и тестирование программного модуля.
курсовая работа [488,7 K], добавлен 08.09.2010Анализ модуля интеграции на предприятии "Вазаро". Оценка электронной коммерции и интернет-магазинов в частности. Реализация необходимых изменений в модуле интеграции "1С: Предприятие" и интернет-магазина. Расчет стоимости и прибыльности модернизации.
дипломная работа [2,8 M], добавлен 03.07.2014Постановка задачи для модуля 1С. Бухгалтерия 3.0. Анализ существующих разработок в области интегрирования данных. Информационное обеспечение модуля "Связь 1С Предприятия 8.2. с "Казначейством". Программное и технологическое обеспечение данного модуля.
курсовая работа [1,5 M], добавлен 10.06.2013Разработка структурной схемы и алгоритма функционирования микропроцессорного модуля программного обеспечения автоматизированной информатизационно-измерительной системы. Характеристика принципиальной схемы модуля, распределения памяти и задание портов.
курсовая работа [1,2 M], добавлен 28.08.2012