Есть необходимость создать систему расширений для приложения на PyQt4. Требуется, чтобы они могли что-либо добавлять в окно/диалоги программы, выводить сообщения на её трей. Не могу представить, как реализовать подобную архитектуру :/ Есть идеи?
Начать, наверное, стоит и изучения Qt4. А если точнее, системы плагинов, которая там присутствует. Но это так, для общего развития... Ибо в питоне есть такая функция -- __import__, и с помощью неё я создал у себя динамическую систему плагинов (а если точнее пакетов, но принцип тот же).
Что нужно? Определится с API плагинов. Он вытекает из требуемой функциональности. А дальше импортируешь класс-плагин (например от QObject, или сразу QDialog), создаёшь объект с родителем -- плагин-менеджером и... дальше сам разбирёшься. Ничего, впринципе, сложного.

P.S. И не забудь про reload, а то я как-то по-парился...
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Реализовал таки систему плагинов, но оно не работает так, как задумывалось =\

Итак, есть базовый класс Plugin:
#       Copyright (C) 2007-2008 GFORGX <gforgx@gmail.com>
#       Distributed under the terms of revised BSD license.

from PyQt4 import QtCore, QtGui

class Plugin(QtCore.QObject):
    def __init__(self, main):
        self.setObjectName("Plugin")
        self.main = main
        self.icon = "/usr/share/notefinder/note.png"
        self.action = 'Does nothing'
        
    def load(self):
        action = QtGui.QAction(QtGui.QIcon(self.icon), QtGui.QApplication.translate("Plugin", self.action, None, QtGui.QApplication.UnicodeUTF8), self.main)
        self.main.ui.menuPlugins.addAction(action)
        self.connect(action, QtCore.SIGNAL("triggered()"), self.do)
    
    def currentNote(self):
        list = self.main.ui.notesList
        index = list.currentRow()
        item = list.item(index)
        if not item is None:
            note = str(item.text().toUtf8())
            return note

    def do(self):
        pass
Есть плагин, например:

#       Copyright (C) 2008 GFORGX <gforgx@gmail.com>
#       Distributed under the terms of revised BSD license.

from notefinder import plugin
from libnofi import Note
from PyQt4 import QtGui
from datetime import datetime

class ClipboardCapture(plugin.Plugin):
    def __init__(self, main):
        self.main = main
        self.action = "Capture clipboard"
        self.icon = "/usr/share/notefinder/paste.png"
    
    def do(self):
        cb = QtGui.QApplication.clipboard()
        text = str(cb.text().toUtf8())
        name = 'New note %s' % (datetime.strftime(datetime.today(),'%Y-%m-%d-%H:%M:%S'))
        note = Note(name)
        note.write(text)
Программа грузит это так (через egg entry points):
#       Copyright (C) 2008 GFORGX <gforgx@gmail.com>
#	 Distributed under the terms of revised BSD license.
import pkg_resources
for ep in pkg_resources.iter_entry_points('notefinder.plugins'):
    plugin = ep.load()
    plug_in = plugin(main)
    plug_in.load()
Т. е. плагину при инициализации в качестве аргумента передаётся основное окно программы.

В менюшке Plugins в программе появляются, но нажатие на них не приводит ни к чему, хотя, по идее, должен выполняться метод do =\

Last edited July 3, 2008, 12:55 p.m.

В общем, судя по всему, проблема в том, что вот тут:
action = QtGui.QAction(QtGui.QIcon(self.icon), QtGui.QApplication.translate("Plugin", self.action, None, QtGui.QApplication.UnicodeUTF8), self.main)

я указываю в качестве последнего параметра окно программы, а не сам объект плагин.
Если заменяю self.main на self - то:
[gforgx@ffap ~]$ notefinder
Traceback (most recent call last):
  File "/usr/bin/notefinder", line 45, in <module>
    plug_in.load()
  File "/usr/lib/python2.5/site-packages/notefinder/plugin.py", line 43, in load
    action = QtGui.QAction(QtGui.QIcon(self.icon), self.action, self)
RuntimeError: underlying C/C++ object has been deleted
ты забыл в потомке вызвать конструктор родителя
Be easy, stay cool