pymuleparser/pyMuleAnalyzerQT.py

246 lines
8.6 KiB
Python
Raw Normal View History

2017-10-24 08:53:13 +02:00
#! /usr/bin/env python3
2017-10-28 20:12:53 +02:00
"""
"""
2017-10-24 08:53:13 +02:00
import sys
2017-10-31 12:37:12 +01:00
import os
import traceback
import time
import random
2017-10-28 20:12:53 +02:00
import PyQt5
2017-10-31 12:37:12 +01:00
from PyQt5.QtCore import Qt, QDateTime, QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool
2017-10-28 20:12:53 +02:00
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QAbstractItemView, \
QTableWidgetItem, QSplashScreen, QProgressBar
2017-10-31 12:37:12 +01:00
from PyQt5.QtGui import QStandardItemModel, QPixmap, QMovie, QPainter
2017-10-24 08:53:13 +02:00
from MuleAnalyzerUI import Ui_MainWindow
from ED2K import load_knownfiles
from HashDatabase import load_hashsets
class ExceptionHandler(QObject):
errorSignal = pyqtSignal()
def __init__(self):
super(ExceptionHandler, self).__init__()
def handler(self, exctype, value, traceback):
self.errorSignal.emit()
sys._excepthook(exctype, value, traceback)
exceptionHandler = ExceptionHandler()
sys._excepthook = sys.excepthook
sys.excepthook = exceptionHandler.handler
2017-10-24 08:53:13 +02:00
2017-10-31 12:37:12 +01:00
class MovieSplashScreen(QSplashScreen):
def __init__(self, movie, parent=None):
movie.jumpToFrame(0)
pixmap = QPixmap(movie.frameRect().size())
QSplashScreen.__init__(self, pixmap, Qt.WindowStaysOnTopHint)
self.movie = movie
self.movie.frameChanged.connect(self.repaint)
def showEvent(self, event):
self.movie.start()
def hideEvent(self, event):
self.movie.stop()
def paintEvent(self, event):
painter = QPainter(self)
pixmap = self.movie.currentPixmap()
self.setMask(pixmap.mask())
painter.drawPixmap(0, 0, pixmap)
def sizeHint(self):
return self.movie.scaledSize()
class WorkerSignals(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(str)
class Worker(QRunnable):
def __init__(self, fn, *args, **kwargs):
QRunnable.__init__(self)
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
kwargs['progress_callback'] = self.signals.progress
@pyqtSlot()
def run(self):
# Retrieve args/kwargs here; and fire processing using them
try:
result = self.fn(*self.args, **self.kwargs)
except:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit()
2017-10-24 08:53:13 +02:00
class MainWindow(QMainWindow, Ui_MainWindow):
2017-10-26 08:48:42 +02:00
# Todo: Replace TreeHeaders
Headers = (
('ID', None, None, 0, Qt.AlignRight),
('Filename', 'FT_FILENAME', str, '', Qt.AlignLeft),
('ED2K Hash', 'ED2KHASH', str, '', Qt.AlignLeft),
('Hashset', None, None, '', Qt.AlignLeft),
2017-10-28 18:24:09 +02:00
('Last Changed', 'LASTCHANGED', QDateTime, 'Never', Qt.AlignLeft),
2017-10-26 08:48:42 +02:00
('Filesize', 'FT_FILESIZE', int, 0, Qt.AlignRight),
('Transfered', 'FT_ATTRANSFERRED', int, 0, Qt.AlignRight),
('Transfered (HI)', 'FT_ATTRANSFERREDHI', int, 0, Qt.AlignRight),
('Requested', 'FT_ATREQUESTED', int, 0, Qt.AlignRight),
('Accepted', 'FT_ATACCEPTED', int, 0, Qt.AlignRight),
('AICHashes', 'FT_AICHHASHSET', str, '', Qt.AlignLeft),
('AICHash', 'FT_AICH_HASH', str, '', Qt.AlignLeft),
('Part Filename', 'FT_PARTFILENAME', str, '', Qt.AlignLeft),
('Number of Parts', 'NUMPARTS', int, 0, Qt.AlignRight),
('Parts Hash', 'PARTHASHES', list, '', Qt.AlignLeft),
)
2017-10-24 08:53:13 +02:00
2017-10-31 12:37:12 +01:00
def __init__(self, *args, **kwargs):
2017-10-24 08:53:13 +02:00
super(MainWindow, self).__init__()
self.setupUi(self)
self.treeModel = self.createED2KModel(self)
self.treeView.setModel(self.treeModel)
self.treeView.setRootIsDecorated(False)
self.treeView.setAlternatingRowColors(True)
2017-10-26 08:48:42 +02:00
self.treeView.setSortingEnabled(True)
self.treeView.setEditTriggers(QAbstractItemView.NoEditTriggers)
#self.treeView.setSelectionMode(QAbstractItemView.MultiSelection)
2017-10-24 08:53:13 +02:00
2017-10-26 08:48:42 +02:00
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.actionFile_open.setShortcut('Ctrl+O')
self.actionFile_open.triggered.connect(self.slot_load_met_file)
self.actionExit.triggered.connect(self.close)
2017-10-24 08:53:13 +02:00
2017-10-31 12:37:12 +01:00
self.threadpool = QThreadPool()
self.hashsets = None
self.splash_screen = kwargs['splash_screen']
worker = Worker(self.load_hashsets)
worker.signals.result.connect(self.cb_got_hashset)
worker.signals.progress.connect(self.cb_progress)
self.threadpool.start(worker)
def cb_progress(self, msg):
self.splash_screen.showMessage('<h1>%s</h1>' % msg, Qt.AlignTop | Qt.AlignCenter, Qt.black)
def load_hashsets(self, progress_callback, folder='Hashsets'):
self.hashsets = load_hashsets(folder, progress_callback)
return self.hashsets
2017-10-28 20:12:53 +02:00
def cb_print_msg(self, message):
print('>>>', message)
2017-10-26 12:43:18 +02:00
2017-10-31 12:37:12 +01:00
def cb_got_hashset(self, hashes):
num_hashsets = len(hashes.keys())
num_hashes = 0
for key in hashes:
num_hashes += len(hashes[key])
self.statusBar.showMessage('Loaded {} hashsets with {:,} hashes.'.format(num_hashsets,
num_hashes))
2017-10-24 08:53:13 +02:00
def createED2KModel(self, parent):
2017-10-26 08:48:42 +02:00
model = QStandardItemModel(0, len(self.Headers), parent)
for i, fields in enumerate(self.Headers):
model.setHeaderData(i, Qt.Horizontal, fields[0])
2017-10-24 08:53:13 +02:00
return model
def addED2K(self, model, metinfo):
model.insertRow(0)
2017-10-26 08:48:42 +02:00
for i, field in enumerate(self.Headers):
2017-10-26 12:43:18 +02:00
if field[2] == None:
2017-10-26 08:48:42 +02:00
if i == 0:
root = self.treeModel.invisibleRootItem()
row_count = root.rowCount()
model.setData(model.index(0, i), row_count+1)
if i == 3:
2017-10-26 12:43:18 +02:00
found_in = []
for hashset, hashes in self.hashsets.items():
if metinfo.ED2KHASH.upper() in hashes or metinfo.ED2KHASH.lower() in hashes:
2017-10-26 12:43:18 +02:00
found_in.append(hashset)
break
2017-10-26 08:48:42 +02:00
# TODO Hash lookup
2017-10-26 12:43:18 +02:00
model.setData(model.index(0, i), ', '.join(found_in))
2017-10-26 08:48:42 +02:00
else:
value = getattr(metinfo, field[1]) or field[3]
if field[2] is QDateTime:
last_changed = QDateTime.fromSecsSinceEpoch(value, 0)
model.setData(model.index(0, i), last_changed.toString('dd.MM.yyyy hh:mm:ss'))
elif field[2] is int:
model.setData(model.index(0, i), '{0:,}'.format(value))
elif field[2] is list:
model.setData(model.index(0, i), ''.join(value))
else:
model.setData(model.index(0, i), value)
model.item(0, i).setTextAlignment(field[4])
2017-10-24 08:53:13 +02:00
def loadMetFile(self, filename):
2017-10-26 08:48:42 +02:00
for met_entry in load_knownfiles(filename):
2017-10-24 08:53:13 +02:00
self.addED2K(self.treeModel, met_entry)
2017-10-31 12:37:12 +01:00
@pyqtSlot()
2017-10-26 08:48:42 +02:00
def slot_load_met_file(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
2017-10-31 12:37:12 +01:00
files, _ = QFileDialog.getOpenFileNames(self, 'Open .met files...', '',
'MET Files (*.met);;All Files (*)',
2017-10-26 08:48:42 +02:00
options=options)
for filename in files:
self.loadMetFile(filename)
root = self.treeModel.invisibleRootItem()
row_count = root.rowCount()
transfered = 0
for i in range(row_count):
2017-10-28 18:24:09 +02:00
row = self.treeModel.item(i, column=5)
2017-10-26 08:48:42 +02:00
transfered += int(row.text().replace(',', ''))
self.tableWidget.setRowCount(1)
self.tableWidget.setColumnCount(2)
self.tableWidget.setItem(0, 0, QTableWidgetItem('Transfered overall:'))
self.tableWidget.setItem(0, 1, QTableWidgetItem(str('{0:,}'.format(transfered))))
2017-10-24 08:53:13 +02:00
def main(argv):
app = QApplication(argv)
2017-10-27 14:27:02 +02:00
2017-10-31 12:37:12 +01:00
resources = './resources/loaders/'
movies = []
for filename in os.listdir(resources):
filepath = os.path.join(resources, filename)
if os.path.isfile(filepath):
movies.append(filepath)
movie = QMovie(random.choice(movies))
splash_screen = MovieSplashScreen(movie)
splash_screen.setEnabled(False)
2017-10-27 14:27:02 +02:00
splash_screen.show()
2017-10-31 12:37:12 +01:00
window = MainWindow(splash_screen=splash_screen)
while not window.hashsets:
app.processEvents()
2017-10-24 08:53:13 +02:00
window.show()
2017-10-27 14:27:02 +02:00
splash_screen.finish(window)
2017-10-24 08:53:13 +02:00
sys.exit(app.exec_())
if __name__ == '__main__':
2017-10-28 18:26:20 +02:00
main(sys.argv)