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

« back to all changes in this revision

Viewing changes to kmenuedit/treeview.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
 *   Copyright (C) 2000 Matthias Elter <elter@kde.org>
 
3
 *   Copyright (C) 2001-2002 Raffaele Sandrini <sandrini@kde.org)
 
4
 *   Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
 
5
 *
 
6
 *   This program is free software; you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU General Public License as published by
 
8
 *   the Free Software Foundation; either version 2 of the License, or
 
9
 *   (at your option) any later version.
 
10
 *
 
11
 *   This program is distributed in the hope that it will be useful,
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *   GNU General Public License for more details.
 
15
 *
 
16
 *   You should have received a copy of the GNU General Public License
 
17
 *   along with this program; if not, write to the Free Software
 
18
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include <unistd.h>
 
23
 
 
24
#include <QCursor>
 
25
#include <QDataStream>
 
26
#include <QDir>
 
27
#include <Qt3Support/Q3ColorDrag>
 
28
#include <QEvent>
 
29
#include <QFileInfo>
 
30
#include <Qt3Support/Q3Header>
 
31
#include <QPainter>
 
32
#include <QRegExp>
 
33
//Added by qt3to4:
 
34
#include <QPixmap>
 
35
#include <Q3PtrList>
 
36
#include <QFrame>
 
37
#include <QDropEvent>
 
38
#include <QMenu>
 
39
 
 
40
#include <kaction.h>
 
41
#include <kactioncollection.h>
 
42
#include <kapplication.h>
 
43
#include <kbuildsycocaprogressdialog.h>
 
44
#include <kdebug.h>
 
45
#include <kdesktopfile.h>
 
46
#include <kglobal.h>
 
47
#include <kiconloader.h>
 
48
#include <kinputdialog.h>
 
49
#include <klocale.h>
 
50
#include <kmessagebox.h>
 
51
#include <kservice.h>
 
52
#include <kservicegroup.h>
 
53
#include <kconfig.h>
 
54
#include <kstandarddirs.h>
 
55
#include <k3multipledrag.h>
 
56
#include <k3urldrag.h>
 
57
 
 
58
#include "treeview.h"
 
59
#include "treeview.moc"
 
60
#include "khotkeys.h"
 
61
#include "menufile.h"
 
62
#include "menuinfo.h"
 
63
 
 
64
#define MOVE_FOLDER 'M'
 
65
#define COPY_FOLDER 'C'
 
66
#define MOVE_FILE   'm'
 
67
#define COPY_FILE   'c'
 
68
#define COPY_SEPARATOR 'S'
 
69
 
 
70
TreeItem::TreeItem(Q3ListViewItem *parent, Q3ListViewItem *after, const QString& menuId, bool __init)
 
71
    :Q3ListViewItem(parent, after), _hidden(false), _init(__init), _layoutDirty(false), _menuId(menuId),
 
72
     m_folderInfo(0), m_entryInfo(0) {}
 
73
 
 
74
TreeItem::TreeItem(Q3ListView *parent, Q3ListViewItem *after, const QString& menuId, bool __init)
 
75
    : Q3ListViewItem(parent, after), _hidden(false), _init(__init), _layoutDirty(false), _menuId(menuId),
 
76
     m_folderInfo(0), m_entryInfo(0) {}
 
77
 
 
78
void TreeItem::setName(const QString &name)
 
79
{
 
80
    _name = name;
 
81
    update();
 
82
}
 
83
 
 
84
void TreeItem::setHidden(bool b)
 
85
{
 
86
    if (_hidden == b) return;
 
87
    _hidden = b;
 
88
    update();
 
89
}
 
90
 
 
91
void TreeItem::update()
 
92
{
 
93
    QString s = _name;
 
94
    if (_hidden)
 
95
       s += i18n(" [Hidden]");
 
96
    setText(0, s);
 
97
}
 
98
 
 
99
void TreeItem::setOpen(bool o)
 
100
{
 
101
    if (o)
 
102
       load();
 
103
 
 
104
    Q3ListViewItem::setOpen(o);
 
105
}
 
106
 
 
107
void TreeItem::load()
 
108
{
 
109
    if (m_folderInfo && !_init)
 
110
    {
 
111
       _init = true;
 
112
       TreeView *tv = static_cast<TreeView *>(listView());
 
113
       tv->fillBranch(m_folderInfo, this);
 
114
    }
 
115
}
 
116
 
 
117
void TreeItem::paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align )
 
118
{
 
119
    Q3ListViewItem::paintCell(p, cg, column, width, align);
 
120
 
 
121
    if (!m_folderInfo && !m_entryInfo)
 
122
    {
 
123
       // Draw Separator
 
124
       int h = (height() / 2) -1;
 
125
       if (isSelected())
 
126
           p->setPen( cg.color( QPalette::HighlightedText ) );
 
127
       else
 
128
           p->setPen( cg.color( QPalette::Text ) );
 
129
       p->drawLine(0, h,
 
130
                   width, h);
 
131
    }
 
132
}
 
133
 
 
134
void TreeItem::setup()
 
135
{
 
136
    Q3ListViewItem::setup();
 
137
    if (!m_folderInfo && !m_entryInfo)
 
138
       setHeight(8);
 
139
}
 
140
 
 
141
static QPixmap appIcon(const QString &iconName)
 
