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

« back to all changes in this revision

Viewing changes to kicker/kicker/ui/k_mnu.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 <stdlib.h>
 
25
#include <sys/types.h>
 
26
#include <unistd.h>
 
27
#include <dmctl.h>
 
28
#include <QtDBus/QtDBus>
 
29
 
 
30
#include <QDesktopWidget>
 
31
#include <QImage>
 
32
#include <QPainter>
 
33
#include <QPixmap>
 
34
#include <QPaintEvent>
 
35
#include <QResizeEvent>
 
36
#include <QHash>
 
37
#include <QMenu>
 
38
#include <QMouseEvent>
 
39
#include <QStyle>
 
40
#include <QStyleOptionFrame>
 
41
#include <kapplication.h>
 
42
#include <kactioncollection.h>
 
43
#include <kbookmarkmenu.h>
 
44
#include <kconfig.h>
 
45
#include <kdebug.h>
 
46
#include <kglobal.h>
 
47
#include <kglobalsettings.h>
 
48
#include <kiconloader.h>
 
49
#include <klocale.h>
 
50
#include <kmessagebox.h>
 
51
#include <kstandarddirs.h>
 
52
#include <kwindowsystem.h>
 
53
#include <kauthorized.h>
 
54
#include <kworkspace.h>
 
55
 
 
56
#include "utils.h"
 
57
 
 
58
#include "container_base.h"
 
59
#include "kicker.h"
 
60
#include "kickerSettings.h"
 
61
#include "konqbookmarkmanager.h"
 
62
#include "menuinfo.h"
 
63
#include "quickbrowser_mnu.h"
 
64
#include "recentapps.h"
 
65
 
 
66
#include "k_mnu.h"
 
67
#include "krunner_interface.h"
 
68
#include "screensaver_interface.h"
 
69
#include "k_mnu.moc"
 
70
 
 
71
PanelKMenu::PanelKMenu()
 
72
  : PanelServiceMenu(QString(), QString(), 0, "KMenu")
 
73
  , bookmarkMenu(0)
 
74
{
 
75
    // set the first client id to some arbitrarily large value.
 
76
    client_id = 10000;
 
77
    // Don't automatically clear the main menu.
 
78
    disableAutoClear();
 
79
    actionCollection = new KActionCollection(this);
 
80
    setWindowTitle(i18n("K Menu"));
 
81
    connect(Kicker::self(), SIGNAL(configurationChanged()),
 
82
            this, SLOT(configChanged()));
 
83
 
 
84
/* FIXME: we need a proper way to file recent app/doc usage
 
85
    DCOPClient *dcopClient = KApplication::dcopClient();
 
86
    dcopClient->connectDCOPSignal(0, "appLauncher",
 
87
        "serviceStartedByStorageId(QString,QString)",
 
88
        dcopObjId,
 
89
        "slotServiceStartedByStorageId(QString,QString)",
 
90
        false);
 
91
    */
 
92
}
 
93
 
 
94
PanelKMenu::~PanelKMenu()
 
95
{
 
96
    clearSubmenus();
 
97
    delete bookmarkMenu;
 
98
}
 
99
#if 0
 
100
void PanelKMenu::slotServiceStartedByStorageId(QString starter,
 
101
                                               QString storageId)
 
102
{
 
103
    if (starter != "kmenu")
 
104
    {
 
105
        kDebug() << "KMenu - updating recently used applications: " <<
 
106
            storageId << endl;
 
107
        KService::Ptr service = KService::serviceByStorageId(storageId);
 
108
        RecentlyLaunchedApps::self().updateRecentlyUsedApps(service);
 
109
    }
 
110
}
 
111
#endif
 
112
 
 
113
bool PanelKMenu::loadSidePixmap()
 
