def initialize(self, check_if_trusted: bool = False) -> None: super().initialize() preferences = Application.getInstance().getPreferences() if check_if_trusted: # Need to do this before the preferences are read for the first time, but after obj-creation, which is here. preferences.indicateUntrustedPreference("general", "theme", lambda value: self._isPathSecure(Resources.getPath(Resources.Themes, value))) preferences.indicateUntrustedPreference("backend", "location", lambda value: self._isPathSecure(os.path.abspath(value))) preferences.addPreference("view/force_empty_shader_cache", False) preferences.addPreference("view/opengl_version_detect", OpenGLContext.OpenGlVersionDetect.Autodetect) # Read preferences here (upgrade won't work) to get: # - The language in use, so the splash window can be shown in the correct language. # - The OpenGL 'force' parameters. try: self.readPreferencesFromConfiguration() except FileNotFoundError: Logger.log("i", "Preferences file not found, ignore and use default language '%s'", self._default_language) # Initialize the package manager to remove and install scheduled packages. self._package_manager = self._package_manager_class(self, parent = self) # If a plugin is removed, check if the matching package is also removed. self._plugin_registry.pluginRemoved.connect(lambda plugin_id: self._package_manager.removePackage(plugin_id)) self._mesh_file_handler = MeshFileHandler(self) #type: MeshFileHandler self._workspace_file_handler = WorkspaceFileHandler(self) #type: WorkspaceFileHandler if preferences.getValue("view/force_empty_shader_cache"): self.setAttribute(Qt.ApplicationAttribute.AA_DisableShaderDiskCache) if preferences.getValue("view/opengl_version_detect") != OpenGLContext.OpenGlVersionDetect.ForceModern: major_version, minor_version, profile = OpenGLContext.detectBestOpenGLVersion( preferences.getValue("view/opengl_version_detect") == OpenGLContext.OpenGlVersionDetect.ForceLegacy) else: Logger.info("Force 'modern' OpenGL (4.1 core) -- overrides 'force legacy opengl' preference.") major_version, minor_version, profile = (4, 1, QSurfaceFormat.OpenGLContextProfile.CoreProfile) if major_version is None or minor_version is None or profile is None: Logger.log("e", "Startup failed because OpenGL version probing has failed: tried to create a 2.0 and 4.1 context. Exiting") if not self.getIsHeadLess(): QMessageBox.critical(None, "Failed to probe OpenGL", "Could not probe OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers.") sys.exit(1) else: opengl_version_str = OpenGLContext.versionAsText(major_version, minor_version, profile) Logger.log("d", "Detected most suitable OpenGL context version: %s", opengl_version_str) if not self.getIsHeadLess(): OpenGLContext.setDefaultFormat(major_version, minor_version, profile = profile) self._qml_import_paths.append(os.path.join(os.path.dirname(sys.executable), "qml")) self._qml_import_paths.append(os.path.join(self.getInstallPrefix(), "Resources", "qml")) Logger.log("i", "Initializing job queue ...") self._job_queue = JobQueue() self._job_queue.jobFinished.connect(self._onJobFinished) Logger.log("i", "Initializing version upgrade manager ...") self._version_upgrade_manager = VersionUpgradeManager(self)
def wrapper(self, *args, **kwargs): try: return func(self, *args, **kwargs) except Exception as e: if isinstance(e, serial.serialutil.SerialException): self.disable_widgets() self.clear_servo() self.port_refresh_button_clicked(None) QMessageBox.critical(None, "Error", "Disconnected from device") else: QMessageBox.information(None, "Error", str(e))
def checkCheck(self): if not fgoFunc.base.serialno: return QMessageBox.critical(self, '错误', '未连接设备') try: fgoFunc.Check().show() except Exception as e: logger.critical(e)
def runFunc(self, func, *args, **kwargs): if not fgoFunc.base.serialno: return QMessageBox.critical(self, '错误', '未连接设备') def f(): try: self.signalFuncBegin.emit() self.applyAll() func(*args, **kwargs) except fgoFunc.ScriptTerminate as e: logger.critical(e) except Exception as e: logger.exception(e) finally: self.signalFuncEnd.emit() fgoFunc.control.reset() fgoFunc.fuse.reset() QApplication.beep() self.thread = threading.Thread( target=f, name= f'{func.__qualname__}({",".join(repr(i)for i in args)}{","if kwargs else""}{",".join((i+"="+repr(j))for i,j in kwargs.items())})' ) self.thread.start()
def accept(self): """Accept the data provided through the dialog.""" self.data = [] for field in (self.nameField, self.jobField, self.emailField): if not field.text(): QMessageBox.critical( self, "Error!", f"You must provide a contact's{field.objectName()}", ) self.data = None # reset .data return self.data.append(field.text()) if not self.data: return() super().accept()
def save_to_file(self, configuration: Union[Dict[str, Any], None], out_file_path: str) -> None: if configuration is None: return try: if not out_file_path: return file = open(out_file_path, 'w') json.dump(configuration, file, indent=4) file.close() QMessageBox.information(self, 'Success', 'Configuration Saved Successfully!', QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) except IOError: QMessageBox.critical(self, 'Failure', 'Unexpected Error Occurred', QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok)
def start_errors_calculate(self): self.waiting_text_3.setText("Команда выполняется…") self.repaint() alpha = self.alpha_input.value() c = self.c_input.value() d = self.d_input.value() time = self.time_input.value() length = self.length_input.value() number = self.number_input_2.value() if 1 <= self.method_3 <= 2: hx_rate, ht_rate = 2, 4 else: hx_rate, ht_rate = 2, 2 norm_error = uniform_norm_error for j in range(self.tableWidget_error_rates.rowCount()): if not self.tableWidget_error_rates.item( j, 0) or not self.tableWidget_error_rates.item(j, 1): QMessageBox.critical( self, "Ошибка! ", "Наличие пустых/полупустых строк в таблицах недопустимо!") break i = int(self.tableWidget_error_rates.item(j, 0).text()) k = int(self.tableWidget_error_rates.item(j, 1).text()) results = get_numerical_experiments(i, k, alpha, c, d, time, length, number, hx_rate, ht_rate, self.methods[self.method_3], norm_error) self.tableWidget_error_rates.setItem( j, 0, QTableWidgetItem(str(int(results[0])))) self.tableWidget_error_rates.setItem( j, 1, QTableWidgetItem(str(int(results[1])))) self.tableWidget_error_rates.setItem( j, 2, QTableWidgetItem(str("%.6e" % results[2]))) self.tableWidget_error_rates.setItem( j, 3, QTableWidgetItem(str("%.6e" % results[3]))) self.tableWidget_error_rates.setItem( j, 4, QTableWidgetItem(str("%.6f" % results[4]))) self.repaint() self.waiting_text_3.setText("Нажмите «Старт» для начала работы.")
def connectToDatabase(self): """Create a QSqlDatabase object and connect to the database.""" database = QSqlDatabase.addDatabase("QSQLITE") database.setDatabaseName("data/inventory.db") database.setConnectOptions("QSQLITE_ENABLE_REGEXP") if not database.open(): error = database.lastError().text() QMessageBox.critical(QApplication.activeWindow(), "Connection Error", f"Something went wrong: {error}") sys.exit(1) # Handle if the database is missing and SQLite creates a new, # empty database tables_needed = { "Staff", "Customers", "Orders", "Products", "Categories" } no_tables = tables_needed - set(database.tables()) if no_tables: QMessageBox.critical(QApplication.activeWindow(), "Error", f'{no_tables} missing.') sys.exit(1)
def __init__(self) -> None: if OpenGL.__instance is not None: raise RuntimeError("Try to create singleton '%s' more than once" % self.__class__.__name__) super().__init__() OpenGL.__instance = self profile = QOpenGLVersionProfile() profile.setVersion(OpenGLContext.major_version, OpenGLContext.minor_version) profile.setProfile(OpenGLContext.profile) context = QOpenGLContext.currentContext() if not context: Logger.log( "e", "Startup failed due to OpenGL context creation failing") QOpenGLContext.currentContext() sys.exit(1) self._gl = QOpenGLVersionFunctionsFactory.get(profile, context) if not self._gl: Logger.log("e", "Startup failed due to OpenGL initialization failing") QMessageBox.critical( QMessageBox.Icon.Critical, "Failed to Initialize OpenGL", i18n_catalog.i18nc( "@message", "Failed to Initialize OpenGL", "Could not initialize OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers." )) sys.exit(1) # It would be nice to be able to not necessarily need OpenGL FrameBuffer Object support, but # due to a limitation in PyQt, currently glReadPixels or similar methods are not available. # This means we can only get frame buffer contents through methods that indirectly call # those methods, in this case primarily QOpenGLFrameBufferObject::toImage(), making us # hard-depend on FrameBuffer Objects. if not self.hasFrameBufferObjects(): Logger.log( "e", "Startup failed, OpenGL does not support Frame Buffer Objects") QMessageBox.critical( None, i18n_catalog.i18nc( "Critical OpenGL Extensions Missing", "Critical OpenGL extensions are missing. This program requires support for Framebuffer Objects. Please check your video card drivers." )) sys.exit(1) self._gl.initializeOpenGLFunctions() self._gpu_vendor = OpenGL.Vendor.Other #type: int vendor_string = self._gl.glGetString(self._gl.GL_VENDOR) if vendor_string is None: vendor_string = "Unknown" vendor_string = vendor_string.lower() if "nvidia" in vendor_string: self._gpu_vendor = OpenGL.Vendor.NVidia elif "amd" in vendor_string or "ati" in vendor_string: self._gpu_vendor = OpenGL.Vendor.AMD elif "intel" in vendor_string: self._gpu_vendor = OpenGL.Vendor.Intel self._gpu_type = "Unknown" # type: str # WORKAROUND: Cura/#1117 Cura-packaging/12 # Some Intel GPU chipsets return a string, which is not undecodable via PyQt6. # This workaround makes the code fall back to a "Unknown" renderer in these cases. try: self._gpu_type = self._gl.glGetString(self._gl.GL_RENDERER) except UnicodeDecodeError: Logger.log( "e", "DecodeError while getting GL_RENDERER via glGetString!") self._opengl_version = self._gl.glGetString( self._gl.GL_VERSION) #type: str short_versions = re.findall( r"(\d+.\d+(.\d+)?)", self._opengl_version ) # Find version numbers, either 2-component or 3-component. if short_versions: self._opengl_version_short = short_versions[0][ 0] # First whole match (second [0] is to grab the first group which is the whole version number). else: self._opengl_version_short = "unknown" self._opengl_shading_language_version = Version("0.0") # type: Version try: self._opengl_shading_language_version = Version( self._gl.glGetString(self._gl.GL_SHADING_LANGUAGE_VERSION)) except: self._opengl_shading_language_version = Version("1.0") if not self.hasFrameBufferObjects(): Logger.log( "w", "No frame buffer support, falling back to texture copies.") Logger.log("d", "Initialized OpenGL subsystems.") Logger.log("d", "OpenGL Version: %s", self._opengl_version) Logger.log("d", "OpenGL Vendor: %s", self._gl.glGetString(self._gl.GL_VENDOR)) Logger.log("d", "OpenGL Renderer: %s", self._gpu_type) Logger.log("d", "GLSL Version: %s", self._opengl_shading_language_version)
def add_x_value(self): if self.add_value(self.x_setted_list, self.x_input.value(), self.length_input.value()) is False: QMessageBox.critical(self, "Ошибка! ", "Выберите x меньше или равным длине трубки")
def __init__(self, args): super(Application, self).__init__(args) QtWebEngineQuick.initialize() splash = QtWidgets.QSplashScreen( QtGui.QPixmap(resourcePath("vi/ui/res/logo_splash.png")) ) splash.show() if version.SNAPSHOT: QMessageBox.critical( splash, "Snapshot", "This is a snapshot release... Use as you will...." ) def change_splash_text(txt): if len(txt): splash.showMessage( f" {txt} ...", QtCore.Qt.AlignmentFlag.AlignLeft, QtGui.QColor(0x808000), ) # Set up paths chat_log_directory = "" if len(sys.argv) > 1: chat_log_directory = sys.argv[1] if not os.path.exists(chat_log_directory): change_splash_text("Searching for EVE Logs") if sys.platform.startswith("darwin"): chat_log_directory = os.path.join( os.path.expanduser("~"), "Documents", "EVE", "logs", "Chatlogs" ) if not os.path.exists(chat_log_directory): chat_log_directory = os.path.join( os.path.expanduser("~"), "Library", "Application Support", "Eve Online", "p_drive", "User", "My Documents", "EVE", "logs", "Chatlogs", ) elif sys.platform.startswith("linux"): chat_log_directory = os.path.join( os.path.expanduser("~"), "Documents", "EVE", "logs", "Chatlogs" ) elif sys.platform.startswith("win32") or sys.platform.startswith("cygwin"): import ctypes.wintypes buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) ctypes.windll.shell32.SHGetFolderPathW(0, 0x05, 0, 0, buf) documents_path = buf.value chat_log_directory = os.path.join( documents_path, "EVE", "logs", "Chatlogs" ) # Now I need to just make sure... Some old pcs could still be on XP if not os.path.exists(chat_log_directory): chat_log_directory = os.path.join( os.path.expanduser("~"), "My Documents", "EVE", "logs", "Chatlogs", ) if not os.path.exists(chat_log_directory): chat_log_directory = QtWidgets.QFileDialog.getExistingDirectory( None, caption="Select EVE Online chat logfiles directory", directory=chat_log_directory, ) if not os.path.exists(chat_log_directory): # None of the paths for logs exist, bailing out QMessageBox.critical( splash, "No path to Logs", "No logs found at: " + chat_log_directory, QMessageBox.Close, ) sys.exit(1) # Setting local directory for cache and logging change_splash_text("Setting Spyglass Directories") spyglass_dir = os.path.join( os.path.dirname(os.path.dirname(chat_log_directory)), "spyglass" ) if not os.path.exists(spyglass_dir): os.mkdir(spyglass_dir) cache.Cache.PATH_TO_CACHE = os.path.join(spyglass_dir, "cache-2.sqlite3") spyglass_log_directory = os.path.join(spyglass_dir, "logs") if not os.path.exists(spyglass_log_directory): os.mkdir(spyglass_log_directory) change_splash_text("Connecting to Cache") spyglass_cache = Cache() log_level = spyglass_cache.getFromCache("logging_level") if not log_level: log_level = logging.WARN if version.SNAPSHOT: log_level = logging.DEBUG # For Testing BACKGROUND_COLOR = spyglass_cache.getFromCache("background_color") if BACKGROUND_COLOR: self.setStyleSheet(f"background-color: {BACKGROUND_COLOR};") css = Styles().getStyle() self.setStyleSheet(css) del css # Setup logging for console and rotated log files formatter = logging.Formatter( "%(asctime)s| %(message)s", datefmt="%m/%d %I:%M:%S" ) root_logger = logging.getLogger() root_logger.setLevel(level=log_level) log_filename = spyglass_log_directory + "/output.log" file_handler = RotatingFileHandler( maxBytes=(1048576 * 5), backupCount=7, filename=log_filename, mode="a" ) file_handler.setFormatter(formatter) root_logger.addHandler(file_handler) console_handler = StreamHandler() console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) logging.critical("") logging.critical( "------------------- Spyglass %s starting up -------------------", version.VERSION, ) logging.critical("") logging.critical(" Looking for chat logs at: %s", chat_log_directory) logging.critical( " Cache maintained here: %s", cache.Cache.PATH_TO_CACHE ) logging.critical(" Writing logs to: %s", spyglass_log_directory) tray_icon = systemtray.TrayIcon(self) tray_icon.show() self.main_window = viui.MainWindow( chat_log_directory, tray_icon, change_splash_text ) self.main_window.show() self.main_window.raise_()
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...' )
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...", )
def isDeviceAvailable(self): if not fgoKernel.device.available: self.LBL_DEVICE.clear() QMessageBox.critical(self, 'FGO-py', '未连接设备') return False return True
def add_t_value(self): if self.add_value(self.t_setted_list, self.t_input.value(), self.time_input.value()) is False: QMessageBox.critical( self, "Ошибка! ", "Выберите t меньше или равным времени наблюдения")
def start_convergences_calculate(self): self.waiting_text_2.setText("Команда выполняется…") self.repaint() alpha = self.alpha_input.value() c = self.c_input.value() d = self.d_input.value() number = self.number_input_2.value() x_input = self.x_input_2.value() t_input = self.t_input_2.value() x_array = np.empty((self.tableWidget_by_t.rowCount() + 1), dtype=object) x_functions = np.empty((self.tableWidget_by_t.rowCount() + 1), dtype=object) x_labels = np.array([]) t_labels = np.array([]) t_array = np.empty((self.tableWidget_by_x.rowCount() + 1), dtype=object) t_functions = np.empty((self.tableWidget_by_x.rowCount() + 1), dtype=object) status_ok = True for i in range(self.tableWidget_by_t.rowCount()): if not self.tableWidget_by_t.item( i, 0) or not self.tableWidget_by_t.item(i, 1): QMessageBox.critical( self, "Ошибка! ", "Наличие пустых/полупустых строк в таблицах недопустимо!") status_ok = False break x = linspace(0, self.length_input.value(), int(self.tableWidget_by_t.item(i, 0).text())) t = linspace(0, self.time_input.value(), int(self.tableWidget_by_t.item(i, 1).text())) field = self.methods[self.method_2](x, t, alpha, c, d, number) index, = np.where(x >= x_input) x_array[i] = t x_functions[i] = field[index[0]] x_labels = np.append( x_labels, "I=" + self.tableWidget_by_t.item(i, 0).text() + " K=" + self.tableWidget_by_t.item(i, 1).text()) for i in range(self.tableWidget_by_x.rowCount()): if not self.tableWidget_by_x.item( i, 0) or not self.tableWidget_by_x.item(i, 1): QMessageBox.critical( self, "Ошибка! ", "Наличие пустых/полупустых строк в таблицах недопустимо!") status_ok = False break x = linspace(0, self.length_input.value(), int(self.tableWidget_by_x.item(i, 0).text())) t = linspace(0, self.time_input.value(), int(self.tableWidget_by_x.item(i, 1).text())) field = self.methods[self.method_2](x, t, alpha, c, d, number) index, = np.where(t >= t_input) t_array[i] = x t_functions[i] = field.T[index[0]] t_labels = np.append( t_labels, "I=" + self.tableWidget_by_x.item(i, 0).text() + " K=" + self.tableWidget_by_x.item(i, 1).text()) if status_ok: x = linspace(0, self.length_input.value(), self.i_input_2.value()) # разбиение интервала длины t = linspace(0, self.time_input.value(), self.k_input_2.value()) # разбиение интервала времени field = analytical_solution(x, t, alpha, c, d, number) index, = np.where(x >= x_input) x_array[-1] = t x_functions[-1] = field[index[0]] x_labels = np.append(x_labels, "Аналитическое решение") index, = np.where(t >= t_input) t_array[-1] = x t_functions[-1] = field.T[index[0]] t_labels = np.append(t_labels, "Аналитическое решение") x_labels = np.append(x_labels, " ") t_labels = np.append(t_labels, " ") plot(x_array, x_functions, x_labels, "t, с", "Сходимость решения u(x,t) к точному, x = " + str(x_input)) plot(t_array, t_functions, t_labels, "x, см", "Сходимость решения u(x, t) к точному, t = " + str(t_input)) self.waiting_text_2.setText("Нажмите «Старт» для начала работы.")
def get_current_configuration(self) -> Union[Dict[str, Any], None]: if len(self.header_name_input.text()) == 0: QMessageBox.critical(self, "Input Data Error", "Header Name cannot be Empty!", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) return None if len(self.header_output_path_input.text()) == 0: QMessageBox.critical(self, "Input Data Error", "Header Output Path cannot be Empty!", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) return None if self.header_name_input.text()[self.header_name_input.text().find('.'):].lower() \ not in ['.h', '.hh', '.hpp']: # noinspection PyTypeChecker if QMessageBox.StandardButton.Yes != QMessageBox.warning( self, "Header Extension Unknown", """Header extension is not .h, .hpp or .hh, continue?""", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No): return None name_violations: [int] = [] for i in range(len(self.warnings)): if not self.warnings[i]['Name']: name_violations.append(i) if name_violations: as_string = '' for i in name_violations: as_string += ' ' + str(i + 1) + '\n' if as_string: as_string = as_string[:-1] QMessageBox.critical( self, "Unnamed Warning Suppression", "The items at the following rows are not named:\n" + as_string, QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) return None type_violations: Dict[str, ([str], str)] = {} final_values: List[Dict[str, Union[str, int]]] = [] for platform in self.platforms: for i in range(len(self.warnings)): while i >= len(final_values): final_values.append({'Name': self.warnings[i]['Name']}) if platform.warning_type.value == Platform.WarningType.INTEGER: try: if len(self.warnings[i][platform.platform_name]) == 0: continue final_values[i][platform.platform_name] = int( self.warnings[i][platform.platform_name]) except ValueError: if platform.platform_name not in type_violations.keys( ): type_violations[platform.platform_name] = ( [], 'Integer') type_violations[platform.platform_name][0].append( self.warnings[i]['Name']) if platform.warning_type.value == Platform.WarningType.COMMENT: try: if len(self.warnings[i][platform.platform_name]) == 0: continue final_values[i][platform.platform_name] = str( self.warnings[i][platform.platform_name]) except ValueError: if platform.platform_name not in type_violations.keys( ): type_violations[platform.platform_name] = ( [], 'Comment') type_violations[platform.platform_name][0].append( self.warnings[i]['Name']) if type_violations.keys(): all_str: str = '' for key in type_violations.keys(): current_str = f"{len(type_violations[key][0])} '{key}' platform violations, of type" \ f" '{type_violations[key][1]}':\n" for name in type_violations[key][0]: current_str += f' {name}\n' all_str += current_str + '\n' QMessageBox.critical( self, "Type Validation Error", "The following Warning Suppression Fields have type " "validation errors:\n" + all_str, QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok) return None return self.get_current_configuration_from_values(final_values)
def mapKey(self, x): if x and not fgoFunc.base.serialno: self.ui.MENU_CONTROL_MAPKEY.setChecked(False) return QMessageBox.critical(self, '错误', '未连接设备')