Files

160 lines
5.5 KiB
Python
Raw Permalink Normal View History

# ==============================================
# =============== Linux系统API ===============
# ==============================================
import os
import shlex
import subprocess
from PySide2.QtCore import QStandardPaths as Qsp
from umi_log import logger
from umi_about import UmiAbout
# ==================== 快捷方式 ====================
class _Shortcut:
@staticmethod
def _getPath(position): # 获取路径
# 桌面
if position == "desktop":
return Qsp.writableLocation(Qsp.DesktopLocation)
# 开始菜单
if position == "startMenu":
return Qsp.writableLocation(Qsp.ApplicationsLocation)
# 开机自启 TODO
elif position == "startup":
raise ValueError("Linux 暂不支持自动添加开机自启。请手动设置。")
# 创建快捷方式返回成功与否的字符串。position取值
# desktop 桌面
# startMenu 开始菜单
# startup 开机自启
@staticmethod
def createShortcut(position):
if position == "startup": # TODO
return "[Warning] Linux 暂不支持自动添加开机自启。请手动设置。\nAutomatically adding startup functions is not supported at this time. Please set it manually."
try:
lnkName = UmiAbout["name"]
appPath = UmiAbout["app"]["path"]
appDir = UmiAbout["app"]["dir"]
if not appPath:
return f"[Error] 未找到程序入口文件。请尝试手动创建快捷方式。\n[Error] Umi-OCR app path not exist. Please try creating a shortcut manually.\n\n{appPath}"
lnkPathBase = _Shortcut._getPath(position)
lnkPathBase = os.path.join(lnkPathBase, lnkName)
lnkPath = lnkPathBase + ".desktop"
i = 1
while os.path.exists(lnkPath): # 快捷方式已存在
lnkPath = lnkPathBase + f" ({i}).desktop" # 添加序号
i += 1
except Exception as e:
return f"[Error] 无法获取应用信息。\n[Error] Unable to obtain application information.\n\n{e}"
# 快捷方式 文件内容
desktop_entry = f"""
[Desktop Entry]
Version={UmiAbout["version"]["string"]}
Type=Application
Name={lnkName}
Exec={appPath}
Path={appDir}
Icon={appDir}/UmiOCR-data/qt_res/images/icons/umiocr.ico
Terminal=false
"""
try:
with open(lnkPath, "w") as f:
f.write(desktop_entry)
os.chmod(lnkPath, 0o755) # 赋予执行权限
logger.info(f"创建快捷方式: {lnkPath}")
return "[Success]"
except Exception as e:
return f"[Error] 创建快捷方式失败。\n[Error] Failed to create shortcut.\n {lnkPath}: {e}"
# 删除快捷方式,返回删除文件的个数
@staticmethod
def deleteShortcut(position):
try:
appName = UmiAbout["name"]
lnkDir = _Shortcut._getPath(position)
except Exception:
logger.error("无法获取应用信息", exc_info=True, stack_info=True)
return 0
num = 0
for fileName in os.listdir(lnkDir):
try:
lnkPath = os.path.join(lnkDir, fileName)
if not os.path.isfile(lnkPath): # 排除非文件
continue
if fileName.startswith(appName) and fileName.endswith(".desktop"):
os.remove(lnkPath)
num += 1
logger.info(f"删除快捷方式: {lnkPath}")
except Exception:
logger.error(
f"删除快捷方式失败。 lnkPath: {lnkPath}",
exc_info=True,
stack_info=True,
)
continue
return num
# ==================== 硬件控制 ====================
class _HardwareCtrl:
# 关机
@staticmethod
def shutdown():
# TODO: sudo权限
os.system("sudo shutdown -h now")
# 休眠
@staticmethod
def hibernate():
os.system("sudo systemctl hibernate")
# ==================== 对外接口 ====================
class Api:
# 快捷方式。接口: createShortcut deleteShortcut
# 参数:快捷方式位置, desktop startMenu startup
Shortcut = _Shortcut()
# 硬件控制。接口: shutdown hibernate
HardwareCtrl = _HardwareCtrl()
# TODO: 根据系统及硬件,判断最适合的渲染器类型
@staticmethod
def getOpenGLUse():
return "AA_UseOpenGLES" # 默认使用GLES。
# return "AA_UseSoftwareOpenGL" # 如果不兼容?则使用软渲染
# 键值转键名
@staticmethod
def getKeyName(key):
# 传入 pynput 按键事件对象,返回键名字符串
if not isinstance(key, str):
key = str(key)
if not key: # 错误,未获取键值
return "unknown"
if key.startswith("'") and key.endswith("'"): # 去除自带引号
key = key[1:-1]
if key.startswith("Key."): # 修饰建
key = key[4:]
if not key: # 再检查一次
return "unknown"
return key
# 让系统运行一个程序,不堵塞当前进程
@staticmethod
def runNewProcess(path, args=""):
# TODO: 测试、完善
command_line = [path] + shlex.split(args)
subprocess.Popen(command_line)
# 用系统默认应用打开一个文件或目录,不堵塞当前进程
@staticmethod
def startfile(path):
os.startfile(path)