114
{
 
115
    if (!KickerSettings::useSidePixmap())
 
116
    {
 
117
        return false;
 
118
    }
 
119
 
 
120
    QString sideName = KickerSettings::sidePixmapName();
 
121
    QString sideTileName = KickerSettings::sideTileName();
 
122
 
 
123
    QImage image;
 
124
    image.load(KStandardDirs::locate("data", "kicker/pics/" + sideName));
 
125
 
 
126
    if (image.isNull())
 
127
    {
 
128
        kDebug(1210) << "Can't find a side pixmap";
 
129
        return false;
 
130
    }
 
131
 
 
132
    Plasma::colorize(image);
 
133
    sidePixmap = QPixmap::fromImage(image);
 
134
 
 
135
    image.load(KStandardDirs::locate("data", "kicker/pics/" + sideTileName));
 
136
 
 
137
    if (image.isNull())
 
138
    {
 
139
        kDebug(1210) << "Can't find a side tile pixmap";
 
140
        return false;
 
141
    }
 
142
 
 
143
    Plasma::colorize(image);
 
144
    sideTilePixmap = QPixmap::fromImage(image);
 
145
 
 
146
    if (sidePixmap.width() != sideTilePixmap.width())
 
147
    {
 
148
        kDebug(1210) << "Pixmaps have to be the same size";
 
149
        return false;
 
150
    }
 
151
 
 
152
    // pretile the pixmap to a height of at least 100 pixels
 
153
    if (sideTilePixmap.height() < 100)
 
154
    {
 
155
        int tiles = (int)(100 / sideTilePixmap.height()) + 1;
 
156
        QPixmap preTiledPixmap(sideTilePixmap.width(), sideTilePixmap.height() * tiles);
 
157
        QPainter p(&preTiledPixmap);
 
158
        p.drawTiledPixmap(preTiledPixmap.rect(), sideTilePixmap);
 
159
        sideTilePixmap = preTiledPixmap;
 
160
    }
 
161
 
 
162
    return true;
 
163
}
 
164
 
 
165
void PanelKMenu::paletteChanged()
 
166
{
 
167
    if (!loadSidePixmap())
 
168
    {
 
169
        sidePixmap = sideTilePixmap = QPixmap();
 
170
        setMinimumSize( sizeHint() );
 
171
    }
 
172
}
 
173
 
 
174
void PanelKMenu::initialize()
 
175
{
 
176
//    kDebug(1210) << "PanelKMenu::initialize()";
 
177
    updateRecent();
 
178
 
 
179
    if (initialized())
 
180
    {
 
181
        return;
 
182
    }
 
183
 
 
184
    if (loadSidePixmap())
 
185
    {
 
186
        // in case we've been through here before, let's disconnect
 
187
        disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
 
188
                   this, SLOT(paletteChanged()));
 
189
        connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
 
190
                this, SLOT(paletteChanged()));
 
191
    }
 
192
    else
 
193
    {
 
194
        sidePixmap = sideTilePixmap = QPixmap();
 
195
    }
 
196
 
 
197
    // add services
 
198
    PanelServiceMenu::initialize();
 
199
 
 
200
    /*
 
201
     FIXME: no more insertTitle! now what?
 
202
    if (KickerSettings::showMenuTitles())
 
203
    {
 
204
        int id;
 
205
        id = insertTitle(i18n("All Applications"), -1, 0);
 
206
        setItemEnabled( id, false );
 
207
        id = insertTitle(i18n("Actions"), -1 , -1);
 
208
        setItemEnabled( id, false );
 
209
    }
 
210
    */
 
211
 
 
212
    // create recent menu section
 
213
    createRecentMenuItems();
 
214
 
 
215
    bool need_separator = false;
 
216
 
 
217
    // insert bookmarks
 
218
    if (KickerSettings::useBookmarks() && KAuthorized::authorizeKAction("bookmarks"))
 
219
    {
 
220
        // Need to create a new popup each time, it's deleted by subMenus.clear()
 
221
        KMenu * bookmarkParent = new KMenu(this);
 
222
        bookmarkParent->setObjectName("bookmarks" );
 
223
        delete bookmarkMenu; // can't reuse old one, the popup has been deleted
 
224
        bookmarkMenu = new KBookmarkMenu( KonqBookmarkManager::self(), 0, bookmarkParent, actionCollection );
 
225
 
 
226
        insertItem(Plasma::menuIconSet("bookmark"),
 
227
                   i18n("Bookmarks"), bookmarkParent);
 
228
 
 
229
        subMenus.append(bookmarkParent);
 
230
        need_separator = true;
 
231
    }
 
