class DownloadItem(QWidget): DEBUG = True def __init__(self, item, downloadItem, path, fileName, openFile, manager): ''' @param: item QListWidgetItem @param: downloadItem QWebEngineDownloadItem @param: path QString @param: fileName QString @param: openFile bool @param: manager DownloadManager ''' super().__init__() self._ui = uic.loadUi('mc/downloads/DownloadItem.ui', self) self._item = item # QListWidgetItem self._download = downloadItem # QWebEngineDownloadItem self._path = path self._fileName = fileName self._downTimer = QTime() self._remTime = QTime() self._downUrl = downloadItem.url() self._openFile = openFile self._downloading = False self._downloadStopped = False self._currSpeed = 0.0 self._received = downloadItem.receivedBytes() self._total = downloadItem.totalBytes() if self.DEBUG: print( 'DEBUG: %s::__init__ %s %s %s %s' % (self.__class__.__name__, item, downloadItem, path, fileName)) self.setMaximumWidth(525) self._ui.button.setPixmap( QIcon.fromTheme('process-stop').pixmap(20, 20)) self._ui.fileName.setText(self._fileName) self._ui.downloadInfo.setText(_('Remaining time unavailable')) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect( self._customContextMenuRequested) self._ui.button.clicked.connect(self._stop) manager.resized.connect(self._parentResized) def item(self): return self._item def isDownloading(self): ''' @return: bool ''' return self._downloading def isCancelled(self): ''' @return: bool ''' self._ui.downloadInfo.text().startswith(_('Cancelled')) def remainingTime(self): ''' @return: QTime ''' return self._remTime def currentSpeed(self): ''' @return: double ''' return self._currSpeed def progress(self): ''' @return: int ''' return self._ui.progressBar.value() def setDownTimer(self, timer): ''' @param: timer QTime ''' self._downTimer = timer def startDownloading(self): self._download.finished.connect(self._finished) self._download.downloadProgress.connect(self._downloadProgress) self._downloading = True if self._downTimer.elapsed() < 1: # TODO: ? self._downTimer.start() self._updateDownloadInfo(0, self._download.receivedBytes(), self._download.totalBytes()) if const.OS_LINUX: # QFileIconProvider uses only suffix on Linux iconProvider = QFileIconProvider() # QIcon fileIcon = iconProvider.icon(QFileInfo(self._fileName)) if not fileIcon.isNull(): self._ui.fileIcon.setPixmap(fileIcon.pixmap(30)) else: self._ui.fileIcon.setPixmap(self.style().standardIcon( QStyle.SP_FileIcon).pixmap(30)) else: self._ui.fileIcon.hide() @classmethod def remaingTimeToString(cls, time): ''' @param: time QTime ''' if time < QTime(0, 0, 10): return _('few seconds') elif time < QTime(0, 1): return _('%s seconds') % time.second() elif time < QTime(1, 0): return _('%s minutes') % time.minute() else: return _('%s hours') % time.hour() @classmethod def currentSpeedToString(cls, speed): ''' @param: speed double ''' if speed < 0: return _('Unknown speed') speed /= 1024 # kB if speed < 1000: return '%s kB/s' % int(speed) speed /= 1024 # MB if speed < 1000: return '%.2f MB/s' % speed speed /= 1024 # GB return '%.2f GB/s' % speed # Q_SIGNALS: deleteItem = pyqtSignal('PyQt_PyObject') # DonwloadItem downloadFinished = pyqtSignal(bool) # bool success # private Q_SLOTS: def _parentResized(self, size): ''' @param: size QSize ''' if size.width() < 200: return self.setMaximumWidth(size.width()) def _finished(self): if self.DEBUG: print('DEBUG: %s::_finished' % self.__class__.__name__) success = False host = self._download.url().host() state = self._download.state() if state == QWebEngineDownloadItem.DownloadCompleted: success = True self._ui.downloadInfo.setText( _('Done - %s (%s)') % (host, QDateTime.currentDateTime().toString( Qt.DefaultLocaleShortDate))) elif state == QWebEngineDownloadItem.DownloadInterrupted: self._ui.donwloadInfo.setText(_('Error - %s') % host) elif state == QWebEngineDownloadItem.DownloadCancelled: self._ui.downloadInfo.setText(_('Cancelled = %s') % host) self._ui.progressBar.hide() self._ui.button.hide() self._ui.frame.hide() self._item.setSizeHint(self.sizeHint()) self._downloading = False if success and self._openFile: self.__openFile() self.downloadFinished.emit(True) def _downloadProgress(self, received, total): ''' @param: received qint64 @param: total qint64 ''' if self.DEBUG: print('DEBUG: %s::_downloadProgress %s %s' % (self.__class__.__name__, received, total)) currentValue = 0 totalValue = 0 if total > 0: currentValue = received * 100 / total totalValue = 100 self._ui.progressBar.setValue(currentValue) self._ui.progressBar.setMaximum(totalValue) self._currSpeed = received * 1000.0 / self._downTimer.elapsed() self._received = received self._total = total self._updateDownloadInfo(self._currSpeed, self._received, self._total) def _stop(self): if self.DEBUG: print('DEBUG: %s::_stop' % self.__class__.__name__) self._downloadStopped = True self._ui.progressBar.hide() self._ui.button.hide() self._item.setSizeHint(self.sizeHint()) self._ui.downloadInfo.setText( _('Cancelled - %s') % self._download.url().host()) self._download.cancel() self._downloading = False self.downloadFinished.emit(False) def __openFile(self): if self._downloading: return fpath = pathjoin(self._path, self._fileName) if pathexists(fpath): QDesktopServices.openUrl(QUrl.fromLocalFile(abspath(fpath))) else: QMessageBox.warning( self._item.listWidget().parentWidget(), _("Not found"), _("Sorry, the file \n %s \n was not found!") % abspath(fpath)) def _openFolder(self): if const.OS_WIN: winFileName = '%s/%s' % (self._path, self._fileName) if self._downloading: winFileName += '.download' winFileName = winFileName.replace('/', '\\') shExArg = '/e,/select,"%s"' % winFileName system('explorer.exe ' + shExArg) else: QDesktopServices.openUrl(QUrl.fromLocalFile(self._path)) def _customContextMenuRequested(self, pos): ''' @param: pos QPoint ''' menu = QMenu() menu.addAction(QIcon.fromTheme('document-open'), _('Open File'), self.__openFile) menu.addAction(_('Open Folder'), self._openFolder) menu.addSeparator() menu.addAction(QIcon.fromTheme('edit-copy'), _('Copy Download Link'), self._copyDownloadLink) menu.addSeparator() menu.addAction(QIcon.fromTheme('process-stop'), _('Cancel downloading'), self._stop).setEnabled(self._downloading) menu.addAction(QIcon.fromTheme('list-remove'), _('Remove From List'), self._clear).setEnabled(not self._downloading) if self._downloading or self._ui.downloadInfo.text().startswith(_('Cancelled')) or \ self._ui.downloadInfo.text().startswith(_('Error')): menu.actions()[0].setEnabled(False) menu.exec_(self.mapToGlobal(pos)) def _clear(self): self.deleteItem.emit(self) def _copyDownloadLink(self): url = self._downUrl.toString() print(url) QApplication.clipboard().setText(url) # private: def _updateDownloadInfo(self, currSpeed, received, total): ''' @param: currSpeed double @param: received qint64 @param: total qint64 ''' if self.DEBUG: print('DEBUG: %s::_updateDownloadInfo %s %s %s' % (self.__class__.__name__, currSpeed, received, total)) # QString QString QString QString # | m_remTime | |m_currSize| |m_fileSize| |m_speed| # Remaining 26 minutes - 339MB of 693 MB (350kB/s) if currSpeed == 0: currSpeed = 1 estimatedTime = ((total - received) / 1024) / (currSpeed / 1024) speed = self.currentSpeedToString(currSpeed) # We have QString speed now time = QTime(0, 0, 0) time = time.addSecs(estimatedTime) remTime = self.remaingTimeToString(time) self._remTime = time currSize = gVar.appTools.fileSizeToString(received) fileSize = gVar.appTools.fileSizeToString(total) if fileSize == _('Unkown size'): self._ui.downloadInfo.setText( _('%s - unkown size (%s)') % (currSize, speed)) else: self._ui.downloadInfo.setText( _('Remaining %s - %s of %s (%s)') % (remTime, currSize, fileSize, speed)) def mouseDoubleClickEvent(self, event): ''' @param: event QMouseEvent ''' self.__openFile() event.accept()
class guiApp(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.video_path = '2019-05-06-10-45-16-tv_30_tnf.avi' self.video_capturer = cv2.VideoCapture(self.video_path) self.video_status = 'Video is not playing' self.width = int(self.video_capturer.get(cv2.CAP_PROP_FRAME_WIDTH)) self.height = int(self.video_capturer.get(cv2.CAP_PROP_FRAME_HEIGHT)) self.out = cv2.VideoWriter(self.video_path[:-4] + '_label.avi', cv2.VideoWriter_fourcc(*'XVID'), 25.0, (self.width, self.height)) self.video_frame = None self.video_src = 'camera' self.proc_image_width = 960 self.proc_image_height = 540 self.proc_qimage = QImage() self.proc_qpixmap = QPixmap() self.tmr = QTimer(self) self.tmr.setInterval(40) self.tmr.timeout.connect(self.timeout_slot) self.tmr.start() self.time = QTime() self.time.start() self.fps_period = None self.last_timestamp = self.time.elapsed() self.enable_detector = False self.enable_detector_yolo = False self.enable_playing = False self.enable_record = False self.cnn_model_path = 'output_models/frozen_inference_graph.pb' self.cfg_yolo_path = 'output_modelsgoit/yolov2.cfg' self.weights_yolo_path = 'output_models/yolov2_last.weights' self.ssd = None self.yolo = None self.camera_id = 0 self.camera_capturer = cv2.VideoCapture(self.camera_id) self.camera_status = 'Stream is non active' self.camera_frame = None self.setWindowTitle('SKL CNN Classifier') self.checkBox_enable_detection.toggled.connect( self.checkbox_enable_detection_toggled) self.checkBox_enable_playing.toggled.connect( self.checkbox_enable_playing_toggled) self.checkBox_enable_camera.toggled.connect( self.checkbox_enable_camera_toggled) self.checkBox_enable_detection_yolo.toggled.connect( self.checkBox_enable_detection_yolo_toggled) self.checkBox_enable_record.toggled.connect( self.checkBox_enable_record_toggled) self.lineEdit_path_video.editingFinished.connect( self.lineedit_path_video_editing_finished) self.lineEdit_path_graph.editingFinished.connect( self.lineedit_path_graph_editing_finished) self.lineEdit_path_cfg_yolo.editingFinished.connect( self.lineedit_path_cfg_yolo_editing_finished) self.lineEdit_path_weight_yolo.editingFinished.connect( self.lineedit_path_weight_yolo_editing_finished) self.pushButton_load_video.clicked.connect( self.pushbutton_load_video_clicked) self.pushButton_load_graph.clicked.connect( self.pushbutton_load_graph_clicked) self.pushButton_load_cdg_yolo.clicked.connect( self.pushButton_load_cdg_yolo_clicked) self.pushButton_load_weights_yolo.clicked.connect( self.pushButton_load_weights_yolo_clicked) self.lineEdit_path_video.setText(self.video_path) self.lineEdit_path_graph.setText(self.cnn_model_path) self.lineEdit_path_cfg_yolo.setText(self.cfg_yolo_path) self.lineEdit_path_weight_yolo.setText(self.weights_yolo_path) self.checkBox_enable_camera.setChecked(True) pass def timeout_slot(self): if self.video_src == 'camera': self.refresh_camera_frame() self.proc_frame = self.camera_frame if self.video_src == 'video': self.refresh_video_frame() self.proc_frame = self.video_frame if self.proc_frame is not None: if self.enable_detector: cropimg = self.proc_frame[ 0:self.proc_frame.shape[0], int((self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2):int((self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), :] ssd_image = self.ssd.forwardpass(cropimg) self.proc_frame[0:self.proc_frame.shape[0], int((self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2):int((self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), :] = ssd_image cv2.rectangle(self.proc_frame, (int( (self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2), 0), (int( (self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), self.proc_frame.shape[0]), (255, 0, 0), 2) elif self.enable_detector_yolo: cropimg = self.proc_frame[ 0:self.proc_frame.shape[0], int((self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2):int((self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), :] yolo_image = self.yolo.detect_by_yolo(cropimg) self.proc_frame[0:self.proc_frame.shape[0], int((self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2):int((self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), :] = yolo_image cv2.rectangle(self.proc_frame, (int( (self.proc_frame.shape[1] - self.proc_frame.shape[0]) / 2), 0), (int( (self.proc_frame.shape[1] + self.proc_frame.shape[0]) / 2), self.proc_frame.shape[0]), (255, 0, 0), 2) if self.enable_record: self.out.write(cv2.cvtColor(self.proc_frame, cv2.COLOR_RGB2BGR)) self.proc_frame = cv2.resize( self.proc_frame, (self.proc_image_width, self.proc_image_height), interpolation=cv2.INTER_CUBIC) self.proc_qimage = convert_ndarray_to_qimg(self.proc_frame) self.proc_qpixmap = QPixmap.fromImage(self.proc_qimage) if self.proc_qpixmap is not None: self.label_image.setPixmap(self.proc_qpixmap) cur_time = self.time.elapsed() self.fps_period = cur_time - self.last_timestamp self.last_timestamp = cur_time self.label_processing_time.setText(str(self.fps_period)) self.label_fps.setText(str(int(1000.0 / self.fps_period))) pass def refresh_camera_frame(self): ret, self.camera_frame = self.camera_capturer.read() if self.camera_frame is not None: self.camera_frame = cv2.cvtColor(self.camera_frame, cv2.COLOR_BGR2RGB) self.camera_status = 'Capturing in progress' else: self.camera_status = 'Error' pass def refresh_camera_stream(self): self.camera_capturer.release() self.camera_capturer = cv2.VideoCapture(self.camera_id) pass def refresh_video_frame(self): ret, self.video_frame = self.video_capturer.read() if self.video_frame is not None: self.video_frame = cv2.cvtColor(self.video_frame, cv2.COLOR_BGR2RGB) self.video_status = 'Playing in progress' else: self.video_status = 'Error' self.label_video_status.setText(self.video_status) pass def refresh_video_stream(self): self.video_capturer.release() self.video_capturer = cv2.VideoCapture(self.video_path) def lineedit_path_video_editing_finished(self): self.video_path = self.lineEdit_path_video.text() self.width = int(self.video_capturer.get(cv2.CAP_PROP_FRAME_WIDTH)) self.height = int(self.video_capturer.get(cv2.CAP_PROP_FRAME_HEIGHT)) self.out = cv2.VideoWriter(self.video_path[:-4] + '_label.avi', cv2.VideoWriter_fourcc(*'XVID'), 25.0, (self.width, self.height)) self.refresh_video_stream() pass def lineedit_path_graph_editing_finished(self): self.cnn_model_path = self.lineEdit_path_graph.text() pass def lineedit_path_cfg_yolo_editing_finished(self): self.cfg_yolo_path = self.lineEdit_path_cfg_yolo.text() pass def lineedit_path_weight_yolo_editing_finished(self): self.weights_yolo_path = self.lineEdit_path_weight_yolo.text() pass def checkbox_enable_detection_toggled(self, checked): if self.ssd is not tf_classifier: self.ssd = tf_classifier() self.ssd.select_path_to_model(self.cnn_model_path) self.enable_detector = checked pass def checkBox_enable_detection_yolo_toggled(self, checked): if self.yolo is not df_classifier: self.yolo = df_classifier() self.yolo.select_path_to_model(self.cfg_yolo_path, self.weights_yolo_path) self.enable_detector_yolo = checked pass def checkbox_enable_camera_toggled(self, checked): if checked: self.video_src = 'camera' else: self.video_src = 'none' self.switch_video_src(self.video_src) pass def checkbox_enable_playing_toggled(self, checked): if checked: self.video_src = 'video' else: self.video_src = 'none' self.switch_video_src(self.video_src) pass def checkBox_enable_record_toggled(self, checked): self.enable_record = checked pass def switch_video_src(self, new_src): if new_src == 'camera': self.checkBox_enable_playing.setChecked(False) self.checkBox_enable_camera.setChecked(True) elif new_src == 'video': self.checkBox_enable_playing.setChecked(True) self.checkBox_enable_camera.setChecked(False) else: self.checkBox_enable_playing.setChecked(False) self.checkBox_enable_camera.setChecked(False) pass def pushbutton_load_video_clicked(self): fname = QFileDialog.getOpenFileName(self, 'Select video', '')[0] self.lineEdit_path_video.setText(fname) self.video_path = self.lineEdit_path_video.text() self.refresh_video_stream() pass def pushbutton_load_graph_clicked(self): fname = QFileDialog.getOpenFileName(self, 'Select graph SSD', '')[0] self.lineEdit_path_graph.setText(fname) pass def pushButton_load_cdg_yolo_clicked(self): fname = QFileDialog.getOpenFileName(self, 'Select cfg Yolo', '')[0] self.lineEdit_path_cfg_yolo.setText(fname) pass def pushButton_load_weights_yolo_clicked(self): fname = QFileDialog.getOpenFileName(self, 'Select weights Yolo', '')[0] self.lineEdit_path_weight_yolo.setText(fname) pass
class BookmarkItem(object): # enum Type Root = 0 Url = 1 Folder = 2 Separator = 3 Invalid = 4 TYPE_STR_CHOICES = ( (Url, 'url'), (Folder, 'folder'), (Separator, 'separator'), ) def __init__(self, type_, parent=None): self._type = type_ self._parent = None # BookmarkItem self._children = [] # QList<BookmarkItem> self._url = QUrl() self._title = '' self._description = '' self._keyword = '' self._icon = QIcon() self._iconTime = QTime() self._visitCount = 0 self._expanded = False self._sidebarExpanded = False if parent: parent.addChild(self) assert (self._parent == parent) def type(self): return self._type def setType(self, type_): self._type = type_ def isFolder(self): return self._type == self.Folder def isUrl(self): return self._type == self.Url def isSeparator(self): return self._type == self.Separator def parent(self): ''' @return: BookmarkItem ''' return self._parent def children(self): ''' @return: QList<BookmarkItem> ''' return self._children def icon(self): ''' @return: QIcon ''' # Cache icon for 20 seconds iconCacheTime = 20 * 1000 if self._type == self.Url: if self._iconTime.isNull( ) or self._iconTime.elapsed() > iconCacheTime: self._icon = IconProvider.iconForUrl(self._url) self._iconTime.restart() return self._icon elif self._type == self.Folder: return IconProvider.standardIcon(QStyle.SP_DirIcon) else: return QIcon() def setIcon(self, icon): self._icon = icon def urlString(self): return self._url.toEncoded().data().decode() def url(self): ''' @return: QUrl ''' return self._url def setUrl(self, url): ''' @param: url QUrl ''' self._url = url def title(self): ''' @return: QString ''' return self._title def setTitle(self, title): ''' @param: title QString ''' self._title = title def description(self): return self._description def setDescription(self, description): self._description = description def keyword(self): return self._keyword def setKeyword(self, keyword): self._keyword = keyword def visitCount(self): ''' @return: int ''' return self._visitCount def setVisitCount(self, count): self._visitCount = count def updateVisitCount(self): ''' @brief: Increments visitCount() (may also update last load time when implemented) ''' self._visitCount += 1 def isExpanded(self): if self._type == self.Root: return True return self._expanded def setExpanded(self, expanded): self._expanded = expanded def isSidebarExpanded(self): ''' @brief: Expanded state in Sidebar ''' if self._type == self.Root: return True else: return self._sidebarExpanded def setSidebarExpanded(self, expanded): self._sidebarExpanded = expanded def addChild(self, child, index=-1): ''' @param: child BookmarkItem ''' if child._parent: child._parent.removeChild(child) child._parent = self if index < 0: self._children.append(child) else: self._children.insert(index, child) def removeChild(self, child): ''' @param: child BookmarkItem ''' child._parent = None self._children.remove(child) @classmethod def typeFromString(cls, string): ''' @param: string QString @return: Type(enum int) ''' for type_, str_ in cls.TYPE_STR_CHOICES: if string == str_: return type_ else: return cls.Invalid @classmethod def typeToString(cls, type_): ''' @parma: type_ Type(enum int) @return: QString ''' for type0, str_ in cls.TYPE_STR_CHOICES: if type0 == type_: return str_ else: return 'invalid'