Subversion Repositories Scribus

Rev

Rev 1731 | Rev 2187 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1549 subik 1
#include "pluginmanager.h"
1551 fschmid 2
#include "pluginmanager.moc"
1549 subik 3
#include <dlfcn.h>
4
#include <qdir.h>
5
#include "scribus.h"
6
#include "menumanager.h"
7
#include "scraction.h"
8
#include "splash.h"
9
#include "mpalette.h"
10
#include "tree.h"
1552 subik 11
#include "prefsfile.h"
1693 craig 12
#include "scpaths.h"
1549 subik 13
 
14
extern ScribusApp *ScApp;
1552 subik 15
extern PrefsFile *prefsFile;
1549 subik 16
 
17
 
18
PluginManager::PluginManager()
19
{
20
        dllInput = "";
21
        dllReturn = "";
1552 subik 22
        prefs = prefsFile->getPluginContext("pluginmanager");
1549 subik 23
}
24
 
25
PluginManager::~PluginManager()
26
{
27
}
28
 
1596 subik 29
void PluginManager::savePreferences()
30
{
31
        // write configuration
32
        for (QMap<int, PluginData>::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
33
                prefs->set(it.data().pluginFile, it.data().loadPlugin);
34
}
35
 
1549 subik 36
void PluginManager::initPlugs()
37
{
1552 subik 38
        QString name = "";
1549 subik 39
        int id = 0;
40
        struct PluginData pda;
1665 craig 41
        QString libPattern = QString("*.%1*").arg(PluginManager::platformDllExtension());
1693 craig 42
 
43
        QDir dirList(ScPaths::instance().pluginDir(),
44
                                 libPattern, QDir::Name,
45
                                 QDir::Files | QDir::Executable | QDir::NoSymLinks);
46
 
1552 subik 47
        if ((dirList.exists()) && (dirList.count() != 0))
1549 subik 48
        {
49
                ScApp->scrMenuMgr->addMenuSeparator("Extras");
1552 subik 50
                for (uint dc = 0; dc < dirList.count(); ++dc)
1549 subik 51
                {
1552 subik 52
                        pda.index = 0;
53
                        pda.pluginFile = "";
54
                        pda.menuID = 0;
55
                        pda.pluginFile = dirList[dc];
56
                        pda.loadPlugin = prefs->getBool(dirList[dc], true);
57
 
58
                        if (DLLname(dirList[dc], &pda.name, &pda.type, &pda.index, &id, &pda.actName, &pda.actKeySequence, &pda.actMenu, &pda.actMenuAfterName, &pda.actEnabledOnStartup, pda.loadPlugin))
1549 subik 59
                        {
2186 cbradney 60
                                pda.actMenuText=pda.name;
1596 subik 61
                                if (ScApp->splashScreen != NULL)
62
                                        ScApp->splashScreen->setStatus(tr(QString("Loading: %1").arg(pda.name), "plugin manager"));
1552 subik 63
                                if (pda.loadPlugin)
1549 subik 64
                                {
1552 subik 65
                                        if (pda.type == Persistent || pda.type == Standard || pda.type == Import)
66
                                        {
67
                                                //Add in ScrAction based plugin linkage
68
                                                //Insert DLL Action into Dictionary with values from plugin interface
69
                                                ScApp->scrActions.insert(pda.actName, new ScrAction(ScrAction::DLL, QIconSet(), pda.name, QKeySequence(pda.actKeySequence), ScApp, pda.actName, id));
1549 subik 70
 
1552 subik 71
                                                if (ScApp->scrActions[pda.actName])
72
                                                {
73
                                                        ScApp->scrActions[pda.actName]->setEnabled(pda.actEnabledOnStartup);
74
                                                        //Connect DLL Action's activated signal with ID to Scribus DLL loader
75
                                                        connect( ScApp->scrActions[pda.actName], SIGNAL(activatedData(int)) , ScApp->pluginManager, SLOT(callDLLBySlot(int)) );
76
                                                        //Get the menu manager to add the DLL's menu item to the right menu, after the chosen existing item
77
                                                        if (QString(pda.actMenuAfterName).length()==0)
78
                                                                ScApp->scrMenuMgr->addMenuItem(ScApp->scrActions[pda.actName], pda.actMenu);
79
                                                        else
80
                                                                ScApp->scrMenuMgr->addMenuItemAfter(ScApp->scrActions[pda.actName], pda.actMenu, pda.actMenuAfterName);
81
                                                }
1549 subik 82
                                        }
1552 subik 83
                                        else
84
                                                qDebug(tr(QString("Old type plugins are not supported anymore")), "plugin manager");
1596 subik 85
                                        pda.loaded = true;
1552 subik 86
                                } // load
1596 subik 87
                                else
88
                                        pda.loaded = false;
1549 subik 89
                                pluginMap.insert(id, pda);
90
                        }
91
                }
92
        }
93
}
94
 
95
void PluginManager::callDLLBySlot(int pluginID)
96
{
97
        //Run old type 2 Import pre call code
1552 subik 98
        if (pluginMap[pluginID].type == 7)
1549 subik 99
        {
100
                if (ScApp->HaveDoc)
101
                        ScApp->doc->OpenNodes = ScApp->outlinePalette->buildReopenVals();
102
        }
103
 
104
        callDLL(pluginID);
105
 
106
        //Run old type 2 Import post call code
1552 subik 107
        if (pluginMap[pluginID].type == 7)
1549 subik 108
        {
109
                if (ScApp->HaveDoc)
110
                {
111
                        ScApp->outlinePalette->BuildTree(ScApp->doc);
112
                        ScApp->outlinePalette->reopenTree(ScApp->doc->OpenNodes);
113
                        ScApp->propertiesPalette->updateCList();
114
                }
115
        }
116
}
117
 
118
void PluginManager::callDLL(int pluginID)
119
{
120
        void *mo;
121
        const char *error;
122
        struct PluginData pda;
123
        pda = pluginMap[pluginID];
124
        typedef void (*sdem)(QWidget *d, ScribusApp *plug);
125
        sdem demo;
1693 craig 126
        QString plugDir = ScPaths::instance().pluginDir();
1552 subik 127
        if (pda.type != 4 && pda.type !=5)
1549 subik 128
        {
1552 subik 129
                plugDir += pda.pluginFile;
1549 subik 130
                mo = dlopen(plugDir, RTLD_LAZY | RTLD_GLOBAL);
131
                if (!mo)
132
                {
1552 subik 133
                        qDebug(tr("Can't find Plug-in"), "plugin manager");
1549 subik 134
                        return;
135
                }
136
        }
137
        else
1552 subik 138
                mo = pda.index;
1549 subik 139
        dlerror();
1552 subik 140
        demo = (sdem)dlsym(mo, "run");
1549 subik 141
        if ((error = dlerror()) != NULL)
142
        {
1552 subik 143
                qDebug(tr(QString("Can't find Symbol (%1)").arg(error)), "plugin manager");
1549 subik 144
                dlclose(mo);
145
                return;
146
        }
147
        (*demo)(ScApp, ScApp);
148
        // FIXME: how is the menu organized? (*demo)(ScApp->scrActions[pluginMap[pluginID].actName], ScApp);
1552 subik 149
        if (pda.type != 4 && pda.type != 5)
1549 subik 150
                dlclose(mo);
151
        if (ScApp->HaveDoc)
152
                ScApp->view->DrawNew();
153
}
154
 
155
bool PluginManager::DLLexists(int pluginID)
156
{
157
        return pluginMap.contains(pluginID);
158
}
159
 
160
// used anywhere?
161
void PluginManager::callDLLbyMenu(int pluginID)
162
{
163
        QMap<int, PluginData>::Iterator it;
164
        struct PluginData pda;
165
        for (it = pluginMap.begin(); it != pluginMap.end(); ++it)
166
        {
1552 subik 167
                if (it.data().menuID == pluginID)
1549 subik 168
                {
169
                        callDLL(it.key());
170
                        break;
171
                }
172
        }
173
}
174
 
1552 subik 175
bool PluginManager::DLLname(QString name, QString *pluginName, PluginType *type, void **index, int *idNr, QString *actName, QString *actKeySequence, QString *actMenu, QString *actMenuAfterName, bool *actEnabledOnStartup, bool loadPlugin)
1549 subik 176
{
177
        void *mo;
178
        const char *error;
179
        typedef QString (*sdem0)();
1552 subik 180
        typedef PluginType (*sdem1)();
1549 subik 181
        typedef void (*sdem2)(QWidget *d, ScribusApp *plug);
182
        typedef bool (*sdem3)();
1552 subik 183
        typedef int (*sdemID)();
1549 subik 184
        sdem0 demo;
185
        sdem1 demo1;
186
        sdem2 demo2;
187
        sdem3 demo3;
1552 subik 188
        sdemID plugID;
1693 craig 189
        QString plugName = ScPaths::instance().pluginDir();
1549 subik 190
        plugName += name;
1596 subik 191
 
1549 subik 192
        mo = dlopen(plugName, RTLD_LAZY | RTLD_GLOBAL);
193
        if (!mo)
194
        {
1552 subik 195
                qDebug(tr(QString("Error: %1").arg(dlerror())), "plugin manager");
1549 subik 196
                return false;
197
        }
198
        dlerror();
1552 subik 199
        demo = (sdem0)dlsym(mo, "name");
1549 subik 200
        if ((error = dlerror()) != NULL)
201
        {
202
                dlclose(mo);
203
                return false;
204
        }
1552 subik 205
        *pluginName = (*demo)();
1549 subik 206
        dlerror();
1552 subik 207
        demo1 = (sdem1)dlsym(mo, "type");
1549 subik 208
        if ((error = dlerror()) != NULL)
209
        {
210
                dlclose(mo);
211
                return false;
212
        }
1552 subik 213
        *type = (*demo1)();
214
        *index = mo;
215
        plugID = (sdemID)dlsym(mo, "ID");
1549 subik 216
        if ((error = dlerror()) != NULL)
217
        {
218
                dlclose(mo);
219
                return false;
220
        }
1552 subik 221
        *idNr = (*plugID)();
1549 subik 222
        //ScrAction based plugins
1552 subik 223
        if (*type == Persistent || *type == Standard || *type == Import)
1549 subik 224
        {
225
                demo = (sdem0)dlsym(mo, "actionName");
226
                if ((error = dlerror()) != NULL)
227
                {
228
                        dlclose(mo);
229
                        return false;
230
                }
231
                *actName = (*demo)();
232
                dlerror();
233
                demo = (sdem0)dlsym(mo, "actionKeySequence");
234
                if ((error = dlerror()) != NULL)
235
                {
236
                        dlclose(mo);
237
                        return false;
238
                }
239
                *actKeySequence = (*demo)();
240
                dlerror();
241
                demo = (sdem0)dlsym(mo, "actionMenu");
242
                if ((error = dlerror()) != NULL)
243
                {
244
                        dlclose(mo);
245
                        return false;
246
                }
247
                *actMenu = (*demo)();
248
                dlerror();
249
                demo = (sdem0)dlsym(mo, "actionMenuAfterName");
250
                if ((error = dlerror()) != NULL)
251
                {
252
                        dlclose(mo);
253
                        return false;
254
                }
255
                *actMenuAfterName = (*demo)();
256
                dlerror();
257
                demo3 = (sdem3)dlsym(mo, "actionEnabledOnStartup");
258
                if ((error = dlerror()) != NULL)
259
                {
260
                        dlclose(mo);
261
                        return false;
262
                }
263
                *actEnabledOnStartup = (*demo3)();
264
        }
265
        else
266
        {
267
                *actName = QString::null;
268
                *actKeySequence = QString::null;
269
                *actMenu = QString::null;
270
                *actMenuAfterName = QString::null;
271
                *actEnabledOnStartup = false;
272
        }
1552 subik 273
        if (*type != Persistent && *type!= Type5)
1549 subik 274
                dlclose(mo);
275
        else
276
        {
1596 subik 277
                if (loadPlugin)
1549 subik 278
                {
1596 subik 279
                        dlerror();
280
                        demo2 = (sdem2)dlsym(mo, "initPlug");
281
                        if ((error = dlerror()) != NULL)
282
                        {
283
                                dlclose(mo);
284
                                return false;
285
                        }
286
                        (*demo2)(ScApp, ScApp);
1549 subik 287
                }
288
        }
289
 
290
        return true;
291
}
292
 
293
void PluginManager::finalizePlugs()
294
{
1552 subik 295
        for (QMap<int, PluginData>::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
1596 subik 296
                if (it.data().loaded == true)
297
                        finalizePlug(it.key());
1552 subik 298
}
299
 
300
void PluginManager::finalizePlug(int pluginID)
301
{
1549 subik 302
        const char *error;
303
        struct PluginData pda;
304
        typedef void (*sdem2)();
305
        sdem2 demo2;
1552 subik 306
        PluginData plug = pluginMap[pluginID];
307
        if (plug.type == Persistent || plug.type == Type5)
1549 subik 308
        {
1552 subik 309
                dlerror();
310
                demo2 = (sdem2)dlsym(plug.index, "cleanUpPlug");
311
                if ((error = dlerror()) != NULL)
1549 subik 312
                {
1552 subik 313
                        dlclose(plug.index);
1549 subik 314
                }
1552 subik 315
                else
316
                        (*demo2)();
1549 subik 317
        }
318
}
1552 subik 319
 
320
QString PluginManager::getPluginType(PluginType aType)
321
{
322
        switch(aType)
323
        {
324
                case Persistent:
325
                        return tr("Persistent", "plugin manager");
326
                        break;
327
                case Import:
328
                        return tr("Import", "plugin manager");
329
                        break;
330
                case Standard:
331
                        return tr("Standard", "plugin manager");
332
                        break;
333
                default:
334
                        return tr("Unknown", "plugin manager");
335
        }
336
}
1665 craig 337
 
338
QCString PluginManager::platformDllExtension()
339
{
340
#ifdef __hpux
341
        // HP/UX
342
        return "sl";
343
#elif defined(__APPLE__) && defined(__MACH__)
344
        // MacOS/X, Darwin
1731 craig 345
 
346
        // MacOS/X may actually use both 'so' and 'dylib'. .so is usually used
347
        // for plugins etc, dylib for system and app libraries We need to
348
        // support this distinction in the plugin manager, but for now it's
349
        // most appropriate to return the extension used by plugins -- CR
350
 
351
        //return "dylib";
352
        return "so";
1665 craig 353
#else
354
        // Generic *NIX
355
        return "so";
356
#endif
357
}