Russian Qt Forum

Программирование => Общий => Тема начата: Igors от Июнь 24, 2015, 14:47



Название: Файлы плагинов
Отправлено: Igors от Июнь 24, 2015, 14:47
Добрый день

Есть хост и плагины которые частенько заводят свои файлы данных. Обычно плагин создает фолдер "рядом с собой" и туда льет. При переносе проектов приложения получается не очень хорошо, еще хуже при выполнении сетевой задачи (когда плагины на др конце). При отключении плагина (не удалении самого плагина, а просто сейчас перестали юзать) файлы данных никто не чистит. Ну и.т.п., в общем - бардак. 

Др словами назрела необходимость расширить API плагинов чтобы все было цивильно, плагин не лез сам, а обращался к хосту чтобы создать/удалить/получить файл. Что Вы "рекомендуете"?  :)  Как насчет "готовых, проверенных решений" - в данном случае я бы ими с удовольствием воспользовался.

Спасибо


Название: Re: Файлы плагинов
Отправлено: kai666_73 от Июнь 24, 2015, 16:00
Я бы не ограничивал плагины подобным образом, а дополнил бы их необходимыми абстрактными методами
Код
C++ (Qt)
class IPlugin
{
public:
  ...
  virtual void saveState() const = 0;
  virtual void restoreState() = 0;
  virtual void clear() = 0;
  ...
};
 
А вот хост пусть хранит список плагинов и в соотв. моменты вызывает соотв. методы для всех плагинов.


Название: Re: Файлы плагинов
Отправлено: Igors от Июнь 24, 2015, 16:20
Я бы не ограничивал плагины подобным образом, а дополнил бы их необходимыми абстрактными методами
Код
C++ (Qt)
class IPlugin
{
public:
  ...
  virtual void saveState() const = 0;
  virtual void restoreState() = 0;
  virtual void clear() = 0;
  ...
};
 
А вот хост пусть хранит список плагинов и в соотв. моменты вызывает соотв. методы для всех плагинов.
Не очень понял что делают эти методы. Пример

- пользователь запустил хост и открыл какой-то проект. Добавил в проект плагин, пусть этот плагин создает 3D объект, напр сферу. Потом еще добавил этот же плагин - в проекте (и окнах хоста) появилась еще сфера. Потом решил удалить первую сферу. Но перепутал и не ту удалил. Спохватился, вызвал undo и исправил. Наконец засейвил файл проекта и закрыл приложение-хост.

Это я к тому что плагину рулить файлами самому (как это сейчас) довольно напряжно


Название: Re: Файлы плагинов
Отправлено: sociopath от Июнь 24, 2015, 18:04
Ничего не понятно.
Архитектура клиент-серверная? Хост - это сервер? Или хост - это просто ядро приложения? Если просто ядро, то и называйте ядром.
Проекты хранятся в ФС клиента или сервера?

Если файл проекта должен быть переносимым, то, значит, файл проекта должен включать в себя всю необходимую информацию, в т.ч. какие плагины использует. Рядом с ним не должны лежать файлы, которые на другой машине понадобятся для корректного запуска проекта. Если просто временные файлы - создайте общий каталог для appdata с разбиением по каталогам для каждого плагина. Работа с ФС должна быть реализована через ядро приложения, плагинам лучше такое не доверять.


Название: Re: Файлы плагинов
Отправлено: Igors от Июнь 25, 2015, 08:57
Архитектура клиент-серверная? Хост - это сервер? Или хост - это просто ядро приложения? Если просто ядро, то и называйте ядром.
И так и так. Приложение может получать задачу по сети, но все может происходить и на одной машине. В любом случае сами плагины - "местные dll". 

Работа с ФС должна быть реализована через ядро приложения, плагинам лучше такое не доверять.
Это я уже прочувствовал, вопрос как лучше это сделать

Если просто временные файлы - создайте общий каталог для appdata с разбиением по каталогам для каждого плагина.
Если "временные" означает "один сеанс работы" - то и проблемы никакой нет, плагин создает такие файлы во временном каталоге ОС, уникальное имя гарантируется.

