You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
765 lines
23 KiB
765 lines
23 KiB
/* |
|
This file is part of the Konsole Terminal. |
|
|
|
Copyright 2006-2008 Robert Knight <robertknight@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. |
|
*/ |
|
|
|
// Own |
|
#include "ViewContainer.h" |
|
|
|
#include <config-konsole.h> |
|
|
|
// Qt |
|
#include <QStackedWidget> |
|
#include <QToolButton> |
|
#include <QtGui/QDrag> |
|
#include <QtGui/QDragMoveEvent> |
|
#include <QtCore/QMimeData> |
|
#include <QHBoxLayout> |
|
#include <QVBoxLayout> |
|
|
|
// KDE |
|
#include <KColorScheme> |
|
#include <KColorUtils> |
|
#include <KLocalizedString> |
|
#include <KMenu> |
|
#include <KIcon> |
|
|
|
// Konsole |
|
#include "IncrementalSearchBar.h" |
|
#include "ViewProperties.h" |
|
#include "ViewContainerTabBar.h" |
|
#include "ProfileList.h" |
|
#include "ViewManager.h" |
|
|
|
// TODO Perhaps move everything which is Konsole-specific into different files |
|
|
|
using namespace Konsole; |
|
|
|
ViewContainer::ViewContainer(NavigationPosition position , QObject* parent) |
|
: QObject(parent) |
|
, _navigationVisibility(AlwaysShowNavigation) |
|
, _navigationPosition(position) |
|
, _searchBar(0) |
|
{ |
|
} |
|
|
|
ViewContainer::~ViewContainer() |
|
{ |
|
foreach(QWidget * view , _views) { |
|
disconnect(view, SIGNAL(destroyed(QObject*)), this, SLOT(viewDestroyed(QObject*))); |
|
} |
|
|
|
if (_searchBar) { |
|
_searchBar->deleteLater(); |
|
} |
|
|
|
emit destroyed(this); |
|
} |
|
void ViewContainer::moveViewWidget(int , int) {} |
|
void ViewContainer::setFeatures(Features features) |
|
{ |
|
_features = features; |
|
} |
|
ViewContainer::Features ViewContainer::features() const |
|
{ |
|
return _features; |
|
} |
|
void ViewContainer::moveActiveView(MoveDirection direction) |
|
{ |
|
const int currentIndex = _views.indexOf(activeView()); |
|
int newIndex = -1; |
|
|
|
switch (direction) { |
|
case MoveViewLeft: |
|
newIndex = qMax(currentIndex - 1 , 0); |
|
break; |
|
case MoveViewRight: |
|
newIndex = qMin(currentIndex + 1 , _views.count() - 1); |
|
break; |
|
} |
|
|
|
Q_ASSERT(newIndex != -1); |
|
|
|
moveViewWidget(currentIndex , newIndex); |
|
|
|
_views.swap(currentIndex, newIndex); |
|
|
|
setActiveView(_views[newIndex]); |
|
} |
|
|
|
void ViewContainer::setNavigationVisibility(NavigationVisibility mode) |
|
{ |
|
_navigationVisibility = mode; |
|
navigationVisibilityChanged(mode); |
|
} |
|
ViewContainer::NavigationPosition ViewContainer::navigationPosition() const |
|
{ |
|
return _navigationPosition; |
|
} |
|
void ViewContainer::setNavigationPosition(NavigationPosition position) |
|
{ |
|
// assert that this position is supported |
|
Q_ASSERT(supportedNavigationPositions().contains(position)); |
|
|
|
_navigationPosition = position; |
|
|
|
navigationPositionChanged(position); |
|
} |
|
QList<ViewContainer::NavigationPosition> ViewContainer::supportedNavigationPositions() const |
|
{ |
|
return QList<NavigationPosition>() << NavigationPositionTop; |
|
} |
|
ViewContainer::NavigationVisibility ViewContainer::navigationVisibility() const |
|
{ |
|
return _navigationVisibility; |
|
} |
|
|
|
void ViewContainer::setNavigationTextMode(bool mode) |
|
{ |
|
navigationTextModeChanged(mode); |
|
} |
|
|
|
void ViewContainer::addView(QWidget* view , ViewProperties* item, int index) |
|
{ |
|
if (index == -1) |
|
_views.append(view); |
|
else |
|
_views.insert(index, view); |
|
|
|
_navigation[view] = item; |
|
|
|
connect(view, SIGNAL(destroyed(QObject*)), this, SLOT(viewDestroyed(QObject*))); |
|
|
|
addViewWidget(view, index); |
|
|
|
emit viewAdded(view, item); |
|
} |
|
void ViewContainer::viewDestroyed(QObject* object) |
|
{ |
|
QWidget* widget = static_cast<QWidget*>(object); |
|
|
|
_views.removeAll(widget); |
|
_navigation.remove(widget); |
|
|
|
// FIXME This can result in ViewContainerSubClass::removeViewWidget() being |
|
// called after the widget's parent has been deleted or partially deleted |
|
// in the ViewContainerSubClass instance's destructor. |
|
// |
|
// Currently deleteLater() is used to remove child widgets in the subclass |
|
// constructors to get around the problem, but this is a hack and needs |
|
// to be fixed. |
|
removeViewWidget(widget); |
|
|
|
emit viewRemoved(widget); |
|
|
|
if (_views.count() == 0) |
|
emit empty(this); |
|
} |
|
void ViewContainer::removeView(QWidget* view) |
|
{ |
|
_views.removeAll(view); |
|
_navigation.remove(view); |
|
|
|
disconnect(view, SIGNAL(destroyed(QObject*)), this, SLOT(viewDestroyed(QObject*))); |
|
|
|
removeViewWidget(view); |
|
|
|
emit viewRemoved(view); |
|
|
|
if (_views.count() == 0) |
|
emit empty(this); |
|
} |
|
|
|
const QList<QWidget*> ViewContainer::views() const |
|
{ |
|
return _views; |
|
} |
|
|
|
IncrementalSearchBar* ViewContainer::searchBar() |
|
{ |
|
if (!_searchBar) { |
|
_searchBar = new IncrementalSearchBar(0); |
|
_searchBar->setVisible(false); |
|
connect(_searchBar, SIGNAL(destroyed(QObject*)), this, SLOT(searchBarDestroyed())); |
|
} |
|
return _searchBar; |
|
} |
|
|
|
void ViewContainer::searchBarDestroyed() |
|
{ |
|
_searchBar = 0; |
|
} |
|
|
|
void ViewContainer::activateNextView() |
|
{ |
|
QWidget* active = activeView(); |
|
|
|
int index = _views.indexOf(active); |
|
|
|
if (index == -1) |
|
return; |
|
|
|
if (index == _views.count() - 1) |
|
index = 0; |
|
else |
|
index++; |
|
|
|
setActiveView(_views.at(index)); |
|
} |
|
|
|
void ViewContainer::activateLastView() |
|
{ |
|
setActiveView(_views.at(_views.count() - 1)); |
|
} |
|
|
|
void ViewContainer::activatePreviousView() |
|
{ |
|
QWidget* active = activeView(); |
|
|
|
int index = _views.indexOf(active); |
|
|
|
if (index == -1) |
|
return; |
|
|
|
if (index == 0) |
|
index = _views.count() - 1; |
|
else |
|
index--; |
|
|
|
setActiveView(_views.at(index)); |
|
} |
|
|
|
ViewProperties* ViewContainer::viewProperties(QWidget* widget) const |
|
{ |
|
Q_ASSERT(_navigation.contains(widget)); |
|
|
|
return _navigation[widget]; |
|
} |
|
|
|
QList<QWidget*> ViewContainer::widgetsForItem(ViewProperties* item) const |
|
{ |
|
return _navigation.keys(item); |
|
} |
|
|
|
TabbedViewContainer::TabbedViewContainer(NavigationPosition position, ViewManager* connectedViewManager, QObject* parent) |
|
: ViewContainer(position, parent) |
|
, _connectedViewManager(connectedViewManager) |
|
, _contextMenuTabIndex(0) |
|
{ |
|
_containerWidget = new QWidget; |
|
_stackWidget = new QStackedWidget(); |
|
|
|
// The tab bar |
|
_tabBar = new ViewContainerTabBar(_containerWidget, this); |
|
_tabBar->setSupportedMimeType(ViewProperties::mimeType()); |
|
|
|
connect(_tabBar, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); |
|
connect(_tabBar, SIGNAL(tabDoubleClicked(int)), this, SLOT(tabDoubleClicked(int))); |
|
connect(_tabBar, SIGNAL(newTabRequest()), this, SIGNAL(newViewRequest())); |
|
connect(_tabBar, SIGNAL(wheelDelta(int)), this, SLOT(wheelScrolled(int))); |
|
connect(_tabBar, SIGNAL(initiateDrag(int)), this, SLOT(startTabDrag(int))); |
|
connect(_tabBar, SIGNAL(querySourceIndex(const QDropEvent*,int&)), |
|
this, SLOT(querySourceIndex(const QDropEvent*,int&))); |
|
connect(_tabBar, SIGNAL(moveViewRequest(int,const QDropEvent*,bool&,TabbedViewContainer*)), |
|
this, SLOT(onMoveViewRequest(int,const QDropEvent*,bool&,TabbedViewContainer*))); |
|
connect(_tabBar, SIGNAL(contextMenu(int,QPoint)), this, |
|
SLOT(openTabContextMenu(int,QPoint))); |
|
|
|
// The context menu of tab bar |
|
_contextPopupMenu = new KMenu(_tabBar); |
|
|
|
#if defined(ENABLE_DETACHING) |
|
_contextPopupMenu->addAction(KIcon("tab-detach"), |
|
i18nc("@action:inmenu", "&Detach Tab"), this, |
|
SLOT(tabContextMenuDetachTab())); |
|
#endif |
|
|
|
_contextPopupMenu->addAction(KIcon("edit-rename"), |
|
i18nc("@action:inmenu", "&Rename Tab..."), this, |
|
SLOT(tabContextMenuRenameTab())); |
|
|
|
_contextPopupMenu->addSeparator(); |
|
|
|
_contextPopupMenu->addAction(KIcon("tab-close"), |
|
i18nc("@action:inmenu", "&Close Tab"), this, |
|
SLOT(tabContextMenuCloseTab())); |
|
|
|
// The 'new tab' and 'close tab' button |
|
_newTabButton = new QToolButton(_containerWidget); |
|
_newTabButton->setFocusPolicy(Qt::NoFocus); |
|
_newTabButton->setIcon(KIcon("tab-new")); |
|
_newTabButton->setToolTip(i18nc("@info:tooltip", "Create new tab")); |
|
_newTabButton->setWhatsThis(i18nc("@info:whatsthis", "Create a new tab. Press and hold to select profile from menu")); |
|
_newTabButton->adjustSize(); |
|
|
|
QMenu* profileMenu = new QMenu(_newTabButton); |
|
ProfileList* profileList = new ProfileList(false, profileMenu); |
|
profileList->syncWidgetActions(profileMenu, true); |
|
connect(profileList, SIGNAL(profileSelected(Profile::Ptr)), |
|
this, SIGNAL(newViewRequest(Profile::Ptr))); |
|
setNewViewMenu(profileMenu); |
|
|
|
_closeTabButton = new QToolButton(_containerWidget); |
|
_closeTabButton->setFocusPolicy(Qt::NoFocus); |
|
_closeTabButton->setIcon(KIcon("tab-close")); |
|
_closeTabButton->setToolTip(i18nc("@info:tooltip", "Close tab")); |
|
_closeTabButton->setWhatsThis(i18nc("@info:whatsthis", "Close the active tab")); |
|
_closeTabButton->adjustSize(); |
|
|
|
// 'new tab' button is initially hidden. It will be shown when setFeatures() |
|
// is called with the QuickNewView flag enabled. The 'close tab' is the same. |
|
_newTabButton->setHidden(true); |
|
_closeTabButton->setHidden(true); |
|
|
|
connect(_newTabButton, SIGNAL(clicked()), this, SIGNAL(newViewRequest())); |
|
connect(_closeTabButton, SIGNAL(clicked()), this, SLOT(closeCurrentTab())); |
|
|
|
// Combine tab bar and 'new/close tab' buttons |
|
_tabBarLayout = new QHBoxLayout; |
|
_tabBarLayout->setSpacing(0); |
|
_tabBarLayout->setContentsMargins(0, 0, 0, 0); |
|
_tabBarLayout->addWidget(_newTabButton); |
|
_tabBarLayout->addWidget(_tabBar); |
|
_tabBarLayout->addWidget(_closeTabButton); |
|
|
|
// The search bar |
|
searchBar()->setParent(_containerWidget); |
|
|
|
// The overall layout |
|
_layout = new QVBoxLayout; |
|
_layout->setSpacing(0); |
|
_layout->setContentsMargins(0, 0, 0, 0); |
|
|
|
setNavigationPosition(position); |
|
|
|
_containerWidget->setLayout(_layout); |
|
} |
|
void TabbedViewContainer::setNewViewMenu(QMenu* menu) |
|
{ |
|
_newTabButton->setMenu(menu); |
|
} |
|
ViewContainer::Features TabbedViewContainer::supportedFeatures() const |
|
{ |
|
return QuickNewView | QuickCloseView; |
|
} |
|
void TabbedViewContainer::setFeatures(Features features) |
|
{ |
|
ViewContainer::setFeatures(features); |
|
updateVisibilityOfQuickButtons(); |
|
} |
|
|
|
void TabbedViewContainer::closeCurrentTab() |
|
{ |
|
if (_stackWidget->currentIndex() != -1) { |
|
emit closeTab(this, _stackWidget->widget(_stackWidget->currentIndex())); |
|
} |
|
} |
|
|
|
void TabbedViewContainer::updateVisibilityOfQuickButtons() |
|
{ |
|
const bool tabBarHidden = _tabBar->isHidden(); |
|
_newTabButton->setVisible(!tabBarHidden && (features() & QuickNewView)); |
|
_closeTabButton->setVisible(!tabBarHidden && (features() & QuickCloseView)); |
|
} |
|
|
|
void TabbedViewContainer::setTabBarVisible(bool visible) |
|
{ |
|
_tabBar->setVisible(visible); |
|
updateVisibilityOfQuickButtons(); |
|
} |
|
QList<ViewContainer::NavigationPosition> TabbedViewContainer::supportedNavigationPositions() const |
|
{ |
|
return QList<NavigationPosition>() << NavigationPositionTop << NavigationPositionBottom; |
|
} |
|
|
|
void TabbedViewContainer::navigationPositionChanged(NavigationPosition position) |
|
{ |
|
// this method assumes that there are three or zero items in the layout |
|
Q_ASSERT(_layout->count() == 3 || _layout->count() == 0); |
|
|
|
// clear all existing items from the layout |
|
_layout->removeItem(_tabBarLayout); |
|
_tabBarLayout->setParent(0); // suppress the warning of "already has a parent" |
|
_layout->removeWidget(_stackWidget); |
|
_layout->removeWidget(searchBar()); |
|
|
|
if (position == NavigationPositionTop) { |
|
_layout->insertLayout(-1, _tabBarLayout); |
|
_layout->insertWidget(-1, _stackWidget); |
|
_layout->insertWidget(-1, searchBar()); |
|
_tabBar->setShape(QTabBar::RoundedNorth); |
|
} else if (position == NavigationPositionBottom) { |
|
_layout->insertWidget(-1, _stackWidget); |
|
_layout->insertWidget(-1, searchBar()); |
|
_layout->insertLayout(-1, _tabBarLayout); |
|
_tabBar->setShape(QTabBar::RoundedSouth); |
|
} else { |
|
Q_ASSERT(false); // should never reach here |
|
} |
|
} |
|
void TabbedViewContainer::navigationVisibilityChanged(NavigationVisibility mode) |
|
{ |
|
if (mode == AlwaysShowNavigation && _tabBar->isHidden()) |
|
setTabBarVisible(true); |
|
|
|
if (mode == AlwaysHideNavigation && !_tabBar->isHidden()) |
|
setTabBarVisible(false); |
|
|
|
if (mode == ShowNavigationAsNeeded) |
|
dynamicTabBarVisibility(); |
|
} |
|
void TabbedViewContainer::dynamicTabBarVisibility() |
|
{ |
|
if (_tabBar->count() > 1 && _tabBar->isHidden()) |
|
setTabBarVisible(true); |
|
|
|
if (_tabBar->count() < 2 && !_tabBar->isHidden()) |
|
setTabBarVisible(false); |
|
} |
|
|
|
void TabbedViewContainer::setStyleSheet(const QString& styleSheet) |
|
{ |
|
_tabBar->setStyleSheet(styleSheet); |
|
} |
|
|
|
void TabbedViewContainer::navigationTextModeChanged(bool useTextWidth) |
|
{ |
|
if (useTextWidth) { |
|
_tabBar->setStyleSheet("QTabBar::tab { }"); |
|
_tabBar->setExpanding(false); |
|
_tabBar->setElideMode(Qt::ElideNone); |
|
} else { |
|
_tabBar->setStyleSheet("QTabBar::tab { min-width: 2em; max-width: 25em }"); |
|
_tabBar->setExpanding(true); |
|
_tabBar->setElideMode(Qt::ElideLeft); |
|
} |
|
} |
|
|
|
TabbedViewContainer::~TabbedViewContainer() |
|
{ |
|
if (!_containerWidget.isNull()) |
|
_containerWidget->deleteLater(); |
|
} |
|
|
|
void TabbedViewContainer::startTabDrag(int tab) |
|
{ |
|
QDrag* drag = new QDrag(_tabBar); |
|
const QRect tabRect = _tabBar->tabRect(tab); |
|
QPixmap tabPixmap = _tabBar->dragDropPixmap(tab); |
|
|
|
drag->setPixmap(tabPixmap); |
|
|
|
// offset the tab position so the tab will follow the cursor exactly |
|
// where it was clicked (as opposed to centering on the origin of the pixmap) |
|
QPoint mappedPos = _tabBar->mapFromGlobal(QCursor::pos()); |
|
mappedPos.rx() -= tabRect.x(); |
|
|
|
drag->setHotSpot(mappedPos); |
|
|
|
const int id = viewProperties(views()[tab])->identifier(); |
|
QWidget* view = views()[tab]; |
|
drag->setMimeData(ViewProperties::createMimeData(id)); |
|
|
|
// start dragging |
|
const Qt::DropAction action = drag->exec(); |
|
|
|
if (drag->target()) { |
|
switch (action) { |
|
case Qt::MoveAction: |
|
// The MoveAction indicates the widget has been successfully |
|
// moved into another tabbar/container, so remove the widget in |
|
// current tabbar/container. |
|
// |
|
// Deleting the view may cause the view container to be deleted, |
|
// which will also delete the QDrag object. This can cause a |
|
// crash if Qt's internal drag-and-drop handling tries to delete |
|
// it later. |
|
// |
|
// For now set the QDrag's parent to 0 so that it won't be |
|
// deleted if this view container is destroyed. |
|
// |
|
// FIXME: Resolve this properly |
|
drag->setParent(0); |
|
removeView(view); |
|
break; |
|
case Qt::IgnoreAction: |
|
// The IgnoreAction is used by the tabbar to indicate the |
|
// special case of dropping one tab into its existing position. |
|
// So nothing need to do here. |
|
break; |
|
default: |
|
break; |
|
} |
|
} else { |
|
// if the tab is dragged onto something that does not accept this |
|
// drop(for example, a different application or a different konsole |
|
// process), then detach the tab to achieve the effect of "dragging tab |
|
// out of current window and into its own window" |
|
// |
|
// It feels unnatural to do the detach when this is only one tab in the |
|
// tabbar |
|
if (_tabBar->count() > 1) |
|
emit detachTab(this, view); |
|
} |
|
} |
|
|
|
void TabbedViewContainer::querySourceIndex(const QDropEvent* event, int& sourceIndex) |
|
{ |
|
const int droppedId = ViewProperties::decodeMimeData(event->mimeData()); |
|
|
|
const QList<QWidget*> viewList = views(); |
|
const int count = viewList.count(); |
|
int index = -1; |
|
for (index = 0; index < count; index++) { |
|
const int id = viewProperties(viewList[index])->identifier(); |
|
if (id == droppedId) |
|
break; |
|
} |
|
|
|
sourceIndex = index; |
|
} |
|
|
|
void TabbedViewContainer::onMoveViewRequest(int index, const QDropEvent* event ,bool& success, TabbedViewContainer* sourceTabbedContainer) |
|
{ |
|
const int droppedId = ViewProperties::decodeMimeData(event->mimeData()); |
|
emit moveViewRequest(index, droppedId, success, sourceTabbedContainer); |
|
} |
|
|
|
void TabbedViewContainer::tabDoubleClicked(int index) |
|
{ |
|
renameTab(index); |
|
} |
|
|
|
void TabbedViewContainer::renameTab(int index) |
|
{ |
|
viewProperties(views()[index])->rename(); |
|
} |
|
|
|
void TabbedViewContainer::openTabContextMenu(int index, const QPoint& pos) |
|
{ |
|
_contextMenuTabIndex = index; |
|
|
|
#if defined(ENABLE_DETACHING) |
|
// Enable 'Detach Tab' menu item only if there is more than 1 tab |
|
// Note: the code is coupled with that action's position within the menu |
|
QAction* detachAction = _contextPopupMenu->actions().first(); |
|
detachAction->setEnabled(_tabBar->count() > 1); |
|
#endif |
|
|
|
_contextPopupMenu->exec(pos); |
|
} |
|
|
|
void TabbedViewContainer::tabContextMenuCloseTab() |
|
{ |
|
_tabBar->setCurrentIndex(_contextMenuTabIndex);// Required for this to work |
|
emit closeTab(this, _stackWidget->widget(_contextMenuTabIndex)); |
|
} |
|
|
|
void TabbedViewContainer::tabContextMenuDetachTab() |
|
{ |
|
emit detachTab(this, _stackWidget->widget(_contextMenuTabIndex)); |
|
} |
|
|
|
void TabbedViewContainer::tabContextMenuRenameTab() |
|
{ |
|
renameTab(_contextMenuTabIndex); |
|
} |
|
|
|
void TabbedViewContainer::moveViewWidget(int fromIndex , int toIndex) |
|
{ |
|
QString text = _tabBar->tabText(fromIndex); |
|
QIcon icon = _tabBar->tabIcon(fromIndex); |
|
|
|
// FIXME - This will lose properties of the tab other than |
|
// their text and icon when moving them |
|
|
|
_tabBar->removeTab(fromIndex); |
|
_tabBar->insertTab(toIndex, icon, text); |
|
|
|
QWidget* widget = _stackWidget->widget(fromIndex); |
|
_stackWidget->removeWidget(widget); |
|
_stackWidget->insertWidget(toIndex, widget); |
|
} |
|
void TabbedViewContainer::currentTabChanged(int index) |
|
{ |
|
_stackWidget->setCurrentIndex(index); |
|
if (_stackWidget->widget(index)) |
|
emit activeViewChanged(_stackWidget->widget(index)); |
|
|
|
// clear activity indicators |
|
setTabActivity(index, false); |
|
} |
|
|
|
void TabbedViewContainer::wheelScrolled(int delta) |
|
{ |
|
if (delta < 0) |
|
activateNextView(); |
|
else |
|
activatePreviousView(); |
|
} |
|
|
|
QWidget* TabbedViewContainer::containerWidget() const |
|
{ |
|
return _containerWidget; |
|
} |
|
QWidget* TabbedViewContainer::activeView() const |
|
{ |
|
return _stackWidget->currentWidget(); |
|
} |
|
void TabbedViewContainer::setActiveView(QWidget* view) |
|
{ |
|
const int index = _stackWidget->indexOf(view); |
|
|
|
Q_ASSERT(index != -1); |
|
|
|
_stackWidget->setCurrentWidget(view); |
|
_tabBar->setCurrentIndex(index); |
|
} |
|
void TabbedViewContainer::addViewWidget(QWidget* view , int index) |
|
{ |
|
_stackWidget->insertWidget(index, view); |
|
_stackWidget->updateGeometry(); |
|
|
|
ViewProperties* item = viewProperties(view); |
|
connect(item, SIGNAL(titleChanged(ViewProperties*)), this , |
|
SLOT(updateTitle(ViewProperties*))); |
|
connect(item, SIGNAL(iconChanged(ViewProperties*)), this , |
|
SLOT(updateIcon(ViewProperties*))); |
|
connect(item, SIGNAL(activity(ViewProperties*)), this , |
|
SLOT(updateActivity(ViewProperties*))); |
|
|
|
_tabBar->insertTab(index , item->icon() , item->title()); |
|
|
|
if (navigationVisibility() == ShowNavigationAsNeeded) |
|
dynamicTabBarVisibility(); |
|
} |
|
void TabbedViewContainer::removeViewWidget(QWidget* view) |
|
{ |
|
if (!_stackWidget) |
|
return; |
|
const int index = _stackWidget->indexOf(view); |
|
|
|
Q_ASSERT(index != -1); |
|
|
|
_stackWidget->removeWidget(view); |
|
_tabBar->removeTab(index); |
|
|
|
if (navigationVisibility() == ShowNavigationAsNeeded) |
|
dynamicTabBarVisibility(); |
|
} |
|
|
|
void TabbedViewContainer::setTabActivity(int index , bool activity) |
|
{ |
|
const QPalette& palette = _tabBar->palette(); |
|
KColorScheme colorScheme(palette.currentColorGroup()); |
|
const QColor colorSchemeActive = colorScheme.foreground(KColorScheme::ActiveText).color(); |
|
|
|
const QColor normalColor = palette.text().color(); |
|
const QColor activityColor = KColorUtils::mix(normalColor, colorSchemeActive); |
|
|
|
QColor color = activity ? activityColor : QColor(); |
|
|
|
if (color != _tabBar->tabTextColor(index)) |
|
_tabBar->setTabTextColor(index, color); |
|
} |
|
|
|
void TabbedViewContainer::updateActivity(ViewProperties* item) |
|
{ |
|
foreach(QWidget* widget, widgetsForItem(item)) { |
|
const int index = _stackWidget->indexOf(widget); |
|
|
|
if (index != _stackWidget->currentIndex()) { |
|
setTabActivity(index, true); |
|
} |
|
} |
|
} |
|
|
|
void TabbedViewContainer::updateTitle(ViewProperties* item) |
|
{ |
|
foreach(QWidget* widget, widgetsForItem(item)) { |
|
const int index = _stackWidget->indexOf(widget); |
|
QString tabText = item->title(); |
|
|
|
_tabBar->setTabToolTip(index , tabText); |
|
|
|
// To avoid having & replaced with _ (shortcut indicator) |
|
tabText.replace('&', "&&"); |
|
_tabBar->setTabText(index , tabText); |
|
} |
|
} |
|
void TabbedViewContainer::updateIcon(ViewProperties* item) |
|
{ |
|
foreach(QWidget* widget, widgetsForItem(item)) { |
|
const int index = _stackWidget->indexOf(widget); |
|
_tabBar->setTabIcon(index , item->icon()); |
|
} |
|
} |
|
|
|
ViewManager* TabbedViewContainer::connectedViewManager() |
|
{ |
|
return _connectedViewManager; |
|
} |
|
|
|
StackedViewContainer::StackedViewContainer(QObject* parent) |
|
: ViewContainer(NavigationPositionTop, parent) |
|
{ |
|
_containerWidget = new QWidget; |
|
QVBoxLayout* layout = new QVBoxLayout(_containerWidget); |
|
|
|
_stackWidget = new QStackedWidget(_containerWidget); |
|
|
|
searchBar()->setParent(_containerWidget); |
|
layout->addWidget(searchBar()); |
|
layout->addWidget(_stackWidget); |
|
layout->setContentsMargins(0, 0, 0, 0); |
|
} |
|
StackedViewContainer::~StackedViewContainer() |
|
{ |
|
if (!_containerWidget.isNull()) |
|
_containerWidget->deleteLater(); |
|
} |
|
QWidget* StackedViewContainer::containerWidget() const |
|
{ |
|
return _containerWidget; |
|
} |
|
QWidget* StackedViewContainer::activeView() const |
|
{ |
|
return _stackWidget->currentWidget(); |
|
} |
|
void StackedViewContainer::setActiveView(QWidget* view) |
|
{ |
|
_stackWidget->setCurrentWidget(view); |
|
} |
|
void StackedViewContainer::addViewWidget(QWidget* view , int) |
|
{ |
|
_stackWidget->addWidget(view); |
|
} |
|
void StackedViewContainer::removeViewWidget(QWidget* view) |
|
{ |
|
if (!_stackWidget) |
|
return; |
|
const int index = _stackWidget->indexOf(view); |
|
|
|
Q_ASSERT(index != -1); |
|
Q_UNUSED(index); |
|
|
|
_stackWidget->removeWidget(view); |
|
} |
|
|
|
#include "ViewContainer.moc"
|
|
|