基本完成

This commit is contained in:
625781186 2018-09-27 16:45:55 +08:00
parent 904b59d71c
commit 4b6072f8fb
16 changed files with 276 additions and 820 deletions

View file

@ -1,350 +0,0 @@
# -*- coding: utf-8 -*-
import os, time, sys , importlib, sip
#__file__ 为此文件路径 , 在ipython里是测不出来的
pluginsManagerPath = os.path.dirname(os.path.abspath(__file__))
#主脚本目录
mainPath = os.path.dirname(pluginsManagerPath)
#自定义插件目录
pluginsPath = os.path.join( mainPath, "Plugins")
#以后可能会有其他插件目录
AllPluginsPath = {"customer":pluginsPath}
#设置模块搜索路径
for key in AllPluginsPath :
if AllPluginsPath[key] not in sys.path:
sys.path.insert(0, AllPluginsPath[key])
from copy import deepcopy
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PluginManager.PluginStore import PluginStore
from PluginManager.PluginStore.StoreModel import FileModel
from Tools.pmf_myjson import *
"setting_flie -> From Tools.pmf_myjson , json写入的位置"
class PluginManager(QObject):
"""
管理插件的加载 , 卸载 , 文件的添加/删除监控.
"""
def __init__(self, parent=None, *args, **kwargs):
super(PluginManager, self).__init__(parent, *args, **kwargs)
self.__mw = parent
self.__initUI()
self.pluginDirs = {"pluginFolder": os.path.join(
os.path.abspath("./"),
"Plugins"), }
self.header = ["PlugName",
"Allow", "CreateTime", "ModifyTime"]
self.pluginsInfo = {
"StartModule": {},
}
# self.jsonPlugin :{插件名:{header参数}}
self.jsonPlugin = None
def __initUI(self):
"""
"""
mw = self.__mw
if mw.findChild(QMenuBar, "menuBar"):
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
mw.menuPlugin = QAction("Plugin", self.__mw.menuBar,
triggered=self.__createPluginStoreDialog)
mw.menuBar.addAction(self.__mw.menuPlugin)
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
else:
QMessageBox.information(mw, "", "主窗体没有菜单栏, 请先创建.")
# 文件监听器
self.model = FileModel(self)
self.model.setRootPath("./Plugins")
self.model.setFilter(QDir.Files)
self.model.setNameFilters(["Plugin*.py"])
self.model.setNameFilterDisables(False);
self.index = self.model.index("./Plugins")
self.model.directoryLoaded.connect(self.start)
def __createPluginStoreDialog(self):
"""
显示插件加载情况的 窗体.
"""
if not hasattr(self, "dia"):
self.dia = PluginStore.PluginStore(self, self.__mw)
self.dia.show()
def m_rowsRemoved(self, index, first, last):
"""
文件被删除或重命名时候被调用.
"""
print("removeName:", self.model.index(first, 0, index).data(),first )
mod = (self.model.index(first, 0, index).data())[:-3]
self.unload(mod)
self.pluginsInfo["StartModule"].pop(mod)
self.delJson(self.jsonPlugin , self.pluginsInfo["StartModule"])
# pop的步骤u已经在deljson中执行
# self.jsonPlugin.pop(mod)
def m_rowsInserted(self, index, first, last):
"""
文件增加或重命名时候被调用.
"""
print("insertName:", self.model.index(first, 0, index).data(), first)
f = self.model.index(first, 0, index).data()
mod = f[:-3]
fullPath = os.path.join(self.pluginDirs["pluginFolder"], f)
self.pluginsInfo["StartModule"][mod] = {"path": fullPath}
mod, data = self.addJson(fullPath, mod)
self.jsonPlugin[mod] = data
self.load(mod)
def start(self):
"""
self.model 异步加载完成之后开始调用 self.startGetPlugin.
"""
self.jsonPlugin = self.startGetPlugin(self.pluginDirs['pluginFolder'])
# print("jsonPlugin:", self.jsonPlugin,"\n",
# "pluginsModule:", self.pluginsInfo)
self.loadAll()
self.model.rowsAboutToBeRemoved.connect(self.m_rowsRemoved)
self.model.rowsInserted.connect(self.m_rowsInserted)
self.model.directoryLoaded.disconnect(self.start)
self.__createPluginStoreDialog()
def startGetPlugin(self, pluginFolder: "./Plugins", CHANGE=False) -> "FoJson":
"""
1 . 程序启动加载插件.
"""
try:
jsonPlugin = mfunc_readJson(setting_flie)
except:
jsonPlugin = {}
pluginInfo = {}
rowCount = self.model.rowCount(self.index)
for row in range(rowCount):
index = self.model.index(row, 0, self.index)
# 文件名
f = index.data()
# 去掉后缀 , 加入模块
module = f[:-3]
fullPath = os.path.join(pluginFolder, f)
pluginInfo[module] = {"path": fullPath}
try:
if module not in jsonPlugin:
self.addJson(fullPath, module)
except:
self.addJson(fullPath, module)
if CHANGE is False:
self.pluginsInfo["StartModule"] = deepcopy(pluginInfo)
jsonPlugin = self.delJson(jsonPlugin, pluginInfo)
# print("jsonPlugin",jsonPlugin, "\n", "pluginInfo",pluginInfo )
return jsonPlugin
def addJson(self, fullPath, module) -> "ToJson":
"""1.1写入插件 的json配置."""
# 插件创建时间
_ctime = time.localtime(os.stat(fullPath).st_ctime)
ctime = time.strftime("%Y-%m-%d-%H:%M:%S", _ctime)
# 插件修改时间
_mtime = time.localtime(os.stat(fullPath).st_mtime)
mtime = time.strftime("%Y-%m-%d-%H:%M:%S", _mtime)
# 写入配置
data = {
self.header[1]: True, # allow
self.header[2]: ctime, # cteateTime
self.header[3]: mtime, # modifyTime
}
mfunc_AKrCVJson(module, data , self=self)
return module, data
def delJson(self, jsonPlugin, pluginInfo) -> "ToJson":
"""
1.2删除插件 的json配置.
"""
# 添加完重新加载一遍看是否有插件删除
if jsonPlugin == {}:
jsonPlugin = mfunc_readJson(setting_flie)
if len(jsonPlugin) - len(pluginInfo):
long, short = jsonPlugin, pluginInfo
else:
long, short = pluginInfo, jsonPlugin
with open(setting_flie, 'a+', encoding='utf-8') as f:
# 被删除的插件集合
delPlugin = set(long) - set(short)
for item in delPlugin:
jsonPlugin.pop(item)
# 写入配置
mfunc_reDumpJson(f, jsonPlugin)
return jsonPlugin
# 加载所有插件
def loadAll(self):
"""
2.加载所有模块.
"""
for mod in self.jsonPlugin:
if self.jsonPlugin[mod]["Allow"]:
try:
self.load(mod)
except:
continue
else:
self.pluginsInfo["StartModule"][mod]["active"] = False
# 加载插件
def load(self, mod: "str"):
"""
2.1 载入模块.
"""
try:
# 动态载入模块
_pluginModule = importlib.import_module(mod)
except:
QMessageBox.information(self.__mw,
"模块导入异常",
"请在%s.py检查模块."%mod)
self.pluginsInfo["StartModule"][mod]["active"] = False
return False
self.instantiation(mod, _pluginModule)
return True
def instantiation(self , mod, moduleObj , NeedRplace = False):
"""
1.--实例化类.
"""
try:
className = getattr(moduleObj, "className")
pluginClass = getattr(moduleObj, className )
except:
self.pluginsInfo[mod]["active"] = False
QMessageBox.information(self.__mw,
"插件加载错误",
"请在%s.py全局指定className值." % mod)
return False
# 如果是替换对象需求 ,和初始化
# 实例化类
pluginObject = pluginClass(self.__mw)
pluginObject.setObjectName(mod)
self.pluginsInfo["StartModule"][mod]["active"] = True
self.pluginsInfo["StartModule"][mod]["pluginClass"] = pluginClass
self.pluginsInfo["StartModule"][mod]["parent"] = pluginObject.parent()
if not NeedRplace:
#TODO:其他接口
layout = pluginObject.getParentLayout()
layout.addWidget(pluginObject)
self.pluginsInfo["StartModule"][mod]["layout"] = layout
self.pluginsInfo["StartModule"][mod]["old"] = pluginObject
else:
self.pluginsInfo["StartModule"][mod]["new"] = pluginObject
return pluginObject
# 卸载插件
def unload(self, mod: "str"):
"""
卸载插件 , 移除模块.
"""
if mod in sys.modules:
self.pluginsInfo["StartModule"][mod]["active"] = False
#删除对象
objInfo = self.findOldObj(mod)
oldObj, layout = objInfo["oldObj"], objInfo["layout"]
print(oldObj.objectName()+" be unload")
sip.delete(oldObj)
# layout.removeWidget(oldObj)
self.pluginsInfo["StartModule"][mod]["old"] = None
sys.modules.pop(mod)
return True
# 重载插件
def reload(self, mod):
if mod in sys.modules:
#TODO: 旧对象替换
print("reload")
moduleObj = sys.modules[mod]
button = QPushButton("哈哈")
objInfo = self.findOldObj(mod, moduleObj = moduleObj , needRplace = True)
oldObj, newObj, layout = objInfo["oldObj"], objInfo["newObj"], objInfo["layout"]
print(layout.replaceWidget(oldObj, newObj ))
self.pluginsInfo["StartModule"][mod]["old"] = newObj
print(self.pluginsInfo["StartModule"][mod])
sip.delete(oldObj)
else:
self.load(mod)
def findOldObj(self, mod, moduleObj=None, needRplace = False):
"""
找到需要删除或替换的对象.
"""
oldObj = self.pluginsInfo["StartModule"][mod]["old"]
parentWidget = self.pluginsInfo["StartModule"][mod]["parent"]
layout = self.pluginsInfo["StartModule"][mod]["layout"]
pluginClass = self.pluginsInfo["StartModule"][mod]["pluginClass"]
if needRplace:
if moduleObj==None:
QMessageBox.information(self.__mw,
"错误",
"请传入moduleObj值.")
else:
newObj = self.instantiation(mod, moduleObj, needRplace)
else:
newObj = None
return {"oldObj" :oldObj ,
"newObj" :newObj ,
"parentWidget":parentWidget,
"layout" :layout,
"pluginClass" :pluginClass,
}
# 卸载所有插件
def unloadAll(self):
pass
def PluginToInterFace(self):
pass

