Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
1549 subik 7
#include "pluginmanager.h"
3207 craig 8
#include "scplugin.h"
3850 fschmid 9
#include "loadsaveplugin.h"
2629 craig 10
 
10223 cbradney 11
#include <QDir>
10859 cbradney 12
#include <QEvent>
16546 jghali 13
#include <QMessageBox>
2629 craig 14
 
2688 craig 15
#include "scconfig.h"
2629 craig 16
 
1549 subik 17
#include "scribus.h"
5975 cbradney 18
#include "scribusdoc.h"
5243 cbradney 19
#include "scribuscore.h"
13576 cbradney 20
#include "ui/sctoolbar.h"
12566 cbradney 21
#include "selection.h"
14509 cbradney 22
#include "ui/scmwmenumanager.h"
1549 subik 23
#include "scraction.h"
13551 cbradney 24
#include "ui/splash.h"
2856 cbradney 25
#include "prefsmanager.h"
1552 subik 26
#include "prefsfile.h"
1693 craig 27
#include "scpaths.h"
5496 subik 28
#include "commonstrings.h"
17501 craig 29
#include "ui/storyeditor.h"
1549 subik 30
 
2629 craig 31
#ifdef HAVE_DLFCN_H
32
#include <dlfcn.h>
33
#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32)
34
#include <windows.h>
35
#else
10223 cbradney 36
#include <QLibrary>
2629 craig 37
#endif
38
 
3205 craig 39
 
2187 cbradney 40
extern ScribusQApp *ScQApp;
1549 subik 41
 
3207 craig 42
PluginManager::PluginManager() :
43
        QObject(0),
44
        prefs(PrefsManager::instance()->prefsFile->getPluginContext("pluginmanager"))
1549 subik 45
{
46
}
47
 
48
PluginManager::~PluginManager()
49
{
50
}
51
 
2629 craig 52
void* PluginManager::loadDLL( QString plugin )
53
{
54
        void* lib = NULL;
55
#ifdef HAVE_DLFCN_H
16577 craig 56
        QString libpath = QDir::toNativeSeparators( plugin );
10553 fschmid 57
        lib = dlopen(libpath.toLocal8Bit().data(), RTLD_LAZY | RTLD_GLOBAL);
2629 craig 58
        if (!lib)
59
        {
4413 cbradney 60
                const char* error = dlerror();
2630 craig 61
                qDebug("%s: %s",
10493 fschmid 62
                                tr("Cannot find plugin", "plugin manager").toLocal8Bit().data(),
63
                                error ? error : tr("unknown error","plugin manager").toLocal8Bit().data());
2629 craig 64
        }
65
        dlerror();
66
#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32)
16577 craig 67
        QString libpath = QDir::toNativeSeparators( plugin );
10304 jghali 68
        HINSTANCE hdll = LoadLibraryW( (const wchar_t*) libpath.utf16() );
2629 craig 69
        lib = (void*) hdll;
70
#else
71
        if( QFile::exists(plugin) )
72
                lib = (void*) new QLibrary( plugin );
73
        else
10752 craig 74
                qDebug("%s \"%s\"", tr("Cannot find plugin", "plugin manager").toLocal8Bit().data(), plugin.toLocal8Bit().data());
2629 craig 75
#endif
76
        return lib;
77
}
78
 
79
void* PluginManager::resolveSym( void* plugin, const char* sym )
80
{
81
        void* symAddr = NULL;
82
#ifdef HAVE_DLFCN_H
83
        const char* error;
84
        dlerror();
85
        symAddr = dlsym( plugin, sym );
86
        if ((error = dlerror()) != NULL)
87
        {
10493 fschmid 88
                qDebug("%s", tr("Cannot find symbol (%1)", "plugin manager").arg(error).toLocal8Bit().data());
2629 craig 89
                symAddr = NULL;
90
        }
91
#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32)
92
        symAddr = (void* ) GetProcAddress( (HMODULE) plugin, sym);
93
        if ( symAddr == NULL)
10493 fschmid 94
                qDebug("%s", tr("Cannot find symbol (%1)", "plugin manager").arg(sym).toLocal8Bit().data());
2629 craig 95
#else
96
        QLibrary* qlib = (QLibrary*) plugin;
97
        if( plugin ) symAddr = qlib->resolve(sym);
98
        if ( symAddr == NULL)
10493 fschmid 99
                qDebug("%s", tr("Cannot find symbol (%1)", "plugin manager").arg(sym).toLocal8Bit().data());
2629 craig 100
#endif
101
        return symAddr;
102
}
103
 
