]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinmainwindow.cpp
0882bac71745ba6d9fdb7bcb525b8b1cc037a828
[dolphin.git] / src / dolphinmainwindow.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz <peter.penz19@gmail.com> *
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 "dolphinapplication.h"
25 #include "dolphindockwidget.h"
26 #include "dolphincontextmenu.h"
27 #include "dolphinnewfilemenu.h"
28 #include "dolphinrecenttabsmenu.h"
29 #include "dolphintabwidget.h"
30 #include "dolphinviewcontainer.h"
31 #include "dolphintabpage.h"
32 #include "panels/folders/folderspanel.h"
33 #include "panels/places/placespanel.h"
34 #include "panels/information/informationpanel.h"
35 #include "settings/dolphinsettingsdialog.h"
36 #include "statusbar/dolphinstatusbar.h"
37 #include "views/dolphinviewactionhandler.h"
38 #include "views/dolphinremoteencoding.h"
39 #include "views/draganddrophelper.h"
40 #include "views/viewproperties.h"
41 #include "views/dolphinnewfilemenuobserver.h"
42
43 #ifndef Q_OS_WIN
44 #include "panels/terminal/terminalpanel.h"
45 #endif
46
47 #include "dolphin_generalsettings.h"
48
49 #include <KAcceleratorManager>
50 #include <KAction>
51 #include <KActionCollection>
52 #include <KActionMenu>
53 #include <KConfig>
54 #include <KDesktopFile>
55 #include <kdeversion.h>
56 #include <kdualaction.h>
57 #include <KFileDialog>
58 #include <KGlobal>
59 #include <KLineEdit>
60 #include <KToolBar>
61 #include <KIcon>
62 #include <KIconLoader>
63 #include <KIO/NetAccess>
64 #include <KIO/JobUiDelegate>
65 #include <KInputDialog>
66 #include <KLocale>
67 #include <KProtocolManager>
68 #include <KMenu>
69 #include <KMenuBar>
70 #include <KMessageBox>
71 #include <KFileItemListProperties>
72 #include <konqmimedata.h>
73 #include <KProtocolInfo>
74 #include <KRun>
75 #include <KShell>
76 #include <KStandardDirs>
77 #include <kstatusbar.h>
78 #include <KStandardAction>
79 #include <KToggleAction>
80 #include <KUrlNavigator>
81 #include <KUrl>
82 #include <KUrlComboBox>
83 #include <KToolInvocation>
84
85 #include <QDesktopWidget>
86 #include <QDBusMessage>
87 #include <QKeyEvent>
88 #include <QClipboard>
89 #include <QToolButton>
90
91 namespace {
92 // Used for GeneralSettings::version() to determine whether
93 // an updated version of Dolphin is running.
94 const int CurrentDolphinVersion = 200;
95 };
96
97 DolphinMainWindow::DolphinMainWindow() :
98 KXmlGuiWindow(0),
99 m_newFileMenu(0),
100 m_tabWidget(0),
101 m_activeViewContainer(0),
102 m_actionHandler(0),
103 m_remoteEncoding(0),
104 m_settingsDialog(),
105 m_controlButton(0),
106 m_updateToolBarTimer(0),
107 m_lastHandleUrlStatJob(0)
108 {
109 setObjectName("Dolphin#");
110
111 connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(errorMessage(QString)),
112 this, SLOT(showErrorMessage(QString)));
113
114 KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
115 undoManager->setUiInterface(new UndoUiInterface());
116
117 connect(undoManager, SIGNAL(undoAvailable(bool)),
118 this, SLOT(slotUndoAvailable(bool)));
119 connect(undoManager, SIGNAL(undoTextChanged(QString)),
120 this, SLOT(slotUndoTextChanged(QString)));
121 connect(undoManager, SIGNAL(jobRecordingStarted(CommandType)),
122 this, SLOT(clearStatusBar()));
123 connect(undoManager, SIGNAL(jobRecordingFinished(CommandType)),
124 this, SLOT(showCommand(CommandType)));
125
126 GeneralSettings* generalSettings = GeneralSettings::self();
127 const bool firstRun = (generalSettings->version() < 200);
128 if (firstRun) {
129 generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
130 }
131
132 setAcceptDrops(true);
133
134 m_tabWidget = new DolphinTabWidget(this);
135 connect(m_tabWidget, SIGNAL(activeViewChanged(DolphinViewContainer*)),
136 this, SLOT(activeViewChanged(DolphinViewContainer*)));
137 connect(m_tabWidget, SIGNAL(tabCountChanged(int)),
138 this, SLOT(tabCountChanged(int)));
139 setCentralWidget(m_tabWidget);
140
141 setupActions();
142
143 m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
144 connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar()));
145 connect(m_actionHandler, SIGNAL(createDirectory()), SLOT(createDirectory()));
146
147 m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
148 connect(this, SIGNAL(urlChanged(KUrl)),
149 m_remoteEncoding, SLOT(slotAboutToOpenUrl()));
150
151 setupDockWidgets();
152
153 setupGUI(Keys | Save | Create | ToolBar);
154 stateChanged("new_file");
155
156 QClipboard* clipboard = QApplication::clipboard();
157 connect(clipboard, SIGNAL(dataChanged()),
158 this, SLOT(updatePasteAction()));
159
160 QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
161 showFilterBarAction->setChecked(generalSettings->filterBar());
162
163 if (firstRun) {
164 menuBar()->setVisible(false);
165 // Assure a proper default size if Dolphin runs the first time
166 resize(750, 500);
167 }
168
169 const bool showMenu = !menuBar()->isHidden();
170 QAction* showMenuBarAction = actionCollection()->action(KStandardAction::name(KStandardAction::ShowMenubar));
171 showMenuBarAction->setChecked(showMenu); // workaround for bug #171080
172 if (!showMenu) {
173 createControlButton();
174 }
175 }
176
177 DolphinMainWindow::~DolphinMainWindow()
178 {
179 }
180
181 void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
182 {
183 m_tabWidget->openDirectories(dirs);
184 }
185
186 void DolphinMainWindow::openFiles(const QList<KUrl>& files)
187 {
188 m_tabWidget->openFiles(files);
189 }
190
191 void DolphinMainWindow::showCommand(CommandType command)
192 {
193 DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
194 switch (command) {
195 case KIO::FileUndoManager::Copy:
196 statusBar->setText(i18nc("@info:status", "Successfully copied."));
197 break;
198 case KIO::FileUndoManager::Move:
199 statusBar->setText(i18nc("@info:status", "Successfully moved."));
200 break;
201 case KIO::FileUndoManager::Link:
202 statusBar->setText(i18nc("@info:status", "Successfully linked."));
203 break;
204 case KIO::FileUndoManager::Trash:
205 statusBar->setText(i18nc("@info:status", "Successfully moved to trash."));
206 break;
207 case KIO::FileUndoManager::Rename:
208 statusBar->setText(i18nc("@info:status", "Successfully renamed."));
209 break;
210
211 case KIO::FileUndoManager::Mkdir:
212 statusBar->setText(i18nc("@info:status", "Created folder."));
213 break;
214
215 default:
216 break;
217 }
218 }
219
220 void DolphinMainWindow::pasteIntoFolder()
221 {
222 m_activeViewContainer->view()->pasteIntoFolder();
223 }
224
225 void DolphinMainWindow::changeUrl(const KUrl& url)
226 {
227 if (!KProtocolManager::supportsListing(url)) {
228 // The URL navigator only checks for validity, not
229 // if the URL can be listed. An error message is
230 // shown due to DolphinViewContainer::restoreView().
231 return;
232 }
233
234 m_activeViewContainer->setUrl(url);
235 updateEditActions();
236 updatePasteAction();
237 updateViewActions();
238 updateGoActions();
239 setUrlAsCaption(url);
240
241 emit urlChanged(url);
242 }
243
244 void DolphinMainWindow::slotTerminalDirectoryChanged(const KUrl& url)
245 {
246 m_activeViewContainer->setAutoGrabFocus(false);
247 changeUrl(url);
248 m_activeViewContainer->setAutoGrabFocus(true);
249 }
250
251 void DolphinMainWindow::slotEditableStateChanged(bool editable)
252 {
253 KToggleAction* editableLocationAction =
254 static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
255 editableLocationAction->setChecked(editable);
256 }
257
258 void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
259 {
260 updateEditActions();
261
262 const int selectedUrlsCount = m_tabWidget->currentTabPage()->selectedItemsCount();
263
264 QAction* compareFilesAction = actionCollection()->action("compare_files");
265 if (selectedUrlsCount == 2) {
266 compareFilesAction->setEnabled(isKompareInstalled());
267 } else {
268 compareFilesAction->setEnabled(false);
269 }
270
271 emit selectionChanged(selection);
272 }
273
274 void DolphinMainWindow::slotRequestItemInfo(const KFileItem& item)
275 {
276 emit requestItemInfo(item);
277 }
278
279 void DolphinMainWindow::updateHistory()
280 {
281 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
282 const int index = urlNavigator->historyIndex();
283
284 QAction* backAction = actionCollection()->action("go_back");
285 if (backAction) {
286 backAction->setToolTip(i18nc("@info", "Go back"));
287 backAction->setEnabled(index < urlNavigator->historySize() - 1);
288 }
289
290 QAction* forwardAction = actionCollection()->action("go_forward");
291 if (forwardAction) {
292 forwardAction->setToolTip(i18nc("@info", "Go forward"));
293 forwardAction->setEnabled(index > 0);
294 }
295 }
296
297 void DolphinMainWindow::updateFilterBarAction(bool show)
298 {
299 QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
300 showFilterBarAction->setChecked(show);
301 }
302
303 void DolphinMainWindow::openNewMainWindow()
304 {
305 KRun::run("dolphin %u", KUrl::List(), this);
306 }
307
308 void DolphinMainWindow::openNewActivatedTab()
309 {
310 m_tabWidget->openNewActivatedTab();
311 }
312
313 void DolphinMainWindow::openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
314 {
315 m_tabWidget->openNewTab(primaryUrl, secondaryUrl);
316 }
317
318 void DolphinMainWindow::openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
319 {
320 m_tabWidget->openNewActivatedTab(primaryUrl, secondaryUrl);
321 }
322
323 void DolphinMainWindow::openInNewTab()
324 {
325 const KFileItemList& list = m_activeViewContainer->view()->selectedItems();
326 if (list.isEmpty()) {
327 openNewTab(m_activeViewContainer->url());
328 } else {
329 foreach (const KFileItem& item, list) {
330 const KUrl& url = DolphinView::openItemAsFolderUrl(item);
331 if (!url.isEmpty()) {
332 openNewTab(url);
333 }
334 }
335 }
336 }
337
338 void DolphinMainWindow::openInNewWindow()
339 {
340 KUrl newWindowUrl;
341
342 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
343 if (list.isEmpty()) {
344 newWindowUrl = m_activeViewContainer->url();
345 } else if (list.count() == 1) {
346 const KFileItem& item = list.first();
347 newWindowUrl = DolphinView::openItemAsFolderUrl(item);
348 }
349
350 if (!newWindowUrl.isEmpty()) {
351 KRun::run("dolphin %u", KUrl::List() << newWindowUrl, this);
352 }
353 }
354
355 void DolphinMainWindow::showEvent(QShowEvent* event)
356 {
357 KXmlGuiWindow::showEvent(event);
358
359 if (!event->spontaneous()) {
360 m_activeViewContainer->view()->setFocus();
361 }
362 }
363
364 void DolphinMainWindow::closeEvent(QCloseEvent* event)
365 {
366 // Find out if Dolphin is closed directly by the user or
367 // by the session manager because the session is closed
368 bool closedByUser = true;
369 DolphinApplication *application = qobject_cast<DolphinApplication*>(qApp);
370 if (application && application->sessionSaving()) {
371 closedByUser = false;
372 }
373
374 if (m_tabWidget->count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) {
375 // Ask the user if he really wants to quit and close all tabs.
376 // Open a confirmation dialog with 3 buttons:
377 // KDialog::Yes -> Quit
378 // KDialog::No -> Close only the current tab
379 // KDialog::Cancel -> do nothing
380 KDialog *dialog = new KDialog(this, Qt::Dialog);
381 dialog->setCaption(i18nc("@title:window", "Confirmation"));
382 dialog->setButtons(KDialog::Yes | KDialog::No | KDialog::Cancel);
383 dialog->setModal(true);
384 dialog->setButtonGuiItem(KDialog::Yes, KStandardGuiItem::quit());
385 dialog->setButtonGuiItem(KDialog::No, KGuiItem(i18n("C&lose Current Tab"), KIcon("tab-close")));
386 dialog->setButtonGuiItem(KDialog::Cancel, KStandardGuiItem::cancel());
387 dialog->setDefaultButton(KDialog::Yes);
388
389 bool doNotAskAgainCheckboxResult = false;
390
391 const int result = KMessageBox::createKMessageBox(dialog,
392 QMessageBox::Warning,
393 i18n("You have multiple tabs open in this window, are you sure you want to quit?"),
394 QStringList(),
395 i18n("Do not ask again"),
396 &doNotAskAgainCheckboxResult,
397 KMessageBox::Notify);
398
399 if (doNotAskAgainCheckboxResult) {
400 GeneralSettings::setConfirmClosingMultipleTabs(false);
401 }
402
403 switch (result) {
404 case KDialog::Yes:
405 // Quit
406 break;
407 case KDialog::No:
408 // Close only the current tab
409 m_tabWidget->closeTab();
410 default:
411 event->ignore();
412 return;
413 }
414 }
415
416 GeneralSettings::setVersion(CurrentDolphinVersion);
417 GeneralSettings::self()->writeConfig();
418
419 KXmlGuiWindow::closeEvent(event);
420 }
421
422 void DolphinMainWindow::saveProperties(KConfigGroup& group)
423 {
424 m_tabWidget->saveProperties(group);
425 }
426
427 void DolphinMainWindow::readProperties(const KConfigGroup& group)
428 {
429 m_tabWidget->readProperties(group);
430 }
431
432 void DolphinMainWindow::updateNewMenu()
433 {
434 m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
435 m_newFileMenu->checkUpToDate();
436 m_newFileMenu->setPopupFiles(activeViewContainer()->url());
437 }
438
439 void DolphinMainWindow::createDirectory()
440 {
441 m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
442 m_newFileMenu->setPopupFiles(activeViewContainer()->url());
443 m_newFileMenu->createDirectory();
444 }
445
446 void DolphinMainWindow::quit()
447 {
448 close();
449 }
450
451 void DolphinMainWindow::showErrorMessage(const QString& message)
452 {
453 m_activeViewContainer->showMessage(message, DolphinViewContainer::Error);
454 }
455
456 void DolphinMainWindow::slotUndoAvailable(bool available)
457 {
458 QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
459 if (undoAction) {
460 undoAction->setEnabled(available);
461 }
462 }
463
464 void DolphinMainWindow::slotUndoTextChanged(const QString& text)
465 {
466 QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
467 if (undoAction) {
468 undoAction->setText(text);
469 }
470 }
471
472 void DolphinMainWindow::undo()
473 {
474 clearStatusBar();
475 KIO::FileUndoManager::self()->uiInterface()->setParentWidget(this);
476 KIO::FileUndoManager::self()->undo();
477 }
478
479 void DolphinMainWindow::cut()
480 {
481 m_activeViewContainer->view()->cutSelectedItems();
482 }
483
484 void DolphinMainWindow::copy()
485 {
486 m_activeViewContainer->view()->copySelectedItems();
487 }
488
489 void DolphinMainWindow::paste()
490 {
491 m_activeViewContainer->view()->paste();
492 }
493
494 void DolphinMainWindow::find()
495 {
496 m_activeViewContainer->setSearchModeEnabled(true);
497 }
498
499 void DolphinMainWindow::updatePasteAction()
500 {
501 QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
502 QPair<bool, QString> pasteInfo = m_activeViewContainer->view()->pasteInfo();
503 pasteAction->setEnabled(pasteInfo.first);
504 pasteAction->setText(pasteInfo.second);
505 }
506
507 void DolphinMainWindow::selectAll()
508 {
509 clearStatusBar();
510
511 // if the URL navigator is editable and focused, select the whole
512 // URL instead of all items of the view
513
514 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
515 QLineEdit* lineEdit = urlNavigator->editor()->lineEdit(); // krazy:exclude=qclasses
516 const bool selectUrl = urlNavigator->isUrlEditable() &&
517 lineEdit->hasFocus();
518 if (selectUrl) {
519 lineEdit->selectAll();
520 } else {
521 m_activeViewContainer->view()->selectAll();
522 }
523 }
524
525 void DolphinMainWindow::invertSelection()
526 {
527 clearStatusBar();
528 m_activeViewContainer->view()->invertSelection();
529 }
530
531 void DolphinMainWindow::toggleSplitView()
532 {
533 DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
534 tabPage->setSplitViewEnabled(!tabPage->splitViewEnabled());
535
536 updateViewActions();
537 }
538
539 void DolphinMainWindow::reloadView()
540 {
541 clearStatusBar();
542 m_activeViewContainer->view()->reload();
543 }
544
545 void DolphinMainWindow::stopLoading()
546 {
547 m_activeViewContainer->view()->stopLoading();
548 }
549
550 void DolphinMainWindow::enableStopAction()
551 {
552 actionCollection()->action("stop")->setEnabled(true);
553 }
554
555 void DolphinMainWindow::disableStopAction()
556 {
557 actionCollection()->action("stop")->setEnabled(false);
558 }
559
560 void DolphinMainWindow::showFilterBar()
561 {
562 m_activeViewContainer->setFilterBarVisible(true);
563 }
564
565 void DolphinMainWindow::toggleEditLocation()
566 {
567 clearStatusBar();
568
569 QAction* action = actionCollection()->action("editable_location");
570 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
571 urlNavigator->setUrlEditable(action->isChecked());
572 }
573
574 void DolphinMainWindow::replaceLocation()
575 {
576 KUrlNavigator* navigator = m_activeViewContainer->urlNavigator();
577 navigator->setUrlEditable(true);
578 navigator->setFocus();
579
580 // select the whole text of the combo box editor
581 QLineEdit* lineEdit = navigator->editor()->lineEdit(); // krazy:exclude=qclasses
582 lineEdit->selectAll();
583 }
584
585 void DolphinMainWindow::togglePanelLockState()
586 {
587 const bool newLockState = !GeneralSettings::lockPanels();
588 foreach (QObject* child, children()) {
589 DolphinDockWidget* dock = qobject_cast<DolphinDockWidget*>(child);
590 if (dock) {
591 dock->setLocked(newLockState);
592 }
593 }
594
595 GeneralSettings::setLockPanels(newLockState);
596 }
597
598 void DolphinMainWindow::goBack()
599 {
600 KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
601 urlNavigator->goBack();
602
603 if (urlNavigator->locationState().isEmpty()) {
604 // An empty location state indicates a redirection URL,
605 // which must be skipped too
606 urlNavigator->goBack();
607 }
608 }
609
610 void DolphinMainWindow::goForward()
611 {
612 m_activeViewContainer->urlNavigator()->goForward();
613 }
614
615 void DolphinMainWindow::goUp()
616 {
617 m_activeViewContainer->urlNavigator()->goUp();
618 }
619
620 void DolphinMainWindow::goHome()
621 {
622 m_activeViewContainer->urlNavigator()->goHome();
623 }
624
625 void DolphinMainWindow::goBack(Qt::MouseButtons buttons)
626 {
627 // The default case (left button pressed) is handled in goBack().
628 if (buttons == Qt::MidButton) {
629 KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
630 const int index = urlNavigator->historyIndex() + 1;
631 openNewTab(urlNavigator->locationUrl(index));
632 }
633 }
634
635 void DolphinMainWindow::goForward(Qt::MouseButtons buttons)
636 {
637 // The default case (left button pressed) is handled in goForward().
638 if (buttons == Qt::MidButton) {
639 KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
640 const int index = urlNavigator->historyIndex() - 1;
641 openNewTab(urlNavigator->locationUrl(index));
642 }
643 }
644
645 void DolphinMainWindow::goUp(Qt::MouseButtons buttons)
646 {
647 // The default case (left button pressed) is handled in goUp().
648 if (buttons == Qt::MidButton) {
649 openNewTab(activeViewContainer()->url().upUrl());
650 }
651 }
652
653 void DolphinMainWindow::goHome(Qt::MouseButtons buttons)
654 {
655 // The default case (left button pressed) is handled in goHome().
656 if (buttons == Qt::MidButton) {
657 openNewTab(GeneralSettings::self()->homeUrl());
658 }
659 }
660
661 void DolphinMainWindow::compareFiles()
662 {
663 const KFileItemList items = m_tabWidget->currentTabPage()->selectedItems();
664 if (items.count() != 2) {
665 // The action is disabled in this case, but it could have been triggered
666 // via D-Bus, see https://bugs.kde.org/show_bug.cgi?id=325517
667 return;
668 }
669
670 KUrl urlA = items.at(0).url();
671 KUrl urlB = items.at(1).url();
672
673 QString command("kompare -c \"");
674 command.append(urlA.pathOrUrl());
675 command.append("\" \"");
676 command.append(urlB.pathOrUrl());
677 command.append('\"');
678 KRun::runCommand(command, "Kompare", "kompare", this);
679 }
680
681 void DolphinMainWindow::toggleShowMenuBar()
682 {
683 const bool visible = menuBar()->isVisible();
684 menuBar()->setVisible(!visible);
685 if (visible) {
686 createControlButton();
687 } else {
688 deleteControlButton();
689 }
690 }
691
692 void DolphinMainWindow::openTerminal()
693 {
694 QString dir(QDir::homePath());
695
696 // If the given directory is not local, it can still be the URL of an
697 // ioslave using UDS_LOCAL_PATH which to be converted first.
698 KUrl url = KIO::NetAccess::mostLocalUrl(m_activeViewContainer->url(), this);
699
700 //If the URL is local after the above conversion, set the directory.
701 if (url.isLocalFile()) {
702 dir = url.toLocalFile();
703 }
704
705 KToolInvocation::invokeTerminal(QString(), dir);
706 }
707
708 void DolphinMainWindow::editSettings()
709 {
710 if (!m_settingsDialog) {
711 DolphinViewContainer* container = activeViewContainer();
712 container->view()->writeSettings();
713
714 const KUrl url = container->url();
715 DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this);
716 connect(settingsDialog, SIGNAL(settingsChanged()), this, SLOT(refreshViews()));
717 settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
718 settingsDialog->show();
719 m_settingsDialog = settingsDialog;
720 } else {
721 m_settingsDialog.data()->raise();
722 }
723 }
724
725 void DolphinMainWindow::handleUrl(const KUrl& url)
726 {
727 delete m_lastHandleUrlStatJob;
728 m_lastHandleUrlStatJob = 0;
729
730 if (url.isLocalFile() && QFileInfo(url.toLocalFile()).isDir()) {
731 activeViewContainer()->setUrl(url);
732 } else if (KProtocolManager::supportsListing(url)) {
733 // stat the URL to see if it is a dir or not
734 m_lastHandleUrlStatJob = KIO::stat(url, KIO::HideProgressInfo);
735 if (m_lastHandleUrlStatJob->ui()) {
736 m_lastHandleUrlStatJob->ui()->setWindow(this);
737 }
738 connect(m_lastHandleUrlStatJob, SIGNAL(result(KJob*)),
739 this, SLOT(slotHandleUrlStatFinished(KJob*)));
740
741 } else {
742 new KRun(url, this); // Automatically deletes itself after being finished
743 }
744 }
745
746 void DolphinMainWindow::slotHandleUrlStatFinished(KJob* job)
747 {
748 m_lastHandleUrlStatJob = 0;
749 const KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
750 const KUrl url = static_cast<KIO::StatJob*>(job)->url();
751 if (entry.isDir()) {
752 activeViewContainer()->setUrl(url);
753 } else {
754 new KRun(url, this); // Automatically deletes itself after being finished
755 }
756 }
757
758 void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable)
759 {
760 newFileMenu()->setEnabled(isFolderWritable);
761 }
762
763 void DolphinMainWindow::openContextMenu(const QPoint& pos,
764 const KFileItem& item,
765 const KUrl& url,
766 const QList<QAction*>& customActions)
767 {
768 QWeakPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, pos, item, url);
769 contextMenu.data()->setCustomActions(customActions);
770 const DolphinContextMenu::Command command = contextMenu.data()->open();
771
772 switch (command) {
773 case DolphinContextMenu::OpenParentFolderInNewWindow: {
774 KRun::run("dolphin %u", KUrl::List() << item.url().upUrl(), this);
775 break;
776 }
777
778 case DolphinContextMenu::OpenParentFolderInNewTab:
779 openNewTab(item.url().upUrl());
780 break;
781
782 case DolphinContextMenu::None:
783 default:
784 break;
785 }
786
787 delete contextMenu.data();
788 }
789
790 void DolphinMainWindow::updateControlMenu()
791 {
792 KMenu* menu = qobject_cast<KMenu*>(sender());
793 Q_ASSERT(menu);
794
795 // All actions get cleared by KMenu::clear(). The sub-menus are deleted
796 // by connecting to the aboutToHide() signal from the parent-menu.
797 menu->clear();
798
799 KActionCollection* ac = actionCollection();
800
801 // Add "Edit" actions
802 bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) |
803 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Find)), menu) |
804 addActionToMenu(ac->action("select_all"), menu) |
805 addActionToMenu(ac->action("invert_selection"), menu);
806
807 if (added) {
808 menu->addSeparator();
809 }
810
811 // Add "View" actions
812 if (!GeneralSettings::showZoomSlider()) {
813 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomIn)), menu);
814 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomOut)), menu);
815 menu->addSeparator();
816 }
817
818 added = addActionToMenu(ac->action("view_mode"), menu) |
819 addActionToMenu(ac->action("sort"), menu) |
820 addActionToMenu(ac->action("additional_info"), menu) |
821 addActionToMenu(ac->action("show_preview"), menu) |
822 addActionToMenu(ac->action("show_in_groups"), menu) |
823 addActionToMenu(ac->action("show_hidden_files"), menu);
824
825 if (added) {
826 menu->addSeparator();
827 }
828
829 added = addActionToMenu(ac->action("split_view"), menu) |
830 addActionToMenu(ac->action("reload"), menu) |
831 addActionToMenu(ac->action("view_properties"), menu);
832 if (added) {
833 menu->addSeparator();
834 }
835
836 addActionToMenu(ac->action("panels"), menu);
837 KMenu* locationBarMenu = new KMenu(i18nc("@action:inmenu", "Location Bar"), menu);
838 locationBarMenu->addAction(ac->action("editable_location"));
839 locationBarMenu->addAction(ac->action("replace_location"));
840 menu->addMenu(locationBarMenu);
841
842 menu->addSeparator();
843
844 // Add "Go" menu
845 KMenu* goMenu = new KMenu(i18nc("@action:inmenu", "Go"), menu);
846 connect(menu, SIGNAL(aboutToHide()), goMenu, SLOT(deleteLater()));
847 goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Back)));
848 goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Forward)));
849 goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Up)));
850 goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Home)));
851 goMenu->addAction(ac->action("closed_tabs"));
852 menu->addMenu(goMenu);
853
854 // Add "Tool" menu
855 KMenu* toolsMenu = new KMenu(i18nc("@action:inmenu", "Tools"), menu);
856 connect(menu, SIGNAL(aboutToHide()), toolsMenu, SLOT(deleteLater()));
857 toolsMenu->addAction(ac->action("show_filter_bar"));
858 toolsMenu->addAction(ac->action("compare_files"));
859 toolsMenu->addAction(ac->action("open_terminal"));
860 toolsMenu->addAction(ac->action("change_remote_encoding"));
861 menu->addMenu(toolsMenu);
862
863 // Add "Settings" menu entries
864 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::KeyBindings)), menu);
865 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ConfigureToolbars)), menu);
866 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Preferences)), menu);
867
868 // Add "Help" menu
869 KMenu* helpMenu = new KMenu(i18nc("@action:inmenu", "Help"), menu);
870 connect(menu, SIGNAL(aboutToHide()), helpMenu, SLOT(deleteLater()));
871 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::HelpContents)));
872 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::WhatsThis)));
873 helpMenu->addSeparator();
874 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::ReportBug)));
875 helpMenu->addSeparator();
876 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage)));
877 helpMenu->addSeparator();
878 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutApp)));
879 helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutKDE)));
880 menu->addMenu(helpMenu);
881
882 menu->addSeparator();
883 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu);
884 }
885
886 void DolphinMainWindow::updateToolBar()
887 {
888 if (!menuBar()->isVisible()) {
889 createControlButton();
890 }
891 }
892
893 void DolphinMainWindow::slotControlButtonDeleted()
894 {
895 m_controlButton = 0;
896 m_updateToolBarTimer->start();
897 }
898
899 void DolphinMainWindow::slotPanelErrorMessage(const QString& error)
900 {
901 activeViewContainer()->showMessage(error, DolphinViewContainer::Error);
902 }
903
904 void DolphinMainWindow::slotPlaceActivated(const KUrl& url)
905 {
906 DolphinViewContainer* view = activeViewContainer();
907
908 if (view->url() == url) {
909 // We can end up here if the user clicked a device in the Places Panel
910 // which had been unmounted earlier, see https://bugs.kde.org/show_bug.cgi?id=161385.
911 reloadView();
912 } else {
913 changeUrl(url);
914 }
915 }
916
917 void DolphinMainWindow::closedTabsCountChanged(unsigned int count)
918 {
919 actionCollection()->action("undo_close_tab")->setEnabled(count > 0);
920 }
921
922 void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
923 {
924 DolphinViewContainer* oldViewContainer = m_activeViewContainer;
925 Q_ASSERT(viewContainer);
926
927 m_activeViewContainer = viewContainer;
928
929 if (oldViewContainer) {
930 // Disconnect all signals between the old view container (container,
931 // view and url navigator) and main window.
932 oldViewContainer->disconnect(this);
933 oldViewContainer->view()->disconnect(this);
934 oldViewContainer->urlNavigator()->disconnect(this);
935 }
936
937 connectViewSignals(viewContainer);
938
939 m_actionHandler->setCurrentView(viewContainer->view());
940
941 updateHistory();
942 updateEditActions();
943 updatePasteAction();
944 updateViewActions();
945 updateGoActions();
946
947 const KUrl url = viewContainer->url();
948 setUrlAsCaption(url);
949
950 emit urlChanged(url);
951 }
952
953 void DolphinMainWindow::tabCountChanged(int count)
954 {
955 const bool enableTabActions = (count > 1);
956 actionCollection()->action("close_tab")->setEnabled(enableTabActions);
957 actionCollection()->action("activate_next_tab")->setEnabled(enableTabActions);
958 actionCollection()->action("activate_prev_tab")->setEnabled(enableTabActions);
959 }
960
961 void DolphinMainWindow::setupActions()
962 {
963 // setup 'File' menu
964 m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this);
965 KMenu* menu = m_newFileMenu->menu();
966 menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New"));
967 menu->setIcon(KIcon("document-new"));
968 m_newFileMenu->setDelayed(false);
969 connect(menu, SIGNAL(aboutToShow()),
970 this, SLOT(updateNewMenu()));
971
972 KAction* newWindow = actionCollection()->addAction("new_window");
973 newWindow->setIcon(KIcon("window-new"));
974 newWindow->setText(i18nc("@action:inmenu File", "New &Window"));
975 newWindow->setShortcut(Qt::CTRL | Qt::Key_N);
976 connect(newWindow, SIGNAL(triggered()), this, SLOT(openNewMainWindow()));
977
978 KAction* newTab = actionCollection()->addAction("new_tab");
979 newTab->setIcon(KIcon("tab-new"));
980 newTab->setText(i18nc("@action:inmenu File", "New Tab"));
981 newTab->setShortcut(KShortcut(Qt::CTRL | Qt::Key_T, Qt::CTRL | Qt::SHIFT | Qt::Key_N));
982 connect(newTab, SIGNAL(triggered()), this, SLOT(openNewActivatedTab()));
983
984 KAction* closeTab = actionCollection()->addAction("close_tab");
985 closeTab->setIcon(KIcon("tab-close"));
986 closeTab->setText(i18nc("@action:inmenu File", "Close Tab"));
987 closeTab->setShortcut(Qt::CTRL | Qt::Key_W);
988 closeTab->setEnabled(false);
989 connect(closeTab, SIGNAL(triggered()), m_tabWidget, SLOT(closeTab()));
990
991 KStandardAction::quit(this, SLOT(quit()), actionCollection());
992
993 // setup 'Edit' menu
994 KStandardAction::undo(this,
995 SLOT(undo()),
996 actionCollection());
997
998 // need to remove shift+del from cut action, else the shortcut for deletejob
999 // doesn't work
1000 KAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection());
1001 KShortcut cutShortcut = cut->shortcut();
1002 cutShortcut.remove(Qt::SHIFT | Qt::Key_Delete, KShortcut::KeepEmpty);
1003 cut->setShortcut(cutShortcut);
1004 KStandardAction::copy(this, SLOT(copy()), actionCollection());
1005 KAction* paste = KStandardAction::paste(this, SLOT(paste()), actionCollection());
1006 // The text of the paste-action is modified dynamically by Dolphin
1007 // (e. g. to "Paste One Folder"). To prevent that the size of the toolbar changes
1008 // due to the long text, the text "Paste" is used:
1009 paste->setIconText(i18nc("@action:inmenu Edit", "Paste"));
1010
1011 KStandardAction::find(this, SLOT(find()), actionCollection());
1012
1013 KAction* selectAll = actionCollection()->addAction("select_all");
1014 selectAll->setText(i18nc("@action:inmenu Edit", "Select All"));
1015 selectAll->setShortcut(Qt::CTRL | Qt::Key_A);
1016 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
1017
1018 KAction* invertSelection = actionCollection()->addAction("invert_selection");
1019 invertSelection->setText(i18nc("@action:inmenu Edit", "Invert Selection"));
1020 invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
1021 connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
1022
1023 // setup 'View' menu
1024 // (note that most of it is set up in DolphinViewActionHandler)
1025
1026 KAction* split = actionCollection()->addAction("split_view");
1027 split->setShortcut(Qt::Key_F3);
1028 connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
1029
1030 KAction* reload = actionCollection()->addAction("reload");
1031 reload->setText(i18nc("@action:inmenu View", "Reload"));
1032 reload->setShortcut(Qt::Key_F5);
1033 reload->setIcon(KIcon("view-refresh"));
1034 connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
1035
1036 KAction* stop = actionCollection()->addAction("stop");
1037 stop->setText(i18nc("@action:inmenu View", "Stop"));
1038 stop->setToolTip(i18nc("@info", "Stop loading"));
1039 stop->setIcon(KIcon("process-stop"));
1040 connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
1041
1042 KToggleAction* editableLocation = actionCollection()->add<KToggleAction>("editable_location");
1043 editableLocation->setText(i18nc("@action:inmenu Navigation Bar", "Editable Location"));
1044 editableLocation->setShortcut(Qt::Key_F6);
1045 connect(editableLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
1046
1047 KAction* replaceLocation = actionCollection()->addAction("replace_location");
1048 replaceLocation->setText(i18nc("@action:inmenu Navigation Bar", "Replace Location"));
1049 replaceLocation->setShortcut(Qt::CTRL | Qt::Key_L);
1050 connect(replaceLocation, SIGNAL(triggered()), this, SLOT(replaceLocation()));
1051
1052 // setup 'Go' menu
1053 KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
1054 connect(backAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goBack(Qt::MouseButtons)));
1055 KShortcut backShortcut = backAction->shortcut();
1056 backShortcut.setAlternate(Qt::Key_Backspace);
1057 backAction->setShortcut(backShortcut);
1058
1059 DolphinRecentTabsMenu* recentTabsMenu = new DolphinRecentTabsMenu(this);
1060 actionCollection()->addAction("closed_tabs", recentTabsMenu);
1061 connect(m_tabWidget, SIGNAL(rememberClosedTab(KUrl,KUrl)),
1062 recentTabsMenu, SLOT(rememberClosedTab(KUrl,KUrl)));
1063 connect(recentTabsMenu, SIGNAL(restoreClosedTab(KUrl,KUrl)),
1064 this, SLOT(openNewActivatedTab(KUrl,KUrl)));
1065 connect(recentTabsMenu, SIGNAL(closedTabsCountChanged(uint)),
1066 this, SLOT(closedTabsCountChanged(uint)));
1067
1068 KAction* undoCloseTab = actionCollection()->addAction("undo_close_tab");
1069 undoCloseTab->setText(i18nc("@action:inmenu File", "Undo close tab"));
1070 undoCloseTab->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_T);
1071 undoCloseTab->setIcon(KIcon("edit-undo"));
1072 undoCloseTab->setEnabled(false);
1073 connect(undoCloseTab, SIGNAL(triggered()), recentTabsMenu, SLOT(undoCloseTab()));
1074
1075 KAction* forwardAction = KStandardAction::forward(this, SLOT(goForward()), actionCollection());
1076 connect(forwardAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goForward(Qt::MouseButtons)));
1077
1078 KAction* upAction = KStandardAction::up(this, SLOT(goUp()), actionCollection());
1079 connect(upAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goUp(Qt::MouseButtons)));
1080
1081 KAction* homeAction = KStandardAction::home(this, SLOT(goHome()), actionCollection());
1082 connect(homeAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goHome(Qt::MouseButtons)));
1083
1084 // setup 'Tools' menu
1085 KAction* showFilterBar = actionCollection()->addAction("show_filter_bar");
1086 showFilterBar->setText(i18nc("@action:inmenu Tools", "Show Filter Bar"));
1087 showFilterBar->setIcon(KIcon("view-filter"));
1088 showFilterBar->setShortcut(Qt::CTRL | Qt::Key_I);
1089 connect(showFilterBar, SIGNAL(triggered()), this, SLOT(showFilterBar()));
1090
1091 KAction* compareFiles = actionCollection()->addAction("compare_files");
1092 compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files"));
1093 compareFiles->setIcon(KIcon("kompare"));
1094 compareFiles->setEnabled(false);
1095 connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
1096
1097 KAction* openTerminal = actionCollection()->addAction("open_terminal");
1098 openTerminal->setText(i18nc("@action:inmenu Tools", "Open Terminal"));
1099 openTerminal->setIcon(KIcon("utilities-terminal"));
1100 openTerminal->setShortcut(Qt::SHIFT | Qt::Key_F4);
1101 connect(openTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));
1102
1103 // setup 'Settings' menu
1104 KToggleAction* showMenuBar = KStandardAction::showMenubar(0, 0, actionCollection());
1105 connect(showMenuBar, SIGNAL(triggered(bool)), // Fixes #286822
1106 this, SLOT(toggleShowMenuBar()), Qt::QueuedConnection);
1107 KStandardAction::preferences(this, SLOT(editSettings()), actionCollection());
1108
1109 // not in menu actions
1110 QList<QKeySequence> nextTabKeys;
1111 nextTabKeys.append(KStandardShortcut::tabNext().primary());
1112 nextTabKeys.append(QKeySequence(Qt::CTRL | Qt::Key_Tab));
1113
1114 QList<QKeySequence> prevTabKeys;
1115 prevTabKeys.append(KStandardShortcut::tabPrev().primary());
1116 prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab));
1117
1118 KAction* activateNextTab = actionCollection()->addAction("activate_next_tab");
1119 activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab"));
1120 activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab"));
1121 activateNextTab->setEnabled(false);
1122 connect(activateNextTab, SIGNAL(triggered()), m_tabWidget, SLOT(activateNextTab()));
1123 activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys);
1124
1125 KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab");
1126 activatePrevTab->setIconText(i18nc("@action:inmenu", "Previous Tab"));
1127 activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab"));
1128 activatePrevTab->setEnabled(false);
1129 connect(activatePrevTab, SIGNAL(triggered()), m_tabWidget, SLOT(activatePrevTab()));
1130 activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys);
1131
1132 // for context menu
1133 KAction* openInNewTab = actionCollection()->addAction("open_in_new_tab");
1134 openInNewTab->setText(i18nc("@action:inmenu", "Open in New Tab"));
1135 openInNewTab->setIcon(KIcon("tab-new"));
1136 connect(openInNewTab, SIGNAL(triggered()), this, SLOT(openInNewTab()));
1137
1138 KAction* openInNewTabs = actionCollection()->addAction("open_in_new_tabs");
1139 openInNewTabs->setText(i18nc("@action:inmenu", "Open in New Tabs"));
1140 openInNewTabs->setIcon(KIcon("tab-new"));
1141 connect(openInNewTabs, SIGNAL(triggered()), this, SLOT(openInNewTab()));
1142
1143 KAction* openInNewWindow = actionCollection()->addAction("open_in_new_window");
1144 openInNewWindow->setText(i18nc("@action:inmenu", "Open in New Window"));
1145 openInNewWindow->setIcon(KIcon("window-new"));
1146 connect(openInNewWindow, SIGNAL(triggered()), this, SLOT(openInNewWindow()));
1147 }
1148
1149 void DolphinMainWindow::setupDockWidgets()
1150 {
1151 const bool lock = GeneralSettings::lockPanels();
1152
1153 KDualAction* lockLayoutAction = actionCollection()->add<KDualAction>("lock_panels");
1154 lockLayoutAction->setActiveText(i18nc("@action:inmenu Panels", "Unlock Panels"));
1155 lockLayoutAction->setActiveIcon(KIcon("object-unlocked"));
1156 lockLayoutAction->setInactiveText(i18nc("@action:inmenu Panels", "Lock Panels"));
1157 lockLayoutAction->setInactiveIcon(KIcon("object-locked"));
1158 lockLayoutAction->setActive(lock);
1159 connect(lockLayoutAction, SIGNAL(triggered()), this, SLOT(togglePanelLockState()));
1160
1161 // Setup "Information"
1162 DolphinDockWidget* infoDock = new DolphinDockWidget(i18nc("@title:window", "Information"));
1163 infoDock->setLocked(lock);
1164 infoDock->setObjectName("infoDock");
1165 infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1166 Panel* infoPanel = new InformationPanel(infoDock);
1167 infoPanel->setCustomContextMenuActions(QList<QAction*>() << lockLayoutAction);
1168 connect(infoPanel, SIGNAL(urlActivated(KUrl)), this, SLOT(handleUrl(KUrl)));
1169 infoDock->setWidget(infoPanel);
1170
1171 QAction* infoAction = infoDock->toggleViewAction();
1172 createPanelAction(KIcon("dialog-information"), Qt::Key_F11, infoAction, "show_information_panel");
1173
1174 addDockWidget(Qt::RightDockWidgetArea, infoDock);
1175 connect(this, SIGNAL(urlChanged(KUrl)),
1176 infoPanel, SLOT(setUrl(KUrl)));
1177 connect(this, SIGNAL(selectionChanged(KFileItemList)),
1178 infoPanel, SLOT(setSelection(KFileItemList)));
1179 connect(this, SIGNAL(requestItemInfo(KFileItem)),
1180 infoPanel, SLOT(requestDelayedItemInfo(KFileItem)));
1181
1182 // Setup "Folders"
1183 DolphinDockWidget* foldersDock = new DolphinDockWidget(i18nc("@title:window", "Folders"));
1184 foldersDock->setLocked(lock);
1185 foldersDock->setObjectName("foldersDock");
1186 foldersDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1187 FoldersPanel* foldersPanel = new FoldersPanel(foldersDock);
1188 foldersPanel->setCustomContextMenuActions(QList<QAction*>() << lockLayoutAction);
1189 foldersDock->setWidget(foldersPanel);
1190
1191 QAction* foldersAction = foldersDock->toggleViewAction();
1192 createPanelAction(KIcon("folder"), Qt::Key_F7, foldersAction, "show_folders_panel");
1193
1194 addDockWidget(Qt::LeftDockWidgetArea, foldersDock);
1195 connect(this, SIGNAL(urlChanged(KUrl)),
1196 foldersPanel, SLOT(setUrl(KUrl)));
1197 connect(foldersPanel, SIGNAL(folderActivated(KUrl)),
1198 this, SLOT(changeUrl(KUrl)));
1199 connect(foldersPanel, SIGNAL(folderMiddleClicked(KUrl)),
1200 this, SLOT(openNewTab(KUrl)));
1201 connect(foldersPanel, SIGNAL(errorMessage(QString)),
1202 this, SLOT(slotPanelErrorMessage(QString)));
1203
1204 // Setup "Terminal"
1205 #ifndef Q_OS_WIN
1206 DolphinDockWidget* terminalDock = new DolphinDockWidget(i18nc("@title:window Shell terminal", "Terminal"));
1207 terminalDock->setLocked(lock);
1208 terminalDock->setObjectName("terminalDock");
1209 terminalDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
1210 Panel* terminalPanel = new TerminalPanel(terminalDock);
1211 terminalPanel->setCustomContextMenuActions(QList<QAction*>() << lockLayoutAction);
1212 terminalDock->setWidget(terminalPanel);
1213
1214 connect(terminalPanel, SIGNAL(hideTerminalPanel()), terminalDock, SLOT(hide()));
1215 connect(terminalPanel, SIGNAL(changeUrl(KUrl)), this, SLOT(slotTerminalDirectoryChanged(KUrl)));
1216 connect(terminalDock, SIGNAL(visibilityChanged(bool)),
1217 terminalPanel, SLOT(dockVisibilityChanged()));
1218
1219 QAction* terminalAction = terminalDock->toggleViewAction();
1220 createPanelAction(KIcon("utilities-terminal"), Qt::Key_F4, terminalAction, "show_terminal_panel");
1221
1222 addDockWidget(Qt::BottomDockWidgetArea, terminalDock);
1223 connect(this, SIGNAL(urlChanged(KUrl)),
1224 terminalPanel, SLOT(setUrl(KUrl)));
1225 #endif
1226
1227 if (GeneralSettings::version() < 200) {
1228 infoDock->hide();
1229 foldersDock->hide();
1230 #ifndef Q_OS_WIN
1231 terminalDock->hide();
1232 #endif
1233 }
1234
1235 // Setup "Places"
1236 DolphinDockWidget* placesDock = new DolphinDockWidget(i18nc("@title:window", "Places"));
1237 placesDock->setLocked(lock);
1238 placesDock->setObjectName("placesDock");
1239 placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
1240
1241 PlacesPanel* placesPanel = new PlacesPanel(placesDock);
1242 placesPanel->setCustomContextMenuActions(QList<QAction*>() << lockLayoutAction);
1243 placesDock->setWidget(placesPanel);
1244
1245 QAction* placesAction = placesDock->toggleViewAction();
1246 createPanelAction(KIcon("bookmarks"), Qt::Key_F9, placesAction, "show_places_panel");
1247
1248 addDockWidget(Qt::LeftDockWidgetArea, placesDock);
1249 connect(placesPanel, SIGNAL(placeActivated(KUrl)),
1250 this, SLOT(slotPlaceActivated(KUrl)));
1251 connect(placesPanel, SIGNAL(placeMiddleClicked(KUrl)),
1252 this, SLOT(openNewTab(KUrl)));
1253 connect(placesPanel, SIGNAL(errorMessage(QString)),
1254 this, SLOT(slotPanelErrorMessage(QString)));
1255 connect(this, SIGNAL(urlChanged(KUrl)),
1256 placesPanel, SLOT(setUrl(KUrl)));
1257 connect(placesDock, SIGNAL(visibilityChanged(bool)),
1258 m_tabWidget, SLOT(slotPlacesPanelVisibilityChanged(bool)));
1259 connect(this, SIGNAL(settingsChanged()),
1260 placesPanel, SLOT(readSettings()));
1261
1262 m_tabWidget->slotPlacesPanelVisibilityChanged(placesPanel->isVisible());
1263
1264 // Add actions into the "Panels" menu
1265 KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Panels"), this);
1266 actionCollection()->addAction("panels", panelsMenu);
1267 panelsMenu->setDelayed(false);
1268 const KActionCollection* ac = actionCollection();
1269 panelsMenu->addAction(ac->action("show_places_panel"));
1270 panelsMenu->addAction(ac->action("show_information_panel"));
1271 panelsMenu->addAction(ac->action("show_folders_panel"));
1272 #ifndef Q_OS_WIN
1273 panelsMenu->addAction(ac->action("show_terminal_panel"));
1274 #endif
1275 panelsMenu->addSeparator();
1276 panelsMenu->addAction(lockLayoutAction);
1277 }
1278
1279 void DolphinMainWindow::updateEditActions()
1280 {
1281 const KFileItemList list = m_activeViewContainer->view()->selectedItems();
1282 if (list.isEmpty()) {
1283 stateChanged("has_no_selection");
1284 } else {
1285 stateChanged("has_selection");
1286
1287 KActionCollection* col = actionCollection();
1288 QAction* renameAction = col->action("rename");
1289 QAction* moveToTrashAction = col->action("move_to_trash");
1290 QAction* deleteAction = col->action("delete");
1291 QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut));
1292 QAction* deleteWithTrashShortcut = col->action("delete_shortcut"); // see DolphinViewActionHandler
1293
1294 KFileItemListProperties capabilities(list);
1295 const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving();
1296
1297 renameAction->setEnabled(capabilities.supportsMoving());
1298 moveToTrashAction->setEnabled(enableMoveToTrash);
1299 deleteAction->setEnabled(capabilities.supportsDeleting());
1300 deleteWithTrashShortcut->setEnabled(capabilities.supportsDeleting() && !enableMoveToTrash);
1301 cutAction->setEnabled(capabilities.supportsMoving());
1302 }
1303 }
1304
1305 void DolphinMainWindow::updateViewActions()
1306 {
1307 m_actionHandler->updateViewActions();
1308
1309 QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
1310 showFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
1311
1312 updateSplitAction();
1313
1314 QAction* editableLocactionAction = actionCollection()->action("editable_location");
1315 const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
1316 editableLocactionAction->setChecked(urlNavigator->isUrlEditable());
1317 }
1318
1319 void DolphinMainWindow::updateGoActions()
1320 {
1321 QAction* goUpAction = actionCollection()->action(KStandardAction::name(KStandardAction::Up));
1322 const KUrl currentUrl = m_activeViewContainer->url();
1323 goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
1324 }
1325
1326 void DolphinMainWindow::createControlButton()
1327 {
1328 if (m_controlButton) {
1329 return;
1330 }
1331 Q_ASSERT(!m_controlButton);
1332
1333 m_controlButton = new QToolButton(this);
1334 m_controlButton->setIcon(KIcon("applications-system"));
1335 m_controlButton->setText(i18nc("@action", "Control"));
1336 m_controlButton->setPopupMode(QToolButton::InstantPopup);
1337 m_controlButton->setToolButtonStyle(toolBar()->toolButtonStyle());
1338
1339 KMenu* controlMenu = new KMenu(m_controlButton);
1340 connect(controlMenu, SIGNAL(aboutToShow()), this, SLOT(updateControlMenu()));
1341
1342 m_controlButton->setMenu(controlMenu);
1343
1344 toolBar()->addWidget(m_controlButton);
1345 connect(toolBar(), SIGNAL(iconSizeChanged(QSize)),
1346 m_controlButton, SLOT(setIconSize(QSize)));
1347 connect(toolBar(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
1348 m_controlButton, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
1349
1350 // The added widgets are owned by the toolbar and may get deleted when e.g. the toolbar
1351 // gets edited. In this case we must add them again. The adding is done asynchronously by
1352 // m_updateToolBarTimer.
1353 connect(m_controlButton, SIGNAL(destroyed()), this, SLOT(slotControlButtonDeleted()));
1354 m_updateToolBarTimer = new QTimer(this);
1355 m_updateToolBarTimer->setInterval(500);
1356 connect(m_updateToolBarTimer, SIGNAL(timeout()), this, SLOT(updateToolBar()));
1357 }
1358
1359 void DolphinMainWindow::deleteControlButton()
1360 {
1361 delete m_controlButton;
1362 m_controlButton = 0;
1363
1364 delete m_updateToolBarTimer;
1365 m_updateToolBarTimer = 0;
1366 }
1367
1368 bool DolphinMainWindow::addActionToMenu(QAction* action, KMenu* menu)
1369 {
1370 Q_ASSERT(action);
1371 Q_ASSERT(menu);
1372
1373 const KToolBar* toolBarWidget = toolBar();
1374 foreach (const QWidget* widget, action->associatedWidgets()) {
1375 if (widget == toolBarWidget) {
1376 return false;
1377 }
1378 }
1379
1380 menu->addAction(action);
1381 return true;
1382 }
1383
1384 void DolphinMainWindow::refreshViews()
1385 {
1386 m_tabWidget->refreshViews();
1387
1388 if (GeneralSettings::modifiedStartupSettings()) {
1389 // The startup settings have been changed by the user (see bug #254947).
1390 // Synchronize the split-view setting with the active view:
1391 const bool splitView = GeneralSettings::splitView();
1392 m_tabWidget->currentTabPage()->setSplitViewEnabled(splitView);
1393 updateSplitAction();
1394 }
1395
1396 emit settingsChanged();
1397 }
1398
1399 void DolphinMainWindow::clearStatusBar()
1400 {
1401 m_activeViewContainer->statusBar()->resetToDefaultText();
1402 }
1403
1404 void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
1405 {
1406 connect(container, SIGNAL(showFilterBarChanged(bool)),
1407 this, SLOT(updateFilterBarAction(bool)));
1408 connect(container, SIGNAL(writeStateChanged(bool)),
1409 this, SLOT(slotWriteStateChanged(bool)));
1410
1411 const DolphinView* view = container->view();
1412 connect(view, SIGNAL(selectionChanged(KFileItemList)),
1413 this, SLOT(slotSelectionChanged(KFileItemList)));
1414 connect(view, SIGNAL(requestItemInfo(KFileItem)),
1415 this, SLOT(slotRequestItemInfo(KFileItem)));
1416 connect(view, SIGNAL(tabRequested(KUrl)),
1417 this, SLOT(openNewTab(KUrl)));
1418 connect(view, SIGNAL(requestContextMenu(QPoint,KFileItem,KUrl,QList<QAction*>)),
1419 this, SLOT(openContextMenu(QPoint,KFileItem,KUrl,QList<QAction*>)));
1420 connect(view, SIGNAL(directoryLoadingStarted()),
1421 this, SLOT(enableStopAction()));
1422 connect(view, SIGNAL(directoryLoadingCompleted()),
1423 this, SLOT(disableStopAction()));
1424 connect(view, SIGNAL(goBackRequested()),
1425 this, SLOT(goBack()));
1426 connect(view, SIGNAL(goForwardRequested()),
1427 this, SLOT(goForward()));
1428
1429 const KUrlNavigator* navigator = container->urlNavigator();
1430 connect(navigator, SIGNAL(urlChanged(KUrl)),
1431 this, SLOT(changeUrl(KUrl)));
1432 connect(navigator, SIGNAL(historyChanged()),
1433 this, SLOT(updateHistory()));
1434 connect(navigator, SIGNAL(editableStateChanged(bool)),
1435 this, SLOT(slotEditableStateChanged(bool)));
1436 connect(navigator, SIGNAL(tabRequested(KUrl)),
1437 this, SLOT(openNewTab(KUrl)));
1438 }
1439
1440 void DolphinMainWindow::updateSplitAction()
1441 {
1442 QAction* splitAction = actionCollection()->action("split_view");
1443 const DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
1444 if (tabPage->splitViewEnabled()) {
1445 if (tabPage->primaryViewActive()) {
1446 splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
1447 splitAction->setToolTip(i18nc("@info", "Close left view"));
1448 splitAction->setIcon(KIcon("view-left-close"));
1449 } else {
1450 splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
1451 splitAction->setToolTip(i18nc("@info", "Close right view"));
1452 splitAction->setIcon(KIcon("view-right-close"));
1453 }
1454 } else {
1455 splitAction->setText(i18nc("@action:intoolbar Split view", "Split"));
1456 splitAction->setToolTip(i18nc("@info", "Split view"));
1457 splitAction->setIcon(KIcon("view-right-new"));
1458 }
1459 }
1460
1461 bool DolphinMainWindow::isKompareInstalled() const
1462 {
1463 static bool initialized = false;
1464 static bool installed = false;
1465 if (!initialized) {
1466 // TODO: maybe replace this approach later by using a menu
1467 // plugin like kdiff3plugin.cpp
1468 installed = !KGlobal::dirs()->findExe("kompare").isEmpty();
1469 initialized = true;
1470 }
1471 return installed;
1472 }
1473
1474 void DolphinMainWindow::setUrlAsCaption(const KUrl& url)
1475 {
1476 QString caption;
1477 if (!url.isLocalFile()) {
1478 caption.append(url.protocol() + " - ");
1479 if (url.hasHost()) {
1480 caption.append(url.host() + " - ");
1481 }
1482 }
1483
1484 const QString fileName = url.fileName().isEmpty() ? "/" : url.fileName();
1485 caption.append(fileName);
1486
1487 setCaption(caption);
1488 }
1489
1490 void DolphinMainWindow::createPanelAction(const KIcon& icon,
1491 const QKeySequence& shortcut,
1492 QAction* dockAction,
1493 const QString& actionName)
1494 {
1495 KAction* panelAction = actionCollection()->addAction(actionName);
1496 panelAction->setCheckable(true);
1497 panelAction->setChecked(dockAction->isChecked());
1498 panelAction->setText(dockAction->text());
1499 panelAction->setIcon(icon);
1500 panelAction->setShortcut(shortcut);
1501
1502 connect(panelAction, SIGNAL(triggered()), dockAction, SLOT(trigger()));
1503 connect(dockAction, SIGNAL(toggled(bool)), panelAction, SLOT(setChecked(bool)));
1504 }
1505
1506 DolphinMainWindow::UndoUiInterface::UndoUiInterface() :
1507 KIO::FileUndoManager::UiInterface()
1508 {
1509 }
1510
1511 DolphinMainWindow::UndoUiInterface::~UndoUiInterface()
1512 {
1513 }
1514
1515 void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)
1516 {
1517 DolphinMainWindow* mainWin= qobject_cast<DolphinMainWindow *>(parentWidget());
1518 if (mainWin) {
1519 DolphinViewContainer* container = mainWin->activeViewContainer();
1520 container->showMessage(job->errorString(), DolphinViewContainer::Error);
1521 } else {
1522 KIO::FileUndoManager::UiInterface::jobError(job);
1523 }
1524 }
1525
1526 #include "dolphinmainwindow.moc"