Subversion Repositories Scribus

Rev

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