~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kmenuedit/treeview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

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