krpopupmenu.cpp 16.1 KB
Newer Older
Fathi Boudra's avatar
Fathi Boudra committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*****************************************************************************
 * Copyright (C) 2003 Shie Erlich <erlich@users.sourceforge.net>             *
 * Copyright (C) 2003 Rafi Yanai <yanai@users.sourceforge.net>               *
 *                                                                           *
 * This program is free software; you can redistribute it and/or modify      *
 * it under the terms of the GNU General Public License as published by      *
 * the Free Software Foundation; either version 2 of the License, or         *
 * (at your option) any later version.                                       *
 *                                                                           *
 * This package is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 * GNU General Public License for more details.                              *
 *                                                                           *
 * You should have received a copy of the GNU General Public License         *
 * along with this package; if not, write to the Free Software               *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/
19

Fathi Boudra's avatar
Fathi Boudra committed
20 21
#include "krpopupmenu.h"

22 23 24
#include <QtGui/QPixmap>

#include <KCoreAddons/KProcess>
Simon Persson's avatar
Simon Persson committed
25
#include <KI18n/KLocalizedString>
26 27 28 29 30 31
#include <KIOWidgets/KRun>
#include <KIconThemes/KIconLoader>
#include <KWidgetsAddons/KMessageBox>
#include <KService/KMimeTypeTrader>
#include <KService/KToolInvocation>
#include <KXmlGui/KActionCollection>
Fathi Boudra's avatar
Fathi Boudra committed
32

33
#include "listpanel.h"
Fathi Boudra's avatar
Fathi Boudra committed
34 35 36
#include "krview.h"
#include "krviewitem.h"
#include "panelfunc.h"
37
#include "listpanelactions.h"
38 39 40
#include "../krservices.h"
#include "../defaults.h"
#include "../MountMan/kmountman.h"
41
#include "../krusader.h"
42 43 44
#include "../krslots.h"
#include "../krusaderview.h"
#include "../panelmanager.h"
45
#include "../krtrashhandler.h"
46
#include "../VFS/krarchandler.h"
47

48 49 50 51 52 53
#ifdef __LIBKONQ__
#include <konq_popupmenu.h>
#include <konq_menuactions.h>
#include <konq_popupmenuinformation.h>
#endif

54
void KrPopupMenu::run(const QPoint &pos, KrPanel *panel)
Fathi Boudra's avatar
Fathi Boudra committed
55 56 57 58 59 60 61
{
    KrPopupMenu menu(panel);
    QAction * res = menu.exec(pos);
    int result = -1;
    if (res && res->data().canConvert<int>())
        result = res->data().toInt();
    menu.performAction(result);
62
}
63

Simon Persson's avatar
Simon Persson committed
64
KrPopupMenu::KrPopupMenu(KrPanel *thePanel, QWidget *parent) : QMenu(parent), panel(thePanel), empty(false),
65
        multipleSelections(false), actions(0), _item(0)
