~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to kicker/kicker/core/pluginmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************
 
2
 
 
3
Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
 
4
 
 
5
Permission is hereby granted, free of charge, to any person obtaining a copy
 
6
of this software and associated documentation files (the "Software"), to deal
 
7
in the Software without restriction, including without limitation the rights
 
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
9
copies of the Software, and to permit persons to whom the Software is
 
10
furnished to do so, subject to the following conditions:
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
******************************************************************/
 
23
 
 
24
#include <QFile>
 
25
#include <QTimer>
 
26
#include <Qt3Support/q3tl.h>
 
27
//Added by qt3to4:
 
28
#include <QMenu>
 
29
 
 
30
#include <k3staticdeleter.h>
 
31
 
 
32
#include <kapplication.h>
 
33
#include <kdebug.h>
 
34
#include <kglobal.h>
 
35
#include <klibloader.h>
 
36
#include <kpanelapplet.h>
 
37
#include <kpanelextension.h>
 
38
#include <kstandarddirs.h>
 
39
 
 
40
#include "appletinfo.h"
 
41
#include "container_applet.h"
 
42
#include "container_extension.h"
 
43
#include "panelextension.h"
 
44
#include "pluginmanager.h"
 
45
#include <kconfiggroup.h>
 
46
 
 
47
static K3StaticDeleter<PluginManager> pluginManagerDeleter;
 
48
PluginManager* PluginManager::m_self = 0;
 
49
 
 
50
PluginManager* PluginManager::self()
 
51
{
 
52
    if (!m_self)
 
53
    {
 
54
        pluginManagerDeleter.setObject(m_self, new PluginManager());
 
55
    }
 
56
 
 
57
    return m_self;
 
58
}
 
59
 
 
60
AppletInfo::List PluginManager::applets(bool sort, AppletInfo::List* list)
 
61
{
 
62
    QStringList rel;
 
63
    KGlobal::dirs()->findAllResources("applets", "*.desktop", KStandardDirs::NoDuplicates, rel);
 
64
    return plugins(rel, AppletInfo::Applet, sort, list);
 
65
}
 
66
 
 
67
AppletInfo::List PluginManager::extensions(bool sort, AppletInfo::List* list)
 
68
{
 
69
    QStringList rel;
 
70
    KGlobal::dirs()->findAllResources("extensions", "*.desktop", KStandardDirs::NoDuplicates, rel);
 
71
    return plugins(rel, AppletInfo::Extension, sort, list);
 
72
}
 
73
 
 
74
AppletInfo::List PluginManager::builtinButtons(bool sort, AppletInfo::List* list)
 
75
{
 
76
    QStringList rel;
 
77
    KGlobal::dirs()->findAllResources("builtinbuttons", "*.desktop", KStandardDirs::NoDuplicates, rel);
 
78
    return plugins(rel, AppletInfo::BuiltinButton, sort, list);
 
79
}
 
80
 
 
81
AppletInfo::List PluginManager::specialButtons(bool sort, AppletInfo::List* list)
 
82
{
 
83
    QStringList rel;
 
84
    KGlobal::dirs()->findAllResources("specialbuttons", "*.desktop", KStandardDirs::NoDuplicates, rel);
 
85
    return plugins(rel, AppletInfo::SpecialButton, sort, list);
 
86
}
 
87
 
 
88
AppletInfo::List PluginManager::plugins(const QStringList& desktopFiles,
 
89
                                        AppletInfo::AppletType type,
 
90
                                        bool sort,
 
91
                                        AppletInfo::List* list)
 
92
{
 
93
    AppletInfo::List plugins;
 
94
 
 
95
    if (list)
 
96
    {
 
97
        plugins = *list;
 
98
    }
 
99
 
 
100
    for (QStringList::ConstIterator it = desktopFiles.constBegin();
 
101
         it != desktopFiles.constEnd(); ++it)
 
102
    {
 
103
        AppletInfo info(*it, QString(), type);
 
104
 
 
105
        if (!info.isHidden())
 
106
        {
 
107
            plugins.append(info);
 
108
        }
 
109
    }
 
110
 
 
111
    if (sort)
 
112
    {
 
113
        qHeapSort(plugins.begin(), plugins.end());
 
114
    }
 
115
 
 
116
    return plugins;
 
117
}
 
118
 
 
119
PluginManager::PluginManager()
 
120
{
 
121
    KConfigGroup generalGroup(KGlobal::config(), "General");
 
122
    m_untrustedApplets = generalGroup.readEntry("UntrustedApplets", QStringList() );
 
123
    m_untrustedExtensions = generalGroup.readEntry("UntrustedExtensions", QStringList() );
 
124
}
 
125
 
 
126
PluginManager::~PluginManager()
 
