/
ArchiveAnalizer.py
342 lines (310 loc) · 17.3 KB
/
ArchiveAnalizer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# -*- coding: utf-8 -*-
# Анализ архива ПО "Интеллект".
# Стерликов К. @ 2013
import sys
import os
from ui.ui_main import Ui_main
from PyQt4 import QtCore, QtGui
from kstools import kssys, ksitv, ksqt, ksconfig, ksenv
import logging
from thrMng import ThrMng
import lya
class main(QtGui.QMainWindow):
"""
Класс основной формы
"""
cfgVersion = "2.0.1"
cfgYaer = "2013"
cfgDefaultFileName = "cfg_default.yaml" # Имя файла конфигурации по умолчанию.
cfgUserFilename = "cfg_user.yaml" # Имя фалйа конфигурации пользоателя по умолчанию.
isProcess = False # Программа находится в процессе работы.
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_main()
self.ui.setupUi(self)
self.baseDir = kssys.getWorkPath() # Рабочая директория программы.
self.threadManager = ThrMng() # Поток менеджера обработки данных.
# Слоты.
self.ui.pushButton.clicked.connect(self.clickOpenCacheFolder) # Открытие папки с кэшэм базы.
self.ui.pushButton_2.clicked.connect(self.clickOpenFileDialog) # Диалог выбора файла.
self.ui.pushButton_3.clicked.connect(self.clickProcess) # Начало процесса создания отчетов.
self.ui.pushButton_4.clicked.connect(self.clickClearFileLine) # Очистка поля выбора внешнего файла.
self.ui.pushButton_5.clicked.connect(self.clickOpenOutFolder) # Открытие папки с выходными файлами.
self.ui.action.triggered.connect(self.clickAbout) # Информация о прогремме.
self.ui.action_Qt.triggered.connect(self.clickAboutQt) # Информация о Qt.
self.connect(self.threadManager, QtCore.SIGNAL("information(QString)"), self.addLogInform, QtCore.Qt.QueuedConnection)
self.connect(self.threadManager, QtCore.SIGNAL("progress(QString)"), self.progress, QtCore.Qt.QueuedConnection)
self.connect(self.threadManager, QtCore.SIGNAL("started()"), lambda: self.formDisabled(True))
self.connect(self.threadManager, QtCore.SIGNAL("finished()"), self.finishProcess)
# Ищем конфиг по умолчанию в теущей папке (если нет завершаем работу программы). Ищем пользовательские настройки и
# наклаываем их на дефаултные.
try:
self.cfg = lya.AttrDict.from_yaml(os.path.join(self.baseDir, self.cfgDefaultFileName))
except IOError, e:
self.errorMsgCritical(unicode(e.__str__(), "cp1251"))
else:
try:
self.cfg.update_yaml(os.path.join(ksenv.getLocalAppDataPath(), self.cfg.main.dir.app_dir, self.cfgUserFilename))
except IOError, e:
logging.error(u"Не удалось прочитать файл пользовательской конфигурации: %s" % unicode(e.__str__(), "cp1251"))
pass
self.configToForm()
# Создание рабочих папок.
# Кэш созраняется в %ALLUSERSPROFILE%, выходная директория создаётся в "моих документах".
try:
dirs = (
os.path.join(ksenv.getLocalAppDataPath(), self.cfg.main.dir.app_dir),
os.path.join(ksenv.getAllUsersProfile(), self.cfg.main.dir.app_dir),
os.path.join(ksenv.getLocationInQt("documents"), self.cfg.main.dir.app_dir),
)
for dir in dirs:
if not os.path.exists(dir):
os.mkdir(dir)
except Exception, e:
self.errorMsgCritical((u"Невозможно создать директорию.", unicode(e.__str__(), 'cp1251',)))
def clickAbout(self):
"""
Информация о программе.
"""
QtGui.QMessageBox.information(
self,
u"О программе...",
u"""
<b>Анализатор видео архива ПО «Интеллект» версии %s</b>
<br>
Автор: Стерликов К.С. @ %s
""" % (self.cfgVersion, self.cfgYaer),
QtGui.QMessageBox.Information
)
def clickAboutQt(self):
"""
Информация о программе.
"""
QtGui.QMessageBox.aboutQt(self)
def clickOpenCacheFolder(self):
"""
Открыть папку с кэшем.
"""
path = os.path.join(ksenv.getAllUsersProfile(), self.cfg.main.dir.app_dir)
try:
os.startfile(path)
except Exception, e:
print e
self.errorMsg((u"Не удаётся открыть папку с кэшем базы архива", unicode(e.__str__(), "cp1251"),))
def clickOpenOutFolder(self):
"""
Открыть папку с выходными файлами.
"""
path = os.path.join(ksenv.getLocationInQt("documents"), self.cfg.main.dir.app_dir)
try:
os.startfile(path)
except Exception, e:
self.errorMsg((u"Не удаётся открыть папку с отчётами.", unicode(e.__str__(), "cp1251"),))
def closeEvent(self, *args, **kwargs):
"""
Переопределяем событие выхода из формы.
"""
self.configToFile()
QtGui.QWidget.closeEvent(self, *args, **kwargs)
def configToForm(self):
"""
Установка параметров формы в зависимости от конфигурации.
"""
self.ui.checkBox_2.setChecked(self.cfg.main.report.in_day)
self.ui.checkBox.setChecked(self.cfg.main.report.cam_in_day)
self.ui.checkBox_3.setChecked(self.cfg.main.report.cam_in_hour)
self.ui.checkBox_4.setChecked(self.cfg.main.triggers.exec_after_create)
self.ui.checkBox_5.setChecked(self.cfg.main.triggers.each_create_new_cache)
if len(self.cfg.main.backup.file) and os.path.exists(self.cfg.main.backup.file):
self.ui.lineEdit.setText(self.cfg.main.backup.file)
def configToFile(self):
"""
Сохранение и сохранение текущего значения конфигурации на диск.
"""
self.cfg.main.report.in_day = self.ui.checkBox_2.checkState() == QtCore.Qt.Checked
self.cfg.main.report.cam_in_day = self.ui.checkBox.checkState() == QtCore.Qt.Checked
self.cfg.main.report.cam_in_hour = self.ui.checkBox_3.checkState() == QtCore.Qt.Checked
self.cfg.main.triggers.exec_after_create = self.ui.checkBox_4.checkState() == QtCore.Qt.Checked
self.cfg.main.triggers.each_create_new_cache = self.ui.checkBox_5.checkState() == QtCore.Qt.Checked
self.cfg.main.backup.file = unicode(self.ui.lineEdit.text())
try:
f = open(os.path.join(ksenv.getLocalAppDataPath(), self.cfg.main.dir.app_dir, self.cfgUserFilename), "w")
self.cfg.dump(f)
except Exception, e:
self.errorMsg((u"Невозможно сохранить конфигурацию программы", unicode(e.__str__(), "cp1251"),))
def progress(self, num):
"""
Установка прогресс бара.
"""
self.ui.progressBar.setValue(int(num))
self.ui.progressBar.repaint()
def addLogInform(self, message):
"""
Вывод сообщения в информационное окно.
"""
self.ui.textEdit.append('<span style="color: #505050">%s</span>' % message)
def addLogOk(self, message):
"""
Вывод положительного результата в информационное окно.
"""
self.ui.textEdit.append('<span style="color: #009100">%s</span>' % message)
def addLogWarning(self, message):
"""
Вывод предупреждения в информационное окно.
"""
self.ui.textEdit.append('<span style="color: #919100">%s</span>' % message)
def addLogError(self, message):
"""
Вывод ошибки в информационное окно.
"""
self.ui.textEdit.append('<span style="color: #910000">%s</span>' % message)
def addLogCommand(self, command):
"""
Команда для информационного окна.
"""
if command == "clear":
self.ui.textEdit.clear()
else:
raise ValueError(u"Передана необрабатываемая комманда.")
def formDisabled(self, disabled=True):
"""
Блокировка / разблокировка формы.
"""
elements = (
self.ui.pushButton,
self.ui.pushButton_2,
self.ui.pushButton_4,
self.ui.pushButton_5,
self.ui.checkBox,
self.ui.checkBox_2,
self.ui.checkBox_3,
)
for item in elements:
if disabled:
item.setDisabled(True)
else:
item.setEnabled(True)
self.ui.pushButton_3.setEnabled(True)
if disabled:
self.ui.pushButton_3.setText(u"Остановить")
else:
self.ui.pushButton_3.setText(u"Сформировать")
def clickClearFileLine(self):
"""
Очистка пути к файлу с базой.
"""
self.ui.lineEdit.setText(u"")
self.cacheFile = ""
def clickOpenFileDialog(self):
"""
Диалог выбора файла с внешней базой данных.
"""
dirName = os.path.join(ksenv.getAllUsersProfile(), self.cfg.main.dir.app_dir)
fileName = QtGui.QFileDialog().getOpenFileName(self, u"Выберите .sql файл...", directory=dirName, filter="*.sql")
if fileName:
self.ui.lineEdit.setText(fileName)
self.cacheFile = fileName
def clickProcess(self):
"""
Начало процесса создания отчетов.
ВНИМАНИЕ! Работает только для первого попавшегося диска с вдиое архивом.
"""
if self.isProcess: # Поток находится в процессе работы:
self.threadManager.chancel = True
self.ui.pushButton_3.setDisabled(True)
else:
self.addLogCommand(u"clear")
archDisks = ksitv.getArchiveDisks() # Списки дисков с крхивами.
if not archDisks:
self.addLogWarning(u"Не найдены жёсткие диски с видео-архивами.")
ksqt.message(self, "warning", u"Внимание...", u"Не найдены жёсткие диски с видео-архивами.")
else:
self.addLogInform(u"Обнаружены диски с архивами: %s" % (", ".join(["%s:" % item for item in archDisks])))
if len(archDisks) > 1:
self.addLogWarning(u"Обнаружено, что видео архив расположен на нескольких жестких дисках: %s<br>что не поддерживается в текущей версии программы." % (", ".join(["%s:" % item for item in archDisks])))
ksqt.message(self, "warning", u"Внимание...", u"Обнаружено, что видео архив расположен на нескольких жестких дисках: %s\nчто не поддерживается в текущей версии программы." % (", ".join(["%s:" % item for item in archDisks])))
else:
# Чтение всех директорий из указанных папок.
archDisk = archDisks[0] # Диск с архивом.
dirList = ksitv.getArchiveFolder(archDisk) # Список папок в архиве.
if not dirList:
self.addLogWarning(u"Видео архив пуст.")
ksqt.message(self, "inform", u"Информация...", u"Видео архив пуст.")
else:
# Запускаем менеджер обработки данных.
self.threadManager.initialize()
self.threadManager.archDisk = archDisk
self.threadManager.dirList = dirList
self.threadManager.logging = logging
self.threadManager.cfg = self.cfg
self.threadManager.workDir = self.baseDir
#self.threadManager.tableName = self.tableName
#self.threadManager.cacheDir = self.cacheDir
#self.threadManager.outDir = self.outDir
if unicode(self.ui.lineEdit.text()) and os.path.exists(unicode(self.ui.lineEdit.text())):
self.threadManager.cacheFile = unicode(self.ui.lineEdit.text())
if self.ui.checkBox_4.checkState() == QtCore.Qt.Checked:
self.threadManager.runAfterComplete = True
checked = 0 # Колличество выбранныз отчетов.
if self.ui.checkBox_2.checkState() == QtCore.Qt.Checked:
self.threadManager.report.append("all_day")
checked += 1
if self.ui.checkBox.checkState() == QtCore.Qt.Checked:
self.threadManager.report.append("cam_in_day")
checked += 1
if self.ui.checkBox_3.checkState() == QtCore.Qt.Checked:
self.threadManager.report.append("cam_in_hour")
checked += 1
if not checked:
ksqt.message(self, "warning", u"Внимание...", u"Необходимо выбрать хотя бы один отчёт.")
else:
self.threadManager.start()
self.isProcess = True
def finishProcess(self):
"""
Слот для окончания работы потока основного процесса.
"""
self.progress(100)
if self.threadManager.error:
self.addLogError(u"<b>%s</b>" % self.threadManager.errorMessage)
ksqt.message(self, "error", u"Ошибка...", u"В процессе работы программы произошли ошибки:<br>%s" % self.threadManager.errorMessage)
else:
if not self.threadManager.normalExit:
self.addLogError(u"<b>Некорректное завершение работы программы.</b>")
else:
self.addLogOk(u"<b>Выполнено!</b>")
self.formDisabled(False)
self.isProcess = False
def errorMsg(self, message):
"""
Формирование отчёта об ошибке.
"""
if isinstance(message, list) or isinstance(message, tuple):
logging.debug("ERROR: %s" % "; ".join(message))
message = u"<ul><li>%s</li></ul>" % u"</li><li>".join(message)
else:
logging.debug("ERROR: %s" % message)
message = u"<ul><li>%s</li></ul>" % message
ksqt.message(self, "error", u"Ошибка...", u"В процессе работы программы произошли ошибки:%s" % message)
def errorMsgCritical(self, message):
"""
Формирование отчёта об ошибке и выход из программы.
"""
if isinstance(message, list) or isinstance(message, tuple):
logging.debug("CRITICAL: %s" % "; ".join(message))
message = u"<ul><li>%s</li></ul>" % u"</li><li>".join(message)
else:
logging.debug("CRITICAL: %s" % message)
message = u"<ul><li>%s</li></ul>" % message
ksqt.message(self, "error", u"Ошибка...", u"В процессе работы программы произошли ошибки:%s<b>Работа программы остановлена!</b>" % message)
sys.exit(1)
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG, format=u'%(filename)s[LINE:%(lineno)d]# %(levelname)-8s [%(asctime)s] %(message)s')
logging.debug(u"****** Начало новой сессии ******")
app = QtGui.QApplication(sys.argv)
myapp = main()
myapp.show()
try:
sys.exit(app.exec_())
except SystemExit:
pass