]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinmainwindow.cpp
This fixes the problem that when you click the first time on a place
[dolphin.git] / src / dolphinmainwindow.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
3 * Copyright (C) 2006 by Stefan Monov <logixoul@gmail.com> *
4 * Copyright (C) 2006 by Cvetoslav Ludmiloff <ludmiloff@gmail.com> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program 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 *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
21
22 #include "dolphinmainwindow.h"
23
24 #include <config-nepomuk.h>
25
26 #include "dolphinapplication.h"
27 #include "dolphinnewmenu.h"
28 #include "dolphinsettings.h"
29 #include "dolphinsettingsdialog.h"
30 #include "dolphinstatusbar.h"
31 #include "dolphinviewcontainer.h"
32 #include "infosidebarpage.h"
33 #include "metadatawidget.h"
34 #include "mainwindowadaptor.h"
35 #include "terminalsidebarpage.h"
36 #include "treeviewsidebarpage.h"
37 #include "kurlnavigator.h"
38 #include "viewpropertiesdialog.h"
39 #include "viewproperties.h"
40 #include "kfileplacesmodel.h"
41 #include "kfileplacesview.h"
42
43 #include "dolphin_generalsettings.h"
44
45 #include <kaction.h>
46 #include <kactioncollection.h>
47 #include <kconfig.h>
48 #include <kdesktopfile.h>
49 #include <kdeversion.h>
50 #include <kfiledialog.h>
51 #include <kglobal.h>
52 #include <kicon.h>
53 #include <kiconloader.h>
54 #include <kio/netaccess.h>
55 #include <kio/deletejob.h>
56 #include <kio/renamedialog.h>
57 #include <kinputdialog.h>
58 #include <klocale.h>
59 #include <kmenu.h>
60 #include <kmessagebox.h>
61 #include <konqmimedata.h>
62 #include <konq_operations.h>
63 #include <kpropertiesdialog.h>
64 #include <kprotocolinfo.h>
65 #include <ktoggleaction.h>
66 #include <krun.h>
67 #include <kshell.h>
68 #include <kstandarddirs.h>
69 #include <kstatusbar.h>
70 #include <kstandardaction.h>
71 #include <kurl.h>
72
73 #include <QtGui/QKeyEvent>
74 #include <QtGui/QClipboard>
75 #include <QtGui/QSplitter>
76 #include <QtGui/QDockWidget>
77
78 DolphinMainWindow::DolphinMainWindow(int id) :
79 KXmlGuiWindow(0),
80 m_newMenu(0),
81 m_splitter(0),
82 m_activeViewContainer(0),
83 m_id(id)
84 {
85 setObjectName("Dolphin");
86 m_viewContainer[PrimaryView] = 0;
87 m_viewContainer[SecondaryView] = 0;
88
89 new MainWindowAdaptor(this);
90 QDBusConnection::sessionBus().registerObject(QString("/dolphin/MainWindow%1").arg(m_id), this);
91
92 KonqUndoManager::incRef();
93
94 KonqUndoManager* undoManager = KonqUndoManager::self();
95 undoManager->setUiInterface(new UndoUiInterface(this));
96
97 connect(undoManager, SIGNAL(undoAvailable(bool)),
98 this, SLOT(slotUndoAvailable(bool)));
99 connect(undoManager, SIGNAL(undoTextChanged(const QString&)),
100 this, SLOT(slotUndoTextChanged(const QString&)));
101 connect(DolphinSettings::instance().placesModel(), SIGNAL(errorMessage(const QString&)),
102 this, SLOT(slotHandlePlacesError(const QString&)));
103 }
104
105 DolphinMainWindow::~DolphinMainWindow()
106 {
107 KonqUndoManager::decRef();
108 DolphinApplication::app()->removeMainWindow(this);
109 }
110
111 void DolphinMainWindow::toggleViews()
112 {
113 if (m_viewContainer[SecondaryView] == 0) {
114 return;
115 }
116
117 // move secondary view from the last position of the splitter
118 // to the first position
119 m_splitter->insertWidget(0, m_viewContainer[SecondaryView]);
120
121 DolphinViewContainer* container = m_viewContainer[PrimaryView];
122 m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView];
123 m_viewContainer[SecondaryView] = container;
124 }
125
126 void DolphinMainWindow::rename(const KUrl& oldUrl, const KUrl& newUrl)
127 {
128 clearStatusBar();
129 KonqOperations::rename(this, oldUrl, newUrl);
130 m_undoCommandTypes.append(KonqUndoManager::RENAME);
131 }
132
133 void DolphinMainWindow::refreshViews()
134 {
135 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
136
137 // remember the current active view, as because of
138 // the refreshing the active view might change to
139 // the secondary view
140 DolphinViewContainer* activeViewContainer = m_activeViewContainer;
141
142 m_viewContainer[PrimaryView]->view()->refresh();
143 if (m_viewContainer[SecondaryView] != 0) {
144 m_viewContainer[SecondaryView]->view()->refresh();
145 }
146
147 setActiveViewContainer(activeViewContainer);
148 }
149
150 void DolphinMainWindow::dropUrls(const KUrl::List& urls,
151 const KUrl& destination)
152 {
153 kDebug() << "Source" << urls;
154 kDebug() << "Destination:" << destination;
155
156 Qt::DropAction action = Qt::CopyAction;
157
158 Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
159 const bool shiftPressed = modifier & Qt::ShiftModifier;
160 const bool controlPressed = modifier & Qt::ControlModifier;
161 if (shiftPressed && controlPressed) {
162 // shortcut for 'Link Here' is used
163 action = Qt::LinkAction;
164 } else if (shiftPressed) {
165 // shortcut for 'Move Here' is used
166 action = Qt::MoveAction;
167 } else if (controlPressed) {
168 // shortcut for 'Copy Here' is used
169 action = Qt::CopyAction;
170 } else {
171 // open a context menu which offers the following actions:
172 // - Move Here
173 // - Copy Here
174 // - Link Here
175 // - Cancel
176
177 KMenu popup(this);
178
179 QString seq = QKeySequence(Qt::ShiftModifier).toString();
180 seq.chop(1); // chop superfluous '+'
181 QAction* moveAction = popup.addAction(KIcon("goto-page"),
182 i18nc("@action:inmenu",
183 "&Move Here\t<shortcut>%1</shortcut>", seq));
184
185 seq = QKeySequence(Qt::ControlModifier).toString();
186 seq.chop(1);
187 QAction* copyAction = popup.addAction(KIcon("edit-copy"),
188 i18nc("@action:inmenu",
189 "&Copy Here\t<shortcut>%1</shortcut>", seq));
190
191 seq = QKeySequence(Qt::ControlModifier + Qt::ShiftModifier).toString();
192 seq.chop(1);
193 QAction* linkAction = popup.addAction(KIcon("www"),
194 i18nc("@action:inmenu",
195 "&Link Here\t<shortcut>%1</shortcut>", seq));
196
197 popup.addSeparator();
198 popup.addAction(KIcon("process-stop"), i18nc("@action:inmenu", "Cancel"));
199
200 QAction* activatedAction = popup.exec(QCursor::pos());
201 if (activatedAction == moveAction) {
202 action = Qt::MoveAction;
203 } else if (activatedAction == copyAction) {
204 action = Qt::CopyAction;
205 } else if (activatedAction == linkAction) {
206 action = Qt::LinkAction;
207 } else {
208 return;
209 }
210 }
211
212 switch (action) {
213 case Qt::MoveAction:
214 moveUrls(urls, destination);
215 break;
216
217 case Qt::CopyAction:
218 copyUrls(urls, destination);
219 break;
220
221 case Qt::LinkAction:
222 linkUrls(urls, destination);
223 break;
224
225 default:
226 break;
227 }
228 }
229
230 void DolphinMainWindow::changeUrl(const KUrl& url)
231 {
232 DolphinViewContainer* view = activeViewContainer();
233 if (view != 0) {
234 view->setUrl(url);
235 updateEditActions();
236 updateViewActions();
237 updateGoActions();
238 setCaption(url.fileName());
239 }
240 }
241
242 void DolphinMainWindow::changeSelection(const KFileItemList& selection)
243 {
244 activeViewContainer()->view()->changeSelection(selection);
245 }
246
247 void DolphinMainWindow::slotViewModeChanged()
248 {
249 updateViewActions();
250 }
251
252 void DolphinMainWindow::slotShowPreviewChanged()
253 {
254 // It is not enough to update the 'Show Preview' action, also
255 // the 'Zoom In' and 'Zoom Out' actions must be adapted.
256 updateViewActions();
257 }
258
259 void DolphinMainWindow::slotShowHiddenFilesChanged()
260 {
261 KToggleAction* showHiddenFilesAction =
262 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
263 const DolphinView* view = m_activeViewContainer->view();
264 showHiddenFilesAction->setChecked(view->showHiddenFiles());
265 }
266
267 void DolphinMainWindow::slotCategorizedSortingChanged()
268 {
269 KToggleAction* showInGroupsAction =
270 static_cast<KToggleAction*>(actionCollection()->action("show_in_groups"));
271 const DolphinView* view = m_activeViewContainer->view();
272 showInGroupsAction->setChecked(view->categorizedSorting());
273 showInGroupsAction->setEnabled(view->supportsCategorizedSorting());
274 }
275
276 void DolphinMainWindow::slotSortingChanged(DolphinView::Sorting sorting)
277 {
278 QAction* action = 0;
279 switch (sorting) {
280 case DolphinView::SortByName:
281 action = actionCollection()->action("sort_by_name");
282 break;
283 case DolphinView::SortBySize:
284 action = actionCollection()->action("sort_by_size");
285 break;
286 case DolphinView::SortByDate:
287 action = actionCollection()->action("sort_by_date");
288 break;
289 case DolphinView::SortByPermissions:
290 action = actionCollection()->action("sort_by_permissions");
291 break;
292 case DolphinView::SortByOwner:
293 action = actionCollection()->action("sort_by_owner");
294 break;
295 case DolphinView::SortByGroup:
296 action = actionCollection()->action("sort_by_group");
297 break;
298 case DolphinView::SortByType:
299 action = actionCollection()->action("sort_by_type");
300 break;
301 #ifdef HAVE_NEPOMUK
302 case DolphinView::SortByRating:
303 action = actionCollection()->action("sort_by_rating");
304 break;
305 case DolphinView::SortByTags:
306 action = actionCollection()->action("sort_by_tags");
307 break;
308 #endif
309 default:
310 break;
311 }
312
313 if (action != 0) {
314 KToggleAction* toggleAction = static_cast<KToggleAction*>(action);
315 toggleAction->setChecked(true);
316 }
317 }
318
319 void DolphinMainWindow::slotSortOrderChanged(Qt::SortOrder order)
320 {
321 KToggleAction* descending = static_cast<KToggleAction*>(actionCollection()->action("descending"));
322 const bool sortDescending = (order == Qt::DescendingOrder);
323 descending->setChecked(sortDescending);
324 }
325
326 void DolphinMainWindow::slotAdditionalInfoChanged(KFileItemDelegate::InformationList list)
327 {
328 QAction* showMimeInfo = actionCollection()->action("show_mime_info");
329 QAction* showSizeInfo = actionCollection()->action("show_size_info");
330 QAction* showDateInfo = actionCollection()->action("show_date_info");
331
332 showMimeInfo->setChecked(false);
333 showSizeInfo->setChecked(false);
334 showDateInfo->setChecked(false);
335
336 const DolphinView* view = m_activeViewContainer->view();
337 // currently only the icons view supports additional information
338 const bool enable = (view->mode() == DolphinView::IconsView);
339 showMimeInfo->setEnabled(enable);
340 showSizeInfo->setEnabled(enable);
341 showDateInfo->setEnabled(enable);
342
343 foreach (KFileItemDelegate::Information info, list) {
344 switch (info) {
345 case KFileItemDelegate::FriendlyMimeType:
346 showMimeInfo->setChecked(true);
347 break;
348 case KFileItemDelegate::Size:
349 showSizeInfo->setChecked(true);
350 break;
351 case KFileItemDelegate::ModificationTime:
352 showDateInfo->setChecked(true);
353 break;
354 default:
355 break;
356 }
357 }
358 }
359
360 void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
361 {
362 updateEditActions();
363
364 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
365 int selectedUrlsCount = m_viewContainer[PrimaryView]->view()->selectedUrls().count();
366 if (m_viewContainer[SecondaryView] != 0) {
367 selectedUrlsCount += m_viewContainer[SecondaryView]->view()->selectedUrls().count();
368 }
369
370 QAction* compareFilesAction = actionCollection()->action("compare_files");
371 compareFilesAction->setEnabled(selectedUrlsCount == 2);
372
373 m_activeViewContainer->updateStatusBar();
374
375 emit selectionChanged(selection);
376 }
377
378 void DolphinMainWindow::slotRequestItemInfo(const KFileItem& item)
379 {
380 emit requestItemInfo(item);
381 }
382
383 void DolphinMainWindow::slotHistoryChanged()
384 {
385 updateHistory();
386 }
387
388 void DolphinMainWindow::updateFilterBarAction(bool show)
389 {
390 KToggleAction* showFilterBarAction =
391 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
392 showFilterBarAction->setChecked(show);
393 }
394
395 void DolphinMainWindow::openNewMainWindow()
396 {
397 DolphinApplication::app()->createMainWindow()->show();
398 }
399
400 void DolphinMainWindow::toggleActiveView()
401 {
402 if (m_viewContainer[SecondaryView] == 0) {
403 // only one view is available
404 return;
405 }
406
407 Q_ASSERT(m_activeViewContainer != 0);
408 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
409
410 DolphinViewContainer* left = m_viewContainer[PrimaryView];
411 DolphinViewContainer* right = m_viewContainer[SecondaryView];
412 setActiveViewContainer(m_activeViewContainer == right ? left : right);
413 }
414
415 void DolphinMainWindow::closeEvent(QCloseEvent* event)
416 {
417 DolphinSettings& settings = DolphinSettings::instance();
418 GeneralSettings* generalSettings = settings.generalSettings();
419 generalSettings->setFirstRun(false);
420
421 settings.save();
422
423 KXmlGuiWindow::closeEvent(event);
424 }
425
426 void DolphinMainWindow::saveProperties(KConfig* config)
427 {
428 KConfigGroup primaryView = config->group("Primary view");
429 primaryView.writeEntry("Url", m_viewContainer[PrimaryView]->url().url());
430 primaryView.writeEntry("Editable Url", m_viewContainer[PrimaryView]->isUrlEditable());
431 if (m_viewContainer[SecondaryView] != 0) {
432 KConfigGroup secondaryView = config->group("Secondary view");
433 secondaryView.writeEntry("Url", m_viewContainer[SecondaryView]->url().url());
434 secondaryView.writeEntry("Editable Url", m_viewContainer[SecondaryView]->isUrlEditable());
435 }
436 }
437
438 void DolphinMainWindow::readProperties(KConfig* config)
439 {
440 const KConfigGroup primaryViewGroup = config->group("Primary view");
441 m_viewContainer[PrimaryView]->setUrl(primaryViewGroup.readEntry("Url"));
442 bool editable = primaryViewGroup.readEntry("Editable Url", false);
443 m_viewContainer[PrimaryView]->urlNavigator()->setUrlEditable(editable);
444
445 if (config->hasGroup("Secondary view")) {
446 const KConfigGroup secondaryViewGroup = config->group("Secondary view");
447 if (m_viewContainer[PrimaryView] == 0) {
448 toggleSplitView();
449 }
450 m_viewContainer[PrimaryView]->setUrl(secondaryViewGroup.readEntry("Url"));
451 editable = secondaryViewGroup.readEntry("Editable Url", false);
452 m_viewContainer[PrimaryView]->urlNavigator()->setUrlEditable(editable);
453 } else if (m_viewContainer[SecondaryView] != 0) {
454 toggleSplitView();
455 }
456 }
457
458 void DolphinMainWindow::updateNewMenu()
459 {
460 m_newMenu->slotCheckUpToDate();
461 m_newMenu->setPopupFiles(activeViewContainer()->url());
462 }
463
464 void DolphinMainWindow::rename()
465 {
466 clearStatusBar();
467 m_activeViewContainer->renameSelectedItems();
468 }
469
470 void DolphinMainWindow::moveToTrash()
471 {
472 clearStatusBar();
473 const KUrl::List selectedUrls = m_activeViewContainer->view()->selectedUrls();
474 KonqOperations::del(this, KonqOperations::TRASH, selectedUrls);
475 m_undoCommandTypes.append(KonqUndoManager::TRASH);
476 }
477
478 void DolphinMainWindow::deleteItems()
479 {
480 clearStatusBar();
481
482 const KUrl::List list = m_activeViewContainer->view()->selectedUrls();
483 const bool del = KonqOperations::askDeleteConfirmation(list,
484 KonqOperations::DEL,
485 KonqOperations::DEFAULT_CONFIRMATION,
486 this);
487
488 if (del) {
489 KIO::Job* job = KIO::del(list);
490 connect(job, SIGNAL(result(KJob*)),
491 this, SLOT(slotHandleJobError(KJob*)));
492 connect(job, SIGNAL(result(KJob*)),
493 this, SLOT(slotDeleteFileFinished(KJob*)));
494 }
495 }
496
497 void DolphinMainWindow::properties()
498 {
499 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
500
501 KPropertiesDialog dialog(list, this);
502 dialog.exec();
503 }
504
505 void DolphinMainWindow::quit()
506 {
507 close();
508 }
509
510 void DolphinMainWindow::slotHandlePlacesError(const QString &message)
511 {
512 if (!message.isEmpty()) {
513 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
514 statusBar->setMessage(message, DolphinStatusBar::Error);
515 }
516 }
517
518 void DolphinMainWindow::slotHandleJobError(KJob* job)
519 {
520 if (job->error() != 0) {
521 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
522 statusBar->setMessage(job->errorString(),
523 DolphinStatusBar::Error);
524 }
525 }
526
527 void DolphinMainWindow::slotDeleteFileFinished(KJob* job)
528 {
529 if (job->error() == 0) {
530 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
531 statusBar->setMessage(i18nc("@info:status", "Delete operation completed."),
532 DolphinStatusBar::OperationCompleted);
533 }
534 }
535
536 void DolphinMainWindow::slotUndoAvailable(bool available)
537 {
538 QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));
539 if (undoAction != 0) {
540 undoAction->setEnabled(available);
541 }
542
543 if (available && (m_undoCommandTypes.count() > 0)) {
544 const KonqUndoManager::CommandType command = m_undoCommandTypes.takeFirst();
545 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
546 switch (command) {
547 case KonqUndoManager::COPY:
548 statusBar->setMessage(i18nc("@info:status", "Copy operation completed."),
549 DolphinStatusBar::OperationCompleted);
550 break;
551 case KonqUndoManager::MOVE:
552 statusBar->setMessage(i18nc("@info:status", "Move operation completed."),
553 DolphinStatusBar::OperationCompleted);
554 break;
555 case KonqUndoManager::LINK:
556 statusBar->setMessage(i18nc("@info:status", "Link operation completed."),
557 DolphinStatusBar::OperationCompleted);
558 break;
559 case KonqUndoManager::TRASH:
560 statusBar->setMessage(i18nc("@info:status", "Move to trash operation completed."),
561 DolphinStatusBar::OperationCompleted);
562 break;
563 case KonqUndoManager::RENAME:
564 statusBar->setMessage(i18nc("@info:status", "Renaming operation completed."),
565 DolphinStatusBar::OperationCompleted);
566 break;
567
568 case KonqUndoManager::MKDIR:
569 statusBar->setMessage(i18nc("@info:status", "Created folder."),
570 DolphinStatusBar::OperationCompleted);
571 break;
572
573 default:
574 break;
575 }
576
577 }
578 }
579
580 void DolphinMainWindow::slotUndoTextChanged(const QString& text)
581 {
582 QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));
583 if (undoAction != 0) {
584 undoAction->setText(text);
585 }
586 }
587
588 void DolphinMainWindow::undo()
589 {
590 clearStatusBar();
591 KonqUndoManager::self()->undo();
592 }
593
594 void DolphinMainWindow::cut()
595 {
596 QMimeData* mimeData = new QMimeData();
597 const KUrl::List kdeUrls = m_activeViewContainer->view()->selectedUrls();
598 const KUrl::List mostLocalUrls;
599 KonqMimeData::populateMimeData(mimeData, kdeUrls, mostLocalUrls, true);
600 QApplication::clipboard()->setMimeData(mimeData);
601 }
602
603 void DolphinMainWindow::copy()
604 {
605 QMimeData* mimeData = new QMimeData();
606 const KUrl::List kdeUrls = m_activeViewContainer->view()->selectedUrls();
607 const KUrl::List mostLocalUrls;
608 KonqMimeData::populateMimeData(mimeData, kdeUrls, mostLocalUrls, false);
609
610 QApplication::clipboard()->setMimeData(mimeData);
611 }
612
613 void DolphinMainWindow::paste()
614 {
615 QClipboard* clipboard = QApplication::clipboard();
616 const QMimeData* mimeData = clipboard->mimeData();
617
618 clearStatusBar();
619
620 const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData);
621
622 // per default the pasting is done into the current Url of the view
623 KUrl destUrl(m_activeViewContainer->url());
624
625 // check whether the pasting should be done into a selected directory
626 KUrl::List selectedUrls = m_activeViewContainer->view()->selectedUrls();
627 if (selectedUrls.count() == 1) {
628 const KFileItem fileItem(S_IFDIR,
629 KFileItem::Unknown,
630 selectedUrls.first(),
631 true);
632 if (fileItem.isDir()) {
633 // only one item is selected which is a directory, hence paste
634 // into this directory
635 destUrl = selectedUrls.first();
636 }
637 }
638
639 if (KonqMimeData::decodeIsCutSelection(mimeData)) {
640 moveUrls(sourceUrls, destUrl);
641 clipboard->clear();
642 } else {
643 copyUrls(sourceUrls, destUrl);
644 }
645 }
646
647 void DolphinMainWindow::updatePasteAction()
648 {
649 QAction* pasteAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Paste));
650 if (pasteAction == 0) {
651 return;
652 }
653
654 QString text(i18nc("@action:inmenu", "Paste"));
655 QClipboard* clipboard = QApplication::clipboard();
656 const QMimeData* mimeData = clipboard->mimeData();
657
658 KUrl::List urls = KUrl::List::fromMimeData(mimeData);
659 if (!urls.isEmpty()) {
660 pasteAction->setEnabled(true);
661
662 pasteAction->setText(i18ncp("@action:inmenu", "Paste One File", "Paste %1 Files", urls.count()));
663 } else {
664 pasteAction->setEnabled(false);
665 pasteAction->setText(i18nc("@action:inmenu", "Paste"));
666 }
667
668 if (pasteAction->isEnabled()) {
669 KUrl::List urls = m_activeViewContainer->view()->selectedUrls();
670 const uint count = urls.count();
671 if (count > 1) {
672 // pasting should not be allowed when more than one file
673 // is selected
674 pasteAction->setEnabled(false);
675 } else if (count == 1) {
676 // Only one file is selected. Pasting is only allowed if this
677 // file is a directory.
678 // TODO: this doesn't work with remote protocols; instead we need a
679 // m_activeViewContainer->selectedFileItems() to get the real KFileItems
680 const KFileItem fileItem(S_IFDIR,
681 KFileItem::Unknown,
682 urls.first(),
683 true);
684 pasteAction->setEnabled(fileItem.isDir());
685 }
686 }
687 }
688
689 void DolphinMainWindow::selectAll()
690 {
691 clearStatusBar();
692 m_activeViewContainer->view()->selectAll();
693 }
694
695 void DolphinMainWindow::invertSelection()
696 {
697 clearStatusBar();
698 m_activeViewContainer->view()->invertSelection();
699 }
700
701 void DolphinMainWindow::setViewMode(QAction* action)
702 {
703 const DolphinView::Mode mode = action->data().value<DolphinView::Mode>();
704 m_activeViewContainer->view()->setMode(mode);
705 }
706
707 void DolphinMainWindow::sortByName()
708 {
709 m_activeViewContainer->view()->setSorting(DolphinView::SortByName);
710 }
711
712 void DolphinMainWindow::sortBySize()
713 {
714 m_activeViewContainer->view()->setSorting(DolphinView::SortBySize);
715 }
716
717 void DolphinMainWindow::sortByDate()
718 {
719 m_activeViewContainer->view()->setSorting(DolphinView::SortByDate);
720 }
721
722 void DolphinMainWindow::sortByPermissions()
723 {
724 m_activeViewContainer->view()->setSorting(DolphinView::SortByPermissions);
725 }
726
727 void DolphinMainWindow::sortByOwner()
728 {
729 m_activeViewContainer->view()->setSorting(DolphinView::SortByOwner);
730 }
731
732 void DolphinMainWindow::sortByGroup()
733 {
734 m_activeViewContainer->view()->setSorting(DolphinView::SortByGroup);
735 }
736
737 void DolphinMainWindow::sortByType()
738 {
739 m_activeViewContainer->view()->setSorting(DolphinView::SortByType);
740 }
741
742 void DolphinMainWindow::sortByRating()
743 {
744 #ifdef HAVE_NEPOMUK
745 m_activeViewContainer->view()->setSorting(DolphinView::SortByRating);
746 #endif
747 }
748
749 void DolphinMainWindow::sortByTags()
750 {
751 #ifdef HAVE_NEPOMUK
752 m_activeViewContainer->view()->setSorting(DolphinView::SortByTags);
753 #endif
754 }
755
756 void DolphinMainWindow::toggleSortOrder()
757 {
758 DolphinView* view = m_activeViewContainer->view();
759 const Qt::SortOrder order = (view->sortOrder() == Qt::AscendingOrder) ?
760 Qt::DescendingOrder :
761 Qt::AscendingOrder;
762 view->setSortOrder(order);
763 }
764
765 void DolphinMainWindow::toggleSortCategorization()
766 {
767 DolphinView* view = m_activeViewContainer->view();
768 const bool categorizedSorting = view->categorizedSorting();
769 view->setCategorizedSorting(!categorizedSorting);
770 }
771
772 void DolphinMainWindow::toggleMimeInfo()
773 {
774 toggleAdditionalInfo("show_mime_info", KFileItemDelegate::FriendlyMimeType);
775 }
776
777 void DolphinMainWindow::toggleSizeInfo()
778 {
779 toggleAdditionalInfo("show_size_info", KFileItemDelegate::Size);
780 }
781
782 void DolphinMainWindow::toggleDateInfo()
783 {
784 toggleAdditionalInfo("show_date_info", KFileItemDelegate::ModificationTime);
785 }
786
787 void DolphinMainWindow::toggleSplitView()
788 {
789 if (m_viewContainer[SecondaryView] == 0) {
790 // create a secondary view
791 const int newWidth = (m_viewContainer[PrimaryView]->width() - m_splitter->handleWidth()) / 2;
792
793 const DolphinView* view = m_viewContainer[PrimaryView]->view();
794 m_viewContainer[SecondaryView] = new DolphinViewContainer(this, 0, view->rootUrl());
795 connectViewSignals(SecondaryView);
796 m_splitter->addWidget(m_viewContainer[SecondaryView]);
797 m_splitter->setSizes(QList<int>() << newWidth << newWidth);
798 m_viewContainer[SecondaryView]->view()->reload();
799 m_viewContainer[SecondaryView]->setActive(false);
800 m_viewContainer[SecondaryView]->show();
801 } else if (m_activeViewContainer == m_viewContainer[PrimaryView]) {
802 // remove secondary view
803 m_viewContainer[SecondaryView]->close();
804 m_viewContainer[SecondaryView]->deleteLater();
805 m_viewContainer[SecondaryView] = 0;
806 } else {
807 // The secondary view is active, hence from a users point of view
808 // the content of the secondary view should be moved to the primary view.
809 // From an implementation point of view it is more efficient to close
810 // the primary view and exchange the internal pointers afterwards.
811 m_viewContainer[PrimaryView]->close();
812 m_viewContainer[PrimaryView]->deleteLater();
813 m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView];
814 m_viewContainer[SecondaryView] = 0;
815 }
816
817 setActiveViewContainer(m_viewContainer[PrimaryView]);
818 updateViewActions();
819 emit activeViewChanged();
820 }
821
822 void DolphinMainWindow::reloadView()
823 {
824 clearStatusBar();
825 m_activeViewContainer->view()->reload();
826 }
827
828 void DolphinMainWindow::stopLoading()
829 {
830 }
831
832 void DolphinMainWindow::togglePreview()
833 {
834 clearStatusBar();
835
836 const KToggleAction* showPreviewAction =
837 static_cast<KToggleAction*>(actionCollection()->action("show_preview"));
838 const bool show = showPreviewAction->isChecked();
839 m_activeViewContainer->view()->setShowPreview(show);
840 }
841
842 void DolphinMainWindow::toggleShowHiddenFiles()
843 {
844 clearStatusBar();
845
846 const KToggleAction* showHiddenFilesAction =
847 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
848 const bool show = showHiddenFilesAction->isChecked();
849 m_activeViewContainer->view()->setShowHiddenFiles(show);
850 }
851
852 void DolphinMainWindow::toggleFilterBarVisibility()
853 {
854 const KToggleAction* showFilterBarAction =
855 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
856 const bool show = showFilterBarAction->isChecked();
857 m_activeViewContainer->showFilterBar(show);
858 }
859
860 void DolphinMainWindow::zoomIn()
861 {
862 m_activeViewContainer->view()->zoomIn();
863 updateViewActions();
864 }
865
866 void DolphinMainWindow::zoomOut()
867 {
868 m_activeViewContainer->view()->zoomOut();
869 updateViewActions();
870 }
871
872 void DolphinMainWindow::toggleEditLocation()
873 {
874 clearStatusBar();
875
876 KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
877
878 bool editOrBrowse = action->isChecked();
879 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
880 urlNavigator->setUrlEditable(editOrBrowse);
881 }
882
883 void DolphinMainWindow::editLocation()
884 {
885 m_activeViewContainer->urlNavigator()->setUrlEditable(true);
886 }
887
888 void DolphinMainWindow::adjustViewProperties()
889 {
890 clearStatusBar();
891 ViewPropertiesDialog dlg(m_activeViewContainer->view());
892 dlg.exec();
893 }
894
895 void DolphinMainWindow::goBack()
896 {
897 clearStatusBar();
898 m_activeViewContainer->urlNavigator()->goBack();
899 }
900
901 void DolphinMainWindow::goForward()
902 {
903 clearStatusBar();
904 m_activeViewContainer->urlNavigator()->goForward();
905 }
906
907 void DolphinMainWindow::goUp()
908 {
909 clearStatusBar();
910 m_activeViewContainer->urlNavigator()->goUp();
911 }
912
913 void DolphinMainWindow::goHome()
914 {
915 clearStatusBar();
916 m_activeViewContainer->urlNavigator()->goHome();
917 }
918
919 void DolphinMainWindow::findFile()
920 {
921 KRun::run("kfind", m_activeViewContainer->url(), this);
922 }
923
924 void DolphinMainWindow::compareFiles()
925 {
926 // The method is only invoked if exactly 2 files have
927 // been selected. The selected files may be:
928 // - both in the primary view
929 // - both in the secondary view
930 // - one in the primary view and the other in the secondary
931 // view
932 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
933
934 KUrl urlA;
935 KUrl urlB;
936 KUrl::List urls = m_viewContainer[PrimaryView]->view()->selectedUrls();
937
938 switch (urls.count()) {
939 case 0: {
940 Q_ASSERT(m_viewContainer[SecondaryView] != 0);
941 urls = m_viewContainer[SecondaryView]->view()->selectedUrls();
942 Q_ASSERT(urls.count() == 2);
943 urlA = urls[0];
944 urlB = urls[1];
945 break;
946 }
947
948 case 1: {
949 urlA = urls[0];
950 Q_ASSERT(m_viewContainer[SecondaryView] != 0);
951 urls = m_viewContainer[SecondaryView]->view()->selectedUrls();
952 Q_ASSERT(urls.count() == 1);
953 urlB = urls[0];
954 break;
955 }
956
957 case 2: {
958 urlA = urls[0];
959 urlB = urls[1];
960 break;
961 }
962
963 default: {
964 // may not happen: compareFiles may only get invoked if 2
965 // files are selected
966 Q_ASSERT(false);
967 }
968 }
969
970 QString command("kompare -c \"");
971 command.append(urlA.pathOrUrl());
972 command.append("\" \"");
973 command.append(urlB.pathOrUrl());
974 command.append('\"');
975 KRun::runCommand(command, "Kompare", "kompare", this);
976
977 }
978
979 void DolphinMainWindow::editSettings()
980 {
981 DolphinSettingsDialog dialog(this);
982 dialog.exec();
983 }
984
985 void DolphinMainWindow::init()
986 {
987 // Check whether Dolphin runs the first time. If yes then
988 // a proper default window size is given at the end of DolphinMainWindow::init().
989 GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
990 const bool firstRun = generalSettings->firstRun();
991 if (firstRun) {
992 generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
993 }
994
995 setAcceptDrops(true);
996
997 m_splitter = new QSplitter(this);
998
999 DolphinSettings& settings = DolphinSettings::instance();
1000
1001 setupActions();
1002
1003 const KUrl& homeUrl = settings.generalSettings()->homeUrl();
1004 setCaption(homeUrl.fileName());
1005 ViewProperties props(homeUrl);
1006 m_viewContainer[PrimaryView] = new DolphinViewContainer(this,
1007 m_splitter,
1008 homeUrl);
1009
1010 m_activeViewContainer = m_viewContainer[PrimaryView];
1011 connectViewSignals(PrimaryView);
1012 m_viewContainer[PrimaryView]->view()->reload();
1013 m_viewContainer[PrimaryView]->show();
1014
1015 setCentralWidget(m_splitter);
1016 setupDockWidgets();
1017
1018 setupGUI(Keys | Save | Create | ToolBar);
1019 createGUI();
1020
1021 stateChanged("new_file");
1022 setAutoSaveSettings();
1023
1024 QClipboard* clipboard = QApplication::clipboard();
1025 connect(clipboard, SIGNAL(dataChanged()),
1026 this, SLOT(updatePasteAction()));
1027 updatePasteAction();
1028 updateGoActions();
1029
1030 if (generalSettings->splitView()) {
1031 toggleSplitView();
1032 }
1033 updateViewActions();
1034
1035 if (firstRun) {
1036 // assure a proper default size if Dolphin runs the first time
1037 resize(700, 500);
1038 }
1039 #ifdef HAVE_NEPOMUK
1040 if (!MetaDataWidget::metaDataAvailable()) {
1041 DolphinStatusBar* statusBar = activeViewContainer()->statusBar();
1042 statusBar->setMessage(i18nc("@info:status",
1043 "Failed to contact Nepomuk service, annotation and tagging are disabled."),
1044 DolphinStatusBar::Error);
1045 }
1046 #endif
1047
1048 emit urlChanged(homeUrl);
1049 }
1050
1051 void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* view)
1052 {
1053 Q_ASSERT(view != 0);
1054 Q_ASSERT((view == m_viewContainer[PrimaryView]) || (view == m_viewContainer[SecondaryView]));
1055 if (m_activeViewContainer == view) {
1056 return;
1057 }
1058
1059 m_activeViewContainer->setActive(false);
1060 m_activeViewContainer = view;
1061 m_activeViewContainer->setActive(true);
1062
1063 updateHistory();
1064 updateEditActions();
1065 updateViewActions();
1066 updateGoActions();
1067
1068 const KUrl& url = m_activeViewContainer->url();
1069 setCaption(url.fileName());
1070
1071 emit activeViewChanged();
1072 emit urlChanged(url);
1073 }
1074
1075 void DolphinMainWindow::setupActions()
1076 {
1077 // setup 'File' menu
1078 m_newMenu = new DolphinNewMenu(this);
1079 KMenu* menu = m_newMenu->menu();
1080 menu->setTitle(i18nc("@title:menu", "Create New"));
1081 menu->setIcon(KIcon("document-new"));
1082 connect(menu, SIGNAL(aboutToShow()),
1083 this, SLOT(updateNewMenu()));
1084
1085 QAction* newWindow = actionCollection()->addAction("new_window");
1086 newWindow->setIcon(KIcon("window-new"));
1087 newWindow->setText(i18nc("@action:inmenu File", "New &Window"));
1088 newWindow->setShortcut(Qt::CTRL | Qt::Key_N);
1089 connect(newWindow, SIGNAL(triggered()), this, SLOT(openNewMainWindow()));
1090
1091 QAction* rename = actionCollection()->addAction("rename");
1092 rename->setText(i18nc("@action:inmenu File", "Rename..."));
1093 rename->setShortcut(Qt::Key_F2);
1094 connect(rename, SIGNAL(triggered()), this, SLOT(rename()));
1095
1096 QAction* moveToTrash = actionCollection()->addAction("move_to_trash");
1097 moveToTrash->setText(i18nc("@action:inmenu File", "Move to Trash"));
1098 moveToTrash->setIcon(KIcon("edit-trash"));
1099 moveToTrash->setShortcut(QKeySequence::Delete);
1100 connect(moveToTrash, SIGNAL(triggered()), this, SLOT(moveToTrash()));
1101
1102 QAction* deleteAction = actionCollection()->addAction("delete");
1103 deleteAction->setText(i18nc("@action:inmenu File", "Delete"));
1104 deleteAction->setShortcut(Qt::SHIFT | Qt::Key_Delete);
1105 deleteAction->setIcon(KIcon("edit-delete"));
1106 connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItems()));
1107
1108 QAction* properties = actionCollection()->addAction("properties");
1109 properties->setText(i18nc("@action:inmenu File", "Properties"));
1110 properties->setShortcut(Qt::ALT | Qt::Key_Return);
1111 connect(properties, SIGNAL(triggered()), this, SLOT(properties()));
1112
1113 KStandardAction::quit(this, SLOT(quit()), actionCollection());
1114
1115 // setup 'Edit' menu
1116 KStandardAction::undo(this,
1117 SLOT(undo()),
1118 actionCollection());
1119
1120 KStandardAction::cut(this, SLOT(cut()), actionCollection());
1121 KStandardAction::copy(this, SLOT(copy()), actionCollection());
1122 KStandardAction::paste(this, SLOT(paste()), actionCollection());
1123
1124 QAction* selectAll = actionCollection()->addAction("select_all");
1125 selectAll->setText(i18nc("@action:inmenu Edit", "Select All"));
1126 selectAll->setShortcut(Qt::CTRL + Qt::Key_A);
1127 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
1128
1129 QAction* invertSelection = actionCollection()->addAction("invert_selection");
1130 invertSelection->setText(i18nc("@action:inmenu Edit", "Invert Selection"));
1131 invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
1132 connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
1133
1134 // setup 'View' menu
1135 KStandardAction::zoomIn(this,
1136 SLOT(zoomIn()),
1137 actionCollection());
1138
1139 KStandardAction::zoomOut(this,
1140 SLOT(zoomOut()),
1141 actionCollection());
1142
1143
1144 KToggleAction* iconsView = DolphinView::iconsModeAction(actionCollection());
1145 KToggleAction* detailsView = DolphinView::detailsModeAction(actionCollection());
1146 KToggleAction* columnView = DolphinView::columnsModeAction(actionCollection());
1147
1148 QActionGroup* viewModeGroup = new QActionGroup(this);
1149 viewModeGroup->addAction(iconsView);
1150 viewModeGroup->addAction(detailsView);
1151 viewModeGroup->addAction(columnView);
1152 connect(viewModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(setViewMode(QAction*)));
1153
1154 KToggleAction* sortByName = actionCollection()->add<KToggleAction>("sort_by_name");
1155 sortByName->setText(i18nc("@action:inmenu Sort By", "Name"));
1156 connect(sortByName, SIGNAL(triggered()), this, SLOT(sortByName()));
1157
1158 KToggleAction* sortBySize = actionCollection()->add<KToggleAction>("sort_by_size");
1159 sortBySize->setText(i18nc("@action:inmenu Sort By", "Size"));
1160 connect(sortBySize, SIGNAL(triggered()), this, SLOT(sortBySize()));
1161
1162 KToggleAction* sortByDate = actionCollection()->add<KToggleAction>("sort_by_date");
1163 sortByDate->setText(i18nc("@action:inmenu Sort By", "Date"));
1164 connect(sortByDate, SIGNAL(triggered()), this, SLOT(sortByDate()));
1165
1166 KToggleAction* sortByPermissions = actionCollection()->add<KToggleAction>("sort_by_permissions");
1167 sortByPermissions->setText(i18nc("@action:inmenu Sort By", "Permissions"));
1168 connect(sortByPermissions, SIGNAL(triggered()), this, SLOT(sortByPermissions()));
1169
1170 KToggleAction* sortByOwner = actionCollection()->add<KToggleAction>("sort_by_owner");
1171 sortByOwner->setText(i18nc("@action:inmenu Sort By", "Owner"));
1172 connect(sortByOwner, SIGNAL(triggered()), this, SLOT(sortByOwner()));
1173
1174 KToggleAction* sortByGroup = actionCollection()->add<KToggleAction>("sort_by_group");
1175 sortByGroup->setText(i18nc("@action:inmenu Sort By", "Group"));
1176 connect(sortByGroup, SIGNAL(triggered()), this, SLOT(sortByGroup()));
1177
1178 KToggleAction* sortByType = actionCollection()->add<KToggleAction>("sort_by_type");
1179 sortByType->setText(i18nc("@action:inmenu Sort By", "Type"));
1180 connect(sortByType, SIGNAL(triggered()), this, SLOT(sortByType()));
1181
1182 KToggleAction* sortByRating = actionCollection()->add<KToggleAction>("sort_by_rating");
1183 sortByRating->setText(i18nc("@action:inmenu Sort By", "Rating"));
1184
1185 KToggleAction* sortByTags = actionCollection()->add<KToggleAction>("sort_by_tags");
1186 sortByTags->setText(i18nc("@action:inmenu Sort By", "Tags"));
1187
1188 #ifdef HAVE_NEPOMUK
1189 if (MetaDataWidget::metaDataAvailable()) {
1190 connect(sortByRating, SIGNAL(triggered()), this, SLOT(sortByRating()));
1191 connect(sortByTags, SIGNAL(triggered()), this, SLOT(sortByTags()));
1192 }
1193 else {
1194 sortByRating->setEnabled(false);
1195 sortByTags->setEnabled(false);
1196 }
1197 #else
1198 sortByRating->setEnabled(false);
1199 sortByTags->setEnabled(false);
1200 #endif
1201
1202 QActionGroup* sortGroup = new QActionGroup(this);
1203 sortGroup->addAction(sortByName);
1204 sortGroup->addAction(sortBySize);
1205 sortGroup->addAction(sortByDate);
1206 sortGroup->addAction(sortByPermissions);
1207 sortGroup->addAction(sortByOwner);
1208 sortGroup->addAction(sortByGroup);
1209 sortGroup->addAction(sortByType);
1210 sortGroup->addAction(sortByRating);
1211 sortGroup->addAction(sortByTags);
1212
1213 KToggleAction* sortDescending = actionCollection()->add<KToggleAction>("descending");
1214 sortDescending->setText(i18nc("@action:inmenu Sort", "Descending"));
1215 connect(sortDescending, SIGNAL(triggered()), this, SLOT(toggleSortOrder()));
1216
1217 KToggleAction* showInGroups = actionCollection()->add<KToggleAction>("show_in_groups");
1218 showInGroups->setText(i18nc("@action:inmenu View", "Show in Groups"));
1219 connect(showInGroups, SIGNAL(triggered()), this, SLOT(toggleSortCategorization()));
1220
1221 KToggleAction* showMimeInfo = actionCollection()->add<KToggleAction>("show_mime_info");
1222 showMimeInfo->setText(i18nc("@action:inmenu Additional information", "Type"));
1223 connect(showMimeInfo, SIGNAL(triggered()), this, SLOT(toggleMimeInfo()));
1224
1225 KToggleAction* showSizeInfo = actionCollection()->add<KToggleAction>("show_size_info");
1226 showSizeInfo->setText(i18nc("@action:inmenu Additional information", "Size"));
1227 connect(showSizeInfo, SIGNAL(triggered()), this, SLOT(toggleSizeInfo()));
1228
1229 KToggleAction* showDateInfo = actionCollection()->add<KToggleAction>("show_date_info");
1230 showDateInfo->setText(i18nc("@action:inmenu Additional information", "Date"));
1231 connect(showDateInfo, SIGNAL(triggered()), this, SLOT(toggleDateInfo()));
1232
1233 KToggleAction* showPreview = actionCollection()->add<KToggleAction>("show_preview");
1234 showPreview->setText(i18nc("@action:intoolbar", "Preview"));
1235 showPreview->setIcon(KIcon("fileview-preview"));
1236 connect(showPreview, SIGNAL(triggered()), this, SLOT(togglePreview()));
1237
1238 KToggleAction* showHiddenFiles = actionCollection()->add<KToggleAction>("show_hidden_files");
1239 showHiddenFiles->setText(i18nc("@action:inmenu View", "Show Hidden Files"));
1240 showHiddenFiles->setShortcut(Qt::ALT | Qt::Key_Period);
1241 connect(showHiddenFiles, SIGNAL(triggered()), this, SLOT(toggleShowHiddenFiles()));
1242
1243 QAction* split = actionCollection()->addAction("split_view");
1244 split->setShortcut(Qt::Key_F10);
1245 updateSplitAction();
1246 connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
1247
1248 QAction* reload = actionCollection()->addAction("reload");
1249 reload->setText(i18nc("@action:inmenu View", "Reload"));
1250 reload->setShortcut(Qt::Key_F5);
1251 reload->setIcon(KIcon("view-refresh"));
1252 connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
1253
1254 QAction* stop = actionCollection()->addAction("stop");
1255 stop->setText(i18nc("@action:inmenu View", "Stop"));
1256 stop->setIcon(KIcon("process-stop"));
1257 connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
1258
1259 // TODO: the URL navigator must emit a signal if the editable state has been
1260 // changed, so that the corresponding showFullLocation action is updated. Also
1261 // the naming "Show full Location" is currently confusing...
1262 KToggleAction* showFullLocation = actionCollection()->add<KToggleAction>("editable_location");
1263 showFullLocation->setText(i18nc("@action:inmenu Navigation Bar", "Show Full Location"));
1264 showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);
1265 connect(showFullLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
1266
1267 QAction* editLocation = actionCollection()->addAction("edit_location");
1268 editLocation->setText(i18nc("@action:inmenu Navigation Bar", "Edit Location"));
1269 editLocation->setShortcut(Qt::Key_F6);
1270 connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation()));
1271
1272 QAction* adjustViewProps = actionCollection()->addAction("view_properties");
1273 adjustViewProps->setText(i18nc("@action:inmenu View", "Adjust View Properties..."));
1274 connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties()));
1275
1276 // setup 'Go' menu
1277 KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
1278 KShortcut backShortcut = backAction->shortcut();
1279 backShortcut.setAlternate(Qt::Key_Backspace);
1280 backAction->setShortcut(backShortcut);
1281
1282 KStandardAction::forward(this, SLOT(goForward()), actionCollection());
1283 KStandardAction::up(this, SLOT(goUp()), actionCollection());
1284 KStandardAction::home(this, SLOT(goHome()), actionCollection());
1285
1286 // setup 'Tools' menu
1287 QAction* findFile = actionCollection()->addAction("find_file");
1288 findFile->setText(i18nc("@action:inmenu Tools", "Find File..."));
1289 findFile->setShortcut(Qt::CTRL | Qt::Key_F);
1290 findFile->setIcon(KIcon("file-find"));
1291 connect(findFile, SIGNAL(triggered()), this, SLOT(findFile()));
1292
1293 KToggleAction* showFilterBar = actionCollection()->add<KToggleAction>("show_filter_bar");
1294 showFilterBar->setText(i18nc("@action:inmenu Tools", "Show Filter Bar"));
1295 showFilterBar->setShortcut(Qt::CTRL | Qt::Key_I);
1296 connect(showFilterBar, SIGNAL(triggered()), this, SLOT(toggleFilterBarVisibility()));
1297
1298 QAction* compareFiles = actionCollection()->addAction("compare_files");
1299 compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files"));
1300 compareFiles->setIcon(KIcon("kompare"));
1301 compareFiles->setEnabled(false);
1302 connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
1303
1304 // setup 'Settings' menu
1305 KStandardAction::preferences(this, SLOT(editSettings()), actionCollection());
1306 }
1307
1308 void DolphinMainWindow::setupDockWidgets()
1309 {
1310 // setup "Information"
1311 QDockWidget* infoDock = new QDockWidget(i18nc("@title:window", "Information"));
1312 infoDock->setObjectName("infoDock");
1313 infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1314 SidebarPage* infoWidget = new InfoSidebarPage(infoDock);
1315 infoDock->setWidget(infoWidget);
1316
1317 infoDock->toggleViewAction()->setText(i18nc("@title:window", "Information"));
1318 infoDock->toggleViewAction()->setShortcut(Qt::Key_F11);
1319 actionCollection()->addAction("show_info_panel", infoDock->toggleViewAction());
1320
1321 addDockWidget(Qt::RightDockWidgetArea, infoDock);
1322 connect(this, SIGNAL(urlChanged(KUrl)),
1323 infoWidget, SLOT(setUrl(KUrl)));
1324 connect(this, SIGNAL(selectionChanged(KFileItemList)),
1325 infoWidget, SLOT(setSelection(KFileItemList)));
1326 connect(this, SIGNAL(requestItemInfo(KFileItem)),
1327 infoWidget, SLOT(requestDelayedItemInfo(KFileItem)));
1328
1329 // setup "Tree View"
1330 QDockWidget* treeViewDock = new QDockWidget(i18nc("@title:window", "Folders"));
1331 treeViewDock->setObjectName("treeViewDock");
1332 treeViewDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1333 TreeViewSidebarPage* treeWidget = new TreeViewSidebarPage(treeViewDock);
1334 treeViewDock->setWidget(treeWidget);
1335
1336 treeViewDock->toggleViewAction()->setText(i18nc("@title:window", "Folders"));
1337 treeViewDock->toggleViewAction()->setShortcut(Qt::Key_F7);
1338 actionCollection()->addAction("show_folders_panel", treeViewDock->toggleViewAction());
1339
1340 addDockWidget(Qt::LeftDockWidgetArea, treeViewDock);
1341 connect(this, SIGNAL(urlChanged(KUrl)),
1342 treeWidget, SLOT(setUrl(KUrl)));
1343 connect(treeWidget, SIGNAL(changeUrl(KUrl)),
1344 this, SLOT(changeUrl(KUrl)));
1345 connect(treeWidget, SIGNAL(changeSelection(KFileItemList)),
1346 this, SLOT(changeSelection(KFileItemList)));
1347 connect(treeWidget, SIGNAL(urlsDropped(KUrl::List, KUrl)),
1348 this, SLOT(dropUrls(KUrl::List, KUrl)));
1349
1350 // setup "Terminal"
1351 QDockWidget* terminalDock = new QDockWidget(i18nc("@title:window", "Terminal"));
1352 terminalDock->setObjectName("terminalDock");
1353 terminalDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
1354 SidebarPage* terminalWidget = new TerminalSidebarPage(terminalDock);
1355 terminalDock->setWidget(terminalWidget);
1356
1357 terminalDock->toggleViewAction()->setText(i18nc("@title:window", "Terminal"));
1358 terminalDock->toggleViewAction()->setShortcut(Qt::Key_F4);
1359 actionCollection()->addAction("show_terminal_panel", terminalDock->toggleViewAction());
1360
1361 addDockWidget(Qt::BottomDockWidgetArea, terminalDock);
1362 connect(this, SIGNAL(urlChanged(KUrl)),
1363 terminalWidget, SLOT(setUrl(KUrl)));
1364
1365 const bool firstRun = DolphinSettings::instance().generalSettings()->firstRun();
1366 if (firstRun) {
1367 infoDock->hide();
1368 treeViewDock->hide();
1369 terminalDock->hide();
1370 }
1371
1372 QDockWidget *placesDock = new QDockWidget(i18nc("@title:window", "Places"));
1373 placesDock->setObjectName("placesDock");
1374 placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1375 KFilePlacesView *listView = new KFilePlacesView(placesDock);
1376 placesDock->setWidget(listView);
1377 listView->setModel(DolphinSettings::instance().placesModel());
1378
1379 placesDock->toggleViewAction()->setText(i18nc("@title:window", "Places"));
1380 placesDock->toggleViewAction()->setShortcut(Qt::Key_F9);
1381 actionCollection()->addAction("show_places_panel", placesDock->toggleViewAction());
1382
1383 addDockWidget(Qt::LeftDockWidgetArea, placesDock);
1384 connect(listView, SIGNAL(urlChanged(KUrl)),
1385 this, SLOT(changeUrl(KUrl)));
1386 connect(this, SIGNAL(urlChanged(KUrl)),
1387 listView, SLOT(setUrl(KUrl)));
1388 }
1389
1390 void DolphinMainWindow::updateHistory()
1391 {
1392 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
1393 const int index = urlNavigator->historyIndex();
1394
1395 QAction* backAction = actionCollection()->action("go_back");
1396 if (backAction != 0) {
1397 backAction->setEnabled(index < urlNavigator->historySize() - 1);
1398 }
1399
1400 QAction* forwardAction = actionCollection()->action("go_forward");
1401 if (forwardAction != 0) {
1402 forwardAction->setEnabled(index > 0);
1403 }
1404 }
1405
1406 void DolphinMainWindow::updateEditActions()
1407 {
1408 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
1409 if (list.isEmpty()) {
1410 stateChanged("has_no_selection");
1411 } else {
1412 stateChanged("has_selection");
1413
1414 QAction* renameAction = actionCollection()->action("rename");
1415 if (renameAction != 0) {
1416 renameAction->setEnabled(list.count() >= 1);
1417 }
1418
1419 bool enableMoveToTrash = true;
1420
1421 KFileItemList::const_iterator it = list.begin();
1422 const KFileItemList::const_iterator end = list.end();
1423 while (it != end) {
1424 const KUrl& url = (*it).url();
1425 // only enable the 'Move to Trash' action for local files
1426 if (!url.isLocalFile()) {
1427 enableMoveToTrash = false;
1428 }
1429 ++it;
1430 }
1431
1432 QAction* moveToTrashAction = actionCollection()->action("move_to_trash");
1433 moveToTrashAction->setEnabled(enableMoveToTrash);
1434 }
1435 updatePasteAction();
1436 }
1437
1438 void DolphinMainWindow::updateViewActions()
1439 {
1440 const DolphinView* view = m_activeViewContainer->view();
1441 QAction* zoomInAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::ZoomIn));
1442 if (zoomInAction != 0) {
1443 zoomInAction->setEnabled(view->isZoomInPossible());
1444 }
1445
1446 QAction* zoomOutAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::ZoomOut));
1447 if (zoomOutAction != 0) {
1448 zoomOutAction->setEnabled(view->isZoomOutPossible());
1449 }
1450
1451 QAction* action = actionCollection()->action(view->currentViewModeActionName());
1452 if (action != 0) {
1453 KToggleAction* toggleAction = static_cast<KToggleAction*>(action);
1454 toggleAction->setChecked(true);
1455 }
1456
1457 slotSortingChanged(view->sorting());
1458 slotSortOrderChanged(view->sortOrder());
1459 slotCategorizedSortingChanged();
1460 slotAdditionalInfoChanged(view->additionalInfo());
1461
1462 KToggleAction* showFilterBarAction =
1463 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
1464 showFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
1465
1466 KToggleAction* showPreviewAction =
1467 static_cast<KToggleAction*>(actionCollection()->action("show_preview"));
1468 showPreviewAction->setChecked(view->showPreview());
1469
1470 KToggleAction* showHiddenFilesAction =
1471 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
1472 showHiddenFilesAction->setChecked(view->showHiddenFiles());
1473
1474 updateSplitAction();
1475
1476 KToggleAction* editableLocactionAction =
1477 static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
1478 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
1479 editableLocactionAction->setChecked(urlNavigator->isUrlEditable());
1480 }
1481
1482 void DolphinMainWindow::updateGoActions()
1483 {
1484 QAction* goUpAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Up));
1485 const KUrl& currentUrl = m_activeViewContainer->url();
1486 goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
1487 }
1488
1489 void DolphinMainWindow::copyUrls(const KUrl::List& source, const KUrl& dest)
1490 {
1491 KonqOperations::copy(this, KonqOperations::COPY, source, dest);
1492 m_undoCommandTypes.append(KonqUndoManager::COPY);
1493 }
1494
1495 void DolphinMainWindow::moveUrls(const KUrl::List& source, const KUrl& dest)
1496 {
1497 KonqOperations::copy(this, KonqOperations::MOVE, source, dest);
1498 m_undoCommandTypes.append(KonqUndoManager::MOVE);
1499 }
1500
1501 void DolphinMainWindow::linkUrls(const KUrl::List& source, const KUrl& dest)
1502 {
1503 KonqOperations::copy(this, KonqOperations::LINK, source, dest);
1504 m_undoCommandTypes.append(KonqUndoManager::LINK);
1505 }
1506
1507 void DolphinMainWindow::clearStatusBar()
1508 {
1509 m_activeViewContainer->statusBar()->clear();
1510 }
1511
1512 void DolphinMainWindow::connectViewSignals(int viewIndex)
1513 {
1514 DolphinViewContainer* container = m_viewContainer[viewIndex];
1515 connect(container, SIGNAL(showFilterBarChanged(bool)),
1516 this, SLOT(updateFilterBarAction(bool)));
1517
1518 DolphinView* view = container->view();
1519 connect(view, SIGNAL(modeChanged()),
1520 this, SLOT(slotViewModeChanged()));
1521 connect(view, SIGNAL(showPreviewChanged()),
1522 this, SLOT(slotShowPreviewChanged()));
1523 connect(view, SIGNAL(showHiddenFilesChanged()),
1524 this, SLOT(slotShowHiddenFilesChanged()));
1525 connect(view, SIGNAL(categorizedSortingChanged()),
1526 this, SLOT(slotCategorizedSortingChanged()));
1527 connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),
1528 this, SLOT(slotSortingChanged(DolphinView::Sorting)));
1529 connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)),
1530 this, SLOT(slotSortOrderChanged(Qt::SortOrder)));
1531 connect(view, SIGNAL(additionalInfoChanged(KFileItemDelegate::InformationList)),
1532 this, SLOT(slotAdditionalInfoChanged(KFileItemDelegate::InformationList)));
1533 connect(view, SIGNAL(selectionChanged(KFileItemList)),
1534 this, SLOT(slotSelectionChanged(KFileItemList)));
1535 connect(view, SIGNAL(requestItemInfo(KFileItem)),
1536 this, SLOT(slotRequestItemInfo(KFileItem)));
1537 connect(view, SIGNAL(activated()),
1538 this, SLOT(toggleActiveView()));
1539
1540 const KUrlNavigator* navigator = container->urlNavigator();
1541 connect(navigator, SIGNAL(urlChanged(const KUrl&)),
1542 this, SLOT(changeUrl(const KUrl&)));
1543 connect(navigator, SIGNAL(historyChanged()),
1544 this, SLOT(slotHistoryChanged()));
1545 }
1546
1547 void DolphinMainWindow::updateSplitAction()
1548 {
1549 QAction* splitAction = actionCollection()->action("split_view");
1550 if (m_viewContainer[SecondaryView] != 0) {
1551 if (m_activeViewContainer == m_viewContainer[PrimaryView]) {
1552 splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
1553 splitAction->setIcon(KIcon("fileview-close-right"));
1554 } else {
1555 splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
1556 splitAction->setIcon(KIcon("fileview-close-left"));
1557 }
1558 } else {
1559 splitAction->setText(i18nc("@action:intoolbar Split view", "Split"));
1560 splitAction->setIcon(KIcon("fileview-split"));
1561 }
1562 }
1563
1564 void DolphinMainWindow::toggleAdditionalInfo(const char* actionName,
1565 KFileItemDelegate::Information info)
1566 {
1567 clearStatusBar();
1568
1569 DolphinView* view = m_activeViewContainer->view();
1570 KFileItemDelegate::InformationList list = view->additionalInfo();
1571
1572 const bool show = actionCollection()->action(actionName)->isChecked();
1573
1574 const int index = list.indexOf(info);
1575 const bool containsInfo = (index >= 0);
1576 if (show && !containsInfo) {
1577 list.append(info);
1578 view->setAdditionalInfo(list);
1579 } else if (!show && containsInfo) {
1580 list.removeAt(index);
1581 view->setAdditionalInfo(list);
1582 Q_ASSERT(list.indexOf(info) < 0);
1583 }
1584 }
1585
1586 DolphinMainWindow::UndoUiInterface::UndoUiInterface(DolphinMainWindow* mainWin) :
1587 KonqUndoManager::UiInterface(mainWin),
1588 m_mainWin(mainWin)
1589 {
1590 Q_ASSERT(m_mainWin != 0);
1591 }
1592
1593 DolphinMainWindow::UndoUiInterface::~UndoUiInterface()
1594 {
1595 }
1596
1597 void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)
1598 {
1599 DolphinStatusBar* statusBar = m_mainWin->activeViewContainer()->statusBar();
1600 statusBar->setMessage(job->errorString(), DolphinStatusBar::Error);
1601 }
1602
1603 #include "dolphinmainwindow.moc"