#include "dolphincontextmenu.h"
#include "dolphinnewfilemenu.h"
#include "dolphinrecenttabsmenu.h"
-#include "dolphintabbar.h"
+#include "dolphintabwidget.h"
#include "dolphinviewcontainer.h"
#include "dolphintabpage.h"
#include "panels/folders/folderspanel.h"
DolphinMainWindow::DolphinMainWindow() :
KXmlGuiWindow(0),
m_newFileMenu(0),
- m_tabBar(0),
+ m_tabWidget(0),
m_activeViewContainer(0),
- m_centralWidgetLayout(0),
- m_tabIndex(-1),
- m_viewTab(),
m_actionHandler(0),
m_remoteEncoding(0),
m_settingsDialog(),
setAcceptDrops(true);
+ m_tabWidget = new DolphinTabWidget(this);
+ connect(m_tabWidget, SIGNAL(activeViewChanged(DolphinViewContainer*)),
+ this, SLOT(activeViewChanged(DolphinViewContainer*)));
+ connect(m_tabWidget, SIGNAL(tabCountChanged(int)),
+ this, SLOT(tabCountChanged(int)));
+ setCentralWidget(m_tabWidget);
+
setupActions();
m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
connect(this, SIGNAL(urlChanged(KUrl)),
m_remoteEncoding, SLOT(slotAboutToOpenUrl()));
- m_tabBar = new DolphinTabBar(this);
- connect(m_tabBar, SIGNAL(currentChanged(int)),
- this, SLOT(setActiveTab(int)));
- connect(m_tabBar, SIGNAL(tabCloseRequested(int)),
- this, SLOT(closeTab(int)));
- connect(m_tabBar, SIGNAL(openNewActivatedTab(int)),
- this, SLOT(openNewActivatedTab(int)));
- connect(m_tabBar, SIGNAL(tabMoved(int,int)),
- this, SLOT(slotTabMoved(int,int)));
- connect(m_tabBar, SIGNAL(tabDropEvent(int,QDropEvent*)),
- this, SLOT(tabDropEvent(int,QDropEvent*)));
- connect(m_tabBar, SIGNAL(tabDetachRequested(int)),
- this, SLOT(detachTab(int)));
-
- m_tabBar->blockSignals(true); // signals get unblocked after at least 2 tabs are open
- m_tabBar->hide();
-
- QWidget* centralWidget = new QWidget(this);
- m_centralWidgetLayout = new QVBoxLayout(centralWidget);
- m_centralWidgetLayout->setSpacing(0);
- m_centralWidgetLayout->setMargin(0);
- m_centralWidgetLayout->addWidget(m_tabBar);
-
- setCentralWidget(centralWidget);
setupDockWidgets();
setupGUI(Keys | Save | Create | ToolBar);
void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
{
- const bool hasSplitView = GeneralSettings::splitView();
-
- // Open each directory inside a new tab. If the "split view" option has been enabled,
- // always show two directories within one tab.
- QList<KUrl>::const_iterator it = dirs.constBegin();
- while (it != dirs.constEnd()) {
- const KUrl& primaryUrl = *(it++);
- if (hasSplitView && (it != dirs.constEnd())) {
- const KUrl& secondaryUrl = *(it++);
- openNewTab(primaryUrl, secondaryUrl);
- } else {
- openNewTab(primaryUrl);
- }
- }
+ m_tabWidget->openDirectories(dirs);
}
void DolphinMainWindow::openFiles(const QList<KUrl>& files)
{
- if (files.isEmpty()) {
- return;
- }
-
- // Get all distinct directories from 'files' and open a tab
- // for each directory. If the "split view" option is enabled, two
- // directories are shown inside one tab (see openDirectories()).
- QList<KUrl> dirs;
- foreach (const KUrl& url, files) {
- const KUrl dir(url.directory());
- if (!dirs.contains(dir)) {
- dirs.append(dir);
- }
- }
-
- openDirectories(dirs);
-
- // Select the files. Although the files can be split between several
- // tabs, there is no need to split 'files' accordingly, as
- // the DolphinView will just ignore invalid selections.
- foreach (DolphinTabPage* tabPage, m_viewTab) {
- tabPage->markUrlsAsSelected(files);
- tabPage->markUrlAsCurrent(files.first());
- }
+ m_tabWidget->openFiles(files);
}
void DolphinMainWindow::showCommand(CommandType command)
return;
}
- DolphinViewContainer* view = activeViewContainer();
- if (view) {
- view->setUrl(url);
- updateEditActions();
- updatePasteAction();
- updateViewActions();
- updateGoActions();
- setUrlAsCaption(url);
-
- const QString iconName = KMimeType::iconNameForUrl(url);
- m_tabBar->setTabIcon(m_tabIndex, KIcon(iconName));
- m_tabBar->setTabText(m_tabIndex, squeezedText(tabName(view->url())));
-
- emit urlChanged(url);
- }
+ m_activeViewContainer->setUrl(url);
+ updateEditActions();
+ updatePasteAction();
+ updateViewActions();
+ updateGoActions();
+ setUrlAsCaption(url);
+
+ emit urlChanged(url);
}
void DolphinMainWindow::slotTerminalDirectoryChanged(const KUrl& url)
{
updateEditActions();
- const int selectedUrlsCount = m_viewTab.at(m_tabIndex)->selectedItemsCount();
+ const int selectedUrlsCount = m_tabWidget->currentTabPage()->selectedItemsCount();
QAction* compareFilesAction = actionCollection()->action("compare_files");
if (selectedUrlsCount == 2) {
KRun::run("dolphin %u", KUrl::List(), this);
}
-void DolphinMainWindow::openNewTab()
+void DolphinMainWindow::openNewActivatedTab()
{
- const bool isUrlEditable = m_activeViewContainer->urlNavigator()->isUrlEditable();
-
- openNewTab(m_activeViewContainer->url());
- m_tabBar->setCurrentIndex(m_viewTab.count() - 1);
-
- // The URL navigator of the new tab should have the same editable state
- // as the current tab
- KUrlNavigator* navigator = m_activeViewContainer->urlNavigator();
- navigator->setUrlEditable(isUrlEditable);
-
- if (isUrlEditable) {
- // If a new tab is opened and the URL is editable, assure that
- // the user can edit the URL without manually setting the focus
- navigator->setFocus();
- }
+ m_tabWidget->openNewActivatedTab();
}
void DolphinMainWindow::openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
{
- QWidget* focusWidget = QApplication::focusWidget();
-
- DolphinTabPage* tabPage = new DolphinTabPage(primaryUrl, secondaryUrl, this);
- m_viewTab.append(tabPage);
-
- connect(tabPage, SIGNAL(activeViewChanged()),
- this, SLOT(activeViewChanged()));
-
- // The places-selector from the URL navigator should only be shown
- // if the places dock is invisible
- QDockWidget* placesDock = findChild<QDockWidget*>("placesDock");
- const bool placesSelectorVisible = !placesDock || !placesDock->isVisible();
- tabPage->setPlacesSelectorVisible(placesSelectorVisible);
-
- DolphinViewContainer* primaryContainer = tabPage->primaryViewContainer();
- connectViewSignals(primaryContainer);
-
- if (tabPage->splitViewEnabled()) {
- DolphinViewContainer* secondaryContainer = tabPage->secondaryViewContainer();
- connectViewSignals(secondaryContainer);
- }
-
- tabPage->hide();
-
- m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(primaryUrl)),
- squeezedText(tabName(primaryUrl)));
-
- if (m_viewTab.count() > 1) {
- actionCollection()->action("close_tab")->setEnabled(true);
- actionCollection()->action("activate_prev_tab")->setEnabled(true);
- actionCollection()->action("activate_next_tab")->setEnabled(true);
- m_tabBar->show();
- m_tabBar->blockSignals(false);
- }
-
- if (focusWidget) {
- // The DolphinViewContainer grabbed the keyboard focus. As the tab is opened
- // in background, assure that the previous focused widget gets the focus back.
- focusWidget->setFocus();
- }
+ m_tabWidget->openNewTab(primaryUrl, secondaryUrl);
}
void DolphinMainWindow::openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
{
- openNewTab(primaryUrl, secondaryUrl);
- setActiveTab(m_viewTab.count() - 1);
-}
-
-void DolphinMainWindow::openNewActivatedTab(int index)
-{
- Q_ASSERT(index >= 0);
- const DolphinTabPage* tabPage = m_viewTab.at(index);
- openNewActivatedTab(tabPage->activeViewContainer()->url());
-}
-
-void DolphinMainWindow::activateNextTab()
-{
- if (m_viewTab.count() >= 2) {
- const int tabIndex = (m_tabBar->currentIndex() + 1) % m_tabBar->count();
- setActiveTab(tabIndex);
- }
-}
-
-void DolphinMainWindow::activatePrevTab()
-{
- if (m_viewTab.count() >= 2) {
- int tabIndex = m_tabBar->currentIndex() - 1;
- if (tabIndex == -1) {
- tabIndex = m_tabBar->count() - 1;
- }
- setActiveTab(tabIndex);
- }
+ m_tabWidget->openNewActivatedTab(primaryUrl, secondaryUrl);
}
void DolphinMainWindow::openInNewTab()
{
KXmlGuiWindow::showEvent(event);
- if (!m_activeViewContainer && m_viewTab.count() > 0) {
- // If we have no active view container yet, we set the primary view container
- // of the first tab as active view container.
- setActiveTab(0);
- }
-
if (!event->spontaneous()) {
m_activeViewContainer->view()->setFocus();
}
closedByUser = false;
}
- if (m_viewTab.count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) {
+ if (m_tabWidget->count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) {
// Ask the user if he really wants to quit and close all tabs.
// Open a confirmation dialog with 3 buttons:
// KDialog::Yes -> Quit
break;
case KDialog::No:
// Close only the current tab
- closeTab();
+ m_tabWidget->closeTab();
default:
event->ignore();
return;
void DolphinMainWindow::saveProperties(KConfigGroup& group)
{
- const int tabCount = m_viewTab.count();
- group.writeEntry("Tab Count", tabCount);
- group.writeEntry("Active Tab Index", m_tabBar->currentIndex());
-
- for (int i = 0; i < tabCount; ++i) {
- const DolphinTabPage* tabPage = m_viewTab.at(i);
- group.writeEntry("Tab " % QString::number(i), tabPage->saveState());
- }
+ m_tabWidget->saveProperties(group);
}
void DolphinMainWindow::readProperties(const KConfigGroup& group)
{
- const int tabCount = group.readEntry("Tab Count", 1);
- for (int i = 0; i < tabCount; ++i) {
- const QByteArray state = group.readEntry("Tab " % QString::number(i), QByteArray());
- DolphinTabPage* tabPage = m_viewTab.at(i);
- tabPage->restoreState(state);
-
- // openNewTab() needs to be called only tabCount - 1 times
- if (i != tabCount - 1) {
- openNewTab();
- }
- }
-
- const int index = group.readEntry("Active Tab Index", 0);
- m_tabBar->setCurrentIndex(index);
+ m_tabWidget->readProperties(group);
}
void DolphinMainWindow::updateNewMenu()
void DolphinMainWindow::toggleSplitView()
{
- DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
+ DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
tabPage->setSplitViewEnabled(!tabPage->splitViewEnabled());
- if (tabPage->splitViewEnabled()) {
- connectViewSignals(tabPage->secondaryViewContainer());
- }
-
updateViewActions();
}
GeneralSettings::setLockPanels(newLockState);
}
-void DolphinMainWindow::slotPlacesPanelVisibilityChanged(bool visible)
-{
- foreach (DolphinTabPage* tabPage, m_viewTab) {
- // The Places selector in the location bar should be shown if and only if the Places panel is hidden.
- tabPage->setPlacesSelectorVisible(!visible);
- }
-}
-
void DolphinMainWindow::goBack()
{
KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
void DolphinMainWindow::compareFiles()
{
- const KFileItemList items = m_viewTab.at(m_tabIndex)->selectedItems();
+ const KFileItemList items = m_tabWidget->currentTabPage()->selectedItems();
if (items.count() != 2) {
// The action is disabled in this case, but it could have been triggered
// via D-Bus, see https://bugs.kde.org/show_bug.cgi?id=325517
}
}
-void DolphinMainWindow::setActiveTab(int index)
-{
- Q_ASSERT(index >= 0);
- Q_ASSERT(index < m_viewTab.count());
- if (index == m_tabIndex) {
- return;
- }
-
- m_tabBar->setCurrentIndex(index);
-
- // hide current tab content
- if (m_tabIndex >= 0) {
- DolphinTabPage* hiddenTabPage = m_viewTab.at(m_tabIndex);
- hiddenTabPage->hide();
- m_centralWidgetLayout->removeWidget(hiddenTabPage);
- }
-
- // show active tab content
- m_tabIndex = index;
-
- DolphinTabPage* tabPage = m_viewTab.at(index);
- m_centralWidgetLayout->addWidget(tabPage, 1);
- tabPage->show();
-
- setActiveViewContainer(tabPage->activeViewContainer());
-}
-
-void DolphinMainWindow::closeTab()
-{
- closeTab(m_tabBar->currentIndex());
-}
-
-void DolphinMainWindow::closeTab(int index)
-{
- Q_ASSERT(index >= 0);
- Q_ASSERT(index < m_viewTab.count());
- if (m_viewTab.count() == 1) {
- // the last tab may never get closed
- return;
- }
-
- if (index == m_tabIndex) {
- // The tab that should be closed is the active tab. Activate the
- // previous tab before closing the tab.
- m_tabBar->setCurrentIndex((index > 0) ? index - 1 : 1);
- }
-
- DolphinTabPage* tabPage = m_viewTab.at(index);
-
- if (tabPage->splitViewEnabled()) {
- emit rememberClosedTab(tabPage->primaryViewContainer()->url(),
- tabPage->secondaryViewContainer()->url());
- } else {
- emit rememberClosedTab(tabPage->primaryViewContainer()->url(), KUrl());
- }
-
- // delete tab
- m_viewTab.removeAt(index);
- tabPage->deleteLater();
-
- m_tabBar->blockSignals(true);
- m_tabBar->removeTab(index);
-
- if (m_tabIndex > index) {
- m_tabIndex--;
- Q_ASSERT(m_tabIndex >= 0);
- }
-
- // if only one tab is left, also remove the tab entry so that
- // closing the last tab is not possible
- if (m_viewTab.count() < 2) {
- actionCollection()->action("close_tab")->setEnabled(false);
- actionCollection()->action("activate_prev_tab")->setEnabled(false);
- actionCollection()->action("activate_next_tab")->setEnabled(false);
- m_tabBar->hide();
- } else {
- m_tabBar->blockSignals(false);
- }
-}
-
-void DolphinMainWindow::detachTab(int index)
-{
- Q_ASSERT(index >= 0);
-
- const QString separator(QLatin1Char(' '));
- QString command = QLatin1String("dolphin");
-
- const DolphinTabPage* tabPage = m_viewTab.at(index);
- command += separator + tabPage->primaryViewContainer()->url().url();
- if (tabPage->splitViewEnabled()) {
- command += separator + tabPage->secondaryViewContainer()->url().url();
- command += separator + QLatin1String("-split");
- }
-
- KRun::runCommand(command, this);
-
- closeTab(index);
-}
-
-void DolphinMainWindow::slotTabMoved(int from, int to)
-{
- m_viewTab.move(from, to);
- m_tabIndex = m_tabBar->currentIndex();
-}
-
void DolphinMainWindow::handleUrl(const KUrl& url)
{
delete m_lastHandleUrlStatJob;
}
}
-void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event)
-{
- const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
- if (!urls.isEmpty() && tab != -1) {
- const DolphinView* view = m_viewTab.at(tab)->activeViewContainer()->view();
-
- QString error;
- DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error);
- if (!error.isEmpty()) {
- activeViewContainer()->showMessage(error, DolphinViewContainer::Error);
- }
- }
-}
-
void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable)
{
newFileMenu()->setEnabled(isFolderWritable);
}
}
-void DolphinMainWindow::activeViewChanged()
-{
- const DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
- setActiveViewContainer(tabPage->activeViewContainer());
-}
-
void DolphinMainWindow::closedTabsCountChanged(unsigned int count)
{
actionCollection()->action("undo_close_tab")->setEnabled(count > 0);
}
-void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer)
+void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
{
+ DolphinViewContainer* oldViewContainer = m_activeViewContainer;
Q_ASSERT(viewContainer);
- Q_ASSERT((viewContainer == m_viewTab.at(m_tabIndex)->primaryViewContainer()) ||
- (viewContainer == m_viewTab.at(m_tabIndex)->secondaryViewContainer()));
- if (m_activeViewContainer == viewContainer) {
- return;
- }
m_activeViewContainer = viewContainer;
+
+ if (oldViewContainer) {
+ // Disconnect all signals between the old view container (container,
+ // view and url navigator) and main window.
+ oldViewContainer->disconnect(this);
+ oldViewContainer->view()->disconnect(this);
+ oldViewContainer->urlNavigator()->disconnect(this);
+ }
+
+ connectViewSignals(viewContainer);
+
m_actionHandler->setCurrentView(viewContainer->view());
updateHistory();
updateViewActions();
updateGoActions();
- const KUrl url = m_activeViewContainer->url();
+ const KUrl url = viewContainer->url();
setUrlAsCaption(url);
- m_tabBar->setTabText(m_tabIndex, squeezedText(tabName(url)));
- m_tabBar->setTabIcon(m_tabIndex, KIcon(KMimeType::iconNameForUrl(url)));
emit urlChanged(url);
}
+void DolphinMainWindow::tabCountChanged(int count)
+{
+ const bool enableTabActions = (count > 1);
+ actionCollection()->action("close_tab")->setEnabled(enableTabActions);
+ actionCollection()->action("activate_next_tab")->setEnabled(enableTabActions);
+ actionCollection()->action("activate_prev_tab")->setEnabled(enableTabActions);
+}
+
void DolphinMainWindow::setupActions()
{
// setup 'File' menu
newTab->setIcon(KIcon("tab-new"));
newTab->setText(i18nc("@action:inmenu File", "New Tab"));
newTab->setShortcut(KShortcut(Qt::CTRL | Qt::Key_T, Qt::CTRL | Qt::SHIFT | Qt::Key_N));
- connect(newTab, SIGNAL(triggered()), this, SLOT(openNewTab()));
+ connect(newTab, SIGNAL(triggered()), this, SLOT(openNewActivatedTab()));
KAction* closeTab = actionCollection()->addAction("close_tab");
closeTab->setIcon(KIcon("tab-close"));
closeTab->setText(i18nc("@action:inmenu File", "Close Tab"));
closeTab->setShortcut(Qt::CTRL | Qt::Key_W);
closeTab->setEnabled(false);
- connect(closeTab, SIGNAL(triggered()), this, SLOT(closeTab()));
+ connect(closeTab, SIGNAL(triggered()), m_tabWidget, SLOT(closeTab()));
KStandardAction::quit(this, SLOT(quit()), actionCollection());
DolphinRecentTabsMenu* recentTabsMenu = new DolphinRecentTabsMenu(this);
actionCollection()->addAction("closed_tabs", recentTabsMenu);
- connect(this, SIGNAL(rememberClosedTab(KUrl,KUrl)),
+ connect(m_tabWidget, SIGNAL(rememberClosedTab(KUrl,KUrl)),
recentTabsMenu, SLOT(rememberClosedTab(KUrl,KUrl)));
connect(recentTabsMenu, SIGNAL(restoreClosedTab(KUrl,KUrl)),
this, SLOT(openNewActivatedTab(KUrl,KUrl)));
activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab"));
activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab"));
activateNextTab->setEnabled(false);
- connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab()));
+ connect(activateNextTab, SIGNAL(triggered()), m_tabWidget, SLOT(activateNextTab()));
activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys);
KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab");
activatePrevTab->setIconText(i18nc("@action:inmenu", "Previous Tab"));
activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab"));
activatePrevTab->setEnabled(false);
- connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab()));
+ connect(activatePrevTab, SIGNAL(triggered()), m_tabWidget, SLOT(activatePrevTab()));
activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys);
// for context menu
connect(this, SIGNAL(urlChanged(KUrl)),
placesPanel, SLOT(setUrl(KUrl)));
connect(placesDock, SIGNAL(visibilityChanged(bool)),
- this, SLOT(slotPlacesPanelVisibilityChanged(bool)));
+ m_tabWidget, SLOT(slotPlacesPanelVisibilityChanged(bool)));
connect(this, SIGNAL(settingsChanged()),
placesPanel, SLOT(readSettings()));
+ m_tabWidget->slotPlacesPanelVisibilityChanged(placesPanel->isVisible());
+
// Add actions into the "Panels" menu
KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Panels"), this);
actionCollection()->addAction("panels", panelsMenu);
void DolphinMainWindow::refreshViews()
{
- foreach (DolphinTabPage* tabPage, m_viewTab) {
- tabPage->refreshViews();
- }
+ m_tabWidget->refreshViews();
if (GeneralSettings::modifiedStartupSettings()) {
// The startup settings have been changed by the user (see bug #254947).
// Synchronize the split-view setting with the active view:
const bool splitView = GeneralSettings::splitView();
- m_viewTab.at(m_tabIndex)->setSplitViewEnabled(splitView);
+ m_tabWidget->currentTabPage()->setSplitViewEnabled(splitView);
updateSplitAction();
}
void DolphinMainWindow::updateSplitAction()
{
QAction* splitAction = actionCollection()->action("split_view");
- const DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
+ const DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
if (tabPage->splitViewEnabled()) {
if (tabPage->primaryViewActive()) {
splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
}
}
-QString DolphinMainWindow::tabName(const KUrl& url) const
-{
- QString name;
- if (url.equals(KUrl("file:///"))) {
- name = '/';
- } else {
- name = url.fileName();
- if (name.isEmpty()) {
- name = url.protocol();
- } else {
- // Make sure that a '&' inside the directory name is displayed correctly
- // and not misinterpreted as a keyboard shortcut in QTabBar::setTabText()
- name.replace('&', "&&");
- }
- }
- return name;
-}
-
bool DolphinMainWindow::isKompareInstalled() const
{
static bool initialized = false;
setCaption(caption);
}
-QString DolphinMainWindow::squeezedText(const QString& text) const
-{
- const QFontMetrics fm = fontMetrics();
- return fm.elidedText(text, Qt::ElideMiddle, fm.maxWidth() * 10);
-}
-
void DolphinMainWindow::createPanelAction(const KIcon& icon,
const QKeySequence& shortcut,
QAction* dockAction,
class DolphinViewActionHandler;
class DolphinApplication;
class DolphinSettingsDialog;
-class DolphinTabBar;
class DolphinViewContainer;
class DolphinRemoteEncoding;
-class DolphinTabPage;
+class DolphinTabWidget;
class KAction;
class KFileItem;
class KFileItemList;
class KJob;
class KNewFileMenu;
class KUrl;
-class QSplitter;
class QToolButton;
-class QVBoxLayout;
/**
* @short Main window for Dolphin.
*/
void settingsChanged();
- /**
- * Is emitted when a tab has been closed.
- */
- void rememberClosedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl);
-
protected:
/** @see QWidget::showEvent() */
virtual void showEvent(QShowEvent* event);
*/
void togglePanelLockState();
- /**
- * Is invoked if the Places panel got visible/invisible and takes care
- * that the places-selector of all views is only shown if the Places panel
- * is invisible.
- */
- void slotPlacesPanelVisibilityChanged(bool visible);
-
/** Goes back one step of the URL history. */
void goBack();
/** Open a new main window. */
void openNewMainWindow();
- /** Opens a new view with the current URL that is part of a tab. */
- void openNewTab();
+ /**
+ * Opens a new view with the current URL that is part of a tab and
+ * activates it.
+ */
+ void openNewActivatedTab();
/**
* Opens a new tab in the background showing the URL \a primaryUrl and the
*/
void openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl());
- /**
- * Opens a new tab showing the url from tab at the given \a index and
- * activates the tab.
- */
- void openNewActivatedTab(int index);
-
- void activateNextTab();
-
- void activatePrevTab();
-
/**
* Opens the selected folder in a new tab.
*/
*/
void showCommand(CommandType command);
- /**
- * Activates the tab with the index \a index, which means that the current view
- * is replaced by the view of the given tab.
- */
- void setActiveTab(int index);
-
- /** Closes the currently active tab. */
- void closeTab();
-
- /**
- * Closes the tab with the index \a index and activates the tab with index - 1.
- */
- void closeTab(int index);
-
- /**
- * Opens the tab with the index \a index in a new Dolphin instance and closes
- * this tab.
- */
- void detachTab(int index);
-
- /**
- * Is connected to the QTabBar signal tabMoved(int from, int to).
- * Reorders the list of tabs after a tab was moved in the tab bar
- * and sets m_tabIndex to the new index of the current tab.
- */
- void slotTabMoved(int from, int to);
-
/**
* If the URL can be listed, open it in the current view, otherwise
* run it through KRun.
*/
void slotHandleUrlStatFinished(KJob* job);
- /**
- * Is connected to the KTabBar signal receivedDropEvent.
- * Allows dragging and dropping files onto tabs.
- */
- void tabDropEvent(int tab, QDropEvent* event);
-
/**
* Is invoked when the write state of a folder has been changed and
* enables/disables the "Create New..." menu entry.
*/
void slotPlaceActivated(const KUrl& url);
- void activeViewChanged();
+ /**
+ * Is called if the another view has been activated by changing the current
+ * tab or activating another view in split-view mode.
+ *
+ * Activates the given view, which means that all menu actions are applied
+ * to this view. When having a split view setup, the nonactive view is
+ * usually shown in darker colors.
+ */
+ void activeViewChanged(DolphinViewContainer* viewContainer);
void closedTabsCountChanged(unsigned int count);
-private:
/**
- * Activates the given view, which means that
- * all menu actions are applied to this view. When
- * having a split view setup, the nonactive view
- * is usually shown in darker colors.
+ * Is called if a new tab has been opened or a tab has been closed to
+ * enable/disable the tab actions.
*/
- void setActiveViewContainer(DolphinViewContainer* view);
+ void tabCountChanged(int count);
+private:
void setupActions();
void setupDockWidgets();
void updateEditActions();
*/
void updateSplitAction();
- /** Returns the name of the tab for the URL \a url. */
- QString tabName(const KUrl& url) const;
-
-
bool isKompareInstalled() const;
/**
*/
void setUrlAsCaption(const KUrl& url);
- QString squeezedText(const QString& text) const;
-
/**
* Creates an action for showing/hiding a panel, that is accessible
* in "Configure toolbars..." and "Configure shortcuts...". This is necessary
};
KNewFileMenu* m_newFileMenu;
- DolphinTabBar* m_tabBar;
+ DolphinTabWidget* m_tabWidget;
DolphinViewContainer* m_activeViewContainer;
- QVBoxLayout* m_centralWidgetLayout;
int m_id;
- int m_tabIndex;
- QList<DolphinTabPage*> m_viewTab;
-
DolphinViewActionHandler* m_actionHandler;
DolphinRemoteEncoding* m_remoteEncoding;
QWeakPointer<DolphinSettingsDialog> m_settingsDialog;
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Emmanuel Pescosta <emmanuelpescosta099@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "dolphintabwidget.h"
+
+#include "dolphintabbar.h"
+#include "dolphintabpage.h"
+#include "dolphinviewcontainer.h"
+#include "dolphin_generalsettings.h"
+#include "views/draganddrophelper.h"
+
+#include <QApplication>
+#include <KConfigGroup>
+#include <KIcon>
+#include <KRun>
+
+DolphinTabWidget::DolphinTabWidget(QWidget* parent) :
+ QTabWidget(parent),
+ m_placesSelectorVisible(true)
+{
+ connect(this, SIGNAL(tabCloseRequested(int)),
+ this, SLOT(closeTab(int)));
+ connect(this, SIGNAL(currentChanged(int)),
+ this, SLOT(currentTabChanged(int)));
+
+ DolphinTabBar* tabBar = new DolphinTabBar(this);
+ connect(tabBar, SIGNAL(openNewActivatedTab(int)),
+ this, SLOT(openNewActivatedTab(int)));
+ connect(tabBar, SIGNAL(tabDropEvent(int,QDropEvent*)),
+ this, SLOT(tabDropEvent(int,QDropEvent*)));
+ connect(tabBar, SIGNAL(tabDetachRequested(int)),
+ this, SLOT(detachTab(int)));
+ tabBar->hide();
+
+ setTabBar(tabBar);
+ setDocumentMode(true);
+ setElideMode(Qt::ElideRight);
+ setUsesScrollButtons(true);
+}
+
+DolphinTabPage* DolphinTabWidget::currentTabPage() const
+{
+ return tabPageAt(currentIndex());
+}
+
+DolphinTabPage* DolphinTabWidget::tabPageAt(const int index) const
+{
+ return static_cast<DolphinTabPage*>(widget(index));
+}
+
+void DolphinTabWidget::saveProperties(KConfigGroup& group) const
+{
+ const int tabCount = count();
+ group.writeEntry("Tab Count", tabCount);
+ group.writeEntry("Active Tab Index", currentIndex());
+
+ for (int i = 0; i < tabCount; ++i) {
+ const DolphinTabPage* tabPage = tabPageAt(i);
+ group.writeEntry("Tab " % QString::number(i), tabPage->saveState());
+ }
+}
+
+void DolphinTabWidget::readProperties(const KConfigGroup& group)
+{
+ const int tabCount = group.readEntry("Tab Count", 0);
+ for (int i = 0; i < tabCount; ++i) {
+ if (i >= count()) {
+ openNewActivatedTab();
+ }
+ const QByteArray state = group.readEntry("Tab " % QString::number(i), QByteArray());
+ tabPageAt(i)->restoreState(state);
+ }
+
+ const int index = group.readEntry("Active Tab Index", 0);
+ setCurrentIndex(index);
+}
+
+void DolphinTabWidget::refreshViews()
+{
+ const int tabCount = count();
+ for (int i = 0; i < tabCount; ++i) {
+ tabPageAt(i)->refreshViews();
+ }
+}
+
+void DolphinTabWidget::openNewActivatedTab()
+{
+ const DolphinViewContainer* oldActiveViewContainer = currentTabPage()->activeViewContainer();
+ Q_ASSERT(oldActiveViewContainer);
+
+ const bool isUrlEditable = oldActiveViewContainer->urlNavigator()->isUrlEditable();
+
+ openNewActivatedTab(oldActiveViewContainer->url());
+
+ DolphinViewContainer* newActiveViewContainer = currentTabPage()->activeViewContainer();
+ Q_ASSERT(newActiveViewContainer);
+
+ // The URL navigator of the new tab should have the same editable state
+ // as the current tab
+ KUrlNavigator* navigator = newActiveViewContainer->urlNavigator();
+ navigator->setUrlEditable(isUrlEditable);
+
+ if (isUrlEditable) {
+ // If a new tab is opened and the URL is editable, assure that
+ // the user can edit the URL without manually setting the focus
+ navigator->setFocus();
+ }
+}
+
+void DolphinTabWidget::openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
+{
+ openNewTab(primaryUrl, secondaryUrl);
+ setCurrentIndex(count() - 1);
+}
+
+void DolphinTabWidget::openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
+{
+ QWidget* focusWidget = QApplication::focusWidget();
+
+ DolphinTabPage* tabPage = new DolphinTabPage(primaryUrl, secondaryUrl, this);
+ tabPage->setPlacesSelectorVisible(m_placesSelectorVisible);
+ connect(tabPage, SIGNAL(activeViewChanged(DolphinViewContainer*)),
+ this, SIGNAL(activeViewChanged(DolphinViewContainer*)));
+ connect(tabPage, SIGNAL(activeViewUrlChanged(KUrl)),
+ this, SLOT(tabUrlChanged(KUrl)));
+ addTab(tabPage, KIcon(KMimeType::iconNameForUrl(primaryUrl)), tabName(primaryUrl));
+
+ if (focusWidget) {
+ // The DolphinViewContainer grabbed the keyboard focus. As the tab is opened
+ // in background, assure that the previous focused widget gets the focus back.
+ focusWidget->setFocus();
+ }
+}
+
+void DolphinTabWidget::openDirectories(const QList<KUrl>& dirs)
+{
+ const bool hasSplitView = GeneralSettings::splitView();
+
+ // Open each directory inside a new tab. If the "split view" option has been enabled,
+ // always show two directories within one tab.
+ QList<KUrl>::const_iterator it = dirs.constBegin();
+ while (it != dirs.constEnd()) {
+ const KUrl& primaryUrl = *(it++);
+ if (hasSplitView && (it != dirs.constEnd())) {
+ const KUrl& secondaryUrl = *(it++);
+ openNewTab(primaryUrl, secondaryUrl);
+ } else {
+ openNewTab(primaryUrl);
+ }
+ }
+}
+
+void DolphinTabWidget::openFiles(const QList<KUrl>& files)
+{
+ if (files.isEmpty()) {
+ return;
+ }
+
+ // Get all distinct directories from 'files' and open a tab
+ // for each directory. If the "split view" option is enabled, two
+ // directories are shown inside one tab (see openDirectories()).
+ QList<KUrl> dirs;
+ foreach (const KUrl& url, files) {
+ const KUrl dir(url.directory());
+ if (!dirs.contains(dir)) {
+ dirs.append(dir);
+ }
+ }
+
+ const int oldTabCount = count();
+ openDirectories(dirs);
+ const int tabCount = count();
+
+ // Select the files. Although the files can be split between several
+ // tabs, there is no need to split 'files' accordingly, as
+ // the DolphinView will just ignore invalid selections.
+ for (int i = oldTabCount; i < tabCount; ++i) {
+ DolphinTabPage* tabPage = tabPageAt(i);
+ tabPage->markUrlsAsSelected(files);
+ tabPage->markUrlAsCurrent(files.first());
+ }
+}
+
+void DolphinTabWidget::closeTab()
+{
+ closeTab(currentIndex());
+}
+
+void DolphinTabWidget::closeTab(const int index)
+{
+ Q_ASSERT(index >= 0);
+ Q_ASSERT(index < count());
+
+ if (count() < 2) {
+ // Never close the last tab.
+ return;
+ }
+
+ DolphinTabPage* tabPage = tabPageAt(index);
+ if (tabPage->splitViewEnabled()) {
+ emit rememberClosedTab(tabPage->primaryViewContainer()->url(),
+ tabPage->secondaryViewContainer()->url());
+ } else {
+ emit rememberClosedTab(tabPage->primaryViewContainer()->url(), KUrl());
+ }
+
+ removeTab(index);
+ tabPage->deleteLater();
+}
+
+void DolphinTabWidget::activateNextTab()
+{
+ const int index = currentIndex() + 1;
+ setCurrentIndex(index < count() ? index : 0);
+}
+
+void DolphinTabWidget::activatePrevTab()
+{
+ const int index = currentIndex() - 1;
+ setCurrentIndex(index >= 0 ? index : (count() - 1));
+}
+
+void DolphinTabWidget::slotPlacesPanelVisibilityChanged(bool visible)
+{
+ // The places-selector from the URL navigator should only be shown
+ // if the places dock is invisible
+ m_placesSelectorVisible = !visible;
+
+ const int tabCount = count();
+ for (int i = 0; i < tabCount; ++i) {
+ DolphinTabPage* tabPage = tabPageAt(i);
+ tabPage->setPlacesSelectorVisible(m_placesSelectorVisible);
+ }
+}
+
+void DolphinTabWidget::detachTab(int index)
+{
+ Q_ASSERT(index >= 0);
+
+ const QString separator(QLatin1Char(' '));
+ QString command = QLatin1String("dolphin");
+
+ const DolphinTabPage* tabPage = tabPageAt(index);
+ command += separator + tabPage->primaryViewContainer()->url().url();
+ if (tabPage->splitViewEnabled()) {
+ command += separator + tabPage->secondaryViewContainer()->url().url();
+ command += separator + QLatin1String("-split");
+ }
+
+ KRun::runCommand(command, this);
+
+ closeTab(index);
+}
+
+void DolphinTabWidget::openNewActivatedTab(int index)
+{
+ Q_ASSERT(index >= 0);
+ const DolphinTabPage* tabPage = tabPageAt(index);
+ openNewActivatedTab(tabPage->activeViewContainer()->url());
+}
+
+void DolphinTabWidget::tabDropEvent(int index, QDropEvent* event)
+{
+ if (index >= 0) {
+ const DolphinView* view = tabPageAt(index)->activeViewContainer()->view();
+
+ QString error;
+ DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error);
+ if (!error.isEmpty()) {
+ currentTabPage()->activeViewContainer()->showMessage(error, DolphinViewContainer::Error);
+ }
+ }
+}
+
+void DolphinTabWidget::tabUrlChanged(const KUrl& url)
+{
+ const int index = indexOf(qobject_cast<QWidget*>(sender()));
+ if (index >= 0) {
+ tabBar()->setTabText(index, tabName(url));
+ tabBar()->setTabIcon(index, KIcon(KMimeType::iconNameForUrl(url)));
+ }
+}
+
+void DolphinTabWidget::currentTabChanged(int index)
+{
+ emit activeViewChanged(tabPageAt(index)->activeViewContainer());
+}
+
+void DolphinTabWidget::tabInserted(int index)
+{
+ QTabWidget::tabInserted(index);
+
+ if (count() > 1) {
+ tabBar()->show();
+ }
+
+ emit tabCountChanged(count());
+}
+
+void DolphinTabWidget::tabRemoved(int index)
+{
+ QTabWidget::tabRemoved(index);
+
+ // If only one tab is left, then remove the tab entry so that
+ // closing the last tab is not possible.
+ if (count() < 2) {
+ tabBar()->hide();
+ }
+
+ emit tabCountChanged(count());
+}
+
+QString DolphinTabWidget::tabName(const KUrl& url) const
+{
+ QString name;
+ if (url.equals(KUrl("file:///"))) {
+ name = '/';
+ } else {
+ name = url.fileName();
+ if (name.isEmpty()) {
+ name = url.protocol();
+ } else {
+ // Make sure that a '&' inside the directory name is displayed correctly
+ // and not misinterpreted as a keyboard shortcut in QTabBar::setTabText()
+ name.replace('&', "&&");
+ }
+ }
+ return name;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Emmanuel Pescosta <emmanuelpescosta099@gmail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef DOLPHIN_TAB_WIDGET_H
+#define DOLPHIN_TAB_WIDGET_H
+
+#include <QTabWidget>
+#include <KUrl>
+
+class DolphinViewContainer;
+class DolphinTabPage;
+class KConfigGroup;
+
+class DolphinTabWidget : public QTabWidget
+{
+ Q_OBJECT
+
+public:
+ explicit DolphinTabWidget(QWidget* parent);
+
+ /**
+ * @return Tab page at the current index (can be 0 if tabs count is smaller than 1)
+ */
+ DolphinTabPage* currentTabPage() const;
+
+ /**
+ * @return Tab page at the given \a index (can be 0 if the index is out-of-range)
+ */
+ DolphinTabPage* tabPageAt(const int index) const;
+
+ void saveProperties(KConfigGroup& group) const;
+ void readProperties(const KConfigGroup& group);
+
+ /**
+ * Refreshes the views of the main window by recreating them according to
+ * the given Dolphin settings.
+ */
+ void refreshViews();
+
+signals:
+ /**
+ * Is emitted when the active view has been changed, by changing the current
+ * tab or by activating another view when split view is enabled in the current
+ * tab.
+ */
+ void activeViewChanged(DolphinViewContainer* viewContainer);
+
+ /**
+ * Is emitted when the number of open tabs has changed (e.g. by opening or
+ * closing a tab)
+ */
+ void tabCountChanged(int count);
+
+ /**
+ * Is emitted when a tab has been closed.
+ */
+ void rememberClosedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl);
+
+public slots:
+ /**
+ * Opens a new view with the current URL that is part of a tab and activates
+ * the tab.
+ */
+ void openNewActivatedTab();
+
+ /**
+ * Opens a new tab showing the URL \a primaryUrl and the optional URL
+ * \a secondaryUrl and activates the tab.
+ */
+ void openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl());
+
+ /**
+ * Opens a new tab in the background showing the URL \a primaryUrl and the
+ * optional URL \a secondaryUrl.
+ */
+ void openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl());
+
+ /**
+ * Opens each directory in \p dirs in a separate tab. If the "split view"
+ * option is enabled, 2 directories are collected within one tab.
+ */
+ void openDirectories(const QList<KUrl>& dirs);
+
+ /**
+ * Opens the directory which contains the files \p files
+ * and selects all files (implements the --select option
+ * of Dolphin).
+ */
+ void openFiles(const QList<KUrl>& files);
+
+ /**
+ * Closes the currently active tab.
+ */
+ void closeTab();
+
+ /**
+ * Closes the tab with the index \a index and activates the tab with index - 1.
+ */
+ void closeTab(const int index);
+
+ /**
+ * Activates the next tab in the tab bar.
+ * If the current active tab is the last tab, it activates the first tab.
+ */
+ void activateNextTab();
+
+ /**
+ * Activates the previous tab in the tab bar.
+ * If the current active tab is the first tab, it activates the last tab.
+ */
+ void activatePrevTab();
+
+ /**
+ * Is invoked if the Places panel got visible/invisible and takes care
+ * that the places-selector of all views is only shown if the Places panel
+ * is invisible.
+ */
+ void slotPlacesPanelVisibilityChanged(bool visible);
+
+private slots:
+ /**
+ * Opens the tab with the index \a index in a new Dolphin instance and closes
+ * this tab.
+ */
+ void detachTab(int index);
+
+ /**
+ * Opens a new tab showing the url from tab at the given \a index and
+ * activates the tab.
+ */
+ void openNewActivatedTab(int index);
+
+ /**
+ * Is connected to the KTabBar signal receivedDropEvent.
+ * Allows dragging and dropping files onto tabs.
+ */
+ void tabDropEvent(int tab, QDropEvent* event);
+
+ /**
+ * The active view url of a tab has been changed so update the text and the
+ * icon of the corresponding tab.
+ */
+ void tabUrlChanged(const KUrl& url);
+
+ void currentTabChanged(int index);
+
+protected:
+ virtual void tabInserted(int index);
+ virtual void tabRemoved(int index);
+
+private:
+ /**
+ * Returns the name of the tab for the URL \a url.
+ */
+ QString tabName(const KUrl& url) const;
+
+private:
+ /** Caches the (negated) places panel visibility */
+ bool m_placesSelectorVisible;
+};
+
+#endif
\ No newline at end of file