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