Implemented DolphinTabWidget class to encapsulate the tab handling from DolphinMainWindow.

REVIEW: 119115
This commit is contained in:
Emmanuel Pescosta 2014-08-10 18:52:06 +02:00
parent 1ffb64db1f
commit 38381bc6a2
7 changed files with 608 additions and 460 deletions

View file

@ -174,6 +174,7 @@ set(dolphin_SRCS
dolphintabbar.cpp
dolphinrecenttabsmenu.cpp
dolphintabpage.cpp
dolphintabwidget.cpp
filterbar/filterbar.cpp
main.cpp
panels/information/filemetadataconfigurationdialog.cpp

View file

@ -26,7 +26,7 @@
#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"
@ -97,11 +97,8 @@ namespace {
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(),
@ -134,6 +131,13 @@ DolphinMainWindow::DolphinMainWindow() :
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);
@ -144,30 +148,6 @@ DolphinMainWindow::DolphinMainWindow() :
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);
@ -200,48 +180,12 @@ DolphinMainWindow::~DolphinMainWindow()
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)
@ -287,21 +231,14 @@ void DolphinMainWindow::changeUrl(const KUrl& url)
return;
}
DolphinViewContainer* view = activeViewContainer();
if (view) {
view->setUrl(url);
updateEditActions();
updatePasteAction();
updateViewActions();
updateGoActions();
setUrlAsCaption(url);
m_activeViewContainer->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);
}
emit urlChanged(url);
}
void DolphinMainWindow::slotTerminalDirectoryChanged(const KUrl& url)
@ -322,7 +259,7 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
{
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) {
@ -368,99 +305,19 @@ void DolphinMainWindow::openNewMainWindow()
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()
@ -499,12 +356,6 @@ void DolphinMainWindow::showEvent(QShowEvent* event)
{
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();
}
@ -520,7 +371,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
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
@ -555,7 +406,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
break;
case KDialog::No:
// Close only the current tab
closeTab();
m_tabWidget->closeTab();
default:
event->ignore();
return;
@ -570,32 +421,12 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
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()
@ -699,13 +530,9 @@ void DolphinMainWindow::invertSelection()
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();
}
@ -768,14 +595,6 @@ void DolphinMainWindow::togglePanelLockState()
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();
@ -841,7 +660,7 @@ void DolphinMainWindow::goHome(Qt::MouseButtons buttons)
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
@ -903,111 +722,6 @@ void DolphinMainWindow::editSettings()
}
}
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;
@ -1041,20 +755,6 @@ void DolphinMainWindow::slotHandleUrlStatFinished(KJob* job)
}
}
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);
@ -1214,27 +914,28 @@ void DolphinMainWindow::slotPlaceActivated(const KUrl& url)
}
}
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();
@ -1243,14 +944,20 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain
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
@ -1272,14 +979,14 @@ void DolphinMainWindow::setupActions()
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());
@ -1351,7 +1058,7 @@ void DolphinMainWindow::setupActions()
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)));
@ -1412,14 +1119,14 @@ void DolphinMainWindow::setupActions()
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
@ -1548,10 +1255,12 @@ void DolphinMainWindow::setupDockWidgets()
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);
@ -1674,15 +1383,13 @@ bool DolphinMainWindow::addActionToMenu(QAction* action, KMenu* menu)
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();
}
@ -1733,7 +1440,7 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
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"));
@ -1751,24 +1458,6 @@ void DolphinMainWindow::updateSplitAction()
}
}
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;
@ -1798,12 +1487,6 @@ void DolphinMainWindow::setUrlAsCaption(const KUrl& url)
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,

View file

@ -38,19 +38,16 @@ typedef KIO::FileUndoManager::CommandType CommandType;
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.
@ -149,11 +146,6 @@ signals:
*/
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);
@ -262,13 +254,6 @@ private slots:
*/
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();
@ -343,8 +328,11 @@ private slots:
/** 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
@ -358,16 +346,6 @@ private slots:
*/
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.
*/
@ -384,33 +362,6 @@ private slots:
*/
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.
@ -423,12 +374,6 @@ private slots:
*/
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.
@ -466,19 +411,25 @@ private slots:
*/
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();
@ -511,10 +462,6 @@ private:
*/
void updateSplitAction();
/** Returns the name of the tab for the URL \a url. */
QString tabName(const KUrl& url) const;
bool isKompareInstalled() const;
/**
@ -523,8 +470,6 @@ private:
*/
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
@ -551,14 +496,10 @@ private:
};
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;

View file

@ -246,7 +246,7 @@ void DolphinTabPage::slotViewActivated()
}
emit activeViewUrlChanged(activeViewContainer()->url());
emit activeViewChanged();
emit activeViewChanged(activeViewContainer());
}
DolphinViewContainer* DolphinTabPage::createViewContainer(const KUrl& url) const

View file

@ -121,7 +121,7 @@ public:
void restoreState(const QByteArray& state);
signals:
void activeViewChanged();
void activeViewChanged(DolphinViewContainer* viewContainer);
void activeViewUrlChanged(const KUrl& url);
private slots:

345
src/dolphintabwidget.cpp Normal file
View file

@ -0,0 +1,345 @@
/***************************************************************************
* 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;
}

178
src/dolphintabwidget.h Normal file
View file

@ -0,0 +1,178 @@
/***************************************************************************
* 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