104
void  PluginManager::unloadDLL( void* plugin )
105
{
106
#ifdef HAVE_DLFCN_H
107
        dlclose( plugin );
108
        dlerror();
109
#elif defined(DLL_USE_NATIVE_API) && defined(_WIN32)
110
        FreeLibrary( (HMODULE) plugin );
111
#else
112
        delete ( (QLibrary*) plugin );
113
#endif
114
}
115
 
1596 subik 116
void PluginManager::savePreferences()
117
{
118
        // write configuration
3207 craig 119
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
10516 cbradney 120
                prefs->set(it.value().pluginName, it.value().enableOnStartup);
1596 subik 121
}
122
 
8552 subik 123
QString PluginManager::getPluginName(QString fileName)
3207 craig 124
{
11162 cbradney 125
        // Must return plugin name. Note that this may be platform dependent;
3207 craig 126
        // it's likely to need some adjustment for platform naming schemes.
127
        // It currently handles:
128
        //    (lib)?pluginname(\.pluginext)?
129
        QFileInfo fi(fileName);
130
        QString baseName(fi.baseName());
131
        if (baseName.startsWith("lib"))
132
                baseName = baseName.remove(0,3);
133
        if (baseName.endsWith(platformDllExtension()))
15498 jghali 134
                baseName.chop(1 + platformDllExtension().length());
3207 craig 135
        // check name
136
        for (int i = 0; i < (int)baseName.length(); i++)
137
                if (! baseName[i].isLetterOrNumber() && baseName[i] != '_' )
138
                {
139
                        qDebug("Invalid character in plugin name for %s; skipping",
10493 fschmid 140
                                        fileName.toLocal8Bit().data());
8552 subik 141
                        return QString();
3207 craig 142
                }
10553 fschmid 143
        return baseName.toLatin1();
3207 craig 144
}
145
 
5496 subik 146
int PluginManager::initPlugin(const QString fileName)
147
{
148
        PluginData pda;
149
        pda.pluginFile = QString("%1/%2").arg(ScPaths::instance().pluginDir()).arg(fileName);
150
        pda.pluginName = getPluginName(pda.pluginFile);
151
        if (pda.pluginName.isNull())
152
                // Couldn't determine plugname from filename. We've already complained, so
153
                // move on to the next one.
154
                return 0;
155
        pda.plugin = 0;
156
        pda.pluginDLL = 0;
157
        pda.enabled = false;
12566 cbradney 158
        pda.enableOnStartup = prefs->getBool(pda.pluginName, false);
6260 fschmid 159
        ScCore->setSplashStatus( tr("Plugin: loading %1", "plugin manager").arg(pda.pluginName));
5496 subik 160
        if (loadPlugin(pda))
161
        {
13382 cbradney 162
                //HACK: Always enable our only persistent plugin, scripter
163
                if (pda.plugin->inherits("ScPersistentPlugin"))
164
                        pda.enableOnStartup=true;
5496 subik 165
                if (pda.enableOnStartup)
166
                        enablePlugin(pda);
167
                pluginMap.insert(pda.pluginName, pda);
168
                return 1;
169
        }
170
        return 0;
171
}
172
 