Fathi Boudra's avatar
Fathi Boudra committed
66
{
Rafi Yanai's avatar
Rafi Yanai committed
67
#ifdef __LIBKONQ__
Fathi Boudra's avatar
Fathi Boudra committed
68
    konqMenu = 0;
69
    konqMenuActions = 0;
Rafi Yanai's avatar
Rafi Yanai committed
70
#endif
71 72

    KrViewItemList items;
Fathi Boudra's avatar
Fathi Boudra committed
73
    panel->view->getSelectedKrViewItems(&items);
74 75 76

    for (KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it) {
        vfile *file = panel->func->files()->vfs_search(((*it)->name()));
77
        QUrl url = file->vfile_getUrl();
78 79 80
        _items.append(KFileItem(url, file->vfile_getMime(), file->vfile_getMode()));
    }

Fathi Boudra's avatar
Fathi Boudra committed
81 82 83 84 85 86 87 88 89
    if (items.empty()) {
        addCreateNewMenu();
        addSeparator();
        addEmptyMenuEntries();
        return;
    } else if (items.size() > 1) multipleSelections = true;

    QList<QString> protocols;
    for (int i = 0; i < items.size(); ++i) {
90
        protocols.append(panel->func->getVFile(items[ i ]) ->vfile_getUrl().scheme());
Fathi Boudra's avatar
Fathi Boudra committed
91 92 93 94
    }
    bool inTrash = protocols.contains("trash");
    bool trashOnly = (protocols.count() == 1) && (protocols[ 0 ] == "trash");

95
    KrViewItem *item = items.first();
Fathi Boudra's avatar
Fathi Boudra committed
96
    vfile *vf = panel->func->getVFile(item);
97
    _item = &_items.first();
Fathi Boudra's avatar
Fathi Boudra committed
98

99
    // ------------ the OPEN/BROWSE option - open preferred service
Fathi Boudra's avatar
Fathi Boudra committed
100 101 102 103 104 105 106 107 108 109 110 111
    QAction * openAct = addAction(i18n("Open/Run"));
    openAct->setData(QVariant(OPEN_ID));
    if (!multipleSelections) {   // meaningful only if one file is selected
        openAct->setIcon(item->icon());
        openAct->setText(vf->vfile_isExecutable() && !vf->vfile_isDir() ? i18n("Run") : i18n("Open"));
        // open in a new tab (if folder)
        if (vf->vfile_isDir()) {
            QAction * openTab = addAction(i18n("Open in New Tab"));
            openTab->setData(QVariant(OPEN_TAB_ID));
            openTab->setIcon(krLoader->loadIcon("tab-new", KIconLoader::Panel));
            openTab->setText(i18n("Open in New Tab"));
        }
112 113
        bool ArchivesAsDirectories = KConfigGroup(krConfig, "Archives").readEntry("ArchivesAsDirectories", _ArchivesAsDirectories);
        QUrl arcPath = panel->func->browsableArchivePath(vf->vfile_getName());
114
        if (!arcPath.isEmpty() && !(ArchivesAsDirectories && KRarcHandler::arcSupported(vf->vfile_getMime()))) {
115 116 117 118 119
            QAction *browseAct = addAction(i18n("Browse"));
            browseAct->setData(QVariant(BROWSE_ID));
            browseAct->setIcon(krLoader->loadIcon("", KIconLoader::Panel));
            browseAct->setText(i18n("Browse Archive"));
        }
Fathi Boudra's avatar
Fathi Boudra committed
120 121 122 123 124 125 126
        addSeparator();
    }

    // ------------- Preview - normal vfs only ?
    if (panel->func->files()->vfs_getType() == vfs::VFS_NORMAL) {
        // create the preview popup
        QStringList names;
127
        panel->gui->getSelectedNames(&names);
128
        preview.setUrls(panel->func->files() ->vfs_getFiles(names));
Fathi Boudra's avatar
Fathi Boudra committed
129 130 131 132 133 134 135 136 137 138 139 140
        QAction *pAct = addMenu(&preview);
        pAct->setData(QVariant(PREVIEW_ID));
        pAct->setText(i18n("Preview"));
    }

    // -------------- Open with: try to find-out which apps can open the file
    // this too, is meaningful only if one file is selected or if all the files
    // have the same mimetype !
    QString mime = panel->func->getVFile(item)->vfile_getMime();
    // check if all the list have the same mimetype
    for (int i = 1; i < items.size(); ++i) {
        if (panel->func->getVFile(items[ i ]) ->vfile_getMime() != mime) {
Fathi Boudra's avatar
Fathi Boudra committed
141
            mime.clear();
Fathi Boudra's avatar
Fathi Boudra committed
142 143 144 145 146 147
            break;
        }
    }
    if (!mime.isEmpty()) {
        offers = KMimeTypeTrader::self()->query(mime);
        for (int i = 0; i < offers.count(); ++i) {
148
            QExplicitlySharedDataPointer<KService> service = offers[i];
Fathi Boudra's avatar
Fathi Boudra committed
149 150 151 152 153 154
            if (service->isValid() && service->isApplication()) {
                openWith.addAction(krLoader->loadIcon(service->icon(), KIconLoader::Small), service->name())->setData(QVariant(SERVICE_LIST_ID + i));
            }
        }
        openWith.addSeparator();
        if (vf->vfile_isDir())
155
            openWith.addAction(krLoader->loadIcon("utilities-terminal", KIconLoader::Small), i18n("Terminal"))->setData(QVariant(OPEN_TERM_ID));
Fathi Boudra's avatar
Fathi Boudra committed
156 157 158 159 160 161 162 163
        openWith.addAction(i18n("Other..."))->setData(QVariant(CHOOSE_ID));
        QAction *owAct = addMenu(&openWith);
        owAct->setData(QVariant(OPEN_WITH_ID));
        owAct->setText(i18n("Open With"));
        addSeparator();
    }

    // --------------- user actions
164
    QAction *uAct = new UserActionPopupMenu(panel->func->files()->vfs_getFile(item->name()));
Fathi Boudra's avatar
Fathi Boudra committed
165 166 167
    addAction(uAct);
    uAct->setText(i18n("User Actions"));

168
#ifdef __LIBKONQ__
Fathi Boudra's avatar
Fathi Boudra committed
169
    // -------------- konqueror menu
170 171 172 173 174 175 176 177
    // This section adds all Konqueror/Dolphin menu items.
    // It's now updated to KDE4 and working, I've just commented it out.
    // Section below this one adds only servicemenus.

    // Append only servicemenus

    //TODO: deprecated since KDE4.3: remove these three lines
    KonqPopupMenuInformation info;
Fathi Boudra's avatar
Fathi Boudra committed
178 179
    info.setItems(_items);
    info.setParentWidget(this);
180 181 182

    konqMenuActions = new KonqMenuActions();
    //TODO: deprecated since KDE4.3: remove this line, use two commented lines
Fathi Boudra's avatar
Fathi Boudra committed
183
    konqMenuActions->setPopupMenuInfo(info);
184 185
    //konqMenuActions->setParentWidget( this );
    //konqMenuActions->setItemListProperties( _items );
Fathi Boudra's avatar
Fathi Boudra committed
186
    konqMenuActions->addActionsTo(this);
187 188

    addSeparator();
189
#endif
Fathi Boudra's avatar
Fathi Boudra committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

    // ------------- 'create new' submenu
    addCreateNewMenu();
    addSeparator();

    // ---------- COPY
    addAction(i18n("Copy..."))->setData(QVariant(COPY_ID));
    if (panel->func->files() ->vfs_isWritable()) {
        // ------- MOVE
        addAction(i18n("Move..."))->setData(QVariant(MOVE_ID));
        // ------- RENAME - only one file
        if (!multipleSelections && !inTrash)
            addAction(i18n("Rename"))->setData(QVariant(RENAME_ID));

        // -------- MOVE TO TRASH
        KConfigGroup saver(krConfig, "General");
        bool trash = saver.readEntry("Move To Trash", _MoveToTrash);
        if (trash && !inTrash)
            addAction(i18n("Move to Trash"))->setData(QVariant(TRASH_ID));
        // -------- DELETE
        addAction(i18n("Delete"))->setData(QVariant(DELETE_ID));
        // -------- SHRED - only one file
        /*      if ( panel->func->files() ->vfs_getType() == vfs::VFS_NORMAL &&
                    !vf->vfile_isDir() && !multipleSelections )
                 addAction( i18n( "Shred" ) )->setData( QVariant( SHRED_ID ) );*/
    }

    // ---------- link handling
    // create new shortcut or redirect links - only on local directories:
    if (panel->func->files() ->vfs_getType() == vfs::VFS_NORMAL) {
        addSeparator();
        linkPopup.addAction(i18n("New Symlink..."))->setData(QVariant(NEW_SYMLINK_ID));
        linkPopup.addAction(i18n("New Hardlink..."))->setData(QVariant(NEW_LINK_ID));
        if (panel->func->getVFile(item)->vfile_isSymLink())
            linkPopup.addAction(i18n("Redirect Link..."))->setData(QVariant(REDIRECT_LINK_ID));
        QAction *linkAct = addMenu(&linkPopup);
        linkAct->setData(QVariant(LINK_HANDLING_ID));
        linkAct->setText(i18n("Link Handling"));
    }
    addSeparator();

    // ---------- calculate space
    if (panel->func->files() ->vfs_getType() == vfs::VFS_NORMAL && (vf->vfile_isDir() || multipleSelections))
233
        addAction(panel->gui->actions()->actCalculate);
Fathi Boudra's avatar
Fathi Boudra committed
234 235 236

    // ---------- mount/umount/eject
    if (panel->func->files() ->vfs_getType() == vfs::VFS_NORMAL && vf->vfile_isDir() && !multipleSelections) {
237
        if (krMtMan.getStatus(panel->func->files() ->vfs_getFile(item->name()).path()) == KMountMan::MOUNTED)
Fathi Boudra's avatar
Fathi Boudra committed
238
            addAction(i18n("Unmount"))->setData(QVariant(UNMOUNT_ID));
239
        else if (krMtMan.getStatus(panel->func->files() ->vfs_getFile(item->name()).path()) == KMountMan::NOT_MOUNTED)
Fathi Boudra's avatar
Fathi Boudra committed
240
            addAction(i18n("Mount"))->setData(QVariant(MOUNT_ID));
241
        if (krMtMan.ejectable(panel->func->files() ->vfs_getFile(item->name()).path()))
Fathi Boudra's avatar
Fathi Boudra committed
242 243 244 245
            addAction(i18n("Eject"))->setData(QVariant(EJECT_ID));
    }

    // --------- send by mail
246
    if (KrServices::supportedTools().contains("MAIL") && !vf->vfile_isDir()) {
Fathi Boudra's avatar
Fathi Boudra committed
247 248 249 250 251 252
        addAction(i18n("Send by Email"))->setData(QVariant(SEND_BY_EMAIL_ID));
    }

    // --------- empty trash
    if (trashOnly) {
        addAction(i18n("Restore"))->setData(QVariant(RESTORE_TRASHED_FILE_ID));
Panagiotis Papadopoulos's avatar
Panagiotis Papadopoulos committed
253
        addAction(i18n("Empty Trash"))->setData(QVariant(EMPTY_TRASH_ID));
Fathi Boudra's avatar
Fathi Boudra committed
254 255
    }

256
#ifdef SYNCHRONIZER_ENABLED
Fathi Boudra's avatar
Fathi Boudra committed
257 258 259 260
    // --------- synchronize
    if (panel->view->numSelected()) {
        addAction(i18n("Synchronize Selected Files..."))->setData(QVariant(SYNC_SELECTED_ID));
    }
261
#endif
Fathi Boudra's avatar
Fathi Boudra committed
262 263 264 265 266 267 268 269 270 271 272

    // --------- copy/paste
    addSeparator();
    addAction(i18n("Copy to Clipboard"))->setData(QVariant(COPY_CLIP_ID));
    if (panel->func->files() ->vfs_isWritable()) {
        addAction(i18n("Cut to Clipboard"))->setData(QVariant(MOVE_CLIP_ID));
        addAction(i18n("Paste from Clipboard"))->setData(QVariant(PASTE_CLIP_ID));
    }
    addSeparator();

    // --------- properties
273
    addAction(panel->gui->actions()->actProperties);
274 275
}

