#!/usr/bin/env python3 # -*- coding: utf-8 -*- from PyQt5.QtGui import QGuiApplication, QIcon, QScreen from PyQt5.QtQuick import QQuickView from PyQt5.QtCore import ( QUrl, QLocale, QTranslator, QLibraryInfo, QVariant, QAbstractListModel, QModelIndex, Qt, QObject, pyqtSlot, pyqtSignal, QCoreApplication, ) from PyQt5.QtNetwork import QNetworkConfigurationManager, QNetworkConfiguration import sys import os import subprocess from helpers import get_desktop_name, get_desktop_name2, is_installed import pwd # Workaround for opengl lib selection from OpenGL import GL translate = QCoreApplication.translate class Networkstate(QObject): def __init__(self): QObject.__init__(self) @pyqtSlot(result=bool) def isOffLine(self): # Search active network connections net = QNetworkConfigurationManager() return not net.isOnline() class ConfList(QAbstractListModel): NameRole = Qt.UserRole + 1 def __init__(self, parent=None): super().__init__(parent) # Changing working directory abspath = os.path.abspath(__file__) dname = os.path.dirname(abspath) os.chdir(dname) # collect sys info release = subprocess.getoutput("lsb_release -sd") release = release[1:-1] release_nb = subprocess.getoutput("lsb_release -sr") release_nb = release_nb.strip() kernel = subprocess.getoutput("uname -r") if os.uname()[4] == ("x86_64", "aarch64"): arch = "64-bit" elif os.uname()[4] in ("i586", "i686", "armv7hl"): arch = "32-bit" else: arch = os.uname()[4] try: desktop = get_desktop_name(os.path.basename(os.getenv("DESKTOP_SESSION"))) except: desktop = "Other" if desktop == "Other": desktop = get_desktop_name2(os.getenv("XDG_CURRENT_DESKTOP")) if desktop == "unknown": desktop = os.getenv("XDG_CURRENT_DESKTOP") self.screen_factor = 0.0 if desktop == "Gnome Wayland": import gi gi.require_version("Gdk", "3.0") from gi.repository.Gdk import Display # pre-3.22, otherwise deprecated # factor = Gdk.Screen.get_default().get_monitor_scale_factor(0) self.screen_factor = Display.get_default().get_monitor(0).get_scale_factor() # Search active network connections net = QNetworkConfigurationManager() first = True if net.isOnline(): confs = net.allConfigurations(QNetworkConfiguration.Active) for conf in confs: if first: netconfs = conf.name() first = False else: netconfs += ", " + conf.name() self.configuration = [ { "name": translate( "ConfList", "Congratulations!
You are now running {}" ).format(release) }, { "name": translate("ConfList", "You are using linux kernel: {}").format( kernel ) }, { "name": translate("ConfList", "Your system architecture is: {}").format( arch ) }, { "name": translate( "ConfList", "You are now using the Desktop: {}" ).format(desktop) }, {"name": translate("ConfList", "Your user id is: {}").format(os.getuid())}, ] if net.isOnline(): self.configuration.append( { "name": translate( "ConfList", "You are connected to a network through {}" ).format(netconfs) } ) else: self.configuration.append( {"name": translate("ConfList", "You have no network connection")} ) def factor(self, app): """ Determine screen factor Can be specific for Gnome Wayland """ if self.screen_factor == 0: screen = app.primaryScreen() self.screen_factor = screen.devicePixelRatio() return self.screen_factor def data(self, index, role=Qt.DisplayRole): row = index.row() return self.configuration[row]["name"] def rowCount(self, parent=QModelIndex()): return len(self.configuration) def roleNames(self): return { ConfList.NameRole: b"name", } class Callbrowser(QObject): def __init__(self): QObject.__init__(self) @pyqtSlot(str) def weblink(self, link): subprocess.Popen(["xdg-open", link]) class Launcher(QObject): installed = pyqtSignal() needed = pyqtSignal(str, arguments=["repo"]) repo = pyqtSignal() noprogram = pyqtSignal() def __init__(self): QObject.__init__(self) @pyqtSlot(QVariant) def command(self, app): if app.isArray(): cmd = [] for i in range(0, app.property("length").toInt()): cmd.append(app.property(i).toString()) self._command(cmd[0]) def _command(self, cmd): try: subprocess.Popen(cmd) except: print(f"Exception running {cmd}") self.noprogram.emit() return @pyqtSlot(QVariant) def install(self, app): if app.isArray(): cmd = [] # app should contain package, repository for i in range(0, app.property("length").toInt()): cmd.append(app.property(i).toString()) repo = cmd[1] # Check if repositories are enabled core = False updates = False tainted = False t_updates = False nonfree = False nf_updates = False core32 = False core32_updates = False try: active = subprocess.run( ["urpmq", "--list-media", "active"], capture_output=True, text=True ) active.check_returncode() except subprocess.CalledProcessError: print("Error with urpmq") return for line in active.stdout.splitlines(): if line.startswith("Core Release"): core = True if line.startswith("Core Updates"): updates = True if line.startswith("Tainted Release"): tainted = True if line.startswith("Tainted Updates"): t_updates = True if line.startswith("Nonfree Release"): nonfree = True if line.startswith("Nonfree Updates"): nf_updates = True if line.startswith("Core 32bit Release"): core32 = True if line.startswith("Core 32bit Updates"): core32_updates = True if repo == "tainted" and not (tainted and t_updates): # repo tainted not enabled self.needed.emit(repo) return if repo == "non-free" and not (nonfree and nf_updates): # repo nonfree not enabled self.needed.emit(repo) return if repo == "steam" and not ( core32 and core32_updates and nonfree and nf_updates ): # repo not enabled self.needed.emit(repo) return if repo == "" and not (core and updates): # repo not enabled self.repo.emit() return proc = subprocess.Popen(["/usr/bin/gurpmi", cmd[0]]) proc.wait() # Give the signal to reload the applist self.installed.emit() return @pyqtSlot(QVariant) def install_and_launch(self, app): """ app should be an array with the package name to install and then the command to launch """ if app.isArray(): cmd = [] # app should contain package, repository for i in range(0, app.property("length").toInt()): cmd.append(app.property(i).toString()) print(cmd) is_app_installed, inst_repo = is_installed(cmd[0]) if not is_app_installed: proc = subprocess.Popen(["/usr/bin/gurpmi", cmd[0]]) proc.wait() self._command(cmd[1]) class Norun(QObject): def __init__(self): QObject.__init__(self) self.home = os.getenv("HOME") self.conffile = self.home + "/.config/mageiawelcome/norun.flag" @pyqtSlot(bool) def setRunAtLaunch(self, checked): print("Setting", checked) if checked: if os.path.exists(self.conffile): os.remove(self.conffile) else: os.makedirs(self.home + "/.config/mageiawelcome", exist_ok=True) with open(self.conffile, "w"): pass @pyqtSlot(result=bool) def startupcheck(self): return not os.path.exists(self.conffile) class Installable(QObject): def __init__(self): QObject.__init__(self) @pyqtSlot(str, str, result=bool) def installable(self, app, repo): is_app_installed, inst_repo = is_installed(app) installable = (not is_app_installed) or (repo != inst_repo and inst_repo == "") return installable @pyqtSlot(str, str, result=bool) def other(self, app, repo): is_app_installed, inst_repo = is_installed(app) return is_app_installed and repo == "" and inst_repo != "" def username(): user = pwd.getpwuid(os.getuid())[4] # pw_gecos, i e the real name if user == "": user = pwd.getpwuid(os.getuid())[0] # login return user if __name__ == "__main__": app = QGuiApplication(sys.argv) locale = QLocale.system().name() qtTranslator = QTranslator() if qtTranslator.load( "qt_" + locale, QLibraryInfo.location(QLibraryInfo.TranslationsPath) ): app.installTranslator(qtTranslator) appTranslator = QTranslator() if appTranslator.load( QLocale(), "mageiawelcome", "_", "/usr/share/mageiawelcome/translations" ): app.installTranslator(appTranslator) app.setOrganizationName("Mageia") app.setApplicationName("Mageiawelcome") view = QQuickView() view.setResizeMode(QQuickView.SizeRootObjectToView) view.setTitle(app.translate("app", "Welcome to Mageia")) app.setWindowIcon(QIcon("/usr/share/icons/hicolor/32x32/apps/mageiawelcome.png")) cb = Callbrowser() la = Launcher() us = username() ins = Installable() cl = ConfList() nr = Norun() ns = Networkstate() sc = nr.startupcheck() factor = cl.factor(app) screen = app.primaryScreen() # if density is high, use at least factor 2 to scale the initial window. Considering high is more than 190 px/inches. if screen.logicalDotsPerInch() > 190: factor = max(2.0, factor) defaultHeight = min(int(700 * factor), screen.availableGeometry().height()) defaultWidth = min(int(1000 * factor), screen.availableGeometry().width()) centerPoint = screen.availableGeometry().center() view.setGeometry( centerPoint.x() - defaultWidth // 2, centerPoint.y() - defaultHeight // 2, defaultWidth, defaultHeight, ) view.rootContext().setContextProperty("link", cb) view.rootContext().setContextProperty("launch", la) view.rootContext().setContextProperty("user", us) view.rootContext().setContextProperty("ConfList", cl) view.rootContext().setContextProperty("pyinstallable", ins) view.rootContext().setContextProperty("startupcheck", sc) view.rootContext().setContextProperty("norun", nr) view.rootContext().setContextProperty("networkstate", ns) current_path = os.path.abspath(os.path.dirname(__file__)) qml_file = os.path.join(current_path, "mw-ui.qml") view.setSource(QUrl.fromLocalFile(qml_file)) if view.status() == QQuickView.Error: for error in view.errors(): print(error.description()) sys.exit(-1) view.show() res = app.exec_() del view sys.exit(res)