1549 subik 173
void PluginManager::initPlugs()
174
{
3207 craig 175
        Q_ASSERT(!pluginMap.count());
176
        QString libPattern = QString("*.%1*").arg(platformDllExtension());
5496 subik 177
        QMap<QString,int> allPlugs;
8561 subik 178
        int loaded = 0;
5496 subik 179
        uint changes = 1;
5710 subik 180
        QStringList failedPlugs; // output string for warn dialog
1693 craig 181
 
5047 subik 182
        /*! \note QDir::Reversed is there due the Mac plugin dependency.
183
        barcode depends on psimport. and load on that platform expect the
5496 subik 184
        psimp before barcode.You know, security by obscurity ;) PV */
1693 craig 185
        QDir dirList(ScPaths::instance().pluginDir(),
5047 subik 186
                                 libPattern, QDir::Name | QDir::Reversed,
10402 jghali 187
                                 (QDir::Filter) PluginManager::platformDllSearchFlags());
1693 craig 188
 
5496 subik 189
        if ((!dirList.exists()) || (dirList.count() == 0))
190
                return;
191
        for (uint dc = 0; dc < dirList.count(); ++dc)
1549 subik 192
        {
5496 subik 193
                int res = initPlugin(dirList[dc]);
194
                allPlugs[dirList[dc]] = res;
195
                if (res != 0)
196
                        ++loaded;
5710 subik 197
                else
198
                        failedPlugs.append(dirList[dc]);
5496 subik 199
        }
200
        /* Re-try the failed plugins again and again until it promote
201
        any progress (changes variable is changing ;)) */
7176 subik 202
        QMap<QString,int>::Iterator it;
5496 subik 203
        while (loaded < allPlugs.count() && changes!=0)
204
        {
205
                changes = 0;
206
                for (it = allPlugs.begin(); it != allPlugs.end(); ++it)
1549 subik 207
                {
10516 cbradney 208
                        if (it.value() != 0)
3207 craig 209
                                continue;
5496 subik 210
                        int res = initPlugin(it.key());
211
                        allPlugs[it.key()] = res;
212
                        if (res == 1)
1549 subik 213
                        {
5496 subik 214
                                ++loaded;
215
                                ++changes;
10553 fschmid 216
                                failedPlugs.removeAll(it.key());
1549 subik 217
                        }
218
                }
219
        }
5496 subik 220
        if (loaded != allPlugs.count())
5655 cbradney 221
        {
222
                if (ScCore->usingGUI())
223
                {
5710 subik 224
                        bool splashShown = ScCore->splashShowing();
225
                        QString failedStr("<ul>");
226
                        for (QStringList::Iterator it = failedPlugs.begin(); it != failedPlugs.end(); ++it)
227
                                failedStr += "<li>" + *it + "</li>";
228
                        failedStr += "</ul>";
5656 cbradney 229
                        if (splashShown)
230
                                ScCore->showSplash(false);
5781 cbradney 231
                        QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
6367 subik 232
                                                                 "<qt>" + tr("There is a problem loading %1 of %2 plugins. %3 This is probably caused by some kind of dependency issue or old plugins existing in your install directory. If you clean out your install directory and reinstall and this still occurs, please report it on bugs.scribus.net."
5710 subik 233
                                                                                ).arg(allPlugs.count()-loaded).arg(allPlugs.count()).arg(failedStr)
5496 subik 234
                                                                         + "</qt>",
235
                                                         CommonStrings::tr_OK);
5656 cbradney 236
                        if (splashShown)
237
                                ScCore->showSplash(true);
5655 cbradney 238
                }
239
        }
1549 subik 240
}
241
 
11162 cbradney 242
// After a plugin has been initialized, this method calls its setup
3207 craig 243
// routines and connects it to the application.
244
void PluginManager::enablePlugin(PluginData & pda)
1549 subik 245
{
3207 craig 246
        Q_ASSERT(pda.enabled == false);
247
        QString failReason;
5243 cbradney 248
        bool isActionPlugin=false;
3207 craig 249
        if (pda.plugin->inherits("ScActionPlugin"))
1549 subik 250
        {
11580 subik 251
//              ScActionPlugin* plugin = dynamic_cast<ScActionPlugin*>(pda.plugin);
252
//              Q_ASSERT(plugin);
5243 cbradney 253
                isActionPlugin=true;
254
                /*
3207 craig 255
                pda.enabled = setupPluginActions(plugin);
256
                if (!pda.enabled)
257
                        failReason = tr("init failed", "plugin load error");
5243 cbradney 258
                */
1549 subik 259
        }
3207 craig 260
        else if (pda.plugin->inherits("ScPersistentPlugin"))
1549 subik 261
        {
3207 craig 262
                ScPersistentPlugin* plugin = dynamic_cast<ScPersistentPlugin*>(pda.plugin);
9810 avox 263
                assert(plugin);
3207 craig 264
                pda.enabled = plugin->initPlugin();
265
                if (!pda.enabled)
266
                        failReason = tr("init failed", "plugin load error");
1549 subik 267
        }
3850 fschmid 268
/* temporary hack to enable the import plugins */
269
        else if (pda.plugin->inherits("LoadSavePlugin"))
270
                pda.enabled = true;
1549 subik 271
        else
3207 craig 272
                failReason = tr("unknown plugin type", "plugin load error");
5243 cbradney 273
        if (pda.enabled || isActionPlugin)
274
                ScCore->setSplashStatus(
275
                                tr("Plugin: %1 loaded", "plugin manager")
276
                                .arg(pda.plugin->fullTrName()));
277
        else
278
                ScCore->setSplashStatus(
279
                                tr("Plugin: %1 failed to load: %2", "plugin manager")
280
                                .arg(pda.plugin->fullTrName()).arg(failReason));
281
}
282
 
