class CountdownWidget(QWidget): """Define custom widget as countdown control panel.""" def __init__(self, ctrl, parent=None): """Init completer.""" super().__init__(parent) self.controller = ctrl self.createLayout() self.loadSettings() self.connect() def createLayout(self): """Create widget to control the countdown browser source.""" layout = QGridLayout() self.rb_static = QRadioButton(_("Static Countdown to date:"), self) layout.addWidget(self.rb_static, 0, 0) self.rb_dynamic = QRadioButton(_("Dynamic Countdown duration:"), self) self.rb_dynamic.setChecked(True) self.rb_dynamic.toggled.connect(self.toggleRadio) layout.addWidget(self.rb_dynamic, 1, 0) self.te_datetime = QDateTimeEdit() self.te_datetime.setCalendarPopup(True) self.te_datetime.setContextMenuPolicy(Qt.CustomContextMenu) self.te_datetime.customContextMenuRequested.connect( self.openDateTimeMenu) layout.addWidget(self.te_datetime, 0, 1) self.te_duration = QTimeEdit() self.te_duration.setDisplayFormat("HH 'h' mm 'm' ss 's'") self.te_duration.setContextMenuPolicy(Qt.CustomContextMenu) self.te_duration.customContextMenuRequested.connect( self.openDurationMenu) layout.addWidget(self.te_duration, 1, 1) self.event_label = QLabel(' ' + _('Event description:')) layout.addWidget(self.event_label, 0, 2) self.le_desc = QLineEdit() self.le_desc.setAlignment(Qt.AlignCenter) layout.addWidget(self.le_desc, 0, 3, 1, 2) self.cb_restart = QCheckBox( _('Restart countdown when source becomes active')) layout.addWidget(self.cb_restart, 1, 2, 1, 2) self.pb_start = QPushButton(" " + _('Start Countdown') + " ") layout.addWidget(self.pb_start, 1, 4) layout.setColumnStretch(2, 1) layout.setColumnStretch(3, 2) self.setLayout(layout) def openDateTimeMenu(self, position): """Open menu to set date to today.""" menu = QMenu() act1 = QAction(_("Set Today")) act1.triggered.connect(self.setToday) menu.addAction(act1) menu.exec_(QCursor.pos()) def openDurationMenu(self, position): """Open menu to set the duration.""" menu = QMenu() for duration in [15, 10, 5, 3, 1]: act = QAction(_("Set {} min").format(duration), menu) act.triggered.connect( lambda x, duration=duration: self.setDuration(duration)) menu.addAction(act) menu.exec_(QCursor.pos()) def setToday(self): """Set date to today.""" today = QDateTime.currentDateTime() today.setTime(self.te_datetime.time()) self.te_datetime.setDateTime(today) def setFromTimestamp(self, timestamp): """Set time and date based on timestamp.""" self.te_datetime.setDateTime(QDateTime.fromTime_t(int(timestamp))) def setDuration(self, duration): """Set the duration.""" self.te_duration.setTime(QTime(0, duration, 0)) def toggleRadio(self): """Toggle radio buttion.""" static = self.rb_static.isChecked() self.te_datetime.setEnabled(static) self.te_duration.setEnabled(not static) self.cb_restart.setEnabled(not static) self.pb_start.setEnabled(not static) def loadSettings(self): """Load data from settings.""" static = scctool.settings.config.parser.getboolean( "Countdown", "static") if static: self.rb_static.setChecked(True) else: self.rb_dynamic.setChecked(True) description = scctool.settings.config.parser.get( 'Countdown', 'description') self.le_desc.setText(description.strip()) restart = scctool.settings.config.parser.getboolean( "Countdown", "restart") self.cb_restart.setChecked(restart) duration = QTime() string = scctool.settings.config.parser.get('Countdown', 'duration').strip() duration = QTime.fromString(string, 'HH:mm:ss') self.te_duration.setTime(duration) string = scctool.settings.config.parser.get('Countdown', 'datetime').strip() datetime = QDateTime.fromString(string, 'yyyy-MM-dd HH:mm') self.te_datetime.setDateTime(datetime) def connect(self): """Connect all form elements.""" self.le_desc.textChanged.connect(self.changed_description) self.cb_restart.toggled.connect(self.changed_restart) self.te_datetime.dateTimeChanged.connect(self.changed_datetime) self.te_duration.timeChanged.connect(self.changed_duration) self.rb_static.toggled.connect(self.changed_static) self.pb_start.pressed.connect(self.start_pressed) def changed_description(self): """Change the description.""" desc = self.le_desc.text().strip() scctool.settings.config.parser.set('Countdown', 'description', desc) self.controller.websocketThread.sendData2Path('countdown', "DESC", desc) def changed_restart(self): """Handle change of restart option.""" restart = self.cb_restart.isChecked() scctool.settings.config.parser.set('Countdown', 'restart', str(restart)) self.controller.websocketThread.sendData2Path('countdown', "RESTART", restart) def changed_datetime(self, time): """Handle change of datetime.""" datetime = time.toString('yyyy-MM-dd HH:mm') scctool.settings.config.parser.set('Countdown', 'datetime', datetime) self.sendData() def changed_duration(self, time): """Handle change of duration.""" duration = time.toString('HH:mm:ss') scctool.settings.config.parser.set('Countdown', 'duration', duration) self.sendData() def changed_static(self): """Handle change of static/dynamic.""" static = self.rb_static.isChecked() scctool.settings.config.parser.set('Countdown', 'static', str(static)) self.sendData() def start_pressed(self): """Handle press of the start button.""" self.controller.websocketThread.sendData2Path('countdown', 'START') def sendData(self): """Send the data to the websocket.""" self.controller.websocketThread.sendData2Path( 'countdown', "DATA", self.controller.websocketThread.getCountdownData())
class Ui_MainWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.transprot_mass =[] self.netprot_mass =[] self.filtering_is_on = 0 grid = QGridLayout() self.setLayout(grid) self.IP_list = IP_list(self) self.TransProt_list = TransProt_list(self) self.NetProt_list = NetProt_list(self) self.setWindowTitle('Гамма') self.setWindowIcon(QIcon('допочки\Gamma_200x200.png')) self.resize(740, 830) self.to_center() self.centralwidget = QWidget(self) self.tabWidget = QTabWidget(self.centralwidget) self.tabWidget.setGeometry(QRect(20, 20, 700, 750)) self.tab = QWidget() grid.addWidget(self.tab) self.cb_time = QCheckBox(self.tab) self.cb_time.setGeometry(QRect(360, 130, 120, 20)) self.cb_time.setText("Фильтр по времени") self.cb_prot = QCheckBox(self.tab) self.cb_prot.setGeometry(QRect(20, 130, 140, 20)) self.cb_prot.setText("Фильтр по протоколам") self.cb_addr = QCheckBox(self.tab) self.cb_addr.setGeometry(QRect(360, 290, 130, 20)) self.cb_addr.setText("Фильтр по IP-адресам") self.dt_beg = QDateTimeEdit(self.tab) self.dt_beg.setGeometry(QRect(360, 210, 150, 20)) self.dt_beg.setDateTime(QDateTime.currentDateTime()) self.dt_beg.setDisplayFormat("dd.MM.yyyy H:mm:ss.zzz") self.dt_beg.setCalendarPopup(True) self.dt_beg.setToolTip('Выбрать начальное время (>=)') self.dt_beg.setEnabled(False) self.dt_end = QDateTimeEdit(self.tab) self.dt_end.setGeometry(QRect(520, 210, 150, 20)) self.dt_end.setDateTime(QDateTime.currentDateTime()) self.dt_end.setDisplayFormat("dd.MM.yyyy H:mm:ss.zzz") self.dt_end.setCalendarPopup(True) self.dt_end.setToolTip('Выбрать конечное время (<)') self.dt_end.setEnabled(False) self.dt_beg.dateChanged.connect(lambda dc: self.date_changed(1)) self.dt_end.dateChanged.connect(lambda dc: self.date_changed(2)) #self.l_input_dir = QLabel(self.tab) #self.l_input_dir.setGeometry(QRect(102, 50, 180, 15)) #self.l_input_dir.setText("Выберите директорию с файлами") #self.l_or = QLabel(self.tab) #self.l_or.setGeometry(QRect(340, 50, 21, 16)) #self.l_or.setText("ИЛИ") self.l_input_file = QLabel(self.tab) self.l_input_file.setGeometry(QRect(300, 50, 90, 15)) self.l_input_file.setText("Выберите файлы") self.l_transpr = QLabel(self.tab) self.l_transpr.setGeometry(QRect(50, 190, 180, 16)) self.l_transpr.setEnabled(False) self.l_transpr.setText("Протоколы Транспортного уровня") self.l_netpr = QLabel(self.tab) self.l_netpr.setGeometry(QRect(50, 290, 180, 16)) self.l_netpr.setEnabled(False) self.l_netpr.setText("Протоколы Сетевого уровня") self.l_beg = QLabel(self.tab) self.l_beg.setGeometry(QRect(390, 190, 60, 16)) self.l_beg.setEnabled(False) self.l_beg.setText("Начиная с..") self.l_end = QLabel(self.tab) self.l_end.setGeometry(QRect(560, 190, 80, 16)) self.l_end.setEnabled(False) self.l_end.setText("Оканчивая до..") self.l_name = QLabel(self.tab) self.l_name.setGeometry(QRect(300, 450, 96, 16)) self.l_name.setText("Как назвать файл?") self.l_filt = QLabel(self.tab) self.l_filt.setGeometry(QRect(300, 10, 91, 16)) self.l_filt.setText("Выборка пакетов") self.line = QFrame(self.tab) self.line.setGeometry(QRect(0, 110, 690, 15)) self.line.setFrameShape(QFrame.HLine) self.line.setFrameShadow(QFrame.Sunken) self.line_2 = QFrame(self.tab) self.line_2.setGeometry(QRect(340, 120, 15, 300)) self.line_2.setFrameShape(QFrame.VLine) self.line_2.setFrameShadow(QFrame.Sunken) self.line_3 = QFrame(self.tab) self.line_3.setGeometry(QRect(0, 420, 690, 15)) self.line_3.setFrameShape(QFrame.HLine) self.line_3.setFrameShadow(QFrame.Sunken) #self.le_dir = QLineEdit(self.tab) #self.le_dir.setGeometry(QRect(110, 80, 211, 20)) #self.le_dir.setEnabled(False) #self.le_dir.setReadOnly(True) self.le_file = QLineEdit(self.tab) self.le_file.setGeometry(QRect(250, 80, 211, 20)) #self.le_file.setEnabled(False) self.le_file.setReadOnly(True) self.le_name = QLineEdit(self.tab) self.le_name.setGeometry(QRect(250, 480, 231, 20)) self.pt_transpr = QPlainTextEdit(self.tab) self.pt_transpr.setGeometry(QRect(50, 210, 271, 71)) self.pt_transpr.setEnabled(False) self.pt_transpr.setReadOnly(True) self.pt_netpr = QPlainTextEdit(self.tab) self.pt_netpr.setGeometry(QRect(50, 320, 271, 71)) self.pt_netpr.setEnabled(False) self.pt_netpr.setReadOnly(True) self.pt_addr = QPlainTextEdit(self.tab) self.pt_addr.setGeometry(QRect(390, 320, 271, 71)) self.pt_addr.setEnabled(False) self.pt_log = QPlainTextEdit(self.tab) self.pt_log.setGeometry(QRect(20, 610, 651, 101)) self.pt_log.setReadOnly(True) self.progressBar = QProgressBar(self.tab) self.progressBar.setGeometry(QRect(20, 580, 651, 20)) self.progressBar.setFormat("%v" + "%") self.progressBar.setMaximum(100) self.progressBar.setValue(0) #self.pb_dir = QPushButton(self.tab) #self.pb_dir.setGeometry(QRect(80, 80, 21, 20)) #self.pb_dir.setIcon(QIcon('допочки\_folder.png')) #self.pb_dir.clicked.connect(lambda gd: self.get_directory(1)) self.pb_file = QPushButton(self.tab) self.pb_file.setGeometry(QRect(220, 80, 21, 20)) self.pb_file.setIcon(QIcon('допочки\_folder.png')) self.pb_file.clicked.connect(lambda gf: self.get_files(1)) self.pb_time = QPushButton(self.tab) self.pb_time.setGeometry(QRect(480, 240, 71, 20)) self.pb_time.setToolTip('Добавить ещё временной отрезок') self.pb_time.setEnabled(False) self.pb_time.setText("Ещё!") self.pb_transpr = QPushButton(self.tab) self.pb_transpr.setGeometry(QRect(20, 210, 21, 20)) self.pb_transpr.setToolTip('Выбрать протоколы Транспортного уровня') self.pb_transpr.setIcon(QIcon('допочки\_blank.png')) self.pb_transpr.setEnabled(False) self.pb_transpr.clicked.connect(self.TransProt_list.exec) self.pb_netpr = QPushButton(self.tab) self.pb_netpr.setGeometry(QRect(20, 320, 21, 20)) self.pb_netpr.setToolTip('Выбрать протоколы Сетевого уровня') self.pb_netpr.setIcon(QIcon('допочки\_blank.png')) self.pb_netpr.setEnabled(False) self.pb_netpr.clicked.connect(self.NetProt_list.exec) self.pb_addr = QPushButton(self.tab) self.pb_addr.setGeometry(QRect(530, 290, 132, 20)) self.pb_addr.setText('Редактировать список') self.pb_addr.setEnabled(False) self.pb_addr.clicked.connect(self.IP_list.exec) self.pb_name = QPushButton(self.tab) self.pb_name.setGeometry(QRect(220, 480, 21, 20)) self.pb_name.setIcon(QIcon('допочки\_folder.png')) self.pb_name.clicked.connect(lambda ed: self.extract_to_directory(1)) self.pb_start = QPushButton(self.tab) self.pb_start.setGeometry(QRect(220, 510, 261, 41)) self.pb_start.setText("Начать выборку") self.pb_start.clicked.connect(self.do_it_motherFucker) #self.radiobutton = QRadioButton(self.tab) #self.radiobutton.setGeometry(QRect(84, 48, 20, 20)) #self.radiobutton_2 = QRadioButton(self.tab) #self.radiobutton_2.setGeometry(QRect(424, 48, 20, 20)) #self.radiobutton.raise_() #self.radiobutton_2.raise_() self.cb_time.raise_() self.cb_prot.raise_() self.cb_addr.raise_() self.dt_beg.raise_() self.dt_end.raise_() #self.l_input_dir.raise_() #self.l_or.raise_() self.l_input_file.raise_() self.l_transpr.raise_() self.l_netpr.raise_() self.l_beg.raise_() self.l_end.raise_() self.l_name.raise_() self.l_filt.raise_() self.line.raise_() self.line_2.raise_() self.line_3.raise_() #self.le_dir.raise_() self.le_file.raise_() self.le_name.raise_() self.pt_transpr.raise_() self.pt_netpr.raise_() self.pt_addr.raise_() self.pt_log.raise_() self.progressBar.raise_() #self.pb_dir.raise_() self.pb_file.raise_() self.pb_time.raise_() self.pb_transpr.raise_() self.pb_netpr.raise_() self.pb_addr.raise_() self.pb_name.raise_() self.pb_start.raise_() self.setCentralWidget(self.centralwidget) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.tabWidget.addTab(self.tab, "") self.cb_time.clicked['bool'].connect(self.dt_beg.setEnabled) self.cb_time.clicked['bool'].connect(self.dt_end.setEnabled) self.cb_time.clicked['bool'].connect(self.l_beg.setEnabled) self.cb_time.clicked['bool'].connect(self.l_end.setEnabled) self.cb_prot.clicked['bool'].connect(self.l_transpr.setEnabled) self.cb_prot.clicked['bool'].connect(self.l_netpr.setEnabled) self.cb_prot.clicked['bool'].connect(self.pt_transpr.setEnabled) self.cb_prot.clicked['bool'].connect(self.pt_netpr.setEnabled) self.cb_prot.clicked['bool'].connect(self.pb_transpr.setEnabled) self.cb_prot.clicked['bool'].connect(self.pb_netpr.setEnabled) self.cb_addr.clicked['bool'].connect(self.pt_addr.setEnabled) self.cb_addr.clicked['bool'].connect(self.pb_addr.setEnabled) #####------------------------------2_TAB self.tab_2 = QWidget() self.tabWidget.addTab(self.tab_2, "") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), ("II работа с файлами")) self.l_merge = QLabel(self.tab_2) self.l_merge.setGeometry(QRect(300, 10, 180, 16)) self.l_merge.setText("Объединение файлов") self.l_arch = QLabel(self.tab_2) self.l_arch.setGeometry(QRect(300, 250, 180, 16)) self.l_arch.setText("Архивирование файлов") #self.radiobutton_3 = QRadioButton(self.tab_2) #self.radiobutton_3.setGeometry(QRect(84, 48, 20, 20)) #self.radiobutton_4 = QRadioButton(self.tab_2) #self.radiobutton_4.setGeometry(QRect(424, 48, 20, 20)) #self.l_input_dir2 = QLabel(self.tab_2) #self.l_input_dir2.setGeometry(QRect(102, 50, 180, 15)) #self.l_input_dir2.setText("Выберите директорию с файлами") #self.l_or2 = QLabel(self.tab_2) #self.l_or2.setGeometry(QRect(340, 50, 21, 16)) #self.l_or2.setText("ИЛИ") self.l_input_file2 = QLabel(self.tab_2) self.l_input_file2.setGeometry(QRect(102, 50, 180, 15))#442, 50, 90, 15)) self.l_input_file2.setText("Выберите файлы") self.l_name2 = QLabel(self.tab_2) self.l_name2.setGeometry(QRect(442, 50, 180, 15))#280, 140, 180, 16)) self.l_name2.setText("Куда сохранить результат?") self.l_ciph2 = QLabel(self.tab_2) self.l_ciph2.setGeometry(QRect(84, 298, 180, 15)) self.l_ciph2.setText("Убрать шифрованный трафик") self.l_arch2 = QLabel(self.tab_2) self.l_arch2.setGeometry(QRect(424, 298, 180, 15)) self.l_arch2.setText("Заархивировать файлы") #self.le_dir2 = QLineEdit(self.tab_2) #self.le_dir2.setGeometry(QRect(110, 80, 211, 20)) #self.le_dir2.setEnabled(False) self.le_file2 = QLineEdit(self.tab_2) self.le_file2.setGeometry(QRect(110, 80, 211, 20))#450, 80, 211, 20)) self.le_file2.setReadOnly(True) self.le_name2 = QLineEdit(self.tab_2) self.le_name2.setGeometry(QRect(450, 80, 211, 20))#260, 170, 180, 20)) #self.pb_dir2 = QPushButton(self.tab_2) #self.pb_dir2.setGeometry(QRect(80, 80, 21, 20)) #self.pb_dir2.setIcon(QIcon('допочки\_folder.png')) #self.pb_dir2.clicked.connect(lambda gd: self.get_directory(2)) self.pb_file2 = QPushButton(self.tab_2) self.pb_file2.setGeometry(QRect(80, 80, 21, 20))#420, 80, 21, 20)) self.pb_file2.setIcon(QIcon('допочки\_folder.png')) self.pb_file2.clicked.connect(lambda gf: self.get_files(2)) self.pb_name2 = QPushButton(self.tab_2) self.pb_name2.setGeometry(QRect(420, 80, 21, 20))#230, 170, 21, 20)) self.pb_name2.setIcon(QIcon('допочки\_folder.png')) self.pb_name2.clicked.connect(lambda ed: self.extract_to_directory(2)) self.pb_merge = QPushButton(self.tab_2) self.pb_merge.setGeometry(QRect(270, 170, 160, 20)) self.pb_merge.setText("Объединить") self.pb_merge.clicked.connect(self.merge_it_motherFucker) self.line_4 = QFrame(self.tab_2) self.line_4.setGeometry(QRect(0, 280, 690, 15)) self.line_4.setFrameShape(QFrame.HLine) self.line_4.setFrameShadow(QFrame.Sunken) self.line_5 = QFrame(self.tab_2) self.line_5.setGeometry(QRect(0, 580, 690, 15)) self.line_5.setFrameShape(QFrame.HLine) self.line_5.setFrameShadow(QFrame.Sunken) self.pt_log2 = QPlainTextEdit(self.tab_2) self.pt_log2.setGeometry(QRect(20, 610, 651, 101)) self.pt_log2.setReadOnly(True) self.graphicsView = QGraphicsView(self.tab_2) self.graphicsView.setGeometry(QRect(0, 330, 714, 277)) self.scene = QGraphicsScene() self.graphicsView.setScene(self.scene) self.scene.addPixmap(QPixmap('допочки\_in_working_3.png')) self.l_merge.raise_() self.l_arch.raise_() #self.l_input_dir2.raise_() #self.l_or2.raise_() self.l_input_file2.raise_() self.l_name2.raise_() #self.radiobutton_3.raise_() #self.radiobutton_4.raise_() #self.pb_dir2.raise_() self.pb_file2.raise_() self.pb_name2.raise_() #self.le_dir2.raise_() self.le_file2.raise_() self.le_name2.raise_() self.line_4.raise_() self.line_5.raise_() self.pt_log2.raise_() #####------------------------------2_TAB #####------------------------------3_TAB self.tab_3 = QWidget() self.tabWidget.addTab(self.tab_3, "") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), ("III Проверка на аномальную активность")) self.tab_3.setEnabled(False) self.l_filt3 = QLabel(self.tab_3) self.l_filt3.setGeometry(QRect(300, 10, 91, 16)) self.l_filt3.setText("Выборка пакетов") self.l_input_file3 = QLabel(self.tab_3) self.l_input_file3.setGeometry(QRect(300, 50, 90, 15)) self.l_input_file3.setText("Выберите файлы") self.pb_file3 = QPushButton(self.tab_3) self.pb_file3.setGeometry(QRect(220, 80, 21, 20)) self.pb_file3.setIcon(QIcon('допочки\_folder.png')) self.pb_file3.clicked.connect(lambda gf: self.get_files(3)) self.le_file3 = QLineEdit(self.tab_3) self.le_file3.setGeometry(QRect(250, 80, 211, 20)) self.le_file3.setReadOnly(True) self.pb_graphy = QPushButton(self.tab_3) self.pb_graphy.setGeometry(QRect(270, 170, 160, 20)) self.pb_graphy.setText("Построить граф") #self.pb_graphy.clicked.connect(self.graph_it) #self.label_6 = QLabel(self.tab_3) #self.pixmap = QPixmap('допочки\_in_working_1.png') #self.label_6.setPixmap(self.pixmap) self.l_filt3.raise_() self.l_input_file3.raise_() self.pb_file3.raise_() self.le_file3.raise_() #####------------------------------3_TAB #####----------------------------IN_WORK self.tab_4 = QWidget() self.tabWidget.addTab(self.tab_4, "") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), ("...IV visualization...")) self.tab_4.setEnabled(False) self.label_7 = QLabel(self.tab_4) self.pixmap_2 = QPixmap('допочки\_in_working_2.png') self.label_7.setPixmap(self.pixmap_2) #####----------------------------IN_WORK self.tabWidget.setCurrentIndex(0) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), ("I выборка пакетов")) QMetaObject.connectSlotsByName(self) self.show() def closeEvent(self, event): reply = QMessageBox.question(self, 'Ща закроется всё', "Ты чо, реально хочешь выйти?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() def to_center(self): qr = self.frameGeometry() qr.moveCenter(QDesktopWidget().availableGeometry().center()) self.move(qr.topLeft()) def get_directory(self, gd): if gd == 1: result = QFileDialog.getExistingDirectory() #self.le_dir.setText(result) self.le_file.setDisabled(True) #self.le_dir.setEnabled(True) #self.radiobutton_2.setChecked(False) #self.radiobutton.setChecked(True) else: result = QFileDialog.getExistingDirectory() #self.le_dir2.setText(result) self.le_file2.setDisabled(True) #self.le_dir2.setEnabled(True) #self.radiobutton_4.setChecked(False) #self.radiobutton_3.setChecked(True) def get_files(self, gf): if gf == 1: result, bullshit = QFileDialog.getOpenFileNames(self, "Выберите pcap-файлы", getcwd(), "files (*.pcap *.pcapng)") #self.le_dir.setDisabled(True) self.le_file.setEnabled(True) #self.radiobutton.setChecked(False) #self.radiobutton_2.setChecked(True) if len(result): self.le_file.setText(", ".join(result)) elif gf == 3: result, bullshit = QFileDialog.getOpenFileNames(self, "Выберите pcap-файлы", getcwd(), "files (*.pcap *.pcapng)") #self.le_dir.setDisabled(True) self.le_file3.setEnabled(True) #self.radiobutton.setChecked(False) #self.radiobutton_2.setChecked(True) if len(result): self.le_file3.setText(", ".join(result)) else: result, bullshit = QFileDialog.getOpenFileNames(self, "Выберите pcap-файлы", getcwd(), "files (*.pcap *.pcapng)") #self.le_dir2.setDisabled(True) self.le_file2.setEnabled(True) #self.radiobutton_3.setChecked(False) #self.radiobutton_4.setChecked(True) if len(result): self.le_file2.setText(", ".join(result)) def date_changed(self, dc): if dc == 1: self.dt_end.setMinimumDateTime(QDateTime(self.dt_beg.dateTime())) else: self.dt_beg.setMaximumDateTime(QDateTime(self.dt_end.dateTime())) def extract_to_directory(self, ed): if ed == 1: result, bullshit =QFileDialog.getSaveFileName(self, "Сохранить файл", getcwd(), "files (*.pcap *.pcapng)") self.le_name.setText(result) else: result, bullshit =QFileDialog.getSaveFileName(self, "Сохранить файл", getcwd(), "files (*.pcap *.pcapng)") self.le_name2.setText(result) def do_it_motherFucker(self): if self.filtering_is_on == 0: #if ((not self.radiobutton.isChecked() and not self.radiobutton_2.isChecked())\ # or (self.radiobutton.isChecked() and self.le_dir.text() == '')\ # or (self.radiobutton_2.isChecked() and self.le_file.text() == ''))\ # and self.le_name.text() == '': if self.le_file.text() == '' and self.le_name.text() == '': self.pt_log.appendPlainText(" " + "Какие файлы обработать? Куда сохранить? Такая неопределённость..") #elif (not self.radiobutton.isChecked() and not self.radiobutton_2.isChecked()) or (self.radiobutton.isChecked() and self.le_dir.text() == '') or (self.radiobutton_2.isChecked() and self.le_file.text() == ''): elif self.le_file.text() == '': self.pt_log.appendPlainText(" " + "Какие файлы обработать?") elif self.le_name.text() == '': self.pt_log.appendPlainText(" " + "Куда сохранить?") else: self.filtering_is_on = 1 # эти пиздецы в идеале нужно заменить на что-нибудь адекватное self.count_for_pr_b = 0 # эти пиздецы в идеале нужно заменить на что-нибудь адекватное self.progressBar.setValue(0) self.pb_start.setText("Остановить выборку") #my_directory = self.le_dir.text() pcap_files_in = self.le_file.text() pcap_file_out = self.le_name.text() per_quest = 0 per_beg = '' per_end = '' prot_quest = 0 net_prot = 0 trans_prot = 0 appl_prot = 0 ## ip_quest = 0 netprot_mass = [] transprot_mass = [] addr_mass = [] if (pcap_file_out.endswith(".pcap") or pcap_file_out.endswith(".pcapng")) == False: pcap_file_out = pcap_file_out + ".pcap" self.pt_log.appendPlainText("Сохранить в:") self.pt_log.appendPlainText(" " + pcap_file_out) #if self.radiobutton.isChecked(): # onlyfiles = [my_directory + '/' + f for f in listdir(my_directory) if # f.endswith(".pcap") or f.endswith(".pcapng") and isfile(join(my_directory, f))] # self.for_pr_b = len(onlyfiles) # # self.pt_log.appendPlainText("Выбрана директория:") # self.pt_log.appendPlainText(" " + self.le_dir.text()) # self.pt_log.appendPlainText("С pcap-файлами:") # for file in onlyfiles: # bullshit, fname = file.rsplit('/', 1) # self.pt_log.appendPlainText(" " + fname) #elif self.radiobutton_2.isChecked(): onlyfiles = pcap_files_in.split(', ') self.for_pr_b = len(onlyfiles) self.pt_log.appendPlainText("Выбраны pcap-файлы:") for file in onlyfiles: self.pt_log.appendPlainText(" " + (file)) if self.cb_addr.isChecked() and self.pt_addr.toPlainText() != '': ip_quest = 1 addr_mass = self.pt_addr.toPlainText().splitlines() if self.cb_time.isChecked(): per_quest = 1 per_beg = self.dt_beg.dateTime() per_end = self.dt_end.dateTime() if self.cb_prot.isChecked(): prot_quest = 1 transprot_mass = self.transprot_mass netprot_mass = self.netprot_mass if self.pt_transpr.toPlainText() != '': trans_prot = 1 if self.pt_netpr.toPlainText() != '': net_prot = 1 #self.radiobutton.setDisabled(True) #self.radiobutton_2.setDisabled(True) #self.l_input_dir.setDisabled(True) #self.l_or.setDisabled(True) self.l_input_file.setDisabled(True) #self.pb_dir.setDisabled(True) self.pb_file.setDisabled(True) #self.le_dir.setDisabled(True) self.le_file.setDisabled(True) self.cb_time.setDisabled(True) self.cb_prot.setDisabled(True) self.cb_addr.setDisabled(True) self.l_transpr.setDisabled(True) self.l_netpr.setDisabled(True) self.l_beg.setDisabled(True) self.l_end.setDisabled(True) self.l_name.setDisabled(True) self.l_filt.setDisabled(True) self.le_name.setDisabled(True) self.dt_beg.setDisabled(True) self.dt_end.setDisabled(True) self.pt_transpr.setDisabled(True) self.pt_netpr.setDisabled(True) self.pt_addr.setDisabled(True) self.pb_time.setDisabled(True) self.pb_transpr.setDisabled(True) self.pb_netpr.setDisabled(True) self.pb_addr.setDisabled(True) self.pb_name.setDisabled(True) self.worker = WorkerThread(onlyfiles, pcap_file_out, per_quest, per_beg, per_end, prot_quest, net_prot, netprot_mass, trans_prot, transprot_mass, appl_prot, ip_quest, addr_mass) self.worker.callback_received.connect(self.append_to_log) self.worker.start() self.pt_log.appendPlainText("") self.pt_log.appendPlainText("В работе:") elif self.filtering_is_on == 1: self.worker.terminate() self.pt_log.appendPlainText("") self.pt_log.appendPlainText("Работа прервана") self.pt_log.appendPlainText("") self.pt_log.appendPlainText("") self.go_to_starting_set() def append_to_log(self, x): self.count_for_pr_b += 1 self.pt_log.appendPlainText("") self.pt_log.appendPlainText(x) self.progressBar.setValue(self.count_for_pr_b * 100 / (self.for_pr_b + 1)) if self.progressBar.value() == 100: self.pt_log.appendPlainText("") self.pt_log.appendPlainText("") self.go_to_starting_set() def go_to_starting_set(self): self.filtering_is_on = 0 self.pb_start.setText("Начать выборку") #self.radiobutton.setDisabled(False) #self.radiobutton_2.setDisabled(False) #self.l_input_dir.setDisabled(False) #self.l_or.setDisabled(False) self.l_input_file.setDisabled(False) #self.pb_dir.setDisabled(False) self.pb_file.setDisabled(False) #self.le_dir.setDisabled(False) self.le_file.setDisabled(False) self.cb_time.setDisabled(False) self.cb_prot.setDisabled(False) self.cb_addr.setDisabled(False) self.l_name.setDisabled(False) self.l_filt.setDisabled(False) self.le_name.setDisabled(False) self.pb_name.setDisabled(False) if self.cb_time.isChecked(): self.dt_beg.setEnabled(True) self.dt_end.setEnabled(True) self.l_beg.setEnabled(True) self.l_end.setEnabled(True) if self.cb_prot.isChecked(): self.l_transpr.setEnabled(True) self.l_netpr.setEnabled(True) self.pt_transpr.setEnabled(True) self.pt_netpr.setEnabled(True) self.pb_transpr.setEnabled(True) self.pb_netpr.setEnabled(True) if self.cb_addr.isChecked(): self.pt_addr.setEnabled(True) self.pb_addr.setEnabled(True) def merge_it_motherFucker(self): #if self.radiobutton_3.isChecked(): # self.pt_log2.appendPlainText("Выбрана директория с pcap-файлами:") # self.pt_log2.appendPlainText(" " + self.le_dir2.text()) # self.pt_log2.appendPlainText('Просматриваем "{}"...'.format(self.le_dir2.text())) # onlyfiles = [self.le_dir2.text() + '/' + f for f in listdir(self.le_dir2.text()) if # f.endswith(".pcap") or f.endswith(".pcapng") and isfile(join(self.le_dir2.text(), f))] # self.pt_log2.appendPlainText(str(onlyfiles)) #elif self.radiobutton_4.isChecked(): self.pt_log2.appendPlainText("Выбраны pcap-файлы:") self.pt_log2.appendPlainText(" " + self.le_file2.text()) onlyfiles = self.le_file2.text().split(', ') self.pt_log2.appendPlainText('Работаем с "{}"...'.format(onlyfiles)) merge_file_out = self.le_name2.text() if (merge_file_out.endswith(".pcap") or merge_file_out.endswith(".pcapng")) == False: merge_file_out = merge_file_out + ".pcap" self.pt_log2.appendPlainText("Сохранить в:") self.pt_log2.appendPlainText(" " + merge_file_out) self.pt_log2.appendPlainText("") merge.mergecap(onlyfiles, merge_file_out)
class ConfirmTxDialog(WindowModalDialog): # set fee and return password (after pw check) def __init__(self, *, window: 'ElectrumWindow', inputs, outputs, output_value: Union[int, str], is_sweep: bool): WindowModalDialog.__init__(self, window, _("BitPost Confirm Transaction")) self.main_window = window self.inputs = inputs self.outputs = outputs self.output_value = output_value self.delay = None self.target = None self.txs = [] self.config = window.config self.wallet = window.wallet self.not_enough_funds = False self.no_dynfee_estimates = False self.needs_update = False self.is_sweep = is_sweep self.password_required = self.wallet.has_keystore_encryption( ) and not is_sweep self.num_txs = int(window.config.get('bitpost_num_txs')) self.imax_fees = 0 self.imax_size = 0 self.build_gui() def build_gui(self): vbox = QVBoxLayout() self.setLayout(vbox) grid = QGridLayout() vbox.addLayout(grid) self.amount_label = QLabel('') grid.addWidget(QLabel(_("Target for confirmation")), 0, 0) self.qtarget = QDateTimeEdit(QDateTime.currentDateTime().addSecs( int(self.main_window.config.get('bitpost_target_interval')) * 60)) grid.addWidget(self.qtarget, 0, 1) self.asap_check = QCheckBox("ASAP") self.asap_check.clicked.connect(self.toggle_target) grid.addWidget(self.asap_check, 0, 2) grid.addWidget(QLabel(_("Maximum Fee")), 2, 0) self.max_fees = QLineEdit( str(self.main_window.config.get('bitpost_max_fee'))) self.max_fees.textChanged.connect(self.change_max_fees) grid.addWidget(self.max_fees, 2, 1) self.fee_combo = QComboBox() fee_combo_values = get_fee_units( self.main_window, self.main_window.config.get('bitpost_max_fee_unit')) self.fee_combo.addItems(fee_combo_values) grid.addWidget(self.fee_combo, 2, 2) self.schedule_check = QCheckBox(_("Schedule transaction")) self.schedule_check.clicked.connect(self.toggle_delay) grid.addWidget(self.schedule_check, 3, 0, 1, -1) self.qdelay = QDateTimeEdit(QDateTime.currentDateTime()) grid.addWidget(self.qdelay, 4, 0) sp_retain = QSizePolicy(self.qdelay.sizePolicy()) sp_retain.setRetainSizeWhenHidden(True) self.qdelay.setSizePolicy(sp_retain) self.qdelay.setVisible(False) self.message_label = QLabel(self.default_message()) grid.addWidget(self.message_label, 9, 0, 1, -1) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit() self.pw.setVisible(self.password_required) grid.addWidget(self.pw_label, 11, 0) grid.addWidget(self.pw, 11, 1, 1, -1) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.preview_button = QPushButton(_('Preview')) self.preview_button.clicked.connect(self.on_preview) self.preview_button.setDefault(True) vbox.addLayout( Buttons(CancelButton(self), self.preview_button, self.send_button)) # set default to ASAP checked self.asap_check.setChecked(True) self.toggle_target() self.update() self.is_send = False def toggle_target(self): if self.asap_check.isChecked(): self.qtarget.setEnabled(False) self.qdelay.setEnabled(False) self.schedule_check.setEnabled(False) else: self.qtarget.setEnabled(True) self.qdelay.setEnabled(True) self.schedule_check.setEnabled(True) def toggle_delay(self): if self.schedule_check.isChecked(): self.qdelay.setVisible(True) else: self.qdelay.setVisible(False) def change_max_fees(self): pass def default_message(self): return _('Enter your password to proceed' ) if self.password_required else _('Click Send to proceed') def on_preview(self): password = self.pw.text() or None BlockingWaitingDialog(self.main_window, _("Preparing transaction..."), self.prepare_txs) if len(self.txs) <= 0: return d = PreviewTxsDialog(window=self.main_window, txs=self.txs, password=password, is_sweep=self.is_sweep) cancelled, is_send, password = d.run() if cancelled: return if is_send: self.pw.setText(password) self.send() def run(self): cancelled = not self.exec_() password = self.pw.text() or None return cancelled, self.is_send, password, self.txs, self.target, self.delay, self.imax_fees, self.imax_size def send(self): password = self.pw.text() or None if self.password_required: if password is None: self.main_window.show_error(_("Password required"), parent=self) return try: self.wallet.check_password(password) except Exception as e: self.main_window.show_error(str(e), parent=self) return self.is_send = True self.target = self.qtarget.dateTime().toPyDateTime().timestamp() if self.asap_check.isChecked(): self.target = round(datetime.now().timestamp() + 20 * 60) if self.schedule_check.isChecked(): self.delay = self.qdelay.dateTime().toPyDateTime() else: self.delay = self.main_window.config.get('bitpost_delay', 0) if self.target < self.delay: self.main_window.show_error( _("Target should be greater than delay")) return self.is_send = True if self.is_send: self.accept() else: print("ERROR: is_send is false") def on_send(self): BlockingWaitingDialog(self.main_window, _("Preparing transaction..."), self.prepare_txs) if len(self.txs) <= 0: return self.send() def get_feerates(self, estimated_size): if self.config.get('testnet'): testnet = True else: testnet = False bitpost_interface = BitpostInterface(testnet=testnet) max_feerate = self.calculate_max_feerate(estimated_size, self.fee_combo.currentText()) return bitpost_interface.get_feerates(max_feerate, size=self.num_txs) def calculate_max_feerate(self, estimated_size, fee_unit): raw_max_fee = float(self.max_fees.text()) if fee_unit == 'sats/byte': return raw_max_fee elif fee_unit == 'sats': return raw_max_fee / estimated_size else: max_sats = 100_000_000 * raw_max_fee / float( self.main_window.fx.exchange_rate()) return max_sats / estimated_size def prepare_txs(self): try: print('prepare txs') self.prepare_txs_by_bumping_fee() except CannotBumpFee as ex: print("cannot bump fee", ex) self.prepare_txs_manually() except Exception as e: print(e) def prepare_txs_manually(self): print('prepare tx manually') max_fee = int( 200 * self.calculate_max_feerate(200, self.fee_combo.currentText())) highest_fee_tx = self.make_tx(max_fee) self.imax_size = est_size = highest_fee_tx.estimated_size() self.imax_fees = max_fee = int( est_size * self.calculate_max_feerate(est_size, self.fee_combo.currentText())) can_be_change = lambda o: self.main_window.wallet.is_change( o.address) and self.main_window.wallet.is_mine(o.address) change_index = max([ i for i in range(len(highest_fee_tx.outputs())) if can_be_change(highest_fee_tx.outputs()[i]) ]) max_feerate = ( highest_fee_tx.input_value() - highest_fee_tx.output_value()) / highest_fee_tx.estimated_size() feerates = self.get_feerates(max_feerate) highest_fee_tx.set_rbf(True) self.txs = [] for fee in feerates: tx = self.main_window.wallet.make_unsigned_transaction( coins=highest_fee_tx.inputs(), outputs=highest_fee_tx.outputs()) new_change = highest_fee_tx.outputs()[change_index].value + int( abs(max_feerate - fee) * highest_fee_tx.estimated_size()) tx.outputs()[change_index].value = new_change self.txs.append(tx) self.not_enough_funds = False self.no_dynfee_estimates = False def prepare_txs_by_bumping_fee(self): try: base_tx = self.make_tx(0) est_size = base_tx.estimated_size() feerates = self.get_feerates(est_size) base_tx.set_rbf(True) base_tx.serialize_to_network() for fee in feerates: tx = self.bump_fee(base_tx, fee) tx.set_rbf(True) self.txs.append(tx) self.imax_fees = max(self.imax_fees, tx.get_fee()) self.imax_size = max(self.imax_size, tx.estimated_size()) self.not_enough_funds = False self.no_dynfee_estimates = False except NotEnoughFunds: self.not_enough_funds = True self.txs = [] print("not enought funds") return except NoDynamicFeeEstimates: self.no_dynfee_estimates = True self.txs = [] print("no dynamic fee estimation") try: self.txs = [self.make_tx(0)] except BaseException: return except InternalAddressCorruption as e: self.txs = [] self.main_window.show_error(str(e)) print("Internal address corruption") return except BitpostDownException: self.main_window.show_error(_("Fee Rates Service Not Available"), parent=self) self.is_send = False print("bitpost down") return except Exception as e: self.txs = [] print("Exception", e) self.main_window.show_error(_("Exception: " + str(e)), parent=self.main_window) return def bump_fee(self, tx, new_fee): inputs = tx.inputs() coco = [] for c in self.inputs: if c not in inputs: coco.append(c) try: self.main_window.logger.debug(str(new_fee) + "bump fee method 1") tx_out = self.main_window.wallet._bump_fee_through_coinchooser( tx=tx, new_fee_rate=new_fee, coins=coco) except Exception as ex: if all( self.main_window.wallet.is_mine(o.address) for o in list(tx.outputs())): raise ex self.window.show_error( _("Not enought funds, please add more inputs or reduce max fee" )) raise NotEnoughFunds return tx_out def make_tx(self, fee_est): tx = self.main_window.wallet.make_unsigned_transaction( coins=self.inputs, outputs=self.outputs, fee=fee_est, is_sweep=self.is_sweep) return tx
class Setting(QWidget, Ui_widget_setting): signal_core_number = pyqtSignal(int) signal_suspend_status = pyqtSignal(bool) signal_waiting_min = pyqtSignal(int) signal_schedule_status = pyqtSignal(bool) signal_cancel_plan = pyqtSignal(str) signal_change_language = pyqtSignal(str) def __init__(self, suspend, cores, schedule_status, waiting_min, language): super().__init__() self.setupUi(self) # ----------init variable------------ self.suspend = suspend self.cores = cores self.schedule_status = schedule_status self.waiting_min = waiting_min self.language = language self.language_list = ['English', 'Chinese'] # ----------init widget-------------- self.label_suspend = QTreeWidgetItem() self.checkbox_suspend = QCheckBox() self.label_cores = QTreeWidgetItem() self.edit_cores = QSpinBox() self.label_plan = QTreeWidgetItem() self.edit_plan_datetime = QDateTimeEdit() self.label_about = QTreeWidgetItem() self.label_language = QTreeWidgetItem() self.combobox_lauguage = QComboBox() # -----------init function---------------- self.ui_set() self.btn() self.init_data_show() self.self_translate(language) self.show() def btn(self): self.tree_setting.itemClicked.connect(self.effect_expand) self.tree_setting.itemChanged.connect(self.enable_schedule) self.combobox_lauguage.activated.connect(self.choose_language) self.checkbox_suspend.stateChanged.connect(self.change_suspend_status) def ui_set(self): # style self.setStyleSheet( "QSpinBox{border:1.5px solid #778899;border-radius:4px; padding:2px 2px}" "QDateTimeEdit{border:1.5px solid #778899;border-radius:4px; padding:2px 2px}" ) self.tree_setting.setColumnWidth(0, 180) self.tree_setting.expandItem(self.tree_setting.topLevelItem(0)) self.tree_setting.topLevelItem(1).setCheckState(1, 0) self.edit_cores.setMaximumSize(50, 25) self.edit_cores.setContentsMargins(0, 4, 0, 0) self.edit_cores.setMinimum(1) self.edit_cores.setMaximum(132) self.label_plan.setDisabled(True) self.edit_plan_datetime.setMaximumSize(135, 28) self.edit_plan_datetime.setDisabled(True) self.combobox_lauguage.setMaximumSize(135, 28) self.combobox_lauguage.addItems(self.language_list) self.combobox_lauguage.setCurrentText(self.language) # function self.add_tree_item(0, self.label_suspend, "暂停队列", self.checkbox_suspend) self.add_tree_item(0, self.label_cores, "使用核数", self.edit_cores) self.add_tree_item(1, self.label_plan, "计划启动于", self.edit_plan_datetime) self.add_tree_item(2, self.label_language, "语言选择", self.combobox_lauguage) def add_tree_item(self, top_level_index, label, label_name, input_edit): label.setText(0, label_name) self.tree_setting.topLevelItem(top_level_index).addChild(label) self.tree_setting.setItemWidget(label, 1, input_edit) def effect_expand(self, item, column): index = self.tree_setting.indexOfTopLevelItem(item) if index >= 0: if item.isExpanded(): item.setExpanded(False) else: item.setExpanded(True) def enable_schedule(self, item, column): index = self.tree_setting.indexOfTopLevelItem(item) if index == 1: check_state = item.checkState(column) self.schedule_status = bool(check_state) self.label_plan.setDisabled(2 - check_state) self.edit_plan_datetime.setEnabled(check_state) item.setExpanded(2 - check_state) self.reset_date_edit() self.suspend = self.checkbox_suspend.checkState() self.checkbox_suspend.setCheckState(self.suspend + check_state) self.checkbox_suspend.setDisabled(check_state) def init_data_show(self): self.edit_cores.setValue(self.cores) self.checkbox_suspend.setCheckState(self.suspend * 2) if self.schedule_status: self.tree_setting.topLevelItem(1).setCheckState(1, 2) self.label_plan.setDisabled(False) self.edit_plan_datetime.setEnabled(True) self.tree_setting.topLevelItem(1).setExpanded(True) waiting_seconds = self.waiting_min * 60 self.edit_plan_datetime.setDisplayFormat("yyyy/MM/dd HH:mm") self.edit_plan_datetime.setDateTime( QDateTime.currentDateTime().addSecs(waiting_seconds)) else: self.reset_date_edit() def reset_date_edit(self): self.edit_plan_datetime.setDisplayFormat("yyyy/MM/dd HH:mm") self.edit_plan_datetime.setDateTime(QDateTime.currentDateTime()) self.edit_plan_datetime.setMinimumDateTime(QDateTime.currentDateTime()) self.edit_plan_datetime.setMaximumDateTime( QDateTime.currentDateTime().addDays(5)) self.edit_plan_datetime.setCalendarPopup(True) def change_suspend_status(self, status): self.suspend = bool(status) def plan_start(self): curr_time = QDateTime.currentSecsSinceEpoch() schedule_time = self.edit_plan_datetime.dateTime().toSecsSinceEpoch() self.waiting_min = int(round((schedule_time - curr_time) / 60, 0)) print('waiting min', self.waiting_min) self.signal_waiting_min.emit(self.waiting_min) def choose_language(self): language = self.combobox_lauguage.currentText() self.signal_change_language.emit(language) self.self_translate(language) def self_translate(self, language): if language == 'English': self.label_suspend.setText(0, 'Suspend next') self.label_cores.setText(0, 'Threads number') self.label_plan.setText(0, 'Scheduled in') self.label_language.setText(0, 'Language') else: self.label_suspend.setText(0, "暂停队列") self.label_cores.setText(0, "使用核数") self.label_plan.setText(0, "计划启动于") self.label_language.setText(0, "语言选择") self.retranslateUi(self) def closeEvent(self, event): self.cores = self.edit_cores.value() suspend_status = self.checkbox_suspend.checkState() self.signal_core_number.emit(self.cores) self.signal_schedule_status.emit(self.schedule_status) if self.schedule_status: self.plan_start() else: self.signal_cancel_plan.emit(' ') self.signal_suspend_status.emit(bool(suspend_status)) self.close()
class StartTimeSetup(QWidget): """Start Time Setup This widget allows the user to set up start times. Start times can be the same for the entire race, or it can be the same for a particular field. Or, the start times can be assigned at a set interval. """ def __init__(self, modeldb, parent=None): """Initialize the StartTimeSetup instance.""" super().__init__(parent=parent) self.modeldb = modeldb field_table_model = self.modeldb.field_table_model field_name_column = field_table_model.name_column # Scope selection (whole race vs a field). field_selection_widget = QGroupBox('Set up start times for:') scope_button_group = QButtonGroup() self.all_fields_radiobutton = QRadioButton('Entire race') self.all_fields_radiobutton.setChecked(True) scope_button_group.addButton(self.all_fields_radiobutton) self.selected_field_radiobutton = QRadioButton('A single field:') scope_button_group.addButton(self.selected_field_radiobutton) self.selected_field_combobox = QComboBox() self.selected_field_combobox.setModel(field_table_model) self.selected_field_combobox.setModelColumn(field_name_column) self.selected_field_combobox.setEnabled(False) field_selection_widget.setLayout(QHBoxLayout()) field_selection_widget.layout().addWidget(self.all_fields_radiobutton) field_selection_widget.layout().addWidget(self.selected_field_radiobutton) field_selection_widget.layout().addWidget(self.selected_field_combobox) # Start time. start_time_widget = QGroupBox('Start time:') start_time_button_group = QButtonGroup() self.start_time_now_radiobutton = QRadioButton('Now') self.start_time_now_radiobutton.setChecked(True) start_time_button_group.addButton(self.start_time_now_radiobutton) self.start_time_specified_radiobutton = QRadioButton('At:') start_time_button_group.addButton(self.start_time_specified_radiobutton) self.start_time_datetimeedit = QDateTimeEdit() # Time "now" set in showEvent() self.start_time_datetimeedit.setDisplayFormat(defaults.DATETIME_FORMAT) self.start_time_datetimeedit.setEnabled(False) start_time_widget.setLayout(QHBoxLayout()) start_time_widget.layout().addWidget(self.start_time_now_radiobutton) start_time_widget.layout().addWidget(self.start_time_specified_radiobutton) start_time_widget.layout().addWidget(self.start_time_datetimeedit) # Start time interval. interval_widget = QGroupBox('Interval:') interval_button_group = QButtonGroup() self.same_start_time_radiobutton = QRadioButton('Same for all') self.same_start_time_radiobutton.setChecked(True) interval_button_group.addButton(self.same_start_time_radiobutton) self.interval_start_time_radiobutton = QRadioButton('Use interval:') interval_button_group.addButton(self.interval_start_time_radiobutton) self.interval_lineedit = QLineEdit() self.interval_lineedit.setText(str(defaults.START_TIME_INTERVAL_SECS)) self.interval_lineedit.setValidator(QRegExpValidator(QRegExp('[1-9][0-9]*'))) interval_lineedit_group = QWidget() interval_lineedit_group.setLayout(QHBoxLayout()) interval_lineedit_group.layout().addWidget(self.interval_lineedit) interval_lineedit_group.layout().addWidget(QLabel('secs')) interval_lineedit_group.setEnabled(False) interval_widget.setLayout(QHBoxLayout()) interval_widget.layout().addWidget(self.same_start_time_radiobutton) interval_widget.layout().addWidget(self.interval_start_time_radiobutton) interval_widget.layout().addWidget(interval_lineedit_group) confirm_button = QPushButton('Assign Start Times') # Top-level widgets. self.setLayout(QVBoxLayout()) self.layout().addWidget(field_selection_widget) self.layout().addWidget(start_time_widget) self.layout().addWidget(interval_widget) self.layout().addWidget(confirm_button) # Signals/slots plumbing. confirm_button.clicked.connect(self.handle_assign_start_times) self.selected_field_radiobutton.toggled.connect(self.selected_field_combobox.setEnabled) self.start_time_specified_radiobutton.toggled.connect(self.start_time_datetimeedit .setEnabled) self.interval_start_time_radiobutton.toggled.connect(interval_lineedit_group .setEnabled) def handle_assign_start_times(self): """Assign the start times, given the contents of the various input widgets.""" race_table_model = self.modeldb.race_table_model racer_table_model = self.modeldb.racer_table_model # Validate inputs. if not self.interval_lineedit.text().isdigit: raise Exception('Invalid interval') field = None if self.selected_field_radiobutton.isChecked(): field = self.selected_field_combobox.currentText() reference_datetime = race_table_model.get_reference_clock_datetime() if self.start_time_now_radiobutton.isChecked(): start_time = reference_datetime.msecsTo(QDateTime.currentDateTime()) else: start_time = reference_datetime.msecsTo(self.start_time_datetimeedit.dateTime()) interval = 0 if self.interval_start_time_radiobutton.isChecked(): interval = int(self.interval_lineedit.text()) try: # If we're potentially going to be overwriting existing start times, # warn before committing. starts_overwritten = racer_table_model.assign_start_times(field, start_time, interval, True) if starts_overwritten > 0: if QMessageBox.question(self, 'Question', 'About to overwrite %s existing ' % starts_overwritten + 'start times. Proceed anyway?') != QMessageBox.Yes: return racer_table_model.assign_start_times(field, start_time, interval) except InputError as e: QMessageBox.warning(self, 'Error', str(e)) success_message = 'Start times have been assigned' if field: success_message += ' to field "%s"' % field start_datetime = reference_datetime.addMSecs(start_time) success_message += ' for %s' % start_datetime.toString(Qt.SystemLocaleLongDate) if interval: success_message += ' at %s secomd intervals' % interval success_message += '.' QMessageBox.information(self, 'Success', success_message) def showEvent(self, event): #pylint: disable=invalid-name """Set up input widgets when this widget is shown. Basically, this amounts to populating the start time edit box with the current date and time, plus some time ahead, rounded to the nearest 5 minutes. """ self.start_time_datetimeedit.setDate(QDate.currentDate()) now = QTime.currentTime().addSecs(defaults.START_TIME_FROM_NOW_SECS) now.setHMS(now.hour(), now.minute() + 5 - now.minute()%5, 0, 0) self.start_time_datetimeedit.setTime(now) super().showEvent(event)
class CountdownWidget(QWidget): """Define custom widget as countdown control panel.""" def __init__(self, ctrl, parent=None): """Init completer.""" super().__init__(parent) self.controller = ctrl self.createLayout() self.loadSettings() self.connect() def createLayout(self): """Create widget to control the countdown browser source.""" layout = QGridLayout() self.rb_static = QRadioButton(_("Static Countdown to date:"), self) layout.addWidget(self.rb_static, 0, 0) self.rb_dynamic = QRadioButton(_("Dynamic Countdown duration:"), self) self.rb_dynamic.setChecked(True) self.rb_dynamic.toggled.connect(self.toggleRadio) layout.addWidget(self.rb_dynamic, 1, 0) self.te_datetime = QDateTimeEdit() layout.addWidget(self.te_datetime, 0, 1) self.te_duration = QTimeEdit() self.te_duration.setDisplayFormat("HH 'h' mm 'm' ss 's'") layout.addWidget(self.te_duration, 1, 1) self.event_label = QLabel(' ' + _('Event description:')) layout.addWidget(self.event_label, 0, 2) self.le_desc = QLineEdit() self.le_desc.setAlignment(Qt.AlignCenter) layout.addWidget(self.le_desc, 0, 3, 1, 2) self.cb_restart = QCheckBox( _('Restart countdown when source becomes active')) layout.addWidget(self.cb_restart, 1, 2, 1, 2) self.pb_start = QPushButton(" " + _('Start Countdown') + " ") layout.addWidget(self.pb_start, 1, 4) layout.setColumnStretch(2, 1) layout.setColumnStretch(3, 2) self.setLayout(layout) def toggleRadio(self): static = self.rb_static.isChecked() self.te_datetime.setEnabled(static) self.te_duration.setEnabled(not static) self.cb_restart.setEnabled(not static) self.pb_start.setEnabled(not static) def loadSettings(self): static = scctool.settings.config.parser.getboolean( "Countdown", "static") if static: self.rb_static.setChecked(True) else: self.rb_dynamic.setChecked(True) description = scctool.settings.config.parser.get( 'Countdown', 'description') self.le_desc.setText(description.strip()) restart = scctool.settings.config.parser.getboolean( "Countdown", "restart") self.cb_restart.setChecked(restart) duration = QTime() string = scctool.settings.config.parser.get('Countdown', 'duration').strip() duration = QTime.fromString(string, 'HH:mm:ss') self.te_duration.setTime(duration) string = scctool.settings.config.parser.get('Countdown', 'datetime').strip() datetime = QDateTime.fromString(string, 'yyyy-MM-dd HH:mm') self.te_datetime.setDateTime(datetime) def connect(self): self.le_desc.textChanged.connect(self.changed_description) self.cb_restart.toggled.connect(self.changed_restart) self.te_datetime.dateTimeChanged.connect(self.changed_datetime) self.te_duration.timeChanged.connect(self.changed_duration) self.rb_static.toggled.connect(self.changed_static) self.pb_start.pressed.connect(self.start_pressed) def changed_description(self): desc = self.le_desc.text().strip() scctool.settings.config.parser.set('Countdown', 'description', desc) self.controller.websocketThread.sendData2Path('countdown', "DESC", desc) def changed_restart(self): restart = self.cb_restart.isChecked() scctool.settings.config.parser.set('Countdown', 'restart', str(restart)) self.controller.websocketThread.sendData2Path('countdown', "RESTART", restart) def changed_datetime(self, time): datetime = time.toString('yyyy-MM-dd HH:mm') scctool.settings.config.parser.set('Countdown', 'datetime', datetime) self.sendData() def changed_duration(self, time): duration = time.toString('HH:mm:ss') scctool.settings.config.parser.set('Countdown', 'duration', duration) self.sendData() def changed_static(self): static = self.rb_static.isChecked() scctool.settings.config.parser.set('Countdown', 'static', str(static)) self.sendData() def start_pressed(self): self.controller.websocketThread.sendData2Path('countdown', 'START') def sendData(self): data = {} data['static'] = scctool.settings.config.parser.getboolean( 'Countdown', 'static') data['desc'] = scctool.settings.config.parser.get( 'Countdown', 'description') data['restart'] = scctool.settings.config.parser.getboolean( 'Countdown', 'restart') data['datetime'] = scctool.settings.config.parser.get( 'Countdown', 'datetime') data['duration'] = scctool.settings.config.parser.get( 'Countdown', 'duration') data['replacement'] = scctool.settings.config.parser.get( 'Countdown', 'replacement') self.controller.websocketThread.sendData2Path('countdown', "DATA", data)
class LessonLoadingWidget(AbstractLoadingWizard, IAcceptDrop, ISelectFile): label = "Загрузить занятия" description = "Открывает интерфейс загрузки занятия" steps = [ Step('Выбрать дату начала семестра', ''), Step('Загрузить файл с расписанием', 'требуется загрузить файл с распсианием занятий', False), Step('Загрузить данные для всех групп', '', False) ] group_steps: Dict[str, Step] def setupUi(self): main_layout = QVBoxLayout() date_input_layout = QHBoxLayout() self.select_date_label = QLabel("Выберите дату начала семестра") self.date_input = QDateTimeEdit( Semester.closest_semester_start().date()) self.date_input.setCalendarPopup(True) self.accept_date_button = QPushButton("Подтвердить") date_input_layout.addWidget(self.select_date_label) date_input_layout.addWidget(self.date_input, stretch=9) date_input_layout.addWidget(self.accept_date_button) self.hello_message = QLabel( "Выберите файл с расписанием или перетащите его в окно.") self.select_button = QPushButton("Выбрать") main_layout.addLayout(date_input_layout) main_layout.addWidget(self.hello_message, alignment=Qt.AlignHCenter | Qt.AlignVCenter) main_layout.addWidget(self.select_button, alignment=Qt.AlignHCenter | Qt.AlignTop) self.setLayout(main_layout) def __init__(self, professor, loading_session, parent=None): QWidget.__init__(self, parent) IAcceptDrop.__init__(self) ISelectFile.__init__(self) self.professor = professor self.session = professor.session() self.loading_session = loading_session self.setupUi() def change_date(): self.date_input.setEnabled(True) self.revoke_step.emit(self.steps[0]) self.accept_date_button.setText("Подтвердить") self.accept_date_button.clicked.connect(accept_date) with suppress(TypeError): self.accept_date_button.clicked.disconnect(change_date) self.select_button.setEnabled(False) self.select_button.setToolTip("Укажите дату начала семестра") def accept_date(): self.date_input.setEnabled(False) self.step.emit(self.steps[0]) self.accept_date_button.setText("Изменить") self.accept_date_button.clicked.connect(change_date) self.accept_date_button.clicked.disconnect(accept_date) self.select_button.setEnabled(True) self.select_button.setToolTip( "Выберите файл с расписанием занятий") self.accept_date_button.clicked.connect(accept_date) self.select_button.clicked.connect( lambda: self.select_file.emit(self.read_file)) self.drop.connect(self.on_drop) self.requested = False self.group_steps: Dict[Group, Step] = dict() change_date() def on_drop(self, files): if not self.date_input.isEnabled(): for file in files: self.read_file(file) else: QMessageBox().information(self, "", "Сначала укажите дату начала семестра.") def read_file(self, file: QUrl): self.worker = LessonLoader.auto(file=file.path(), start_day=datetime( self.date_input.date().year(), self.date_input.date().month(), self.date_input.date().day()), professor=self.professor, session=self.loading_session) main_layout = self.layout() main_layout.removeWidget(self.hello_message) main_layout.removeWidget(self.select_button) self.hello_message.deleteLater() self.select_button.deleteLater() self.info_message = QLabel( "Предоставте необходимые данные для завершения загрузки") data_layout = QHBoxLayout() discipline_layout = QVBoxLayout() self.discipline_title = QLabel("Обнаружены следующие дисциплины") self.discipline_list = QNewItemsTable(self.session, self.loading_session) for discipline in self.worker.get_disciplines(): self.discipline_list.addItem(discipline) discipline_layout.addWidget(self.discipline_title) discipline_layout.addWidget(self.discipline_list) group_layout = QVBoxLayout() self.group_title = QLabel("Обнаружены следующие группы") self.group_list = QNewItemsTable(self.session, self.loading_session) self.steps = self.steps[:-1] for group in self.worker.get_groups(): self.group_list.addItem(group) group_step = Step(f'Загрузить данные группы {group.name}', '') self.group_steps[group.name]: Dict[str, Step] = group_step self.steps.append(group_step) self.steps_changed.emit(self.steps) student_layout = QHBoxLayout() control_student_layout = QVBoxLayout() self.description_label = QLabel( "Необходимо загрузить информацию о группах.") self.server_load_button = QPushButton("Загрузить с сервера") self.server_load_button.clicked.connect(self.request_students) self.client_load_button = QPushButton("Выбрать файл") self.client_load_button.clicked.connect( lambda x: self.select_file.emit(self.load_group)) list_student_layout = QVBoxLayout() self.tabs = QTabWidget() self.students_lists: Dict[Group, QListWidget] = dict() for group in self.worker.get_groups(): list_widget = QNewItemsTable(self.session, self.loading_session) self.students_lists[group] = list_widget self.tabs.addTab(list_widget, group.name) for group in self.worker.get_groups(): if len(group.students): self._apply_group(group_name=group.name, students=group.students) self.step.emit(self.group_steps[group.name]) list_student_layout.addWidget(QLabel("Списки групп")) list_student_layout.addWidget(self.tabs) control_student_layout.addWidget(self.description_label) control_student_layout.addWidget(self.server_load_button) control_student_layout.addWidget(self.client_load_button) student_layout.addLayout(control_student_layout) student_layout.addLayout(list_student_layout) group_layout.addWidget(self.group_title) group_layout.addWidget(self.group_list) data_layout.addLayout(discipline_layout) data_layout.addLayout(group_layout) main_layout.addLayout(data_layout, stretch=1) main_layout.addWidget(QSeparator(Qt.Horizontal)) main_layout.addLayout(student_layout, stretch=10) self.step.emit(self.steps[1]) def check_groups(self, groups: List[Group]): for index, group in enumerate(groups): existing_group = self.session.query(Group).filter( Group.name == group.name).first() if existing_group is not None: students = Student.of(existing_group) if len(students) > 0: self._apply_group(existing_group.name, existing_group.students) def load_group(self, file: QUrl): group_loader = GroupLoader.auto(file=file.path(), professor=self.professor, session=self.loading_session) group = group_loader.get_group() self._apply_group(group.name, group_loader.get_students_list()) def _apply_group(self, group_name: str, students: List[Student]): group: Group = list( filter(lambda x: x.name == group_name, self.students_lists.keys()))[0] list_widget = self.students_lists[group] list_widget.clear() for student in students: self.loading_session.add(student) list_widget.addItem(student) self.loading_session.flush() self.step.emit(self.group_steps[group.name]) def request_students(self): def apply_response(group: GroupAPI.GroupResponse): self._apply_group(group_name=group.name, students=group.students) if not self.requested: self.managers = list() for group in self.students_lists.keys(): self.managers.append( QBisitorRequest(address='/api/group', user=self.professor, data={'name': group.name}, on_finish=apply_response)) self.requested = True else: QMessageBox().information( self, "", "Вы уже запросили информацию с сервера.")
class SelectionScreen(QWidget): """ Screen for showing and modifying current selections """ def __init__(self, parent, selection_manager): super().__init__(parent) self.selection_manager = selection_manager layout = QGridLayout(self) layout.setColumnMinimumWidth(0, 0) layout.setColumnMinimumWidth(1, 0) layout.setColumnMinimumWidth(2, 0) layout.setColumnMinimumWidth(3, 400) layout.setSpacing(5) label_size = 200 self.date_label = QLabel('Date ', self) self.date_label.setAlignment(Qt.AlignRight) self.date_widget = QDateTimeEdit(self) self.date_widget.setDisplayFormat("dd-MM-yyyy") self.date_widget.setCalendarPopup(True) self.date_widget.setAlignment(Qt.AlignLeft) self.date_widget.setFixedWidth(label_size) self.date_widget.dateChanged.connect(self.handleSelectDate) self.date_widget.setEnabled(False) self.enable_date_button = QPushButton('Enable', self) self.enable_date_button.clicked.connect(self.enableSelectDate) self.enabled = False self.clear_all_button = QPushButton('Clear', self) self.clear_all_button.clicked.connect(self.clearAllSelections) self.selected_label = QLabel('Selected: ', self) self.selected_label.setAlignment(Qt.AlignRight) self.selected_field = QLabel('None', self) self.selected_field.setAlignment(Qt.AlignLeft) empty_widget = QWidget() empty_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) layout.addWidget( self.date_label, 0, 0, ) layout.addWidget(self.date_widget, 0, 1) layout.addWidget(self.enable_date_button, 0, 2) layout.addWidget(self.selected_label, 1, 0) layout.addWidget(self.selected_field, 1, 1) layout.addWidget(self.clear_all_button, 1, 2) layout.addWidget(empty_widget, 2, 0) self.setLayout(layout) def clearAllSelections(self): """ Function for clearing all selections """ self.parent().parent().clearSelections() def updateViews(self): """ Function for updating all views """ self.parent().parent().updateDataViewWidget() def enableSelectDate(self): """ Function for clearing date selection """ if self.enabled: self.date_widget.setEnabled(False) self.selection_manager.clearDate() self.enabled = False self.enable_date_button.setText('Enable') else: self.date_widget.setEnabled(True) self.selection_manager.selectDate( self.date_widget.date().toPyDate()) self.enabled = True self.enable_date_button.setText('Disable') self.updateViews() def handleSelectDate(self, new_date): """ Function that handles select date changes """ self.selection_manager.selectDate(new_date.toPyDate()) def changeSelectedFieldLabel(self, new_text): """ Function for changing the label text """ self.selected_field.setText(new_text)
class SurveyInfoDialog(QDialog): audioIndexSignal = pyqtSignal(str) def __init__(self, parent, **kwargs): super().__init__(parent) self.surveyTableModel = parent.surveyTableModel self.mainLayout = QVBoxLayout() self.setLayout(self.mainLayout) self.kwargs = kwargs # form self.surveyDatetimeField = QDateTimeEdit() self.recorderIDField = QComboBox() self.recordingDatetimeField = QDateTimeEdit() self.recordingDurationField = QLabel() self.audioField = QComboBox() self.urlField = QLineEdit() self.noteField = QLineEdit() self.initForm() # buttons self.initButtons() # TODO make a property? @pyqtSlot(int) def setDuration(self, duration): # self.audioDuration = int self.recordingDurationField.setText(str(duration)) def initForm(self): # labels formLayout = QFormLayout() surveyDatetimeLabel = QLabel("Survey Datetime") recorderIDLabel = QLabel("Recorder ID") recordingDatetimeLabel = QLabel("Recording Datetime") recordingDurationLabel = QLabel("Recording Duration") audioLabel = QLabel("Audio File Path") urlLabel = QLabel("Audio URL") noteLabel = QLabel("Notes") # datetime format self.surveyDatetimeField.setDisplayFormat(R.datetimeFormat) self.recordingDatetimeField.setDisplayFormat(R.datetimeFormat) self.surveyDatetimeField.setEnabled(False) # primary key should not be edited # combo boxes self.recorderIDField.setEditable(True) self.audioField.setEditable(False) self.recorderIDField.addItems(self.kwargs["recorderIds"]) self.audioField.addItems(self.kwargs["audioFiles"]) self.audioField.currentTextChanged.connect(self.onFileIndexChange) # populate fields self.setInitialValues(**self.kwargs) # assemble form formLayout.addRow(surveyDatetimeLabel, self.surveyDatetimeField) formLayout.addRow(recorderIDLabel, self.recorderIDField) formLayout.addRow(recordingDatetimeLabel, self.recordingDatetimeField) formLayout.addRow(recordingDurationLabel, self.recordingDurationField) formLayout.addRow(audioLabel, self.audioField) formLayout.addRow(urlLabel, self.urlField) formLayout.addRow(noteLabel, self.noteField) self.mainLayout.addLayout(formLayout) @pyqtSlot(str) def onFileIndexChange(self, file): print(file) # newDuration = self.updateDuration(file) # self.recordingDurationField.setText(str(newDuration)) self.audioIndexSignal.emit(file) # self.updateDuration(file) QApplication.processEvents() self.repaint() @abc.abstractmethod def setInitialValues(self, **kwargs): pass def initButtons(self): buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) self.mainLayout.addWidget(buttonBox) # helper for loadForm() def getQDateTime(self, string): idStr = re.split("[:\s.\-]", string) idStr = list(map(int, idStr)) if len(idStr) == 6: id = QDateTime(int(idStr[0]), idStr[1], idStr[2], idStr[3], idStr[4], idStr[5]) elif len(idStr) == 7: id = QDateTime(int(idStr[0]), idStr[1], idStr[2], idStr[3], idStr[4], idStr[5], idStr[6]) return id def getDateTime(self): return self.surveyDatetimeField.dateTime() def createRecord(self): return SurveyRecord(surveyDatetime=self.surveyDatetimeField.dateTime(), recorderID=self.recorderIDField.currentText(), recordingDatetime=self.recordingDatetimeField.dateTime(), recordingDuration=self.recordingDurationField.text(), audioFilePath=self.audioField.currentText(), audioURL=self.urlField.text(), note=self.noteField.text())