plugins refactoring
This commit is contained in:
parent
2a97beb5af
commit
9c742d10de
4 changed files with 91 additions and 81 deletions
|
@ -338,7 +338,7 @@ class App:
|
||||||
self._group_factory = GroupFactory(self._profile_manager, self._settings, self._tox, db, contact_items_factory)
|
self._group_factory = GroupFactory(self._profile_manager, self._settings, self._tox, db, contact_items_factory)
|
||||||
self._contacts_provider = ContactProvider(self._tox, self._friend_factory, self._group_factory)
|
self._contacts_provider = ContactProvider(self._tox, self._friend_factory, self._group_factory)
|
||||||
self._profile = Profile(self._profile_manager, self._tox, self._ms, self._contacts_provider, self._reset)
|
self._profile = Profile(self._profile_manager, self._tox, self._ms, self._contacts_provider, self._reset)
|
||||||
self._plugin_loader = PluginLoader(self._tox, self._toxes, self._profile, self._settings)
|
self._plugin_loader = PluginLoader(self._settings, self)
|
||||||
history = None
|
history = None
|
||||||
messages_items_factory = MessagesItemsFactory(self._settings, self._plugin_loader, self._smiley_loader,
|
messages_items_factory = MessagesItemsFactory(self._settings, self._plugin_loader, self._smiley_loader,
|
||||||
self._ms, lambda m: history.delete_message(m))
|
self._ms, lambda m: history.delete_message(m))
|
||||||
|
|
|
@ -6,7 +6,7 @@ import common.tox_save as tox_save
|
||||||
|
|
||||||
class Profile(basecontact.BaseContact, tox_save.ToxSave):
|
class Profile(basecontact.BaseContact, tox_save.ToxSave):
|
||||||
"""
|
"""
|
||||||
Profile of current toxygen user. Contains friends list, tox instance
|
Profile of current toxygen user.
|
||||||
"""
|
"""
|
||||||
def __init__(self, profile_manager, tox, screen, contacts_provider, reset_action):
|
def __init__(self, profile_manager, tox, screen, contacts_provider, reset_action):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,31 +4,47 @@ import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import plugins.plugin_super_class as pl
|
import plugins.plugin_super_class as pl
|
||||||
import sys
|
import sys
|
||||||
from common.tox_save import ToxSave
|
|
||||||
|
|
||||||
|
|
||||||
class PluginLoader(ToxSave):
|
class Plugin:
|
||||||
|
|
||||||
def __init__(self, tox, toxes, profile, settings):
|
def __init__(self, plugin, is_active):
|
||||||
super().__init__(tox)
|
self._instance = plugin
|
||||||
self._profile = profile
|
self._is_active = is_active
|
||||||
|
|
||||||
|
def get_instance(self):
|
||||||
|
return self._instance
|
||||||
|
|
||||||
|
instance = property(get_instance)
|
||||||
|
|
||||||
|
def get_is_active(self):
|
||||||
|
return self._is_active
|
||||||
|
|
||||||
|
def set_is_active(self, is_active):
|
||||||
|
self._is_active = is_active
|
||||||
|
|
||||||
|
is_active = property(get_is_active, set_is_active)
|
||||||
|
|
||||||
|
|
||||||
|
class PluginLoader:
|
||||||
|
|
||||||
|
def __init__(self, settings, app):
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._plugins = {} # dict. key - plugin unique short name, value - tuple (plugin instance, is active)
|
self._app = app
|
||||||
self._toxes = toxes
|
self._plugins = {} # dict. key - plugin unique short name, value - Plugin instance
|
||||||
|
|
||||||
def set_tox(self, tox):
|
def set_tox(self, tox):
|
||||||
"""
|
"""
|
||||||
New tox instance
|
New tox instance
|
||||||
"""
|
"""
|
||||||
super().set_tox(tox)
|
for plugin in self._plugins.values():
|
||||||
for value in self._plugins.values():
|
plugin.instance.set_tox(tox)
|
||||||
value[0].set_tox(tox)
|
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""
|
"""
|
||||||
Load all plugins in plugins folder
|
Load all plugins in plugins folder
|
||||||
"""
|
"""
|
||||||
path = util.curr_directory() + '/plugins/'
|
path = util.get_plugins_directory()
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
util.log('Plugin dir not found')
|
util.log('Plugin dir not found')
|
||||||
return
|
return
|
||||||
|
@ -50,17 +66,18 @@ class PluginLoader(ToxSave):
|
||||||
for elem in dir(module):
|
for elem in dir(module):
|
||||||
obj = getattr(module, elem)
|
obj = getattr(module, elem)
|
||||||
# looking for plugin class in module
|
# looking for plugin class in module
|
||||||
if inspect.isclass(obj) and hasattr(obj, 'is_plugin') and obj.is_plugin:
|
if not inspect.isclass(obj) or not hasattr(obj, 'is_plugin') or not obj.is_plugin:
|
||||||
|
continue
|
||||||
print('Plugin', elem)
|
print('Plugin', elem)
|
||||||
try: # create instance of plugin class
|
try: # create instance of plugin class
|
||||||
inst = obj(self._tox, self._profile, self._settings, self._toxes)
|
instance = obj(self._app)
|
||||||
autostart = inst.get_short_name() in self._settings['plugins']
|
is_active = instance.get_short_name() in self._settings['plugins']
|
||||||
if autostart:
|
if is_active:
|
||||||
inst.start()
|
instance.start()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
util.log('Exception in module ' + name + ' Exception: ' + str(ex))
|
util.log('Exception in module ' + name + ' Exception: ' + str(ex))
|
||||||
continue
|
continue
|
||||||
self._plugins[inst.get_short_name()] = [inst, autostart] # (inst, is active)
|
self._plugins[instance.get_short_name()] = Plugin(instance, is_active)
|
||||||
break
|
break
|
||||||
|
|
||||||
def callback_lossless(self, friend_number, data):
|
def callback_lossless(self, friend_number, data):
|
||||||
|
@ -69,8 +86,8 @@ class PluginLoader(ToxSave):
|
||||||
"""
|
"""
|
||||||
l = data[0] - pl.LOSSLESS_FIRST_BYTE
|
l = data[0] - pl.LOSSLESS_FIRST_BYTE
|
||||||
name = ''.join(chr(x) for x in data[1:l + 1])
|
name = ''.join(chr(x) for x in data[1:l + 1])
|
||||||
if name in self._plugins and self._plugins[name][1]:
|
if name in self._plugins and self._plugins[name].is_active:
|
||||||
self._plugins[name][0].lossless_packet(''.join(chr(x) for x in data[l + 1:]), friend_number)
|
self._plugins[name].instance.lossless_packet(''.join(chr(x) for x in data[l + 1:]), friend_number)
|
||||||
|
|
||||||
def callback_lossy(self, friend_number, data):
|
def callback_lossy(self, friend_number, data):
|
||||||
"""
|
"""
|
||||||
|
@ -78,37 +95,38 @@ class PluginLoader(ToxSave):
|
||||||
"""
|
"""
|
||||||
l = data[0] - pl.LOSSY_FIRST_BYTE
|
l = data[0] - pl.LOSSY_FIRST_BYTE
|
||||||
name = ''.join(chr(x) for x in data[1:l + 1])
|
name = ''.join(chr(x) for x in data[1:l + 1])
|
||||||
if name in self._plugins and self._plugins[name][1]:
|
if name in self._plugins and self._plugins[name].is_active:
|
||||||
self._plugins[name][0].lossy_packet(''.join(chr(x) for x in data[l + 1:]), friend_number)
|
self._plugins[name].instance.lossy_packet(''.join(chr(x) for x in data[l + 1:]), friend_number)
|
||||||
|
|
||||||
def friend_online(self, friend_number):
|
def friend_online(self, friend_number):
|
||||||
"""
|
"""
|
||||||
Friend with specified number is online
|
Friend with specified number is online
|
||||||
"""
|
"""
|
||||||
for elem in self._plugins.values():
|
for plugin in self._plugins.values():
|
||||||
if elem[1]:
|
if plugin.is_active:
|
||||||
elem[0].friend_connected(friend_number)
|
plugin.instance.friend_connected(friend_number)
|
||||||
|
|
||||||
def get_plugins_list(self):
|
def get_plugins_list(self):
|
||||||
"""
|
"""
|
||||||
Returns list of all plugins
|
Returns list of all plugins
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
for data in self._plugins.values():
|
for plugin in self._plugins.values():
|
||||||
try:
|
try:
|
||||||
result.append([data[0].get_name(), # plugin full name
|
result.append([plugin.instance.get_name(), # plugin full name
|
||||||
data[1], # is enabled
|
plugin.is_active, # is enabled
|
||||||
data[0].get_description(), # plugin description
|
plugin.instance.get_description(), # plugin description
|
||||||
data[0].get_short_name()]) # key - short unique name
|
plugin.instance.get_short_name()]) # key - short unique name
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def plugin_window(self, key):
|
def plugin_window(self, key):
|
||||||
"""
|
"""
|
||||||
Return window or None for specified plugin
|
Return window or None for specified plugin
|
||||||
"""
|
"""
|
||||||
return self._plugins[key][0].get_window()
|
return self._plugins[key].instance.get_window()
|
||||||
|
|
||||||
def toggle_plugin(self, key):
|
def toggle_plugin(self, key):
|
||||||
"""
|
"""
|
||||||
|
@ -116,12 +134,12 @@ class PluginLoader(ToxSave):
|
||||||
:param key: plugin short name
|
:param key: plugin short name
|
||||||
"""
|
"""
|
||||||
plugin = self._plugins[key]
|
plugin = self._plugins[key]
|
||||||
if plugin[1]:
|
if plugin.is_active:
|
||||||
plugin[0].stop()
|
plugin.instance.stop()
|
||||||
else:
|
else:
|
||||||
plugin[0].start()
|
plugin.instance.start()
|
||||||
plugin[1] = not plugin[1]
|
plugin.is_active = not plugin.is_active
|
||||||
if plugin[1]:
|
if plugin.is_active:
|
||||||
self._settings['plugins'].append(key)
|
self._settings['plugins'].append(key)
|
||||||
else:
|
else:
|
||||||
self._settings['plugins'].remove(key)
|
self._settings['plugins'].remove(key)
|
||||||
|
@ -133,28 +151,30 @@ class PluginLoader(ToxSave):
|
||||||
"""
|
"""
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
name = text.split()[0]
|
name = text.split()[0]
|
||||||
if name in self._plugins and self._plugins[name][1]:
|
if name in self._plugins and self._plugins[name].is_active:
|
||||||
self._plugins[name][0].command(text[len(name) + 1:])
|
self._plugins[name].instance.command(text[len(name) + 1:])
|
||||||
|
|
||||||
def get_menu(self, num):
|
def get_menu(self, num):
|
||||||
"""
|
"""
|
||||||
Return list of items for menu
|
Return list of items for menu
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
for elem in self._plugins.values():
|
for plugin in self._plugins.values():
|
||||||
if elem[1]:
|
if not plugin.is_active:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
result.extend(elem[0].get_menu(num))
|
result.extend(plugin.instance.get_menu(num))
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_message_menu(self, menu, selected_text):
|
def get_message_menu(self, menu, selected_text):
|
||||||
result = []
|
result = []
|
||||||
for elem in self._plugins.values():
|
for plugin in self._plugins.values():
|
||||||
if elem[1]:
|
if not plugin.is_active:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
result.extend(elem[0].get_message_menu(menu, selected_text))
|
result.extend(plugin.instance.get_message_menu(menu, selected_text))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
@ -164,8 +184,8 @@ class PluginLoader(ToxSave):
|
||||||
App is closing, stop all plugins
|
App is closing, stop all plugins
|
||||||
"""
|
"""
|
||||||
for key in list(self._plugins.keys()):
|
for key in list(self._plugins.keys()):
|
||||||
if self._plugins[key][1]:
|
if self._plugins[key].is_active:
|
||||||
self._plugins[key][0].close()
|
self._plugins[key].instance.close()
|
||||||
del self._plugins[key]
|
del self._plugins[key]
|
||||||
|
|
||||||
def reload(self):
|
def reload(self):
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import os
|
import os
|
||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
|
import utils.ui as util_ui
|
||||||
|
import common.tox_save as tox_save
|
||||||
|
|
||||||
|
|
||||||
MAX_SHORT_NAME_LENGTH = 5
|
MAX_SHORT_NAME_LENGTH = 5
|
||||||
|
@ -26,25 +28,22 @@ def log(name, data):
|
||||||
fl.write(str(data) + '\n')
|
fl.write(str(data) + '\n')
|
||||||
|
|
||||||
|
|
||||||
class PluginSuperClass:
|
class PluginSuperClass(tox_save.ToxSave):
|
||||||
"""
|
"""
|
||||||
Superclass for all plugins. Plugin is Python3 module with at least one class derived from PluginSuperClass.
|
Superclass for all plugins. Plugin is Python3 module with at least one class derived from PluginSuperClass.
|
||||||
"""
|
"""
|
||||||
is_plugin = True
|
is_plugin = True
|
||||||
|
|
||||||
def __init__(self, name, short_name, tox=None, profile=None, settings=None, encrypt_save=None):
|
def __init__(self, name, short_name, app):
|
||||||
"""
|
"""
|
||||||
Constructor. In plugin __init__ should take only 4 last arguments
|
Constructor. In plugin __init__ should take only 1 last argument
|
||||||
:param name: plugin full name
|
:param name: plugin full name
|
||||||
:param short_name: plugin unique short name (length of short name should not exceed MAX_SHORT_NAME_LENGTH)
|
:param short_name: plugin unique short name (length of short name should not exceed MAX_SHORT_NAME_LENGTH)
|
||||||
:param tox: tox instance
|
:param app: App instance
|
||||||
:param profile: profile instance
|
|
||||||
:param settings: profile settings
|
|
||||||
:param encrypt_save: ToxES instance.
|
|
||||||
"""
|
"""
|
||||||
self._settings = settings
|
tox = getattr(app, '_tox')
|
||||||
self._profile = profile
|
super().__init__(tox)
|
||||||
self._tox = tox
|
self._settings = getattr(app, '_settings')
|
||||||
name = name.strip()
|
name = name.strip()
|
||||||
short_name = short_name.strip()
|
short_name = short_name.strip()
|
||||||
if not name or not short_name:
|
if not name or not short_name:
|
||||||
|
@ -52,7 +51,6 @@ class PluginSuperClass:
|
||||||
self._name = name
|
self._name = name
|
||||||
self._short_name = short_name[:MAX_SHORT_NAME_LENGTH]
|
self._short_name = short_name[:MAX_SHORT_NAME_LENGTH]
|
||||||
self._translator = None # translator for plugin's GUI
|
self._translator = None # translator for plugin's GUI
|
||||||
self._encrypt_save = encrypt_save
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Get methods
|
# Get methods
|
||||||
|
@ -99,12 +97,6 @@ class PluginSuperClass:
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_tox(self, tox):
|
|
||||||
"""
|
|
||||||
New tox instance
|
|
||||||
"""
|
|
||||||
self._tox = tox
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Plugin was stopped, started or new command received
|
# Plugin was stopped, started or new command received
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -133,11 +125,9 @@ class PluginSuperClass:
|
||||||
:param command: string with command
|
:param command: string with command
|
||||||
"""
|
"""
|
||||||
if command == 'help':
|
if command == 'help':
|
||||||
msgbox = QtWidgets.QMessageBox()
|
text = util_ui.tr('No commands available')
|
||||||
title = QtWidgets.QApplication.translate("PluginWindow", "List of commands for plugin {}")
|
title = util_ui.tr('List of commands for plugin {}').format(self._name)
|
||||||
msgbox.setWindowTitle(title.format(self._name))
|
util_ui.message_box(text, title)
|
||||||
msgbox.setText(QtWidgets.QApplication.translate("PluginWindow", "No commands available"))
|
|
||||||
msgbox.exec_()
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Translations support
|
# Translations support
|
||||||
|
|
Loading…
Reference in a new issue