283
bool PluginManager::setupPluginActions(ScribusMainWindow *mw)
284
{
285
        Q_CHECK_PTR(mw);
7176 subik 286
        ScActionPlugin* plugin = 0;
287
 
18556 craig 288
        mw->scrMenuMgr->addMenuItemString("SEPARATOR", "Extras");
5243 cbradney 289
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
1549 subik 290
        {
10516 cbradney 291
                if (it.value().plugin->inherits("ScActionPlugin"))
5243 cbradney 292
                {
293
                        //Add in ScrAction based plugin linkage
294
                        //Insert DLL Action into Dictionary with values from plugin interface
10516 cbradney 295
                        plugin = dynamic_cast<ScActionPlugin*>(it.value().plugin);
9810 avox 296
                        assert(plugin);
5243 cbradney 297
                        ScActionPlugin::ActionInfo ai(plugin->actionInfo());
9857 cbradney 298
                        ScrAction* action = new ScrAction(ScrAction::ActionDLL, ai.icon1, ai.icon2, ai.text, ai.keySequence, mw);
5243 cbradney 299
                        Q_CHECK_PTR(action);
15637 fschmid 300
                        action->setStatusTip(ai.helpText);
301
                        action->setToolTip(ai.helpText);
5243 cbradney 302
                        mw->scrActions.insert(ai.name, action);
7126 subik 303
 
5243 cbradney 304
                        // then enable and connect up the action
305
                        mw->scrActions[ai.name]->setEnabled(ai.enabledOnStartup);
306
                        // Connect action's activated signal with the plugin's run method
10728 cbradney 307
                        it.value().enabled = connect( mw->scrActions[ai.name], SIGNAL(triggeredData(ScribusDoc*)),
5781 cbradney 308
                                                        plugin, SLOT(run(ScribusDoc*)) );
18533 craig 309
 
310
                         //Get the menu manager to add the DLL's menu item to the right menu, after the chosen existing item
5243 cbradney 311
                        if ( ai.menuAfterName.isEmpty() )
11040 fschmid 312
                        {
313
                                if (!ai.menu.isEmpty())
11050 fschmid 314
                                {
315
                                        if ((!ai.subMenuName.isEmpty()) && (!ai.parentMenu.isEmpty()))
316
                                        {
317
                                                if (!mw->scrMenuMgr->menuExists(ai.menu))
18438 craig 318
                                                {
11050 fschmid 319
                                                        mw->scrMenuMgr->createMenu(ai.menu, ai.subMenuName, ai.parentMenu);
18438 craig 320
                                                }
11050 fschmid 321
                                        }
18533 craig 322
                                        mw->scrMenuMgr->addMenuItemString(ai.name, ai.menu);
11050 fschmid 323
                                }
11040 fschmid 324
                        }
5243 cbradney 325
                        else
5781 cbradney 326
                        {
16016 fschmid 327
//                              QString actionName(ai.menu.toLower()+ai.menuAfterName);
328
                                QString actionName(ai.menuAfterName);
5781 cbradney 329
                                ScrAction* afterAction=0;
330
                                if (mw->scrActions.contains(actionName))
331
                                        afterAction=mw->scrActions[actionName];
11050 fschmid 332
                                if ((!ai.subMenuName.isEmpty()) && (!ai.parentMenu.isEmpty()))
333
                                {
334
                                        if (!mw->scrMenuMgr->menuExists(ai.menu))
335
                                                mw->scrMenuMgr->createMenu(ai.menu, ai.subMenuName, ai.parentMenu);
336
                                }
18533 craig 337
                                mw->scrMenuMgr->addMenuItemStringAfter(ai.name, ai.menuAfterName, ai.menu);
5781 cbradney 338
                        }
11040 fschmid 339
                        if (!ai.toolbar.isEmpty())
340
                        {
18624 fschmid 341
                                QString tbName = ai.toolbar;
11040 fschmid 342
                                if (mw->scrToolBars.contains(tbName))
343
                                        mw->scrToolBars[tbName]->addAction(mw->scrActions[ai.name]);
344
                                else
345
                                {
346
                                        ScToolBar *tb = new ScToolBar(ai.toolBarName, ai.toolbar, mw);
347
                                        tb->addAction(mw->scrActions[ai.name]);
348
                                        mw->addScToolBar(tb, tbName);
349
                                }
350
                        }
10516 cbradney 351
                        if (it.value().enabled)
11040 fschmid 352
                                ScCore->setSplashStatus( tr("Plugin: %1 initialized ok ", "plugin manager").arg(plugin->fullTrName()));
5243 cbradney 353
                        else
11040 fschmid 354
                                ScCore->setSplashStatus( tr("Plugin: %1 failed post initialization", "plugin manager").arg(plugin->fullTrName()));
5243 cbradney 355
                }
3207 craig 356
                else
5243 cbradney 357
                {
10516 cbradney 358
                        it.value().plugin->addToMainWindowMenu(mw);
5243 cbradney 359
                }
7126 subik 360
 
1549 subik 361
        }
18568 craig 362
        //CB maybe we should just call mw->createMenuBar() here instead...
18533 craig 363
        mw->scrMenuMgr->clearMenu("File");
364
        mw->scrMenuMgr->addMenuItemStringstoMenuBar("File", mw->scrActions);
18568 craig 365
        mw->scrMenuMgr->clearMenu("Insert");
366
        mw->scrMenuMgr->addMenuItemStringstoMenuBar("Insert", mw->scrActions);
18533 craig 367
        mw->scrMenuMgr->clearMenu("Item");
368
        mw->scrMenuMgr->addMenuItemStringstoMenuBar("Item", mw->scrActions);
369
        mw->scrMenuMgr->clearMenu("Extras");
370
        mw->scrMenuMgr->addMenuItemStringstoMenuBar("Extras", mw->scrActions);
5243 cbradney 371
        return true;
1549 subik 372
}
373
 
