def __init__(self): super().__init__() self.statusBar = QStatusBar() self.restartProcessButton = QPushButton('START Myo Connect') self.iconLabel = QLabel() self.informationLabel = QLabel( 'App current information is displayed here...') self.left = int(self.screen().size().width() / 4) self.top = int(self.screen().size().height() / 4) self.width = 640 self.height = 450 self.title = 'Myo Exercises' if MyoService.check_if_process_running(): print("Myo Connect is running!") self.classifyExercises = ClassifyExercises( # subject="Ervin", # nr_of_samples=number_of_samples, epochs=300, # nr_of_gestures=4, exercises=PREDEFINED_EXERCISES, # batch_size=50, training_batch_size=16) else: self.classifyExercises = None # self.informationLabel.setText('Myo Connect is not running! Please start process.') self.table_widget = MainTabWidget(self) self.initUI() self.setStyleSheet("background-color: white;")
def create_widgets(self): self.windows = set() self.gallery = Gallery(self) self.preview = Preview(self, 'white') self.layout.addWidget(self.gallery) self.layout.addWidget(self.preview) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.setFixedHeight(25)
def __init__(self, downloads_indicator, parent=None): QStatusBar.__init__(self, parent) self.setMaximumHeight(STATUS_BAR_HEIGHT) self.setMinimumHeight(STATUS_BAR_HEIGHT) self.sb_background = 'status bar private background' if getattr( parent, 'is_private', False) else 'status bar background' if parent: f = parent.font() f.setPixelSize(min(f.pixelSize(), self.maximumHeight() - 4)) self.setFont(f) self.status_msg = Status(self) self.status_msg.hidden.connect(self.search_bar_hidden) self.status_msg.search.edit.do_search.connect(self.do_search) self.show_search = self.status_msg.show_search self.show_message = self.status_msg.show_message self.set_permanent_message = self.status_msg self.addWidget(self.status_msg) self.mode_label = ModeLabel() self.update_mode = self.mode_label.update_mode self.passthrough_button = PassthroughButton(self) self.passthrough_button.toggled.connect(self.change_passthrough) self.update_passthrough_state = self.passthrough_button.update_state self.addPermanentWidget(self.mode_label) self.addPermanentWidget(downloads_indicator) self.addPermanentWidget(self.passthrough_button) self.setStyleSheet(''' QStatusBar { color: FG; background: BG; } QStatusBar QLabel { color: FG; background: BG; } '''.replace('FG', color('status bar foreground', 'palette(window-text)')).replace( 'BG', color(self.sb_background, 'palette(window)')))
def setUpMainWindow(self): """Create and arrange widgets in the main window.""" # Create the container widget for each of the pages # in the tab widget self.customer_tab = QWidget() self.orders_tab = QWidget() self.category_tab = QWidget() self.products_tab = QWidget() # Add or insert the tabs into the tab widget self.tabs = QTabWidget() self.tabs.setDocumentMode(True) self.tabs.addTab(self.customer_tab, "Customers") self.tabs.addTab(self.orders_tab, "Orders") self.tabs.addTab(self.category_tab, "Categories") self.tabs.addTab(self.products_tab, "Products") if self.admin_or_not == 1: self.staff_tab = QWidget() self.tabs.insertTab(0, self.staff_tab, "Staff") self.createStaffTab() self.tabs.setCurrentIndex(1) # Set tab to Customers tab self.tabs.currentChanged.connect(self.updateWidgetsAndStates) # Call the methods to construct each page self.createCustomersTab() self.createOrdersTab() self.createCategoriesTab() self.createProductsTab() # Create the widgets in the sidebar for filtering table content self.table_name_label = QLabel("<b>Customers</b>") self.table_name_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.filter_pattern_line = QLineEdit() self.filter_pattern_line.setClearButtonEnabled(True) self.filter_pattern_line.textChanged.connect(self.filterRegExpChanged) self.filter_regex_combo = QComboBox() filter_options = ["Default", "Wildcard", "Fixed String"] self.filter_regex_combo.addItems(filter_options) self.filter_regex_combo.currentIndexChanged.connect( self.filterRegExpChanged) self.filter_field_combo = QComboBox() self.updateWidgetsAndStates( 1) # Initialize the values in filter_field_combo self.filter_field_combo.currentIndexChanged.connect( self.selectTableColumn) filter_case_sensitivity_cb = QCheckBox("Filter with Case Sensitivity") filter_case_sensitivity_cb.toggled.connect(self.toggleCaseSensitivity) filter_case_sensitivity_cb.toggle() # Layout for the sidebar filter_v_box = QVBoxLayout() filter_v_box.addWidget(self.table_name_label) filter_v_box.addWidget(QLabel("Filter Pattern")) filter_v_box.addWidget(self.filter_pattern_line) filter_v_box.addWidget(QLabel("Filter filter")) filter_v_box.addWidget(self.filter_regex_combo) filter_v_box.addWidget(QLabel("Select Table Column")) filter_v_box.addWidget(self.filter_field_combo) filter_v_box.addWidget(filter_case_sensitivity_cb) filter_v_box.addStretch(2) self.filter_group = QGroupBox("Filtering") self.filter_group.setMaximumWidth(260) self.filter_group.setLayout(filter_v_box) # Arrange the containers in the main window main_h_box = QHBoxLayout() main_h_box.addWidget(self.tabs) main_h_box.addWidget(self.filter_group) main_container = QWidget() main_container.setLayout(main_h_box) self.setCentralWidget(main_container) # Create status bar self.setStatusBar(QStatusBar())
def __init__(self): super().__init__() # setup some flags self.isFetching = False self.isDownloading = False # default output path self.outputPath = f'{QDir.homePath()}/videos' # setup some window specific things self.setWindowTitle('YouTube Downloader') self.setWindowIcon(QIcon('assets/yt-icon.ico')) self.setFixedSize(705, 343) # parent layout layout = QVBoxLayout() layout.setContentsMargins(15, 15, 15, 10) self.setLayout(layout) # top bar layout topBar = QHBoxLayout() # detail section detailSec = QHBoxLayout() metaSec = QVBoxLayout() # download section downloadSec = QHBoxLayout() downloadBtn = QVBoxLayout() # output path link button self.outputBtn = QPushButton('📂 Output Path') self.outputBtn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.outputBtn.setToolTip(self.outputPath) self.outputBtn.clicked.connect(self.setOutputPath) # status bar self.statusBar = QStatusBar() # message box self.message = QMessageBox() # setting up widgets self.urlBox = QLineEdit() self.urlBox.setFocusPolicy(Qt.FocusPolicy.ClickFocus or Qt.FocusPolicy.NoFocus) self.urlBox.setPlaceholderText('🔍 Enter or paste video URL...') self.button = QPushButton('Get') self.button.setDefault(True) self.button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button.clicked.connect(self.getDetails) # thumbnail pixmap = QPixmap('assets\placeholder.jpg') self.thumb = QLabel() self.thumb.setFixedSize(250, 141) self.thumb.setScaledContents(True) self.thumb.setPixmap(pixmap) # detail widgets self.title = QLabel('Title: ') self.author = QLabel('Author: ') self.length = QLabel('Duration: ') self.publish_date = QLabel('Published: ') # progress bar self.progress_bar = QProgressBar() # download options self.download = QComboBox() self.download.setPlaceholderText('Download Video') self.download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download.activated.connect(lambda: self.getContent(0)) self.download.setEnabled(False) # download audio button self.download_audio = QPushButton('Download Audio') self.download_audio.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download_audio.clicked.connect(lambda: self.getContent(1)) self.download_audio.setEnabled(False) # add widgets and layouts topBar.addWidget(self.urlBox) topBar.addWidget(self.button) # detail section metaSec.addWidget(self.title) metaSec.addWidget(self.author) metaSec.addWidget(self.length) metaSec.addWidget(self.publish_date) detailSec.addWidget(self.thumb) detailSec.addSpacing(20) detailSec.addLayout(metaSec) # download section downloadBtn.addWidget(self.download) downloadBtn.addWidget(self.download_audio) downloadSec.addWidget(self.progress_bar) downloadSec.addSpacing(10) downloadSec.addLayout(downloadBtn) # status bar self.statusBar.setSizeGripEnabled(False) self.statusBar.addPermanentWidget(self.outputBtn) # add content to parent layout layout.addLayout(topBar) layout.addSpacing(20) layout.addLayout(detailSec) layout.addSpacing(5) layout.addLayout(downloadSec) layout.addWidget(self.statusBar) # setup a connection thread to keep checking internet connectivity self.connection = ConnectionThread() self.connection.start() # catch the connection response signal self.connection.con_response.connect(self.connection_slot)
class YTdownloader(QWidget): def __init__(self): super().__init__() # setup some flags self.isFetching = False self.isDownloading = False # default output path self.outputPath = f'{QDir.homePath()}/videos' # setup some window specific things self.setWindowTitle('YouTube Downloader') self.setWindowIcon(QIcon('assets/yt-icon.ico')) self.setFixedSize(705, 343) # parent layout layout = QVBoxLayout() layout.setContentsMargins(15, 15, 15, 10) self.setLayout(layout) # top bar layout topBar = QHBoxLayout() # detail section detailSec = QHBoxLayout() metaSec = QVBoxLayout() # download section downloadSec = QHBoxLayout() downloadBtn = QVBoxLayout() # output path link button self.outputBtn = QPushButton('📂 Output Path') self.outputBtn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.outputBtn.setToolTip(self.outputPath) self.outputBtn.clicked.connect(self.setOutputPath) # status bar self.statusBar = QStatusBar() # message box self.message = QMessageBox() # setting up widgets self.urlBox = QLineEdit() self.urlBox.setFocusPolicy(Qt.FocusPolicy.ClickFocus or Qt.FocusPolicy.NoFocus) self.urlBox.setPlaceholderText('🔍 Enter or paste video URL...') self.button = QPushButton('Get') self.button.setDefault(True) self.button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.button.clicked.connect(self.getDetails) # thumbnail pixmap = QPixmap('assets\placeholder.jpg') self.thumb = QLabel() self.thumb.setFixedSize(250, 141) self.thumb.setScaledContents(True) self.thumb.setPixmap(pixmap) # detail widgets self.title = QLabel('Title: ') self.author = QLabel('Author: ') self.length = QLabel('Duration: ') self.publish_date = QLabel('Published: ') # progress bar self.progress_bar = QProgressBar() # download options self.download = QComboBox() self.download.setPlaceholderText('Download Video') self.download.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download.activated.connect(lambda: self.getContent(0)) self.download.setEnabled(False) # download audio button self.download_audio = QPushButton('Download Audio') self.download_audio.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download_audio.clicked.connect(lambda: self.getContent(1)) self.download_audio.setEnabled(False) # add widgets and layouts topBar.addWidget(self.urlBox) topBar.addWidget(self.button) # detail section metaSec.addWidget(self.title) metaSec.addWidget(self.author) metaSec.addWidget(self.length) metaSec.addWidget(self.publish_date) detailSec.addWidget(self.thumb) detailSec.addSpacing(20) detailSec.addLayout(metaSec) # download section downloadBtn.addWidget(self.download) downloadBtn.addWidget(self.download_audio) downloadSec.addWidget(self.progress_bar) downloadSec.addSpacing(10) downloadSec.addLayout(downloadBtn) # status bar self.statusBar.setSizeGripEnabled(False) self.statusBar.addPermanentWidget(self.outputBtn) # add content to parent layout layout.addLayout(topBar) layout.addSpacing(20) layout.addLayout(detailSec) layout.addSpacing(5) layout.addLayout(downloadSec) layout.addWidget(self.statusBar) # setup a connection thread to keep checking internet connectivity self.connection = ConnectionThread() self.connection.start() # catch the connection response signal self.connection.con_response.connect(self.connection_slot) # connection slot def connection_slot(self, status): curMsg = self.statusBar.currentMessage() # connection succeeded if status: if curMsg == '🔴 Disconnected': self.statusBar.showMessage('🟢 Connection restored!', 3000) elif curMsg != '🟢 Connected': self.statusBar.showMessage('🟢 Connected') # connection failed elif curMsg == '🟢 Connected': self.statusBar.showMessage('🔴 Connection interrupted!', 3000) elif curMsg != '🔴 Disconnected': self.statusBar.showMessage('🔴 Disconnected') # set output path slot def setOutputPath(self): # update the output path path = str(QFileDialog.getExistingDirectory(self, "Select Output Directory")) if path: self.outputPath = path # update tooltip self.outputBtn.setToolTip(path) # get button slot def getDetails(self): curMsg = self.statusBar.currentMessage() if curMsg == '🔴 Disconnected' or curMsg == '🔴 Connection interrupted!': self.message.critical( self, 'Error', 'Connection failed!\nAre you sure you\'re connected to the internet ? ' ) elif self.button.text() == 'Get': self.button.setText('Stop') # indicate progress bar as busy self.progress_bar.setRange(0, 0) # set fetching flag self.isFetching = True # setup a worker thread to keep UI responsive self.worker = WorkerThread(self.urlBox.text()) self.worker.start() # catch the finished signal self.worker.finished.connect(self.finished_slot) # catch the response signal self.worker.worker_response.connect(self.response_slot) # catch the error signal self.worker.worker_err_response.connect(self.err_slot) elif self.button.text() == 'Stop': if self.isFetching: # stop worker thread self.worker.terminate() # set back the button text self.button.setText('Get') elif self.isDownloading: # stop download thread self.download_thread.terminate() # show the warning message self.message.information( self, 'Interrupted', 'Download interrupted!\nThe process was aborted while the file was being downloaded... ' ) # reset pogress bar self.progress_bar.reset() # download options slot def getContent(self, id): if self.isFetching: # show the warning message self.message.warning( self, 'Warning', 'Please wait!\nWait while the details are being fetched... ' ) else: # disable the download options self.download.setDisabled(True) self.download_audio.setDisabled(True) # set downloading flag self.isDownloading = True # set button to stop self.button.setText('Stop') # setup download thread if id == 0: self.download_thread = DownloadThread(self.yt, self.download.currentText()[:4], self.outputPath) else: self.download_thread = DownloadThread(self.yt, 'audio', self.outputPath) # start the thread self.download_thread.start() # catch the finished signal self.download_thread.finished.connect(self.download_finished_slot) # catch the response signal self.download_thread.download_response.connect(self.download_response_slot) # catch the complete signal self.download_thread.download_complete.connect(self.download_complete_slot) # catch the error signal self.download_thread.download_err.connect(self.download_err_slot) # finished slot def finished_slot(self): # remove progress bar busy indication self.progress_bar.setRange(0, 100) # unset fetching flag self.isFetching = False # response slot def response_slot(self, res): # set back the button text self.button.setText('Get') # save the yt object for speeding up download self.yt = res[0] # set the actual thumbnail of requested video self.thumb.setPixmap(res[1]) # slice the title if it is more than the limit if len(res[2]) > 50: self.title.setText(f'Title: {res[2][:50]}...') else: self.title.setText(f'Title: {res[2]}') # set leftover details self.author.setText(f'Author: {res[3]}') self.length.setText(f'Duration: {timedelta(seconds=res[4])}') self.publish_date.setText(f'Published: {res[5].strftime("%d/%m/%Y")}') # clear any previous items if any self.download.clear() # add resolutions as items to the download button and enable them self.download.addItems([item for item in res[6]]) self.download.setDisabled(False) self.download_audio.setDisabled(False) # error slot def err_slot(self): # show the warning message self.message.warning( self, 'Warning', 'Something went wrong!\nProbably a broken link or some restricted content... ' ) # set back the button text self.button.setText('Get') # download finished slot def download_finished_slot(self): # set back the button text self.button.setText('Get') # now enable the download options self.download.setDisabled(False) self.download_audio.setDisabled(False) # unset downloading flag self.isDownloading = False # reset pogress bar self.progress_bar.reset() # download response slot def download_response_slot(self, per): # update progress bar self.progress_bar.setValue(per) # adjust the font color to maintain the contrast if per > 52: self.progress_bar.setStyleSheet('QProgressBar { color: #fff }') else: self.progress_bar.setStyleSheet('QProgressBar { color: #000 }') # download complete slot def download_complete_slot(self, location): # use native separators location = QDir.toNativeSeparators(location) # show the success message if self.message.information( self, 'Downloaded', f'Download complete!\nFile was successfully downloaded to :\n{location}\n\nOpen the downloaded file now ?', QMessageBox.StandardButtons.Open, QMessageBox.StandardButtons.Cancel ) is QMessageBox.StandardButtons.Open: subprocess.Popen(f'explorer /select,{location}') # download error slot def download_err_slot(self): # show the error message self.message.critical( self, 'Error', 'Error!\nSomething unusual happened and was unable to download...' )
def __init__(self): super(B23Download, self).__init__() # setup some flags self.is_fetching = False self.is_downloading = False # default output path basepath = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(basepath, "videos") self.output_path = path # setup some window specific things self.setWindowTitle("Bilibili Favorite Downloader") self.setWindowIcon(QIcon("images/icon_bilibili.ico")) self.setFixedSize(705, 343) # parent layout main_layout = QVBoxLayout() main_layout.setContentsMargins(15, 15, 15, 10) self.setLayout(main_layout) # top bar layout top_layout = QHBoxLayout() # detail section mid_main_layout = QHBoxLayout() mid_right_layout = QVBoxLayout() # download section bottom_main_layout = QHBoxLayout() bottom_right_layout = QVBoxLayout() # output path link button self.output_btn = QPushButton("📂 Output Path") self.output_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.output_btn.setToolTip(self.output_path) self.output_btn.clicked.connect(self.set_output_path) # status bar self.status_bar = QStatusBar() # message box self.message_box = QMessageBox() # setting up widgets self.url_edit = QLineEdit() self.url_edit.setPlaceholderText("🔍 Enter or paste favorite URL...") self.get_btn = QPushButton("Get") self.get_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.get_btn.clicked.connect(self.get_details) # thumbnail pixmap = QPixmap("images/placeholder.png") self.thumb = QLabel() self.thumb.setFixedSize(250, 141) self.thumb.setScaledContents(True) self.thumb.setPixmap(pixmap) # detail widgets self.title = QLabel("Title: ") self.author = QLabel("Author: ") self.length = QLabel("Videos: ") self.publish_date = QLabel("Published: ") # progress bar self.progress_bar = QProgressBar() # download options self.download_btn = QPushButton(" Download Videos ") self.download_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download_btn.clicked.connect(self.get_content) self.download_btn.setEnabled(False) self.download_btn.setShortcut("Ctrl+Return") self.download_btn.setMinimumWidth(200) # add widgets and layouts top_layout.addWidget(self.url_edit) top_layout.addWidget(self.get_btn) # detail section mid_right_layout.addWidget(self.title) mid_right_layout.addWidget(self.author) mid_right_layout.addWidget(self.length) mid_right_layout.addWidget(self.publish_date) mid_main_layout.addWidget(self.thumb) mid_main_layout.addSpacing(20) mid_main_layout.addLayout(mid_right_layout) # download section bottom_right_layout.addWidget(self.download_btn) bottom_main_layout.addWidget(self.progress_bar) bottom_main_layout.addSpacing(10) bottom_main_layout.addLayout(bottom_right_layout) # status bar self.status_bar.setSizeGripEnabled(False) self.status_bar.addPermanentWidget(self.output_btn) # add content to parent layout main_layout.addLayout(top_layout) main_layout.addSpacing(20) main_layout.addLayout(mid_main_layout) main_layout.addSpacing(5) main_layout.addLayout(bottom_main_layout) main_layout.addWidget(self.status_bar)
class B23Download(QWidget): def __init__(self): super(B23Download, self).__init__() # setup some flags self.is_fetching = False self.is_downloading = False # default output path basepath = os.path.dirname(os.path.abspath(__file__)) path = os.path.join(basepath, "videos") self.output_path = path # setup some window specific things self.setWindowTitle("Bilibili Favorite Downloader") self.setWindowIcon(QIcon("images/icon_bilibili.ico")) self.setFixedSize(705, 343) # parent layout main_layout = QVBoxLayout() main_layout.setContentsMargins(15, 15, 15, 10) self.setLayout(main_layout) # top bar layout top_layout = QHBoxLayout() # detail section mid_main_layout = QHBoxLayout() mid_right_layout = QVBoxLayout() # download section bottom_main_layout = QHBoxLayout() bottom_right_layout = QVBoxLayout() # output path link button self.output_btn = QPushButton("📂 Output Path") self.output_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.output_btn.setToolTip(self.output_path) self.output_btn.clicked.connect(self.set_output_path) # status bar self.status_bar = QStatusBar() # message box self.message_box = QMessageBox() # setting up widgets self.url_edit = QLineEdit() self.url_edit.setPlaceholderText("🔍 Enter or paste favorite URL...") self.get_btn = QPushButton("Get") self.get_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.get_btn.clicked.connect(self.get_details) # thumbnail pixmap = QPixmap("images/placeholder.png") self.thumb = QLabel() self.thumb.setFixedSize(250, 141) self.thumb.setScaledContents(True) self.thumb.setPixmap(pixmap) # detail widgets self.title = QLabel("Title: ") self.author = QLabel("Author: ") self.length = QLabel("Videos: ") self.publish_date = QLabel("Published: ") # progress bar self.progress_bar = QProgressBar() # download options self.download_btn = QPushButton(" Download Videos ") self.download_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) self.download_btn.clicked.connect(self.get_content) self.download_btn.setEnabled(False) self.download_btn.setShortcut("Ctrl+Return") self.download_btn.setMinimumWidth(200) # add widgets and layouts top_layout.addWidget(self.url_edit) top_layout.addWidget(self.get_btn) # detail section mid_right_layout.addWidget(self.title) mid_right_layout.addWidget(self.author) mid_right_layout.addWidget(self.length) mid_right_layout.addWidget(self.publish_date) mid_main_layout.addWidget(self.thumb) mid_main_layout.addSpacing(20) mid_main_layout.addLayout(mid_right_layout) # download section bottom_right_layout.addWidget(self.download_btn) bottom_main_layout.addWidget(self.progress_bar) bottom_main_layout.addSpacing(10) bottom_main_layout.addLayout(bottom_right_layout) # status bar self.status_bar.setSizeGripEnabled(False) self.status_bar.addPermanentWidget(self.output_btn) # add content to parent layout main_layout.addLayout(top_layout) main_layout.addSpacing(20) main_layout.addLayout(mid_main_layout) main_layout.addSpacing(5) main_layout.addLayout(bottom_main_layout) main_layout.addWidget(self.status_bar) # set output path slot def set_output_path(self): # update the output path path = str( QFileDialog.getExistingDirectory(self, "Select Output Directory")) if path: self.output_path = path # update tooltip self.output_btn.setToolTip(path) # get button slot def get_details(self): text = self.url_edit.text().strip() if not text: return if text.find("fid") < 0: self.message_box.warning( self, "Error", ("Input a correct favorite URL!\n" "For example: https://space.bilibili.com/xxx/favlist?fid=xxx..." ), ) return if self.get_btn.text() == "Get": self.get_btn.setText("Stop") # indicate progress bar as busy self.progress_bar.setRange(0, 0) # set fetching flag self.is_fetching = True # setup a worker thread to keep UI responsive self.media_id = text.split("fid=")[-1].split("&")[0] self.worker = WorkerThread(self.media_id) self.worker.start() # catch the finished signal self.worker.finished.connect(self.finished_slot) # catch the response signal self.worker.worker_response.connect(self.response_slot) # catch the error signal self.worker.worker_err_response.connect(self.err_slot) elif self.get_btn.text() == "Stop": if self.is_fetching: # stop worker thread self.worker.terminate() # set back the get_btn text self.get_btn.setText("Get") elif self.is_downloading: # stop download thread self.download_thread.terminate() # show the warning message_box self.message_box.information( self, "Interrupted", "Download interrupted!\nThe process was aborted while the file was being downloaded... ", ) # reset progress bar self.progress_bar.reset() # download options slot def get_content(self): if self.is_fetching: # show the warning message self.message_box.critical( self, "Error", "Please wait!\nWait while the details are being fetched... ", ) else: # disable the download options self.download_btn.setDisabled(True) # set downloading flag self.is_downloading = True # set button to stop self.get_btn.setText("Stop") self.download_thread = DownloadThread( self.media_id, self.media_counts, self.first_page_medias, self.output_path, ) # start the thread self.download_thread.start() # catch the finished signal self.download_thread.finished.connect(self.download_finished_slot) # catch the response signal self.download_thread.download_response.connect( self.download_response_slot) # catch the complete signal self.download_thread.download_complete.connect( self.download_complete_slot) # catch the error signal self.download_thread.download_err.connect(self.download_err_slot) # handling enter key for get/stop button def keyPressEvent(self, event): self.url_edit.setFocus() if (event.key() == Qt.Key.Key_Enter.value or event.key() == Qt.Key.Key_Return.value): self.get_details() # finished slot def finished_slot(self): # remove progress bar busy indication self.progress_bar.setRange(0, 100) # unset fetching flag self.is_fetching = False # response slot def response_slot(self, res): # set back the button text self.get_btn.setText("Get") # set the actual thumbnail of requested video self.thumb.setPixmap(res.thumb_img) # slice the title if it is more than the limit if len(res.title) > 50: self.title.setText(f"Title: {res.title[:50]}...") else: self.title.setText(f"Title: {res.title}") # cache first page medias self.first_page_medias = res.medias self.media_counts = res.media_counts # set leftover details self.author.setText(f"Author: {res.author}") self.length.setText(f"Videos: {res.media_counts}") self.publish_date.setText( f'Published: {time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(res.publish_date))}' ) self.download_btn.setDisabled(False) # error slot def err_slot(self): # show the warning message self.message_box.warning( self, "Warning", "Something went wrong!\nProbably a broken link or some restricted content... ", ) # set back the button text self.get_btn.setText("Get") # download finished slot def download_finished_slot(self): # set back the button text self.get_btn.setText("Get") # now enable the download options self.download_btn.setDisabled(False) # unset downloading flag self.is_downloading = False # reset pogress bar self.progress_bar.reset() # download response slot def download_response_slot(self, per): # update progress bar self.progress_bar.setValue(per) # adjust the font color to maintain the contrast if per > 52: self.progress_bar.setStyleSheet("QProgressBar { color: #fff }") else: self.progress_bar.setStyleSheet("QProgressBar { color: #000 }") # download complete slot def download_complete_slot(self, location): # use native separators location = QDir.toNativeSeparators(location) # show the success message if (self.message_box.information( self, "Downloaded", f"Download complete!\nFile was successfully downloaded to :\n{location}\n\nOpen the downloaded file now ?", QMessageBox.StandardButtons.Open, QMessageBox.StandardButtons.Cancel, ) is QMessageBox.StandardButtons.Open): subprocess.Popen(f"explorer /select,{location}") # download error slot def download_err_slot(self): # show the error message self.message_box.critical( self, "Error", "Error!\nSomething unusual happened and was unable to download...", )
class ManageData(QMainWindow): populateGallery = pyqtSignal() closedWindow = pyqtSignal(object) def __init__(self): super(ManageData, self).__init__() self.setWindowTitle('Manage Data') self.configure_gui() self.create_widgets() self.create_menu() self.showMaximized() self.mysql = Authenticate() def configure_gui(self): self.center = QWidget(self) self.layout = QHBoxLayout() self.center.setLayout(self.layout) self.setCentralWidget(self.center) self.layout.setContentsMargins(5, 0, 5, 0) self.layout.setSpacing(0) def create_widgets(self): self.windows = set() self.gallery = Gallery(self) self.preview = Preview(self, 'white') self.layout.addWidget(self.gallery) self.layout.addWidget(self.preview) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.setFixedHeight(25) def create_menu(self): pass def keyPressEvent(self, event): key_press = event.key() modifiers = event.modifiers() alt = modifiers == Qt.Modifier.ALT if alt: if key_press == Qt.Key_Left: self.ribbon.go_back() elif key_press == Qt.Key_Right: self.ribbon.go_forward() if key_press == Qt.Key.Key_F4: self.ribbon.tags.setFocus() elif key_press == Qt.Key.Key_F5: self.select_records() elif key_press == Qt.Key.Key_Delete: self.delete_records(self.gallery.selectedIndexes()) elif key_press == Qt.Key.Key_Escape: self.close() def closeEvent(self, event): self.mysql.close() for window in self.windows: window.close() self.closedWindow.emit(self)
def _create_status_bar(self): status = QStatusBar() status.showMessage("Activo") self.setStatusBar(status)
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) layout = QVBoxLayout() self.editor = TextEdit() self.editor.setAutoFormatting(QTextEdit.AutoFormatting.AutoAll) self.editor.selectionChanged.connect(self.update_format) font = QFont("Times", 12) self.editor.setFont(font) self.editor.setFontPointSize(12) self.path = None layout.addWidget(self.editor) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) self.status = QStatusBar() self.setStatusBar(self.status) file_toolbar = QToolBar("File") file_toolbar.setIconSize(QSize(14, 14)) self.addToolBar(file_toolbar) file_menu = self.menuBar().addMenu("&File") open_file_action = QAction( QIcon(os.path.join("images", "blue-folder-open-document.png")), "Open file...", self, ) open_file_action.setStatusTip("Open file") open_file_action.triggered.connect(self.file_open) file_menu.addAction(open_file_action) file_toolbar.addAction(open_file_action) save_file_action = QAction(QIcon(os.path.join("images", "disk.png")), "Save", self) save_file_action.setStatusTip("Save current page") save_file_action.triggered.connect(self.file_save) file_menu.addAction(save_file_action) file_toolbar.addAction(save_file_action) save_as_file_action = QAction( QIcon(os.path.join("images", "disk--pencil.png")), "Save As...", self) save_as_file_action.setStatusTip("Save current page to specified file") save_as_file_action.triggered.connect(self.file_save_as) file_menu.addAction(save_as_file_action) file_toolbar.addAction(save_as_file_action) print_action = QAction(QIcon(os.path.join("images", "printer.png")), "Print...", self) print_action.setStatusTip("Print current page") print_action.triggered.connect(self.file_print) file_menu.addAction(print_action) file_toolbar.addAction(print_action) edit_toolbar = QToolBar("Edit") edit_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(edit_toolbar) edit_menu = self.menuBar().addMenu("&Edit") undo_action = QAction( QIcon(os.path.join("images", "arrow-curve-180-left.png")), "Undo", self) undo_action.setStatusTip("Undo last change") undo_action.triggered.connect(self.editor.undo) edit_menu.addAction(undo_action) redo_action = QAction(QIcon(os.path.join("images", "arrow-curve.png")), "Redo", self) redo_action.setStatusTip("Redo last change") redo_action.triggered.connect(self.editor.redo) edit_toolbar.addAction(redo_action) edit_menu.addAction(redo_action) edit_menu.addSeparator() cut_action = QAction(QIcon(os.path.join("images", "scissors.png")), "Cut", self) cut_action.setStatusTip("Cut selected text") cut_action.setShortcut(QKeySequence.StandardKey.Cut) cut_action.triggered.connect(self.editor.cut) edit_toolbar.addAction(cut_action) edit_menu.addAction(cut_action) copy_action = QAction( QIcon(os.path.join("images", "document-copy.png")), "Copy", self) copy_action.setStatusTip("Copy selected text") cut_action.setShortcut(QKeySequence.StandardKey.Copy) copy_action.triggered.connect(self.editor.copy) edit_toolbar.addAction(copy_action) edit_menu.addAction(copy_action) paste_action = QAction( QIcon(os.path.join("images", "clipboard-paste-document-text.png")), "Paste", self, ) paste_action.setStatusTip("Paste from clipboard") cut_action.setShortcut(QKeySequence.StandardKey.Paste) paste_action.triggered.connect(self.editor.paste) edit_toolbar.addAction(paste_action) edit_menu.addAction(paste_action) select_action = QAction( QIcon(os.path.join("images", "selection-input.png")), "Select all", self) select_action.setStatusTip("Select all text") cut_action.setShortcut(QKeySequence.StandardKey.SelectAll) select_action.triggered.connect(self.editor.selectAll) edit_menu.addAction(select_action) edit_menu.addSeparator() wrap_action = QAction( QIcon(os.path.join("images", "arrow-continue.png")), "Wrap text to window", self, ) wrap_action.setStatusTip("Toggle wrap text to window") wrap_action.setCheckable(True) wrap_action.setChecked(True) wrap_action.triggered.connect(self.edit_toggle_wrap) edit_menu.addAction(wrap_action) format_toolbar = QToolBar("Format") format_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(format_toolbar) format_menu = self.menuBar().addMenu("&Format") self.fonts = QFontComboBox() self.fonts.currentFontChanged.connect(self.editor.setCurrentFont) format_toolbar.addWidget(self.fonts) self.fontsize = QComboBox() self.fontsize.addItems([str(s) for s in FONT_SIZES]) self.fontsize.currentTextChanged[str].connect( lambda s: self.editor.setFontPointSize(float(s))) format_toolbar.addWidget(self.fontsize) self.bold_action = QAction( QIcon(os.path.join("images", "edit-bold.png")), "Bold", self) self.bold_action.setStatusTip("Bold") self.bold_action.setShortcut(QKeySequence.StandardKey.Bold) self.bold_action.setCheckable(True) self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight( QFont.Weight.Bold if x else QFont.Weight.Normal)) format_toolbar.addAction(self.bold_action) format_menu.addAction(self.bold_action) self.italic_action = QAction( QIcon(os.path.join("images", "edit-italic.png")), "Italic", self) self.italic_action.setStatusTip("Italic") self.italic_action.setShortcut(QKeySequence.StandardKey.Italic) self.italic_action.setCheckable(True) self.italic_action.toggled.connect(self.editor.setFontItalic) format_toolbar.addAction(self.italic_action) format_menu.addAction(self.italic_action) self.underline_action = QAction( QIcon(os.path.join("images", "edit-underline.png")), "Underline", self) self.underline_action.setStatusTip("Underline") self.underline_action.setShortcut(QKeySequence.StandardKey.Underline) self.underline_action.setCheckable(True) self.underline_action.toggled.connect(self.editor.setFontUnderline) format_toolbar.addAction(self.underline_action) format_menu.addAction(self.underline_action) format_menu.addSeparator() self.align_left_action = QAction( QIcon(os.path.join("images", "edit-alignment.png")), "Align left", self) self.align_left_action.setStatusTip("Align text left") self.align_left_action.setCheckable(True) self.align_left_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignLeft)) format_toolbar.addAction(self.align_left_action) format_menu.addAction(self.align_left_action) self.align_center_action = QAction( QIcon(os.path.join("images", "edit-alignment-center.png")), "Align center", self, ) self.align_center_action.setStatusTip("Align text center") self.align_center_action.setCheckable(True) self.align_center_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignCenter)) format_toolbar.addAction(self.align_center_action) format_menu.addAction(self.align_center_action) self.align_right_action = QAction( QIcon(os.path.join("images", "edit-alignment-right.png")), "Align right", self, ) self.align_right_action.setStatusTip("Align text right") self.align_right_action.setCheckable(True) self.align_right_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignRight)) format_toolbar.addAction(self.align_right_action) format_menu.addAction(self.align_right_action) self.align_justify_action = QAction( QIcon(os.path.join("images", "edit-alignment-justify.png")), "Justify", self) self.align_justify_action.setStatusTip("Justify text") self.align_justify_action.setCheckable(True) self.align_justify_action.triggered.connect( lambda: self.editor.setAlignment(Qt.Alignment.AlignJustify)) format_toolbar.addAction(self.align_justify_action) format_menu.addAction(self.align_justify_action) format_group = QActionGroup(self) format_group.setExclusive(True) format_group.addAction(self.align_left_action) format_group.addAction(self.align_center_action) format_group.addAction(self.align_right_action) format_group.addAction(self.align_justify_action) format_menu.addSeparator() self._format_actions = [ self.fonts, self.fontsize, self.bold_action, self.italic_action, self.underline_action, ] self.update_format() self.update_title() self.show()
def _createStatusBar(self): status = QStatusBar() status.showMessage("I'm the Status Bar") self.setStatusBar(status)
class HIMOApp(QMainWindow): EXIT_CODE_REBOOT = -12345678 # or whatever number not already taken def __init__(self): super().__init__() self.statusBar = QStatusBar() self.restartProcessButton = QPushButton('START Myo Connect') self.iconLabel = QLabel() self.informationLabel = QLabel( 'App current information is displayed here...') self.left = int(self.screen().size().width() / 4) self.top = int(self.screen().size().height() / 4) self.width = 640 self.height = 450 self.title = 'Myo Exercises' if MyoService.check_if_process_running(): print("Myo Connect is running!") self.classifyExercises = ClassifyExercises( # subject="Ervin", # nr_of_samples=number_of_samples, epochs=300, # nr_of_gestures=4, exercises=PREDEFINED_EXERCISES, # batch_size=50, training_batch_size=16) else: self.classifyExercises = None # self.informationLabel.setText('Myo Connect is not running! Please start process.') self.table_widget = MainTabWidget(self) self.initUI() self.setStyleSheet("background-color: white;") def initUI(self): self.setWindowTitle(self.title) self.setMinimumHeight(self.height) self.setMinimumWidth(self.width) bar = self.menuBar() about = bar.addMenu("About") config = bar.addMenu("Configuration") info = QAction("App Information", self) about.triggered[QAction].connect(self.aboutThis) about.addAction(info) configAction = QAction("System configuration", self) config.triggered[QAction].connect(self.configWindow) config.addAction(configAction) self.setGeometry(self.left, self.top, self.width, self.height) self.setCentralWidget(self.table_widget) widget = QWidget() container = QHBoxLayout() icon = self.style().standardIcon( QStyle.StandardPixmap.SP_MessageBoxInformation) self.iconLabel.setPixmap(icon.pixmap(QSize(16, 16))) self.restartProcessButton.clicked.connect(self.restartProcess) container.setSpacing(5) container.addWidget(self.iconLabel) container.addWidget(self.informationLabel) if self.classifyExercises is None: self.informationLabel.setText( 'Myo Connect is not running!Please start process.') container.addWidget(self.restartProcessButton) widget.setLayout(container) self.statusBar.addWidget(widget) self.setStatusBar(self.statusBar) self.show() def restartProcess(self): MyoService.start_process() def aboutThis(self, q): # TODO: open dialog with app informations print(q.text() + " is triggered") def configWindow(self): print("config..") widget = ConfigDialog(self) res = widget.exec()
def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle("StudioProject") self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.gScene = QGraphicsScene(self) self.gView = GraphicView(self.gScene, self) self.gView.viewport().setAttribute( Qt.WidgetAttribute.WA_AcceptTouchEvents, False) # self.gView.setBackgroundBrush(QBrush(Qt.black)) self.videoStartDatetime = None self.videoCurrentDatetime = None self.projectFile = '' self.graphicsFile = '' self.videoFile = '' self.obsTb = ObsToolbox(self) # # ===================== Setting video item ============================== # self.videoItem = QGraphicsVideoItem() # self.videoItem.setAspectRatioMode(Qt.KeepAspectRatio) # self.gScene.addItem(self.videoItem) # self.videoItem.mouseMoveEvent = self.gView.mouseMoveEvent self.mediaPlayer = QMediaPlayer(self) # self.mediaPlayer.setVideoOutput(self.videoItem) self.mediaPlayer.playbackStateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.errorOccurred.connect(self.handleError) # self.mediaPlayer.setMuted(True) # self.mediaPlayer.setNotifyInterval(100) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon( QStyle.StandardPixmap.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.changePlayRateBtn = QPushButton('1x') self.changePlayRateBtn.setFixedWidth(40) # self.incrPlayRateBtn.setEnabled(False) self.changePlayRateBtn.clicked.connect(self.changePlayRate) self.positionSlider = QSlider(Qt.Orientation.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.timerLabel = QLabel() self.timerLabel.setText('--:--:--') self.timerLabel.setFixedWidth(58) self.dateLabel = QLabel() self.dateLabel.setText('Video date: --') self.statusBar.addPermanentWidget(self.dateLabel) # Create open action self.openVideoAction = QAction(QIcon('icons/video-file.png'), 'Open video', self) self.openVideoAction.setShortcut('Ctrl+O') self.openVideoAction.setStatusTip('Open video file') self.openVideoAction.triggered.connect(self.openVideoFile) # Create observation action obsTbAction = QAction(QIcon('icons/checklist.png'), 'Observation toolbox', self) obsTbAction.setStatusTip('Open observation toolbox') obsTbAction.triggered.connect(self.openObsToolbox) self.drawPointAction = QAction(QIcon('icons/drawPoint.png'), 'Draw point', self) self.drawPointAction.setStatusTip('Draw point over the video') self.drawPointAction.setCheckable(True) self.drawPointAction.setEnabled(False) self.drawPointAction.triggered.connect(self.drawingClick) self.drawLineAction = QAction(QIcon('icons/drawLine.png'), 'Draw line', self) self.drawLineAction.setStatusTip('Draw line over the video') self.drawLineAction.setCheckable(True) self.drawLineAction.setEnabled(False) self.drawLineAction.triggered.connect(self.drawingClick) self.drawZoneAction = QAction(QIcon('icons/drawZone.png'), 'Draw zone', self) self.drawZoneAction.setStatusTip('Draw zone over the video') self.drawZoneAction.setCheckable(True) self.drawZoneAction.setEnabled(False) self.drawZoneAction.triggered.connect(self.drawingClick) self.maskGenAction = QAction(QIcon('icons/mask.png'), 'Generate mask file', self) self.maskGenAction.setStatusTip( 'Generate mask file for TrafficIntelligence') self.maskGenAction.setCheckable(True) self.maskGenAction.setEnabled(False) self.maskGenAction.triggered.connect(self.generateMask) actionGroup = QActionGroup(self) actionGroup.addAction(self.drawPointAction) actionGroup.addAction(self.drawLineAction) actionGroup.addAction(self.drawZoneAction) openProjectAction = QAction(QIcon('icons/open-project.png'), 'Open project', self) openProjectAction.setStatusTip('Open project') openProjectAction.triggered.connect(self.openProject) self.saveProjectAction = QAction(QIcon('icons/save-project.png'), 'Save project', self) self.saveProjectAction.setStatusTip('Save project') self.saveProjectAction.setEnabled(False) self.saveProjectAction.triggered.connect(self.saveProject) self.saveGraphAction = QAction(QIcon('icons/save-graphics.png'), 'Save graphics', self) self.saveGraphAction.setStatusTip('Save graphics to database') self.saveGraphAction.setEnabled(False) self.saveGraphAction.triggered.connect(self.saveGraphics) self.loadGraphAction = QAction(QIcon('icons/folders.png'), 'Load graphics', self) self.loadGraphAction.setStatusTip('Load graphics from database') self.loadGraphAction.setEnabled(False) self.loadGraphAction.triggered.connect(self.loadGraphics) # Create exit action exitAction = QAction(QIcon('icons/close.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # self.exitCall # Create menu bar and add action # menuBar = self.menuBar() # menuBar.setNativeMenuBar(False) # fileMenu = menuBar.addMenu('&File') # fileMenu.addAction(openVideoAction) # fileMenu.addAction(obsTbAction) # fileMenu.addAction(exitAction) self.toolbar = self.addToolBar('Tools') self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.addAction(openProjectAction) self.toolbar.addAction(self.saveProjectAction) self.toolbar.addAction(self.openVideoAction) # self.toolbar.insertSeparator(self.loadGraphAction) # self.toolbar.addAction(self.loadGraphAction) # self.toolbar.addAction(self.saveGraphAction) # self.toolbar.addAction(self.drawPointAction) # self.toolbar.addAction(self.drawLineAction) # self.toolbar.addAction(self.drawZoneAction) self.toolbar.addAction(self.maskGenAction) # self.toolbar.insertSeparator(self.drawPointAction) self.toolbar.insertSeparator(obsTbAction) self.toolbar.addAction(obsTbAction) self.toolbar.insertSeparator(exitAction) self.toolbar.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) # controlLayout.addWidget(self.decrPlayRateBtn) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.changePlayRateBtn) controlLayout.addWidget(self.timerLabel) controlLayout.addWidget(self.positionSlider) # controlLayout.addWidget(self.durationLabel) layout = QVBoxLayout() layout.addWidget(self.gView) layout.addLayout(controlLayout) # Set widget to contain window contents wid.setLayout(layout)
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle("StudioProject") self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.gScene = QGraphicsScene(self) self.gView = GraphicView(self.gScene, self) self.gView.viewport().setAttribute( Qt.WidgetAttribute.WA_AcceptTouchEvents, False) # self.gView.setBackgroundBrush(QBrush(Qt.black)) self.videoStartDatetime = None self.videoCurrentDatetime = None self.projectFile = '' self.graphicsFile = '' self.videoFile = '' self.obsTb = ObsToolbox(self) # # ===================== Setting video item ============================== # self.videoItem = QGraphicsVideoItem() # self.videoItem.setAspectRatioMode(Qt.KeepAspectRatio) # self.gScene.addItem(self.videoItem) # self.videoItem.mouseMoveEvent = self.gView.mouseMoveEvent self.mediaPlayer = QMediaPlayer(self) # self.mediaPlayer.setVideoOutput(self.videoItem) self.mediaPlayer.playbackStateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.errorOccurred.connect(self.handleError) # self.mediaPlayer.setMuted(True) # self.mediaPlayer.setNotifyInterval(100) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon( QStyle.StandardPixmap.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.changePlayRateBtn = QPushButton('1x') self.changePlayRateBtn.setFixedWidth(40) # self.incrPlayRateBtn.setEnabled(False) self.changePlayRateBtn.clicked.connect(self.changePlayRate) self.positionSlider = QSlider(Qt.Orientation.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.timerLabel = QLabel() self.timerLabel.setText('--:--:--') self.timerLabel.setFixedWidth(58) self.dateLabel = QLabel() self.dateLabel.setText('Video date: --') self.statusBar.addPermanentWidget(self.dateLabel) # Create open action self.openVideoAction = QAction(QIcon('icons/video-file.png'), 'Open video', self) self.openVideoAction.setShortcut('Ctrl+O') self.openVideoAction.setStatusTip('Open video file') self.openVideoAction.triggered.connect(self.openVideoFile) # Create observation action obsTbAction = QAction(QIcon('icons/checklist.png'), 'Observation toolbox', self) obsTbAction.setStatusTip('Open observation toolbox') obsTbAction.triggered.connect(self.openObsToolbox) self.drawPointAction = QAction(QIcon('icons/drawPoint.png'), 'Draw point', self) self.drawPointAction.setStatusTip('Draw point over the video') self.drawPointAction.setCheckable(True) self.drawPointAction.setEnabled(False) self.drawPointAction.triggered.connect(self.drawingClick) self.drawLineAction = QAction(QIcon('icons/drawLine.png'), 'Draw line', self) self.drawLineAction.setStatusTip('Draw line over the video') self.drawLineAction.setCheckable(True) self.drawLineAction.setEnabled(False) self.drawLineAction.triggered.connect(self.drawingClick) self.drawZoneAction = QAction(QIcon('icons/drawZone.png'), 'Draw zone', self) self.drawZoneAction.setStatusTip('Draw zone over the video') self.drawZoneAction.setCheckable(True) self.drawZoneAction.setEnabled(False) self.drawZoneAction.triggered.connect(self.drawingClick) self.maskGenAction = QAction(QIcon('icons/mask.png'), 'Generate mask file', self) self.maskGenAction.setStatusTip( 'Generate mask file for TrafficIntelligence') self.maskGenAction.setCheckable(True) self.maskGenAction.setEnabled(False) self.maskGenAction.triggered.connect(self.generateMask) actionGroup = QActionGroup(self) actionGroup.addAction(self.drawPointAction) actionGroup.addAction(self.drawLineAction) actionGroup.addAction(self.drawZoneAction) openProjectAction = QAction(QIcon('icons/open-project.png'), 'Open project', self) openProjectAction.setStatusTip('Open project') openProjectAction.triggered.connect(self.openProject) self.saveProjectAction = QAction(QIcon('icons/save-project.png'), 'Save project', self) self.saveProjectAction.setStatusTip('Save project') self.saveProjectAction.setEnabled(False) self.saveProjectAction.triggered.connect(self.saveProject) self.saveGraphAction = QAction(QIcon('icons/save-graphics.png'), 'Save graphics', self) self.saveGraphAction.setStatusTip('Save graphics to database') self.saveGraphAction.setEnabled(False) self.saveGraphAction.triggered.connect(self.saveGraphics) self.loadGraphAction = QAction(QIcon('icons/folders.png'), 'Load graphics', self) self.loadGraphAction.setStatusTip('Load graphics from database') self.loadGraphAction.setEnabled(False) self.loadGraphAction.triggered.connect(self.loadGraphics) # Create exit action exitAction = QAction(QIcon('icons/close.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # self.exitCall # Create menu bar and add action # menuBar = self.menuBar() # menuBar.setNativeMenuBar(False) # fileMenu = menuBar.addMenu('&File') # fileMenu.addAction(openVideoAction) # fileMenu.addAction(obsTbAction) # fileMenu.addAction(exitAction) self.toolbar = self.addToolBar('Tools') self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.addAction(openProjectAction) self.toolbar.addAction(self.saveProjectAction) self.toolbar.addAction(self.openVideoAction) # self.toolbar.insertSeparator(self.loadGraphAction) # self.toolbar.addAction(self.loadGraphAction) # self.toolbar.addAction(self.saveGraphAction) # self.toolbar.addAction(self.drawPointAction) # self.toolbar.addAction(self.drawLineAction) # self.toolbar.addAction(self.drawZoneAction) self.toolbar.addAction(self.maskGenAction) # self.toolbar.insertSeparator(self.drawPointAction) self.toolbar.insertSeparator(obsTbAction) self.toolbar.addAction(obsTbAction) self.toolbar.insertSeparator(exitAction) self.toolbar.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) # controlLayout.addWidget(self.decrPlayRateBtn) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.changePlayRateBtn) controlLayout.addWidget(self.timerLabel) controlLayout.addWidget(self.positionSlider) # controlLayout.addWidget(self.durationLabel) layout = QVBoxLayout() layout.addWidget(self.gView) layout.addLayout(controlLayout) # Set widget to contain window contents wid.setLayout(layout) # def showEvent(self, event): # self.gView.fitInView(self.videoItem, Qt.KeepAspectRatio) def openVideoFile(self): # self.mediaPlayer.setMedia(QMediaContent()) if self.sender() == self.openVideoAction: self.videoFile, _ = QFileDialog.getOpenFileName( self, "Open video", QDir.homePath()) # if self.videoFile != '': # self.setWindowTitle('{} - {}'.format(os.path.basename(self.videoFile), # os.path.basename(self.projectFile))) if self.videoFile != '': self.setWindowTitle('{} - {}'.format( os.path.basename(self.videoFile), os.path.basename(self.projectFile))) self.saveProjectAction.setEnabled(True) self.maskGenAction.setEnabled(True) # self.loadGraphAction.setEnabled(True) # self.saveGraphAction.setEnabled(True) # self.drawPointAction.setEnabled(True) # self.drawLineAction.setEnabled(True) # self.drawZoneAction.setEnabled(True) creation_datetime, width, height = getVideoMetadata(self.videoFile) self.videoStartDatetime = self.videoCurrentDatetime = creation_datetime self.dateLabel.setText(creation_datetime.strftime('%a, %b %d, %Y')) self.gView.setSceneRect(0, 0, width, height) self.videoItem = QGraphicsVideoItem() self.videoItem.setAspectRatioMode( Qt.AspectRatioMode.KeepAspectRatio) self.gScene.addItem(self.videoItem) self.videoItem.mouseMoveEvent = self.gView.mouseMoveEvent self.videoItem.setSize(QSizeF(width, height)) self.mediaPlayer.setVideoOutput(self.videoItem) self.mediaPlayer.setSource(QUrl.fromLocalFile(self.videoFile)) self.gView.labelSize = width / 50 self.playButton.setEnabled(True) # self.gView.setViewport(QOpenGLWidget()) self.mediaPlayer.pause() def exitCall(self): # sys.exit(app.exec()) # self.mediaPlayer.pause() self.close() def play(self): # self.gView.fitInView(self.videoItem, Qt.KeepAspectRatio) if self.mediaPlayer.playbackState( ) == QMediaPlayer.PlaybackState.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def changePlayRate(self): if self.mediaPlayer.playbackRate() < 2: r = self.mediaPlayer.playbackRate() + 0.5 self.mediaPlayer.setPlaybackRate(r) self.changePlayRateBtn.setText('{:g}x'.format(r)) self.statusBar.showMessage('Play back rate = {:g}x'.format(r), 2000) elif self.mediaPlayer.playbackRate() == 2: self.mediaPlayer.setPlaybackRate(1) self.changePlayRateBtn.setText('{}x'.format(1)) self.statusBar.showMessage('Play back rate = {}x'.format(1), 2000) def mediaStateChanged(self, state): if self.mediaPlayer.playbackState( ) == QMediaPlayer.PlaybackState.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.StandardPixmap.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.StandardPixmap.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) s, m, h = self.convertMillis(position) self.videoCurrentDatetime = self.videoStartDatetime + \ timedelta(hours=h, minutes=m, seconds=s) self.timerLabel.setText('{:02d}:{:02d}:{:02d}'.format( self.videoCurrentDatetime.time().hour, self.videoCurrentDatetime.time().minute, self.videoCurrentDatetime.time().second)) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) # s, m, h = self.convertMillis(duration) # self.durationLabel.setText('{:02d}:{:02d}'.format(m, s)) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) # self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def openObsToolbox(self): if not self.obsTb.isVisible(): self.obsTb.show() def drawingClick(self): # if self.sender() == self.drawLineAction: # self.labelingAction.setChecked(False) # else: # self.drawLineAction.setChecked(False) cursor = QCursor(Qt.CursorShape.CrossCursor) self.gView.setCursor(cursor) def generateMask(self): if not self.sender().isChecked(): self.gView.unsetCursor() return cursor = QCursor(Qt.CursorShape.CrossCursor) self.gView.setCursor(cursor) # dbfilename = self.obsTb.dbFilename # if dbfilename != None: # self.session = connectDatabase(dbfilename) # else: # msg = QMessageBox() # msg.setIcon(QMessageBox.Information) # msg.setText('The database file is not defined.') # msg.setInformativeText('In order to set the database file, open the Observation Toolbox') # msg.setIcon(QMessageBox.Critical) # msg.exec_() # return # if self.gView.unsavedLines == [] and self.gView.unsavedZones == [] and \ # self.gView.unsavedPoints == []: # QMessageBox.information(self, 'Save', 'There is no polygon to generate mask!') # return def saveMaskFile(self): creation_datetime, width, height = getVideoMetadata(self.videoFile) item = self.gView.gPolyItem #self.gView.unsavedZones[0] mask_polygon = item.polygon() xy = [] for p in mask_polygon: xy.append((p.x(), p.y())) img = Image.new('RGB', (width, height), color='black') img1 = ImageDraw.Draw(img) img1.polygon(xy, fill="white", outline="white") fileName, _ = QFileDialog.getSaveFileName(self, "Open database file", QDir.homePath(), "PNG files (*.png)") if fileName != '': img.save(fileName) self.gView.scene().removeItem(item) self.gView.unsavedZones = [] def openProject(self): self.projectFile, _ = QFileDialog.getOpenFileName( self, "Open project file", QDir.homePath(), "Project (*.prj)") if self.projectFile == '': return self.saveProjectAction.setEnabled(True) self.maskGenAction.setEnabled(True) # self.loadGraphAction.setEnabled(True) # self.saveGraphAction.setEnabled(True) # self.drawPointAction.setEnabled(True) # self.drawLineAction.setEnabled(True) # self.drawZoneAction.setEnabled(True) tree = ET.parse(self.projectFile) root = tree.getroot() gItems = [] for elem in root: subEelTexts = {} for subelem in elem: subEelTexts[subelem.tag] = subelem.text gItems.append([elem.tag, subEelTexts]) for key in gItems: if key[0] == 'database': item = key[1] if item['fileName'] is not None: self.obsTb.dbFilename = item['fileName'] self.obsTb.opendbFile() elif key[0] == 'video': item = key[1] if item['fileName'] is not None: self.videoFile = item['fileName'] self.openVideoFile() self.mediaPlayer.setPosition(int(item['sliderValue'])) if item['fileName'] is not None: self.loadGraphics() elif key[0] == 'trajectory': item = key[1] if item['metadata'] != None: self.obsTb.mdbFileLedit.setText(item['metadata']) self.obsTb.openMdbFile() self.obsTb.siteNameCombobx.setCurrentIndex( int(item['site'])) self.obsTb.camViewCombobx.setCurrentIndex( int(item['cam_view'])) self.obsTb.trjDbCombobx.setCurrentIndex( int(item['traj_db'])) elif key[0] == 'window': item = key[1] x, y = item['mainWin_pos'].split(',') w, h = item['mainWin_size'].split(',') self.setGeometry(int(x), int(y), int(w), int(h)) if item['obsTbx_open'] == 'True': self.obsTb.show() x, y = item['obsTbx_pos'].split(',') w, h = item['obsTbx_size'].split(',') self.obsTb.setGeometry(int(x), int(y), int(w), int(h)) # self.setWindowTitle('{} - {}'.format(os.path.basename(self.videoFile), # os.path.basename(self.projectFile))) def saveProject(self): if self.projectFile == '': fileDir = QDir.homePath() else: fileDir = self.projectFile self.projectFile, _ = QFileDialog.getSaveFileName( self, "Save project file", fileDir, "Project (*.prj)") # fileName = "/Users/Abbas/project.xml" if self.projectFile == '': return file = QFile(self.projectFile) if (not file.open(QIODevice.OpenModeFlag.WriteOnly | QIODevice.OpenModeFlag.Text)): return xmlWriter = QXmlStreamWriter(file) xmlWriter.setAutoFormatting(True) xmlWriter.writeStartDocument() xmlWriter.writeStartElement('project') xmlWriter.writeStartElement('database') xmlWriter.writeTextElement("fileName", self.obsTb.dbFilename) xmlWriter.writeEndElement() xmlWriter.writeStartElement('video') xmlWriter.writeTextElement( "fileName", self.videoFile) #mediaPlayer.media().canonicalUrl().path()) xmlWriter.writeTextElement("sliderValue", str(self.mediaPlayer.position())) xmlWriter.writeEndElement() xmlWriter.writeStartElement('trajectory') xmlWriter.writeTextElement("metadata", self.obsTb.mdbFileLedit.text()) xmlWriter.writeTextElement( "site", str(self.obsTb.siteNameCombobx.currentIndex())) xmlWriter.writeTextElement( "cam_view", str(self.obsTb.camViewCombobx.currentIndex())) xmlWriter.writeTextElement("traj_db", str(self.obsTb.trjDbCombobx.currentIndex())) xmlWriter.writeEndElement() xmlWriter.writeStartElement('window') xmlWriter.writeTextElement( "mainWin_size", "{},{}".format(int(self.width()), int(self.height()))) xmlWriter.writeTextElement( "mainWin_pos", "{},{}".format(int(self.x()), int(self.y()))) xmlWriter.writeTextElement("obsTbx_open", str(self.obsTb.isVisible())) xmlWriter.writeTextElement( "obsTbx_size", "{},{}".format(int(self.obsTb.width()), int(self.obsTb.height()))) xmlWriter.writeTextElement( "obsTbx_pos", "{},{}".format(int(self.obsTb.x()), int(self.obsTb.y()))) xmlWriter.writeEndElement() xmlWriter.writeEndElement() self.setWindowTitle('{} - {}'.format( os.path.basename(self.videoFile), os.path.basename(self.projectFile))) if self.obsTb.dbFilename != None: self.obsTb.setWindowTitle('{} - {}'.format( os.path.basename(self.obsTb.dbFilename), os.path.basename(self.projectFile))) def saveGraphics(self): dbfilename = self.obsTb.dbFilename if dbfilename != None: self.session = connectDatabase(dbfilename) else: msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText('The database file is not defined.') msg.setInformativeText( 'In order to set the database file, open the Observation Toolbox' ) msg.setIcon(QMessageBox.Critical) msg.exec_() return if self.gView.unsavedLines == [] and self.gView.unsavedZones == [] and \ self.gView.unsavedPoints == []: QMessageBox.information(self, 'Save', 'No new graphical items to save!') return for item in self.gView.unsavedLines: x1 = round(item.line().x1(), 2) y1 = round(item.line().y1(), 2) x2 = round(item.line().x2(), 2) y2 = round(item.line().y2(), 2) line = Line(None, None, x1, y1, x2, y2) self.session.add(line) self.session.flush() label = self.generate_itemGroup([x1, x2], [y1, y2], line.idx) self.gView.scene().addItem(label) for item in self.gView.unsavedZones: xs = [] ys = [] for p in item.polygon(): xs.append(round(p.x(), 2)) ys.append(round(p.y(), 2)) zone = Zone(None, None, xs, ys) self.session.add(zone) self.session.flush() label = self.generate_itemGroup(xs, ys, zone.idx) self.gView.scene().addItem(label) for item in self.gView.unsavedPoints: x = round(item.rect().center().x(), 2) y = round(item.rect().center().y(), 2) point = Point(x, y) self.session.add(point) self.session.flush() label = self.generate_itemGroup([x], [y], point.idx) self.gView.scene().removeItem(item) self.gView.scene().addItem(label) QMessageBox.information( self, 'Save', '{} point(s), {} line(s) and {} zone(s) saved to database successfully!' .format(len(self.gView.unsavedPoints), len(self.gView.unsavedLines), len(self.gView.unsavedZones))) self.gView.unsavedLines = [] self.gView.unsavedZones = [] self.gView.unsavedPoints = [] self.session.commit() def generate_itemGroup(self, xs, ys, label, type): gItemGroup = QGraphicsItemGroup() pointBbx = QRectF() pointBbx.setSize(QSizeF(self.gView.labelSize, self.gView.labelSize)) textLabel = QGraphicsTextItem(label) if len(xs) == 1: pointBbx.moveCenter(QPointF(xs[0], ys[0])) textLabel.setPos(xs[0] - (textLabel.boundingRect().width() / 2), ys[0] - (textLabel.boundingRect().height() / 2)) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = Qt.GlobalColor.white textColor = Qt.GlobalColor.black tooltip = 'P{}:{}' elif len(xs) == 2: pointBbx.moveCenter(QPointF(xs[1], ys[1])) textLabel.setPos(xs[1] - (textLabel.boundingRect().width() / 2), ys[1] - (textLabel.boundingRect().height() / 2)) r, g, b = np.random.choice(range(256), size=3) line_item = QGraphicsLineItem(xs[0], ys[0], xs[1], ys[1]) line_item.setPen( QPen(QColor(r, g, b, 128), self.gView.labelSize / 6)) gItemGroup.addToGroup(line_item) # line_end = QGraphicsEllipseItem(xs[1], ys[1], # int(self.gView.labelSize/3), int(self.gView.labelSize/3)) # line_end.setPen(QPen(QColor(r, g, b), 0.5)) # line_end.setBrush(QBrush(QColor(r, g, b))) # gItemGroup.addToGroup(line_end) pointShape = QGraphicsEllipseItem(pointBbx) shapeColor = QColor(r, g, b, 128) textColor = Qt.GlobalColor.black tooltip = 'L{}:{}' # textLabel.setRotation(np.arctan((ys[1] - ys[0])/(xs[1] - xs[0]))*(180/3.14)) else: pointBbx.moveCenter(QPointF(np.mean(xs), np.mean(ys))) textLabel.setPos( np.mean(xs) - (textLabel.boundingRect().width() / 2), np.mean(ys) - (textLabel.boundingRect().height() / 2)) points = [QPointF(x, y) for x, y in zip(xs, ys)] polygon = QPolygonF(points) r, g, b = np.random.choice(range(256), size=3) zone_item = QGraphicsPolygonItem(polygon) zone_item.setPen(QPen(QColor(r, g, b), self.gView.labelSize / 10)) zone_item.setBrush(QBrush(QColor(r, g, b, 40))) gItemGroup.addToGroup(zone_item) pointShape = QGraphicsRectItem(pointBbx) shapeColor = Qt.GlobalColor.darkBlue textColor = Qt.GlobalColor.white tooltip = 'Z{}:{}' pointShape.setPen(QPen(Qt.GlobalColor.white, 0.5)) pointShape.setBrush(QBrush(shapeColor)) # self.gView.scene().addEllipse(pointBbx, QPen(Qt.white, 0.5), QBrush(Qt.black)) gItemGroup.setToolTip(tooltip.format(label, type)) gItemGroup.addToGroup(pointShape) labelFont = QFont() labelFont.setPointSize(round(self.gView.labelSize / 2)) labelFont.setBold(True) textLabel.setFont(labelFont) textLabel.setDefaultTextColor(textColor) gItemGroup.addToGroup(textLabel) return gItemGroup def loadGraphics(self): dbfilename = self.obsTb.dbFilename if dbfilename != None: self.session = connectDatabase(dbfilename) else: msg = QMessageBox() # msg.setIcon(QMessageBox.Icon.Information) msg.setText('The database file is not defined.') msg.setInformativeText( 'In order to set the database file, open the Observation Toolbox' ) msg.setIcon(QMessageBox.Icon.Critical) msg.exec() return for gitem in self.gView.scene().items(): if isinstance(gitem, QGraphicsItemGroup): self.gView.scene().removeItem(gitem) q_line = self.session.query(Line) q_zone = self.session.query(Zone) if q_line.all() == [] and q_zone.all() == []: QMessageBox.information(self, 'Warning!', 'There is no graphics to load!') return line_items = [] for line in q_line: p1 = line.points[0] p2 = line.points[1] if line.type != None: lineType = line.type.name else: lineType = None gItmGroup = self.generate_itemGroup([p1.x, p2.x], [p1.y, p2.y], str(line.idx), lineType) self.gScene.addItem(gItmGroup) line_items.append(str(line.idx)) self.obsTb.line_list_wdgt.clear() self.obsTb.line_list_wdgt.addItems(line_items) self.obsTb.line_list_wdgt.setCurrentRow(0) self.obsTb.line_newRecButton.setEnabled(False) self.obsTb.line_saveButton.setEnabled(True) self.obsTb.line_saveButton.setText('Edit line(s)') self.obsTb.line_saveButton.setIcon(QIcon('icons/edit.png')) zone_items = [] for zone in q_zone: if zone.type != None: zoneType = zone.type.name else: zoneType = None gItmGroup = self.generate_itemGroup( [point.x for point in zone.points], [point.y for point in zone.points], str(zone.idx), zoneType) self.gScene.addItem(gItmGroup) zone_items.append(str(zone.idx)) self.obsTb.zone_list_wdgt.clear() self.obsTb.zone_list_wdgt.addItems(zone_items) self.obsTb.zone_list_wdgt.setCurrentRow(0) self.obsTb.zone_newRecButton.setEnabled(False) self.obsTb.zone_saveButton.setEnabled(True) self.obsTb.zone_saveButton.setText('Edit zone(s)') self.obsTb.zone_saveButton.setIcon(QIcon('icons/edit.png')) @staticmethod def convertMillis(millis): seconds = int(millis / 1000) % 60 minutes = int(millis / (1000 * 60)) % 60 hours = int(millis / (1000 * 60 * 60)) % 24 return seconds, minutes, hours