232
 
 
233
    // insert quickbrowser
 
234
    if (KickerSettings::useBrowser())
 
235
    {
 
236
        PanelQuickBrowser *browserMnu = new PanelQuickBrowser(this);
 
237
        browserMnu->initialize();
 
238
 
 
239
        insertItem(Plasma::menuIconSet("kdisknav"),
 
240
                   i18n("Quick Browser"),
 
241
                   Plasma::reduceMenu(browserMnu));
 
242
        subMenus.append(browserMnu);
 
243
        need_separator = true;
 
244
    }
 
245
 
 
246
    // insert dynamic menus
 
247
    QStringList menu_ext = KickerSettings::menuExtensions();
 
248
    if (!menu_ext.isEmpty())
 
249
    {
 
250
        for (QStringList::ConstIterator it=menu_ext.begin(); it!=menu_ext.end(); ++it)
 
251
        {
 
252
            MenuInfo info(*it);
 
253
            if (!info.isValid())
 
254
               continue;
 
255
 
 
256
            KPanelMenu *menu = info.load();
 
257
            if (menu)
 
258
            {
 
259
                insertItem(Plasma::menuIconSet(info.icon()), info.name(), menu);
 
260
                dynamicSubMenus.append(menu);
 
261
                need_separator = true;
 
262
            }
 
263
        }
 
264
    }
 
265
 
 
266
    if (need_separator)
 
267
        addSeparator();
 
268
 
 
269
    // run command
 
270
    if (KAuthorized::authorizeKAction("run_command"))
 
271
    {
 
272
        insertItem(Plasma::menuIconSet("system-run"),
 
273
                   i18n("Run Command..."),
 
274
                   this,
 
275
                   SLOT( slotRunCommand()));
 
276
        addSeparator();
 
277
    }
 
278
 
 
279
    if (DM().isSwitchable() && KAuthorized::authorizeKAction("switch_user"))
 
280
    {
 
281
        sessionsMenu = new QMenu( this );
 
282
        insertItem(Plasma::menuIconSet("switchuser"),
 
283
                   i18n("Switch User"), sessionsMenu);
 
284
        connect( sessionsMenu, SIGNAL(aboutToShow()), SLOT(slotPopulateSessions()) );
 
285
        connect( sessionsMenu, SIGNAL(activated(int)), SLOT(slotSessionActivated(int)) );
 
286
    }
 
287
 
 
288
    /*
 
289
      If  the user configured ksmserver to
 
290
    */
 
291
    KConfig ksmserver("ksmserverrc", KConfig::NoGlobals);
 
292
    if (ksmserver.group("General").readEntry( "loginMode" ) == "restoreSavedSession")
 
293
    {
 
294
        insertItem(Plasma::menuIconSet("document-save"),
 
295
                   i18n("Save Session"), this, SLOT(slotSaveSession()));
 
296
    }
 
297
 
 
298
    if (KAuthorized::authorizeKAction("lock_screen"))
 
299
    {
 
300
        insertItem(Plasma::menuIconSet("system-lock-screen"),
 
301
                   i18n("Lock Session"), this, SLOT(slotLock()));
 
302
    }
 
303
 
 
304
    if (KAuthorized::authorizeKAction("logout"))
 
305
    {
 
306
        insertItem(Plasma::menuIconSet("application-exit"),
 
307
                   i18n("Log Out..."), this, SLOT(slotLogout()));
 
308
    }
 
309
 
 
310
#if 0
 
311
    // WABA: tear off handles don't work together with dynamically updated
 
312
    // menus. We can't update the menu while torn off, and we don't know
 
313
    // when it is torn off.
 
314
    if (KGlobalSettings::insertTearOffHandle())
 
315
      insertTearOffHandle();
 
316
#endif
 
317
 
 
318
    setInitialized(true);
 
319
}
 
320
 
 
321
extern int kicker_screen_number;
 
322
 
 
323
void PanelKMenu::slotLock()
 