View file

@ -1,256 +0,0 @@
# -*- coding: utf-8 -*-
import os , time , imp
from copy import deepcopy
from importlib.machinery import SourceFileLoader
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PluginManager import PluginStore
from Tools.pmf_myjson import *
"setting_flie -> From Tools.pmf_myjson , json写入的位置"
class PluginManager(QObject):
def __init__(self, parent = None , *args, **kwargs):
super(PluginManager, self).__init__(parent , *args, **kwargs)
self.__mw = parent
self.__initUI()
self.pluginDirs = {"pluginPath": os.path.join("./", "Plugins"),}
self.header = ["PlugName",
"Allow" , "CreateTime", "ModifyTime"]
self.changePlugin = {
"StartModule" :{},
"NewModule" :None,
"Load" :{},
"del" :set(),
"rename" :[],
}
# self.existPlugin :{插件名:{header参数}}
# self.pluginsModule :{插件名:{path:插件路径}}
self.existPlugin, self.pluginsModule = None, None
self.existPlugin, self.pluginsModule = \
self.getPluginModules(self.pluginDirs['pluginPath'])
# print("existPlugin:", self.existPlugin,"\n",
# "pluginsModule:", self.pluginsModule)
#载入模块
self.loadAll()
# 文件监听器
self.model = QFileSystemModel()
self.model.setRootPath("./Plugins")
self.model.setFilter( QDir.Files )
self.model.setNameFilters(["Plugin*.py"])
index = self.model.index("./Plugins")
print(self.model.size(index))
self.model.setNameFilterDisables(False);
self.model.rowsRemoved.connect(self.m_rowsRemoved)
self.model.directoryLoaded.connect(lambda :self.model.size(index) )
self.tree = QTreeView()
self.tree.setModel(self.model)
self.tree.setRootIndex(index);
self.tree.show()
def m_rowsRemoved(self, index,first, last):
print(index)
# print(self.model.size())
# self.watcher = QFileSystemWatcher(
# ["./Plugins"],
# directoryChanged = self.m_directoryChanged
# )
def m_directoryChanged(self):
self.existPlugin, self.pluginsModule = \
self.getPluginModules(self.pluginDirs['pluginPath'], True)
del self.changePlugin["NewModule"]
self.changePlugin["NewModule"] = deepcopy(self.pluginsModule)
StartModuleLen = len(self.changePlugin["StartModule"])
NewModuleLen = len(self.changePlugin["NewModule"])
LoadLen = len(self.changePlugin["Load"])
NewSucModuleLen = NewModuleLen \
- StartModuleLen \
- LoadLen
if NewSucModuleLen>0:
moduleSet = set(self.changePlugin["NewModule"]) \
- set(self.changePlugin["StartModule"])\
- set(self.changePlugin["Load"]) \
module = moduleSet.pop()
if not self.load(module):
self.changePlugin["Load"]["Success"] = False
else:
self.changePlugin["Load"]["Success"] = True
elif NewSucModuleLen<0:
pass
def __initUI(self):
if self.__mw.findChild(QMenuBar, "menuBar"):
self.__mw.menuPlugin = QAction("Plugin", self.__mw.menuBar,
triggered = self.__createPluginStoreDialog)
self.__mw.menuBar.addAction(self.__mw.menuPlugin)
else:
QMessageBox.information(self.__mw, "", "主窗体没有菜单栏, 请先创建.")
def __createPluginStoreDialog(self):
"""
显示插件加载情况的 窗体.
"""
dia = PluginStore.PluginStore(self, self.__mw)
dia.exec_()
def getPluginModules(self, pluginPath:"./Plugins" , CHANGE=False)->"FoJson":
"""
Public method to get a list of plugin modules.
"""
try:
existPlugin = mfunc_readJson(setting_flie)
except:
existPlugin=None
pluginFiles = {} if CHANGE is False else self.pluginsModule
for f in os.listdir(pluginPath):
# 插件名称的有效性检查
if f.endswith(".py") and f.startswith("Plugin"):
# 去掉后缀 , 加入模块
module = f[:-3]
fullPath = os.path.join( pluginPath , f)
# 增删改的变化
if module not in self.changePlugin["StartModule"]:
pluginFiles[module] = {"path" :fullPath}
if "active" not in pluginFiles[module]:
pluginFiles[module]["active"] = False
print("---" , )
# 判断模块不在json文件中
if module not in existPlugin:
self.addJson(fullPath, module)
self.delJson(existPlugin, pluginFiles)
if CHANGE is False:
self.changePlugin["StartModule"] = deepcopy(pluginFiles)
return existPlugin, pluginFiles
def addJson(self, fullPath , module )->"ToJson":
# 插件创建时间
_ctime = time.localtime(os.stat(fullPath).st_ctime)
ctime = time.strftime("%Y-%m-%d-%H:%M:%S",_ctime)
# 插件修改时间
_mtime = time.localtime(os.stat(fullPath).st_mtime)
mtime = time.strftime("%Y-%m-%d-%H:%M:%S",_mtime)
# 写入配置
mfunc_AKrCVJson( module ,
{
self.header[1]: True, #allow
self.header[2]: ctime,#cteateTime
self.header[3]: mtime,#modifyTime
} ,
self = self)
def delJson(self , existPlugin, pluginFiles)->"ToJson":
"""
删除插件 的json配置.
"""
# 获取最终json配置
# self.existPlugin = mfunc_readJson(setting_flie)
# 添加完重新加载一遍看是否有插件删除
if existPlugin==None:
existPlugin = mfunc_readJson(setting_flie)
if len(existPlugin)>len(pluginFiles):
with open( setting_flie ,'a+' , encoding='utf-8') as f:
# 被删除的插件集合
delPlugin = set(existPlugin)-set(pluginFiles)
for item in delPlugin:
existPlugin.pop(item)
self.changePlugin["del"]
# 写入配置
mfunc_reDumpJson(f, existPlugin)
# 加载所有插件
def loadAll(self):
for mod in self.existPlugin:
if self.existPlugin[mod]["Allow"] \
and not self.pluginsModule[mod]["active"]:
try:
self.load(mod)
except:
continue
# 加载插件
def load(self , mod:"str"):
try:
# print(self.pluginsModule[mod]["path"])
# python内置函数, 把.py 当做模块载入
_pluginModule = SourceFileLoader( mod ,
self.pluginsModule[mod]["path"]).load_module()
# _pluginModule=imp.load_source(mod, self.pluginsModule[mod]["path"])
except:
# QMessageBox.information(self.__mw,
# "模块导入异常",
# "请在%s.py检查模块."%mod)
self.pluginsModule[mod]["active"] = False
return False
try:
className = getattr(_pluginModule, "className")
pluginClass = getattr(_pluginModule, className )
except:
self.pluginsModule[mod]["active"] = False
QMessageBox.information(self.__mw,
"插件加载错误",
"请在%s.py全局指定className值."%mod)
return False
# 实例化类
pluginObject = pluginClass()
pluginObject.setObjectName(className)
self.__mw.verticalLayout.addWidget(pluginObject)
self.pluginsModule[mod]["active"] = True
return True
# 卸载插件
def unload(self, mod:"str"):
# self.__mw.findchild()
print(sys.modules[mod], mod)
print(self.__mw.findChild(QWidget, mod))
#TODO:
return True
# 卸载所有插件
def unloadAll(self):
pass