17501 craig 374
bool PluginManager::setupPluginActions(StoryEditor *sew)
375
{
376
        Q_CHECK_PTR(sew);
377
        ScActionPlugin* plugin = 0;
378
 
379
        //sew->seMenuMgr->addMenuSeparator("Extras");
380
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
381
        {
382
                if (it.value().plugin->inherits("ScActionPlugin"))
383
                {
384
                        //Add in ScrAction based plugin linkage
385
                        //Insert DLL Action into Dictionary with values from plugin interface
386
                        plugin = dynamic_cast<ScActionPlugin*>(it.value().plugin);
387
                        assert(plugin);
388
                        ScActionPlugin::ActionInfo ai(plugin->actionInfo());
389
                        if (ai.enabledForStoryEditor)
390
                        {
391
                                ScrAction* action = new ScrAction(ScrAction::ActionDLLSE, ai.icon1, ai.icon2, ai.text, ai.keySequence, sew);
392
                                Q_CHECK_PTR(action);
393
                                sew->seActions.insert(ai.name, action);
394
 
395
                                // then enable and connect up the action
396
                                sew->seActions[ai.name]->setEnabled(ai.enabledForStoryEditor);
397
 
398
                                // Connect action's activated signal with the plugin's run method
399
                                it.value().enabled = connect( sew->seActions[ai.name], SIGNAL(triggeredData(QWidget*, ScribusDoc*)),
400
                                                        plugin, SLOT(run(QWidget*, ScribusDoc*)) );
401
                                //Get the menu manager to add the DLL's menu item to the right menu, after the chosen existing item
402
                                if ( ai.menuAfterName.isEmpty() )
403
                                {
404
                                        if (!ai.seMenu.isEmpty())
405
                                        {
406
                                                if ((!ai.subMenuName.isEmpty()) && (!ai.parentMenu.isEmpty()))
407
                                                {
408
                                                        if (!sew->seMenuMgr->menuExists(ai.seMenu))
409
                                                                sew->seMenuMgr->createMenu(ai.seMenu, ai.subMenuName, ai.parentMenu);
410
                                                }
18544 craig 411
//                                              sew->seMenuMgr->addMenuItem(sew->seActions[ai.name], ai.seMenu, true);
412
                                                sew->seMenuMgr->addMenuItemString(ai.name, ai.menu);
17501 craig 413
                                        }
414
                                }
415
                                else
416
                                {
417
                                        QString actionName(ai.seMenu.toLower()+ai.menuAfterName);
418
                                        ScrAction* afterAction=0;
419
                                        if (sew->seActions.contains(actionName))
420
                                                afterAction=sew->seActions[actionName];
421
                                        if ((!ai.subMenuName.isEmpty()) && (!ai.parentMenu.isEmpty()))
422
                                        {
423
                                                if (!sew->seMenuMgr->menuExists(ai.seMenu))
424
                                                        sew->seMenuMgr->createMenu(ai.seMenu, ai.subMenuName, ai.parentMenu);
425
                                        }
18544 craig 426
//                                      sew->seMenuMgr->addMenuItemAfter(sew->seActions[ai.name], ai.seMenu, true, afterAction);
427
                                        sew->seMenuMgr->addMenuItemStringAfter(ai.name, ai.menuAfterName, ai.menu);
17501 craig 428
                                }
429
                        }
430
                }
431
        }
432
        return true;
433
}
434
 