324
{
 
325
    QString interface( "org.freedesktop.ScreenSaver" );
 
326
    org::freedesktop::ScreenSaver screenSaverInterface( interface, "/ScreenSaver", QDBusConnection::sessionBus() );
 
327
    if ( screenSaverInterface.isValid() )
 
328
        screenSaverInterface.Lock();
 
329
}
 
330
 
 
331
void PanelKMenu::slotLogout()
 
332
{
 
333
    KWorkSpace::requestShutDown();
 
334
}
 
335
 
 
336
void PanelKMenu::slotPopulateSessions()
 
337
{
 
338
    int p = 0;
 
339
    DM dm;
 
340
 
 
341
    sessionsMenu->clear();
 
342
    if (KAuthorized::authorizeKAction("start_new_session") && (p = dm.numReserve()) >= 0)
 
343
    {
 
344
        if (KAuthorized::authorizeKAction("lock_screen"))
 
345
          sessionsMenu->insertItem(/*KIcon("lockfork"),*/ i18n("Lock Current && Start New Session"), 100 );
 
346
        sessionsMenu->insertItem(KIcon("fork"), i18n("Start New Session"), 101 );
 
347
        if (!p) {
 
348
            sessionsMenu->setItemEnabled( 100, false );
 
349
            sessionsMenu->setItemEnabled( 101, false );
 
350
        }
 
351
        sessionsMenu->addSeparator();
 
352
    }
 
353
    SessList sess;
 
354
    if (dm.localSessions( sess ))
 
355
        for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
 
356
            int id = sessionsMenu->insertItem( DM::sess2Str( *it ), (*it).vt );
 
357
            if (!(*it).vt)
 
358
                sessionsMenu->setItemEnabled( id, false );
 
359
            if ((*it).self)
 
360
                sessionsMenu->setItemChecked( id, true );
 
361
        }
 
362
}
 
363
 
 
364
void PanelKMenu::slotSessionActivated( int ent )
 
365
{
 
366
    if (ent == 100)
 
367
        doNewSession( true );
 
368
    else if (ent == 101)
 
369
        doNewSession( false );
 
370
    else if (!sessionsMenu->isItemChecked( ent ))
 
371
        DM().lockSwitchVT( ent );
 
372
}
 
373
 
 
374
void PanelKMenu::doNewSession( bool lock )
 
375
{
 
376
    int result = KMessageBox::warningContinueCancel(
 
377
        kapp->desktop()->screen(kapp->desktop()->screenNumber(this)),
 
378
        i18n("<p>You have chosen to open another desktop session.<br>"
 
379
               "The current session will be hidden "
 
380
               "and a new login screen will be displayed.<br>"
 
381
               "An F-key is assigned to each session; "
 
382
               "F%1 is usually assigned to the first session, "
 
383
               "F%2 to the second session and so on. "
 
384
               "You can switch between sessions by pressing "
 
385
               "Ctrl, Alt and the appropriate F-key at the same time. "
 
386
               "Additionally, the KDE Panel and Desktop menus have "
 
387
               "actions for switching between sessions.</p>",
 
388
                            7, 8),
 
389
        i18n("Warning - New Session"),
 
390
        KGuiItem(i18n("&Start New Session"), "fork"),
 
391
        KStandardGuiItem::cancel(),
 
392
        ":confirmNewSession",
 
393
        KMessageBox::PlainCaption | KMessageBox::Notify);
 
394
 
 
395
    if (result==KMessageBox::Cancel)
 
396
        return;
 
397
 
 
398
    if (lock)
 
399
        slotLock();
 
400
 
 
401
    DM().startReserve();
 
402
}
 
403
 
 
404
void PanelKMenu::slotSaveSession()
 
405
{
 
406
    QDBusInterface ksmserver("org.kde.ksmserver", "/ksmserver", "org.kde.KSMServerInterface");
 
407
    ksmserver.call("saveCurrentSession");
 
408
}
 
409
 
 
410
void PanelKMenu::slotRunCommand()
 
411
{
 
412
    QString interface( "org.kde.krunner" );
 
413
    org::kde::krunner::Interface desktopInterface( interface, "/Interface", QDBusConnection::sessionBus() );
 
414
    desktopInterface.display();
 
415
}
 
