Implemented DolphinTabPage class to encapsulate the split view handling from DolphinMainWindow.

The signal activeViewUrlChanged in DolphinTabPage is currently unused, but we need it later when
we implement the tab widget and tab bar.

DolphinTabPage has saveState/restoreState which are using a QByteArray instead of the KConfigGroup to
be more generic.

REVIEW: 118964
This commit is contained in:
Emmanuel Pescosta 2014-07-02 15:30:37 +02:00
parent 20e13c31df
commit b0fb590ebd
6 changed files with 534 additions and 379 deletions

View file

@ -172,6 +172,7 @@ set(dolphin_SRCS
dolphinviewcontainer.cpp
dolphincontextmenu.cpp
dolphinrecenttabsmenu.cpp
dolphintabpage.cpp
filterbar/filterbar.cpp
main.cpp
panels/information/filemetadataconfigurationdialog.cpp

View file

@ -27,6 +27,7 @@
#include "dolphinnewfilemenu.h"
#include "dolphinrecenttabsmenu.h"
#include "dolphinviewcontainer.h"
#include "dolphintabpage.h"
#include "panels/folders/folderspanel.h"
#include "panels/places/placespanel.h"
#include "panels/information/informationpanel.h"
@ -86,7 +87,6 @@
#include <QKeyEvent>
#include <QClipboard>
#include <QToolButton>
#include <QSplitter>
namespace {
// Used for GeneralSettings::version() to determine whether
@ -100,7 +100,7 @@ DolphinMainWindow::DolphinMainWindow() :
m_tabBar(0),
m_activeViewContainer(0),
m_centralWidgetLayout(0),
m_tabIndex(0),
m_tabIndex(-1),
m_viewTab(),
m_actionHandler(0),
m_remoteEncoding(0),
@ -111,10 +111,6 @@ DolphinMainWindow::DolphinMainWindow() :
{
setObjectName("Dolphin#");
m_viewTab.append(ViewTab());
ViewTab& viewTab = m_viewTab[m_tabIndex];
viewTab.wasActive = true; // The first opened tab is automatically active
connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(errorMessage(QString)),
this, SLOT(showErrorMessage(QString)));
@ -138,25 +134,12 @@ DolphinMainWindow::DolphinMainWindow() :
setAcceptDrops(true);
viewTab.splitter = new QSplitter(this);
viewTab.splitter->setChildrenCollapsible(false);
setupActions();
const KUrl homeUrl(generalSettings->homeUrl());
setUrlAsCaption(homeUrl);
m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar()));
connect(m_actionHandler, SIGNAL(createDirectory()), SLOT(createDirectory()));
viewTab.primaryView = createViewContainer(homeUrl, viewTab.splitter);
m_activeViewContainer = viewTab.primaryView;
connectViewSignals(m_activeViewContainer);
DolphinView* view = m_activeViewContainer->view();
m_activeViewContainer->show();
m_actionHandler->setCurrentView(view);
m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
connect(this, SIGNAL(urlChanged(KUrl)),
m_remoteEncoding, SLOT(slotAboutToOpenUrl()));
@ -182,17 +165,16 @@ DolphinMainWindow::DolphinMainWindow() :
this, SLOT(tabDropEvent(int,QDropEvent*)));
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);
m_centralWidgetLayout->addWidget(viewTab.splitter, 1);
setCentralWidget(centralWidget);
setupDockWidgets();
emit urlChanged(homeUrl);
setupGUI(Keys | Save | Create | ToolBar);
stateChanged("new_file");
@ -201,14 +183,6 @@ DolphinMainWindow::DolphinMainWindow() :
connect(clipboard, SIGNAL(dataChanged()),
this, SLOT(updatePasteAction()));
if (generalSettings->splitView()) {
toggleSplitView();
}
updateEditActions();
updatePasteAction();
updateViewActions();
updateGoActions();
QAction* showFilterBarAction = actionCollection()->action("show_filter_bar");
showFilterBarAction->setChecked(generalSettings->filterBar());
@ -224,6 +198,9 @@ DolphinMainWindow::DolphinMainWindow() :
if (!showMenu) {
createControlButton();
}
const KUrl homeUrl(generalSettings->homeUrl());
openNewActivatedTab(homeUrl);
}
DolphinMainWindow::~DolphinMainWindow()
@ -249,13 +226,12 @@ void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
// always show two directories within one tab.
QList<KUrl>::const_iterator it = dirs.constBegin();
while (it != dirs.constEnd()) {
openNewTab(*it);
++it;
const KUrl& primaryUrl = *(it++);
if (hasSplitView && (it != dirs.constEnd())) {
const int tabIndex = m_viewTab.count() - 1;
m_viewTab[tabIndex].secondaryView->setUrl(*it);
++it;
const KUrl& secondaryUrl = *(it++);
openNewTab(primaryUrl, secondaryUrl);
} else {
openNewTab(primaryUrl);
}
}
@ -287,14 +263,9 @@ void DolphinMainWindow::openFiles(const QList<KUrl>& files)
// 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.
const int tabCount = m_viewTab.count();
for (int i = 0; i < tabCount; ++i) {
m_viewTab[i].primaryView->view()->markUrlsAsSelected(files);
m_viewTab[i].primaryView->view()->markUrlAsCurrent(files.at(0));
if (m_viewTab[i].secondaryView) {
m_viewTab[i].secondaryView->view()->markUrlsAsSelected(files);
m_viewTab[i].secondaryView->view()->markUrlAsCurrent(files.at(0));
}
foreach (DolphinTabPage* tabPage, m_viewTab) {
tabPage->markUrlsAsSelected(files);
tabPage->markUrlAsCurrent(files.first());
}
}
@ -349,11 +320,11 @@ void DolphinMainWindow::changeUrl(const KUrl& url)
updateViewActions();
updateGoActions();
setUrlAsCaption(url);
if (m_viewTab.count() > 1) {
m_tabBar->setTabText(m_tabIndex, squeezedText(tabName(m_activeViewContainer->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);
}
}
@ -376,11 +347,7 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
{
updateEditActions();
Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
int selectedUrlsCount = m_viewTab[m_tabIndex].primaryView->view()->selectedItemsCount();
if (m_viewTab[m_tabIndex].secondaryView) {
selectedUrlsCount += m_viewTab[m_tabIndex].secondaryView->view()->selectedItemsCount();
}
const int selectedUrlsCount = m_viewTab.at(m_tabIndex)->selectedItemsCount();
QAction* compareFilesAction = actionCollection()->action("compare_files");
if (selectedUrlsCount == 2) {
@ -445,41 +412,41 @@ void DolphinMainWindow::openNewTab()
}
}
void DolphinMainWindow::openNewTab(const KUrl& url)
void DolphinMainWindow::openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
{
QWidget* focusWidget = QApplication::focusWidget();
if (m_viewTab.count() == 1) {
// Only one view is open currently and hence no tab is shown at
// all. Before creating a tab for 'url', provide a tab for the current URL.
const KUrl currentUrl = m_activeViewContainer->url();
m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(currentUrl)),
squeezedText(tabName(currentUrl)));
m_tabBar->blockSignals(false);
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);
}
m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(url)),
squeezedText(tabName(url)));
tabPage->hide();
ViewTab viewTab;
viewTab.splitter = new QSplitter(this);
viewTab.splitter->setChildrenCollapsible(false);
viewTab.primaryView = createViewContainer(url, viewTab.splitter);
viewTab.primaryView->setActive(false);
connectViewSignals(viewTab.primaryView);
m_tabBar->addTab(KIcon(KMimeType::iconNameForUrl(primaryUrl)),
squeezedText(tabName(primaryUrl)));
m_viewTab.append(viewTab);
actionCollection()->action("close_tab")->setEnabled(true);
actionCollection()->action("activate_prev_tab")->setEnabled(true);
actionCollection()->action("activate_next_tab")->setEnabled(true);
// Provide a split view, if the startup settings are set this way
if (GeneralSettings::splitView()) {
const int newTabIndex = m_viewTab.count() - 1;
createSecondaryView(newTabIndex);
m_viewTab[newTabIndex].secondaryView->setActive(true);
m_viewTab[newTabIndex].isPrimaryViewActive = false;
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) {
@ -489,17 +456,17 @@ void DolphinMainWindow::openNewTab(const KUrl& url)
}
}
void DolphinMainWindow::openNewActivatedTab(const KUrl& url)
void DolphinMainWindow::openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
{
openNewTab(url);
m_tabBar->setCurrentIndex(m_viewTab.count() - 1);
openNewTab(primaryUrl, secondaryUrl);
setActiveTab(m_viewTab.count() - 1);
}
void DolphinMainWindow::activateNextTab()
{
if (m_viewTab.count() >= 2) {
const int tabIndex = (m_tabBar->currentIndex() + 1) % m_tabBar->count();
m_tabBar->setCurrentIndex(tabIndex);
setActiveTab(tabIndex);
}
}
@ -510,7 +477,7 @@ void DolphinMainWindow::activatePrevTab()
if (tabIndex == -1) {
tabIndex = m_tabBar->count() - 1;
}
m_tabBar->setCurrentIndex(tabIndex);
setActiveTab(tabIndex);
}
}
@ -546,21 +513,6 @@ void DolphinMainWindow::openInNewWindow()
}
}
void DolphinMainWindow::toggleActiveView()
{
if (!m_viewTab[m_tabIndex].secondaryView) {
// only one view is available
return;
}
Q_ASSERT(m_activeViewContainer);
Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
DolphinViewContainer* left = m_viewTab[m_tabIndex].primaryView;
DolphinViewContainer* right = m_viewTab[m_tabIndex].secondaryView;
setActiveViewContainer(m_activeViewContainer == right ? left : right);
}
void DolphinMainWindow::showEvent(QShowEvent* event)
{
KXmlGuiWindow::showEvent(event);
@ -634,17 +586,8 @@ void DolphinMainWindow::saveProperties(KConfigGroup& group)
group.writeEntry("Active Tab Index", m_tabBar->currentIndex());
for (int i = 0; i < tabCount; ++i) {
const DolphinViewContainer* cont = m_viewTab[i].primaryView;
group.writeEntry(tabProperty("Primary URL", i), cont->url().url());
group.writeEntry(tabProperty("Primary Editable", i),
cont->urlNavigator()->isUrlEditable());
cont = m_viewTab[i].secondaryView;
if (cont) {
group.writeEntry(tabProperty("Secondary URL", i), cont->url().url());
group.writeEntry(tabProperty("Secondary Editable", i),
cont->urlNavigator()->isUrlEditable());
}
const DolphinTabPage* tabPage = m_viewTab.at(i);
group.writeEntry("Tab " % QString::number(i), tabPage->saveState());
}
}
@ -652,38 +595,9 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group)
{
const int tabCount = group.readEntry("Tab Count", 1);
for (int i = 0; i < tabCount; ++i) {
DolphinViewContainer* cont = m_viewTab[i].primaryView;
cont->setUrl(group.readEntry(tabProperty("Primary URL", i)));
const bool editable = group.readEntry(tabProperty("Primary Editable", i), false);
cont->urlNavigator()->setUrlEditable(editable);
cont = m_viewTab[i].secondaryView;
const QString secondaryUrl = group.readEntry(tabProperty("Secondary URL", i));
if (!secondaryUrl.isEmpty()) {
if (!cont) {
// a secondary view should be shown, but no one is available
// currently -> create a new view
toggleSplitView();
cont = m_viewTab[i].secondaryView;
Q_ASSERT(cont);
}
// The right view must be activated before the URL is set. Changing
// the URL in the right view will emit the right URL navigator's
// urlChanged(KUrl) signal, which is connected to the changeUrl(KUrl)
// slot. That slot will change the URL in the left view if it is still
// active. See https://bugs.kde.org/show_bug.cgi?id=330047.
setActiveViewContainer(cont);
cont->setUrl(secondaryUrl);
const bool editable = group.readEntry(tabProperty("Secondary Editable", i), false);
cont->urlNavigator()->setUrlEditable(editable);
} else if (cont) {
// no secondary view should be shown, but the default setting shows
// one already -> close the view
toggleSplitView();
}
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) {
@ -796,28 +710,11 @@ void DolphinMainWindow::invertSelection()
void DolphinMainWindow::toggleSplitView()
{
if (!m_viewTab[m_tabIndex].secondaryView) {
createSecondaryView(m_tabIndex);
setActiveViewContainer(m_viewTab[m_tabIndex].secondaryView);
} else if (m_activeViewContainer == m_viewTab[m_tabIndex].secondaryView) {
// remove secondary view
m_viewTab[m_tabIndex].secondaryView->close();
m_viewTab[m_tabIndex].secondaryView->deleteLater();
m_viewTab[m_tabIndex].secondaryView = 0;
DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
tabPage->setSplitViewEnabled(!tabPage->splitViewEnabled());
setActiveViewContainer(m_viewTab[m_tabIndex].primaryView);
} else {
// The primary view is active and should be closed. Hence from a users point of view
// the content of the secondary view should be moved to the primary view.
// From an implementation point of view it is more efficient to close
// the primary view and exchange the internal pointers afterwards.
m_viewTab[m_tabIndex].primaryView->close();
m_viewTab[m_tabIndex].primaryView->deleteLater();
m_viewTab[m_tabIndex].primaryView = m_viewTab[m_tabIndex].secondaryView;
m_viewTab[m_tabIndex].secondaryView = 0;
setActiveViewContainer(m_viewTab[m_tabIndex].primaryView);
if (tabPage->splitViewEnabled()) {
connectViewSignals(tabPage->secondaryViewContainer());
}
updateViewActions();
@ -884,14 +781,8 @@ void DolphinMainWindow::togglePanelLockState()
void DolphinMainWindow::slotPlacesPanelVisibilityChanged(bool visible)
{
const int tabCount = m_viewTab.count();
for (int i = 0; i < tabCount; ++i) {
ViewTab& tab = m_viewTab[i];
Q_ASSERT(tab.primaryView);
tab.primaryView->urlNavigator()->setPlacesSelectorVisible(!visible);
if (tab.secondaryView) {
tab.secondaryView->urlNavigator()->setPlacesSelectorVisible(!visible);
}
foreach (DolphinTabPage* tabPage, m_viewTab) {
tabPage->setPlacesSelectorVisible(visible);
}
}
@ -960,15 +851,7 @@ void DolphinMainWindow::goHome(Qt::MouseButtons buttons)
void DolphinMainWindow::compareFiles()
{
const DolphinViewContainer* primaryViewContainer = m_viewTab[m_tabIndex].primaryView;
Q_ASSERT(primaryViewContainer);
KFileItemList items = primaryViewContainer->view()->selectedItems();
const DolphinViewContainer* secondaryViewContainer = m_viewTab[m_tabIndex].secondaryView;
if (secondaryViewContainer) {
items.append(secondaryViewContainer->view()->selectedItems());
}
const KFileItemList items = m_viewTab.at(m_tabIndex)->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
@ -1038,42 +921,23 @@ void DolphinMainWindow::setActiveTab(int index)
return;
}
m_tabBar->setCurrentIndex(index);
// hide current tab content
ViewTab& hiddenTab = m_viewTab[m_tabIndex];
hiddenTab.isPrimaryViewActive = hiddenTab.primaryView->isActive();
hiddenTab.primaryView->setActive(false);
if (hiddenTab.secondaryView) {
hiddenTab.secondaryView->setActive(false);
if (m_tabIndex >= 0) {
DolphinTabPage* hiddenTabPage = m_viewTab.at(m_tabIndex);
hiddenTabPage->hide();
m_centralWidgetLayout->removeWidget(hiddenTabPage);
}
QSplitter* splitter = m_viewTab[m_tabIndex].splitter;
splitter->hide();
m_centralWidgetLayout->removeWidget(splitter);
// show active tab content
m_tabIndex = index;
ViewTab& viewTab = m_viewTab[index];
m_centralWidgetLayout->addWidget(viewTab.splitter, 1);
viewTab.primaryView->show();
if (viewTab.secondaryView) {
viewTab.secondaryView->show();
}
viewTab.splitter->show();
DolphinTabPage* tabPage = m_viewTab.at(index);
m_centralWidgetLayout->addWidget(tabPage, 1);
tabPage->show();
if (!viewTab.wasActive) {
viewTab.wasActive = true;
// If the tab has not been activated yet the size of the KItemListView is
// undefined and results in an unwanted animation. To prevent this a
// reloading of the directory gets triggered.
viewTab.primaryView->view()->reload();
if (viewTab.secondaryView) {
viewTab.secondaryView->view()->reload();
}
}
setActiveViewContainer(viewTab.isPrimaryViewActive ? viewTab.primaryView :
viewTab.secondaryView);
setActiveViewContainer(tabPage->activeViewContainer());
}
void DolphinMainWindow::closeTab()
@ -1096,17 +960,18 @@ void DolphinMainWindow::closeTab(int index)
m_tabBar->setCurrentIndex((index > 0) ? index - 1 : 1);
}
const KUrl primaryUrl(m_viewTab[index].primaryView->url());
const KUrl secondaryUrl(m_viewTab[index].secondaryView ? m_viewTab[index].secondaryView->url() : KUrl());
emit rememberClosedTab(primaryUrl, secondaryUrl);
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[index].primaryView->deleteLater();
if (m_viewTab[index].secondaryView) {
m_viewTab[index].secondaryView->deleteLater();
}
m_viewTab[index].splitter->deleteLater();
m_viewTab.erase(m_viewTab.begin() + index);
m_viewTab.removeAt(index);
tabPage->deleteLater();
m_tabBar->blockSignals(true);
m_tabBar->removeTab(index);
@ -1118,11 +983,11 @@ void DolphinMainWindow::closeTab(int index)
// if only one tab is left, also remove the tab entry so that
// closing the last tab is not possible
if (m_viewTab.count() == 1) {
m_tabBar->removeTab(0);
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);
}
@ -1143,22 +1008,18 @@ void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos)
closeTabAction->setShortcut(actionCollection()->action("close_tab")->shortcut());
QAction* selectedAction = menu.exec(pos);
if (selectedAction == newTabAction) {
const ViewTab& tab = m_viewTab[index];
Q_ASSERT(tab.primaryView);
const KUrl url = tab.secondaryView && tab.secondaryView->isActive() ?
tab.secondaryView->url() : tab.primaryView->url();
const KUrl url = m_viewTab.at(index)->activeViewContainer()->url();
openNewTab(url);
m_tabBar->setCurrentIndex(m_viewTab.count() - 1);
} else if (selectedAction == detachTabAction) {
const QString separator(QLatin1Char(' '));
QString command = QLatin1String("dolphin");
const ViewTab& tab = m_viewTab[index];
Q_ASSERT(tab.primaryView);
const DolphinTabPage* tabPage = m_viewTab.at(index);
command += separator + tab.primaryView->url().url();
if (tab.secondaryView) {
command += separator + tab.secondaryView->url().url();
command += separator + tabPage->primaryViewContainer()->url().url();
if (tabPage->splitViewEnabled()) {
command += separator + tabPage->secondaryViewContainer()->url().url();
command += separator + QLatin1String("-split");
}
@ -1226,9 +1087,8 @@ void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event)
{
const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
if (!urls.isEmpty() && tab != -1) {
const ViewTab& viewTab = m_viewTab[tab];
const DolphinView* view = viewTab.isPrimaryViewActive ? viewTab.primaryView->view()
: viewTab.secondaryView->view();
const DolphinView* view = m_viewTab.at(tab)->activeViewContainer()->view();
QString error;
DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error);
if (!error.isEmpty()) {
@ -1396,37 +1256,22 @@ void DolphinMainWindow::slotPlaceActivated(const KUrl& url)
}
}
void DolphinMainWindow::restoreClosedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl)
void DolphinMainWindow::activeViewChanged()
{
openNewActivatedTab(primaryUrl);
if (!secondaryUrl.isEmpty() && secondaryUrl.isValid()) {
const int index = m_tabBar->currentIndex();
createSecondaryView(index);
setActiveViewContainer(m_viewTab[index].secondaryView);
m_viewTab[index].secondaryView->setUrl(secondaryUrl);
}
const DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
setActiveViewContainer(tabPage->activeViewContainer());
}
void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer)
{
Q_ASSERT(viewContainer);
Q_ASSERT((viewContainer == m_viewTab[m_tabIndex].primaryView) ||
(viewContainer == m_viewTab[m_tabIndex].secondaryView));
Q_ASSERT((viewContainer == m_viewTab.at(m_tabIndex)->primaryViewContainer()) ||
(viewContainer == m_viewTab.at(m_tabIndex)->secondaryViewContainer()));
if (m_activeViewContainer == viewContainer) {
return;
}
m_activeViewContainer->setActive(false);
m_activeViewContainer = viewContainer;
// Activating the view container might trigger a recursive setActiveViewContainer() call
// inside DolphinMainWindow::toggleActiveView() when having a split view. Temporary
// disconnect the activated() signal in this case:
disconnect(m_activeViewContainer->view(), SIGNAL(activated()), this, SLOT(toggleActiveView()));
m_activeViewContainer->setActive(true);
connect(m_activeViewContainer->view(), SIGNAL(activated()), this, SLOT(toggleActiveView()));
m_actionHandler->setCurrentView(viewContainer->view());
updateHistory();
@ -1437,26 +1282,12 @@ void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContain
const KUrl url = m_activeViewContainer->url();
setUrlAsCaption(url);
if (m_viewTab.count() > 1) {
m_tabBar->setTabText(m_tabIndex, tabName(url));
m_tabBar->setTabIcon(m_tabIndex, KIcon(KMimeType::iconNameForUrl(url)));
}
m_tabBar->setTabText(m_tabIndex, squeezedText(tabName(url)));
m_tabBar->setTabIcon(m_tabIndex, KIcon(KMimeType::iconNameForUrl(url)));
emit urlChanged(url);
}
DolphinViewContainer* DolphinMainWindow::createViewContainer(const KUrl& url, QWidget* parent)
{
DolphinViewContainer* container = new DolphinViewContainer(url, parent);
// The places-selector from the URL navigator should only be shown
// if the places dock is invisible
QDockWidget* placesDock = findChild<QDockWidget*>("placesDock");
container->urlNavigator()->setPlacesSelectorVisible(!placesDock || !placesDock->isVisible());
return container;
}
void DolphinMainWindow::setupActions()
{
// setup 'File' menu
@ -1524,7 +1355,6 @@ void DolphinMainWindow::setupActions()
KAction* split = actionCollection()->addAction("split_view");
split->setShortcut(Qt::Key_F3);
updateSplitAction();
connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
KAction* reload = actionCollection()->addAction("reload");
@ -1561,7 +1391,7 @@ void DolphinMainWindow::setupActions()
connect(this, SIGNAL(rememberClosedTab(KUrl,KUrl)),
recentTabsMenu, SLOT(rememberClosedTab(KUrl,KUrl)));
connect(recentTabsMenu, SIGNAL(restoreClosedTab(KUrl,KUrl)),
this, SLOT(restoreClosedTab(KUrl,KUrl)));
this, SLOT(openNewActivatedTab(KUrl,KUrl)));
KAction* forwardAction = KStandardAction::forward(this, SLOT(goForward()), actionCollection());
connect(forwardAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goForward(Qt::MouseButtons)));
@ -1872,33 +1702,16 @@ bool DolphinMainWindow::addActionToMenu(QAction* action, KMenu* menu)
void DolphinMainWindow::refreshViews()
{
Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
// remember the current active view, as because of
// the refreshing the active view might change to
// the secondary view
DolphinViewContainer* activeViewContainer = m_activeViewContainer;
const int tabCount = m_viewTab.count();
for (int i = 0; i < tabCount; ++i) {
m_viewTab[i].primaryView->readSettings();
if (m_viewTab[i].secondaryView) {
m_viewTab[i].secondaryView->readSettings();
}
foreach (DolphinTabPage* tabPage, m_viewTab) {
tabPage->refreshViews();
}
setActiveViewContainer(activeViewContainer);
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();
const ViewTab& activeTab = m_viewTab[m_tabIndex];
const bool toggle = ( splitView && !activeTab.secondaryView)
|| (!splitView && activeTab.secondaryView);
if (toggle) {
toggleSplitView();
}
m_viewTab.at(m_tabIndex)->setSplitViewEnabled(splitView);
updateSplitAction();
}
emit settingsChanged();
@ -1916,13 +1729,11 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
connect(container, SIGNAL(writeStateChanged(bool)),
this, SLOT(slotWriteStateChanged(bool)));
DolphinView* view = container->view();
const DolphinView* view = container->view();
connect(view, SIGNAL(selectionChanged(KFileItemList)),
this, SLOT(slotSelectionChanged(KFileItemList)));
connect(view, SIGNAL(requestItemInfo(KFileItem)),
this, SLOT(slotRequestItemInfo(KFileItem)));
connect(view, SIGNAL(activated()),
this, SLOT(toggleActiveView()));
connect(view, SIGNAL(tabRequested(KUrl)),
this, SLOT(openNewTab(KUrl)));
connect(view, SIGNAL(requestContextMenu(QPoint,KFileItem,KUrl,QList<QAction*>)),
@ -1950,15 +1761,16 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
void DolphinMainWindow::updateSplitAction()
{
QAction* splitAction = actionCollection()->action("split_view");
if (m_viewTab[m_tabIndex].secondaryView) {
if (m_activeViewContainer == m_viewTab[m_tabIndex].secondaryView) {
splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
splitAction->setToolTip(i18nc("@info", "Close right view"));
splitAction->setIcon(KIcon("view-right-close"));
} else {
const DolphinTabPage* tabPage = m_viewTab.at(m_tabIndex);
if (tabPage->splitViewEnabled()) {
if (tabPage->primaryViewActive()) {
splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
splitAction->setToolTip(i18nc("@info", "Close left view"));
splitAction->setIcon(KIcon("view-left-close"));
} else {
splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
splitAction->setToolTip(i18nc("@info", "Close right view"));
splitAction->setIcon(KIcon("view-right-close"));
}
} else {
splitAction->setText(i18nc("@action:intoolbar Split view", "Split"));
@ -1998,35 +1810,6 @@ bool DolphinMainWindow::isKompareInstalled() const
return installed;
}
void DolphinMainWindow::createSecondaryView(int tabIndex)
{
ViewTab& viewTab = m_viewTab[tabIndex];
QSplitter* splitter = viewTab.splitter;
const int newWidth = (viewTab.primaryView->width() - splitter->handleWidth()) / 2;
const DolphinView* view = viewTab.primaryView->view();
// The final parent of the new view container will be set by adding it
// to the splitter. However, we must make sure that the DolphinMainWindow
// is a parent of the view container already when it is constructed
// because this enables the container's KFileItemModel to assign its
// dir lister to the right main window. The dir lister can then cache
// authentication data.
viewTab.secondaryView = createViewContainer(view->url(), this);
splitter->addWidget(viewTab.secondaryView);
splitter->setSizes(QList<int>() << newWidth << newWidth);
connectViewSignals(viewTab.secondaryView);
viewTab.secondaryView->setActive(false);
viewTab.secondaryView->resize(newWidth, viewTab.primaryView->height());
viewTab.secondaryView->show();
}
QString DolphinMainWindow::tabProperty(const QString& property, int tabIndex) const
{
return "Tab " + QString::number(tabIndex) + ' ' + property;
}
void DolphinMainWindow::setUrlAsCaption(const KUrl& url)
{
QString caption;

View file

@ -40,6 +40,7 @@ class DolphinApplication;
class DolphinSettingsDialog;
class DolphinViewContainer;
class DolphinRemoteEncoding;
class DolphinTabPage;
class KAction;
class KFileItem;
class KFileItemList;
@ -88,13 +89,6 @@ public:
*/
void openFiles(const QList<KUrl>& files);
/**
* Returns true, if the main window contains two instances
* of a view container. The active view constainer can be
* accessed by DolphinMainWindow::activeViewContainer().
*/
bool isSplit() const;
/**
* Returns the 'Create New...' sub menu which also can be shared
* with other menus (e. g. a context menu).
@ -353,15 +347,16 @@ private slots:
void openNewTab();
/**
* Opens a new tab in the background showing the URL \a url.
* Opens a new tab in the background showing the URL \a primaryUrl and the
* optional URL \a secondaryUrl.
*/
void openNewTab(const KUrl& url);
void openNewTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl());
/**
* Opens a new tab showing the URL \a url and activates
* the tab.
* Opens a new tab showing the URL \a primaryUrl and the optional URL
* \a secondaryUrl and activates the tab.
*/
void openNewActivatedTab(const KUrl& url);
void openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl());
void activateNextTab();
@ -377,9 +372,6 @@ private slots:
*/
void openInNewWindow();
/** Toggles the active view if two views are shown within the main window. */
void toggleActiveView();
/**
* Indicates in the statusbar that the execution of the command \a command
* has been finished.
@ -474,11 +466,7 @@ private slots:
*/
void slotPlaceActivated(const KUrl& url);
/**
* Is called when the user wants to reopen a previously closed \a tab from
* the recent tabs menu.
*/
void restoreClosedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl);
void activeViewChanged();
private:
/**
@ -489,11 +477,6 @@ private:
*/
void setActiveViewContainer(DolphinViewContainer* view);
/**
* Creates a view container and does a default initialization.
*/
DolphinViewContainer* createViewContainer(const KUrl& url, QWidget* parent);
void setupActions();
void setupDockWidgets();
void updateEditActions();
@ -529,17 +512,9 @@ private:
/** Returns the name of the tab for the URL \a url. */
QString tabName(const KUrl& url) const;
bool isKompareInstalled() const;
void createSecondaryView(int tabIndex);
/**
* Helper method for saveProperties() and readProperties(): Returns
* the property string for a tab with the index \a tabIndex and
* the property \a property.
*/
QString tabProperty(const QString& property, int tabIndex) const;
/**
* Sets the window caption to url.fileName() if this is non-empty,
* "/" if the URL is "file:///", and url.protocol() otherwise.
@ -579,18 +554,8 @@ private:
QVBoxLayout* m_centralWidgetLayout;
int m_id;
// Members for the tab-handling:
struct ViewTab
{
ViewTab() : isPrimaryViewActive(true), wasActive(false), primaryView(0), secondaryView(0), splitter(0) {}
bool isPrimaryViewActive;
bool wasActive;
DolphinViewContainer* primaryView;
DolphinViewContainer* secondaryView;
QSplitter* splitter;
};
int m_tabIndex;
QList<ViewTab> m_viewTab;
QList<DolphinTabPage*> m_viewTab;
DolphinViewActionHandler* m_actionHandler;
DolphinRemoteEncoding* m_remoteEncoding;
@ -608,11 +573,6 @@ inline DolphinViewContainer* DolphinMainWindow::activeViewContainer() const
return m_activeViewContainer;
}
inline bool DolphinMainWindow::isSplit() const
{
return m_viewTab[m_tabIndex].secondaryView != 0;
}
inline KNewFileMenu* DolphinMainWindow::newFileMenu() const
{
return m_newFileMenu;

258
src/dolphintabpage.cpp Normal file
View file

@ -0,0 +1,258 @@
/***************************************************************************
* 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 "dolphintabpage.h"
#include "dolphinviewcontainer.h"
#include "dolphin_generalsettings.h"
#include <QSplitter>
DolphinTabPage::DolphinTabPage(const KUrl& primaryUrl, const KUrl& secondaryUrl, QWidget* parent) :
QWidget(parent),
m_primaryViewActive(true),
m_splitViewEnabled(false)
{
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setSpacing(0);
layout->setMargin(0);
m_splitter = new QSplitter(Qt::Horizontal, this);
m_splitter->setChildrenCollapsible(false);
layout->addWidget(m_splitter);
// Create a new primary view
m_primaryViewContainer = createViewContainer(primaryUrl);
connect(m_primaryViewContainer->view(), SIGNAL(urlChanged(KUrl)),
this, SIGNAL(activeViewUrlChanged(KUrl)));
m_splitter->addWidget(m_primaryViewContainer);
m_primaryViewContainer->show();
if (secondaryUrl.isValid() || GeneralSettings::splitView()) {
// Provide a secondary view, if the given secondary url is valid or if the
// startup settings are set this way (use the url of the primary view).
m_splitViewEnabled = true;
const KUrl& url = secondaryUrl.isValid() ? secondaryUrl : primaryUrl;
m_secondaryViewContainer = createViewContainer(url);
m_splitter->addWidget(m_secondaryViewContainer);
m_secondaryViewContainer->show();
}
m_primaryViewContainer->setActive(true);
}
bool DolphinTabPage::primaryViewActive() const
{
return m_primaryViewActive;
}
bool DolphinTabPage::splitViewEnabled() const
{
return m_splitViewEnabled;
}
void DolphinTabPage::setSplitViewEnabled(bool enabled)
{
if (m_splitViewEnabled != enabled) {
m_splitViewEnabled = enabled;
if (enabled) {
const KUrl& url = m_primaryViewContainer->url();
m_secondaryViewContainer = createViewContainer(url);
m_splitter->addWidget(m_secondaryViewContainer);
m_secondaryViewContainer->show();
m_secondaryViewContainer->setActive(true);
} else {
// Close the view which is active.
DolphinViewContainer* view = activeViewContainer();
if (m_primaryViewActive) {
// If the primary view is active, we have to swap the pointers
// because the secondary view will be the new primary view.
qSwap(m_primaryViewContainer, m_secondaryViewContainer);
}
m_primaryViewContainer->setActive(true);
view->close();
view->deleteLater();
}
}
}
DolphinViewContainer* DolphinTabPage::primaryViewContainer() const
{
return m_primaryViewContainer;
}
DolphinViewContainer* DolphinTabPage::secondaryViewContainer() const
{
return m_secondaryViewContainer;
}
DolphinViewContainer* DolphinTabPage::activeViewContainer() const
{
return m_primaryViewActive ? m_primaryViewContainer :
m_secondaryViewContainer;
}
KFileItemList DolphinTabPage::selectedItems() const
{
KFileItemList items = m_primaryViewContainer->view()->selectedItems();
if (m_splitViewEnabled) {
items += m_secondaryViewContainer->view()->selectedItems();
}
return items;
}
int DolphinTabPage::selectedItemsCount() const
{
int selectedItemsCount = m_primaryViewContainer->view()->selectedItemsCount();
if (m_splitViewEnabled) {
selectedItemsCount += m_secondaryViewContainer->view()->selectedItemsCount();
}
return selectedItemsCount;
}
void DolphinTabPage::markUrlsAsSelected(const QList<KUrl>& urls)
{
m_primaryViewContainer->view()->markUrlsAsSelected(urls);
if (m_splitViewEnabled) {
m_secondaryViewContainer->view()->markUrlsAsSelected(urls);
}
}
void DolphinTabPage::markUrlAsCurrent(const KUrl& url)
{
m_primaryViewContainer->view()->markUrlAsCurrent(url);
if (m_splitViewEnabled) {
m_secondaryViewContainer->view()->markUrlAsCurrent(url);
}
}
void DolphinTabPage::setPlacesSelectorVisible(bool visible)
{
m_primaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
if (m_splitViewEnabled) {
m_secondaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
}
}
void DolphinTabPage::refreshViews()
{
m_primaryViewContainer->readSettings();
if (m_splitViewEnabled) {
m_secondaryViewContainer->readSettings();
}
}
QByteArray DolphinTabPage::saveState() const
{
QByteArray state;
QDataStream stream(&state, QIODevice::WriteOnly);
stream << m_splitViewEnabled;
stream << m_primaryViewContainer->url();
stream << m_primaryViewContainer->urlNavigator()->isUrlEditable();
if (m_splitViewEnabled) {
stream << m_secondaryViewContainer->url();
stream << m_secondaryViewContainer->urlNavigator()->isUrlEditable();
}
stream << m_primaryViewActive;
stream << m_splitter->saveState();
return state;
}
void DolphinTabPage::restoreState(const QByteArray& state)
{
QByteArray sd = state;
QDataStream stream(&sd, QIODevice::ReadOnly);
bool isSplitViewEnabled = false;
stream >> isSplitViewEnabled;
setSplitViewEnabled(isSplitViewEnabled);
KUrl primaryUrl;
stream >> primaryUrl;
m_primaryViewContainer->setUrl(primaryUrl);
bool primaryUrlEditable;
stream >> primaryUrlEditable;
m_primaryViewContainer->urlNavigator()->setUrlEditable(primaryUrlEditable);
if (isSplitViewEnabled) {
KUrl secondaryUrl;
stream >> secondaryUrl;
m_secondaryViewContainer->setUrl(secondaryUrl);
bool secondaryUrlEditable;
stream >> secondaryUrlEditable;
m_secondaryViewContainer->urlNavigator()->setUrlEditable(secondaryUrlEditable);
}
stream >> m_primaryViewActive;
if (m_primaryViewActive) {
m_primaryViewContainer->setActive(true);
} else {
Q_ASSERT(m_splitViewEnabled);
m_secondaryViewContainer->setActive(true);
}
QByteArray splitterState;
stream >> splitterState;
m_splitter->restoreState(splitterState);
}
void DolphinTabPage::slotViewActivated()
{
const DolphinView* oldActiveView = activeViewContainer()->view();
// Set the view, which was active before, to inactive
// and update the active view type.
if (m_splitViewEnabled) {
activeViewContainer()->setActive(false);
m_primaryViewActive = !m_primaryViewActive;
} else {
m_primaryViewActive = true;
}
const DolphinView* newActiveView = activeViewContainer()->view();
if (newActiveView != oldActiveView) {
disconnect(oldActiveView, SIGNAL(urlChanged(KUrl)),
this, SIGNAL(activeViewUrlChanged(KUrl)));
connect(newActiveView, SIGNAL(urlChanged(KUrl)),
this, SIGNAL(activeViewUrlChanged(KUrl)));
}
emit activeViewUrlChanged(activeViewContainer()->url());
emit activeViewChanged();
}
DolphinViewContainer* DolphinTabPage::createViewContainer(const KUrl& url) const
{
DolphinViewContainer* container = new DolphinViewContainer(url, m_splitter);
container->setActive(false);
const DolphinView* view = container->view();
connect(view, SIGNAL(activated()),
this, SLOT(slotViewActivated()));
return container;
}

152
src/dolphintabpage.h Normal file
View file

@ -0,0 +1,152 @@
/***************************************************************************
* 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_PAGE_H
#define DOLPHIN_TAB_PAGE_H
#include <QWidget>
#include <QPointer>
#include <KUrl>
class QSplitter;
class DolphinViewContainer;
class KFileItemList;
class DolphinTabPage : public QWidget
{
Q_OBJECT
public:
explicit DolphinTabPage(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl(), QWidget* parent = 0);
/**
* @return True if primary view is the active view in this tab.
*/
bool primaryViewActive() const;
/**
* @return True if split view is enabled.
*/
bool splitViewEnabled() const;
/**
* Enables or disables the split view mode.
*
* If \a enabled is true, it creates a secondary view with the url of the primary view.
*/
void setSplitViewEnabled(bool enabled);
/**
* @return The primary view containter.
*/
DolphinViewContainer* primaryViewContainer() const;
/**
* @return The secondary view containter, can be 0 if split view is disabled.
*/
DolphinViewContainer* secondaryViewContainer() const;
/**
* @return DolphinViewContainer of the active view
*/
DolphinViewContainer* activeViewContainer() const;
/**
* Returns the selected items. The list is empty if no item has been
* selected.
*/
KFileItemList selectedItems() const;
/**
* Returns the number of selected items (this is faster than
* invoking selectedItems().count()).
*/
int selectedItemsCount() const;
/**
* Marks the items indicated by \p urls to get selected after the
* directory DolphinView::url() has been loaded. Note that nothing
* gets selected if no loading of a directory has been triggered
* by DolphinView::setUrl() or DolphinView::reload().
*/
void markUrlsAsSelected(const QList<KUrl>& urls);
/**
* Marks the item indicated by \p url to be scrolled to and as the
* current item after directory DolphinView::url() has been loaded.
*/
void markUrlAsCurrent(const KUrl& url);
/**
* Sets the places selector visible, if \a visible is true.
* The places selector allows to select the places provided
* by the places model passed in the constructor. Per default
* the places selector is visible.
*/
void setPlacesSelectorVisible(bool visible);
/**
* Refreshes the views of the main window by recreating them according to
* the given Dolphin settings.
*/
void refreshViews();
/**
* Saves all tab related properties (urls, splitter layout, ...).
*
* @return A byte-array which contains all properties.
*/
QByteArray saveState() const;
/**
* Restores all tab related properties (urls, splitter layout, ...) from
* the given \a state.
*/
void restoreState(const QByteArray& state);
signals:
void activeViewChanged();
void activeViewUrlChanged(const KUrl& url);
private slots:
/**
* Handles the view activated event.
*
* It sets the previous active view to inactive, updates the current
* active view type and triggers the activeViewChanged event.
*/
void slotViewActivated();
private:
/**
* Creates a new view container and does the default initialization.
*/
DolphinViewContainer* createViewContainer(const KUrl& url) const;
private:
QSplitter* m_splitter;
QPointer<DolphinViewContainer> m_primaryViewContainer;
QPointer<DolphinViewContainer> m_secondaryViewContainer;
bool m_primaryViewActive;
bool m_splitViewEnabled;
};
#endif // DOLPHIN_TAB_PAGE_H

View file

@ -125,6 +125,7 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) :
connect(m_view, SIGNAL(urlAboutToBeChanged(KUrl)), this, SLOT(slotViewUrlAboutToBeChanged(KUrl)));
connect(m_view, SIGNAL(errorMessage(QString)), this, SLOT(showErrorMessage(QString)));
connect(m_view, SIGNAL(urlIsFileError(KUrl)), this, SLOT(slotUrlIsFileError(KUrl)));
connect(m_view, SIGNAL(activated()), this, SLOT(activate()));
connect(m_urlNavigator, SIGNAL(urlAboutToBeChanged(KUrl)),
this, SLOT(slotUrlNavigatorLocationAboutToBeChanged(KUrl)));