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"
28 #include <kfiledialog.h>
31 #include <kstringhandler.h>
34 KonqCopyToMenuPrivate::KonqCopyToMenuPrivate()
35 : m_urls(), m_readOnly(false)
41 KonqCopyToMenu::KonqCopyToMenu()
42 : d(new KonqCopyToMenuPrivate
)
47 KonqCopyToMenu::~KonqCopyToMenu()
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
)
66 void KonqCopyToMenu::setReadOnly(bool 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
);
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
);
88 KonqCopyToMainMenu::KonqCopyToMainMenu(QMenu
* parent
, KonqCopyToMenuPrivate
* _d
, MenuType menuType
)
89 : KMenu(parent
), m_menuType(menuType
),
90 m_actionGroup(static_cast<QWidget
*>(0)),
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()
101 KonqCopyToDirectoryMenu
* subMenu
;
103 subMenu
= new KonqCopyToDirectoryMenu(this, this, QDir::homePath());
104 subMenu
->setTitle(i18nc("@title:menu", "Home Folder"));
105 subMenu
->setIcon(KIcon("go-home"));
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"));
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);
129 m_actionGroup
.addAction(act
);
134 void KonqCopyToMainMenu::slotBrowse()
136 const KUrl dest
= KFileDialog::getExistingDirectoryUrl(KUrl("kfiledialog:///copyto"), this);
137 if (!dest
.isEmpty()) {
142 void KonqCopyToMainMenu::slotTriggered(QAction
* action
)
144 const KUrl url
= action
->data().value
<KUrl
>();
145 Q_ASSERT(!url
.isEmpty());
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
,
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()
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
);
186 addSeparator(); // looks like Qt4 handles removing it automatically if it's last in the menu, nice.
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.
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('/'))
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
);