127
{
 
128
    AppletInfo::Dict::const_iterator it = m_appletDict.constBegin();
 
129
    for (; it != m_appletDict.constEnd(); ++it)
 
130
    {
 
131
        disconnect(it.key(), SIGNAL(destroyed( QObject*)),
 
132
                   this, SLOT(slotPluginDestroyed(QObject*)));
 
133
        delete it.value();
 
134
    }
 
135
 
 
136
    // clear the untrusted lists
 
137
    clearUntrustedLists();
 
138
}
 
139
 
 
140
KPanelApplet* PluginManager::loadApplet(const AppletInfo& info,
 
141
                                        QWidget* parent )
 
142
{
 
143
    KLibLoader* loader = KLibLoader::self();
 
144
    KLibrary* lib = loader->library( info.library() );
 
145
 
 
146
    if (!lib)
 
147
    {
 
148
        kWarning() << "cannot open applet: " << info.library()
 
149
                    << " because of " << loader->lastErrorMessage() << endl;
 
150
        return 0;
 
151
    }
 
152
 
 
153
    KPanelApplet* (*init_ptr)(QWidget *, const QString&);
 
154
    init_ptr = (KPanelApplet* (*)(QWidget *, const QString&))lib->resolveFunction( "init" );
 
155
 
 
156
    if (!init_ptr)
 
157
    {
 
158
        kWarning() << info.library() << " is not a kicker extension!" ;
 
159
        loader->unloadLibrary( info.library() );
 
160
        return 0;
 
161
    }
 
162
 
 
163
    KPanelApplet* applet = init_ptr( parent, info.configFile() );
 
164
 
 
165
    if (applet)
 
166
    {
 
167
        m_appletDict.insert( applet, new AppletInfo( info ) );
 
168
        connect( applet, SIGNAL( destroyed( QObject* ) ),
 
169
                 SLOT( slotPluginDestroyed( QObject* ) ) );
 
170
    }
 
171
 
 
172
    return applet;
 
173
}
 
174
 
 
175
KPanelExtension* PluginManager::loadExtension(const AppletInfo& info, QWidget* parent )
 
176
{
 
177
    if (info.library() == QLatin1String("childpanel_panelextension")
 
178
        /* KDE4? || info.library() == "panel" */)
 
179
    {
 
180
        return new PanelExtension(info.configFile(), parent);
 
181
    }
 
182
 
 
183
    KLibLoader* loader = KLibLoader::self();
 
184
    KLibrary* lib = loader->library( info.library() );
 
185
 
 
186
    if( !lib ) {
 
187
        kWarning() << "cannot open extension: " << info.library()
 
188
                    << " because of " << loader->lastErrorMessage() << endl;
 
189
        return 0;
 
190
    }
 
191
 
 
192
    KPanelExtension* (*init_ptr)(QWidget *, const QString&);
 
193
    init_ptr = (KPanelExtension* (*)(QWidget *, const QString&))lib->resolveFunction( "init" );
 
194
 
 
195
    if(!init_ptr){
 
196
        kWarning() << info.library() << " is not a kicker extension!" ;
 
197
        loader->unloadLibrary( info.library() );
 
198
        return 0;
 
199
    }
 
200
 
 
201
    KPanelExtension* extension = init_ptr( parent, info.configFile() );
 
202
 
 
203
    if( extension ) {
 
204
        m_appletDict.insert( extension, new AppletInfo( info ) );
 
205
        connect( extension, SIGNAL( destroyed( QObject* ) ),
 
206
                 SLOT( slotPluginDestroyed( QObject* ) ) );
 
207
    }
 
208
 
 
209
    return extension;
 
210
}
 
211
 
 
212
bool PluginManager::hasInstance( const AppletInfo& info ) const
 
213
{
 
214
    AppletInfo::Dict::const_iterator it = m_appletDict.constBegin();
 
215
    for (; it != m_appletDict.constEnd(); ++it)
 
216
    {
 
217
        if (it.value()->library() == info.library())
 
218
        {
 
219
            return true;
 
220
        }
 
221
    }
 
222
 
 
223
    return false;
 
224
}
 
225
 
 
226
void PluginManager::slotPluginDestroyed(QObject* object)
 
227
{
 
228
    AppletInfo* info = 0;
 
229
    AppletInfo::Dict::iterator it = m_appletDict.begin();
 
230
    for (; it != m_appletDict.end(); ++it)
 
231
    {
 
232
        if (it.key() == object)
 
233
        {
 
234
            info = dynamic_cast<AppletInfo*>(it.value());
 
235
            m_appletDict.erase(it);
 
236
            break;
 
237
        }
 
238
    }
 
239
 
 
240
    if (!info)
 
241
    {
 
242
        return;
 
243
    }
 
244
 
 
245
    LibUnloader::unload(info->library());
 
246
    delete info;
 
247
 
 
248
    emit pluginDestroyed();
 
249
}
 
