not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / plasma / applets / kickoff / ui / contextmenufactory.cpp
blobcd6bace5fa9e9740fa392e0a2ac89f4e3ed74b7a
1 /*
2 Copyright 2007 Robert Knight <robertknight@gmail.com>
3 Copyright 2007 Kevin Ottens <ervin@kde.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 // Own
22 #include "ui/contextmenufactory.h"
24 // Qt
25 #include <QAbstractItemView>
26 #include <QMap>
28 // KDE
29 #include <KIcon>
30 #include <KLocalizedString>
31 #include <KMenu>
32 #include <KActionCollection>
33 #include <KFileItem>
34 #include <KParts/BrowserExtension>
35 #include <KBookmarkManager>
36 #include <Solid/Device>
37 #include <Solid/StorageAccess>
38 #include <Solid/OpticalDrive>
39 #include <Solid/OpticalDisc>
40 #include <KUrl>
42 // Plasma
43 #include <Plasma/Containment>
44 #include <Plasma/Corona>
46 // Local
47 #include "core/favoritesmodel.h"
48 #include "core/models.h"
50 using namespace Kickoff;
52 class ContextMenuFactory::Private
54 public:
55 Private()
56 : applet(0) {
59 QAction *advancedActionsMenu(const QString& url) const {
60 KUrl kUrl(url);
61 KActionCollection actionCollection((QObject*)0);
62 KFileItemList items;
63 QString mimeType = KMimeType::findByUrl(kUrl, 0, false, true)->name();
64 items << KFileItem(url, mimeType, KFileItem::Unknown);
65 KParts::BrowserExtension::PopupFlags browserFlags = KParts::BrowserExtension::DefaultPopupItems;
66 if (items.first().isLocalFile()) {
67 browserFlags |= KParts::BrowserExtension::ShowProperties;
69 KParts::BrowserExtension::ActionGroupMap actionGroupMap;
70 return 0;
71 // ### TODO: remove kdebase-apps dependency
72 #if 0
73 KonqPopupMenu *menu = new KonqPopupMenu(items, kUrl, actionCollection,
74 0, 0, browserFlags,
75 0, KBookmarkManager::userBookmarksManager(), actionGroupMap);
77 if (!menu->isEmpty()) {
78 QAction *action = menu->menuAction();
79 action->setText(i18n("Advanced"));
80 action->setIcon(KIcon("list-add"));
81 return action;
82 } else {
83 delete menu;
84 return 0;
86 #endif
89 QMap<QAbstractItemView*, QList<QAction*> > viewActions;
90 Plasma::Applet *applet;
93 ContextMenuFactory::ContextMenuFactory(QObject *parent)
94 : QObject(parent)
95 , d(new Private)
99 ContextMenuFactory::~ContextMenuFactory()
101 delete d;
104 void ContextMenuFactory::showContextMenu(QAbstractItemView *view, const QPoint &pos)
106 Q_ASSERT(view);
108 const QModelIndex index = view->indexAt(pos);
109 const QString url = index.data(UrlRole).value<QString>();
111 if (url.isEmpty()) {
112 return;
115 bool isFavorite = FavoritesModel::isFavorite(url);
117 QList<QAction*> actions;
119 // add to / remove from favorites
120 QAction *favoriteAction = new QAction(this);
121 if (isFavorite) {
122 favoriteAction->setText(i18n("Remove From Favorites"));
123 favoriteAction->setIcon(KIcon("list-remove"));
124 actions << favoriteAction;
125 //exclude stuff in the leave tab
126 } else if (KUrl(url).protocol() != "leave") {
127 favoriteAction->setText(i18n("Add to Favorites"));
128 favoriteAction->setIcon(KIcon("bookmark-new"));
129 actions << favoriteAction;
133 // add to desktop
134 QAction *addToDesktopAction = new QAction(this);
136 // add to main panel
137 QAction *addToPanelAction = new QAction(this);
139 //### FIXME : icons in leave-view are not properly based on a .desktop file
140 //so you cant put them in desktop or panel
141 //### TODO : do not forget to remove (kurl.scheme() != "leave") and kurl declaration
142 //when proper action for such case will be provided
143 KUrl kurl(url);
144 if ((d->applet) && (kurl.scheme() != "leave")) {
145 Plasma::Containment *containment = d->applet->containment();
147 if (containment && containment->corona()) {
148 Plasma::Containment *desktop = containment->corona()->containmentForScreen(containment->screen());
150 if (desktop && desktop->immutability() == Plasma::Mutable) {
151 addToDesktopAction->setText(i18n("Add to Desktop"));
152 actions << addToDesktopAction;
156 if (containment && containment->immutability() == Plasma::Mutable &&
157 containment->containmentType() == Plasma::Containment::PanelContainment) {
158 addToPanelAction->setText(i18n("Add to Panel"));
159 actions << addToPanelAction;
163 // advanced item actions
164 QAction *advancedSeparator = new QAction(this);
165 advancedSeparator->setSeparator(true);
166 actions << advancedSeparator;
168 QAction *advanced = d->advancedActionsMenu(url);
169 if (advanced) {
170 actions << advanced;
173 // device actions
174 QString udi = index.data(DeviceUdiRole).toString();
175 Solid::Device device(udi);
176 Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
177 QAction *ejectAction = 0;
178 if (device.isValid() && access) {
179 ejectAction = new QAction(this);
180 if (device.is<Solid::OpticalDisc>()) {
181 ejectAction->setText(i18n("Eject"));
182 } else {
183 ejectAction->setText(i18n("Safely Remove"));
185 actions << ejectAction;
188 //return if we added just a separator so far
189 if (actions.count() < 2) {
190 return;
193 // add view specific actions
194 QAction *viewSeparator = new QAction(this);
195 viewSeparator->setSeparator(true);
196 actions << viewSeparator;
197 actions << viewActions(view);
199 // display menu
200 KMenu menu;
201 menu.addTitle(index.data(Qt::DisplayRole).value<QString>());
202 foreach(QAction* action, actions) {
203 menu.addAction(action);
206 QAction *result = menu.exec(QCursor::pos());
208 if (favoriteAction && result == favoriteAction) {
209 if (isFavorite) {
210 FavoritesModel::remove(url);
211 } else {
212 FavoritesModel::add(url);
214 } else if (ejectAction && result == ejectAction) {
215 if (device.is<Solid::OpticalDisc>()) {
216 Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
217 drive->eject();
218 } else {
219 access->teardown();
221 } else if (addToDesktopAction && result == addToDesktopAction) {
222 if (d->applet) {
223 Plasma::Containment *containment = d->applet->containment();
224 if (containment) {
225 Plasma::Corona *corona = containment->corona();
226 if (corona) {
227 Plasma::Containment *desktop = corona->containmentForScreen(containment->screen());
228 if (desktop) {
229 QVariantList args;
230 args << url;
231 desktop->addApplet("icon", args);
236 } else if (addToPanelAction && result == addToPanelAction) {
237 if (d->applet) {
238 // we assume that the panel is the same containment where the kickoff is located
239 Plasma::Containment *panel = d->applet->containment();
240 if (panel) {
241 QVariantList args;
242 args << url;
244 // move it to the middle of the panel
245 QRectF rect(panel->geometry().width() / 2, 0, 150, panel->boundingRect().height());
246 panel->addApplet("icon", args, rect);
251 delete favoriteAction;
252 delete addToDesktopAction;
253 delete addToPanelAction;
254 delete viewSeparator;
255 delete ejectAction;
257 void ContextMenuFactory::setViewActions(QAbstractItemView *view, const QList<QAction*>& actions)
259 if (actions.isEmpty()) {
260 d->viewActions.remove(view);
261 } else {
262 d->viewActions.insert(view, actions);
265 QList<QAction*> ContextMenuFactory::viewActions(QAbstractItemView *view) const
267 return d->viewActions[view];
270 void ContextMenuFactory::setApplet(Plasma::Applet *applet)
272 d->applet = applet;
275 #include "contextmenufactory.moc"