Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / lib / konq / konq_copytomenu.cpp
blobd72a64d23149a5c172a5a37e364ce8d32c5ef499
1 /* This file is part of the KDE project
3 Copyright 2008 David Faure <faure@kde.org>
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as published
7 by the Free Software Foundation; either version 2 of the License or
8 ( at your option ) version 3 or, at the discretion of KDE e.V.
9 ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version.
11 This library 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 GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
22 #include "konq_copytomenu.h"
23 #include "konq_copytomenu_p.h"
24 #include "konq_operations.h"
25 #include <kaction.h>
26 #include <kdebug.h>
27 #include <kicon.h>
28 #include <kfiledialog.h>
29 #include <klocale.h>
30 #include <kmenu.h>
31 #include <kstringhandler.h>
32 #include <QDir>
34 KonqCopyToMenuPrivate::KonqCopyToMenuPrivate()
35 : m_urls(), m_readOnly(false)
39 ////
41 KonqCopyToMenu::KonqCopyToMenu()
42 : d(new KonqCopyToMenuPrivate)
47 KonqCopyToMenu::~KonqCopyToMenu()
49 delete d;
52 void KonqCopyToMenu::setItems(const KFileItemList& items)
54 // For now we lose all the information except for the urls
55 // But this API is useful in case KIO can make use of this information later
56 // (e.g. to avoid stat'ing the source urls)
57 Q_FOREACH(const KFileItem& item, items)
58 d->m_urls.append(item.url());
61 void KonqCopyToMenu::setUrls(const KUrl::List& urls)
63 d->m_urls = urls;
66 void KonqCopyToMenu::setReadOnly(bool ro)
68 d->m_readOnly = ro;
71 void KonqCopyToMenu::addActionsTo(QMenu* menu)
73 KMenu* mainCopyMenu = new KonqCopyToMainMenu(menu, d, Copy);
74 mainCopyMenu->setTitle(i18nc("@title:menu", "Copy To"));
75 mainCopyMenu->menuAction()->setObjectName("copyTo_submenu"); // for the unittest
76 menu->addMenu(mainCopyMenu);
78 if (!d->m_readOnly) {
79 KMenu* mainMoveMenu = new KonqCopyToMainMenu(menu, d, Move);
80 mainMoveMenu->setTitle(i18nc("@title:menu", "Move To"));
81 mainMoveMenu->menuAction()->setObjectName("moveTo_submenu"); // for the unittest
82 menu->addMenu(mainMoveMenu);
86 ////
88 KonqCopyToMainMenu::KonqCopyToMainMenu(QMenu* parent, KonqCopyToMenuPrivate* _d, MenuType menuType)
89 : KMenu(parent), m_menuType(menuType),
90 m_actionGroup(static_cast<QWidget *>(0)),
91 d(_d),
92 m_recentDirsGroup(KGlobal::config(), m_menuType == Copy ? "kuick-copy" : "kuick-move")
94 connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
95 connect(&m_actionGroup, SIGNAL(triggered(QAction*)), SLOT(slotTriggered(QAction*)));
98 void KonqCopyToMainMenu::slotAboutToShow()
100 clear();
101 KonqCopyToDirectoryMenu* subMenu;
102 // Home Folder
103 subMenu = new KonqCopyToDirectoryMenu(this, this, QDir::homePath());
104 subMenu->setTitle(i18nc("@title:menu", "Home Folder"));
105 subMenu->setIcon(KIcon("go-home"));
106 addMenu(subMenu);
108 // Root Folder
109 // TODO on Windows: one submenu per drive? (Or even a Drives submenu with the drives in it?)
110 subMenu = new KonqCopyToDirectoryMenu(this, this, QDir::rootPath());
111 subMenu->setTitle(i18nc("@title:menu", "Root Folder"));
112 subMenu->setIcon(KIcon("folder-red"));
113 addMenu(subMenu);
115 // Browse... action, shows a KFileDialog
116 KAction* browseAction = new KAction(i18nc("@title:menu in Copy To or Move To submenu", "Browse..."), this);
117 connect(browseAction, SIGNAL(triggered()), this, SLOT(slotBrowse()));
118 addAction(browseAction);
120 addSeparator(); // looks like Qt4 handles removing it automatically if it's last in the menu, nice.
122 // Recent Destinations
123 const QStringList recentDirs = m_recentDirsGroup.readPathEntry("Paths", QStringList());
124 Q_FOREACH(const QString& recentDir, recentDirs) {
125 const KUrl url(recentDir);
126 const QString text = KStringHandler::csqueeze(url.pathOrUrl(), 60); // shorten very long paths (#61386)
127 KAction* act = new KAction(text, this);
128 act->setData(url);
129 m_actionGroup.addAction(act);
130 addAction(act);
134 void KonqCopyToMainMenu::slotBrowse()
136 const KUrl dest = KFileDialog::getExistingDirectoryUrl(KUrl("kfiledialog:///copyto"), this);
137 if (!dest.isEmpty()) {
138 copyOrMoveTo(dest);
142 void KonqCopyToMainMenu::slotTriggered(QAction* action)
144 const KUrl url = action->data().value<KUrl>();
145 Q_ASSERT(!url.isEmpty());
146 copyOrMoveTo(url);
149 void KonqCopyToMainMenu::copyOrMoveTo(const KUrl& dest)
151 // Insert into the recent destinations list
152 QStringList recentDirs = m_recentDirsGroup.readPathEntry("Paths", QStringList());
153 const QString niceDest = dest.pathOrUrl();
154 if (!recentDirs.contains(niceDest)) { // don't change position if already there, moving stuff is bad usability
155 recentDirs.prepend(niceDest);
156 while (recentDirs.size() > 10) { // hardcoded max size
157 recentDirs.removeLast();
159 m_recentDirsGroup.writePathEntry("Paths", recentDirs);
162 // And now let's do the copy or move -- with undo/redo support.
163 KonqOperations::copy(this, m_menuType == Copy ? KonqOperations::COPY : KonqOperations::MOVE,
164 d->m_urls, dest);
167 ////
169 KonqCopyToDirectoryMenu::KonqCopyToDirectoryMenu(QMenu* parent, KonqCopyToMainMenu* mainMenu, const QString& path)
170 : KMenu(parent), m_mainMenu(mainMenu), m_path(path)
172 connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
175 void KonqCopyToDirectoryMenu::slotAboutToShow()
177 clear();
178 KAction* act = new KAction(m_mainMenu->menuType() == Copy
179 ? i18nc("@title:menu", "Copy Here")
180 : i18nc("@title:menu", "Move Here"), this);
181 act->setData(KUrl(m_path));
182 act->setEnabled(QFileInfo(m_path).isWritable());
183 m_mainMenu->actionGroup().addAction(act);
184 addAction(act);
186 addSeparator(); // looks like Qt4 handles removing it automatically if it's last in the menu, nice.
188 // List directory
189 // All we need is sub folder names, their permissions, their icon.
190 // KDirLister or KIO::listDir would fetch much more info, and would be async,
191 // and we only care about local directories so we use QDir directly.
192 QDir dir(m_path);
193 const QStringList entries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::LocaleAware);
194 KMimeType::Ptr dirMime = KMimeType::mimeType("inode/directory");
195 Q_FOREACH(const QString& subDir, entries) {
196 QString subPath = m_path;
197 if (!subPath.endsWith('/'))
198 subPath.append('/');
199 subPath += subDir;
200 KonqCopyToDirectoryMenu* subMenu = new KonqCopyToDirectoryMenu(this, m_mainMenu, subPath);
201 subMenu->setTitle(subDir);
202 const QString iconName = dirMime->iconName(KUrl(subPath));
203 subMenu->setIcon(KIcon(iconName));
204 if (QFileInfo(subPath).isSymLink()) { // I hope this isn't too slow...
205 QFont font = subMenu->menuAction()->font();
206 font.setItalic(true);
207 subMenu->menuAction()->setFont(font);
209 addMenu(subMenu);