Речь идет о файлах которые требуют значительного времени для их создания и/или специальных действий. Поэтому они должны сохраняться перманентно, напр до тех пор пока установки плагина не изменились. Общий каталог с разбиением - ну так

1) Файл плагина имеет смысл в контексте  данного проекта. Кстати - неясно что делать если вызван напр "Save As" для проекта.

2) Один и тот же плагин может быть задействован в 1 проекте любое число раз с разными установками (см пример со сферой выше)

Хмм... вроде простая задача, начал обдумывать - оказалось совсем непросто  :)   


Название: Re: Файлы плагинов
Отправлено: kai666_73 от Июнь 25, 2015, 11:42
1) Файл плагина имеет смысл в контексте  данного проекта
Вот теперь только задачка вырисовывается ) ...
Хотите готовое решение?
Может кто-то и даст Вам его, но в контексте собственного понятия проекта и собственного понятия плагина.
Оно Вам надо? Оно Вам будет полезно?


Название: Re: Файлы плагинов
Отправлено: Igors от Июнь 25, 2015, 12:58
Вот теперь только задачка вырисовывается ) ...
Ну темы с плагинами здесь мелькают постоянно, думал чего все разжевывать  :)

Может кто-то и даст Вам его, но в контексте собственного понятия проекта и собственного понятия плагина.
Оно Вам надо? Оно Вам будет полезно?
Какие "собственные"?  Проект - данные (как собственные так и ссылки на внешние файлы/данные). Плагин - подгружаемый модуль. Проект может использовать плагин(ы). Вот собственно и все "понятия", никогда не видел каких-то других.

Хотите готовое решение?
Звучит типа - бездарь, сам придумать не может, вот и ищет готовое  :)


Название: Re: Файлы плагинов
Отправлено: sociopath от Июнь 25, 2015, 13:54
Перманентно требуемые файлы имхо нужно сохранять тупо в тот же каталог, где и каталог проекта. Если юзверь их удалил - пусть ждет, пока они пересоздадутся. Если изменились настройки проекта - то ядро должно их затереть и создать новые. Если этих файлов хренова туча и не хочется засорять ФС, можно создавать скрытый каталог с этими файлами рядом с проектным файлом (под unix-based системы скрытый каталог делается очень просто, а вот под win придется писать ветку с win api).

Имхо при сохранении проекта нужно все необходимые при переносе файлы запаковывать и сжимать в проектном файле. И этот файл будет переносимым между машинами, при условии, что есть все необходимые плагины. Но обеспечение наличия всех необходимых плагинов, как правило, возлагается на самого пользователя. Или если необходимого плагина нет, то клиент может запросить плагин у сервера. Мы делали такую схему - на стороне БД сервера достаточно простенькой таблицы plugin - os - version - file, где plugin - имя плагина, os - операционная система, version - версия приложения, file - id blob'a, в котором содержимое плагина.

У класса плагина Plugin должна быть функция типа virtual void init(ICoreObject* obj), которая вызывается при загрузке плагина. При выгрузке плагина должна вызываться функция virtual void finalize(). ICoreObject должен выглядеть как-то так:
Код:
class ICoreObject
{
public:
// сохранение перманентно требуемого файла рядом с проектом
   virtual bool saveFile(const QString& file, const QByteArray& data) = 0;
// сохранение данных в проектный файл
   virtual bool saveProject(const QByteArray& data) = 0;
};
В нем должны быть объявлены все функции, которые могут понадобиться плагинам. Так как это будет интерфейс, то плагинам достаточно будет подключать только заголовочный файл.
Ну и конечно должны быть реализованы все эти методы в приватном классе ядра. Причем в приватном классе желательно передавать в конструкторе имя плагина:
Код:
class CoreObject : public ICoreObject
{
public:
   CoreObject(const QString& plugin) : _plugin(plugin) {}
   QString plugin() const { return _plugin; }
// сохранение перманентно требуемого файла рядом с проектом
   bool saveFile(const QString& file, const QByteArray& data);
// сохранение данных в проектный файл
   bool saveProject(const QByteArray& data);

private:
   QString _plugin;
};
Таким образом, будет понятно, какой именно плагин дергает функции. Соответственно, при инициализации плагина ядро будет вызывать функцию loadPlugins:
Код:
QString getPluginNameFromPath(const QString& path);

