]> cloud.milkyroute.net Git - dolphin.git/blob - src/views/dolphinviewactionhandler.cpp
Use capitalized KDE includes
[dolphin.git] / src / views / dolphinviewactionhandler.cpp
1 /***************************************************************************
2 * Copyright (C) 2008 by David Faure <faure@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "dolphinviewactionhandler.h"
21
22 #include "additionalinfoaccessor.h"
23 #include "settings/viewpropertiesdialog.h"
24 #include "views/dolphinview.h"
25 #include "views/zoomlevelinfo.h"
26 #include <konq_operations.h>
27
28 #include <KAction>
29 #include <KActionCollection>
30 #include <KActionMenu>
31 #include <KFileItemDelegate>
32 #include <KLocale>
33 #include <knewmenu.h>
34 #include <KSelectAction>
35 #include <KToggleAction>
36 #include <KRun>
37 #include <KPropertiesDialog>
38
39 DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent)
40 : QObject(parent),
41 m_actionCollection(collection),
42 m_currentView(0)
43 {
44 Q_ASSERT(m_actionCollection);
45 createActions();
46 }
47
48 void DolphinViewActionHandler::setCurrentView(DolphinView* view)
49 {
50 Q_ASSERT(view);
51
52 if (m_currentView)
53 disconnect(m_currentView, 0, this, 0);
54
55 m_currentView = view;
56
57 connect(view, SIGNAL(modeChanged()),
58 this, SLOT(updateViewActions()));
59 connect(view, SIGNAL(showPreviewChanged()),
60 this, SLOT(slotShowPreviewChanged()));
61 connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)),
62 this, SLOT(slotSortOrderChanged(Qt::SortOrder)));
63 connect(view, SIGNAL(sortFoldersFirstChanged(bool)),
64 this, SLOT(slotSortFoldersFirstChanged(bool)));
65 connect(view, SIGNAL(additionalInfoChanged()),
66 this, SLOT(slotAdditionalInfoChanged()));
67 connect(view, SIGNAL(categorizedSortingChanged()),
68 this, SLOT(slotCategorizedSortingChanged()));
69 connect(view, SIGNAL(showHiddenFilesChanged()),
70 this, SLOT(slotShowHiddenFilesChanged()));
71 connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),
72 this, SLOT(slotSortingChanged(DolphinView::Sorting)));
73 connect(view, SIGNAL(zoomLevelChanged(int)),
74 this, SLOT(slotZoomLevelChanged(int)));
75 }
76
77 DolphinView* DolphinViewActionHandler::currentView()
78 {
79 return m_currentView;
80 }
81
82 void DolphinViewActionHandler::createActions()
83 {
84 // This action doesn't appear in the GUI, it's for the shortcut only.
85 // KNewFileMenu takes care of the GUI stuff.
86 KAction* newDirAction = m_actionCollection->addAction("create_dir");
87 newDirAction->setText(i18nc("@action", "Create Folder..."));
88 newDirAction->setShortcut(Qt::Key_F10);
89 newDirAction->setIcon(KIcon("folder-new"));
90 connect(newDirAction, SIGNAL(triggered()), this, SIGNAL(createDirectory()));
91
92 // File menu
93
94 KAction* rename = m_actionCollection->addAction("rename");
95 rename->setText(i18nc("@action:inmenu File", "Rename..."));
96 rename->setShortcut(Qt::Key_F2);
97 rename->setIcon(KIcon("edit-rename"));
98 connect(rename, SIGNAL(triggered()), this, SLOT(slotRename()));
99
100 KAction* moveToTrash = m_actionCollection->addAction("move_to_trash");
101 moveToTrash->setText(i18nc("@action:inmenu File", "Move to Trash"));
102 moveToTrash->setIcon(KIcon("user-trash"));
103 moveToTrash->setShortcut(QKeySequence::Delete);
104 connect(moveToTrash, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)),
105 this, SLOT(slotTrashActivated(Qt::MouseButtons, Qt::KeyboardModifiers)));
106
107 KAction* deleteAction = m_actionCollection->addAction("delete");
108 deleteAction->setIcon(KIcon("edit-delete"));
109 deleteAction->setText(i18nc("@action:inmenu File", "Delete"));
110 deleteAction->setShortcut(Qt::SHIFT | Qt::Key_Delete);
111 connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDeleteItems()));
112
113 // This action is useful for being enabled when "move_to_trash" should be
114 // disabled and "delete" is enabled (e.g. non-local files), so that Key_Del
115 // can be used for deleting the file (#76016). It needs to be a separate action
116 // so that the Edit menu isn't affected.
117 KAction* deleteWithTrashShortcut = m_actionCollection->addAction("delete_shortcut");
118 // The descriptive text is just for the shortcuts editor.
119 deleteWithTrashShortcut->setText(i18nc("@action \"Move to Trash\" for non-local files, etc.", "Delete (using shortcut for Trash)"));
120 deleteWithTrashShortcut->setShortcut(QKeySequence::Delete);
121 deleteWithTrashShortcut->setEnabled(false);
122 connect(deleteWithTrashShortcut, SIGNAL(triggered()), this, SLOT(slotDeleteItems()));
123
124 KAction *propertiesAction = m_actionCollection->addAction( "properties" );
125 // Well, it's the File menu in dolphinmainwindow and the Edit menu in dolphinpart... :)
126 propertiesAction->setText( i18nc("@action:inmenu File", "Properties") );
127 propertiesAction->setIcon(KIcon("document-properties"));
128 propertiesAction->setShortcut(Qt::ALT | Qt::Key_Return);
129 connect(propertiesAction, SIGNAL(triggered()), SLOT(slotProperties()));
130
131 // View menu
132 KToggleAction* iconsAction = iconsModeAction();
133 KToggleAction* detailsAction = detailsModeAction();
134 KToggleAction* columnsAction = columnsModeAction();
135
136 KSelectAction* viewModeActions = m_actionCollection->add<KSelectAction>("view_mode");
137 viewModeActions->setText(i18nc("@action:intoolbar", "View Mode"));
138 viewModeActions->addAction(iconsAction);
139 viewModeActions->addAction(detailsAction);
140 viewModeActions->addAction(columnsAction);
141 viewModeActions->setToolBarMode(KSelectAction::MenuMode);
142 connect(viewModeActions, SIGNAL(triggered(QAction*)), this, SLOT(slotViewModeActionTriggered(QAction*)));
143
144 KStandardAction::zoomIn(this,
145 SLOT(zoomIn()),
146 m_actionCollection);
147
148 KStandardAction::zoomOut(this,
149 SLOT(zoomOut()),
150 m_actionCollection);
151
152 KToggleAction* showPreview = m_actionCollection->add<KToggleAction>("show_preview");
153 showPreview->setText(i18nc("@action:intoolbar", "Preview"));
154 showPreview->setToolTip(i18nc("@info", "Show preview of files and folders"));
155 showPreview->setIcon(KIcon("view-preview"));
156 connect(showPreview, SIGNAL(triggered(bool)), this, SLOT(togglePreview(bool)));
157
158 KToggleAction* sortDescending = m_actionCollection->add<KToggleAction>("descending");
159 sortDescending->setText(i18nc("@action:inmenu Sort", "Descending"));
160 connect(sortDescending, SIGNAL(triggered()), this, SLOT(toggleSortOrder()));
161
162 KToggleAction* sortFoldersFirst = m_actionCollection->add<KToggleAction>("folders_first");
163 sortFoldersFirst->setText(i18nc("@action:inmenu Sort", "Folders First"));
164 connect(sortFoldersFirst, SIGNAL(triggered()), this, SLOT(toggleSortFoldersFirst()));
165
166 // View -> Sort By
167 QActionGroup* sortByActionGroup = createSortByActionGroup();
168 connect(sortByActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSortTriggered(QAction*)));
169
170 KActionMenu* sortByActionMenu = m_actionCollection->add<KActionMenu>("sort");
171 sortByActionMenu->setText(i18nc("@action:inmenu View", "Sort By"));
172 sortByActionMenu->setDelayed(false);
173
174 foreach (QAction* action, sortByActionGroup->actions()) {
175 sortByActionMenu->addAction(action);
176 }
177 sortByActionMenu->addSeparator();
178 sortByActionMenu->addAction(sortDescending);
179 sortByActionMenu->addAction(sortFoldersFirst);
180
181 // View -> Additional Information
182 QActionGroup* additionalInfoGroup = createAdditionalInformationActionGroup();
183 connect(additionalInfoGroup, SIGNAL(triggered(QAction*)), this, SLOT(toggleAdditionalInfo(QAction*)));
184
185 KActionMenu* additionalInfoMenu = m_actionCollection->add<KActionMenu>("additional_info");
186 additionalInfoMenu->setText(i18nc("@action:inmenu View", "Additional Information"));
187 additionalInfoMenu->setDelayed(false);
188 foreach (QAction* action, additionalInfoGroup->actions()) {
189 additionalInfoMenu->addAction(action);
190 }
191
192 KToggleAction* showInGroups = m_actionCollection->add<KToggleAction>("show_in_groups");
193 showInGroups->setText(i18nc("@action:inmenu View", "Show in Groups"));
194 connect(showInGroups, SIGNAL(triggered(bool)), this, SLOT(toggleSortCategorization(bool)));
195
196 KToggleAction* showHiddenFiles = m_actionCollection->add<KToggleAction>("show_hidden_files");
197 showHiddenFiles->setText(i18nc("@action:inmenu View", "Show Hidden Files"));
198 showHiddenFiles->setShortcuts(QList<QKeySequence>() << Qt::ALT + Qt::Key_Period << Qt::Key_F8);
199 connect(showHiddenFiles, SIGNAL(triggered(bool)), this, SLOT(toggleShowHiddenFiles(bool)));
200
201 KAction* adjustViewProps = m_actionCollection->addAction("view_properties");
202 adjustViewProps->setText(i18nc("@action:inmenu View", "Adjust View Properties..."));
203 connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(slotAdjustViewProperties()));
204 }
205
206 QActionGroup* DolphinViewActionHandler::createAdditionalInformationActionGroup()
207 {
208 QActionGroup* additionalInfoGroup = new QActionGroup(m_actionCollection);
209 additionalInfoGroup->setExclusive(false);
210
211 KActionMenu* showInformationMenu = m_actionCollection->add<KActionMenu>("additional_info");
212 showInformationMenu->setText(i18nc("@action:inmenu View", "Additional Information"));
213 showInformationMenu->setDelayed(false);
214
215 const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
216
217 const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
218 foreach (KFileItemDelegate::Information info, infoKeys) {
219 const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::AdditionalInfoType);
220 KToggleAction* action = m_actionCollection->add<KToggleAction>(name);
221 action->setText(infoAccessor.translation(info));
222 action->setData(info);
223 action->setActionGroup(additionalInfoGroup);
224 }
225
226 return additionalInfoGroup;
227 }
228
229 Q_DECLARE_METATYPE(DolphinView::Sorting)
230
231 QActionGroup* DolphinViewActionHandler::createSortByActionGroup()
232 {
233 QActionGroup* sortByActionGroup = new QActionGroup(m_actionCollection);
234 sortByActionGroup->setExclusive(true);
235
236 KToggleAction* sortByName = m_actionCollection->add<KToggleAction>("sort_by_name");
237 sortByName->setText(i18nc("@action:inmenu Sort By", "Name"));
238 sortByName->setData(QVariant::fromValue(DolphinView::SortByName));
239 sortByActionGroup->addAction(sortByName);
240
241 const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
242 const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
243 foreach (KFileItemDelegate::Information info, infoKeys) {
244 const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::SortByType);
245 KToggleAction* action = m_actionCollection->add<KToggleAction>(name);
246 action->setText(infoAccessor.translation(info));
247 const DolphinView::Sorting sorting = infoAccessor.sorting(info);
248 action->setData(QVariant::fromValue(sorting));
249 sortByActionGroup->addAction(action);
250 }
251
252 return sortByActionGroup;
253 }
254
255 void DolphinViewActionHandler::slotViewModeActionTriggered(QAction* action)
256 {
257 const DolphinView::Mode mode = action->data().value<DolphinView::Mode>();
258 m_currentView->setMode(mode);
259
260 QAction* viewModeMenu = m_actionCollection->action("view_mode");
261 viewModeMenu->setIcon(KIcon(action->icon()));
262 }
263
264 void DolphinViewActionHandler::slotRename()
265 {
266 emit actionBeingHandled();
267 m_currentView->renameSelectedItems();
268 }
269
270 void DolphinViewActionHandler::slotTrashActivated(Qt::MouseButtons, Qt::KeyboardModifiers modifiers)
271 {
272 emit actionBeingHandled();
273 // Note: kde3's konq_mainwindow.cpp used to check
274 // reason == KAction::PopupMenuActivation && ...
275 // but this isn't supported anymore
276 if (modifiers & Qt::ShiftModifier) {
277 m_currentView->deleteSelectedItems();
278 } else {
279 m_currentView->trashSelectedItems();
280 }
281 }
282
283 void DolphinViewActionHandler::slotDeleteItems()
284 {
285 emit actionBeingHandled();
286 m_currentView->deleteSelectedItems();
287 }
288
289 void DolphinViewActionHandler::togglePreview(bool show)
290 {
291 emit actionBeingHandled();
292 m_currentView->setShowPreview(show);
293 }
294
295 void DolphinViewActionHandler::slotShowPreviewChanged()
296 {
297 // It is not enough to update the 'Show Preview' action, also
298 // the 'Zoom In' and 'Zoom Out' actions must be adapted.
299 updateViewActions();
300 }
301
302 QString DolphinViewActionHandler::currentViewModeActionName() const
303 {
304 switch (m_currentView->mode()) {
305 case DolphinView::IconsView:
306 return "icons";
307 case DolphinView::DetailsView:
308 return "details";
309 case DolphinView::ColumnView:
310 return "columns";
311 }
312 return QString(); // can't happen
313 }
314
315 KActionCollection* DolphinViewActionHandler::actionCollection()
316 {
317 return m_actionCollection;
318 }
319
320 void DolphinViewActionHandler::updateViewActions()
321 {
322 QAction* viewModeAction = m_actionCollection->action(currentViewModeActionName());
323 if (viewModeAction != 0) {
324 viewModeAction->setChecked(true);
325
326 QAction* viewModeMenu = m_actionCollection->action("view_mode");
327 viewModeMenu->setIcon(KIcon(viewModeAction->icon()));
328 }
329
330 QAction* showPreviewAction = m_actionCollection->action("show_preview");
331 showPreviewAction->setChecked(m_currentView->showPreview());
332
333 slotSortOrderChanged(m_currentView->sortOrder());
334 slotSortFoldersFirstChanged(m_currentView->sortFoldersFirst());
335 slotAdditionalInfoChanged();
336 slotCategorizedSortingChanged();
337 slotSortingChanged(m_currentView->sorting());
338 slotZoomLevelChanged(m_currentView->zoomLevel());
339
340 QAction* showHiddenFilesAction = m_actionCollection->action("show_hidden_files");
341 showHiddenFilesAction->setChecked(m_currentView->showHiddenFiles());
342 }
343
344 void DolphinViewActionHandler::zoomIn()
345 {
346 const int level = m_currentView->zoomLevel();
347 m_currentView->setZoomLevel(level + 1);
348 updateViewActions();
349 }
350
351 void DolphinViewActionHandler::zoomOut()
352 {
353 const int level = m_currentView->zoomLevel();
354 m_currentView->setZoomLevel(level - 1);
355 updateViewActions();
356 }
357
358 void DolphinViewActionHandler::toggleSortOrder()
359 {
360 const Qt::SortOrder order = (m_currentView->sortOrder() == Qt::AscendingOrder) ?
361 Qt::DescendingOrder :
362 Qt::AscendingOrder;
363 m_currentView->setSortOrder(order);
364 }
365
366 void DolphinViewActionHandler::toggleSortFoldersFirst()
367 {
368 const bool sortFirst = m_currentView->sortFoldersFirst();
369 m_currentView->setSortFoldersFirst(!sortFirst);
370 }
371
372 void DolphinViewActionHandler::slotSortOrderChanged(Qt::SortOrder order)
373 {
374 QAction* descending = m_actionCollection->action("descending");
375 const bool sortDescending = (order == Qt::DescendingOrder);
376 descending->setChecked(sortDescending);
377 }
378
379 void DolphinViewActionHandler::slotSortFoldersFirstChanged(bool foldersFirst)
380 {
381 m_actionCollection->action("folders_first")->setChecked(foldersFirst);
382 }
383
384 void DolphinViewActionHandler::toggleAdditionalInfo(QAction* action)
385 {
386 emit actionBeingHandled();
387
388 const KFileItemDelegate::Information info =
389 static_cast<KFileItemDelegate::Information>(action->data().toInt());
390
391 KFileItemDelegate::InformationList list = m_currentView->additionalInfo();
392
393 const bool show = action->isChecked();
394
395 const int index = list.indexOf(info);
396 const bool containsInfo = (index >= 0);
397 if (show && !containsInfo) {
398 list.append(info);
399 m_currentView->setAdditionalInfo(list);
400 } else if (!show && containsInfo) {
401 list.removeAt(index);
402 m_currentView->setAdditionalInfo(list);
403 Q_ASSERT(list.indexOf(info) < 0);
404 }
405 }
406
407 void DolphinViewActionHandler::slotAdditionalInfoChanged()
408 {
409 m_currentView->updateAdditionalInfoActions(m_actionCollection);
410 }
411
412 void DolphinViewActionHandler::toggleSortCategorization(bool categorizedSorting)
413 {
414 m_currentView->setCategorizedSorting(categorizedSorting);
415 }
416
417 void DolphinViewActionHandler::slotCategorizedSortingChanged()
418 {
419 QAction* showInGroupsAction = m_actionCollection->action("show_in_groups");
420 showInGroupsAction->setChecked(m_currentView->categorizedSorting());
421 showInGroupsAction->setEnabled(m_currentView->supportsCategorizedSorting());
422 }
423
424 void DolphinViewActionHandler::toggleShowHiddenFiles(bool show)
425 {
426 emit actionBeingHandled();
427 m_currentView->setShowHiddenFiles(show);
428 }
429
430 void DolphinViewActionHandler::slotShowHiddenFilesChanged()
431 {
432 QAction* showHiddenFilesAction = m_actionCollection->action("show_hidden_files");
433 showHiddenFilesAction->setChecked(m_currentView->showHiddenFiles());
434 }
435
436
437 KToggleAction* DolphinViewActionHandler::iconsModeAction()
438 {
439 KToggleAction* iconsView = m_actionCollection->add<KToggleAction>("icons");
440 iconsView->setText(i18nc("@action:inmenu View Mode", "Icons"));
441 iconsView->setToolTip(i18nc("@info", "Icons view mode"));
442 iconsView->setShortcut(Qt::CTRL | Qt::Key_1);
443 iconsView->setIcon(KIcon("view-list-icons"));
444 iconsView->setData(QVariant::fromValue(DolphinView::IconsView));
445 return iconsView;
446 }
447
448 KToggleAction* DolphinViewActionHandler::detailsModeAction()
449 {
450 KToggleAction* detailsView = m_actionCollection->add<KToggleAction>("details");
451 detailsView->setText(i18nc("@action:inmenu View Mode", "Details"));
452 detailsView->setToolTip(i18nc("@info", "Details view mode"));
453 detailsView->setShortcut(Qt::CTRL | Qt::Key_2);
454 detailsView->setIcon(KIcon("view-list-details"));
455 detailsView->setData(QVariant::fromValue(DolphinView::DetailsView));
456 return detailsView;
457 }
458
459 KToggleAction* DolphinViewActionHandler::columnsModeAction()
460 {
461 KToggleAction* columnView = m_actionCollection->add<KToggleAction>("columns");
462 columnView->setText(i18nc("@action:inmenu View Mode", "Columns"));
463 columnView->setToolTip(i18nc("@info", "Columns view mode"));
464 columnView->setShortcut(Qt::CTRL | Qt::Key_3);
465 columnView->setIcon(KIcon("view-file-columns"));
466 columnView->setData(QVariant::fromValue(DolphinView::ColumnView));
467 return columnView;
468 }
469
470 void DolphinViewActionHandler::slotSortingChanged(DolphinView::Sorting sorting)
471 {
472 QAction* action = 0;
473 if (sorting == DolphinView::SortByName) {
474 action = m_actionCollection->action("sort_by_name");
475 } else {
476 const AdditionalInfoAccessor& infoAccessor = AdditionalInfoAccessor::instance();
477 const KFileItemDelegate::InformationList infoKeys = infoAccessor.keys();
478 foreach (const KFileItemDelegate::Information info, infoKeys) {
479 if (sorting == infoAccessor.sorting(info)) {
480 const QString name = infoAccessor.actionCollectionName(info, AdditionalInfoAccessor::SortByType);
481 action = m_actionCollection->action(name);
482 break;
483 }
484 }
485 }
486
487 if (action != 0) {
488 action->setChecked(true);
489
490 QAction* sortByMenu = m_actionCollection->action("sort");
491 sortByMenu->setIcon(KIcon(action->icon()));
492 }
493 }
494
495 void DolphinViewActionHandler::slotZoomLevelChanged(int level)
496 {
497 QAction* zoomInAction = m_actionCollection->action(KStandardAction::name(KStandardAction::ZoomIn));
498 if (zoomInAction != 0) {
499 zoomInAction->setEnabled(level < ZoomLevelInfo::maximumLevel());
500 }
501
502 QAction* zoomOutAction = m_actionCollection->action(KStandardAction::name(KStandardAction::ZoomOut));
503 if (zoomOutAction != 0) {
504 zoomOutAction->setEnabled(level > ZoomLevelInfo::minimumLevel());
505 }
506 }
507
508 void DolphinViewActionHandler::slotSortTriggered(QAction* action)
509 {
510 const DolphinView::Sorting sorting = action->data().value<DolphinView::Sorting>();
511 m_currentView->setSorting(sorting);
512 }
513
514 void DolphinViewActionHandler::slotAdjustViewProperties()
515 {
516 emit actionBeingHandled();
517 QPointer<ViewPropertiesDialog> dialog = new ViewPropertiesDialog(m_currentView);
518 dialog->exec();
519 delete dialog;
520 }
521
522 void DolphinViewActionHandler::slotProperties()
523 {
524 KPropertiesDialog* dialog = 0;
525 const KFileItemList list = m_currentView->selectedItems();
526 if (list.isEmpty()) {
527 const KUrl url = m_currentView->url();
528 dialog = new KPropertiesDialog(url, m_currentView);
529 } else {
530 dialog = new KPropertiesDialog(list, m_currentView);
531 }
532
533 dialog->setAttribute(Qt::WA_DeleteOnClose);
534 dialog->show();
535 dialog->raise();
536 dialog->activateWindow();
537 }