416
 
 
417
void PanelKMenu::slotEditUserContact()
 
418
{
 
419
}
 
420
 
 
421
void PanelKMenu::setMinimumSize(const QSize & s)
 
422
{
 
423
    KPanelMenu::setMinimumSize(s.width() + sidePixmap.width(), s.height());
 
424
}
 
425
 
 
426
void PanelKMenu::setMaximumSize(const QSize & s)
 
427
{
 
428
    KPanelMenu::setMaximumSize(s.width() + sidePixmap.width(), s.height());
 
429
}
 
430
 
 
431
void PanelKMenu::setMinimumSize(int w, int h)
 
432
{
 
433
    KPanelMenu::setMinimumSize(w + sidePixmap.width(), h);
 
434
}
 
435
 
 
436
void PanelKMenu::setMaximumSize(int w, int h)
 
437
{
 
438
  KPanelMenu::setMaximumSize(w + sidePixmap.width(), h);
 
439
}
 
440
 
 
441
QRect PanelKMenu::sideImageRect()
 
442
{
 
443
    return QStyle::visualRect( layoutDirection(), rect(), QRect( frameWidth(), frameWidth(), sidePixmap.width(),
 
444
                                      height() - 2*frameWidth() ) );
 
445
}
 
446
 
 
447
void PanelKMenu::resizeEvent(QResizeEvent * e)
 
448
{
 
449
//    kDebug(1210) << "PanelKMenu::resizeEvent():";
 
450
//    kDebug(1210) << geometry().width() << ", " << geometry().height();
 
451
 
 
452
    PanelServiceMenu::resizeEvent(e);
 
453
#ifdef __GNUC__
 
454
#warning "KDE4: Qt4 doesn't seem to provide a way of doing this, will need different impl. for side image"
 
455
#endif
 
456
//    setFrameRect( QStyle::visualRect( layoutDirection(), rect(), QRect( sidePixmap.width(), 0,
 
457
//                                      width() - sidePixmap.width(), height() ) ) );
 
458
}
 
459
 
 
460
//Workaround Qt3.3.x sizing bug, by ensuring we're always wide enough.
 
461
void PanelKMenu::resize(int width, int height)
 
462
{
 
463
    width = qMax(width, maximumSize().width());
 
464
    PanelServiceMenu::resize(width, height);
 
465
}
 
466
 
 
467
QSize PanelKMenu::sizeHint() const
 
468
{
 
469
    QSize s = PanelServiceMenu::sizeHint();
 
470
//    kDebug(1210) << "PanelKMenu::sizeHint()";
 
471
//    kDebug(1210) << s.width() << ", " << s.height();
 
472
    return s;
 
473
}
 
474
 
 
475
void PanelKMenu::paintEvent(QPaintEvent * e)
 
476
{
 
477
    if (sidePixmap.isNull()) {
 
478
        PanelServiceMenu::paintEvent(e);
 
479
        return;
 
480
    }
 
481
 
 
482
    QPainter p(this);
 
483
    p.setClipRegion(e->region());
 
484
 
 
485
    QStyleOptionFrame frOpt;
 
486
    frOpt.init(this);
 
487
    frOpt.lineWidth    = frameWidth();
 
488
    frOpt.midLineWidth = 0;
 
489
    style()->drawPrimitive( QStyle::PE_FrameMenu, &frOpt, &p, this);
 
490
 
 
491
    QRect r = sideImageRect();
 
492
    r.setBottom( r.bottom() - sidePixmap.height() );
 
493
    if ( r.intersects( e->rect() ) )
 
494
    {
 
495
        p.drawTiledPixmap( r, sideTilePixmap );
 
496
    }
 
497
 
 
498
    r = sideImageRect();
 
499
    r.setTop( r.bottom() - sidePixmap.height() );
 
500
    if ( r.intersects( e->rect() ) )
 
501
    {
 
502
        QRect drawRect = r.intersect( e->rect() );
 
503
        QRect pixRect = drawRect;
 
504
        pixRect.translate( -r.left(), -r.top() );
 
505
        p.drawPixmap( drawRect.topLeft(), sidePixmap, pixRect );
 
506
    }
 
507
 
 
508
    PanelServiceMenu::paintEvent( e );
 
509
}
 
