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