435
 
12566 cbradney 436
void PluginManager::enableOnlyStartupPluginActions(ScribusMainWindow* mw)
437
{
438
        Q_CHECK_PTR(mw);
439
        ScActionPlugin* plugin = 0;
440
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
441
        {
442
                if (it.value().plugin->inherits("ScActionPlugin"))
443
                {
444
                        plugin = dynamic_cast<ScActionPlugin*>(it.value().plugin);
445
                        assert(plugin);
446
                        ScActionPlugin::ActionInfo ai(plugin->actionInfo());
447
                        if (mw->scrActions.contains(ai.name))
448
                                mw->scrActions[ai.name]->setEnabled(ai.enabledOnStartup);
449
                }
450
        }
451
}
452
 
453
void PluginManager::enablePluginActionsForSelection(ScribusMainWindow* mw)
454
{
455
        Q_CHECK_PTR(mw);
456
        ScribusDoc* doc=mw->doc;
457
        if (!doc)
458
                return;
459
 
12794 cbradney 460
        ScActionPlugin* ixplug = 0;
12566 cbradney 461
        ScrAction* pluginAction = 0;
462
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
463
        {
464
                if (it.value().plugin->inherits("ScActionPlugin"))
465
                {
466
                        ixplug = dynamic_cast<ScActionPlugin*>(it.value().plugin);
467
                        Q_ASSERT(ixplug);
12794 cbradney 468
                        if (ixplug)
12566 cbradney 469
                        {
12794 cbradney 470
                                ScActionPlugin::ActionInfo ai(ixplug->actionInfo());
471
                                pluginAction = mw->scrActions[ai.name];
472
                                if (pluginAction != 0)
473
                                {
474
                                        if (doc->m_Selection->count() != 0)
475
                                                pluginAction->setEnabled(ixplug->handleSelection(doc, doc->m_Selection->itemAt(0)->itemType()));
476
                                        else
477
                                                pluginAction->setEnabled(ixplug->handleSelection(doc));
478
                                }
12566 cbradney 479
                        }
480
                }
481
        }
482
}
483
 
8552 subik 484
bool PluginManager::DLLexists(QString name, bool includeDisabled) const
1549 subik 485
{
3207 craig 486
        // the plugin name must be known
487
        if (pluginMap.contains(name))
3850 fschmid 488
        {
3207 craig 489
                // the plugin must be loaded
490
                if (pluginMap[name].plugin)
3850 fschmid 491
                {
3383 craig 492
                        // and the plugin must be enabled unless we were told otherwise
3850 fschmid 493
                        if (pluginMap[name].enabled)
3207 craig 494
                                return true;
3850 fschmid 495
                        else
496
                                return includeDisabled;
497
                }
498
        }
3207 craig 499
        return false;
1549 subik 500
}
501
 
3207 craig 502
bool PluginManager::loadPlugin(PluginData & pda)
1549 subik 503
{
3207 craig 504
        typedef int (*getPluginAPIVersionPtr)();
505
        typedef ScPlugin* (*getPluginPtr)();
506
        getPluginAPIVersionPtr getPluginAPIVersion;
507
        getPluginPtr getPlugin;
1549 subik 508
 
3207 craig 509
        Q_ASSERT(pda.plugin == 0);
510
        Q_ASSERT(pda.pluginDLL == 0);
511
        Q_ASSERT(!pda.enabled);
512
        pda.plugin = 0;
1596 subik 513
 
3207 craig 514
        pda.pluginDLL = loadDLL(pda.pluginFile);
515
        if (!pda.pluginDLL)
1549 subik 516
                return false;
2629 craig 517
 
3207 craig 518
        getPluginAPIVersion = (getPluginAPIVersionPtr)
10553 fschmid 519
                resolveSym(pda.pluginDLL, QString(pda.pluginName + "_getPluginAPIVersion").toLocal8Bit().data());
3207 craig 520
        if (getPluginAPIVersion)
1549 subik 521
        {
3207 craig 522
                int gotVersion = (*getPluginAPIVersion)();
523
                if ( gotVersion != PLUGIN_API_VERSION )
1549 subik 524
                {
3207 craig 525
                        qDebug("API version mismatch when loading %s: Got %i, expected %i",
10493 fschmid 526
                                        pda.pluginFile.toLocal8Bit().data(), gotVersion, PLUGIN_API_VERSION);
1549 subik 527
                }
3207 craig 528
                else
1549 subik 529
                {
3207 craig 530
                        getPlugin = (getPluginPtr)
10553 fschmid 531
                                resolveSym(pda.pluginDLL, QString(pda.pluginName + "_getPlugin").toLocal8Bit().data());
3207 craig 532
                        if (getPlugin)
1596 subik 533
                        {
3207 craig 534
                                pda.plugin = (*getPlugin)();
535
                                if (!pda.plugin)
536
                                {
537
                                        qDebug("Unable to get ScPlugin when loading %s",
10493 fschmid 538
                                                        pda.pluginFile.toLocal8Bit().data());
3207 craig 539
                                }
540
                                else
541
                                        return true;
1596 subik 542
                        }
1549 subik 543
                }
544
        }
3207 craig 545
        unloadDLL(pda.pluginDLL);
546
        pda.pluginDLL = 0;
547
        Q_ASSERT(!pda.plugin);
548
        return false;
1549 subik 549
}
550
 