510
 
 
511
QMouseEvent PanelKMenu::translateMouseEvent( QMouseEvent* e )
 
512
{
 
513
    QRect side = sideImageRect();
 
514
 
 
515
    if ( !side.contains( e->pos() ) )
 
516
        return *e;
 
517
 
 
518
    QPoint newpos( e->pos() );
 
519
    QApplication::isRightToLeft() ?
 
520
        newpos.setX( newpos.x() - side.width() ) :
 
521
        newpos.setX( newpos.x() + side.width() );
 
522
    QPoint newglobal( e->globalPos() );
 
523
    QApplication::isRightToLeft() ?
 
524
        newglobal.setX( newpos.x() - side.width() ) :
 
525
        newglobal.setX( newpos.x() + side.width() );
 
526
 
 
527
    return QMouseEvent( e->type(), newpos, newglobal, e->button(), e->state() );
 
528
}
 
529
 
 
530
void PanelKMenu::mousePressEvent(QMouseEvent * e)
 
531
{
 
532
    QMouseEvent newEvent = translateMouseEvent(e);
 
533
    PanelServiceMenu::mousePressEvent( &newEvent );
 
534
}
 
535
 
 
536
void PanelKMenu::mouseReleaseEvent(QMouseEvent *e)
 
537
{
 
538
    QMouseEvent newEvent = translateMouseEvent(e);
 
539
    PanelServiceMenu::mouseReleaseEvent( &newEvent );
 
540
}
 
541
 
 
542
void PanelKMenu::mouseMoveEvent(QMouseEvent *e)
 
543
{
 
544
    QMouseEvent newEvent = translateMouseEvent(e);
 
545
    PanelServiceMenu::mouseMoveEvent( &newEvent );
 
546
}
 
547
 
 
548
void PanelKMenu::configChanged()
 
549
{
 
550
    RecentlyLaunchedApps::self().m_bNeedToUpdate = false;
 
551
    RecentlyLaunchedApps::self().configChanged();
 
552
    PanelServiceMenu::configChanged();
 
553
}
 
554
 
 
555
// create and fill "recent" section at first
 
556
void PanelKMenu::createRecentMenuItems()
 
557
{
 
558
    RecentlyLaunchedApps::self().init();
 
559
    RecentlyLaunchedApps::self().m_nNumMenuItems = 0;
 
560
 
 
561
    QStringList RecentApps;
 
562
    RecentlyLaunchedApps::self().getRecentApps(RecentApps);
 
563
 
 
564
    if (RecentApps.count() > 0)
 
565
    {
 
566
        bool bSeparator = KickerSettings::showMenuTitles();
 
567
        int nId = serviceMenuEndId() + 1;
 
568
        int nIndex = KickerSettings::showMenuTitles() ? 1 : 0;
 
569
 
 
570
        for (QList<QString>::iterator it =
 
571
             RecentApps.fromLast(); /*nop*/; --it)
 
572
        {
 
573
            KService::Ptr s = KService::serviceByDesktopPath(*it);
 
574
            if (!s)
 
575
            {
 
576
                RecentlyLaunchedApps::self().removeItem(*it);
 
577
            }
 
578
            else
 
579
            {
 
580
                if (bSeparator)
 
581
                {
 
582
                    bSeparator = false;
 
583
                    /*
 
584
                     FIXME: no more titles!
 
585
                    int id = insertTitle(
 
586
                        RecentlyLaunchedApps::self().caption(),
 
587
                        serviceMenuEndId(), 0);
 
588
                    setItemEnabled( id, false );
 
589
                    */
 
590
                    addSeparator();
 
591
                }
 
592
                insertMenuItem(s, nId++, nIndex);
 
593
                RecentlyLaunchedApps::self().m_nNumMenuItems++;
 
594
            }
 
595
 
 
596
            if (it == RecentApps.begin())
 
597
            {
 
598
                break;
 
599
            }
 
600
        }
 
601
 
 
602
        if (!KickerSettings::showMenuTitles())
 
603
        {
 
604
            insertSeparator(RecentlyLaunchedApps::self().m_nNumMenuItems);
 
605
        }
 
606
    }
 
607
}
 