View file

@ -2,7 +2,7 @@
""" """
管理插件的加载 , 卸载 , 监控文件的添加/删除. 管理插件的加载 , 卸载 , 监控文件的添加/删除.
""" """
import os, time, sys , importlib, sip import os, time, sys , importlib, sip, traceback
# ==添加插件的搜索路径== # ==添加插件的搜索路径==
#__file__ 为此文件路径 , 在ipython里是测不出来的 #__file__ 为此文件路径 , 在ipython里是测不出来的
pluginsManagerPath = os.path.dirname(os.path.abspath(__file__)) pluginsManagerPath = os.path.dirname(os.path.abspath(__file__))
@ -62,10 +62,10 @@ class PluginManager(QObject):
mw = self.__mw mw = self.__mw
if mw.findChild(QMenuBar, "menuBar"): if mw.findChild(QMenuBar, "menuBar"):
# 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体=== # 插入到mainwindow的menuBar下 , 点击查看弹出插件加载情况窗体===
mw.menuPlugin = QAction("Plugin", self.__mw.menuBar, mw.menuPlugin = QAction("Plugin", mw.menuBar,
triggered=self.__createPluginStoreDialog) triggered=self.__createPluginStoreDialog)
mw.menuBar.addAction(self.__mw.menuPlugin) mw.menuBar.addAction(mw.menuPlugin)
else: else:
QMessageBox.information(mw, "", "主窗体没有菜单栏, 请先创建.") QMessageBox.information(mw, "", "主窗体没有菜单栏, 请先创建.")
@ -156,16 +156,16 @@ class PluginManager(QObject):
fullPath = os.path.join(pluginFolder, f) fullPath = os.path.join(pluginFolder, f)
pluginInfo[module] = {"path": fullPath} pluginInfo[module] = {"path": fullPath}
try:
if module not in jsonPlugin: if module not in jsonPlugin:
self.addJson(fullPath, module) module, data = self.addJson(fullPath, module)
except: jsonPlugin[module]=data
self.addJson(fullPath, module)
if CHANGE is False: if CHANGE is False:
self.pluginsInfo["StartModule"] = deepcopy(pluginInfo) self.pluginsInfo["StartModule"] = deepcopy(pluginInfo)
jsonPlugin = self.delJson(jsonPlugin, pluginInfo) jsonPlugin = self.delJson({}, pluginInfo)
# print("jsonPlugin",jsonPlugin, "\n", "pluginInfo",pluginInfo ) # print("jsonPlugin",jsonPlugin, "\n", "pluginInfo",pluginInfo )
@ -238,7 +238,7 @@ class PluginManager(QObject):
_pluginModule = importlib.import_module(mod) _pluginModule = importlib.import_module(mod)
except: except:
import traceback
errmsg = traceback.format_exc() errmsg = traceback.format_exc()
QMessageBox.information(self.__mw, QMessageBox.information(self.__mw,
@ -264,26 +264,34 @@ class PluginManager(QObject):
className = getattr(moduleObj, "className") className = getattr(moduleObj, "className")
pluginClass = getattr(moduleObj, className ) pluginClass = getattr(moduleObj, className )
except: except:
self.pluginsInfo[mod]["active"] = False self.pluginsInfo["StartModule"][mod]["active"] = False
errmsg = traceback.format_exc()
QMessageBox.information(self.__mw, QMessageBox.information(self.__mw,
"插件加载错误", "插件加载错误",
"请在%s.py全局指定className值." % mod) "%s ,请在%s.py全局指定className值." % (errmsg, mod))
return False return False
# 如果是替换对象需求 ,和初始化 # 如果是替换对象需求 ,和初始化
# 实例化类 # 实例化类
pluginObject = pluginClass(self.__mw) try:
pluginObject.setObjectName(mod) pluginObject = pluginClass(self.__mw)
pluginObject.setObjectName(mod)
self.pluginsInfo["StartModule"][mod]["active"] = True self.pluginsInfo["StartModule"][mod]["active"] = True
self.pluginsInfo["StartModule"][mod]["pluginClass"] = pluginClass self.pluginsInfo["StartModule"][mod]["pluginClass"] = pluginClass
self.pluginsInfo["StartModule"][mod]["parent"] = pluginObject.parent() self.pluginsInfo["StartModule"][mod]["parent"] = pluginObject.parent()
except:
self.pluginsInfo["StartModule"][mod]["active"] = False
errmsg = traceback.format_exc()
QMessageBox.information(self.__mw,
"插件加载错误",
"%s ,请在%s.py全局指定className值." % (errmsg, mod))
if not NeedRplace: if not NeedRplace:
#TODO:其他接口 #TODO:其他接口
layout = pluginObject.getParentLayout() layout = pluginObject.getParentLayout()
layout.addWidget(pluginObject) pluginObject.toInterface()
self.pluginsInfo["StartModule"][mod]["layout"] = layout self.pluginsInfo["StartModule"][mod]["layout"] = layout
self.pluginsInfo["StartModule"][mod]["old"] = pluginObject self.pluginsInfo["StartModule"][mod]["old"] = pluginObject
else: else:
@ -300,8 +308,15 @@ class PluginManager(QObject):
print("reload") print("reload")
importlib.reload(sys.modules[mod]) importlib.reload(sys.modules[mod])
moduleObj = sys.modules[mod] moduleObj = sys.modules[mod]
try:
objInfo = self.findOldObj(mod, moduleObj , True)
except:
errmsg = traceback.format_exc()
QMessageBox.information(self.__mw,
"模块导入异常",
"%s,请在%s.py检查模块."%(errmsg,mod ))
objInfo = self.findOldObj(mod, moduleObj , True)
oldObj, newObj, layout = objInfo["oldObj"],\ oldObj, newObj, layout = objInfo["oldObj"],\
objInfo["newObj"],\ objInfo["newObj"],\
objInfo["layout"] objInfo["layout"]
@ -309,7 +324,7 @@ class PluginManager(QObject):
# 新对象替换旧对象 并把地址赋值给旧对象 # 新对象替换旧对象 并把地址赋值给旧对象
layout.replaceWidget(oldObj, newObj ) layout.replaceWidget(oldObj, newObj )
self.pluginsInfo["StartModule"][mod]["old"] = newObj self.pluginsInfo["StartModule"][mod]["old"] = newObj
oldObj.flag="reload"
sip.delete(oldObj) sip.delete(oldObj)
else: else:
self.load(mod) self.load(mod)
@ -352,7 +367,7 @@ class PluginManager(QObject):
#删除对象 #删除对象
objInfo = self.findOldObj(mod) objInfo = self.findOldObj(mod)
oldObj = objInfo["oldObj"] oldObj = objInfo["oldObj"]
oldObj.flag="unload"
sip.delete(oldObj) sip.delete(oldObj)
self.pluginsInfo["StartModule"][mod]["old"] = None self.pluginsInfo["StartModule"][mod]["old"] = None

View file

@ -117,7 +117,6 @@ class PluginStore(QDialog, Ui_Dialog):
if msg==QMessageBox.Yes: if msg==QMessageBox.Yes:
self.manager.unload(mod) self.manager.unload(mod)
else: else:
self.manager.reload(mod) self.manager.reload(mod)
# 右键菜单重载和卸载 , 默认的是选行的第0列 # 右键菜单重载和卸载 , 默认的是选行的第0列

View file

@ -1,10 +1,4 @@
# -*- coding: utf-8 -*-
#import sys, os """
#pluginsManagetPath = os.path.dirname(os.path.abspath(__file__)) 插件的加载 , 重载 , 卸载模块 , 配置文件模块.
#mainPath = os.path.dirname(pluginsManagetPath) """
#pluginsPath = os.path.join(pluginsManagetPath, "Plugins")
#
#for i in [pluginsPath]:
# print(mainPath, pluginsManagetPath, pluginsPath)
# sys.path.insert(0, i)
# print("add")

View file

@ -1,17 +1,32 @@
{ {
"PluginPage1": { "PluginPage0_inMainLayout": {
"Allow": false, "Allow": true,
"CreateTime": "2018-09-18-18:44:18", "CreateTime": "2018-09-18-18:44:18",
"ModifyTime": "2018-09-23-20:13:56" "ModifyTime": "2018-09-24-15:58:45"
}, },
"PluginPage2": { "PluginPage1_addTab3": {
"Allow": true,
"CreateTime": "2018-09-24-17:48:29",
"ModifyTime": "2018-09-24-18:24:48"
},
"PluginPage1_addTab4": {
"Allow": true,
"CreateTime": "2018-09-24-18:17:19",
"ModifyTime": "2018-09-24-18:24:22"
},
"PluginPage2_error": {
"Allow": false, "Allow": false,
"CreateTime": "2018-09-18-18:45:14", "CreateTime": "2018-09-18-18:45:14",
"ModifyTime": "2018-09-19-18:16:08" "ModifyTime": "2018-09-19-18:16:08"
}, },
"Pluginmmm": { "PluginPage3_addAction2": {
"Allow": true, "Allow": true,
"CreateTime": "2018-09-23-20:57:37", "CreateTime": "2018-09-24-20:54:48",
"ModifyTime": "2018-09-23-20:13:56" "ModifyTime": "2018-09-24-20:57:03"
},
"PluginPage3_addAction1": {
"Allow": true,
"CreateTime": "2018-09-24-18:26:10",
"ModifyTime": "2018-09-24-20:50:02"
} }
} }

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-6.0.dtd"> <!DOCTYPE Project SYSTEM "Project-6.0.dtd">
<!-- eric project file for project Plugins --> <!-- eric project file for project Plugins -->
<!-- Saved: 2018-09-21, 22:53:13 --> <!-- Saved: 2018-09-24, 21:05:10 -->
<!-- Copyright (C) 2018 , --> <!-- Copyright (C) 2018 , -->
<Project version="6.0"> <Project version="6.0">
<Language></Language> <Language></Language>
@ -17,10 +17,14 @@
<Source>PluginManager/PluginStore/PluginStore.py</Source> <Source>PluginManager/PluginStore/PluginStore.py</Source>
<Source>PluginManager/PluginStore/StoreModel.py</Source> <Source>PluginManager/PluginStore/StoreModel.py</Source>
<Source>PluginManager/PluginStore/Ui_PluginStore.py</Source> <Source>PluginManager/PluginStore/Ui_PluginStore.py</Source>
<Source>PluginManager/PluginStore/__init__.py</Source>
<Source>PluginManager/__init__.py</Source> <Source>PluginManager/__init__.py</Source>
<Source>Plugins/PluginPage1.py</Source> <Source>Plugins/PluginPage0_inMainLayout.py</Source>
<Source>Plugins/PluginPage2.py</Source> <Source>Plugins/PluginPage1_addTab3.py</Source>
<Source>Plugins/Pluginmmm.py</Source> <Source>Plugins/PluginPage1_addTab4.py</Source>
<Source>Plugins/PluginPage2_error.py</Source>
<Source>Plugins/PluginPage3_addAction1.py</Source>
<Source>Plugins/PluginPage3_addAction2.py</Source>
<Source>Plugins/__init__.py</Source> <Source>Plugins/__init__.py</Source>
<Source>Plugins/page1/Ui_PluginPage1.py</Source> <Source>Plugins/page1/Ui_PluginPage1.py</Source>
<Source>Plugins/page1/__init__.py</Source> <Source>Plugins/page1/__init__.py</Source>
@ -38,6 +42,9 @@
<Form>Plugins/page2/PluginPage2.ui</Form> <Form>Plugins/page2/PluginPage2.ui</Form>
<Form>main.ui</Form> <Form>main.ui</Form>
</Forms> </Forms>
<Others>
<Other>Documentation</Other>
</Others>
<MainScript>main.py</MainScript> <MainScript>main.py</MainScript>
<Vcs> <Vcs>
<VcsType>None</VcsType> <VcsType>None</VcsType>
@ -60,4 +67,59 @@
<FiletypeAssociation pattern="README" type="OTHERS"/> <FiletypeAssociation pattern="README" type="OTHERS"/>
<FiletypeAssociation pattern="README.*" type="OTHERS"/> <FiletypeAssociation pattern="README.*" type="OTHERS"/>
</FiletypeAssociations> </FiletypeAssociations>
<Documentation>
<DocumentationParams>
<dict>
<key>
<string>ERIC4DOC</string>
</key>
<value>
<dict>
<key>
<string>cssFile</string>
</key>
<value>
<string>%PYTHON%/eric6/CSSs/default.css</string>
</value>
<key>
<string>ignoreDirectories</string>
</key>
<value>
<list>
<string>page1</string>
<string>page2</string>
</list>
</value>
<key>
<string>ignoreFilePatterns</string>
</key>
<value>
<list>
<string>Ui*.py</string>
<string>Plugins\\*Page*.py</string>
</list>
</value>
<key>
<string>outputDirectory</string>
</key>
<value>
<string>Documentation</string>
</value>
<key>
<string>qtHelpEnabled</string>
</key>
<value>
<bool>False</bool>
</value>
<key>
<string>useRecursion</string>
</key>
<value>
<bool>True</bool>
</value>
</dict>
</value>
</dict>
</DocumentationParams>
</Documentation>
</Project> </Project>

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Module implementing Form. 插件例子1.
""" """
""" """
@ -14,8 +14,6 @@ site: https://github.com/625781186 <br>
视频教程: https://space.bilibili.com/1863103/#/ <br> 视频教程: https://space.bilibili.com/1863103/#/ <br>
""" """
from PyQt5 import QtGui, QtWidgets, QtCore from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import * from PyQt5.QtCore import *
from PyQt5.QtGui import * from PyQt5.QtGui import *
@ -27,6 +25,7 @@ try:
except: except:
from page1.Ui_PluginPage1 import Ui_Form from page1.Ui_PluginPage1 import Ui_Form
# 实例化类名, 必须
className = "Form" className = "Form"
class Form(QWidget, Ui_Form): class Form(QWidget, Ui_Form):
@ -35,10 +34,7 @@ class Form(QWidget, Ui_Form):
""" """
def __init__(self, parent=None): def __init__(self, parent=None):
""" """
Constructor
@param parent reference to the parent widget
@type QWidget
""" """
super(Form, self).__init__(parent) super(Form, self).__init__(parent)
self.setupUi(self) self.setupUi(self)
@ -46,8 +42,18 @@ class Form(QWidget, Ui_Form):
# layout = self.getParentLayout() # layout = self.getParentLayout()
# layout.addWidget(self) # layout.addWidget(self)
def getParentLayout(self): def getParentLayout(self):
"""
布局函数,必须.
"""
return self.__mw.verticalLayout return self.__mw.verticalLayout
def toInterface(self):
"""
插入到界面,必须
"""
layout = self.getParentLayout()
layout.addWidget(self)
def __del__(self): def __del__(self):
print("die") print("die")

View file

@ -1,61 +0,0 @@
# -*- coding: utf-8 -*-
"""
Module implementing Form.
"""
"""
Created on 2018-09-18 <br>
description: $description$ <br>
author: 625781186@qq.com <br>
site: https://github.com/625781186 <br>
更多经典例子:https://github.com/892768447/PyQt <br>
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
视频教程: https://space.bilibili.com/1863103/#/ <br>
"""
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QWidget
from Plugin..Ui_PluginPage2 import Ui_Form
className = "Form"
class Form(QWidget, Ui_Form):
"""
Class documentation goes here.
"""
def __init__(self, parent=None):
"""
Constructor
@param parent reference to the parent widget
@type QWidget
"""
super(Form, self).__init__(parent)
self.setupUi(self)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QStyleFactory.create("Fusion"))
# 自定义CSS样式
# from BasePack.CommonHelper import CommonHelper
# styleFile = 'BasePack/style.css'
# qssStyle = CommonHelper.readQss( styleFile )
# framelessWindow.setStyleSheet( qssStyle )
# If you want to use this style, please pip install qdarkstyle.
# import qdarkstyle
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
ui = Form()
ui.show()
sys.exit(app.exec_())

View file

@ -1,87 +0,0 @@
# -*- coding: utf-8 -*-
"""
Module implementing Form.
"""
"""
Created on 2018-09-18 <br>
description: $description$ <br>
author: 625781186@qq.com <br>
site: https://github.com/625781186 <br>
更多经典例子:https://github.com/892768447/PyQt <br>
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
视频教程: https://space.bilibili.com/1863103/#/ <br>
"""
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QWidget
try:
from Ui_PluginPage1 import Ui_Form
except:
from page1.Ui_PluginPage1 import Ui_Form
className = "Form"
class Form(QWidget, Ui_Form):
"""
Class documentation goes here.
"""
def __init__(self, parent=None):
"""
Constructor
@param parent reference to the parent widget
@type QWidget
"""
super(Form, self).__init__(parent)
self.setupUi(self)
self.__mw = parent
def __del__(self):
print("die")
@pyqtSlot()
def on_pushButton_clicked(self):
print(15111)
pass
@pyqtSlot()
def on_pushButton_2_clicked(self):
print(222)
pass
@pyqtSlot()
def on_pushButton_3_clicked(self):
print(333)
pass
def getParentLayout(self):
return self.__mw.verticalLayout
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QStyleFactory.create("Fusion"))
# 自定义CSS样式
# from BasePack.CommonHelper import CommonHelper
# styleFile = 'BasePack/style.css'
# qssStyle = CommonHelper.readQss( styleFile )
# framelessWindow.setStyleSheet( qssStyle )
# If you want to use this style, please pip install qdarkstyle.
# import qdarkstyle
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
ui = Form()
ui.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
"""
插件搜索目录.
"""

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
"""
增删改查建json.
"""

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
初始化json配置函数. 增删改查建json.
""" """
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QMessageBox , QWidget , QApplication from PyQt5.QtWidgets import QMessageBox , QWidget , QApplication

