plugins refactoring

This commit is contained in:
ingvar1995 2018-07-16 21:29:15 +03:00
parent 2a97beb5af
commit 9c742d10de
4 changed files with 91 additions and 81 deletions

View file

@ -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))

View file

@ -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):
""" """

View file

@ -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):

View file

@ -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