Fathi Boudra's avatar
Fathi Boudra committed
276 277 278 279
KrPopupMenu::~KrPopupMenu()
{
    _items.clear();
    if (actions) delete actions;
280
#ifdef __LIBKONQ__
Fathi Boudra's avatar
Fathi Boudra committed
281
    if (konqMenu) delete konqMenu;
282
    if (konqMenuActions) delete konqMenuActions;
Fathi Boudra's avatar
Fathi Boudra committed
283
#endif
284 285
}

Fathi Boudra's avatar
Fathi Boudra committed
286 287 288
void KrPopupMenu::addEmptyMenuEntries()
{
    addAction(i18n("Paste from Clipboard"))->setData(QVariant(PASTE_CLIP_ID));
289 290
}

Fathi Boudra's avatar
Fathi Boudra committed
291 292 293
void KrPopupMenu::addCreateNewMenu()
{
    createNewPopup.addAction(krLoader->loadIcon("folder", KIconLoader::Small), i18n("Folder..."))->setData(QVariant(MKDIR_ID));
294
    createNewPopup.addAction(krLoader->loadIcon("text-plain", KIconLoader::Small), i18n("Text File..."))->setData(QVariant(NEW_TEXT_FILE_ID));
Fathi Boudra's avatar
Fathi Boudra committed
295 296 297 298 299

    QAction *newAct = addMenu(&createNewPopup);
    newAct->setData(QVariant(CREATE_NEW_ID));
    newAct->setText(i18n("Create New"));

300 301
}

