2 This file is part of the Konsole Terminal.
4 Copyright 2006-2008 Robert Knight <robertknight@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "ViewContainer.h"
26 #include <QtCore/QHash>
27 #include <QtGui/QLabel>
28 #include <QtGui/QLineEdit>
29 #include <QtGui/QBrush>
30 #include <QtGui/QListWidget>
31 #include <QtGui/QSplitter>
32 #include <QtGui/QStackedWidget>
33 #include <QtGui/QTabBar>
34 #include <QtGui/QToolButton>
35 #include <QtGui/QWidgetAction>
37 #include <QtGui/QDrag>
38 #include <QtGui/QDragMoveEvent>
42 #include <KColorDialog>
43 #include <kcolorscheme.h>
44 #include <kcolorutils.h>
46 #include <kconfiggroup.h>
49 #include <KColorCollection>
53 #include "IncrementalSearchBar.h"
54 #include "ViewProperties.h"
56 // TODO Perhaps move everything which is Konsole-specific into different files
57 #include "ProfileListWidget.h"
59 using namespace Konsole
;
61 ViewContainer::ViewContainer(NavigationPosition position
, QObject
* parent
)
63 , _navigationDisplayMode(AlwaysShowNavigation
)
64 , _navigationPosition(position
)
69 ViewContainer::~ViewContainer()
71 foreach( QWidget
* view
, _views
)
73 disconnect(view
,SIGNAL(destroyed(QObject
*)),this,SLOT(viewDestroyed(QObject
*)));
77 _searchBar
->deleteLater();
82 void ViewContainer::moveViewWidget( int , int ) {}
83 void ViewContainer::setFeatures(Features features
)
84 { _features
= features
; }
85 ViewContainer::Features
ViewContainer::features() const
87 void ViewContainer::moveActiveView( MoveDirection direction
)
89 const int currentIndex
= _views
.indexOf( activeView() ) ;
95 newIndex
= qMax( currentIndex
-1 , 0 );
98 newIndex
= qMin( currentIndex
+1 , _views
.count() -1 );
102 Q_ASSERT( newIndex
!= -1 );
104 moveViewWidget( currentIndex
, newIndex
);
106 _views
.swap(currentIndex
,newIndex
);
108 setActiveView( _views
[newIndex
] );
111 void ViewContainer::setNavigationDisplayMode(NavigationDisplayMode mode
)
113 _navigationDisplayMode
= mode
;
114 navigationDisplayModeChanged(mode
);
116 ViewContainer::NavigationPosition
ViewContainer::navigationPosition() const
118 return _navigationPosition
;
120 void ViewContainer::setNavigationPosition(NavigationPosition position
)
122 // assert that this position is supported
123 Q_ASSERT( supportedNavigationPositions().contains(position
) );
125 _navigationPosition
= position
;
127 navigationPositionChanged(position
);
129 QList
<ViewContainer::NavigationPosition
> ViewContainer::supportedNavigationPositions() const
131 return QList
<NavigationPosition
>() << NavigationPositionTop
;
133 ViewContainer::NavigationDisplayMode
ViewContainer::navigationDisplayMode() const
135 return _navigationDisplayMode
;
137 void ViewContainer::addView(QWidget
* view
, ViewProperties
* item
, int index
)
142 _views
.insert(index
,view
);
144 _navigation
[view
] = item
;
146 connect( view
, SIGNAL(destroyed(QObject
*)) , this , SLOT( viewDestroyed(QObject
*) ) );
148 addViewWidget(view
,index
);
150 emit
viewAdded(view
,item
);
152 void ViewContainer::viewDestroyed(QObject
* object
)
154 QWidget
* widget
= static_cast<QWidget
*>(object
);
156 _views
.removeAll(widget
);
157 _navigation
.remove(widget
);
159 // FIXME This can result in ViewContainerSubClass::removeViewWidget() being
160 // called after the widget's parent has been deleted or partially deleted
161 // in the ViewContainerSubClass instance's destructor.
163 // Currently deleteLater() is used to remove child widgets in the subclass
164 // constructors to get around the problem, but this is a hack and needs
166 removeViewWidget(widget
);
168 emit
viewRemoved(widget
);
170 if (_views
.count() == 0)
173 void ViewContainer::removeView(QWidget
* view
)
175 _views
.removeAll(view
);
176 _navigation
.remove(view
);
178 disconnect( view
, SIGNAL(destroyed(QObject
*)) , this , SLOT( viewDestroyed(QObject
*) ) );
180 removeViewWidget(view
);
182 emit
viewRemoved(view
);
184 if (_views
.count() == 0)
189 const QList
<QWidget
*> ViewContainer::views()
194 IncrementalSearchBar
* ViewContainer::searchBar()
197 _searchBar
= new IncrementalSearchBar( IncrementalSearchBar::AllFeatures
, 0);
198 _searchBar
->setVisible(false);
199 connect(_searchBar
, SIGNAL(destroyed(QObject
*)), this, SLOT(searchBarDestroyed()));
204 void ViewContainer::searchBarDestroyed()
209 void ViewContainer::activateNextView()
211 QWidget
* active
= activeView();
213 int index
= _views
.indexOf(active
);
218 if ( index
== _views
.count() - 1 )
223 setActiveView( _views
.at(index
) );
226 void ViewContainer::activatePreviousView()
228 QWidget
* active
= activeView();
230 int index
= _views
.indexOf(active
);
236 index
= _views
.count() - 1;
240 setActiveView( _views
.at(index
) );
243 ViewProperties
* ViewContainer::viewProperties( QWidget
* widget
)
245 Q_ASSERT( _navigation
.contains(widget
) );
247 return _navigation
[widget
];
250 QList
<QWidget
*> ViewContainer::widgetsForItem(ViewProperties
* item
) const
252 return _navigation
.keys(item
);
255 ViewContainerTabBar::ViewContainerTabBar(QWidget
* parent
,TabbedViewContainer
* container
)
257 , _container(container
)
259 , _dropIndicatorIndex(-1)
260 , _drawIndicatorDisabled(false)
263 void ViewContainerTabBar::setDropIndicator(int index
, bool drawDisabled
)
265 if (!parentWidget() || _dropIndicatorIndex
== index
)
268 _dropIndicatorIndex
= index
;
269 const int ARROW_SIZE
= 22;
270 bool north
= shape() == QTabBar::RoundedNorth
|| shape() == QTabBar::TriangularNorth
;
272 if (!_dropIndicator
|| _drawIndicatorDisabled
!= drawDisabled
)
276 _dropIndicator
= new QLabel(parentWidget());
277 _dropIndicator
->resize(ARROW_SIZE
,ARROW_SIZE
);
280 QIcon::Mode drawMode
= drawDisabled
? QIcon::Disabled
: QIcon::Normal
;
281 const QString iconName
= north
? "arrow-up" : "arrow-down";
282 _dropIndicator
->setPixmap(KIcon(iconName
).pixmap(ARROW_SIZE
,ARROW_SIZE
,drawMode
));
283 _drawIndicatorDisabled
= drawDisabled
;
288 _dropIndicator
->hide();
292 const QRect rect
= tabRect(index
< count() ? index
: index
-1);
296 pos
= rect
.topLeft();
298 pos
= rect
.topRight();
301 pos
.ry() += ARROW_SIZE
;
303 pos
.ry() -= ARROW_SIZE
;
305 pos
.rx() -= ARROW_SIZE
/2;
307 _dropIndicator
->move(mapTo(parentWidget(),pos
));
308 _dropIndicator
->show();
311 void ViewContainerTabBar::dragLeaveEvent(QDragLeaveEvent
*)
313 setDropIndicator(-1);
315 void ViewContainerTabBar::dragEnterEvent(QDragEnterEvent
* event
)
317 if (event
->mimeData()->hasFormat(ViewProperties::mimeType()) &&
318 event
->source() != 0)
319 event
->acceptProposedAction();
321 void ViewContainerTabBar::dragMoveEvent(QDragMoveEvent
* event
)
323 if (event
->mimeData()->hasFormat(ViewProperties::mimeType())
324 && event
->source() != 0)
326 int index
= dropIndex(event
->pos());
330 setDropIndicator(index
,proposedDropIsSameTab(event
));
332 event
->acceptProposedAction();
335 int ViewContainerTabBar::dropIndex(const QPoint
& pos
) const
337 int tab
= tabAt(pos
);
341 // pick the closest tab boundary
342 QRect rect
= tabRect(tab
);
343 if ( (pos
.x()-rect
.left()) > (rect
.width()/2) )
351 bool ViewContainerTabBar::proposedDropIsSameTab(const QDropEvent
* event
) const
353 int index
= dropIndex(event
->pos());
354 int droppedId
= ViewProperties::decodeMimeData(event
->mimeData());
355 bool sameTabBar
= event
->source() == this;
360 const QList
<QWidget
*> viewList
= _container
->views();
361 int sourceIndex
= -1;
362 for (int i
=0;i
<count();i
++)
364 int idAtIndex
= _container
->viewProperties(viewList
[i
])->identifier();
365 if (idAtIndex
== droppedId
)
369 bool sourceAndDropAreLast
= sourceIndex
== count()-1 && index
== -1;
370 if (sourceIndex
== index
|| sourceIndex
== index
-1 || sourceAndDropAreLast
)
375 void ViewContainerTabBar::dropEvent(QDropEvent
* event
)
377 setDropIndicator(-1);
379 if ( !event
->mimeData()->hasFormat(ViewProperties::mimeType())
380 || proposedDropIsSameTab(event
) )
386 int index
= dropIndex(event
->pos());
387 int droppedId
= ViewProperties::decodeMimeData(event
->mimeData());
389 emit _container
->moveViewRequest(index
,droppedId
,result
);
397 QSize
ViewContainerTabBar::tabSizeHint(int index
) const
399 return QTabBar::tabSizeHint(index
);
401 QPixmap
ViewContainerTabBar::dragDropPixmap(int tab
)
403 Q_ASSERT(tab
>= 0 && tab
< count());
405 // TODO - grabWidget() works except that it includes part
406 // of the tab bar outside the tab itself if the tab has
408 const QRect rect
= tabRect(tab
);
409 const int borderWidth
= 1;
411 QPixmap
tabPixmap(rect
.width()+borderWidth
,
412 rect
.height()+borderWidth
);
413 QPainter
painter(&tabPixmap
);
414 painter
.drawPixmap(0,0,QPixmap::grabWidget(this,rect
));
416 borderPen
.setBrush(palette().dark());
417 borderPen
.setWidth(borderWidth
);
418 painter
.setPen(borderPen
);
419 painter
.drawRect(0,0,rect
.width(),rect
.height());
424 TabbedViewContainer::TabbedViewContainer(NavigationPosition position
, QObject
* parent
)
425 : ViewContainer(position
,parent
)
427 _containerWidget
= new QWidget
;
428 _stackWidget
= new QStackedWidget();
429 _tabBar
= new ViewContainerTabBar(_containerWidget
,this);
430 _tabBar
->setDrawBase(true);
432 const int cornerButtonWidth
= 50;
433 _newTabButton
= new KPushButton(KIcon("tab-new"),QString(),_containerWidget
);
434 // The button width here is hard coded, it would be better to use the value from
435 // the current style (see QTabWidget::setUpLayout())
436 _newTabButton
->setFixedWidth(cornerButtonWidth
);
437 _newTabButton
->setFlat(true);
438 // new tab button is initially hidden, it will be shown when setFeatures() is called
439 // with the QuickNewView flag enabled
440 _newTabButton
->setHidden(true);
442 _closeTabButton
= new KPushButton(KIcon("tab-close"),QString(),_containerWidget
);
443 _closeTabButton
->setFixedWidth(cornerButtonWidth
);
444 _closeTabButton
->setFlat(true);
445 _closeTabButton
->setHidden(true);
447 connect( _tabBar
, SIGNAL(currentChanged(int)) , this , SLOT(currentTabChanged(int)) );
448 connect( _tabBar
, SIGNAL(tabDoubleClicked(int)) , this , SLOT(tabDoubleClicked(int)) );
449 connect( _tabBar
, SIGNAL(newTabRequest()) , this , SIGNAL(newViewRequest()) );
450 connect( _tabBar
, SIGNAL(wheelDelta(int)) , this , SLOT(wheelScrolled(int)) );
451 connect( _tabBar
, SIGNAL(closeRequest(int)) , this , SLOT(closeTab(int)) );
452 connect( _tabBar
, SIGNAL(initiateDrag(int)) , this , SLOT(startTabDrag(int)) );
454 connect( _newTabButton
, SIGNAL(clicked()) , this , SIGNAL(newViewRequest()) );
455 connect( _closeTabButton
, SIGNAL(clicked()) , this , SLOT(closeCurrentTab()) );
457 _layout
= new TabbedViewContainerLayout
;
458 _layout
->setSpacing(0);
459 _layout
->setMargin(0);
460 _tabBarLayout
= new QHBoxLayout
;
461 _tabBarLayout
->setSpacing(0);
462 _tabBarLayout
->setMargin(0);
463 _tabBarLayout
->addWidget(_newTabButton
);
464 _tabBarLayout
->addWidget(_tabBar
);
465 _tabBarLayout
->addWidget(_closeTabButton
);
466 _tabBarSpacer
= new QSpacerItem(0,TabBarSpace
);
468 _layout
->addWidget(_stackWidget
);
469 searchBar()->setParent(_containerWidget
);
470 if ( position
== NavigationPositionTop
)
472 _layout
->insertLayout(0,_tabBarLayout
);
473 _layout
->insertItemAt(0,_tabBarSpacer
);
474 _layout
->insertWidget(-1,searchBar());
475 _tabBar
->setShape(QTabBar::RoundedNorth
);
477 else if ( position
== NavigationPositionBottom
)
479 _layout
->insertWidget(-1,searchBar());
480 _layout
->insertLayout(-1,_tabBarLayout
);
481 _layout
->insertItemAt(-1,_tabBarSpacer
);
482 _tabBar
->setShape(QTabBar::RoundedSouth
);
485 Q_ASSERT(false); // position not supported
487 _containerWidget
->setLayout(_layout
);
489 void TabbedViewContainer::setNewViewMenu(QMenu
* menu
)
491 _newTabButton
->setDelayedMenu(menu
);
493 ViewContainer::Features
TabbedViewContainer::supportedFeatures() const
495 return QuickNewView
|QuickCloseView
;
497 void TabbedViewContainer::setFeatures(Features features
)
499 ViewContainer::setFeatures(features
);
501 const bool tabBarHidden
= _tabBar
->isHidden();
502 _newTabButton
->setVisible(!tabBarHidden
&& (features
& QuickNewView
));
503 _closeTabButton
->setVisible(!tabBarHidden
&& (features
& QuickCloseView
));
505 void TabbedViewContainer::closeCurrentTab()
507 if (_stackWidget
->currentIndex() != -1)
509 closeTab(_stackWidget
->currentIndex());
512 void TabbedViewContainer::closeTab(int tab
)
514 Q_ASSERT(tab
>= 0 && tab
< _stackWidget
->count());
516 if (viewProperties(_stackWidget
->widget(tab
))->confirmClose())
517 removeView(_stackWidget
->widget(tab
));
519 void TabbedViewContainer::setTabBarVisible(bool visible
)
521 _tabBar
->setVisible(visible
);
522 _newTabButton
->setVisible(visible
&& (features() & QuickNewView
));
523 _closeTabButton
->setVisible(visible
&& (features() & QuickCloseView
));
526 _tabBarSpacer
->changeSize(0,TabBarSpace
);
530 _tabBarSpacer
->changeSize(0,0);
533 QList
<ViewContainer::NavigationPosition
> TabbedViewContainer::supportedNavigationPositions() const
535 return QList
<NavigationPosition
>() << NavigationPositionTop
<< NavigationPositionBottom
;
537 void TabbedViewContainer::navigationPositionChanged(NavigationPosition position
)
539 // this method assumes that there are only three items
541 Q_ASSERT( _layout
->count() == 4 );
543 // index of stack widget in the layout when tab bar is at the bottom
544 const int StackIndexWithTabBottom
= 0;
546 if ( position
== NavigationPositionTop
547 && _layout
->indexOf(_stackWidget
) == StackIndexWithTabBottom
)
549 _layout
->removeItem(_tabBarLayout
);
550 _layout
->removeItem(_tabBarSpacer
);
551 _layout
->removeWidget(searchBar());
553 _layout
->insertLayout(0,_tabBarLayout
);
554 _layout
->insertItemAt(0,_tabBarSpacer
);
555 _layout
->insertWidget(-1,searchBar());
556 _tabBar
->setShape(QTabBar::RoundedNorth
);
558 else if ( position
== NavigationPositionBottom
559 && _layout
->indexOf(_stackWidget
) != StackIndexWithTabBottom
)
561 _layout
->removeItem(_tabBarLayout
);
562 _layout
->removeItem(_tabBarSpacer
);
563 _layout
->removeWidget(searchBar());
565 _layout
->insertWidget(-1,searchBar());
566 _layout
->insertLayout(-1,_tabBarLayout
);
567 _layout
->insertItemAt(-1,_tabBarSpacer
);
568 _tabBar
->setShape(QTabBar::RoundedSouth
);
571 void TabbedViewContainer::navigationDisplayModeChanged(NavigationDisplayMode mode
)
573 if ( mode
== AlwaysShowNavigation
&& _tabBar
->isHidden() )
574 setTabBarVisible(true);
576 if ( mode
== AlwaysHideNavigation
&& !_tabBar
->isHidden() )
577 setTabBarVisible(false);
579 if ( mode
== ShowNavigationAsNeeded
)
580 dynamicTabBarVisibility();
582 void TabbedViewContainer::dynamicTabBarVisibility()
584 if ( _tabBar
->count() > 1 && _tabBar
->isHidden() )
585 setTabBarVisible(true);
587 if ( _tabBar
->count() < 2 && !_tabBar
->isHidden() )
588 setTabBarVisible(false);
590 TabbedViewContainer::~TabbedViewContainer()
592 if (!_containerWidget
.isNull())
593 _containerWidget
->deleteLater();
596 void TabbedViewContainer::startTabDrag(int tab
)
598 QDrag
* drag
= new QDrag(_tabBar
);
599 const QRect tabRect
= _tabBar
->tabRect(tab
);
600 QPixmap tabPixmap
= _tabBar
->dragDropPixmap(tab
);
602 drag
->setPixmap(tabPixmap
);
604 int id
= viewProperties(views()[tab
])->identifier();
605 QWidget
* view
= views()[tab
];
606 drag
->setMimeData(ViewProperties::createMimeData(id
));
608 // start drag, if drag-and-drop is successful the view at 'tab' will be
611 // if the tab was dragged onto another application
612 // which blindly accepted the drop then ignore it
613 if (drag
->exec() == Qt::MoveAction
&& drag
->target() != 0)
615 // Deleting the view may cause the view container to be deleted, which
616 // will also delete the QDrag object.
617 // This can cause a crash if Qt's internal drag-and-drop handling
618 // tries to delete it later.
620 // For now set the QDrag's parent to 0 so that it won't be deleted if
621 // this view container is destroyed.
623 // FIXME: Resolve this properly
628 void TabbedViewContainer::tabDoubleClicked(int tab
)
630 viewProperties( views()[tab
] )->rename();
632 void TabbedViewContainer::moveViewWidget( int fromIndex
, int toIndex
)
634 QString text
= _tabBar
->tabText(fromIndex
);
635 QIcon icon
= _tabBar
->tabIcon(fromIndex
);
637 // FIXME - This will lose properties of the tab other than
638 // their text and icon when moving them
640 _tabBar
->removeTab(fromIndex
);
641 _tabBar
->insertTab(toIndex
,icon
,text
);
643 QWidget
* widget
= _stackWidget
->widget(fromIndex
);
644 _stackWidget
->removeWidget(widget
);
645 _stackWidget
->insertWidget(toIndex
,widget
);
647 void TabbedViewContainer::currentTabChanged(int index
)
649 _stackWidget
->setCurrentIndex(index
);
650 if (_stackWidget
->widget(index
))
651 emit
activeViewChanged(_stackWidget
->widget(index
));
653 // clear activity indicators
654 setTabActivity(index
,false);
657 void TabbedViewContainer::wheelScrolled(int delta
)
662 activatePreviousView();
665 QWidget
* TabbedViewContainer::containerWidget() const
667 return _containerWidget
;
669 QWidget
* TabbedViewContainer::activeView() const
671 return _stackWidget
->currentWidget();
673 void TabbedViewContainer::setActiveView(QWidget
* view
)
675 const int index
= _stackWidget
->indexOf(view
);
677 Q_ASSERT( index
!= -1 );
679 _stackWidget
->setCurrentWidget(view
);
680 _tabBar
->setCurrentIndex(index
);
682 void TabbedViewContainer::addViewWidget( QWidget
* view
, int index
)
684 _stackWidget
->insertWidget(index
,view
);
685 _stackWidget
->updateGeometry();
687 ViewProperties
* item
= viewProperties(view
);
688 connect( item
, SIGNAL(titleChanged(ViewProperties
*)) , this ,
689 SLOT(updateTitle(ViewProperties
*)));
690 connect( item
, SIGNAL(iconChanged(ViewProperties
*) ) , this ,
691 SLOT(updateIcon(ViewProperties
*)));
692 connect( item
, SIGNAL(activity(ViewProperties
*)) , this ,
693 SLOT(updateActivity(ViewProperties
*)));
695 _tabBar
->insertTab( index
, item
->icon() , item
->title() );
697 if ( navigationDisplayMode() == ShowNavigationAsNeeded
)
698 dynamicTabBarVisibility();
700 void TabbedViewContainer::removeViewWidget( QWidget
* view
)
704 const int index
= _stackWidget
->indexOf(view
);
706 Q_ASSERT( index
!= -1 );
708 _stackWidget
->removeWidget(view
);
709 _tabBar
->removeTab(index
);
711 if ( navigationDisplayMode() == ShowNavigationAsNeeded
)
712 dynamicTabBarVisibility();
715 void TabbedViewContainer::setTabActivity(int index
, bool activity
)
717 const QPalette
& palette
= _tabBar
->palette();
718 KColorScheme
colorScheme(palette
.currentColorGroup());
719 const QColor colorSchemeActive
= colorScheme
.foreground(KColorScheme::ActiveText
).color();
721 const QColor normalColor
= palette
.text().color();
722 const QColor activityColor
= KColorUtils::mix(normalColor
,colorSchemeActive
);
724 QColor color
= activity
? activityColor
: QColor();
726 if ( color
!= _tabBar
->tabTextColor(index
) )
727 _tabBar
->setTabTextColor(index
,color
);
730 void TabbedViewContainer::updateActivity(ViewProperties
* item
)
732 QListIterator
<QWidget
*> iter(widgetsForItem(item
));
733 while ( iter
.hasNext() )
735 const int index
= _stackWidget
->indexOf(iter
.next());
737 if ( index
!= _stackWidget
->currentIndex() )
739 setTabActivity(index
,true);
744 void TabbedViewContainer::updateTitle(ViewProperties
* item
)
746 // prevent tab titles from becoming overly-long as this limits the number
747 // of tabs which can fit in the tab bar.
749 // if the view's title is overly long then trim it and select the
750 // right-most 20 characters (assuming they contain the most useful
751 // information) and insert an elide at the front
752 const int MAX_TAB_TEXT_LENGTH
= 20;
754 QListIterator
<QWidget
*> iter(widgetsForItem(item
));
755 while ( iter
.hasNext() )
757 const int index
= _stackWidget
->indexOf( iter
.next() );
759 QString tabText
= item
->title();
760 if (tabText
.count() > MAX_TAB_TEXT_LENGTH
)
761 tabText
= tabText
.right(MAX_TAB_TEXT_LENGTH
).prepend("...");
763 _tabBar
->setTabText( index
, tabText
);
766 void TabbedViewContainer::updateIcon(ViewProperties
* item
)
768 QListIterator
<QWidget
*> iter(widgetsForItem(item
));
769 while ( iter
.hasNext() )
771 const int index
= _stackWidget
->indexOf( iter
.next() );
772 _tabBar
->setTabIcon( index
, item
->icon() );
776 StackedViewContainer::StackedViewContainer(QObject
* parent
)
777 : ViewContainer(NavigationPositionTop
,parent
)
779 _containerWidget
= new QWidget
;
780 QVBoxLayout
*layout
= new QVBoxLayout(_containerWidget
);
782 _stackWidget
= new QStackedWidget(_containerWidget
);
784 searchBar()->setParent(_containerWidget
);
785 layout
->addWidget(searchBar());
786 layout
->addWidget(_stackWidget
);
788 StackedViewContainer::~StackedViewContainer()
790 if (!_containerWidget
.isNull())
791 _containerWidget
->deleteLater();
793 QWidget
* StackedViewContainer::containerWidget() const
795 return _containerWidget
;
797 QWidget
* StackedViewContainer::activeView() const
799 return _stackWidget
->currentWidget();
801 void StackedViewContainer::setActiveView(QWidget
* view
)
803 _stackWidget
->setCurrentWidget(view
);
805 void StackedViewContainer::addViewWidget( QWidget
* view
, int )
807 _stackWidget
->addWidget(view
);
809 void StackedViewContainer::removeViewWidget( QWidget
* view
)
813 const int index
= _stackWidget
->indexOf(view
);
815 Q_ASSERT( index
!= -1);
817 _stackWidget
->removeWidget(view
);
820 ListViewContainer::ListViewContainer(NavigationPosition position
,QObject
* parent
)
821 : ViewContainer(position
,parent
)
823 _splitter
= new QSplitter
;
824 _listWidget
= new ProfileListWidget(_splitter
);
826 QWidget
*contentArea
= new QWidget(_splitter
);
827 QVBoxLayout
*layout
= new QVBoxLayout(contentArea
);
828 _stackWidget
= new QStackedWidget(contentArea
);
829 searchBar()->setParent(contentArea
);
830 layout
->addWidget(_stackWidget
);
831 layout
->addWidget(searchBar());
833 // elide left is used because the most informative part of the session name is often
834 // the rightmost part
836 // this means you get entries looking like:
838 // ...dirA ...dirB ...dirC ( helpful )
842 // johnSmith@comput... johnSmith@comput... ( not so helpful )
845 _listWidget
->setTextElideMode( Qt::ElideLeft
);
846 _listWidget
->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff
);
847 _listWidget
->setDragDropMode(QAbstractItemView::DragDrop
);
848 _splitter
->addWidget(_listWidget
);
849 _splitter
->addWidget(contentArea
);
851 connect( _listWidget
, SIGNAL(currentRowChanged(int)) , this , SLOT(rowChanged(int)) );
854 ListViewContainer::~ListViewContainer()
856 _splitter
->deleteLater();
859 QWidget
* ListViewContainer::containerWidget() const
864 QWidget
* ListViewContainer::activeView() const
866 return _stackWidget
->currentWidget();
869 QBrush
ListViewContainer::randomItemBackground(int r
)
873 //and now for something truly unpleasant:
874 static const int r1
[] = {255,190,190,255,190,255};
875 static const int r2
[] = {255,180,180,255,180,255};
876 static const int b1
[] = {190,255,190,255,255,190};
877 static const int b2
[] = {180,255,180,255,255,180};
878 static const int g1
[] = {190,190,255,190,255,255};
879 static const int g2
[] = {180,180,255,180,255,255};
881 // hardcoded assumes item height is 32px
882 QLinearGradient
gradient( QPoint(0,0) , QPoint(0,32) );
883 gradient
.setColorAt(0,QColor(r1
[i
],g1
[i
],b1
[i
],100));
884 gradient
.setColorAt(0.5,QColor(r2
[i
],g2
[i
],b2
[i
],100));
885 gradient
.setColorAt(1,QColor(r1
[i
],g1
[i
],b1
[i
],100));
886 return QBrush(gradient
);
889 void ListViewContainer::addViewWidget( QWidget
* view
, int )
891 _stackWidget
->addWidget(view
);
893 ViewProperties
* properties
= viewProperties(view
);
895 QListWidgetItem
* item
= new QListWidgetItem(_listWidget
);
896 item
->setText( properties
->title() );
897 item
->setIcon( properties
->icon() );
899 const int randomIndex
= _listWidget
->count();
900 item
->setData( Qt::BackgroundRole
, randomItemBackground(randomIndex
) );
902 connect( properties
, SIGNAL(titleChanged(ViewProperties
*)) , this , SLOT(updateTitle(ViewProperties
*)));
903 connect( properties
, SIGNAL(iconChanged(ViewProperties
*)) , this , SLOT(updateIcon(ViewProperties
*)));
906 void ListViewContainer::removeViewWidget( QWidget
* view
)
910 int index
= _stackWidget
->indexOf(view
);
911 _stackWidget
->removeWidget(view
);
912 delete _listWidget
->takeItem( index
);
915 void ListViewContainer::setActiveView( QWidget
* view
)
917 _stackWidget
->setCurrentWidget(view
);
918 _listWidget
->setCurrentRow(_stackWidget
->indexOf(view
));
921 void ListViewContainer::rowChanged( int row
)
923 // row may be -1 if the last row has been removed from the model
926 _stackWidget
->setCurrentIndex( row
);
928 emit
activeViewChanged( _stackWidget
->currentWidget() );
932 void ListViewContainer::updateTitle( ViewProperties
* properties
)
934 QList
<QWidget
*> items
= widgetsForItem(properties
);
935 QListIterator
<QWidget
*> itemIter(items
);
937 while ( itemIter
.hasNext() )
939 int index
= _stackWidget
->indexOf( itemIter
.next() );
940 _listWidget
->item( index
)->setText( properties
->title() );
944 void ListViewContainer::updateIcon( ViewProperties
* properties
)
946 QList
<QWidget
*> items
= widgetsForItem(properties
);
947 QListIterator
<QWidget
*> itemIter(items
);
949 while ( itemIter
.hasNext() )
951 int index
= _stackWidget
->indexOf( itemIter
.next() );
952 _listWidget
->item( index
)->setIcon( properties
->icon() );
956 #include "ViewContainer.moc"