Initial commit with README
This commit is contained in:
34
sys/kernel/AskDuc.md
Normal file
34
sys/kernel/AskDuc.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# MikOs 文档
|
||||
|
||||
## 1.文件目录结构
|
||||
文件目录结构大多数借用Linux操作系统文件目录结构,但有有所不同,具体如下
|
||||
|
||||
文件结构:
|
||||
|
||||
|文件深度1|文件深度2|文件深度3|文件深度4|类型|文件解释|
|
||||
|:-|:-|:-|:-|:-|:-|
|
||||
|\_\_pycache\_\_/||||目录|Python导入文件|
|
||||
|home||||目录|用户组文件|
|
||||
|home/|root/|||目录|默认用户|
|
||||
|home/|root/|PASSWD||文件|用户密码|
|
||||
|home/|root/|Desktop||目录|用户桌面文件夹|
|
||||
|sys/||||目录|操作系统文件|
|
||||
|sys/|\_\_pycache\_\_/|||目录|Python导入文件|
|
||||
|sys/|config/|||目录|操作系统配置|
|
||||
|sys/|config/|config.json||目录|操作系统配置|
|
||||
|sys/|images.mik/|||目录|操作系统桌面显示图标|
|
||||
|sys/|kernel/|||目录|操作系统内核文件|
|
||||
|sys/|kernel/|\_\_pycache\_\_/||目录|Python导入文件|
|
||||
|sys/|kernel/|login.py||文件|操作系统登录程序|
|
||||
|sys/|kernel/|main.pyw||文件|操作系统内核程序|
|
||||
|sys/|kernel/|mount.py||文件|操作系统虚拟挂载程序|
|
||||
|sys/|kernel/|tools.py||文件|操作系统辅助功能程序|
|
||||
|sys/|kernel/|UI.py||文件|操作系统UI程序|
|
||||
|sys/|lib/|||目录|操作系统级程序目录|
|
||||
|sys/|tkinter.mik/|||目录|tkinter辅助程序和图标|
|
||||
|sys/|ui.mik/|||目录|操作系统UI辅助程序和图标|
|
||||
|sys/|wallpaper/|||目录|操作系统壁纸文件夹|
|
||||
|usr/||||目录|功能文件|
|
||||
|usr/|bin/|||目录|MikDos命令行程序|
|
||||
|usr/|sbin/|||目录|MikDos命令行Root程序|
|
||||
|usr/|local/|||目录|用户级程序|
|
||||
183
sys/kernel/UI.py
Normal file
183
sys/kernel/UI.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from tools import *
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TasksFrame=""
|
||||
ui_mik=""
|
||||
tkinter_mik=""
|
||||
master=""
|
||||
|
||||
def index(root,W,H):
|
||||
screenWidth = root.winfo_screenwidth()
|
||||
screenHeight = root.winfo_screenheight()
|
||||
width = W
|
||||
height = H
|
||||
left = (screenWidth - width) / 2
|
||||
top = (screenHeight - height) / 2
|
||||
root.geometry("%dx%d+%d+%d" % (width, height, left, top))
|
||||
def index100(root,W,H):
|
||||
screenWidth = root.winfo_screenwidth()
|
||||
screenHeight = root.winfo_screenheight()
|
||||
width = W
|
||||
height = H
|
||||
left = (screenWidth - width) / 2
|
||||
top = (screenHeight - height) / 2 - 100
|
||||
root.geometry("%dx%d+%d+%d" % (width, height, left, top))
|
||||
def index50(root,W,H):
|
||||
screenWidth = root.winfo_screenwidth()
|
||||
screenHeight = root.winfo_screenheight()
|
||||
width = W
|
||||
height = H
|
||||
left = (screenWidth - width) / 2
|
||||
top = (screenHeight - height) / 2 - 50
|
||||
root.geometry("%dx%d+%d+%d" % (width, height, left, top))
|
||||
|
||||
|
||||
|
||||
class Menu(tk.Frame):
|
||||
def __init__(self,master):
|
||||
if hasattr(master,"Widget"):
|
||||
master=master.Widget
|
||||
super().__init__(master,bg="#FFF",highlightbackground="#fed79e")
|
||||
self.pack(fill=tk.X,anchor="sw",side="top")
|
||||
self.subs=[]
|
||||
def add_sub(self,label,menu=tk.Menu,font=("微软雅黑",10)):
|
||||
sub=tk.Button(self,text=label+" "*3,bg="#FFF",fg="#000",font=font,bd=0)
|
||||
sub.pack(side=tk.LEFT)
|
||||
sub.config(command=lambda:self.Choose(sub,menu))
|
||||
menu.config(bg="#FFF")
|
||||
self.subs.append([sub,menu])
|
||||
def Choose(self,subutton=tk.Button,menu=tk.Menu):
|
||||
root_x = self.master.winfo_rootx()
|
||||
root_y = self.master.winfo_rooty()
|
||||
x = subutton.winfo_x() + root_x
|
||||
y = subutton.winfo_y() + subutton.winfo_height() + root_y
|
||||
menu.post(x, y)
|
||||
|
||||
|
||||
|
||||
class Window(tk.Toplevel):
|
||||
def __init__(self,title="MikOs - NewWindow",geometry="700x500"):
|
||||
super().__init__()
|
||||
index(self,1000,600)
|
||||
self.TasksFrame=TasksFrame
|
||||
self.withdraw()
|
||||
self.geometry(geometry)
|
||||
self.overrideredirect(True)
|
||||
self.config(bg="#FFF")
|
||||
self.focus()
|
||||
self.wm_attributes("-topmost",True)
|
||||
|
||||
self.Title=tk.Frame(self,bg="#FFF",highlightbackground="#fed79e")
|
||||
self.Title.pack(fill=tk.X)
|
||||
|
||||
self.TitleTextSpace1=tk.Label(self.Title,text=" ",fg="#FFF",bg="#FFF")
|
||||
self.TitleTextSpace1.pack(side=tk.LEFT)
|
||||
|
||||
self.TitleICOImage=ImageTk.PhotoImage(Image.open(tkinter_mik+"ICO.png"))
|
||||
self.TitleICO=tk.Label(self.Title,image=self.TitleICOImage,fg="#FFF",bg="#FFF")
|
||||
self.TitleICO.pack(side=tk.LEFT)
|
||||
|
||||
self.TitleTextSpace2=tk.Label(self.Title,text=" ",fg="#FFF",bg="#FFF")
|
||||
self.TitleTextSpace2.pack(side=tk.LEFT)
|
||||
|
||||
self.TitleText=tk.Label(self.Title,text=title,bg="#FFF",fg="#000",font=("字魂59号-创粗黑",12))
|
||||
self.TitleText.pack(side=tk.LEFT)
|
||||
|
||||
self.TitleTextSpace3=tk.Label(self.Title,text=" ",fg="#FFF",bg="#FFF")
|
||||
self.TitleTextSpace3.pack(side=tk.LEFT)
|
||||
|
||||
self.Widget=tk.Frame(self,bg="#FFF",highlightbackground="#fed79e")
|
||||
self.Widget.pack(fill="both",expand=True)
|
||||
|
||||
self.ExitImg = ImageTk.PhotoImage(Image.open(ui_mik+"close_100.png"))
|
||||
self.Exit = tk.Button(self.Title, bg=self.Title.cget("bg"), bd=0, width=40, relief=tk.FLAT, activebackground="#C42B1C",image=self.ExitImg,command=self.destroy)
|
||||
self.Exit.bind("<Enter>", lambda _: self.Exit.config(background="#dd0009"))
|
||||
self.Exit.bind("<Leave>", lambda _: self.Exit.config(background=self.Title.cget("bg") if self.focus else "#797979"))
|
||||
self.Exit.pack(fill=tk.Y, side=tk.RIGHT)
|
||||
|
||||
def ComMax():
|
||||
self.wm_state("zoomed")
|
||||
self.Max.config(image=self.MaxSmallImg,command=ComMaxSmall)
|
||||
self.Title.bind("<Double-Button-1>", lambda event:ComMaxSmall())
|
||||
def ComMaxSmall():
|
||||
self.wm_state("normal")
|
||||
self.Max.config(image=self.MaxImg,command=ComMax)
|
||||
self.Title.bind("<Double-Button-1>", lambda event:ComMax())
|
||||
self.EmbedParentWindow()
|
||||
|
||||
self.MaxImg = ImageTk.PhotoImage(Image.open(ui_mik+"fullwin_100.png"))
|
||||
self.MaxSmallImg = ImageTk.PhotoImage(Image.open(ui_mik+"togglefull_100.png"))
|
||||
self.Max = tk.Button(self.Title, bg=self.Title.cget("bg"), bd=0, width=40, relief=tk.FLAT, activebackground="#ebedf1",image=self.MaxImg,command=ComMax)
|
||||
self.Max.bind("<Enter>", lambda _: self.Max.config(background="#f2efef"))
|
||||
self.Max.bind("<Leave>", lambda _: self.Max.config(background=self.Title.cget("bg") if self.focus else "#797979"))
|
||||
self.Max.pack(fill=tk.Y, side=tk.RIGHT)
|
||||
self.Title.bind("<Double-Button-1>", lambda event:ComMax())
|
||||
|
||||
self.MinImg = ImageTk.PhotoImage(Image.open(ui_mik+"minisize_100.png"))
|
||||
self.Min = tk.Button(self.Title, bg=self.Title.cget("bg"), bd=0, width=40, relief=tk.FLAT, activebackground="#ebedf1",image=self.MinImg,command=self.stateicon)
|
||||
self.Min.bind("<Enter>", lambda _: self.Min.config(background="#f2efef"))
|
||||
self.Min.bind("<Leave>", lambda _: self.Min.config(background=self.Title.cget("bg") if self.focus else "#797979"))
|
||||
self.Min.pack(fill=tk.Y, side=tk.RIGHT)
|
||||
|
||||
if type(self.TasksFrame) == type(self.Title):
|
||||
self.TaskICOImage=ImageTk.PhotoImage(Image.open(ui_mik+"text_file.png").resize([15,15]))
|
||||
self.TaskICO=tk.Button(self.TasksFrame,image=self.TaskICOImage,bg=TasksFrame.cget("bg"),fg="#000",bd=0,command=self.statenor)
|
||||
self.TaskICO.pack(side=tk.LEFT)
|
||||
|
||||
self.MoveBind()
|
||||
self.EmbedParentWindow()
|
||||
self.deiconify()
|
||||
def MoveBind(self):
|
||||
x=0
|
||||
y=0
|
||||
def start_move(event):
|
||||
nonlocal x, y
|
||||
x = event.x
|
||||
y = event.y
|
||||
def stop_move(event):
|
||||
nonlocal x, y
|
||||
x = None
|
||||
y = None
|
||||
def on_motion(event):
|
||||
nonlocal x, y
|
||||
deltax = event.x - x
|
||||
deltay = event.y - y
|
||||
self.geometry(f"+{self.winfo_x() + deltax}+{self.winfo_y() + deltay}")
|
||||
self.update()
|
||||
self.Title.bind("<ButtonPress-1>", start_move)
|
||||
self.Title.bind("<ButtonRelease-1>", stop_move)
|
||||
self.Title.bind("<B1-Motion>", on_motion)
|
||||
self.TitleText.bind("<ButtonPress-1>", start_move)
|
||||
self.TitleText.bind("<ButtonRelease-1>", stop_move)
|
||||
self.TitleText.bind("<B1-Motion>", on_motion)
|
||||
def destroy(self):
|
||||
if type(self.TasksFrame) == type(self.Title):
|
||||
self.TaskICO.destroy()
|
||||
super().destroy()
|
||||
def stateicon(self):
|
||||
self.wm_overrideredirect(False)
|
||||
self.wm_state("icon")
|
||||
def statenor(self):
|
||||
if self.wm_state() != "normal":
|
||||
self.EmbedParentWindow()
|
||||
self.wm_overrideredirect(True)
|
||||
self.wm_state("normal")
|
||||
self.wm_attributes("-topmost",True)
|
||||
else:
|
||||
self.stateicon()
|
||||
@asyncs
|
||||
def EmbedParentWindow(self):
|
||||
#while True:
|
||||
# if master:
|
||||
# u32.SetParent(u32.GetParent(self.winfo_id()),master.winfo_id())
|
||||
# time.sleep(1)
|
||||
for i in range(10):
|
||||
u32.SetParent(u32.GetParent(self.winfo_id()),master.winfo_id())
|
||||
BIN
sys/kernel/__pycache__/UI.cpython-312.pyc
Normal file
BIN
sys/kernel/__pycache__/UI.cpython-312.pyc
Normal file
Binary file not shown.
BIN
sys/kernel/__pycache__/login.cpython-312.pyc
Normal file
BIN
sys/kernel/__pycache__/login.cpython-312.pyc
Normal file
Binary file not shown.
BIN
sys/kernel/__pycache__/mount.cpython-312.pyc
Normal file
BIN
sys/kernel/__pycache__/mount.cpython-312.pyc
Normal file
Binary file not shown.
BIN
sys/kernel/__pycache__/tools.cpython-312.pyc
Normal file
BIN
sys/kernel/__pycache__/tools.cpython-312.pyc
Normal file
Binary file not shown.
41
sys/kernel/login.py
Normal file
41
sys/kernel/login.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from tools import *
|
||||
|
||||
|
||||
|
||||
|
||||
class login(tk.Frame):
|
||||
def __init__(self,master,bg="./sys/wallpaper/森林1.png",width=1000,height=900,callback=lambda x,y:print(x,y),e=True):
|
||||
super().__init__(master=master)
|
||||
self.bg=bg
|
||||
self.width=width
|
||||
self.height=height
|
||||
self.callback=callback
|
||||
self.e=e
|
||||
self.pack(fill="both",expand=True)
|
||||
self.layer = tk.Canvas(self)
|
||||
self.layer.pack(fill="both",expand=True)
|
||||
|
||||
self.tranimg = Image.open('./sys/wallpaper/translucent.png')
|
||||
self.tranimg = self.tranimg.resize((width-20,height-20))
|
||||
self.tranimg = ImageTk.PhotoImage(self.tranimg)
|
||||
|
||||
self.bgimg = Image.open(bg)
|
||||
self.bgimg = self.bgimg.resize((width,height))
|
||||
self.bgimg = ImageTk.PhotoImage(self.bgimg)
|
||||
self.layer.create_image(0, 0, anchor='nw', image=self.bgimg)
|
||||
self.layer.create_image(width//2,height//2, image=self.tranimg)
|
||||
add_xy=0
|
||||
for i in ["black","dark gray","gray","gray","light gray","white"]:
|
||||
text=self.layer.create_text(245+add_xy,105+add_xy, text="Welcome to MikOS",font=('arial',25),fill=i)
|
||||
#(self.layer.bbox(text)[2] - self.layer.bbox(text)[0])
|
||||
self.layer.move(text, self.width//2-(self.layer.bbox(text)[2] - self.layer.bbox(text)[0])+27.5+add_xy, 0+add_xy)
|
||||
add_xy+=0.5
|
||||
self.button = tk.Button(self, text="登录", bg="sky blue", command=self.login,width = 15,overrelief='sunken',bd=4,cursor="hand2",activebackground="sky blue")
|
||||
self.button.update()
|
||||
self.button.place(x=self.winfo_width()//2-self.button.winfo_width()//2, y=180, anchor="center")
|
||||
def login(self):
|
||||
username="root"
|
||||
userpwd="ROOT"
|
||||
if self.e:
|
||||
self.destroy()
|
||||
self.callback(username,userpwd)
|
||||
124
sys/kernel/main.pyw
Normal file
124
sys/kernel/main.pyw
Normal file
@@ -0,0 +1,124 @@
|
||||
#导入模块
|
||||
from tools import *
|
||||
import login
|
||||
import mount
|
||||
import UI
|
||||
|
||||
|
||||
#操作系统核心
|
||||
class System:
|
||||
def __init__(self):
|
||||
#临时
|
||||
self.username="root"
|
||||
|
||||
|
||||
#将程序工作目录改到系统根目录
|
||||
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
|
||||
|
||||
self.ReadConfig()
|
||||
|
||||
mount.endMount(self.DiskSite+":")#取消挂载虚拟磁盘,以防止过去的过期记录影响正常挂载
|
||||
if not mount.Mount("\\".join(os.getcwd().split("\\")[:-2]),self.DiskSite+":"):#挂载虚拟磁盘,如果返回值为False,表示错误,加not变为True,运行If语句内容
|
||||
print("EFI: Error, Mount DiskSite "+self.DiskSite+" not true")#输出虚拟磁盘挂载错误信息
|
||||
os._exit(0)#补上的,如果运行失败程序需要停止运行
|
||||
os.chdir(self.DiskSite+":")#将目录转移至虚拟磁盘
|
||||
|
||||
|
||||
self.root = tk.Tk()
|
||||
self.root.title('MikOS')
|
||||
# 通过config.json个性化窗口
|
||||
for i in self.config["res"]["set"]:
|
||||
if i == "full":
|
||||
self.root.state("zoomed")
|
||||
elif i == "overrideredirect":
|
||||
self.root.overrideredirect(True)
|
||||
else:
|
||||
print(f"Error: {i} no know")
|
||||
UI.index(self.root,self.width,self.height)
|
||||
self.root.update()
|
||||
|
||||
self.StartSysApp("explorer","__init__.mia")
|
||||
|
||||
self.root.protocol("WM_DELETE_WINDOW",self.CloseEvent)
|
||||
self.root.mainloop()
|
||||
def ReadConfig(self):
|
||||
#获取配置文件
|
||||
self.config=json.loads(openr("../config/config.json")) #全部配置句柄
|
||||
self.width=self.config["res"]["width"] #窗口长
|
||||
self.height=self.config["res"]["height"] #窗口宽
|
||||
self.chicun=str(self.width)+"x"+str(self.height) #窗口长宽(可直接应用到self.root.geometry)
|
||||
self.EFI=self.config["EFI"] #引导(EFI)配置句柄
|
||||
self.Kernel=self.config["Kernel"] #内核(Kernel)配置句柄
|
||||
self.DOS=self.config["DOS"] #命令行(DOS)配置句柄
|
||||
self.DiskSite=self.EFI["DiskSite"] #虚拟磁盘挂载地址
|
||||
self.BootSite=self.EFI["BootSite"] #操作系统程序文件所在
|
||||
self.SysAppSite=self.BootSite+self.Kernel["SysAppSite"] #系统级程序文件所在
|
||||
self.NorAppSite=self.Kernel["NorAppSite"] #全局用户级程序文件所在
|
||||
self.ui_mik=self.BootSite+self.Kernel["ui"] #MikOs窗口图标文件所在
|
||||
self.images_mik=self.BootSite+self.Kernel["images"] #MikOs桌面图标文件所在
|
||||
self.tkinter_mik=self.BootSite+self.Kernel["tkinter"] #MikOs-Tkinter支持文件所在
|
||||
UI.ui_mik=self.ui_mik #将MikOs窗口图标文件所在注册到UI
|
||||
UI.tkinter_mik=self.tkinter_mik #将MikOs-Tkinter支持文件所在注册到UI
|
||||
self.UsersSite=self.Kernel["UsersSite"] #用户组文件所在
|
||||
self.bg=self.BootSite+self.config["bg"]["sys"] #桌面壁纸
|
||||
self.suffixs=self.config["suffixs"] #文件图标后缀关联
|
||||
self.filesuffixs=self.config["filesuffixs"] #文件名称图标关联(无后缀但需显示图标文件)(如:MakeFile)
|
||||
self.color=self.config["color"] #主题色配置句柄
|
||||
self.SysFileSuffixMapping=self.config["SysFileSuffixMapping"] #文件功能后缀关联
|
||||
def CloseEvent(self):#关闭事件
|
||||
if tm.askokcancel('MikOS:提示','确认要关闭MikOS吗?'):
|
||||
os._exit(0)
|
||||
def ERROR(self,WrongDevice,IOFlowErrorMessage,DebuggerApp,MemoryAddresss,EndMemoryAddress):
|
||||
ERROR=tk.Frame(self.root,bg="#000")
|
||||
ERROR.place(x=0,y=0)
|
||||
def Text(text):
|
||||
tk.Label(ERROR,text=text,fg="#FFF",bg="#000",font=("Moder DOS 437",15)).pack(anchor="sw")
|
||||
def FText():
|
||||
tk.Label(ERROR,text="",bg="#000",font=("Moder DOS 437",15)).pack(anchor="sw")
|
||||
Text("There are some problems with your MikOS,")
|
||||
Text("This may come from MikOs itself or some of its settings,")
|
||||
Text("Python version problems, Or because of your own external operating system,")
|
||||
Text("In short, MikOs has an error, We are not sure if the program can still run normally,")
|
||||
Text("So we interrupted the program, But there may be some subprograms that have not")
|
||||
Text("stopped completely, We can only do it here, the following are some error prompts")
|
||||
FText()
|
||||
Text(f'Error({WrongDevice}): "{IOFlowErrorMessage}"')
|
||||
Text(f"Debugger Called: <{DebuggerApp}>")
|
||||
Text("Specific Error Points:")
|
||||
for i in MemoryAddresss:Text(f"{i[0]} : {i[1]} ()")
|
||||
Text(f"Error Terminated At {{EndMemoryAddress}} Memory Pointer")
|
||||
FText()
|
||||
Text("Operating System Has Been Terminated")
|
||||
FText()
|
||||
Text("Kernel version:")
|
||||
Text(f"MikOS Kernel V{self.Kernel['VerSion']} / EFI Boot System V{self.EFI['VerSion']}")
|
||||
FText()
|
||||
FText()
|
||||
FText()
|
||||
def StartSysApp(self,appname,file,*args,**kw):
|
||||
self.global_dict=globals()
|
||||
self.global_dict["args"]=args
|
||||
self.global_dict["kw"]=kw
|
||||
self.global_dict["app_info"]={"path":self.SysAppSite+"/"+appname+"/"}
|
||||
self.global_dict["OperatingSystemHandle"]=self
|
||||
code=openr(self.global_dict["app_info"]["path"]+file)
|
||||
exec(code,self.global_dict)
|
||||
def StartApp(self,appname,file,*args,**kw):
|
||||
self.global_dict=globals()
|
||||
self.global_dict["args"]=args
|
||||
self.global_dict["kw"]=kw
|
||||
self.global_dict["app_info"]={"path":self.NorAppSite+"/"+appname+"/"}
|
||||
self.global_dict["OperatingSystemHandle"]=self
|
||||
code=openr(self.global_dict["app_info"]["path"]+file)
|
||||
exec(code,self.global_dict)
|
||||
def StartFile(self,File=str,*args):
|
||||
if os.path.isfile(File):
|
||||
if (suffix := File.split(".")[-1].lower()) in self.SysFileSuffixMapping:
|
||||
self.StartSysApp(self.SysFileSuffixMapping[suffix],"__init__.mia",f=File,*args)
|
||||
|
||||
#免登录
|
||||
#login.login(root,bg=BootSite+config["bg"]["login"],width=root.winfo_width(),height=root.winfo_height(),callback=verifylogin)
|
||||
System()
|
||||
s=tk.Tk()#堵塞进程
|
||||
s.withdraw()
|
||||
s.mainloop()
|
||||
16
sys/kernel/mount.py
Normal file
16
sys/kernel/mount.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import os
|
||||
|
||||
def Mount(dir,Note):
|
||||
get=os.popen(f"subst {Note} {dir}").read()
|
||||
if get==f"无效参数 - {Note}\n":
|
||||
return "error:Note"
|
||||
elif get==f"找不到路径 - {dir}\n":
|
||||
return "error:dir"
|
||||
else:
|
||||
return True
|
||||
def endMount(Note):
|
||||
get=os.popen(f"subst {Note} /d").read()
|
||||
if get==f"无效参数 - {Note}\n":
|
||||
return "error:Note"
|
||||
else:
|
||||
return True
|
||||
321
sys/kernel/tools.py
Normal file
321
sys/kernel/tools.py
Normal file
@@ -0,0 +1,321 @@
|
||||
#550W 工具箱
|
||||
#所需模块
|
||||
#UI库
|
||||
import tkinter.filedialog as tf
|
||||
import tkinter.messagebox as tm
|
||||
import tkinter.constants as Keys
|
||||
import tkinter.ttk as ttk
|
||||
import tkinter as tk
|
||||
import os
|
||||
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"]=""#阻止pygame-print
|
||||
import pygame
|
||||
try:
|
||||
pygame.mixer.init()
|
||||
except:
|
||||
print("PyGame InIt Error")
|
||||
#系统库
|
||||
import tempfile
|
||||
import sys,os
|
||||
from io import BytesIO
|
||||
import platform
|
||||
import getpass
|
||||
import psutil
|
||||
import shutil
|
||||
import traceback
|
||||
import ctypes
|
||||
import wmi
|
||||
u32=ctypes.windll.user32
|
||||
#文件库
|
||||
import configparser
|
||||
import zipfile
|
||||
import json
|
||||
#编码库
|
||||
import binascii
|
||||
import hashlib
|
||||
import base64
|
||||
import uuid
|
||||
import re
|
||||
#进程库
|
||||
from threading import Thread
|
||||
import asyncio
|
||||
import subprocess
|
||||
import pystray
|
||||
#时间库
|
||||
import datetime,time
|
||||
#图像库
|
||||
from PIL import Image,ImageTk,ImageDraw
|
||||
import cv2
|
||||
#网页库
|
||||
import urllib
|
||||
import flask
|
||||
import flask_socketio
|
||||
#数学库
|
||||
import random
|
||||
import numpy
|
||||
import math
|
||||
import copy
|
||||
#音频库
|
||||
import pyaudio
|
||||
import wave
|
||||
|
||||
|
||||
#基础变量
|
||||
temp=os.environ["temp"]
|
||||
#Windows管理接口
|
||||
WindowsManagementInterface=wmi.WMI()
|
||||
|
||||
#UUID
|
||||
def GUUID():
|
||||
return str(uuid.uuid3(uuid.NAMESPACE_DNS, str(random.randint(0, 10000000000000000000))))
|
||||
# 读/写/添
|
||||
def openw(file, write, mode="1", encoding="UTF-8"):
|
||||
if mode == "1" or mode == 1:
|
||||
with open(file, "w", encoding=encoding) as f:
|
||||
f.write(write)
|
||||
elif mode == "2" or mode == 2:
|
||||
with open(file, "wb") as f:
|
||||
f.write(write)
|
||||
|
||||
def opena(file, write, mode="1", encoding="UTF-8"):
|
||||
if mode == "1" or mode == 1:
|
||||
with open(file, "a", encoding=encoding) as f:
|
||||
f.write(write)
|
||||
elif mode == "2" or mode == 2:
|
||||
with open(file, "ab") as f:
|
||||
f.write(write)
|
||||
|
||||
def openr(file, mode="1", encoding="UTF-8"):
|
||||
if mode == "1" or mode == 1:
|
||||
with open(file, "r", encoding=encoding) as f:
|
||||
read = f.read()
|
||||
elif mode == "2" or mode == 2:
|
||||
with open(file, "rb") as f:
|
||||
read = f.read()
|
||||
return read
|
||||
|
||||
def MakeTempFile(write):
|
||||
tmp_file = tempfile.NamedTemporaryFile(delete=True)
|
||||
tmp_file.write(write)
|
||||
tmp_file.close()
|
||||
return tmp_file
|
||||
|
||||
def MakeTempFilePattern(suffix=".tmp",delete=True):
|
||||
with tempfile.NamedTemporaryFile(suffix='.png', delete=delete) as tmp_file:
|
||||
return tmp_file
|
||||
|
||||
#MP3播放
|
||||
def MP3Play(mp3_path,volume=10,sleep=-1):
|
||||
pygame.mixer.music.load(mp3_path) # 加载音乐
|
||||
pygame.mixer.music.set_volume(volume)# 设置音量大小0~1的浮点数
|
||||
pygame.mixer.music.play() # 播放音频
|
||||
if sleep == -1:
|
||||
time.sleep(get_duration_wave(mp3_path))
|
||||
else:
|
||||
time.sleep(sleep)
|
||||
|
||||
#MP3时间获取
|
||||
def get_duration_wave(file_path):
|
||||
with wave.open(file_path, "r") as audio_file:
|
||||
frame_rate = audio_file.getframerate()
|
||||
n_frames = audio_file.getnframes()
|
||||
duration = n_frames / float(frame_rate)
|
||||
return duration
|
||||
|
||||
#时间格式化
|
||||
def TimeFormat(s,end=""):
|
||||
return time.strftime("[%Y/%m/%d %H:%M:%S]: "+str(s)+end, time.localtime())
|
||||
|
||||
def TimeFormatStr(s="%Y/%m/%d %H:%M:%S",end=""):
|
||||
return time.strftime(s+end, time.localtime())
|
||||
|
||||
def TimeFormatv(make_uuid=True):
|
||||
return datetime.datetime.now().strftime("%Y年%m月%d日-%H时%M分%S秒%f毫"+"-"+str(uuid.uuid3(uuid.NAMESPACE_DNS, str(random.randint(0, 10000000000000000000)))))
|
||||
|
||||
def Is_TrueColorCode(code):
|
||||
pattern = re.compile(r'^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$')
|
||||
return bool(pattern.match(code))
|
||||
|
||||
#Base64转图片
|
||||
def base64_to_image(base64_str: str) -> Image.Image:
|
||||
base64_data = re.sub("^data:image/.+;base64,", "", base64_str)
|
||||
byte_data = base64.b64decode(base64_data)
|
||||
image_data = BytesIO(byte_data)
|
||||
img = Image.open(image_data)
|
||||
return img
|
||||
|
||||
#图片转Base64
|
||||
def image_to_base64(image: Image.Image, fmt="png") -> str:
|
||||
output_buffer = BytesIO()
|
||||
image.save(output_buffer, format=fmt)
|
||||
byte_data = output_buffer.getvalue()
|
||||
base64_str = base64.b64encode(byte_data).decode("utf-8")
|
||||
return f"data:image/{fmt};base64," + base64_str
|
||||
|
||||
#返回"没有文件"错误类型
|
||||
def ReturnFileNotFoundError(InFo,file):
|
||||
ERROR=FileNotFoundError(InFo)
|
||||
ERROR.filename=file
|
||||
|
||||
#判断ini文件是否正确
|
||||
def IS_INI(ini_file):
|
||||
#创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
#读取INI文件
|
||||
try:
|
||||
#尝试读取
|
||||
config.read(ini_file)
|
||||
except configparser.Error as e:
|
||||
#报错
|
||||
return False
|
||||
else:
|
||||
#没有报错
|
||||
return True
|
||||
|
||||
#ini转字典
|
||||
def INI2DICT(ini_file):
|
||||
#创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
#读取INI文件
|
||||
config.read(ini_file)
|
||||
#创建二级字典
|
||||
config_dict = {}
|
||||
#遍历INI文件的sections
|
||||
for section in config.sections():
|
||||
#创建子字典
|
||||
section_dict = {}
|
||||
#遍历每个section中的options
|
||||
for option in config.options(section):
|
||||
#将选项和值添加到子字典中
|
||||
section_dict[option] = config.get(section, option)
|
||||
#将子字典添加到二级字典中
|
||||
config_dict[section] = section_dict
|
||||
#返回文件
|
||||
return config_dict
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def WriteToFile(content, filename):
|
||||
with open(filename, "wb") as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#信息结构体
|
||||
class InFo:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
#异步装饰器
|
||||
def asyncs(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
thr = Thread(target = f, args = args, kwargs = kwargs)
|
||||
thr.start()
|
||||
return wrapper
|
||||
|
||||
|
||||
#获取多个文件MD5(自匹配)
|
||||
def GetFilesMD5(*file_paths):
|
||||
md5_list = []
|
||||
for file_path in file_paths:
|
||||
md5_list.append(GetFileMD5(file_path))
|
||||
return md5_list
|
||||
|
||||
def GetFileMD5(file_name):
|
||||
"""
|
||||
计算文件的md5
|
||||
:param file_name:
|
||||
:return:
|
||||
"""
|
||||
m = hashlib.md5()
|
||||
with open(file_name,'rb') as fobj:
|
||||
while True:
|
||||
data = fobj.read(4096)
|
||||
if not data:
|
||||
break
|
||||
m.update(data)
|
||||
return m.hexdigest()
|
||||
def GetStrMD5(content):
|
||||
"""
|
||||
计算字符串md5
|
||||
:param content:
|
||||
:return:
|
||||
"""
|
||||
m = hashlib.md5(content)
|
||||
return m.hexdigest()
|
||||
def GetDirFileMD5(Dir):
|
||||
"""
|
||||
计算文件夹所有文件(二枝树算法)
|
||||
:param Dir:
|
||||
:return list:
|
||||
"""
|
||||
MD5S=[]
|
||||
if not os.path.isdir(Dir):
|
||||
#No Use raise
|
||||
return FileNotFoundError()
|
||||
for i in os.listdir(Dir):
|
||||
if os.path.isfile(os.path.normpath(Dir+"/"+i)):
|
||||
MD5S.append({"FileName":os.path.normpath(Dir+"/"+i),"Type":"File","MD5":GetFileMD5(os.path.normpath(Dir+"/"+i))})
|
||||
if os.path.isdir(os.path.normpath(Dir+"/"+i)):
|
||||
MD5S.append({"FileName":os.path.normpath(Dir+"/"+i),"Type":"Dir","ChildRen":GetDirFileMD5(os.path.normpath(Dir+"/"+i))})
|
||||
return MD5S
|
||||
|
||||
def IsDirFileMD5(MD5List,Dir,Bind=lambda x:None,sleep=0):
|
||||
for i in MD5List:
|
||||
s=copy.deepcopy(i)
|
||||
s["ChildRen"]="Pass"
|
||||
Bind(s["FileName"])
|
||||
time.sleep(sleep)
|
||||
if i["Type"]=="File":
|
||||
if not os.path.isfile(i["FileName"]):
|
||||
return False,1,i["FileName"]
|
||||
if not GetFileMD5(i["FileName"]) == i["MD5"]:
|
||||
return False,2,i["FileName"]
|
||||
if i["Type"]=="Dir":
|
||||
if not os.path.isdir(i["FileName"]):
|
||||
return False,3,i["FileName"]
|
||||
Thing=IsDirFileMD5(i["ChildRen"],i["FileName"],Bind,sleep)
|
||||
if not Thing[0]:
|
||||
return False,4,i["FileName"],Thing
|
||||
return (True,1)
|
||||
|
||||
|
||||
#获取所有可用的摄像头设备
|
||||
def get_available_cameras():
|
||||
camera_list = []
|
||||
index = 0
|
||||
while True:
|
||||
cap = cv2.VideoCapture(index)
|
||||
if not cap.read()[0]:
|
||||
break
|
||||
else:
|
||||
camera_list.append(index)
|
||||
cap.release()
|
||||
index += 1
|
||||
return camera_list
|
||||
|
||||
class Mod_Var():
|
||||
def __init__(self):
|
||||
self.Global={}
|
||||
|
||||
|
||||
class FileVarToVar():
|
||||
def __init__(self,Var):
|
||||
N2={}
|
||||
if not type(Var) == type({}):
|
||||
raise TypeError("Var Not Is Dict")
|
||||
for i in Var:
|
||||
if len(i) > 2:
|
||||
if not i[0:2] == "__":
|
||||
if not i[-2:] == "__":
|
||||
N2[i]=Var[i]
|
||||
self.Global=N2
|
||||
ToolsGlobalVar=FileVarToVar(globals())
|
||||
ToolsGlobal=ToolsGlobalVar.Global
|
||||
Reference in New Issue
Block a user