void loadPlugins(const QStringList& pluginPaths)
{
    foreach (QString pluginPath, pluginPaths) {
        QPluginLoader l(pluginPath);
        if (!l.load())
            continue;
        Plugin* p = dynamic_cast<Plugin*>(l.instance());
        if (p == 0)
            continue;
        QString plugin = getPluginNameFromPath(pluginPath);
        CoreObject* obj = new CoreObject(plugin);
        p->init(obj);
        _plugins.insert(plugin, p);
        _objects.insert(plugin, obj);
    }
}

QString getPluginNameFromPath(const QString& path)
{
    QString result = QFileInfo(path).fileName();
#ifdef Q_WS_WIN
    result.chop(4);       // убираем с конца ".dll"
#else
#ifdef Q_WS_MAC
    result.chop(6);       // убираем с конца ".dylib"
#else
    result.chop(3);       // убираем с конца ".so"
#endif
    result = result.mid(3); // убираем с начала "lib"
#endif
    return result;
}

Но это такое. На самом деле, без знания алгоритмов, как формируется проектный и прочие файлы, сложно сказать, как лучше построить архитектуру.


Название: Re: Файлы плагинов
Отправлено: Igors от Июнь 25, 2015, 15:16
Но это такое. На самом деле, без знания алгоритмов, как формируется проектный и прочие файлы, сложно сказать, как лучше построить архитектуру.
Не вижу никакой "специфики" которую необходимо дополнительно знать. Проблемы-то видны невооруженным глазом. Мои соображения

1) Куда писать (место для файлов). Фолдер рядом с файлом проекта, напр "Plugin Data". Не вижу никакой необходимости делать его скрытым. Наоборот, юзер может в любой момент его очистить, да, будет ждать пересоздания.

2) Конфликт "несколько (инстансов) плагинов в одном проекте" - ну видимо решается уникальным ID которое хранится в хосте для каждого подключенного плагина. Именем файла (как оно в ФС) должен рулить хост, также хранить "внутреннее" имя, по которому плагин обращается к файлу.

3) Конфликт "несколько проектов в 1 фолдере" - пожалуй самый проблематичный случай. Городить "свой фолдер данных для каждого проекта" - думаю нехорошо.  Юзер решил работать с неск проектами в 1 фолдере (часто с неск версиями 1 проекта) - ну и "Plugin Data" один. Нужно какое-то "ID проекта" + полное имя файла проекта записанное в нем самом. Так можно отловить что проект скопирован/перемещен. Правда что дальше (и как синхронизировать файлы плагинов) - неясно. Обычно файл читается/используется гораздо чаще чем пишется, поэтому ничего плохого если неск проектов шарят файл(ы) по чтению.


Название: Re: Файлы плагинов
Отправлено: sociopath от Июнь 25, 2015, 17:19
Если очень хочется синхронизировать plugin data между разными проектами - флаг вам в руки) Я бы поленился таким заниматься. Имхо для каждого проекта свой plugin data будет и проще в реализации, и проще для пользователя (раз каталог не скрыт, то пользователь должен ясно понимать, к какому проекту он относится; в случае shared каталога он этого не поймет). Если файл проекта скопирован, программа должна иметь возможность восстановить рабочее состояние проекта, сгенерировав plugin data по новому пути. Ну это все имхо основанное на наблюдениях, как работает большинство софта с проектными файлами.


Название: Re: Файлы плагинов
Отправлено: Igors от Июнь 26, 2015, 09:24
Кажется все придумалось. Все-таки жаль что не удалось "попользоваться готовым" :) Ну ладно, это не последняя задача

Спасибо принявшим участие в обсуждении