url 9 months ago
parent 4dbff8d4c5
commit e214f96578

@ -4,135 +4,457 @@ from tkinter import ttk
import tkinter as tk
import tkinter.font as tkFont
import tkinter.messagebox as messagebox #弹窗
#主界面
class StartPage:
def __init__(self, parent_window):
parent_window.destroy()#销毁子界面
#parent_window.destroy()#销毁子界面
self.window = tk.Tk()
self.window.title('某期刊的在线投稿审稿管理系统')
self.window.geometry('300x470')
self.window.geometry('500x600')
label=Label(self.window,text="某期刊的在线投稿审稿管理系统",font=("Verdana",20))
label.pack(pady=100)#pady=100界面的长度
Button(self.window,text="作者登录",font=tkFont.Font(size=16),command=lambda:Authorlogin,
height=2,fg='white',bg='gray',activebackground='black',activeforeground='white').place(pady=25)
Button(self.window,text="审稿人登录",font=tkFont.Font(size=16),command=lambda:Reviewerlogin,
height=2,fg='white',bg='gray',activebackground='black',activeforeground='white').place(pady=25)
Button(self.window,text="作者登录",font=tkFont.Font(size=16),command=Authorlogin,
height=2,fg='white',bg='gray',activebackground='black',activeforeground='white').pack(pady=25)
Button(self.window,text="审稿人登录",font=tkFont.Font(size=16),command=Reviewerlogin,
height=2,fg='white',bg='gray',activebackground='black',activeforeground='white').pack(pady=25)
self.window.mainloop()#主消息循环
def login(self):
print(str(self.author_account.get()))
print(str(self.author_password.get()))
author_password=None
#数据库操作 查询作者表
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
#cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor()#使用cursor方法获取操作游标
sql="select * from author where author_account='%s'" % self.author_account.get()
try:
#执行sql语句
cursor.execute(sql)
#获取所有记录列表
result = cursor.fetchall()
for row in result:
author_id=row[0]
author_password=row[1]
#打印结果
print("author_id=%s,author_password=%s" % (author_id,author_password))
except:
print("Error:unable to fecth date")
messagebox.showinfo("Error", "Author not found.")
db.close()
print("正在登录作者界面")
print("self",self.author_password)
print("local",author_password)
if self.author_password.get()==author_password:
AuthorManage(self.window)#进入作者操作界面
else:
messagebox.showinfo("Error", "Author not found.")
def back(self):
StartPage(self.window)#显示主窗口 销毁本窗口
def login(self):
print(str(self.reviewer_account.get()))
print(str(self.reviewer_password.get()))
reviewer_password=None
#数据库操作 查询作者表
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
#cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor()#使用cursor方法获取操作游标
sql="select * from reviewer where author_account='%s'" % self.reviewer_account.get()
try:
#执行sql语句
cursor.execute(sql)
#获取所有记录列表
result = cursor.fetchall()
for row in result:
reviewer_id=row[0]
reviewer_password=row[1]
#打印结果
print("author_id=%s,reviewer_password=%s" % (reviewer_id,reviewer_password))
except:
print("Error:unable to fecth date")
messagebox.showinfo("Error", "Author not found.")
db.close()
print("正在登录作者界面")
print("self",self.reviewer_password)
print("local",reviewer_password)
if self.reviewer_password.get()==reviewer_password:
ReviewerManage(self.window)#进入作者操作界面
else:
messagebox.showinfo("")
def back(self):
StartPage(self.window)#显示主窗口 销毁本窗口
def back(self):
#parent_window.destroy() # 销毁子界面
StartPage(self.window)
#作者账号设置
class Authorlogin:
def __init__(self,parent_window):
parent_window.destroy()
self.window=tk.Tk()#初始框的声明
def __init__(self):
self.window = tk.Tk() # 初始窗口的声明
self.window.title('请先登录作者账户')
self.window.geometry('500x500')
label=tk.Label(self.window,text='作者登录',bg='pink',ront=('Verdana',20),width=30,height=40)
label = tk.Label(self.window, text='作者登录', bg='pink', font=('Verdana', 20), width=30, height=4)
label.pack()
label(self.window,text='作者账号:',font=tkFont.Font(size=14)).pack(pady=25)
self.author_account=tk.Entry(self.window,font=tkFont.Font(size=14))
# 注意这里应使用tk.Label而不是label它是一个已经定义的变量
tk.Label(self.window, text='作者账号:', font=tkFont.Font(size=14)).pack(pady=25)
self.author_account = tk.Entry(self.window, font=tkFont.Font(size=14))
self.author_account.pack()
Label(self.window,text='作者密码:',font=tkFont.Font(size=14)).pack(pady=25)
self.author_password=tk.Entry(self.window,font=tkFont.Font(size=14),bg='Ivory',show='*')
tk.Label(self.window, text='作者密码:', font=tkFont.Font(size=14)).pack(pady=25)
self.author_password = tk.Entry(self.window, font=tkFont.Font(size=14), bg='Ivory', show='*')
self.author_password.pack()
Button(self.window,text="修改密码",width=8,font=tkFont.Font(size=12),command=self.login_change).pack(pady=25)
Button(self.window, text="创建账号", width=8, font=tkFont.Font(size=12), command=self.login_create).pack(pady=25)
Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back).pack(pady=25)
self.window.protocol("WM_DELETE_WINDOW",self.back)#捕捉右上角关闭点击
self.window.mainloop()#进入消息循环
# 使用lambda表达式传递无参数的函数给command
tk.Button(self.window, text="登录", width=8, font=tkFont.Font(size=12), command=lambda:self.login()).pack(
pady=25)
# 您可能还想添加一个“取消”或“返回”按钮
tk.Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=lambda :self.back).pack(pady=25)
self.window.mainloop() # 进入消息循环
def login(self):
account = self.author_account.get()
password_input = self.author_password.get()
# 数据库操作 查询作者表
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8'
# cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor() # 使用cursor方法获取操作游标
sql = "select * from author where author_account='%s'" % self.author_account.get()
try:
# 执行sql语句
cursor.execute(sql)
# 获取所有记录列表
result = cursor.fetchall()
for row in result:
author_account = row[4]
author_password = row[5]
# 打印结果
print("author_account=%s,author_password=%s" % (author_account, author_password))
except:
print("Error:unable to fecth date")
messagebox.showinfo("Error", "Author not found.")
db.close()
print("正在登录作者界面")
print("local", author_password)
if self.author_password.get() == author_password:
Authormanage(self.window) # 进入作者操作界面
else:
messagebox.showinfo("Error", "Author not found.")
def back(self):
self.window.destroy() # 销毁窗口结束Tkinter消息循环
# 设置WM_DELETE_WINDOW协议以调用back方法
self.window.protocol("WM_DELETE_WINDOW",self.back())
#审稿人账号设置
class Reviewerlogin:
def __init__(self,parent_window):
parent_window.destroy()
self.window=tk.Tk()#初始框的声明
def __init__(self):
self.window = tk.Tk() # 初始窗口的声明
self.window.title('请先登录审稿人账户')
self.window.geometry('500x500')
label=tk.Label(self.window,text='审稿人登录',bg='green',ront=('Verdana',20),width=30,height=40)
label = tk.Label(self.window, text='作者登录', bg='green', font=('Verdana', 20), width=30, height=4)
label.pack()
label(self.window,text='审稿人账号:',font=tkFont.Font(size=14)).pack(pady=25)
self.reviewer_account=tk.Entry(self.window,font=tkFont.Font(size=14))
# 注意这里应使用tk.Label而不是label它是一个已经定义的变量
tk.Label(self.window, text='审稿人账号:', font=tkFont.Font(size=14)).pack(pady=25)
self.reviewer_account = tk.Entry(self.window, font=tkFont.Font(size=14))
self.reviewer_account.pack()
Label(self.window,text='作者密码:',font=tkFont.Font(size=14)).pack(pady=25)
self.reviewer_password=tk.Entry(self.window,font=tkFont.Font(size=14),bg='Ivory',show='*')
tk.Label(self.window, text='审稿人密码:', font=tkFont.Font(size=14)).pack(pady=25)
self.reviewer_password = tk.Entry(self.window, font=tkFont.Font(size=14), bg='Ivory', show='*')
self.reviewer_password.pack()
Button(self.window,text="修改密码",width=8,font=tkFont.Font(size=12),command=self.login_change).pack(pady=25)
Button(self.window, text="创建账号", width=8, font=tkFont.Font(size=12), command=self.login_create).pack(pady=25)
Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back).pack(pady=25)
self.window.protocol("WM_DELETE_WINDOW",self.back)#捕捉右上角关闭点击
self.window.mainloop()#进入消息循环
# 使用lambda表达式传递无参数的函数给command
tk.Button(self.window, text="登录", width=8, font=tkFont.Font(size=12), command=lambda: self.login()).pack(
pady=25)
# 您可能还想添加一个“取消”或“返回”按钮
tk.Button(self.window, text="返回首页", width=8, font=tkFont.Font(size=12), command=self.back).pack(pady=25)
self.window.mainloop() # 进入消息循环
def login(self):
account = self.reviewer_account.get()
password_input = self.reviewer_password.get()
# 数据库操作 查询作者表
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
# cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor() # 使用cursor方法获取操作游标
sql = "select * from reviewer where reviewer_account='%s'" % self.reviewer_account.get()
try:
# 执行sql语句
cursor.execute(sql)
# 获取所有记录列表
result = cursor.fetchall()
for row in result:
reviewer_account = row[4]
reviewer_password = row[5]
# 打印结果
print("reviewer_account=%s,reviewer_password=%s" % (reviewer_account, reviewer_password))
except:
print("Error:unable to fecth date")
messagebox.showinfo("Error", "Author not found.")
db.close()
print("正在登录审稿人界面")
print("self", self.reviewer_name)
print("local", reviewer_password)
if self.reviewer_password.get() == reviewer_password:
Reviewermaanage(self.window) # 进入审稿人操作界面
else:
messagebox.showinfo("Error", "Author not found.")
def back(self):
self.window.destroy() # 销毁窗口结束Tkinter消息循环
# 设置WM_DELETE_WINDOW协议以调用back方法
self.window.protocol("WM_DELETE_WINDOW", self.back())
self.window.mainloop() # 进入消息循环
#作者操作界面
class Authormanage:
def __init__(self,parent_window):
parent_window.destroy()#销毁主界面
self.window=tk.Tk()#初始框的声明
self.window.title('作者操作界面')
self.frame_left_top=tk.Frame(height=200,width=300).pack(pady=10)
self.frame_right_top=tk.Frame(height=200,width=200).pack(pady=10)
self.frame_center=tk.Frame(height=400,width=500).pack(pady=10)
self.frame_bottom=tk.Frame(height=50,width=650).pack(pady=10)
#定义下方中心列表区域
self.columns=("编号","内容","类型","标题")
self.tree=ttk.Treeview(self.frame_center)
self.vbar=ttk.Scrollbar(self.frame_center,orient=tk.VERTICAL)
self.vbar.pack(side=tk.RIGHT,fill=tk.Y)
#定义树形结构与滚动条
self.tree.configure(yscrollcommand=self.vbar.set)
#表格的标题
self.tree.column("编号",width=150,anchor='center')
self.tree.column("内容",width=150,anchor='center')
self.tree.column("类型",width=100,anchor='center')
self.tree.column("标题",width=100,anchor='center')
#调用方法获取表格内容插入
self.tree.grid(row=0,column=0,sticky=NSEW)
self.vbar.grid(row=0,column=1,sticky=NS)
self.manuscript_id=[]
self.manuscript_content=[]
self.manuscript_type=[]
self.manuscript_title=[]
#打开数据库连接
db=pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8'
)
cursor=db.cursor()
sql="SELECT * FROM manuscript"#查询稿件表
try:
#执行sql语句
cursor.execute(sql)
#获取所有记录列表
result=cursor.fetchall()
for row in result:
self.manuscript_id.append(row[0])
self.manuscript_content.append(row[1])
self.manuscript_type.append(row[2])
self.manuscript_title.append(row[3])
except:
print("Error:unable to fetch data")
messagebox.showinfo('警告!','数据库连接失败!')
db.close()
print("test*********************************************")
for i in range(len(min(len(self.manuscript_id))),len(self.manuscript_content),len(self.manuscript_type),len(self.manuscript_title)):
self.tree.insert('',i,
values=(self.manuscript_id[i],
self.manuscript_content[i],
self.manuscript_type[i],
self.manuscript_title[i]))
for col in self.columns:#绑定函数,使表头可排序
self.tree.heading(col, text=col,
command=lambda _col=col:self.tree_sort_column(self.tree,_col))
#定义顶部区域和定义左上方区域
self.top_title=Label(self.frame_left_top,text="稿件信息:",font=('Verdana',20))
self.top_title.grid(row=0,column=0,sticky=NSEW,columnspan=2,padx=50,pady=10)
self.left_top_frame=tk.Frame(self.frame_left_top)
self.var_manuscript_id=StringVar()#声明稿件编号
self.var_manuscript_content=StringVar()
self.var_manuscript_type=StringVar()
self.var_manuscript_title=StringVar()
#稿件编号
self.right_top_manuscript_id_label=Label(self.frame_left_top,text="编号:",font=('Verdana',15))
self.right_top_manuscript_id_entry=Entry(self.frame_right_top,textvariable=self.var_manuscript_id,font=tkFont.Font(size=14))
self.right_top_manuscript_id_label.grid(row=1,column=0)#位置设置
self.right_top_manuscript_id_entry.grid(row=1,column=1)
#稿件内容
self.right_top_manuscript_content_label = Label(self.frame_left_top, text="内容:", font=('Verdana', 15))
self.right_top_manuscript_content_entry = Entry(self.frame_right_top, textvariable=self.var_manuscript_content,font=tkFont.Font(size=14))
self.right_top_manuscript_content_label.grid(row=2, column=0) # 位置设置
self.right_top_manuscript_content_entry.grid(row=2, column=1)
#稿件类型
self.right_top_manuscript_type_label = Label(self.frame_left_top, text="类型:", font=('Verdana', 15))
self.right_top_manuscript_type_entry = Entry(self.frame_right_top, textvariable=self.var_manuscript_type,
font=tkFont.Font(size=14))
self.right_top_manuscript_type_label.grid(row=3, column=0) # 位置设置
self.right_top_manuscript_type_entry.grid(row=3, column=1)
#稿件标题
self.right_top_manuscript_title_label = Label(self.frame_left_top, text="标题:", font=('Verdana', 15))
self.right_top_manuscript_title_entry = Entry(self.frame_right_top, textvariable=self.var_manuscript_title,
font=tkFont.Font(size=14))
self.right_top_manuscript_title_label.grid(row=4, column=0) # 位置设置
self.right_top_manuscript_title_entry.grid(row=4, column=1)
#定义右上方区域
self.right_top_title=Label(self.frame_right_top,text="操作:",font=('Verdana', 20))
self.tree.bind('<Button-1>',self.click)#左键获取
self.right_top_button1=ttk.Button(self.frame_right_top,text='添加',width=20,command=self.new_row)
self.right_top_button1 = ttk.Button(self.frame_right_top, text='更新', width=20, command=self.update_row)
self.right_top_button1 = ttk.Button(self.frame_right_top, text='删除', width=20, command=self.del_row)
#位置设置
self.right_top_title.grid(row=1, column=0,pady=10)
self.right_top_button1.grid(row=2,column=0,pady=10, padx=10)
self.right_top_button2.grid(row=3, column=0, pady=10, padx=10)
self.right_top_button3.grid(row=4, column=0, pady=10, padx=10)
#整体区域定位
self.frame_left_top.grid(row=0,column=0,columnspan=2,padx=2,pady=5)
self.frame_right_top.grid(row=0,column=1,columnspan=2,padx=30,pady=30)
self.frame_center.grid(row=1,column=0,columnspan=2,padx=4,pady=5)
self.frame_bottom.grid(row=1,column=0,columnspan=2)
self.frame_left_top.grid_propagate(0)
self.frame_right_top.grid_propagate(0)
self.frame_center.grid_propagate(0)
self.frame_bottom.grid_propagate(0)
self.frame_left_top.tkraise()#开始显示主菜单
self.frame_right_top.tkraise()
self.frame_center.tkraise()
self.frame_bottom.tkraise()
self.window.protocol("WM_DELETE_WINDOW",self.back)#捕捉右上方关闭点击
def back(self):
StartPage(self.window)#显示主窗口 销毁本窗口
def click(self,event):
self.col=self.tree.identify_column(event.x)#列
self.row=self.tree.identify_row(event.y)#行
print(self.col)
print(self.row)
self.row_info=self.tree.item(self.row,"values")
self.var_manuscript_id.set(self.row_info[0])
self.var_manuscript_content.set(self.row_info[1])
self.var_manuscript_type.set(self.row_info[2])
self.var_manuscript_title.set(self.row_info[3])
self.right_top_manuscript_id_entry=Entry(self.frame_left_top,textvariable=self.var_manuscript_id,font=tkFont.Font(size=14))
print('')
def tree_sort_column_by_id(self, tv, col, reverse=False):
# 假设id是Treeview条目中的一个值并且我们想要根据这个id进行排序
def get_id(manuscript_id):
# 获取条目的id值这里假设id是Treeview条目的一个值
return int(tv.item(manuscript_id, 'values')[manuscript_id]) # index_of_id是id在values中的索引
# 获取所有子项的id和它们的id-item_id对
items = [(get_id(k), k) for k in tv.get_children('')]
# 根据id进行排序
items.sort(key=lambda x: x[0], reverse=reverse)
# 清空Treeview以重新插入排序后的条目可选取决于你的需求
# for item in tv.get_children(''):
# tv.delete(item)
# 根据排序后的顺序重新插入或移动条目
for index, (id_value, item_id) in enumerate(items):
# 如果Treeview是空的或者我们需要重新插入所有条目则使用insert
# 否则只使用move方法移动现有的条目
if index == 0:
# 第一个条目或者Treeview是空的使用insert
tv.insert('', 'end', item_id, values=tv.item(item_id, 'values'))
else:
# 其他条目使用move
prev_item_id = items[index - 1][1]
tv.move(item_id, '', tv.index(prev_item_id) + 1) # +1是因为index是从0开始的但Treeview的索引是从1开始的
# 更新列标题的排序箭头和点击事件(如果需要)
def sort_command():
self.tree_sort_column_by_id(tv, col, not reverse)
tv.heading(col, text=col, command=sort_command)
# 注意你需要知道id在values中的索引这里用index_of_id表示
# 例如如果你的Treeview条目的values是(id, name, date)那么index_of_id就是0
def update_row(self):
res=messagebox.askyesnocancel('警告!','是否更新所填写的数据?')
if res==True:
if self.var_manuscript_id.get()==self.row_info[0]:#如果所填编号和所选编号相同则打开数据库
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
# cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
db=db.cursor()
sql_update="UPDATE manuscript SET manuscript_content=%s,manuscript_type=%s,manuscript_title=%s WHERE manuscript_id=%s"%(self.var_manuscript_content.get(),self.var_manuscript_type.get(),self.var_manuscript_title.get(),self.var_manuscript_id)
try:
cursor = db.cursor()
cursor.execute(sql_update)
db.commit()
messagebox.showinfo('提交!','更新成功!')
except:
db.rollback()
messagebox.showinfo('警告!','更新失败,数据库连接失败!')
db.close()
id_index=self.manuscript_id.index(self.row_info[0])
self.manuscript_content[id_index]=self.var_manuscript_content.get()
self.manuscript_type[id_index]=self.var_manuscript_type.get()
self.manuscript_title[id_index]=self.var_manuscript_title.get()
self.tree.item(self.tree.selection()[0],values=(
self.var_manuscript_id.get(),self.var_manuscript_content.get(),self.manuscript_type.get(),self.manuscript_title.get()))#修改对于行信息
else:
messagebox.showinfo('警告!','不能修改稿件编号')
def del_row(self):
res=messagebox.askyesnocancel('警告!','是否删除所选数据?')
if res==True:
print(self.row_info[0])#鼠标选中的编号
print(self.tree.selection()[0])#行号
print(self.tree.get_children())#所有行
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
# cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor()
sql_delete="DELETE FROM manuscript WHERE manuscript_id=%s"%(self.row_info[0])
#sql_deletes="DELETE FROM stu_login_k WHERE manuscript_id=%s"%(self.row_info[0])
try:
cursor.execute(sql_delete)
#cursor.execute(sql_deletes)
db.commit()
messagebox.showinfo('提示!','删除成功!')
except:
db.rollback()
messagebox.showinfo('警告!','删除失败,数据库连接失败!')
db.close()
id_index=self.manuscript_id.index(self.row_info[0])
print(id_index)
del self.manuscript_id[id_index]
del self.manuscript_content[id_index]
del self.manuscript_type[id_index]
del self.manuscript_title[id_index]
print(self.manuscript_id)
self.tree.delete(self.tree.selection()[0])#删除所选行
print(self.tree.get_children())
#审稿人审稿界面
class Reviewermaanage:
def __init__(self,parent_window,manuscript_id):
parent_window.destroy()#销毁主界面
self.window=tk.Tk()#初始框的声明
self.window.title('查看稿件')
self.window.geometry('300x480')
label=tk.Label(self.window,text='稿件查看',bg='silver',font=('Verdana',20),width=20,height=2)
label.pack(pady=20)
self.manuscript_id='编号:'+''
self.manuscript_content='内容:'+''
self.manuscript_type='类型:'+''
self.manuscript_title='标题'+''
db = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123456',
database='投稿',
charset='utf8',
# cursorclass=pymysql.cursors.DictCursor # 游标类型默认为元组,现在我们设置为字典类型
)
cursor = db.cursor()
sql="SELECT * FROM manuscript WHERE manuscript_id='%$'"%(manuscript_id)
try:
cursor.execute(sql)
result=cursor.fetchall()
for row in result:
self.manuscript_id = '编号:' +row[0]
self.manuscript_content = '内容:' + row[1]
self.manuscript_type = '类型:' + row[2]
self.manuscript_title = '标题' + row[3]
except:
print("Error:unable to fetch data")
db.close()
Label(self.window,text=self.manuscript_id,font=('Verdana',18)).pack(pady=5)
Label(self.window,text=self.manuscript_content,font=('Verdana',18)).pack(pady=5)
Label(self.window,text=self.manuscript_type,font=('Verdana',18)).pack(pady=5)
Label(self.window,text=self.manuscript_title,font=('Verdana',18)).pack(pady=5)
Button(self.window,text="通过",width=8,font=tkFont.Font(size=16)).pack(pady=25)
Button(self.window,text="不通过",width=8,font=tkFont.Font(size=16)).pack(pady=25)
Button(self.window,text="返回首页",width=8,font=tkFont.Font(size=16),command=self.back).pack(pady=25)
self.window.protocol("WM_DELETE_WINDOW",self.back)
self.window.mainloop()
def back(self):
StartPage(self.window)
# 使用 StartPage 类(这里假设没有父窗口,所以传入 None
if __name__ == "__main__":
StartPage(None)
#class Review:
#def __init__(self,window):

Loading…
Cancel
Save