608
 
 
609
void PanelKMenu::clearSubmenus()
 
610
{
 
611
    // we don't need to delete these on the way out since the libloader
 
612
    // handles them for us
 
613
    if (QApplication::closingDown())
 
614
    {
 
615
        return;
 
616
    }
 
617
 
 
618
    for (PopupMenuList::const_iterator it = dynamicSubMenus.constBegin();
 
619
            it != dynamicSubMenus.constEnd();
 
620
            ++it)
 
621
    {
 
622
        delete *it;
 
623
    }
 
624
    dynamicSubMenus.clear();
 
625
 
 
626
    PanelServiceMenu::clearSubmenus();
 
627
}
 
628
 
 
629
void PanelKMenu::updateRecent()
 
630
{
 
631
    if (!RecentlyLaunchedApps::self().m_bNeedToUpdate)
 
632
    {
 
633
        return;
 
634
    }
 
635
 
 
636
    RecentlyLaunchedApps::self().m_bNeedToUpdate = false;
 
637
 
 
638
    int nId = serviceMenuEndId() + 1;
 
639
 
 
640
    // remove previous items
 
641
    if (RecentlyLaunchedApps::self().m_nNumMenuItems > 0)
 
642
    {
 
643
        // -1 --> menu title
 
644
        int i = KickerSettings::showMenuTitles() ? -1 : 0;
 
645
        for (; i < RecentlyLaunchedApps::self().m_nNumMenuItems; i++)
 
646
        {
 
647
            removeItem(nId + i);
 
648
            entryMap_.remove(nId + i);
 
649
        }
 
650
        RecentlyLaunchedApps::self().m_nNumMenuItems = 0;
 
651
 
 
652
        if (!KickerSettings::showMenuTitles())
 
653
        {
 
654
            removeItemAt(0);
 
655
        }
 
656
    }
 
657
 
 
658
    // insert new items
 
659
    QStringList RecentApps;
 
660
    RecentlyLaunchedApps::self().getRecentApps(RecentApps);
 
661
 
 
662
    if (RecentApps.count() > 0)
 
663
    {
 
664
        bool bNeedSeparator = KickerSettings::showMenuTitles();
 
665
        for (QList<QString>::iterator it = RecentApps.fromLast();
 
666
             /*nop*/; --it)
 
667
        {
 
668
            KService::Ptr s = KService::serviceByDesktopPath(*it);
 
669
            if (!s)
 
670
            {
 
671
                RecentlyLaunchedApps::self().removeItem(*it);
 
672
            }
 
673
            else
 
674
            {
 
675
                if (bNeedSeparator)
 
676
                {
 
677
                    bNeedSeparator = false;
 
678
                    addSeparator();
 
679
                    /* FIXME: no more titles!
 
680
                    int id = insertTitle(
 
681
                        RecentlyLaunchedApps::self().caption(),
 
682
                        nId - 1, 0);
 
683
                    setItemEnabled( id, false );
 
684
                    */
 
685
                }
 
686
                insertMenuItem(s, nId++, KickerSettings::showMenuTitles() ?
 
687
                    1 : 0);
 
688
                RecentlyLaunchedApps::self().m_nNumMenuItems++;
 
689
            }
 
690
 
 
691
            if (it == RecentApps.begin())
 
692
                break;
 
693
        }
 
694
 
 
695
        if (!KickerSettings::showMenuTitles())
 
696
        {
 
697
            insertSeparator(RecentlyLaunchedApps::self().m_nNumMenuItems);
 
698
        }
 
699
    }
 
700
}
 
701
 
 
702
void PanelKMenu::clearRecentMenuItems()
 
703
{
 
704
    RecentlyLaunchedApps::self().clearRecentApps();
 
705
    RecentlyLaunchedApps::self().save();
 
706
    RecentlyLaunchedApps::self().m_bNeedToUpdate = true;
 
707
    updateRecent();
 
708
}
 
709
 
 
710