3207 craig 551
void PluginManager::cleanupPlugins()
1549 subik 552
{
3207 craig 553
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
10516 cbradney 554
                if (it.value().enabled == true)
555
                        finalizePlug(it.value());
1552 subik 556
}
557
 
3207 craig 558
void PluginManager::finalizePlug(PluginData & pda)
1552 subik 559
{
3207 craig 560
        typedef void (*freePluginPtr)(ScPlugin* plugin);
561
        if (pda.plugin)
1549 subik 562
        {
3207 craig 563
                if (pda.enabled)
564
                        disablePlugin(pda);
565
                Q_ASSERT(!pda.enabled);
566
                freePluginPtr freePlugin =
10553 fschmid 567
                        (freePluginPtr) resolveSym(pda.pluginDLL, QString(pda.pluginName + "_freePlugin").toLocal8Bit().data());
3207 craig 568
                if ( freePlugin )
569
                        (*freePlugin)( pda.plugin );
570
                pda.plugin = 0;
1549 subik 571
        }
3207 craig 572
        Q_ASSERT(!pda.enabled);
573
        if (pda.pluginDLL)
574
        {
575
                unloadDLL(pda.pluginDLL);
576
                pda.pluginDLL = 0;
577
        }
1549 subik 578
}
1552 subik 579
 
3207 craig 580
void PluginManager::disablePlugin(PluginData & pda)
1552 subik 581
{
3207 craig 582
        Q_ASSERT(pda.enabled);
583
        Q_ASSERT(pda.plugin);
584
        if (pda.plugin->inherits("ScActionPlugin"))
1552 subik 585
        {
3207 craig 586
                ScActionPlugin* plugin = dynamic_cast<ScActionPlugin*>(pda.plugin);
9810 avox 587
                assert(plugin);
3207 craig 588
                // FIXME: Correct way to delete action?
5781 cbradney 589
                delete ScCore->primaryMainWindow()->scrActions[plugin->actionInfo().name];
1552 subik 590
        }
3207 craig 591
        else if (pda.plugin->inherits("ScPersistentPlugin"))
592
        {
593
                ScPersistentPlugin* plugin = dynamic_cast<ScPersistentPlugin*>(pda.plugin);
9810 avox 594
                assert(plugin);
3207 craig 595
                plugin->cleanupPlugin();
596
        }
3850 fschmid 597
/* temporary hack to enable the import plugins */
598
        else if (pda.plugin->inherits("LoadSavePlugin"))
599
                pda.enabled = false;
3207 craig 600
        else
601
                Q_ASSERT(false); // We shouldn't ever have enabled an unknown plugin type.
602
        pda.enabled = false;
1552 subik 603
}
1665 craig 604
 
8552 subik 605
QString PluginManager::platformDllExtension()
1665 craig 606
{
607
#ifdef __hpux
608
        // HP/UX
609
        return "sl";
610
#elif defined(__APPLE__) && defined(__MACH__)
611
        // MacOS/X, Darwin
1731 craig 612
 
613
        // MacOS/X may actually use both 'so' and 'dylib'. .so is usually used
614
        // for plugins etc, dylib for system and app libraries We need to
615
        // support this distinction in the plugin manager, but for now it's
616
        // most appropriate to return the extension used by plugins -- CR
617
 
618
        //return "dylib";
619
        return "so";
2629 craig 620
#elif defined(_WIN32) || defined(_WIN64)
621
        return "dll";
1665 craig 622
#else
623
        // Generic *NIX
624
        return "so";
625
#endif
626
}
2187 cbradney 627
 
