Subversion Repositories Scribus

Rev

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