View file

@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow") MainWindow.setObjectName("MainWindow")
MainWindow.resize(510, 379) MainWindow.resize(510, 378)
self.centralWidget = QtWidgets.QWidget(MainWindow) self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget") self.centralWidget.setObjectName("centralWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralWidget) self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralWidget)
@ -39,11 +39,44 @@ class Ui_MainWindow(object):
self.menuBar.setObjectName("menuBar") self.menuBar.setObjectName("menuBar")
self.menuFile = QtWidgets.QMenu(self.menuBar) self.menuFile = QtWidgets.QMenu(self.menuBar)
self.menuFile.setObjectName("menuFile") self.menuFile.setObjectName("menuFile")
self.menuOpen_Recent_Files = QtWidgets.QMenu(self.menuFile)
self.menuOpen_Recent_Files.setObjectName("menuOpen_Recent_Files")
self.menufile1 = QtWidgets.QMenu(self.menuOpen_Recent_Files)
self.menufile1.setObjectName("menufile1")
self.menufile11 = QtWidgets.QMenu(self.menufile1)
self.menufile11.setObjectName("menufile11")
self.menuEdit = QtWidgets.QMenu(self.menuBar) self.menuEdit = QtWidgets.QMenu(self.menuBar)
self.menuEdit.setObjectName("menuEdit") self.menuEdit.setObjectName("menuEdit")
self.menuView = QtWidgets.QMenu(self.menuBar) self.menuView = QtWidgets.QMenu(self.menuBar)
self.menuView.setObjectName("menuView") self.menuView.setObjectName("menuView")
MainWindow.setMenuBar(self.menuBar) MainWindow.setMenuBar(self.menuBar)
self.actionadd1 = QtWidgets.QAction(MainWindow)
self.actionadd1.setObjectName("actionadd1")
self.actionsave = QtWidgets.QAction(MainWindow)
self.actionsave.setObjectName("actionsave")
self.actionOpen = QtWidgets.QAction(MainWindow)
self.actionOpen.setObjectName("actionOpen")
self.actionfile2 = QtWidgets.QAction(MainWindow)
self.actionfile2.setObjectName("actionfile2")
self.actionfile3 = QtWidgets.QAction(MainWindow)
self.actionfile3.setObjectName("actionfile3")
self.actionfile11 = QtWidgets.QAction(MainWindow)
self.actionfile11.setObjectName("actionfile11")
self.actionfile22 = QtWidgets.QAction(MainWindow)
self.actionfile22.setObjectName("actionfile22")
self.actionfile111 = QtWidgets.QAction(MainWindow)
self.actionfile111.setObjectName("actionfile111")
self.menufile11.addAction(self.actionfile111)
self.menufile1.addAction(self.menufile11.menuAction())
self.menufile1.addAction(self.actionfile22)
self.menuOpen_Recent_Files.addAction(self.menufile1.menuAction())
self.menuOpen_Recent_Files.addAction(self.actionfile2)
self.menuOpen_Recent_Files.addAction(self.actionfile3)
self.menuFile.addAction(self.actionadd1)
self.menuFile.addAction(self.actionsave)
self.menuFile.addAction(self.actionOpen)
self.menuFile.addSeparator()
self.menuFile.addAction(self.menuOpen_Recent_Files.menuAction())
self.menuBar.addAction(self.menuFile.menuAction()) self.menuBar.addAction(self.menuFile.menuAction())
self.menuBar.addAction(self.menuEdit.menuAction()) self.menuBar.addAction(self.menuEdit.menuAction())
self.menuBar.addAction(self.menuView.menuAction()) self.menuBar.addAction(self.menuView.menuAction())
@ -60,8 +93,19 @@ class Ui_MainWindow(object):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))
self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuOpen_Recent_Files.setTitle(_translate("MainWindow", "Open Recent Files"))
self.menufile1.setTitle(_translate("MainWindow", "file1"))
self.menufile11.setTitle(_translate("MainWindow", "file11"))
self.menuEdit.setTitle(_translate("MainWindow", "Edit")) self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
self.menuView.setTitle(_translate("MainWindow", "View")) self.menuView.setTitle(_translate("MainWindow", "View"))
self.actionadd1.setText(_translate("MainWindow", "New Window"))
self.actionsave.setText(_translate("MainWindow", "New"))
self.actionOpen.setText(_translate("MainWindow", "Open"))
self.actionfile2.setText(_translate("MainWindow", "file2"))
self.actionfile3.setText(_translate("MainWindow", "file3"))
self.actionfile11.setText(_translate("MainWindow", "file11"))
self.actionfile22.setText(_translate("MainWindow", "file22"))
self.actionfile111.setText(_translate("MainWindow", "file111"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
Module implementing MainWindow. 主函数入口.
""" """
""" """
@ -13,7 +13,7 @@ site: https://github.com/625781186 <br>
课件: https://github.com/625781186/WoHowLearn_PyQt5 <br> 课件: https://github.com/625781186/WoHowLearn_PyQt5 <br>
视频教程: https://space.bilibili.com/1863103/#/ <br> 视频教程: https://space.bilibili.com/1863103/#/ <br>
""" """
import os, time, imp, sys import sys
from PyQt5 import QtGui, QtWidgets, QtCore from PyQt5 import QtGui, QtWidgets, QtCore
@ -48,20 +48,21 @@ class MainWindow(QMainWindow, Ui_MainWindow):
""" """
print(sys.path) print(sys.path)
pass pass
def closeEvent(self, e):
self.pluginManager.dia.close()
if __name__ == "__main__": if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
app.setStyle(QStyleFactory.create("Fusion")) app.setStyle(QStyleFactory.create("Fusion"))
# def excepthook(type, value, trace): def excepthook(type, value, trace):
# try: try:
# pass pass
# except : except :
# pass pass
# sys.__excepthook__(type, value, trace) sys.__excepthook__(type, value, trace)
# sys.excepthook = excepthook sys.excepthook = excepthook
ui = MainWindow() ui = MainWindow()

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>510</width> <width>510</width>
<height>379</height> <height>378</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -63,6 +63,32 @@
<property name="title"> <property name="title">
<string>File</string> <string>File</string>
</property> </property>
<widget class="QMenu" name="menuOpen_Recent_Files">
<property name="title">
<string>Open Recent Files</string>
</property>
<widget class="QMenu" name="menufile1">
<property name="title">
<string>file1</string>
</property>
<widget class="QMenu" name="menufile11">
<property name="title">
<string>file11</string>
</property>
<addaction name="actionfile111"/>
</widget>
<addaction name="menufile11"/>
<addaction name="actionfile22"/>
</widget>
<addaction name="menufile1"/>
<addaction name="actionfile2"/>
<addaction name="actionfile3"/>
</widget>
<addaction name="actionadd1"/>
<addaction name="actionsave"/>
<addaction name="actionOpen"/>
<addaction name="separator"/>
<addaction name="menuOpen_Recent_Files"/>
</widget> </widget>
<widget class="QMenu" name="menuEdit"> <widget class="QMenu" name="menuEdit">
<property name="title"> <property name="title">
@ -78,6 +104,46 @@
<addaction name="menuEdit"/> <addaction name="menuEdit"/>
<addaction name="menuView"/> <addaction name="menuView"/>
</widget> </widget>
<action name="actionadd1">
<property name="text">
<string>New Window</string>
</property>
</action>
<action name="actionsave">
<property name="text">
<string>New</string>
</property>
</action>
<action name="actionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="actionfile2">
<property name="text">
<string>file2</string>
</property>
</action>
<action name="actionfile3">
<property name="text">
<string>file3</string>
</property>
</action>
<action name="actionfile11">
<property name="text">
<string>file11</string>
</property>
</action>
<action name="actionfile22">
<property name="text">
<string>file22</string>
</property>
</action>
<action name="actionfile111">
<property name="text">
<string>file111</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>