def test_getFail404() -> None: app = QCoreApplication([]) http_request_manager = HttpRequestManager.getInstance() cbo = mock.Mock() def callback(*args, **kwargs): cbo.callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) def error_callback(*args, **kwargs): cbo.error_callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) request_data = http_request_manager.get( url="http://localhost:8080/do_not_exist", callback=callback, error_callback=error_callback) # Make sure that if something goes wrong, we quit after 10 seconds http_request_manager.callLater(10.0, app.quit) app.exec() http_request_manager.cleanup() # Remove all unscheduled events cbo.error_callback.assert_called_once_with( request_data.reply, QNetworkReply.NetworkError.ContentNotFoundError) cbo.callback.assert_not_called()
def cleanup(self) -> None: for event in list(self._delayed_events.keys()): self._cleanupDelayedCallEvent(event) self._delayed_events.clear() # Removes all events that have been posted to the QApplication. QCoreApplication.instance().removePostedEvents(None, self._event_type)
def __init__(self, engine, parent=None) -> None: super().__init__(parent) self._engine = engine self._path = "" self._icons = {} # type: Dict[str, Dict[str, QUrl]] self._deprecated_icons = {} # type: Dict[str, Dict[str, str]] self._images = {} # type: Dict[str, QUrl] # Workaround for incorrect default font on Windows if sys.platform == "win32": default_font = QFont() default_font.setPointSize(9) QCoreApplication.instance().setFont(default_font) self._em_height = int( QFontMetrics(QCoreApplication.instance().font()).ascent()) self._em_width = self._em_height # Cache the initial language in the preferences. For fonts, a special font can be defined with, for example, # "medium" and "medium_nl_NL". If the special one exists, getFont() will return that, otherwise the default # will be returned. We cache the initial language here is because Cura can only change its language if it gets # restarted, so we need to keep the fonts consistent in a single Cura run. self._preferences = UM.Application.Application.getInstance( ).getPreferences() self._lang_code = self._preferences.getValue("general/language") self._initializeDefaults() self._check_if_trusted = False self.reload()
def test_getBasicAuthSuccess() -> None: app = QCoreApplication([]) http_request_manager = HttpRequestManager.getInstance() cbo = mock.Mock() def callback(*args, **kwargs): cbo.callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) def error_callback(*args, **kwargs): cbo.callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) request_data = http_request_manager.get( url="http://localhost:8080/auth", headers_dict={"Authorization": "Basic dXNlcjp1c2Vy"}, callback=callback, error_callback=error_callback) # Make sure that if something goes wrong, we quit after 10 seconds http_request_manager.callLater(10.0, app.quit) app.exec() http_request_manager.cleanup() # Remove all unscheduled events cbo.callback.assert_called_once_with(request_data.reply) cbo.error_callback.assert_not_called()
def execute(self, data): Logger.log("d", "[Woodgrain Effect] Begin processing") # Show the progress bar self.progress_bar = Message(title="Apply Woodgrain Effect", text="This may take several minutes, please be patient.\n\n", lifetime=0, dismissable=False, progress=-1) self.progress_bar.show() # Start the processing thread self._locks = {} self._locks["metadata"] = threading.Lock() self._locks["output"] = threading.Lock() self.progress = (-1,0) self.output_gcode=[] self.apply_woodgrain_thread = threading.Thread(target=self.apply_woodgrain, args=(data,)) self.apply_woodgrain_thread.start() # Keep the GUI responsive while we wait, even though this script blocks the UI thread GUI_UPDATE_FREQUENCY = 50 # as used in cura source PROGRESS_CHECK_INTERVAL = 1000 # milliseconds update_period = 1 / GUI_UPDATE_FREQUENCY updates_per_check = int(GUI_UPDATE_FREQUENCY * (PROGRESS_CHECK_INTERVAL / 1000)) # Wait until the processing thread is done while True: for i in range(0, updates_per_check): QCoreApplication.processEvents() # Ensure that the GUI does not freeze. sleep(update_period) # Grab an update on the progress self._locks["metadata"].acquire() progress = self.progress self._locks["metadata"].release() # Update progress bar self.progress_bar.setProgress((progress[0] / progress[1]) * 100) # float(100) means complete # Check if Cura is still open.. # If it's not, this loop will just run forever main_window = QtApplication.getInstance().getMainWindow() if main_window is None: return None #close out the loop #Check if we're done if progress[0] >= progress[1]: self.apply_woodgrain_thread.join() break # Wrap things up and pass the modified gcode back to cura Logger.log("d", "[Woodgrain Effect] End processing. " + str(progress[1]) + " iterations performed") self.progress_bar.hide() return self.output_gcode
def loadPlugins(self, metadata: Optional[Dict[str, Any]] = None) -> None: """Load all plugins matching a certain set of metadata :param metadata: The meta data that needs to be matched. NOTE: This is the method which kicks everything off at app launch. """ start_time = time.time() # First load all of the pre-loaded plug-ins. for preloaded_plugin in self.preloaded_plugins: self.loadPlugin(preloaded_plugin) # Get a list of all installed plugins: plugin_ids = self._findInstalledPlugins() for plugin_id in plugin_ids: if plugin_id in self.preloaded_plugins: continue # Already loaded this before. self.pluginLoadStarted.emit(plugin_id) # Get the plugin metadata: try: plugin_metadata = self.getMetaData(plugin_id) except TrustException: Logger.error( "Plugin {} was not loaded because it could not be verified.", plugin_id) message_text = i18n_catalog.i18nc( "@error:untrusted", "Plugin {} was not loaded because it could not be verified.", plugin_id) Message(text=message_text, message_type=Message.MessageType.ERROR).show() continue # Save all metadata to the metadata dictionary: self._metadata[plugin_id] = plugin_metadata if metadata is None or self._subsetInDict( self._metadata[plugin_id], metadata): # try: self.loadPlugin(plugin_id) QCoreApplication.processEvents( ) # Ensure that the GUI does not freeze. # Add the plugin to the list after actually load the plugin: self._all_plugins.append(plugin_id) self._plugins_installed.append(plugin_id) except PluginNotFoundError: pass self.pluginLoadStarted.emit("") Logger.log("d", "Loading all plugins took %s seconds", time.time() - start_time)
def _initializeDefaults(self) -> None: self._fonts = { "system": QCoreApplication.instance().font(), "fixed": QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont) } palette = QCoreApplication.instance().palette() self._colors = { "system_window": palette.window(), "system_text": palette.text() } self._sizes = {"line": QSizeF(self._em_width, self._em_height)}
def _hashFile(cls, file_path: str) -> str: """ Returns a SHA-256 hash of the specified file. :param file_path: The path to a file to get the hash of. :return: A cryptographic hash of the specified file. """ block_size = 2**16 hasher = hashlib.sha256() with open(file_path, "rb") as f: contents = f.read(block_size) while len(contents) > 0: hasher.update(contents) contents = f.read(block_size) QCoreApplication.processEvents( ) # Process events to allow the interface to update return hasher.hexdigest()
def callLater(self, delay: float, callback: Callable, *args, **kwargs) -> None: if delay < 0: raise ValueError( "delay must be a non-negative value, but got [%s] instead." % delay) delay_to_use = None if delay <= 0 else delay event = _CallFunctionEvent(self, callback, args, kwargs, delay=delay_to_use) if delay_to_use is None: QCoreApplication.instance().postEvent(self, event) else: self._scheduleDelayedCallEvent(event)
def test_getSuccessful() -> None: app = QCoreApplication([]) http_request_manager = HttpRequestManager.getInstance() cbo = mock.Mock() def callback(*args, **kwargs): cbo.callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) request_data = http_request_manager.get( url="http://localhost:8080/success", callback=callback) # Make sure that if something goes wrong, we quit after 10 seconds http_request_manager.callLater(10.0, app.quit) app.exec() http_request_manager.cleanup() # Remove all unscheduled events cbo.callback.assert_called_once_with(request_data.reply)
def _screenScaleFactor(self) -> float: # OSX handles sizes of dialogs behind our backs, but other platforms need # to know about the device pixel ratio if sys.platform == "darwin": return 1.0 else: # determine a device pixel ratio from font metrics, using the same logic as UM.Theme fontPixelRatio = QFontMetrics(QCoreApplication.instance().font()).ascent() / 11 # round the font pixel ratio to quarters fontPixelRatio = int(fontPixelRatio * 4) / 4 return fontPixelRatio
def upgrade(self) -> bool: """Performs the version upgrades of all configuration files to the most recent version. The upgrade plug-ins must all be loaded at this point, or no upgrades can be performed. :return: True if anything was upgraded, or False if it was already up to date. """ start_time = time.time() Logger.log("i", "Looking for old configuration files to upgrade.") self._upgrade_tasks.extend( self._getUpgradeTasks()) # Get the initial files to upgrade. self._upgrade_routes = self._findShortestUpgradeRoutes( ) # Pre-compute the upgrade routes. upgraded = False # Did we upgrade something? while self._upgrade_tasks: upgrade_task = self._upgrade_tasks.popleft() self._upgradeFile( upgrade_task.storage_path, upgrade_task.file_name, upgrade_task.configuration_type) # Upgrade this file. QCoreApplication.processEvents( ) # Ensure that the GUI does not freeze. if upgraded: message = UM.Message.Message(text=catalogue.i18nc( "@info:version-upgrade", "A configuration from an older version of {0} was imported.", Application.getInstance().getApplicationName()), title=catalogue.i18nc( "@info:title", "Version Upgrade"), message_type=UM.Message.Message. MessageType.POSITIVE) message.show() Logger.log("i", "Checking and performing updates took %s", time.time() - start_time) return upgraded
def test_getTimeout() -> None: app = QCoreApplication([]) http_request_manager = HttpRequestManager.getInstance() cbo = mock.Mock() def error_callback(*args, **kwargs): cbo.error_callback(*args, **kwargs) # quit now so we don't need to wait http_request_manager.callLater(0, app.quit) request_data = http_request_manager.get( url="http://localhost:8080/timeout", error_callback=error_callback, timeout=1) # Make sure that if something goes wrong, we quit after 10 seconds http_request_manager.callLater(10.0, app.quit) app.exec() http_request_manager.cleanup() # Remove all unscheduled events cbo.error_callback.assert_called_once_with( request_data.reply, QNetworkReply.NetworkError.OperationCanceledError) assert request_data.is_aborted_due_to_timeout
def __init__(self, parent=None): super().__init__(parent) self._name = None self._catalog = None # Slightly hacky way of getting at the QML engine defined by QtApplication. engine = QCoreApplication.instance()._qml_engine self._i18n_function = self._wrapFunction(engine, self, self._call_i18n) self._i18nc_function = self._wrapFunction(engine, self, self._call_i18nc) self._i18np_function = self._wrapFunction(engine, self, self._call_i18np) self._i18ncp_function = self._wrapFunction(engine, self, self._call_i18ncp)
def __init__(self, tray_icon_name: str = None, **kwargs) -> None: self.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL) QQuickWindow.setGraphicsApi(QSGRendererInterface.GraphicsApi.OpenGL) plugin_path = "" if sys.platform == "win32": if hasattr(sys, "frozen"): plugin_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "PyQt6", "plugins") Logger.log("i", "Adding QT6 plugin path: %s", plugin_path) QCoreApplication.addLibraryPath(plugin_path) else: import site for sitepackage_dir in site.getsitepackages(): QCoreApplication.addLibraryPath(os.path.join(sitepackage_dir, "PyQt6", "plugins")) elif sys.platform == "darwin": plugin_path = os.path.join(self.getInstallPrefix(), "Resources", "plugins") if plugin_path: Logger.log("i", "Adding QT5 plugin path: %s", plugin_path) QCoreApplication.addLibraryPath(plugin_path) # use Qt Quick Scene Graph "basic" render loop os.environ["QSG_RENDER_LOOP"] = "basic" # Force using Fusion style for consistency between Windows, mac OS and Linux os.environ["QT_QUICK_CONTROLS_STYLE"] = "Fusion" super().__init__(sys.argv, **kwargs) self._qml_import_paths: List[str] = [] self._main_qml: str = "main.qml" self._qml_engine: Optional[QQmlApplicationEngine] = None self._main_window: Optional[MainWindow] = None self._tray_icon_name: Optional[str] = tray_icon_name self._tray_icon: Optional[str] = None self._tray_icon_widget: Optional[QSystemTrayIcon] = None self._theme: Optional[Theme] = None self._renderer: Optional[QtRenderer] = None self._job_queue: Optional[JobQueue] = None self._version_upgrade_manager: Optional[VersionUpgradeManager] = None self._is_shutting_down: bool = False self._recent_files: List[QUrl] = [] self._configuration_error_message: Optional[ConfigurationErrorMessage] = None self._http_network_request_manager: Optional[HttpRequestManager] = None #Metadata required for the file dialogues. self.setOrganizationDomain("https://ultimaker.com/") self.setOrganizationName("Ultimaker B.V.")
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self._background_color = QColor(204, 204, 204, 255) self.beforeRenderPassRecording.connect( self._render, type=Qt.ConnectionType.DirectConnection) self._mouse_device = QtMouseDevice(self) self._mouse_device.setPluginId("qt_mouse") self._key_device = QtKeyDevice() self._key_device.setPluginId("qt_key") self._previous_focus = None # type: Optional["QQuickItem"] self._app = QCoreApplication.instance() # Remove previously added input devices (if any). This can happen if the window was re-loaded. self._app.getController().removeInputDevice("qt_mouse") self._app.getController().removeInputDevice("qt_key") self._app.getController().addInputDevice(self._mouse_device) self._app.getController().addInputDevice(self._key_device) self._app.getController().getScene().sceneChanged.connect( self._onSceneChanged) self._app.getController().activeViewChanged.connect( self._onActiveViewChanged) Selection.selectionChanged.connect(self._onSceneChanged) self._preferences = Application.getInstance().getPreferences() self._preferences.addPreference("general/window_width", self.DEFAULT_WINDOW_WIDTH) self._preferences.addPreference("general/window_height", self.DEFAULT_WINDOW_HEIGHT) self._preferences.addPreference("general/window_left", self.DEFAULT_WINDOW_LEFT) self._preferences.addPreference("general/window_top", self.DEFAULT_WINDOW_TOP) self._preferences.addPreference("general/window_state", Qt.WindowState.WindowNoState.value) self._preferences.addPreference("general/restore_window_geometry", True) restored_geometry = QRect( int(self._preferences.getValue("general/window_left")), int(self._preferences.getValue("general/window_top")), int(self._preferences.getValue("general/window_width")), int(self._preferences.getValue("general/window_height"))) if not self._preferences.getValue("general/restore_window_geometry"): # Ignore whatever the preferences said. Logger.log( "i", "Not restoring window geometry from preferences because 'restore_window_geometry' is false" ) restored_geometry = QRect(self.DEFAULT_WINDOW_LEFT, self.DEFAULT_WINDOW_TOP, self.DEFAULT_WINDOW_WIDTH, self.DEFAULT_WINDOW_HEIGHT) # Make sure restored geometry is not outside the currently available screens screen_found = False for screen in self._app.screens(): if restored_geometry.intersects(screen.availableGeometry()): screen_found = True break if not screen_found: Logger.log( "w", "Could not restore to previous location on screen, since the sizes or number of monitors " "have changed since then") # Unable to find the screen that this window used to be on, so just use the defaults restored_geometry = QRect(self.DEFAULT_WINDOW_LEFT, self.DEFAULT_WINDOW_TOP, self.DEFAULT_WINDOW_WIDTH, self.DEFAULT_WINDOW_HEIGHT) self.setGeometry(restored_geometry) # Translate window state back to enum. try: window_state = int( self._preferences.getValue("general/window_state")) except ValueError: self._preferences.resetPreference("general/window_state") window_state = int( self._preferences.getValue("general/window_state")) if window_state == Qt.WindowState.WindowNoState.value: self.setWindowState(Qt.WindowState.WindowNoState) elif window_state == Qt.WindowState.WindowMaximized.value: self.setWindowState(Qt.WindowState.WindowMaximized) self._mouse_x = 0 self._mouse_y = 0 self._mouse_pressed = False self._viewport_rect = QRectF(0, 0, 1.0, 1.0) self.closing.connect(self.preClosing) Application.getInstance().setMainWindow(self) self._fullscreen = False self._full_render_required = True self._allow_resize = True
def handle_exception(exc_type, exc_value, trace): try: exc_tuple = (exc_type, exc_value, trace) error_message = ''.join(traceback.format_exception(*exc_tuple)) popup = ErrorPopup(error_message) popup.exec() if popup.sending: send_error_report(exc_tuple) stacks = inspect.stack() if len(stacks) >= 2: stack = stacks[1] module = inspect.getmodule(stack.frame) if module: module_name = module.__name__ else: path = pathlib.Path(stack.filename) module_name = f"{path.parent.name}.{path.stem}" else: for filename in map( lambda frame: frame.filename, reversed(traceback.extract_tb(exc_tuple[-1])) ): path = pathlib.Path(filename) if path.parent.name == 'beskar' and not path.stem.startswith('__'): module_name = f"beskar.{path.stem}" break else: module_name = None if module_name in sys.modules: logger = logging.getLogger(module_name) else: logger = logging.getLogger('beskar.unknown') logger.warning( 'Failed to determine which module caused ' 'the error in the upcoming logging message.' ) logger.critical('The following error occured:', exc_info=exc_tuple) if pool is not None: pool.clear() except Exception as second_error: second_error.__context__ = exc_value if popup.sending: send_error_report(second_error) logger = logging.getLogger('beskar.unknown') logger.error( 'Two exceptions occured in handle_exception:', exc_info=second_error ) finally: try: # NOTE: Trying to close the application even # if there is an error in the try block above # however, despite this we MUST exit the app # no matter what. In an abudance of caution # wrap this in a try finally block. QCoreApplication.quit() finally: sys.exit(1)
def load(self, path: str, is_first_call: bool = True) -> None: if path == self._path: return theme_full_path = os.path.join(path, "theme.json") Logger.log( "d", "Loading theme file: {theme_full_path}".format( theme_full_path=theme_full_path)) try: with open(theme_full_path, encoding="utf-8") as f: data = json.load(f) except EnvironmentError as e: Logger.error( "Unable to load theme file at {theme_full_path}: {err}".format( theme_full_path=theme_full_path, err=e)) return except UnicodeDecodeError: Logger.error( "Theme file at {theme_full_path} is corrupt (invalid UTF-8 bytes)." .format(theme_full_path=theme_full_path)) return except json.JSONDecodeError: Logger.error( "Theme file at {theme_full_path} is corrupt (invalid JSON syntax)." .format(theme_full_path=theme_full_path)) return # Iteratively load inherited themes try: theme_id = data["metadata"]["inherits"] self.load(Resources.getPath(Resources.Themes, theme_id), is_first_call=False) except FileNotFoundError: Logger.log("e", "Could not find inherited theme %s", theme_id) except KeyError: pass # No metadata or no inherits keyword in the theme.json file if "colors" in data: for name, value in data["colors"].items(): if not is_first_call and isinstance(value, str): # Keep parent theme string colors as strings and parse later self._colors[name] = value continue if isinstance(value, str) and is_first_call: # value is reference to base_colors color name try: color = data["base_colors"][value] except IndexError: Logger.log( "w", "Colour {value} could not be found in base_colors". format(value=value)) continue else: color = value try: c = QColor(color[0], color[1], color[2], color[3]) except IndexError: # Color doesn't have enough components. Logger.log( "w", "Colour {name} doesn't have enough components. Need to have 4, but had {num_components}." .format(name=name, num_components=len(color))) continue # Skip this one then. self._colors[name] = c if "base_colors" in data: for name, color in data["base_colors"].items(): try: c = QColor(color[0], color[1], color[2], color[3]) except IndexError: # Color doesn't have enough components. Logger.log( "w", "Colour {name} doesn't have enough components. Need to have 4, but had {num_components}." .format(name=name, num_components=len(color))) continue # Skip this one then. self._colors[name] = c if is_first_call and self._colors: #Convert all string value colors to their referenced color for name, color in self._colors.items(): if isinstance(color, str): try: c = self._colors[color] self._colors[name] = c except: Logger.log( "w", "Colour {name} {color} does".format(name=name, color=color)) fonts_dir = os.path.join(path, "fonts") if os.path.isdir(fonts_dir): for root, dirnames, filenames in os.walk(fonts_dir): for filename in filenames: if filename.lower().endswith(".ttf"): QFontDatabase.addApplicationFont( os.path.join(root, filename)) if "fonts" in data: system_font_size = QCoreApplication.instance().font().pointSize() for name, font in data["fonts"].items(): q_font = QFont() q_font.setFamily( font.get("family", QCoreApplication.instance().font().family())) if font.get("bold"): q_font.setBold(font.get("bold", False)) else: q_font.setWeight(font.get("weight", 500)) q_font.setLetterSpacing(QFont.SpacingType.AbsoluteSpacing, font.get("letterSpacing", 0)) q_font.setItalic(font.get("italic", False)) q_font.setPointSize(int( font.get("size", 1) * system_font_size)) q_font.setCapitalization(QFont.Capitalization.AllUppercase if font.get("capitalize", False) else QFont.Capitalization.MixedCase) self._fonts[name] = q_font if "sizes" in data: for name, size in data["sizes"].items(): s = QSizeF() s.setWidth(round(size[0] * self._em_width)) s.setHeight(round(size[1] * self._em_height)) self._sizes[name] = s iconsdir = os.path.join(path, "icons") if os.path.isdir(iconsdir): try: for base_path, _, icons in os.walk(iconsdir): detail_level = base_path.split(os.sep)[-1] if detail_level not in self._icons: self._icons[detail_level] = {} for icon in icons: name = os.path.splitext(icon)[0] self._icons[detail_level][name] = QUrl.fromLocalFile( os.path.join(base_path, icon)) except EnvironmentError as err: # Exception when calling os.walk, e.g. no access rights. Logger.error( f"Can't access icons of theme ({iconsdir}): {err}") # Won't get any icons then. Images will show as black squares. deprecated_icons_file = os.path.join(iconsdir, "deprecated_icons.json") if os.path.isfile(deprecated_icons_file): try: with open(deprecated_icons_file, encoding="utf-8") as f: data = json.load(f) for icon in data: self._deprecated_icons[icon] = data[icon] except (UnicodeDecodeError, json.decoder.JSONDecodeError, EnvironmentError): Logger.logException( "w", "Could not parse deprecated icons list %s", deprecated_icons_file) imagesdir = os.path.join(path, "images") if os.path.isdir(imagesdir): try: for image in os.listdir(imagesdir): name = os.path.splitext(image)[0] self._images[name] = QUrl.fromLocalFile( os.path.join(imagesdir, image)) except EnvironmentError as err: # Exception when calling os.listdir, e.g. no access rights. Logger.error( f"Can't access image of theme ({imagesdir}): {err}") # Won't get any images then. They will show as black squares. Logger.log("d", "Loaded theme %s", path) Logger.info(f"System's em size is {self._em_height}px.") self._path = path # only emit the theme loaded signal once after all the themes in the inheritance chain have been loaded if is_first_call: self.themeLoaded.emit()
def _onDelayReached(self, event: "_CallFunctionEvent") -> None: QCoreApplication.instance().postEvent(self, event)
def _installPackage(self, installation_package_data: PackageData) -> None: package_info = installation_package_data["package_info"] filename = installation_package_data["filename"] package_id = package_info["package_id"] Logger.log("i", "Installing package [%s] from file [%s]", package_id, filename) # Load the cached package file and extract all contents to a temporary directory if not os.path.exists(filename): Logger.log( "w", "Package [%s] file '%s' is missing, cannot install this package", package_id, filename) return try: with zipfile.ZipFile(filename, "r") as archive: name_list = archive.namelist() temp_dir = tempfile.TemporaryDirectory() for archive_filename in name_list: archive.extract(archive_filename, temp_dir.name) QCoreApplication.processEvents() except Exception: Logger.logException("e", "Failed to install package from file [%s]", filename) return # Remove it first and then install try: self._purgePackage(package_id) except Exception as e: message = Message(catalog.i18nc( "@error:update", "There was an error uninstalling the package {package} before installing " "new version:\n{error}.\nPlease try to upgrade again later.". format(package=package_id, error=str(e))), title=catalog.i18nc("@info:title", "Updating error"), message_type=Message.MessageType.ERROR) message.show() return # Copy the folders there for sub_dir_name, installation_root_dir in self._installation_dirs_dict.items( ): src_dir_path = os.path.join(temp_dir.name, "files", sub_dir_name) dst_dir_path = os.path.join(installation_root_dir, package_id) if not os.path.exists(src_dir_path): Logger.log( "w", "The path %s does not exist, so not installing the files", src_dir_path) continue try: self.__installPackageFiles(package_id, src_dir_path, dst_dir_path) except EnvironmentError as e: Logger.log( "e", "Can't install package due to EnvironmentError: {err}". format(err=str(e))) continue # Remove the file try: os.remove(filename) except Exception: Logger.log("w", "Tried to delete file [%s], but it failed", filename) # Move the info to the installed list of packages only when it succeeds self._installed_package_dict[ package_id] = self._to_install_package_dict[package_id] self._installed_package_dict[package_id]["package_info"][ "is_installed"] = True
# -*- coding: utf-8 -*- import sys from PyQt6.QtWidgets import QApplication, QWidget, QPushButton from PyQt6.QtCore import QCoreApplication if __name__ == '__main__': app = QApplication(sys.argv) btn = QPushButton("Hello PyQt6") btn.clicked.connect(QCoreApplication.instance().quit) btn.resize(400,100) btn.move(50,50) btn.show() sys.exit(app.exec())
def functionEvent(self, event: QEvent) -> None: e = _QtFunctionEvent(event) QCoreApplication.postEvent(self, e)