142
{
 
143
    QPixmap normal = KIconLoader::global()->loadIcon(iconName, K3Icon::Small, 0, K3Icon::DefaultState, QStringList(), 0L, true);
 
144
    // make sure they are not larger than 20x20
 
145
    if (normal.width() > 20 || normal.height() > 20)
 
146
    {
 
147
       QImage tmp = normal.toImage();
 
148
       tmp = tmp.scaled(20, 20, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
 
149
       normal = QPixmap::fromImage(tmp);
 
150
    }
 
151
    return normal;
 
152
}
 
153
 
 
154
 
 
155
TreeView::TreeView( bool controlCenter, KActionCollection *ac, QWidget *parent, const char *name )
 
156
    : K3ListView(parent), m_ac(ac), m_rmb(0), m_clipboard(0),
 
157
      m_clipboardFolderInfo(0), m_clipboardEntryInfo(0),
 
158
      m_controlCenter(controlCenter), m_layoutDirty(false)
 
159
{
 
160
    setObjectName(name);
 
161
        setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
 
162
    setAllColumnsShowFocus(true);
 
163
    setRootIsDecorated(true);
 
164
    setSorting(-1);
 
165
    setAcceptDrops(true);
 
166
    setDropVisualizer(true);
 
167
    setDragEnabled(true);
 
168
    setMinimumWidth(240);
 
169
 
 
170
    addColumn("");
 
171
    header()->hide();
 
172
 
 
173
    connect(this, SIGNAL(dropped(QDropEvent*, Q3ListViewItem*, Q3ListViewItem*)),
 
174
            SLOT(slotDropped(QDropEvent*, Q3ListViewItem*, Q3ListViewItem*)));
 
175
 
 
176
    connect(this, SIGNAL(clicked( Q3ListViewItem* )),
 
177
            SLOT(itemSelected( Q3ListViewItem* )));
 
178
 
 
179
    connect(this,SIGNAL(selectionChanged ( Q3ListViewItem * )),
 
180
            SLOT(itemSelected( Q3ListViewItem* )));
 
181
 
 
182
    connect(this, SIGNAL(rightButtonPressed(Q3ListViewItem*, const QPoint&, int)),
 
183
            SLOT(slotRMBPressed(Q3ListViewItem*, const QPoint&)));
 
184
 
 
185
    // connect actions
 
186
    connect(m_ac->action("newitem"), SIGNAL(activated()), SLOT(newitem()));
 
187
    connect(m_ac->action("newsubmenu"), SIGNAL(activated()), SLOT(newsubmenu()));
 
188
    if (m_ac->action("newsep"))
 
189
        connect(m_ac->action("newsep"), SIGNAL(activated()), SLOT(newsep()));
 
190
 
 
191
    m_menuFile = new MenuFile( KStandardDirs::locateLocal("xdgconf-menu", "applications-kmenuedit.menu"));
 
192
    m_rootFolder = new MenuFolderInfo;
 
193
    m_separator = new MenuSeparatorInfo;
 
194
    m_drag = 0;
 
195
 
 
196
    //  Read menu format configuration information
 
197
    KSharedConfig::Ptr pConfig = KSharedConfig::openConfig("kickerrc");
 
198
    KConfigGroup cg(pConfig, "menus");
 
199
    m_detailedMenuEntries = cg.readEntry("DetailedMenuEntries", true);
 
200
    if (m_detailedMenuEntries)
 
201
    {
 
202
        m_detailedEntriesNamesFirst = cg.readEntry("DetailedEntriesNamesFirst", false);
 
203
    }
 
204
}
 
205
 
 
206
TreeView::~TreeView() {
 
207
    cleanupClipboard();
 
208
    delete m_rootFolder;
 
209
    delete m_separator;
 
210
}
 
211
 
 
212
void TreeView::setViewMode(bool showHidden)
 
213
{
 
214
    delete m_rmb;
 
215
 
 
216
    // setup rmb menu
 
217
    m_rmb = new QMenu(this);
 
218
    QAction *action;
 
219
 
 
220
    action = m_ac->action("edit_cut");
 
221
    if(action) {
 
222
        m_rmb->addAction( action );
 
223
        action->setEnabled(false);
 
224
        connect(action, SIGNAL(activated()), SLOT(cut()));
 
225
    }
 
226
 
 
227
    action = m_ac->action("edit_copy");
 
228
    if(action) {
 
229
        m_rmb->addAction( action );
 
230
        action->setEnabled(false);
 
231
        connect(action, SIGNAL(activated()), SLOT(copy()));
 
232
    }
 
233
 
 
234
    action = m_ac->action("edit_paste");
 
235
    if(action) {
 
236
        m_rmb->addAction( action );
 
237
        action->setEnabled(false);
 
238
        connect(action, SIGNAL(activated()), SLOT(paste()));
 
239
    }
 
240
 
 
241
    m_rmb->addSeparator();
 
242
 
 
243
    action = m_ac->action("delete");
 
244
    if(action) {
 
245
        m_rmb->addAction( action );
 
246
        action->setEnabled(false);
 
247
        connect(action, SIGNAL(activated()), SLOT(del()));
 
248
    }
 
249
 
 
250
    m_rmb->addSeparator();
 
251
 
 
252
    if(m_ac->action("newitem"))
 
253
        m_rmb->addAction( m_ac->action("newitem") );
 
254
    if(m_ac->action("newsubmenu"))
 
255
        m_rmb->addAction( m_ac->action("newsubmenu") );
 
256
    if(m_ac->action("newsep"))
 
257
        m_rmb->addAction( m_ac->action("newsep") );
 
258
 
 
259
    m_showHidden = showHidden;
 
260
    readMenuFolderInfo();
 
261
    fill();
 
262
}
 
263
 
 
264
void TreeView::readMenuFolderInfo(MenuFolderInfo *folderInfo, KServiceGroup::Ptr folder, const QString &prefix)
 
265
{
 
266
    if (!folderInfo)
 
267
    {
 
268
       folderInfo = m_rootFolder;
 
269
       if (m_controlCenter)
 
270
          folder = KServiceGroup::baseGroup("settings");
 
271
       else
 
272
          folder = KServiceGroup::root();
 
273
    }
 
274
 
 
275
    if (!folder || !folder->isValid())
 
276
        return;
 
277
 
 
278
    folderInfo->caption = folder->caption();
 
279
    folderInfo->comment = folder->comment();
 
280
 
 
281
    // Item names may contain ampersands. To avoid them being converted
 
282
    // to accelerators, replace them with two ampersands.
 
283
    folderInfo->hidden = folder->noDisplay();
 
284
    folderInfo->directoryFile = folder->directoryEntryPath();
 
285
    folderInfo->icon = folder->icon();
 
286
    QString id = folder->relPath();
 
287
    int i = id.lastIndexOf('/', -2);
 
288
    id = id.mid(i+1);
 
289
    folderInfo->id = id;
 
290
    folderInfo->fullId = prefix + id;
 
291
 
 
292
    foreach(const KSycocaEntry::Ptr &e, folder->entries(true, !m_showHidden, true, m_detailedMenuEntries && !m_detailedEntriesNamesFirst))
 
293
    {
 
294
        if (e->isType(KST_KServiceGroup))
 
295
        {
 
296
            KServiceGroup::Ptr g(KServiceGroup::Ptr::staticCast(e));
 
297
            MenuFolderInfo *subFolderInfo = new MenuFolderInfo();
 
298
            readMenuFolderInfo(subFolderInfo, g, folderInfo->fullId);
 
299
            folderInfo->add(subFolderInfo, true);
 
300
        }
 
301
        else if (e->isType(KST_KService))
 
302
        {
 
303
            folderInfo->add(new MenuEntryInfo(KService::Ptr::staticCast(e)), true);
 
304
        }
 
305
        else if (e->isType(KST_KServiceSeparator))
 
306
        {
 
307
            folderInfo->add(m_separator, true);
 
308
        }
 
309
    }
 
310
}
 
311
 
 
312
void TreeView::fill()
 
313
{
 
314
    QApplication::setOverrideCursor(Qt::WaitCursor);
 
315
    clear();
 
316
    fillBranch(m_rootFolder, 0);
 
317
    QApplication::restoreOverrideCursor();
 
318
}
 
319
 
 
320
QString TreeView::findName(KDesktopFile *df, bool deleted)
 
321
{
 
322
    QString name = df->readName();
 
323
    if (deleted)
 
324
    {
 
325
       if (name == "empty")
 
326
          name.clear();
 
327
       if (name.isEmpty())
 
328
       {
 
329
          QString file = df->fileName();
 
330
          QString res = df->resource();
 
331
 
 
332
          bool isLocal = true;
 
333
          QStringList files = KGlobal::dirs()->findAllResources(res.toLatin1(), file);
 
334
          for(QStringList::ConstIterator it = files.begin();
 
335
              it != files.end();
 
336
              ++it)
 
337
          {
 
338
             if (isLocal)
 
339
             {
 
340
                isLocal = false;
 
341
                continue;
 
342
             }
 
343
 
 
344
             KDesktopFile df2(*it);
 
345
             name = df2.readName();
 
346
 
 
347
             if (!name.isEmpty() && (name != "empty"))
 
348
                return name;
 
349
          }
 
350
       }
 
351
    }
 
352
    return name;
 
353
}
 
354
 
 
355
TreeItem *TreeView::createTreeItem(TreeItem *parent, Q3ListViewItem *after, MenuFolderInfo *folderInfo, bool _init)
 
356
{
 
357
   TreeItem *item;
 
358
   if (parent == 0)
 
359
     item = new TreeItem(this, after, QString(), _init);
 
360
   else
 
361
     item = new TreeItem(parent, after, QString(), _init);
 
362
 
 
363
   item->setMenuFolderInfo(folderInfo);
 
364
   item->setName(folderInfo->caption);
 
365
   item->setPixmap(0, appIcon(folderInfo->icon));
 
366
   item->setDirectoryPath(folderInfo->fullId);
 
367
   item->setHidden(folderInfo->hidden);
 
368
   item->setExpandable(true);
 
369
   return item;
 
370
}
 
371
 
 
372
TreeItem *TreeView::createTreeItem(TreeItem *parent, Q3ListViewItem *after, MenuEntryInfo *entryInfo, bool _init)
 
373
{
 
374
   bool hidden = entryInfo->hidden;
 
375
 
 
376
   TreeItem* item;
 
377
   if (parent == 0)
 
378
     item = new TreeItem(this, after, entryInfo->menuId(), _init);
 
379
   else
 
380
     item = new TreeItem(parent, after, entryInfo->menuId(),_init);
 
381
 
 
382
   QString      name;
 
383
 
 
384
   if (m_detailedMenuEntries && entryInfo->description.length() != 0)
 
385
   {
 
386
      if (m_detailedEntriesNamesFirst)
 
387
      {
 
388
         name = entryInfo->caption + " (" + entryInfo->description + ')';
 
389
      }
 
390
      else
 
391
      {
 
392
         name = entryInfo->description + " (" + entryInfo->caption + ')';
 
393
      }
 
394
   }
 
395
   else
 
396
   {
 
397
      name = entryInfo->caption;
 
398
   }
 
399
   item->setMenuEntryInfo(entryInfo);
 
400
   item->setName(name);
 
401
   item->setPixmap(0, appIcon(entryInfo->icon));
 
402
 
 
403
   item->setHidden(hidden);
 
404
   return item;
 
405
}
 
406
 
 
407
TreeItem *TreeView::createTreeItem(TreeItem *parent, Q3ListViewItem *after, MenuSeparatorInfo *, bool _init)
 
408
{
 
409
   TreeItem* item;
 
410
   if (parent == 0)
 
411
     item = new TreeItem(this, after, QString(), _init);
 
412
   else
 
413
     item = new TreeItem(parent, after, QString(),_init);
 
414
 
 
415
   return item;
 
416
}
 
417
 
 
418
void TreeView::fillBranch(MenuFolderInfo *folderInfo, TreeItem *parent)
 
419
{
 
420
    QString relPath = parent ? parent->directory() : QString();
 
421
    Q3PtrListIterator<MenuInfo> it( folderInfo->initialLayout );
 
422
    TreeItem *after = 0;
 
423
    for (MenuInfo *info; (info = it.current()); ++it)
 
424
    {
 
425
       MenuEntryInfo *entry = dynamic_cast<MenuEntryInfo*>(info);
 
426
       if (entry)
 
427
       {
 
428
          after = createTreeItem(parent, after, entry);
 
429
          continue;
 
430
       }
 
431
 
 
432
       MenuFolderInfo *subFolder = dynamic_cast<MenuFolderInfo*>(info);
 
433
       if (subFolder)
 
434
       {
 
435
          after = createTreeItem(parent, after, subFolder);
 
436
          continue;
 
437
       }
 
438
       MenuSeparatorInfo *separator = dynamic_cast<MenuSeparatorInfo*>(info);
 
439
       if (separator)
 
440
       {
 
441
          after = createTreeItem(parent, after, separator);
 
442
          continue;
 
443
       }
 
444
    }
 
445
}
 
446
 
 
447
void TreeView::closeAllItems(Q3ListViewItem *item)
 
448
{
 
449
    if (!item) return;
 
450
    while(item)
 
451
    {
 
452
       item->setOpen(false);
 
453
       closeAllItems(item->firstChild());
 
454
       item = item->nextSibling();
 
455
    }
 
456
}
 
457
 
 
458
void TreeView::selectMenu(const QString &menu)
 
459
{
 
460
   closeAllItems(firstChild());
 
461
 
 
462
   if (menu.length() <= 1)
 
463
   {
 
464
      setCurrentItem(firstChild());
 
465
      clearSelection();
 
466
      return; // Root menu
 
467
   }
 
468
 
 
469
   QString restMenu = menu.mid(1);
 
470
   if (!restMenu.endsWith('/'))
 
471
      restMenu += '/';
 
472
 
 
473
   TreeItem *item = 0;
 
474
   do
 
475
   {
 
476
      int i = restMenu.indexOf("/");
 
477
      QString subMenu = restMenu.left(i+1);
 
478
      restMenu = restMenu.mid(i+1);
 
479
 
 
480
      item = (TreeItem*)(item ? item->firstChild() : firstChild());
 
481
      while(item)
 
482
      {
 
483
         MenuFolderInfo *folderInfo = item->folderInfo();
 
484
         if (folderInfo && (folderInfo->id == subMenu))
 
485
         {
 
486
            item->setOpen(true);
 
487
            break;
 
488
         }
 
489
         item = (TreeItem*) item->nextSibling();
 
490
      }
 
491
   }
 
492
   while( item && !restMenu.isEmpty());
 
493
 
 
494
   if (item)
 
495
   {
 
496
      setCurrentItem(item);
 
497
      ensureItemVisible(item);
 
498
   }
 
499
}
 
500
 
 
501
void TreeView::selectMenuEntry(const QString &menuEntry)
 
502
{
 
503
   TreeItem *item = (TreeItem *) selectedItem();
 
504
   if (!item)
 
505
   {
 
506
      item = (TreeItem *) currentItem();
 
507
      while (item && item->isDirectory())
 
508
          item = (TreeItem*) item->nextSibling();
 
509
   }
 
510
   else
 
511
       item = (TreeItem *) item->firstChild();
 
512
 
 
513
   while(item)
 
514
   {
 
515
      MenuEntryInfo *entry = item->entryInfo();
 
516
      if (entry && (entry->menuId() == menuEntry))
 
517
      {
 
518
         setCurrentItem(item);
 
519
         ensureItemVisible(item);
 
520
         return;
 
521
      }
 
522
      item = (TreeItem*) item->nextSibling();
 
523
   }
 
524
}
 
525
 
 
526
void TreeView::itemSelected(Q3ListViewItem *item)
 
527
{
 
528
    TreeItem *_item = (TreeItem*)item;
 
529
    bool selected = false;
 
530
    bool dselected = false;
 
531
    if (_item) {
 
532
        selected = true;
 
533
        dselected = _item->isHidden();
 
534
    }
 
535
 
 
536
    m_ac->action("edit_cut")->setEnabled(selected);
 
537
    m_ac->action("edit_copy")->setEnabled(selected);
 
538
 
 
539
    if (m_ac->action("delete"))
 
540
        m_ac->action("delete")->setEnabled(selected && !dselected);
 
541
 
 
542
    if(!item)
 
543
    {
 
544
        emit disableAction();
 
545
        return;
 
546
    }
 
547
 
 
548
    if (_item->isDirectory())
 
549
       emit entrySelected(_item->folderInfo());
 
550
    else
 
551
       emit entrySelected(_item->entryInfo());
 
552
}
 
553
 
 
554
void TreeView::currentChanged(MenuFolderInfo *folderInfo)
 
555
{
 
556
    TreeItem *item = (TreeItem*)selectedItem();
 
557
    if (item == 0) return;
 
558
    if (folderInfo == 0) return;
 
559
 
 
560
    item->setName(folderInfo->caption);
 
561
    item->setPixmap(0, appIcon(folderInfo->icon));
 
562
}
 
563
 
 
564
void TreeView::currentChanged(MenuEntryInfo *entryInfo)
 
565
{
 
566
    TreeItem *item = (TreeItem*)selectedItem();
 
567
    if (item == 0) return;
 
568
    if (entryInfo == 0) return;
 
569
 
 
570
    QString     name;
 
571
 
 
572
    if (m_detailedMenuEntries && entryInfo->description.length() != 0)
 
573
    {
 
574
        if (m_detailedEntriesNamesFirst)
 
575
         {
 
576
            name = entryInfo->caption + " (" + entryInfo->description + ')';
 
577
        }
 
578
         else
 
579
        {
 
580
            name = entryInfo->description + " (" + entryInfo->caption + ')';
 
581
        }
 
582
    }
 
583
    else
 
584
    {
 
585
        name = entryInfo->caption;
 
586
    }
 
587
    item->setName(name);
 
588
    item->setPixmap(0, appIcon(entryInfo->icon));
 
589
}
 
590
 
 
591
QStringList TreeView::fileList(const QString& rPath)
 
592
{
 
593
    QString relativePath = rPath;
 
594
 
 
595
    // truncate "/.directory"
 
596
    int pos = relativePath.lastIndexOf("/.directory");
 
597
    if (pos > 0) relativePath.truncate(pos);
 
598
 
 
599
    QStringList filelist;
 
600
 
 
601
    // loop through all resource dirs and build a file list
 
602
    QStringList resdirlist = KGlobal::dirs()->resourceDirs("apps");
 
603
    for (QStringList::ConstIterator it = resdirlist.begin(); it != resdirlist.end(); ++it)
 
604
    {
 
605
        QDir dir((*it) + '/' + relativePath);
 
606
        if(!dir.exists()) continue;
 
607
 
 
608
        dir.setFilter(QDir::Files);
 
609
        dir.setNameFilter("*.desktop;*.kdelnk");
 
610
 
 
611
        // build a list of files
 
612
        QStringList files = dir.entryList();
 
613
        for (QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
 
614
            // does not work?!
 
615
            //if (filelist.contains(*it)) continue;
 
616
 
 
617
            if (relativePath.isEmpty()) {
 
618
                filelist.removeAll(*it); // hack
 
619
                filelist.append(*it);
 
620
            }
 
621
            else {
 
622
                filelist.removeAll(relativePath + '/' + *it); //hack
 
623
                filelist.append(relativePath + '/' + *it);
 
624
            }
 
625
        }
 
626
    }
 
627
    return filelist;
 
628
}
 
629
 
 
630
QStringList TreeView::dirList(const QString& rPath)
 
631
{
 
632
    QString relativePath = rPath;
 
633
 
 
634
    // truncate "/.directory"
 
635
    int pos = relativePath.lastIndexOf("/.directory");
 
636
    if (pos > 0) relativePath.truncate(pos);
 
637
 
 
638
    QStringList dirlist;
 
639
 
 
640
    // loop through all resource dirs and build a subdir list
 
641
    QStringList resdirlist = KGlobal::dirs()->resourceDirs("apps");
 
642
    for (QStringList::ConstIterator it = resdirlist.begin(); it != resdirlist.end(); ++it)
 
643
    {
 
644
        QDir dir((*it) + '/' + relativePath);
 
645
        if(!dir.exists()) continue;
 
646
        dir.setFilter(QDir::Dirs);
 
647
 
 
648
        // build a list of subdirs
 
649
        QStringList subdirs = dir.entryList();
 
650
        for (QStringList::ConstIterator it = subdirs.begin(); it != subdirs.end(); ++it) {
 
651
            if ((*it) == "." || (*it) == "..") continue;
 
652
            // does not work?!
 
653
            // if (dirlist.contains(*it)) continue;
 
654
 
 
655
            if (relativePath.isEmpty()) {
 
656
                dirlist.removeAll(*it); //hack
 
657
                dirlist.append(*it);
 
658
            }
 
659
            else {
 
660
                dirlist.removeAll(relativePath + '/' + *it); //hack
 
661
                dirlist.append(relativePath + '/' + *it);
 
662
            }
 
663
        }
 
664
    }
 
665
    return dirlist;
 
666
}
 
667
 
 
668
bool TreeView::acceptDrag(QDropEvent* e) const
 
669
{
 
670
    if (e->provides("application/x-kmenuedit-internal") &&
 
671
           (e->source() == const_cast<TreeView *>(this)))
 
672
       return true;
 
673
    KUrl::List urls;
 
674
    if (K3URLDrag::decode(e, urls) && (urls.count() == 1) &&
 
675
        urls[0].isLocalFile() && urls[0].path().endsWith(".desktop"))
 
676
       return true;
 
677
    return false;
 
678
}
 
679
 
 
680
 
 
681
static QString createDesktopFile(const QString &file, QString *menuId, QStringList *excludeList)
 
682
{
 
683
   QString base = file.mid(file.lastIndexOf('/')+1);
 
684
   base = base.left(base.lastIndexOf('.'));
 
685
 
 
686
   QRegExp r("(.*)(?=-\\d+)");
 
687
   base = (r.indexIn(base) > -1) ? r.cap(1) : base;
 
688
 
 
689
   QString result = KService::newServicePath(true, base, menuId, excludeList);
 
690
   excludeList->append(*menuId);
 
691
   // Todo for Undo-support: Undo menuId allocation:
 
692
 
 
693
   return result;
 
694
}
 
695
 
 
696
static KDesktopFile *copyDesktopFile(MenuEntryInfo *entryInfo, QString *menuId, QStringList *excludeList)
 
697
{
 
698
   QString result = createDesktopFile(entryInfo->file(), menuId, excludeList);
 
699
   KDesktopFile *df = entryInfo->desktopFile()->copyTo(result);
 
700
   df->desktopGroup().deleteEntry("Categories"); // Don't set any categories!
 
701
 
 
702
   return df;
 
703
}
 
704
 
 
705
static QString createDirectoryFile(const QString &file, QStringList *excludeList)
 
706
{
 
707
   QString base = file.mid(file.lastIndexOf('/')+1);
 
708
   base = base.left(base.lastIndexOf('.'));
 
709
 
 
710
   QString result;
 
711
   int i = 1;
 
712
   while(true)
 
713
   {
 
714
      if (i == 1)
 
715
         result = base + ".directory";
 
716
      else
 
717
         result = base + QString("-%1.directory").arg(i);
 
718
 
 
719
      if (!excludeList->contains(result))
 
720
      {
 
721
         if (KStandardDirs::locate("xdgdata-dirs", result).isEmpty())
 
722
            break;
 
723
      }
 
724
      i++;
 
725
   }
 
726
   excludeList->append(result);
 
727
   result = KStandardDirs::locateLocal("xdgdata-dirs", result);
 
728
   return result;
 
729
}
 
730
 
 
731
 
 
732
void TreeView::slotDropped (QDropEvent * e, Q3ListViewItem *parent, Q3ListViewItem*after)
 
733
{
 
734
   if(!e) return;
 
735
 
 
736
   // get destination folder
 
737
   TreeItem *parentItem = static_cast<TreeItem*>(parent);
 
738
   QString folder = parentItem ? parentItem->directory() : QString();
 
739
   MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
740
 
 
741
   if (e->source() != this)
 
742
   {
 
743
     // External drop
 
744
     KUrl::List urls;
 
745
     if (!K3URLDrag::decode(e, urls) || (urls.count() != 1) || !urls[0].isLocalFile())
 
746
        return;
 
747
     QString path = urls[0].path();
 
748
     if (!path.endsWith(".desktop"))
 
749
        return;
 
750
 
 
751
     QString menuId;
 
752
     QString result = createDesktopFile(path, &menuId, &m_newMenuIds);
 
753
     KDesktopFile orig_df(path);
 
754
     KDesktopFile *df = orig_df.copyTo(result);
 
755
     df->desktopGroup().deleteEntry("Categories"); // Don't set any categories!
 
756
 
 
757
     KService::Ptr s(new KService(df));
 
758
     s->setMenuId(menuId);
 
759
 
 
760
     MenuEntryInfo *entryInfo = new MenuEntryInfo(s, df);
 
761
 
 
762
     QString oldCaption = entryInfo->caption;
 
763
     QString newCaption = parentFolderInfo->uniqueItemCaption(oldCaption, oldCaption);
 
764
     entryInfo->setCaption(newCaption);
 
765
 
 
766
     // Add file to menu
 
767
     // m_menuFile->addEntry(folder, menuId);
 
768
     m_menuFile->pushAction(MenuFile::ADD_ENTRY, folder, menuId);
 
769
 
 
770
     // create the TreeItem
 
771
     if(parentItem)
 
772
        parentItem->setOpen(true);
 
773
 
 
774
     // update fileInfo data
 
775
     parentFolderInfo->add(entryInfo);
 
776
 
 
777
     TreeItem *newItem = createTreeItem(parentItem, after, entryInfo, true);
 
778
 
 
779
     setSelected ( newItem, true);
 
780
     itemSelected( newItem);
 
781
 
 
782
     m_drag = 0;
 
783
     setLayoutDirty(parentItem);
 
784
     return;
 
785
   }
 
786
 
 
787
   // is there content in the clipboard?
 
788
   if (!m_drag) return;
 
789
 
 
790
   if (m_dragItem == after) return; // Nothing to do
 
791
 
 
792
   int command = m_drag;
 
793
   if (command == MOVE_FOLDER)
 
794
   {
 
795
      MenuFolderInfo *folderInfo = m_dragInfo;
 
796
      if (e->action() == QDropEvent::Copy)
 
797
      {
 
798
         // Ugh.. this is hard :)
 
799
         // * Create new .directory file
 
800
         // Add
 
801
      }
 
802
      else
 
803
      {
 
804
          TreeItem *tmpItem = static_cast<TreeItem*>(parentItem);
 
805
          while (  tmpItem )
 
806
          {
 
807
              if (  tmpItem == m_dragItem )
 
808
              {
 
809
                  m_drag = 0;
 
810
                  return;
 
811
              }
 
812
              tmpItem = static_cast<TreeItem*>(tmpItem->parent() );
 
813
          }
 
814
 
 
815
         // Remove MenuFolderInfo
 
816
         TreeItem *oldParentItem = static_cast<TreeItem*>(m_dragItem->parent());
 
817
         MenuFolderInfo *oldParentFolderInfo = oldParentItem ? oldParentItem->folderInfo() : m_rootFolder;
 
818
         oldParentFolderInfo->take(folderInfo);
 
819
 
 
820
         // Move menu
 
821
         QString oldFolder = folderInfo->fullId;
 
822
         QString folderName = folderInfo->id;
 
823
         QString newFolder = m_menuFile->uniqueMenuName(folder, folderName, parentFolderInfo->existingMenuIds());
 
824
         folderInfo->id = newFolder;
 
825
 
 
826
         // Add file to menu
 
827
         //m_menuFile->moveMenu(oldFolder, folder + newFolder);
 
828
         m_menuFile->pushAction(MenuFile::MOVE_MENU, oldFolder, folder + newFolder);
 
829
 
 
830
         // Make sure caption is unique
 
831
         QString newCaption = parentFolderInfo->uniqueMenuCaption(folderInfo->caption);
 
832
         if (newCaption != folderInfo->caption)
 
833
         {
 
834
            folderInfo->setCaption(newCaption);
 
835
         }
 
836
 
 
837
         // create the TreeItem
 
838
         if(parentItem)
 
839
           parentItem->setOpen(true);
 
840
 
 
841
         // update fileInfo data
 
842
         folderInfo->updateFullId(parentFolderInfo->fullId);
 
843
         folderInfo->setInUse(true);
 
844
         parentFolderInfo->add(folderInfo);
 
845
 
 
846
         if ((parentItem != oldParentItem) || !after)
 
847
         {
 
848
            if (oldParentItem)
 
849
               oldParentItem->takeItem(m_dragItem);
 
850
            else
 
851
               takeItem(m_dragItem);
 
852
            if (parentItem)
 
853
               parentItem->insertItem(m_dragItem);
 
854
            else
 
855
               insertItem(m_dragItem);
 
856
         }
 
857
         m_dragItem->moveItem(after);
 
858
         m_dragItem->setName(folderInfo->caption);
 
859
         m_dragItem->setDirectoryPath(folderInfo->fullId);
 
860
         setSelected(m_dragItem, true);
 
861
         itemSelected(m_dragItem);
 
862
      }
 
863
   }
 
864
   else if (command == MOVE_FILE)
 
865
   {
 
866
      MenuEntryInfo *entryInfo = m_dragItem->entryInfo();
 
867
      QString menuId = entryInfo->menuId();
 
868
 
 
869
      if (e->action() == QDropEvent::Copy)
 
870
      {
 
871
 
 
872
         // Need to copy file and then add it
 
873
         KDesktopFile *df = copyDesktopFile(entryInfo, &menuId, &m_newMenuIds); // Duplicate
 
874
//UNDO-ACTION: NEW_MENU_ID (menuId)
 
875
 
 
876
         KService::Ptr s(new KService(df));
 
877
         s->setMenuId(menuId);
 
878
 
 
879
         entryInfo = new MenuEntryInfo(s, df);
 
880
 
 
881
         QString oldCaption = entryInfo->caption;
 
882
         QString newCaption = parentFolderInfo->uniqueItemCaption(oldCaption, oldCaption);
 
883
         entryInfo->setCaption(newCaption);
 
884
      }
 
885
      else
 
886
      {
 
887
         del(m_dragItem, false);
 
888
         QString oldCaption = entryInfo->caption;
 
889
         QString newCaption = parentFolderInfo->uniqueItemCaption(oldCaption);
 
890
         entryInfo->setCaption(newCaption);
 
891
         entryInfo->setInUse(true);
 
892
      }
 
893
      // Add file to menu
 
894
      // m_menuFile->addEntry(folder, menuId);
 
895
      m_menuFile->pushAction(MenuFile::ADD_ENTRY, folder, menuId);
 
896
 
 
897
      // create the TreeItem
 
898
      if(parentItem)
 
899
         parentItem->setOpen(true);
 
900
 
 
901
      // update fileInfo data
 
902
      parentFolderInfo->add(entryInfo);
 
903
 
 
904
      TreeItem *newItem = createTreeItem(parentItem, after, entryInfo, true);
 
905
 
 
906
      setSelected ( newItem, true);
 
907
      itemSelected( newItem);
 
908
   }
 
909
   else if (command == COPY_SEPARATOR)
 
910
   {
 
911
      if (e->action() != QDropEvent::Copy)
 
912
         del(m_dragItem, false);
 
913
 
 
914
      TreeItem *newItem = createTreeItem(parentItem, after, m_separator, true);
 
915
 
 
916
      setSelected ( newItem, true);
 
917
      itemSelected( newItem);
 
918
   }
 
919
   else
 
920
   {
 
921
      // Error
 
922
   }
 
923
   m_drag = 0;
 
924
   setLayoutDirty(parentItem);
 
925
}
 
926
 
 
927
 
 
928
void TreeView::startDrag()
 
929
{
 
930
  Q3DragObject *drag = dragObject();
 
931
 
 
932
  if (!drag)
 
933
     return;
 
934
 
 
935
  drag->dragMove();
 
936
}
 
937
 
 
938
Q3DragObject *TreeView::dragObject()
 
939
{
 
940
    m_dragPath.clear();
 
941
    TreeItem *item = (TreeItem*)selectedItem();
 
942
    if(item == 0) return 0;
 
943
 
 
944
    K3MultipleDrag *drag = new K3MultipleDrag( this );
 
945
 
 
946
    if (item->isDirectory())
 
947
    {
 
948
       m_drag = MOVE_FOLDER;
 
949
       m_dragInfo = item->folderInfo();
 
950
       m_dragItem = item;
 
951
    }
 
952
    else if (item->isEntry())
 
953
    {
 
954
       m_drag = MOVE_FILE;
 
955
       m_dragInfo = 0;
 
956
       m_dragItem = item;
 
957
       QString menuId = item->menuId();
 
958
       m_dragPath = item->entryInfo()->service->desktopEntryPath();
 
959
       if (!m_dragPath.isEmpty())
 
960
          m_dragPath = KStandardDirs::locate("apps", m_dragPath);
 
961
       if (!m_dragPath.isEmpty())
 
962
       {
 
963
          KUrl url;
 
964
          url.setPath(m_dragPath);
 
965
          drag->addDragObject( new K3URLDrag(url, 0));
 
966
       }
 
967
    }
 
968
    else
 
969
    {
 
970
       m_drag = COPY_SEPARATOR;
 
971
       m_dragInfo = 0;
 
972
       m_dragItem = item;
 
973
    }
 
974
 
 
975
    drag->addDragObject( new Q3StoredDrag("application/x-kmenuedit-internal", 0));
 
976
    if ( item->pixmap(0) )
 
977
        drag->setPixmap(*item->pixmap(0));
 
978
    return drag;
 
979
}
 
980
 
 
981
void TreeView::slotRMBPressed(Q3ListViewItem*, const QPoint& p)
 
982
{
 
983
    TreeItem *item = (TreeItem*)selectedItem();
 
984
    if(item == 0) return;
 
985
 
 
986
    if(m_rmb) m_rmb->exec(p);
 
987
}
 
988
 
 
989
void TreeView::newsubmenu()
 
990
{
 
991
   TreeItem *parentItem = 0;
 
992
   TreeItem *item = (TreeItem*)selectedItem();
 
993
 
 
994
   bool ok;
 
995
   QString caption = KInputDialog::getText( i18n( "New Submenu" ),
 
996
        i18n( "Submenu name:" ), QString(), &ok, this );
 
997
 
 
998
   if (!ok) return;
 
999
 
 
1000
   QString file = caption;
 
1001
   file.replace('/', '-');
 
1002
 
 
1003
   file = createDirectoryFile(file, &m_newDirectoryList); // Create
 
1004
 
 
1005
   // get destination folder
 
1006
   QString folder;
 
1007
 
 
1008
   if(!item)
 
1009
   {
 
1010
      parentItem = 0;
 
1011
      folder.clear();
 
1012
   }
 
1013
   else if(item->isDirectory())
 
1014
   {
 
1015
      parentItem = item;
 
1016
      item = 0;
 
1017
      folder = parentItem->directory();
 
1018
   }
 
1019
   else
 
1020
   {
 
1021
      parentItem = static_cast<TreeItem*>(item->parent());
 
1022
      folder = parentItem ? parentItem->directory() : QString();
 
1023
   }
 
1024
 
 
1025
   MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
1026
   MenuFolderInfo *folderInfo = new MenuFolderInfo();
 
1027
   folderInfo->caption = parentFolderInfo->uniqueMenuCaption(caption);
 
1028
   folderInfo->id = m_menuFile->uniqueMenuName(folder, caption, parentFolderInfo->existingMenuIds());
 
1029
   folderInfo->directoryFile = file;
 
1030
   folderInfo->icon = "package";
 
1031
   folderInfo->hidden = false;
 
1032
   folderInfo->setDirty();
 
1033
 
 
1034
   KDesktopFile *df = new KDesktopFile(file);
 
1035
   KConfigGroup desktopGroup = df->desktopGroup();
 
1036
   desktopGroup.writeEntry("Name", folderInfo->caption);
 
1037
   desktopGroup.writeEntry("Icon", folderInfo->icon);
 
1038
   df->sync();
 
1039
   delete df;
 
1040
   // Add file to menu
 
1041
   // m_menuFile->addMenu(folder + folderInfo->id, file);
 
1042
   m_menuFile->pushAction(MenuFile::ADD_MENU, folder + folderInfo->id, file);
 
1043
 
 
1044
   folderInfo->fullId = parentFolderInfo->fullId + folderInfo->id;
 
1045
 
 
1046
   // create the TreeItem
 
1047
   if(parentItem)
 
1048
      parentItem->setOpen(true);
 
1049
 
 
1050
   // update fileInfo data
 
1051
   parentFolderInfo->add(folderInfo);
 
1052
 
 
1053
   TreeItem *newItem = createTreeItem(parentItem, item, folderInfo, true);
 
1054
 
 
1055
   setSelected ( newItem, true);
 
1056
   itemSelected( newItem);
 
1057
 
 
1058
   setLayoutDirty(parentItem);
 
1059
}
 
1060
 
 
1061
void TreeView::newitem()
 
1062
{
 
1063
   TreeItem *parentItem = 0;
 
1064
   TreeItem *item = (TreeItem*)selectedItem();
 
1065
 
 
1066
   bool ok;
 
1067
   QString caption = KInputDialog::getText( i18n( "New Item" ),
 
1068
        i18n( "Item name:" ), QString(), &ok, this );
 
1069
 
 
1070
   if (!ok) return;
 
1071
 
 
1072
   QString menuId;
 
1073
   QString file = caption;
 
1074
   file.replace('/', '-');
 
1075
 
 
1076
   file = createDesktopFile(file, &menuId, &m_newMenuIds); // Create
 
1077
 
 
1078
   KDesktopFile *df = new KDesktopFile(file);
 
1079
   KConfigGroup desktopGroup = df->desktopGroup();
 
1080
   desktopGroup.writeEntry("Name", caption);
 
1081
   desktopGroup.writeEntry("Type", "Application");
 
1082
 
 
1083
   // get destination folder
 
1084
   QString folder;
 
1085
 
 
1086
   if(!item)
 
1087
   {
 
1088
      parentItem = 0;
 
1089
      folder.clear();
 
1090
   }
 
1091
   else if(item->isDirectory())
 
1092
   {
 
1093
      parentItem = item;
 
1094
      item = 0;
 
1095
      folder = parentItem->directory();
 
1096
   }
 
1097
   else
 
1098
   {
 
1099
      parentItem = static_cast<TreeItem*>(item->parent());
 
1100
      folder = parentItem ? parentItem->directory() : QString();
 
1101
   }
 
1102
 
 
1103
   MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
1104
 
 
1105
   // Add file to menu
 
1106
   // m_menuFile->addEntry(folder, menuId);
 
1107
   m_menuFile->pushAction(MenuFile::ADD_ENTRY, folder, menuId);
 
1108
 
 
1109
   KService::Ptr s(new KService(df));
 
1110
   s->setMenuId(menuId);
 
1111
 
 
1112
   MenuEntryInfo *entryInfo = new MenuEntryInfo(s, df);
 
1113
 
 
1114
   // create the TreeItem
 
1115
   if(parentItem)
 
1116
      parentItem->setOpen(true);
 
1117
 
 
1118
   // update fileInfo data
 
1119
   parentFolderInfo->add(entryInfo);
 
1120
 
 
1121
   TreeItem *newItem = createTreeItem(parentItem, item, entryInfo, true);
 
1122
 
 
1123
   setSelected ( newItem, true);
 
1124
   itemSelected( newItem);
 
1125
 
 
1126
   setLayoutDirty(parentItem);
 
1127
}
 
1128
 
 
1129
void TreeView::newsep()
 
1130
{
 
1131
   TreeItem *parentItem = 0;
 
1132
   TreeItem *item = (TreeItem*)selectedItem();
 
1133
 
 
1134
   if(!item)
 
1135
   {
 
1136
      parentItem = 0;
 
1137
   }
 
1138
   else if(item->isDirectory())
 
1139
   {
 
1140
      parentItem = item;
 
1141
      item = 0;
 
1142
   }
 
1143
   else
 
1144
   {
 
1145
      parentItem = static_cast<TreeItem*>(item->parent());
 
1146
   }
 
1147
 
 
1148
   // create the TreeItem
 
1149
   if(parentItem)
 
1150
      parentItem->setOpen(true);
 
1151
 
 
1152
   TreeItem *newItem = createTreeItem(parentItem, item, m_separator, true);
 
1153
 
 
1154
   setSelected ( newItem, true);
 
1155
   itemSelected( newItem);
 
1156
 
 
1157
   setLayoutDirty(parentItem);
 
1158
}
 
1159
 
 
1160
void TreeView::cut()
 
1161
{
 
1162
    copy( true );
 
1163
 
 
1164
    m_ac->action("edit_cut")->setEnabled(false);
 
1165
    m_ac->action("edit_copy")->setEnabled(false);
 
1166
    m_ac->action("delete")->setEnabled(false);
 
1167
 
 
1168
    // Select new current item
 
1169
    setSelected( currentItem(), true );
 
1170
    // Switch the UI to show that item
 
1171
    itemSelected( selectedItem() );
 
1172
}
 
1173
 
 
1174
void TreeView::copy()
 
1175
{
 
1176
    copy( false );
 
1177
}
 
1178
 
 
1179
void TreeView::copy( bool cutting )
 
1180
{
 
1181
    TreeItem *item = (TreeItem*)selectedItem();
 
1182
 
 
1183
    // nil selected? -> nil to copy
 
1184
    if (item == 0) return;
 
1185
 
 
1186
    if (cutting)
 
1187
       setLayoutDirty((TreeItem*)item->parent());
 
1188
 
 
1189
    // clean up old stuff
 
1190
    cleanupClipboard();
 
1191
 
 
1192
    // is item a folder or a file?
 
1193
    if(item->isDirectory())
 
1194
    {
 
1195
        QString folder = item->directory();
 
1196
        if (cutting)
 
1197
        {
 
1198
           // Place in clipboard
 
1199
           m_clipboard = MOVE_FOLDER;
 
1200
           m_clipboardFolderInfo = item->folderInfo();
 
1201
 
 
1202
           del(item, false);
 
1203
        }
 
1204
        else
 
1205
        {
 
1206
           // Place in clipboard
 
1207
           m_clipboard = COPY_FOLDER;
 
1208
           m_clipboardFolderInfo = item->folderInfo();
 
1209
        }
 
1210
    }
 
1211
    else if (item->isEntry())
 
1212
    {
 
1213
        if (cutting)
 
1214
        {
 
1215
           // Place in clipboard
 
1216
           m_clipboard = MOVE_FILE;
 
1217
           m_clipboardEntryInfo = item->entryInfo();
 
1218
 
 
1219
           del(item, false);
 
1220
        }
 
1221
        else
 
1222
        {
 
1223
           // Place in clipboard
 
1224
           m_clipboard = COPY_FILE;
 
1225
           m_clipboardEntryInfo = item->entryInfo();
 
1226
        }
 
1227
    }
 
1228
    else
 
1229
    {
 
1230
        // Place in clipboard
 
1231
        m_clipboard = COPY_SEPARATOR;
 
1232
        if (cutting)
 
1233
           del(item, false);
 
1234
    }
 
1235
 
 
1236
    m_ac->action("edit_paste")->setEnabled(true);
 
1237
}
 
1238
 
 
1239
 
 
1240
void TreeView::paste()
 
1241
{
 
1242
   TreeItem *parentItem = 0;
 
1243
   TreeItem *item = (TreeItem*)selectedItem();
 
1244
 
 
1245
   // nil selected? -> nil to paste to
 
1246
   if (item == 0) return;
 
1247
 
 
1248
   // is there content in the clipboard?
 
1249
   if (!m_clipboard) return;
 
1250
 
 
1251
   // get destination folder
 
1252
   QString folder;
 
1253
 
 
1254
   if(item->isDirectory())
 
1255
   {
 
1256
      parentItem = item;
 
1257
      item = 0;
 
1258
      folder = parentItem->directory();
 
1259
   }
 
1260
   else
 
1261
   {
 
1262
      parentItem = static_cast<TreeItem*>(item->parent());
 
1263
      folder = parentItem ? parentItem->directory() : QString();
 
1264
   }
 
1265
 
 
1266
   MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
1267
   int command = m_clipboard;
 
1268
   if ((command == COPY_FOLDER) || (command == MOVE_FOLDER))
 
1269
   {
 
1270
      MenuFolderInfo *folderInfo = m_clipboardFolderInfo;
 
1271
      if (command == COPY_FOLDER)
 
1272
      {
 
1273
         // Ugh.. this is hard :)
 
1274
         // * Create new .directory file
 
1275
         // Add
 
1276
      }
 
1277
      else if (command == MOVE_FOLDER)
 
1278
      {
 
1279
         // Move menu
 
1280
         QString oldFolder = folderInfo->fullId;
 
1281
         QString folderName = folderInfo->id;
 
1282
         QString newFolder = m_menuFile->uniqueMenuName(folder, folderName, parentFolderInfo->existingMenuIds());
 
1283
         folderInfo->id = newFolder;
 
1284
 
 
1285
         // Add file to menu
 
1286
         // m_menuFile->moveMenu(oldFolder, folder + newFolder);
 
1287
         m_menuFile->pushAction(MenuFile::MOVE_MENU, oldFolder, folder + newFolder);
 
1288
 
 
1289
         // Make sure caption is unique
 
1290
         QString newCaption = parentFolderInfo->uniqueMenuCaption(folderInfo->caption);
 
1291
         if (newCaption != folderInfo->caption)
 
1292
         {
 
1293
            folderInfo->setCaption(newCaption);
 
1294
         }
 
1295
         // create the TreeItem
 
1296
         if(parentItem)
 
1297
             parentItem->setOpen(true);
 
1298
 
 
1299
         // update fileInfo data
 
1300
         folderInfo->fullId = parentFolderInfo->fullId + folderInfo->id;
 
1301
         folderInfo->setInUse(true);
 
1302
         parentFolderInfo->add(folderInfo);
 
1303
 
 
1304
         TreeItem *newItem = createTreeItem(parentItem, item, folderInfo);
 
1305
 
 
1306
         setSelected ( newItem, true);
 
1307
         itemSelected( newItem);
 
1308
      }
 
1309
 
 
1310
      m_clipboard = COPY_FOLDER; // Next one copies.
 
1311
   }
 
1312
   else if ((command == COPY_FILE) || (command == MOVE_FILE))
 
1313
   {
 
1314
      MenuEntryInfo *entryInfo = m_clipboardEntryInfo;
 
1315
      QString menuId;
 
1316
 
 
1317
      if (command == COPY_FILE)
 
1318
      {
 
1319
         // Need to copy file and then add it
 
1320
         KDesktopFile *df = copyDesktopFile(entryInfo, &menuId, &m_newMenuIds); // Duplicate
 
1321
 
 
1322
         KService::Ptr s(new KService(df));
 
1323
         s->setMenuId(menuId);
 
1324
         entryInfo = new MenuEntryInfo(s, df);
 
1325
 
 
1326
         QString oldCaption = entryInfo->caption;
 
1327
         QString newCaption = parentFolderInfo->uniqueItemCaption(oldCaption, oldCaption);
 
1328
         entryInfo->setCaption(newCaption);
 
1329
      }
 
1330
      else if (command == MOVE_FILE)
 
1331
      {
 
1332
         menuId = entryInfo->menuId();
 
1333
         m_clipboard = COPY_FILE; // Next one copies.
 
1334
 
 
1335
         QString oldCaption = entryInfo->caption;
 
1336
         QString newCaption = parentFolderInfo->uniqueItemCaption(oldCaption);
 
1337
         entryInfo->setCaption(newCaption);
 
1338
         entryInfo->setInUse(true);
 
1339
      }
 
1340
      // Add file to menu
 
1341
      // m_menuFile->addEntry(folder, menuId);
 
1342
      m_menuFile->pushAction(MenuFile::ADD_ENTRY, folder, menuId);
 
1343
 
 
1344
      // create the TreeItem
 
1345
      if(parentItem)
 
1346
         parentItem->setOpen(true);
 
1347
 
 
1348
      // update fileInfo data
 
1349
      parentFolderInfo->add(entryInfo);
 
1350
 
 
1351
      TreeItem *newItem = createTreeItem(parentItem, item, entryInfo, true);
 
1352
 
 
1353
      setSelected ( newItem, true);
 
1354
      itemSelected( newItem);
 
1355
   }
 
1356
   else
 
1357
   {
 
1358
      // create separator
 
1359
      if(parentItem)
 
1360
         parentItem->setOpen(true);
 
1361
 
 
1362
      TreeItem *newItem = createTreeItem(parentItem, item, m_separator, true);
 
1363
 
 
1364
      setSelected ( newItem, true);
 
1365
      itemSelected( newItem);
 
1366
   }
 
1367
   setLayoutDirty(parentItem);
 
1368
}
 
1369
 
 
1370
void TreeView::del()
 
1371
{
 
1372
    TreeItem *item = (TreeItem*)selectedItem();
 
1373
 
 
1374
    // nil selected? -> nil to delete
 
1375
    if (item == 0) return;
 
1376
 
 
1377
    del(item, true);
 
1378
 
 
1379
    m_ac->action("edit_cut")->setEnabled(false);
 
1380
    m_ac->action("edit_copy")->setEnabled(false);
 
1381
    m_ac->action("delete")->setEnabled(false);
 
1382
    // Select new current item
 
1383
    setSelected( currentItem(), true );
 
1384
    // Switch the UI to show that item
 
1385
    itemSelected( selectedItem() );
 
1386
}
 
1387
 
 
1388
void TreeView::del(TreeItem *item, bool deleteInfo)
 
1389
{
 
1390
    TreeItem *parentItem = static_cast<TreeItem*>(item->parent());
 
1391
    // is file a .directory or a .desktop file
 
1392
    if(item->isDirectory())
 
1393
    {
 
1394
        MenuFolderInfo *folderInfo = item->folderInfo();
 
1395
 
 
1396
        // Remove MenuFolderInfo
 
1397
        MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
1398
        parentFolderInfo->take(folderInfo);
 
1399
        folderInfo->setInUse(false);
 
1400
 
 
1401
        if (m_clipboard == COPY_FOLDER && (m_clipboardFolderInfo == folderInfo))
 
1402
        {
 
1403
           // Copy + Del == Cut
 
1404
           m_clipboard = MOVE_FOLDER; // Clipboard now owns folderInfo
 
1405
 
 
1406
        }
 
1407
        else
 
1408
        {
 
1409
           if (folderInfo->takeRecursive(m_clipboardFolderInfo))
 
1410
              m_clipboard = MOVE_FOLDER; // Clipboard now owns m_clipboardFolderInfo
 
1411
 
 
1412
           if (deleteInfo)
 
1413
              delete folderInfo; // Delete folderInfo
 
1414
        }
 
1415
 
 
1416
        // Remove from menu
 
1417
        // m_menuFile->removeMenu(item->directory());
 
1418
        m_menuFile->pushAction(MenuFile::REMOVE_MENU, item->directory(), QString());
 
1419
 
 
1420
        // Remove tree item
 
1421
        delete item;
 
1422
    }
 
1423
    else if (item->isEntry())
 
1424
    {
 
1425
        MenuEntryInfo *entryInfo = item->entryInfo();
 
1426
        QString menuId = entryInfo->menuId();
 
1427
 
 
1428
        // Remove MenuFolderInfo
 
1429
        MenuFolderInfo *parentFolderInfo = parentItem ? parentItem->folderInfo() : m_rootFolder;
 
1430
        parentFolderInfo->take(entryInfo);
 
1431
        entryInfo->setInUse(false);
 
1432
 
 
1433
        if (m_clipboard == COPY_FILE && (m_clipboardEntryInfo == entryInfo))
 
1434
        {
 
1435
           // Copy + Del == Cut
 
1436
           m_clipboard = MOVE_FILE; // Clipboard now owns entryInfo
 
1437
        }
 
1438
        else
 
1439
        {
 
1440
           if (deleteInfo)
 
1441
              delete entryInfo; // Delete entryInfo
 
1442
        }
 
1443
 
 
1444
        // Remove from menu
 
1445
        QString folder = parentItem ? parentItem->directory() : QString();
 
1446
        // m_menuFile->removeEntry(folder, menuId);
 
1447
        m_menuFile->pushAction(MenuFile::REMOVE_ENTRY, folder, menuId);
 
1448
 
 
1449
        // Remove tree item
 
1450
        delete item;
 
1451
    }
 
1452
    else
 
1453
    {
 
1454
        // Remove separator
 
1455
        delete item;
 
1456
    }
 
1457
    setLayoutDirty(parentItem);
 
1458
}
 
1459
 
 
1460
void TreeView::cleanupClipboard() {
 
1461
    if (m_clipboard == MOVE_FOLDER)
 
1462
       delete m_clipboardFolderInfo;
 
1463
    m_clipboardFolderInfo = 0;
 
1464
 
 
1465
    if (m_clipboard == MOVE_FILE)
 
1466
       delete m_clipboardEntryInfo;
 
1467
    m_clipboardEntryInfo = 0;
 
1468
 
 
1469
    m_clipboard = 0;
 
1470
}
 
1471
 
 
1472
static QStringList extractLayout(TreeItem *item)
 
1473
{
 
1474
    bool firstFolder = true;
 
1475
    bool firstEntry = true;
 
1476
    QStringList layout;
 
1477
    for(;item; item = static_cast<TreeItem*>(item->nextSibling()))
 
1478
    {
 
1479
       if (item->isDirectory())
 
1480
       {
 
1481
          if (firstFolder)
 
1482
          {
 
1483
             firstFolder = false;
 
1484
             layout << ":M"; // Add new folders here...
 
1485
          }
 
1486
          layout << (item->folderInfo()->id);
 
1487
       }
 
1488
       else if (item->isEntry())
 
1489
       {
 
1490
          if (firstEntry)
 
1491
          {
 
1492
             firstEntry = false;
 
1493
             layout << ":F"; // Add new entries here...
 
1494
          }
 
1495
          layout << (item->entryInfo()->menuId());
 
1496
       }
 
1497
       else
 
1498
       {
 
1499
          layout << ":S";
 
1500
       }
 
1501
    }
 
1502
    return layout;
 
1503
}
 
1504
 
 
1505
QStringList TreeItem::layout()
 
1506
{
 
1507
    QStringList layout = extractLayout(static_cast<TreeItem*>(firstChild()));
 
1508
    _layoutDirty = false;
 
1509
    return layout;
 
1510
}
 
1511
 
 
1512
void TreeView::saveLayout()
 
1513
{
 
1514
    if (m_layoutDirty)
 
1515
    {
 
1516
       QStringList layout = extractLayout(static_cast<TreeItem*>(firstChild()));
 
1517
       m_menuFile->setLayout(m_rootFolder->fullId, layout);
 
1518
       m_layoutDirty = false;
 
1519
    }
 
1520
 
 
1521
    Q3PtrList<Q3ListViewItem> lst;
 
1522
    Q3ListViewItemIterator it( this );
 
1523
    while ( it.current() ) {
 
1524
       TreeItem *item = static_cast<TreeItem*>(it.current());
 
1525
       if ( item->isLayoutDirty() )
 
1526
       {
 
1527
          m_menuFile->setLayout(item->folderInfo()->fullId, item->layout());
 
1528
       }
 
1529
       ++it;
 
1530
    }
 
1531
}
 
1532
 
 
1533
bool TreeView::save()
 
1534
{
 
1535
    saveLayout();
 
1536
    m_rootFolder->save(m_menuFile);
 
1537
 
 
1538
    bool success = m_menuFile->performAllActions();
 
1539
 
 
1540
    m_newMenuIds.clear();
 
1541
    m_newDirectoryList.clear();
 
1542
 
 
1543
    if (success)
 
1544
    {
 
1545
       KBuildSycocaProgressDialog::rebuildKSycoca(this);
 
1546
    }
 
1547
    else
 
1548
    {
 
1549
       KMessageBox::sorry(this, "<qt>"+i18n("Menu changes could not be saved because of the following problem:")+"<br><br>"+
 
1550
                                m_menuFile->error()+"</qt>");
 
1551
    }
 
1552
    return success;
 
1553
}
 
1554
 
 
1555
void TreeView::setLayoutDirty(TreeItem *parentItem)
 
1556
{
 
1557
    if (parentItem)
 
1558
       parentItem->setLayoutDirty();
 
1559
    else
 
1560
       m_layoutDirty = true;
 
1561
}
 
1562
 
 
1563
bool TreeView::isLayoutDirty()
 
1564
{
 
1565
    Q3PtrList<Q3ListViewItem> lst;
 
1566
    Q3ListViewItemIterator it( this );
 
1567
    while ( it.current() ) {
 
1568
       if ( static_cast<TreeItem*>(it.current())->isLayoutDirty() )
 
1569
          return true;
 
1570
       ++it;
 
1571
    }
 
1572
    return false;
 
1573
}
 
1574
 
 
1575
bool TreeView::dirty()
 
1576
{
 
1577
    return m_layoutDirty || m_rootFolder->hasDirt() || m_menuFile->dirty() || isLayoutDirty();
 
1578
}
 
1579
 
 
1580
void TreeView::findServiceShortcut(const KShortcut&cut, KService::Ptr &service)
 
1581
{
 
1582
    service = m_rootFolder->findServiceShortcut(cut);
 
1583
}
 
1584