10402 jghali 628
int PluginManager::platformDllSearchFlags()
629
{
630
#if defined(_WIN32) || defined(_WIN64)
631
        return (QDir::Files | QDir::NoSymLinks);
632
#else
633
        return (QDir::Files | QDir::Executable | QDir::NoSymLinks);
634
#endif
635
}
636
 
10859 cbradney 637
void PluginManager::changeEvent(QEvent *e)
638
{
639
        if (e->type() == QEvent::LanguageChange)
640
        {
641
                languageChange();
642
        }
643
}
644
 
2187 cbradney 645
void PluginManager::languageChange()
646
{
7176 subik 647
        ScPlugin* plugin = 0;
648
        ScActionPlugin* ixplug = 0;
649
        ScrAction* pluginAction = 0;
3207 craig 650
        for (PluginMap::Iterator it = pluginMap.begin(); it != pluginMap.end(); ++it)
2187 cbradney 651
        {
10516 cbradney 652
                plugin = it.value().plugin;
3207 craig 653
                if (plugin)
654
                {
655
                        plugin->languageChange();
7176 subik 656
                        ixplug = dynamic_cast<ScActionPlugin*>(plugin);
3207 craig 657
                        if (ixplug)
658
                        {
659
                                ScActionPlugin::ActionInfo ai(ixplug->actionInfo());
7176 subik 660
                                pluginAction = ScCore->primaryMainWindow()->scrActions[ai.name];
3207 craig 661
                                if (pluginAction != 0)
10427 cbradney 662
                                        pluginAction->setText( ai.text );
18438 craig 663
//FIXME QT5 port causes disappearing menus, qt 5.1+
664
                                //if ((!ai.menu.isEmpty()) && (!ai.subMenuName.isEmpty()))
665
                                //      ScCore->primaryMainWindow()->scrMenuMgr->setText(ai.menu, ai.subMenuName);
3207 craig 666
                        }
667
                }
2187 cbradney 668
        }
669
}
3207 craig 670
 
8552 subik 671
ScPlugin* PluginManager::getPlugin(const QString & pluginName, bool includeDisabled) const
3207 craig 672
{
673
        if (DLLexists(pluginName, includeDisabled))
674
                return pluginMap[pluginName].plugin;
675
        return 0;
676
}
677
 
678
PluginManager & PluginManager::instance()
679
{
5243 cbradney 680
        return (*ScCore->pluginManager);
3207 craig 681
}
682
 
8910 jghali 683
const QString PluginManager::getPluginPath(const QString & pluginName) const
3207 craig 684
{
685
        // It is not legal to call this function without a valid
686
        // plug in name.
687
        Q_ASSERT(pluginMap.contains(pluginName));
688
        return pluginMap[pluginName].pluginFile;
689
}
690
 
8552 subik 691
bool & PluginManager::enableOnStartup(const QString & pluginName)
3207 craig 692
{
693
        // It is not legal to call this function without a valid
694
        // plug in name.
695
        Q_ASSERT(pluginMap.contains(pluginName));
696
        return pluginMap[pluginName].enableOnStartup;
697
}
698
 
8552 subik 699
bool PluginManager::enabled(const QString & pluginName)
3246 craig 700
{
701
        // It is not legal to call this function without a valid
702
        // plug in name.
703
        Q_ASSERT(pluginMap.contains(pluginName));
704
        return pluginMap[pluginName].enabled;
705
}
706
 
8552 subik 707
QStringList PluginManager::pluginNames(
3383 craig 708
                bool includeDisabled, const char* inherits) const
3207 craig 709
{
3383 craig 710
        // Scan the plugin map for plugins...
8552 subik 711
        QStringList names;
3207 craig 712
        for (PluginMap::ConstIterator it = pluginMap.constBegin(); it != pluginMap.constEnd(); ++it)
10516 cbradney 713
                if (includeDisabled || it.value().enabled)
3383 craig 714
                        // Only including plugins that inherit a named parent (if
715
                        // specified), using the QMetaObject system.
10516 cbradney 716
                        if (!inherits || it.value().plugin->inherits(inherits))
717
                                names.append(it.value().pluginName);
3207 craig 718
        return names;
719
}