Fathi Boudra's avatar
Fathi Boudra committed
302 303
void KrPopupMenu::performAction(int id)
{
304
    QList<QUrl> lst;
Fathi Boudra's avatar
Fathi Boudra committed
305 306 307 308 309 310

    switch (id) {
    case - 1 : // the user clicked outside of the menu
        return ;
    case OPEN_TAB_ID :
        // assuming only 1 file is selected (otherwise we won't get here)
311
        panel->manager()->newTab(_item->url(), panel);
Fathi Boudra's avatar
Fathi Boudra committed
312 313
        break;
    case OPEN_ID :
314 315
        foreach(KFileItem fi, _items)
            panel->func->execute(fi.name());
Fathi Boudra's avatar
Fathi Boudra committed
316
        break;
317 318 319
    case BROWSE_ID :
        panel->func->goInside(_item->url().fileName());
        break;
Fathi Boudra's avatar
Fathi Boudra committed
320 321 322 323 324 325 326
    case COPY_ID :
        panel->func->copyFiles();
        break;
    case MOVE_ID :
        panel->func->moveFiles();
        break;
    case RENAME_ID :
327
        panel->func->rename();
Fathi Boudra's avatar
Fathi Boudra committed
328 329 330 331 332 333 334 335
        break;
    case TRASH_ID :
        panel->func->deleteFiles(false);
        break;
    case DELETE_ID :
        panel->func->deleteFiles(true);
        break;
    case EJECT_ID :
336
        krMtMan.eject(_item->url().adjusted(QUrl::StripTrailingSlash).path());
Fathi Boudra's avatar
Fathi Boudra committed
337 338 339
        break;
        /*         case SHRED_ID :
                    if ( KMessageBox::warningContinueCancel( krApp,
Pino Toscano's avatar
Pino Toscano committed
340
                         i18n("<qt>Do you really want to shred <b>%1</b>? Once shred, the file is gone forever.</qt>", item->name()),
Fathi Boudra's avatar
Fathi Boudra committed
341
                         QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "Shred" ) == KMessageBox::Continue )
342
                       KShred::shred( panel->func->files() ->vfs_getFile( item->name() ).adjusted(QUrl::RemoveTrailingSlash).path() );
Fathi Boudra's avatar
Fathi Boudra committed
343 344
                  break;*/
    case OPEN_KONQ_ID :
345
        KToolInvocation::startServiceByDesktopName("konqueror", _item->url().toDisplayString(QUrl::PreferLocalFile));
Fathi Boudra's avatar
Fathi Boudra committed
346 347
        break;
    case CHOOSE_ID : // open-with dialog
348
        lst << _item->url();
349
        panel->func->displayOpenWithDialog(lst);
Fathi Boudra's avatar
Fathi Boudra committed
350 351
        break;
    case MOUNT_ID :
352
        krMtMan.mount(_item->url().adjusted(QUrl::StripTrailingSlash).path());
Fathi Boudra's avatar
Fathi Boudra committed
353 354 355 356 357 358 359 360 361 362 363 364 365
        break;
    case NEW_LINK_ID :
        panel->func->krlink(false);
        break;
    case NEW_SYMLINK_ID :
        panel->func->krlink(true);
        break;
    case REDIRECT_LINK_ID :
        panel->func->redirectLink();
        break;
    case EMPTY_TRASH_ID :
        KrTrashHandler::emptyTrash();
        break;
366 367
    case RESTORE_TRASHED_FILE_ID :
        KrTrashHandler::restoreTrashedFiles(_items.urlList());
Fathi Boudra's avatar
Fathi Boudra committed
368 369
    break;
    case UNMOUNT_ID :
370
        krMtMan.unmount(_item->url().adjusted(QUrl::StripTrailingSlash).path());
Fathi Boudra's avatar
Fathi Boudra committed
371 372 373 374 375 376 377 378 379 380 381
        break;
    case COPY_CLIP_ID :
        panel->func->copyToClipboard();
        break;
    case MOVE_CLIP_ID :
        panel->func->copyToClipboard(true);
        break;
    case PASTE_CLIP_ID :
        panel->func->pasteFromClipboard();
        break;
    case SEND_BY_EMAIL_ID : {
382
        SLOTS->sendFileByEmail(_items.urlList());
Fathi Boudra's avatar
Fathi Boudra committed
383 384 385
        break;
    }
    case MKDIR_ID :
386
        panel->func->mkdir();
Fathi Boudra's avatar
Fathi Boudra committed
387 388
        break;
    case NEW_TEXT_FILE_ID:
389
        panel->func->editNew();
Fathi Boudra's avatar
Fathi Boudra committed
390
        break;
391
#ifdef SYNCHRONIZER_ENABLED
Fathi Boudra's avatar
Fathi Boudra committed
392 393
    case SYNC_SELECTED_ID : {
        QStringList selectedNames;
394 395
        foreach(KFileItem item, _items)
            selectedNames << item.name();
396
        if (panel->otherPanel()->view->numSelected()) {
Fathi Boudra's avatar
Fathi Boudra committed
397
            KrViewItemList otherItems;
398
            panel->otherPanel()->view->getSelectedKrViewItems(&otherItems);
Fathi Boudra's avatar
Fathi Boudra committed
399 400 401 402 403

            for (KrViewItemList::Iterator it2 = otherItems.begin(); it2 != otherItems.end(); ++it2) {
                QString name = (*it2) ->name();
                if (!selectedNames.contains(name))
                    selectedNames.append(name);
404
            }
Fathi Boudra's avatar
Fathi Boudra committed
405 406 407 408
        }
        SLOTS->slotSynchronizeDirs(selectedNames);
    }
    break;
409
#endif
Fathi Boudra's avatar
Fathi Boudra committed
410 411
    case OPEN_TERM_ID : {
        QStringList args;
412 413 414
        if (!_item->isDir())
            args << _item->name();
        SLOTS->runTerminal(_item->url().path(), args);
Fathi Boudra's avatar
Fathi Boudra committed
415 416 417 418 419 420 421
    }
    break;
    }

    // check if something from the open-with-offered-services was selected
    if (id >= SERVICE_LIST_ID) {
        QStringList names;
422
        panel->gui->getSelectedNames(&names);
423
        panel->func->runService(*(offers[ id - SERVICE_LIST_ID ]),
424
                                panel->func->files()->vfs_getFiles(names));
Fathi Boudra's avatar
Fathi Boudra committed
425
    }
426 427
}