]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinmainwindow.cpp
Forwardport 773570:
[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 #include "dolphinviewactionhandler.h"
24 #include "dolphindropcontroller.h"
25
26 #include <config-nepomuk.h>
27
28 #include "dolphinapplication.h"
29 #include "dolphinfileplacesview.h"
30 #include "dolphinnewmenu.h"
31 #include "dolphinsettings.h"
32 #include "dolphinsettingsdialog.h"
33 #include "dolphinstatusbar.h"
34 #include "dolphinviewcontainer.h"
35 #include "infosidebarpage.h"
36 #include "metadatawidget.h"
37 #include "mainwindowadaptor.h"
38 #include "terminalsidebarpage.h"
39 #include "treeviewsidebarpage.h"
40 #include "viewpropertiesdialog.h"
41 #include "viewproperties.h"
42
43 #include "dolphin_generalsettings.h"
44 #include "dolphin_iconsmodesettings.h"
45
46 #include <kaction.h>
47 #include <kactioncollection.h>
48 #include <kconfig.h>
49 #include <kdesktopfile.h>
50 #include <kdeversion.h>
51 #include <kfiledialog.h>
52 #include <kfileplacesmodel.h>
53 #include <kglobal.h>
54 #include <kicon.h>
55 #include <kiconloader.h>
56 #include <kio/netaccess.h>
57 #include <kinputdialog.h>
58 #include <klocale.h>
59 #include <kmenu.h>
60 #include <kmenubar.h>
61 #include <kmessagebox.h>
62 #include <kurlnavigator.h>
63 #include <konqmimedata.h>
64 #include <kpropertiesdialog.h>
65 #include <kprotocolinfo.h>
66 #include <ktoggleaction.h>
67 #include <krun.h>
68 #include <kshell.h>
69 #include <kstandarddirs.h>
70 #include <kstatusbar.h>
71 #include <kstandardaction.h>
72 #include <kurl.h>
73 #include <kurlcombobox.h>
74
75 #include <QKeyEvent>
76 #include <QClipboard>
77 #include <QLineEdit>
78 #include <QSplitter>
79 #include <QDockWidget>
80
81 DolphinMainWindow::DolphinMainWindow(int id) :
82 KXmlGuiWindow(0),
83 m_newMenu(0),
84 m_showMenuBar(0),
85 m_splitter(0),
86 m_activeViewContainer(0),
87 m_id(id)
88 {
89 setObjectName("Dolphin");
90 m_viewContainer[PrimaryView] = 0;
91 m_viewContainer[SecondaryView] = 0;
92
93 new MainWindowAdaptor(this);
94 QDBusConnection::sessionBus().registerObject(QString("/dolphin/MainWindow%1").arg(m_id), this);
95
96 KonqFileUndoManager::incRef();
97
98 KonqFileUndoManager* undoManager = KonqFileUndoManager::self();
99 undoManager->setUiInterface(new UndoUiInterface(this));
100
101 connect(undoManager, SIGNAL(undoAvailable(bool)),
102 this, SLOT(slotUndoAvailable(bool)));
103 connect(undoManager, SIGNAL(undoTextChanged(const QString&)),
104 this, SLOT(slotUndoTextChanged(const QString&)));
105 connect(DolphinSettings::instance().placesModel(), SIGNAL(errorMessage(const QString&)),
106 this, SLOT(slotHandlePlacesError(const QString&)));
107 }
108
109 DolphinMainWindow::~DolphinMainWindow()
110 {
111 KonqFileUndoManager::decRef();
112 DolphinApplication::app()->removeMainWindow(this);
113 }
114
115 void DolphinMainWindow::toggleViews()
116 {
117 if (m_viewContainer[SecondaryView] == 0) {
118 return;
119 }
120
121 // move secondary view from the last position of the splitter
122 // to the first position
123 m_splitter->insertWidget(0, m_viewContainer[SecondaryView]);
124
125 DolphinViewContainer* container = m_viewContainer[PrimaryView];
126 m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView];
127 m_viewContainer[SecondaryView] = container;
128 }
129
130 void DolphinMainWindow::slotDoingOperation(KonqFileUndoManager::CommandType commandType)
131 {
132 clearStatusBar();
133 m_undoCommandTypes.append(commandType);
134 }
135
136 void DolphinMainWindow::refreshViews()
137 {
138 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
139
140 // remember the current active view, as because of
141 // the refreshing the active view might change to
142 // the secondary view
143 DolphinViewContainer* activeViewContainer = m_activeViewContainer;
144
145 m_viewContainer[PrimaryView]->view()->refresh();
146 if (m_viewContainer[SecondaryView] != 0) {
147 m_viewContainer[SecondaryView]->view()->refresh();
148 }
149
150 setActiveViewContainer(activeViewContainer);
151 }
152
153 void DolphinMainWindow::dropUrls(const KUrl::List& urls,
154 const KUrl& destination)
155 {
156 DolphinDropController dropController(this);
157 connect(&dropController, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)),
158 this, SLOT(slotDoingOperation(KonqFileUndoManager::CommandType)));
159 dropController.dropUrls(urls, destination);
160 }
161
162 void DolphinMainWindow::changeUrl(const KUrl& url)
163 {
164 DolphinViewContainer* view = activeViewContainer();
165 if (view != 0) {
166 view->setUrl(url);
167 updateEditActions();
168 updateViewActions();
169 updateGoActions();
170 setCaption(url.fileName());
171 emit urlChanged(url);
172 }
173 }
174
175 void DolphinMainWindow::changeSelection(const KFileItemList& selection)
176 {
177 activeViewContainer()->view()->changeSelection(selection);
178 }
179
180 void DolphinMainWindow::slotViewModeChanged()
181 {
182 updateViewActions();
183 }
184
185 void DolphinMainWindow::slotSortingChanged(DolphinView::Sorting sorting)
186 {
187 QAction* action = 0;
188 switch (sorting) {
189 case DolphinView::SortByName:
190 action = actionCollection()->action("sort_by_name");
191 break;
192 case DolphinView::SortBySize:
193 action = actionCollection()->action("sort_by_size");
194 break;
195 case DolphinView::SortByDate:
196 action = actionCollection()->action("sort_by_date");
197 break;
198 case DolphinView::SortByPermissions:
199 action = actionCollection()->action("sort_by_permissions");
200 break;
201 case DolphinView::SortByOwner:
202 action = actionCollection()->action("sort_by_owner");
203 break;
204 case DolphinView::SortByGroup:
205 action = actionCollection()->action("sort_by_group");
206 break;
207 case DolphinView::SortByType:
208 action = actionCollection()->action("sort_by_type");
209 break;
210 #ifdef HAVE_NEPOMUK
211 case DolphinView::SortByRating:
212 action = actionCollection()->action("sort_by_rating");
213 break;
214 case DolphinView::SortByTags:
215 action = actionCollection()->action("sort_by_tags");
216 break;
217 #endif
218 default:
219 break;
220 }
221
222 if (action != 0) {
223 action->setChecked(true);
224 }
225 }
226
227 void DolphinMainWindow::slotEditableStateChanged(bool editable)
228 {
229 KToggleAction* editableLocationAction =
230 static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
231 editableLocationAction->setChecked(editable);
232 }
233
234 void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
235 {
236 updateEditActions();
237
238 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
239 int selectedUrlsCount = m_viewContainer[PrimaryView]->view()->selectedUrls().count();
240 if (m_viewContainer[SecondaryView] != 0) {
241 selectedUrlsCount += m_viewContainer[SecondaryView]->view()->selectedUrls().count();
242 }
243
244 QAction* compareFilesAction = actionCollection()->action("compare_files");
245 if (selectedUrlsCount == 2) {
246 const bool kompareInstalled = !KGlobal::dirs()->findExe("kompare").isEmpty();
247 compareFilesAction->setEnabled(selectedUrlsCount == 2 && kompareInstalled);
248 } else {
249 compareFilesAction->setEnabled(false);
250 }
251
252 m_activeViewContainer->updateStatusBar();
253
254 emit selectionChanged(selection);
255 }
256
257 void DolphinMainWindow::slotRequestItemInfo(const KFileItem& item)
258 {
259 emit requestItemInfo(item);
260 }
261
262 void DolphinMainWindow::slotHistoryChanged()
263 {
264 updateHistory();
265 }
266
267 void DolphinMainWindow::updateFilterBarAction(bool show)
268 {
269 QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
270 showFilterBarAction->setChecked(show);
271 }
272
273 void DolphinMainWindow::openNewMainWindow()
274 {
275 DolphinApplication::app()->createMainWindow()->show();
276 }
277
278 void DolphinMainWindow::toggleActiveView()
279 {
280 if (m_viewContainer[SecondaryView] == 0) {
281 // only one view is available
282 return;
283 }
284
285 Q_ASSERT(m_activeViewContainer != 0);
286 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
287
288 DolphinViewContainer* left = m_viewContainer[PrimaryView];
289 DolphinViewContainer* right = m_viewContainer[SecondaryView];
290 setActiveViewContainer(m_activeViewContainer == right ? left : right);
291 }
292
293 void DolphinMainWindow::closeEvent(QCloseEvent* event)
294 {
295 DolphinSettings& settings = DolphinSettings::instance();
296 GeneralSettings* generalSettings = settings.generalSettings();
297 generalSettings->setFirstRun(false);
298
299 settings.save();
300
301 KXmlGuiWindow::closeEvent(event);
302 }
303
304 void DolphinMainWindow::saveProperties(KConfigGroup& group)
305 {
306 DolphinViewContainer* cont = m_viewContainer[PrimaryView];
307 group.writeEntry("Primary Url", cont->url().url());
308 group.writeEntry("Primary Editable Url", cont->isUrlEditable());
309
310 cont = m_viewContainer[SecondaryView];
311 if (cont != 0) {
312 group.writeEntry("Secondary Url", cont->url().url());
313 group.writeEntry("Secondary Editable Url", cont->isUrlEditable());
314 }
315 }
316
317 void DolphinMainWindow::readProperties(const KConfigGroup& group)
318 {
319 DolphinViewContainer* cont = m_viewContainer[PrimaryView];
320
321 cont->setUrl(group.readEntry("Primary Url"));
322 bool editable = group.readEntry("Primary Editable Url", false);
323 cont->urlNavigator()->setUrlEditable(editable);
324
325 cont = m_viewContainer[SecondaryView];
326 const QString secondaryUrl = group.readEntry("Secondary Url");
327 if (!secondaryUrl.isEmpty()) {
328 if (cont == 0) {
329 // a secondary view should be shown, but no one is available
330 // currently -> create a new view
331 toggleSplitView();
332 cont = m_viewContainer[SecondaryView];
333 Q_ASSERT(cont != 0);
334 }
335
336 cont->setUrl(secondaryUrl);
337 bool editable = group.readEntry("Secondary Editable Url", false);
338 cont->urlNavigator()->setUrlEditable(editable);
339 } else if (cont != 0) {
340 // no secondary view should be shown, but the default setting shows
341 // one already -> close the view
342 toggleSplitView();
343 }
344 }
345
346 void DolphinMainWindow::updateNewMenu()
347 {
348 m_newMenu->slotCheckUpToDate();
349 m_newMenu->setPopupFiles(activeViewContainer()->url());
350 }
351
352 void DolphinMainWindow::properties()
353 {
354 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
355
356 KPropertiesDialog *dialog = new KPropertiesDialog(list, this);
357 dialog->setAttribute(Qt::WA_DeleteOnClose);
358 dialog->show();
359 dialog->raise();
360 dialog->activateWindow();
361 }
362
363 void DolphinMainWindow::quit()
364 {
365 close();
366 }
367
368 void DolphinMainWindow::slotHandlePlacesError(const QString &message)
369 {
370 if (!message.isEmpty()) {
371 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
372 statusBar->setMessage(message, DolphinStatusBar::Error);
373 }
374 }
375
376 void DolphinMainWindow::slotUndoAvailable(bool available)
377 {
378 QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
379 if (undoAction != 0) {
380 undoAction->setEnabled(available);
381 }
382
383 if (available && (m_undoCommandTypes.count() > 0)) {
384 const KonqFileUndoManager::CommandType command = m_undoCommandTypes.takeFirst();
385 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
386 switch (command) {
387 case KonqFileUndoManager::COPY:
388 statusBar->setMessage(i18nc("@info:status", "Copy operation completed."),
389 DolphinStatusBar::OperationCompleted);
390 break;
391 case KonqFileUndoManager::MOVE:
392 statusBar->setMessage(i18nc("@info:status", "Move operation completed."),
393 DolphinStatusBar::OperationCompleted);
394 break;
395 case KonqFileUndoManager::LINK:
396 statusBar->setMessage(i18nc("@info:status", "Link operation completed."),
397 DolphinStatusBar::OperationCompleted);
398 break;
399 case KonqFileUndoManager::TRASH:
400 statusBar->setMessage(i18nc("@info:status", "Move to trash operation completed."),
401 DolphinStatusBar::OperationCompleted);
402 break;
403 case KonqFileUndoManager::RENAME:
404 statusBar->setMessage(i18nc("@info:status", "Renaming operation completed."),
405 DolphinStatusBar::OperationCompleted);
406 break;
407
408 case KonqFileUndoManager::MKDIR:
409 statusBar->setMessage(i18nc("@info:status", "Created folder."),
410 DolphinStatusBar::OperationCompleted);
411 break;
412
413 default:
414 break;
415 }
416
417 }
418 }
419
420 void DolphinMainWindow::slotUndoTextChanged(const QString& text)
421 {
422 QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
423 if (undoAction != 0) {
424 undoAction->setText(text);
425 }
426 }
427
428 void DolphinMainWindow::undo()
429 {
430 clearStatusBar();
431 KonqFileUndoManager::self()->undo();
432 }
433
434 void DolphinMainWindow::cut()
435 {
436 m_activeViewContainer->view()->cutSelectedItems();
437 }
438
439 void DolphinMainWindow::copy()
440 {
441 m_activeViewContainer->view()->copySelectedItems();
442 }
443
444 void DolphinMainWindow::paste()
445 {
446 m_activeViewContainer->view()->paste();
447 }
448
449 void DolphinMainWindow::updatePasteAction()
450 {
451 QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
452 if (pasteAction == 0) {
453 return;
454 }
455
456 QPair<bool, QString> pasteInfo = m_activeViewContainer->view()->pasteInfo();
457 pasteAction->setEnabled(pasteInfo.first);
458 pasteAction->setText(pasteInfo.second);
459 }
460
461 void DolphinMainWindow::selectAll()
462 {
463 clearStatusBar();
464
465 // if the URL navigator is editable and focused, select the whole
466 // URL instead of all items of the view
467
468 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
469 QLineEdit* lineEdit = urlNavigator->editor()->lineEdit();
470 const bool selectUrl = urlNavigator->isUrlEditable() &&
471 lineEdit->hasFocus();
472 if (selectUrl) {
473 lineEdit->selectAll();
474 } else {
475 m_activeViewContainer->view()->selectAll();
476 }
477 }
478
479 void DolphinMainWindow::invertSelection()
480 {
481 clearStatusBar();
482 m_activeViewContainer->view()->invertSelection();
483 }
484
485 void DolphinMainWindow::setViewMode(QAction* action)
486 {
487 const DolphinView::Mode mode = action->data().value<DolphinView::Mode>();
488 m_activeViewContainer->view()->setMode(mode);
489 }
490
491 void DolphinMainWindow::sortByName()
492 {
493 m_activeViewContainer->view()->setSorting(DolphinView::SortByName);
494 }
495
496 void DolphinMainWindow::sortBySize()
497 {
498 m_activeViewContainer->view()->setSorting(DolphinView::SortBySize);
499 }
500
501 void DolphinMainWindow::sortByDate()
502 {
503 m_activeViewContainer->view()->setSorting(DolphinView::SortByDate);
504 }
505
506 void DolphinMainWindow::sortByPermissions()
507 {
508 m_activeViewContainer->view()->setSorting(DolphinView::SortByPermissions);
509 }
510
511 void DolphinMainWindow::sortByOwner()
512 {
513 m_activeViewContainer->view()->setSorting(DolphinView::SortByOwner);
514 }
515
516 void DolphinMainWindow::sortByGroup()
517 {
518 m_activeViewContainer->view()->setSorting(DolphinView::SortByGroup);
519 }
520
521 void DolphinMainWindow::sortByType()
522 {
523 m_activeViewContainer->view()->setSorting(DolphinView::SortByType);
524 }
525
526 void DolphinMainWindow::sortByRating()
527 {
528 #ifdef HAVE_NEPOMUK
529 m_activeViewContainer->view()->setSorting(DolphinView::SortByRating);
530 #endif
531 }
532
533 void DolphinMainWindow::sortByTags()
534 {
535 #ifdef HAVE_NEPOMUK
536 m_activeViewContainer->view()->setSorting(DolphinView::SortByTags);
537 #endif
538 }
539
540 void DolphinMainWindow::toggleSplitView()
541 {
542 if (m_viewContainer[SecondaryView] == 0) {
543 // create a secondary view
544 const int newWidth = (m_viewContainer[PrimaryView]->width() - m_splitter->handleWidth()) / 2;
545
546 const DolphinView* view = m_viewContainer[PrimaryView]->view();
547 m_viewContainer[SecondaryView] = new DolphinViewContainer(this, 0, view->rootUrl());
548 connectViewSignals(SecondaryView);
549 m_splitter->addWidget(m_viewContainer[SecondaryView]);
550 m_splitter->setSizes(QList<int>() << newWidth << newWidth);
551 m_viewContainer[SecondaryView]->view()->reload();
552 m_viewContainer[SecondaryView]->setActive(false);
553 m_viewContainer[SecondaryView]->show();
554 } else if (m_activeViewContainer == m_viewContainer[PrimaryView]) {
555 // remove secondary view
556 m_viewContainer[SecondaryView]->close();
557 m_viewContainer[SecondaryView]->deleteLater();
558 m_viewContainer[SecondaryView] = 0;
559 } else {
560 // The secondary view is active, hence from a users point of view
561 // the content of the secondary view should be moved to the primary view.
562 // From an implementation point of view it is more efficient to close
563 // the primary view and exchange the internal pointers afterwards.
564 m_viewContainer[PrimaryView]->close();
565 m_viewContainer[PrimaryView]->deleteLater();
566 m_viewContainer[PrimaryView] = m_viewContainer[SecondaryView];
567 m_viewContainer[SecondaryView] = 0;
568 }
569
570 setActiveViewContainer(m_viewContainer[PrimaryView]);
571 updateViewActions();
572 emit activeViewChanged(); // TODO unused; remove?
573 }
574
575 void DolphinMainWindow::reloadView()
576 {
577 clearStatusBar();
578 m_activeViewContainer->view()->reload();
579 }
580
581 void DolphinMainWindow::stopLoading()
582 {
583 }
584
585 void DolphinMainWindow::toggleFilterBarVisibility(bool show)
586 {
587 m_activeViewContainer->showFilterBar(show);
588 }
589
590 void DolphinMainWindow::toggleEditLocation()
591 {
592 clearStatusBar();
593
594 QAction* action = actionCollection()->action("editable_location");
595 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
596 urlNavigator->setUrlEditable(action->isChecked());
597 }
598
599 void DolphinMainWindow::editLocation()
600 {
601 KUrlNavigator* navigator = m_activeViewContainer->urlNavigator();
602 navigator->setUrlEditable(true);
603 navigator->setFocus();
604 }
605
606 void DolphinMainWindow::adjustViewProperties()
607 {
608 clearStatusBar();
609 ViewPropertiesDialog dlg(m_activeViewContainer->view());
610 dlg.exec();
611 }
612
613 void DolphinMainWindow::goBack()
614 {
615 clearStatusBar();
616 m_activeViewContainer->urlNavigator()->goBack();
617 }
618
619 void DolphinMainWindow::goForward()
620 {
621 clearStatusBar();
622 m_activeViewContainer->urlNavigator()->goForward();
623 }
624
625 void DolphinMainWindow::goUp()
626 {
627 clearStatusBar();
628 m_activeViewContainer->urlNavigator()->goUp();
629 }
630
631 void DolphinMainWindow::goHome()
632 {
633 clearStatusBar();
634 m_activeViewContainer->urlNavigator()->goHome();
635 }
636
637 void DolphinMainWindow::findFile()
638 {
639 KRun::run("kfind", m_activeViewContainer->url(), this);
640 }
641
642 void DolphinMainWindow::compareFiles()
643 {
644 // The method is only invoked if exactly 2 files have
645 // been selected. The selected files may be:
646 // - both in the primary view
647 // - both in the secondary view
648 // - one in the primary view and the other in the secondary
649 // view
650 Q_ASSERT(m_viewContainer[PrimaryView] != 0);
651
652 KUrl urlA;
653 KUrl urlB;
654 KUrl::List urls = m_viewContainer[PrimaryView]->view()->selectedUrls();
655
656 switch (urls.count()) {
657 case 0: {
658 Q_ASSERT(m_viewContainer[SecondaryView] != 0);
659 urls = m_viewContainer[SecondaryView]->view()->selectedUrls();
660 Q_ASSERT(urls.count() == 2);
661 urlA = urls[0];
662 urlB = urls[1];
663 break;
664 }
665
666 case 1: {
667 urlA = urls[0];
668 Q_ASSERT(m_viewContainer[SecondaryView] != 0);
669 urls = m_viewContainer[SecondaryView]->view()->selectedUrls();
670 Q_ASSERT(urls.count() == 1);
671 urlB = urls[0];
672 break;
673 }
674
675 case 2: {
676 urlA = urls[0];
677 urlB = urls[1];
678 break;
679 }
680
681 default: {
682 // may not happen: compareFiles may only get invoked if 2
683 // files are selected
684 Q_ASSERT(false);
685 }
686 }
687
688 QString command("kompare -c \"");
689 command.append(urlA.pathOrUrl());
690 command.append("\" \"");
691 command.append(urlB.pathOrUrl());
692 command.append('\"');
693 KRun::runCommand(command, "Kompare", "kompare", this);
694
695 }
696
697 void DolphinMainWindow::toggleShowMenuBar()
698 {
699 const bool visible = menuBar()->isVisible();
700 menuBar()->setVisible(!visible);
701 }
702
703 void DolphinMainWindow::editSettings()
704 {
705 DolphinSettingsDialog dialog(this);
706 dialog.exec();
707 }
708
709 void DolphinMainWindow::init()
710 {
711 // Check whether Dolphin runs the first time. If yes then
712 // a proper default window size is given at the end of DolphinMainWindow::init().
713 GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
714 const bool firstRun = generalSettings->firstRun();
715 if (firstRun) {
716 generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
717 }
718
719 setAcceptDrops(true);
720
721 m_splitter = new QSplitter(this);
722
723 DolphinSettings& settings = DolphinSettings::instance();
724
725 setupActions();
726
727 const KUrl& homeUrl = settings.generalSettings()->homeUrl();
728 setCaption(homeUrl.fileName());
729 m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
730 connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar()));
731 ViewProperties props(homeUrl);
732 m_viewContainer[PrimaryView] = new DolphinViewContainer(this,
733 m_splitter,
734 homeUrl);
735
736 m_activeViewContainer = m_viewContainer[PrimaryView];
737 connectViewSignals(PrimaryView);
738 DolphinView* view = m_viewContainer[PrimaryView]->view();
739 view->reload();
740 m_viewContainer[PrimaryView]->show();
741 m_actionHandler->setCurrentView(view);
742
743 setCentralWidget(m_splitter);
744 setupDockWidgets();
745
746 setupGUI(Keys | Save | Create | ToolBar);
747 createGUI();
748
749 stateChanged("new_file");
750 setAutoSaveSettings();
751
752 QClipboard* clipboard = QApplication::clipboard();
753 connect(clipboard, SIGNAL(dataChanged()),
754 this, SLOT(updatePasteAction()));
755 updatePasteAction();
756 updateGoActions();
757
758 if (generalSettings->splitView()) {
759 toggleSplitView();
760 }
761 updateViewActions();
762
763 if (firstRun) {
764 // assure a proper default size if Dolphin runs the first time
765 resize(700, 500);
766 }
767
768 emit urlChanged(homeUrl);
769 }
770
771 void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer)
772 {
773 Q_ASSERT(viewContainer != 0);
774 Q_ASSERT((viewContainer == m_viewContainer[PrimaryView]) || (viewContainer == m_viewContainer[SecondaryView]));
775 if (m_activeViewContainer == viewContainer) {
776 return;
777 }
778
779 m_activeViewContainer->setActive(false);
780 m_activeViewContainer = viewContainer;
781 m_activeViewContainer->setActive(true);
782
783 updateHistory();
784 updateEditActions();
785 updateViewActions();
786 updateGoActions();
787
788 const KUrl& url = m_activeViewContainer->url();
789 setCaption(url.fileName());
790
791 m_actionHandler->setCurrentView(viewContainer->view());
792
793 emit activeViewChanged(); // TODO unused; remove?
794 emit urlChanged(url);
795 }
796
797 void DolphinMainWindow::setupActions()
798 {
799 // setup 'File' menu
800 m_newMenu = new DolphinNewMenu(this);
801 KMenu* menu = m_newMenu->menu();
802 menu->setTitle(i18nc("@title:menu", "Create New"));
803 menu->setIcon(KIcon("document-new"));
804 connect(menu, SIGNAL(aboutToShow()),
805 this, SLOT(updateNewMenu()));
806
807 KAction* newWindow = actionCollection()->addAction("new_window");
808 newWindow->setIcon(KIcon("window-new"));
809 newWindow->setText(i18nc("@action:inmenu File", "New &Window"));
810 newWindow->setShortcut(Qt::CTRL | Qt::Key_N);
811 connect(newWindow, SIGNAL(triggered()), this, SLOT(openNewMainWindow()));
812
813 KAction* properties = actionCollection()->addAction("properties");
814 properties->setText(i18nc("@action:inmenu File", "Properties"));
815 properties->setShortcut(Qt::ALT | Qt::Key_Return);
816 connect(properties, SIGNAL(triggered()), this, SLOT(properties()));
817
818 KStandardAction::quit(this, SLOT(quit()), actionCollection());
819
820 // setup 'Edit' menu
821 KStandardAction::undo(this,
822 SLOT(undo()),
823 actionCollection());
824
825 // need to remove shift+del from cut action, else the shortcut for deletejob
826 // doesn't work
827 KAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection());
828 KShortcut cutShortcut = cut->shortcut();
829 cutShortcut.remove(Qt::SHIFT + Qt::Key_Delete, KShortcut::KeepEmpty);
830 cut->setShortcut(cutShortcut);
831 KStandardAction::copy(this, SLOT(copy()), actionCollection());
832 KStandardAction::paste(this, SLOT(paste()), actionCollection());
833
834 KAction* selectAll = actionCollection()->addAction("select_all");
835 selectAll->setText(i18nc("@action:inmenu Edit", "Select All"));
836 selectAll->setShortcut(Qt::CTRL + Qt::Key_A);
837 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
838
839 KAction* invertSelection = actionCollection()->addAction("invert_selection");
840 invertSelection->setText(i18nc("@action:inmenu Edit", "Invert Selection"));
841 invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
842 connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
843
844 // setup 'View' menu
845
846 KToggleAction* iconsView = DolphinView::iconsModeAction(actionCollection());
847 KToggleAction* detailsView = DolphinView::detailsModeAction(actionCollection());
848 KToggleAction* columnView = DolphinView::columnsModeAction(actionCollection());
849
850 QActionGroup* viewModeGroup = new QActionGroup(this);
851 viewModeGroup->addAction(iconsView);
852 viewModeGroup->addAction(detailsView);
853 viewModeGroup->addAction(columnView);
854 connect(viewModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(setViewMode(QAction*)));
855
856 //QActionGroup* sortActionGroup = DolphinView::createSortActionGroup(actionCollection());
857 //connect(sortActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(sortActionGroupTriggered(QAction*)));
858
859 // TODO use a QActionGroup
860
861 KToggleAction* sortByName = actionCollection()->add<KToggleAction>("sort_by_name");
862 sortByName->setText(i18nc("@action:inmenu Sort By", "Name"));
863 connect(sortByName, SIGNAL(triggered()), this, SLOT(sortByName()));
864
865 KToggleAction* sortBySize = actionCollection()->add<KToggleAction>("sort_by_size");
866 sortBySize->setText(i18nc("@action:inmenu Sort By", "Size"));
867 connect(sortBySize, SIGNAL(triggered()), this, SLOT(sortBySize()));
868
869 KToggleAction* sortByDate = actionCollection()->add<KToggleAction>("sort_by_date");
870 sortByDate->setText(i18nc("@action:inmenu Sort By", "Date"));
871 connect(sortByDate, SIGNAL(triggered()), this, SLOT(sortByDate()));
872
873 KToggleAction* sortByPermissions = actionCollection()->add<KToggleAction>("sort_by_permissions");
874 sortByPermissions->setText(i18nc("@action:inmenu Sort By", "Permissions"));
875 connect(sortByPermissions, SIGNAL(triggered()), this, SLOT(sortByPermissions()));
876
877 KToggleAction* sortByOwner = actionCollection()->add<KToggleAction>("sort_by_owner");
878 sortByOwner->setText(i18nc("@action:inmenu Sort By", "Owner"));
879 connect(sortByOwner, SIGNAL(triggered()), this, SLOT(sortByOwner()));
880
881 KToggleAction* sortByGroup = actionCollection()->add<KToggleAction>("sort_by_group");
882 sortByGroup->setText(i18nc("@action:inmenu Sort By", "Group"));
883 connect(sortByGroup, SIGNAL(triggered()), this, SLOT(sortByGroup()));
884
885 KToggleAction* sortByType = actionCollection()->add<KToggleAction>("sort_by_type");
886 sortByType->setText(i18nc("@action:inmenu Sort By", "Type"));
887 connect(sortByType, SIGNAL(triggered()), this, SLOT(sortByType()));
888
889 // TODO: Hided "sort by rating" and "sort by tags" as without caching the performance
890 // is too slow currently (Nepomuk will support caching in future releases).
891 //
892 // KToggleAction* sortByRating = actionCollection()->add<KToggleAction>("sort_by_rating");
893 // sortByRating->setText(i18nc("@action:inmenu Sort By", "Rating"));
894 //
895 // KToggleAction* sortByTags = actionCollection()->add<KToggleAction>("sort_by_tags");
896 // sortByTags->setText(i18nc("@action:inmenu Sort By", "Tags"));
897 //
898 #ifdef HAVE_NEPOMUK
899 // if (MetaDataWidget::metaDataAvailable()) {
900 // connect(sortByRating, SIGNAL(triggered()), this, SLOT(sortByRating()));
901 // connect(sortByTags, SIGNAL(triggered()), this, SLOT(sortByTags()));
902 // }
903 // else {
904 // sortByRating->setEnabled(false);
905 // sortByTags->setEnabled(false);
906 // }
907 #else
908 // sortByRating->setEnabled(false);
909 // sortByTags->setEnabled(false);
910 #endif
911
912 QActionGroup* sortGroup = new QActionGroup(this);
913 sortGroup->addAction(sortByName);
914 sortGroup->addAction(sortBySize);
915 sortGroup->addAction(sortByDate);
916 sortGroup->addAction(sortByPermissions);
917 sortGroup->addAction(sortByOwner);
918 sortGroup->addAction(sortByGroup);
919 sortGroup->addAction(sortByType);
920
921 // TODO: Hided "sort by rating" and "sort by tags" as without caching the performance
922 // is too slow currently (Nepomuk will support caching in future releases).
923 //sortGroup->addAction(sortByRating);
924 //sortGroup->addAction(sortByTags);
925
926 KAction* split = actionCollection()->addAction("split_view");
927 split->setShortcut(Qt::Key_F3);
928 updateSplitAction();
929 connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
930
931 KAction* reload = actionCollection()->addAction("reload");
932 reload->setText(i18nc("@action:inmenu View", "Reload"));
933 reload->setShortcut(Qt::Key_F5);
934 reload->setIcon(KIcon("view-refresh"));
935 connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
936
937 KAction* stop = actionCollection()->addAction("stop");
938 stop->setText(i18nc("@action:inmenu View", "Stop"));
939 stop->setIcon(KIcon("process-stop"));
940 connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
941
942 // TODO: the naming "Show full Location" is currently confusing...
943 KToggleAction* showFullLocation = actionCollection()->add<KToggleAction>("editable_location");
944 showFullLocation->setText(i18nc("@action:inmenu Navigation Bar", "Show Full Location"));
945 showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);
946 connect(showFullLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
947
948 KAction* editLocation = actionCollection()->addAction("edit_location");
949 editLocation->setText(i18nc("@action:inmenu Navigation Bar", "Edit Location"));
950 editLocation->setShortcut(Qt::Key_F6);
951 connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation()));
952
953 KAction* adjustViewProps = actionCollection()->addAction("view_properties");
954 adjustViewProps->setText(i18nc("@action:inmenu View", "Adjust View Properties..."));
955 connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties()));
956
957 // setup 'Go' menu
958 KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
959 KShortcut backShortcut = backAction->shortcut();
960 backShortcut.setAlternate(Qt::Key_Backspace);
961 backAction->setShortcut(backShortcut);
962
963 KStandardAction::forward(this, SLOT(goForward()), actionCollection());
964 KStandardAction::up(this, SLOT(goUp()), actionCollection());
965 KStandardAction::home(this, SLOT(goHome()), actionCollection());
966
967 // setup 'Tools' menu
968 QAction* findFile = actionCollection()->addAction("find_file");
969 findFile->setText(i18nc("@action:inmenu Tools", "Find File..."));
970 findFile->setShortcut(Qt::CTRL | Qt::Key_F);
971 findFile->setIcon(KIcon("edit-find"));
972 connect(findFile, SIGNAL(triggered()), this, SLOT(findFile()));
973
974 KToggleAction* showFilterBar = actionCollection()->add<KToggleAction>("show_filter_bar");
975 showFilterBar->setText(i18nc("@action:inmenu Tools", "Show Filter Bar"));
976 showFilterBar->setShortcut(Qt::CTRL | Qt::Key_I);
977 connect(showFilterBar, SIGNAL(triggered(bool)), this, SLOT(toggleFilterBarVisibility(bool)));
978
979 KAction* compareFiles = actionCollection()->addAction("compare_files");
980 compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files"));
981 compareFiles->setIcon(KIcon("kompare"));
982 compareFiles->setEnabled(false);
983 connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
984
985 // setup 'Settings' menu
986 m_showMenuBar = KStandardAction::showMenubar(this, SLOT(toggleShowMenuBar()), actionCollection());
987 KStandardAction::preferences(this, SLOT(editSettings()), actionCollection());
988 }
989
990 void DolphinMainWindow::setupDockWidgets()
991 {
992 // setup "Information"
993 QDockWidget* infoDock = new QDockWidget(i18nc("@title:window", "Information"));
994 infoDock->setObjectName("infoDock");
995 infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
996 SidebarPage* infoWidget = new InfoSidebarPage(infoDock);
997 infoDock->setWidget(infoWidget);
998
999 infoDock->toggleViewAction()->setText(i18nc("@title:window", "Information"));
1000 infoDock->toggleViewAction()->setShortcut(Qt::Key_F11);
1001 actionCollection()->addAction("show_info_panel", infoDock->toggleViewAction());
1002
1003 addDockWidget(Qt::RightDockWidgetArea, infoDock);
1004 connect(this, SIGNAL(urlChanged(KUrl)),
1005 infoWidget, SLOT(setUrl(KUrl)));
1006 connect(this, SIGNAL(selectionChanged(KFileItemList)),
1007 infoWidget, SLOT(setSelection(KFileItemList)));
1008 connect(this, SIGNAL(requestItemInfo(KFileItem)),
1009 infoWidget, SLOT(requestDelayedItemInfo(KFileItem)));
1010
1011 // setup "Tree View"
1012 QDockWidget* treeViewDock = new QDockWidget(i18nc("@title:window", "Folders"));
1013 treeViewDock->setObjectName("treeViewDock");
1014 treeViewDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1015 TreeViewSidebarPage* treeWidget = new TreeViewSidebarPage(treeViewDock);
1016 treeViewDock->setWidget(treeWidget);
1017
1018 treeViewDock->toggleViewAction()->setText(i18nc("@title:window", "Folders"));
1019 treeViewDock->toggleViewAction()->setShortcut(Qt::Key_F7);
1020 actionCollection()->addAction("show_folders_panel", treeViewDock->toggleViewAction());
1021
1022 addDockWidget(Qt::LeftDockWidgetArea, treeViewDock);
1023 connect(this, SIGNAL(urlChanged(KUrl)),
1024 treeWidget, SLOT(setUrl(KUrl)));
1025 connect(treeWidget, SIGNAL(changeUrl(KUrl)),
1026 this, SLOT(changeUrl(KUrl)));
1027 connect(treeWidget, SIGNAL(changeSelection(KFileItemList)),
1028 this, SLOT(changeSelection(KFileItemList)));
1029 connect(treeWidget, SIGNAL(urlsDropped(KUrl::List, KUrl)),
1030 this, SLOT(dropUrls(KUrl::List, KUrl)));
1031
1032 // setup "Terminal"
1033 QDockWidget* terminalDock = new QDockWidget(i18nc("@title:window", "Terminal"));
1034 terminalDock->setObjectName("terminalDock");
1035 terminalDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
1036 SidebarPage* terminalWidget = new TerminalSidebarPage(terminalDock);
1037 terminalDock->setWidget(terminalWidget);
1038
1039 connect(terminalWidget, SIGNAL(hideTerminalSidebarPage()), terminalDock, SLOT(hide()));
1040
1041 terminalDock->toggleViewAction()->setText(i18nc("@title:window", "Terminal"));
1042 terminalDock->toggleViewAction()->setShortcut(Qt::Key_F4);
1043 actionCollection()->addAction("show_terminal_panel", terminalDock->toggleViewAction());
1044
1045 addDockWidget(Qt::BottomDockWidgetArea, terminalDock);
1046 connect(this, SIGNAL(urlChanged(KUrl)),
1047 terminalWidget, SLOT(setUrl(KUrl)));
1048
1049 const bool firstRun = DolphinSettings::instance().generalSettings()->firstRun();
1050 if (firstRun) {
1051 infoDock->hide();
1052 treeViewDock->hide();
1053 terminalDock->hide();
1054 }
1055
1056 QDockWidget* placesDock = new QDockWidget(i18nc("@title:window", "Places"));
1057 placesDock->setObjectName("placesDock");
1058 placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1059
1060 DolphinFilePlacesView* placesView = new DolphinFilePlacesView(placesDock);
1061 placesDock->setWidget(placesView);
1062 placesView->setModel(DolphinSettings::instance().placesModel());
1063 placesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1064
1065 placesDock->toggleViewAction()->setText(i18nc("@title:window", "Places"));
1066 placesDock->toggleViewAction()->setShortcut(Qt::Key_F9);
1067 actionCollection()->addAction("show_places_panel", placesDock->toggleViewAction());
1068
1069 addDockWidget(Qt::LeftDockWidgetArea, placesDock);
1070 connect(placesView, SIGNAL(urlChanged(KUrl)),
1071 this, SLOT(changeUrl(KUrl)));
1072 connect(this, SIGNAL(urlChanged(KUrl)),
1073 placesView, SLOT(setUrl(KUrl)));
1074 }
1075
1076 void DolphinMainWindow::updateHistory()
1077 {
1078 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
1079 const int index = urlNavigator->historyIndex();
1080
1081 QAction* backAction = actionCollection()->action("go_back");
1082 if (backAction != 0) {
1083 backAction->setEnabled(index < urlNavigator->historySize() - 1);
1084 }
1085
1086 QAction* forwardAction = actionCollection()->action("go_forward");
1087 if (forwardAction != 0) {
1088 forwardAction->setEnabled(index > 0);
1089 }
1090 }
1091
1092 void DolphinMainWindow::updateEditActions()
1093 {
1094 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
1095 if (list.isEmpty()) {
1096 stateChanged("has_no_selection");
1097 } else {
1098 stateChanged("has_selection");
1099
1100 QAction* renameAction = actionCollection()->action("rename");
1101 if (renameAction != 0) {
1102 renameAction->setEnabled(true);
1103 }
1104
1105 bool enableMoveToTrash = true;
1106
1107 KFileItemList::const_iterator it = list.begin();
1108 const KFileItemList::const_iterator end = list.end();
1109 while (it != end) {
1110 const KUrl& url = (*it).url();
1111 // only enable the 'Move to Trash' action for local files
1112 if (!url.isLocalFile()) {
1113 enableMoveToTrash = false;
1114 }
1115 ++it;
1116 }
1117
1118 QAction* moveToTrashAction = actionCollection()->action("move_to_trash");
1119 moveToTrashAction->setEnabled(enableMoveToTrash);
1120 }
1121 updatePasteAction();
1122 }
1123
1124 void DolphinMainWindow::updateViewActions()
1125 {
1126 m_actionHandler->updateViewActions();
1127
1128 const DolphinView* view = m_activeViewContainer->view();
1129 QAction* action = actionCollection()->action(view->currentViewModeActionName());
1130 if (action != 0) {
1131 action->setChecked(true);
1132 }
1133
1134 slotSortingChanged(view->sorting());
1135
1136 QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
1137 showFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
1138
1139 updateSplitAction();
1140
1141 QAction* editableLocactionAction = actionCollection()->action("editable_location");
1142 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
1143 editableLocactionAction->setChecked(urlNavigator->isUrlEditable());
1144 }
1145
1146 void DolphinMainWindow::updateGoActions()
1147 {
1148 QAction* goUpAction = actionCollection()->action(KStandardAction::name(KStandardAction::Up));
1149 const KUrl& currentUrl = m_activeViewContainer->url();
1150 goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
1151 }
1152
1153 void DolphinMainWindow::clearStatusBar()
1154 {
1155 m_activeViewContainer->statusBar()->clear();
1156 }
1157
1158 void DolphinMainWindow::connectViewSignals(int viewIndex)
1159 {
1160 DolphinViewContainer* container = m_viewContainer[viewIndex];
1161 connect(container, SIGNAL(showFilterBarChanged(bool)),
1162 this, SLOT(updateFilterBarAction(bool)));
1163
1164 DolphinView* view = container->view();
1165 connect(view, SIGNAL(modeChanged()),
1166 this, SLOT(slotViewModeChanged()));
1167 connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),
1168 this, SLOT(slotSortingChanged(DolphinView::Sorting)));
1169 connect(view, SIGNAL(selectionChanged(KFileItemList)),
1170 this, SLOT(slotSelectionChanged(KFileItemList)));
1171 connect(view, SIGNAL(requestItemInfo(KFileItem)),
1172 this, SLOT(slotRequestItemInfo(KFileItem)));
1173 connect(view, SIGNAL(activated()),
1174 this, SLOT(toggleActiveView()));
1175 connect(view, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)),
1176 this, SLOT(slotDoingOperation(KonqFileUndoManager::CommandType)));
1177
1178 const KUrlNavigator* navigator = container->urlNavigator();
1179 connect(navigator, SIGNAL(urlChanged(const KUrl&)),
1180 this, SLOT(changeUrl(const KUrl&)));
1181 connect(navigator, SIGNAL(historyChanged()),
1182 this, SLOT(slotHistoryChanged()));
1183 connect(navigator, SIGNAL(editableStateChanged(bool)),
1184 this, SLOT(slotEditableStateChanged(bool)));
1185 }
1186
1187 void DolphinMainWindow::updateSplitAction()
1188 {
1189 QAction* splitAction = actionCollection()->action("split_view");
1190 if (m_viewContainer[SecondaryView] != 0) {
1191 if (m_activeViewContainer == m_viewContainer[PrimaryView]) {
1192 splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
1193 splitAction->setIcon(KIcon("view-right-close"));
1194 } else {
1195 splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
1196 splitAction->setIcon(KIcon("view-left-close"));
1197 }
1198 } else {
1199 splitAction->setText(i18nc("@action:intoolbar Split view", "Split"));
1200 splitAction->setIcon(KIcon("view-right-new"));
1201 }
1202 }
1203
1204 DolphinMainWindow::UndoUiInterface::UndoUiInterface(DolphinMainWindow* mainWin) :
1205 KonqFileUndoManager::UiInterface(mainWin),
1206 m_mainWin(mainWin)
1207 {
1208 Q_ASSERT(m_mainWin != 0);
1209 }
1210
1211 DolphinMainWindow::UndoUiInterface::~UndoUiInterface()
1212 {
1213 }
1214
1215 void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)
1216 {
1217 DolphinStatusBar* statusBar = m_mainWin->activeViewContainer()->statusBar();
1218 statusBar->setMessage(job->errorString(), DolphinStatusBar::Error);
1219 }
1220
1221 #include "dolphinmainwindow.moc"