250
 
 
251
AppletContainer* PluginManager::createAppletContainer(
 
252
        const QString& desktopFile,
 
253
        bool isStartup,
 
254
        const QString& configFile,
 
255
        QMenu* opMenu,
 
256
        QWidget* parent,
 
257
        bool isImmutable)
 
258
{
 
259
    QString desktopPath = KGlobal::dirs()->findResource( "applets", desktopFile );
 
260
 
 
261
    if (desktopPath.isEmpty())
 
262
    {
 
263
        return 0;
 
264
    }
 
265
 
 
266
    AppletInfo info( desktopPath, configFile, AppletInfo::Applet );
 
267
 
 
268
    bool instanceFound = hasInstance(info);
 
269
    if (info.isUniqueApplet() && instanceFound)
 
270
    {
 
271
        return 0;
 
272
    }
 
273
 
 
274
    bool untrusted = m_untrustedApplets.indexOf(desktopFile) != -1;
 
275
    if (isStartup && untrusted)
 
276
    {
 
277
        // don't load extensions that bombed on us previously!
 
278
        return 0;
 
279
    }
 
280
    else if (!isStartup && !instanceFound && !untrusted)
 
281
    {
 
282
        // we haven't loaded this puppy before and we're not in the untrusted list
 
283
        m_untrustedApplets.append(desktopFile);
 
284
        KConfigGroup generalGroup(KGlobal::config(), "General");
 
285
        generalGroup.writeEntry("UntrustedApplets", m_untrustedApplets);
 
286
        generalGroup.sync();
 
287
    }
 
288
 
 
289
    AppletContainer* container = new AppletContainer(info, opMenu, isImmutable, parent);
 
290
 
 
291
    if (!container->isValid())
 
292
    {
 
293
        delete container;
 
294
        return 0;
 
295
    }
 
296
 
 
297
    return container;
 
298
}
 
299
 
 
300
ExtensionContainer* PluginManager::createExtensionContainer(const QString& desktopFile,
 
301
                                                            bool isStartup,
 
302
                                                            const QString& configFile,
 
303
                                                            const QString& extensionId)
 
304
{
 
305
    if (desktopFile.isEmpty())
 
306
    {
 
307
        return 0;
 
308
    }
 
309
 
 
310
    QString desktopPath = KGlobal::dirs()->findResource("extensions", desktopFile);
 
311
    if (desktopPath.isEmpty())
 
312
    {
 
313
        return 0;
 
314
    }
 
315
 
 
316
    AppletInfo info(desktopPath, configFile, AppletInfo::Extension);
 
317
 
 
318
    bool internal = (info.library() == "childpanel_panelextension");
 
319
    bool instance = !internal && hasInstance(info);
 
320
    if (instance && info.isUniqueApplet())
 
321
    {
 
322
        return 0;
 
323
    }
 
324
 
 
325
    if (!internal)
 
326
    {
 
327
        bool untrusted = m_untrustedExtensions.indexOf(desktopFile) != -1;
 
328
        if (isStartup && untrusted)
 
329
        {
 
330
            // don't load extensions that bombed on us previously!
 
331
            return 0;
 
332
        }
 
333
        else if (!isStartup && !instance && !untrusted)
 
334
        {
 
335
            // we don't have an instance around and we're not in the untrusted list!
 
336
            m_untrustedExtensions.append(desktopFile);
 
337
            KConfigGroup generalGroup(KGlobal::config(), "General");
 
338
            generalGroup.writeEntry("UntrustedExtensions", m_untrustedExtensions);
 
339
            generalGroup.sync();
 
340
        }
 
341
    }
 
342
 
 
343
    return new ExtensionContainer(info, extensionId);
 
344
}
 
345
 
 
346
void PluginManager::clearUntrustedLists()
 
347
{
 
348
    m_untrustedExtensions.clear();
 
349
    m_untrustedApplets.clear();
 
350
 
 
351
    KConfigGroup generalGroup(KGlobal::config(), "General");
 
352
    generalGroup.writeEntry("UntrustedApplets", m_untrustedApplets);
 
353
    generalGroup.writeEntry("UntrustedExtensions", m_untrustedExtensions);
 
354
    generalGroup.sync();
 
355
}
 
356
 
 
357
LibUnloader::LibUnloader( const QString &libName, QObject *parent )
 
358
    : QObject( parent ), _libName( libName )
 
359
{
 
360
    // NOTE: this doesn't work on kicker shutdown because the timer never gets
 
361
    //       fired.
 
362
    QTimer::singleShot( 0, this, SLOT( unload() ) );
 
363
}
 
364
 
 
365
void LibUnloader::unload( const QString &libName )
 
366
{
 
367
    (void)new LibUnloader( libName, kapp );
 
368
}
 
369
 
 
370
void LibUnloader::unload()
 
371
{
 
372
    KLibLoader::self()->unloadLibrary( _libName );
 
373
    deleteLater();
 
374
}
 
375
 
 
376
#include "pluginmanager.moc"
 
377