Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konsole / src / ViewContainer.cpp
blobef81d17166a7128b15f018c60452fffc8709c70d
1 /*
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
19 02110-1301 USA.
22 // Own
23 #include "ViewContainer.h"
25 // Qt
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>
39 #include <QMimeData>
41 // KDE
42 #include <KColorDialog>
43 #include <kcolorscheme.h>
44 #include <kcolorutils.h>
45 #include <kdebug.h>
46 #include <kconfiggroup.h>
47 #include <KLocale>
48 #include <KMenu>
49 #include <KColorCollection>
50 #include <KTabWidget>
52 // Konsole
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)
62 : QObject(parent)
63 , _navigationDisplayMode(AlwaysShowNavigation)
64 , _navigationPosition(position)
65 , _searchBar(0)
69 ViewContainer::~ViewContainer()
71 foreach( QWidget* view , _views )
73 disconnect(view,SIGNAL(destroyed(QObject*)),this,SLOT(viewDestroyed(QObject*)));
76 if (_searchBar) {
77 _searchBar->deleteLater();
80 emit destroyed(this);
82 void ViewContainer::moveViewWidget( int , int ) {}
83 void ViewContainer::setFeatures(Features features)
84 { _features = features; }
85 ViewContainer::Features ViewContainer::features() const
86 { return _features; }
87 void ViewContainer::moveActiveView( MoveDirection direction )
89 const int currentIndex = _views.indexOf( activeView() ) ;
90 int newIndex = -1;
92 switch ( direction )
94 case MoveViewLeft:
95 newIndex = qMax( currentIndex-1 , 0 );
96 break;
97 case MoveViewRight:
98 newIndex = qMin( currentIndex+1 , _views.count() -1 );
99 break;
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)
139 if (index == -1)
140 _views.append(view);
141 else
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
165 // to be fixed.
166 removeViewWidget(widget);
168 emit viewRemoved(widget);
170 if (_views.count() == 0)
171 emit empty(this);
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)
185 emit empty(this);
189 const QList<QWidget*> ViewContainer::views()
191 return _views;
194 IncrementalSearchBar* ViewContainer::searchBar()
196 if (!_searchBar) {
197 _searchBar = new IncrementalSearchBar( IncrementalSearchBar::AllFeatures , 0);
198 _searchBar->setVisible(false);
199 connect(_searchBar, SIGNAL(destroyed(QObject*)), this, SLOT(searchBarDestroyed()));
201 return _searchBar;
204 void ViewContainer::searchBarDestroyed()
206 _searchBar = 0;
209 void ViewContainer::activateNextView()
211 QWidget* active = activeView();
213 int index = _views.indexOf(active);
215 if ( index == -1 )
216 return;
218 if ( index == _views.count() - 1 )
219 index = 0;
220 else
221 index++;
223 setActiveView( _views.at(index) );
226 void ViewContainer::activatePreviousView()
228 QWidget* active = activeView();
230 int index = _views.indexOf(active);
232 if ( index == -1 )
233 return;
235 if ( index == 0 )
236 index = _views.count() - 1;
237 else
238 index--;
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)
256 : KTabBar(parent)
257 , _container(container)
258 , _dropIndicator(0)
259 , _dropIndicatorIndex(-1)
260 , _drawIndicatorDisabled(false)
263 void ViewContainerTabBar::setDropIndicator(int index, bool drawDisabled)
265 if (!parentWidget() || _dropIndicatorIndex == index)
266 return;
268 _dropIndicatorIndex = index;
269 const int ARROW_SIZE = 22;
270 bool north = shape() == QTabBar::RoundedNorth || shape() == QTabBar::TriangularNorth;
272 if (!_dropIndicator || _drawIndicatorDisabled != drawDisabled)
274 if (!_dropIndicator)
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;
286 if (index < 0)
288 _dropIndicator->hide();
289 return;
292 const QRect rect = tabRect(index < count() ? index : index-1);
294 QPoint pos;
295 if (index < count())
296 pos = rect.topLeft();
297 else
298 pos = rect.topRight();
300 if (north)
301 pos.ry() += ARROW_SIZE;
302 else
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());
327 if (index == -1)
328 index = count();
330 setDropIndicator(index,proposedDropIsSameTab(event));
332 event->acceptProposedAction();
335 int ViewContainerTabBar::dropIndex(const QPoint& pos) const
337 int tab = tabAt(pos);
338 if (tab < 0)
339 return tab;
341 // pick the closest tab boundary
342 QRect rect = tabRect(tab);
343 if ( (pos.x()-rect.left()) > (rect.width()/2) )
344 tab++;
346 if (tab == count())
347 return -1;
349 return tab;
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;
357 if (!sameTabBar)
358 return false;
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)
366 sourceIndex = i;
369 bool sourceAndDropAreLast = sourceIndex == count()-1 && index == -1;
370 if (sourceIndex == index || sourceIndex == index-1 || sourceAndDropAreLast)
371 return true;
372 else
373 return false;
375 void ViewContainerTabBar::dropEvent(QDropEvent* event)
377 setDropIndicator(-1);
379 if ( !event->mimeData()->hasFormat(ViewProperties::mimeType())
380 || proposedDropIsSameTab(event) )
382 event->ignore();
383 return;
386 int index = dropIndex(event->pos());
387 int droppedId = ViewProperties::decodeMimeData(event->mimeData());
388 bool result = false;
389 emit _container->moveViewRequest(index,droppedId,result);
391 if (result)
392 event->accept();
393 else
394 event->ignore();
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
407 // curved corners
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));
415 QPen borderPen;
416 borderPen.setBrush(palette().dark());
417 borderPen.setWidth(borderWidth);
418 painter.setPen(borderPen);
419 painter.drawRect(0,0,rect.width(),rect.height());
420 painter.end();
422 return tabPixmap;
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);
484 else
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));
524 if ( visible )
526 _tabBarSpacer->changeSize(0,TabBarSpace);
528 else
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
540 // in the layout
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
609 // deleted
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
624 drag->setParent(0);
625 removeView(view);
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)
659 if ( delta < 0 )
660 activateNextView();
661 else
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 )
702 if (!_stackWidget)
703 return;
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 )
811 if (!_stackWidget)
812 return;
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 )
840 // instead of
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
861 return _splitter;
864 QWidget* ListViewContainer::activeView() const
866 return _stackWidget->currentWidget();
869 QBrush ListViewContainer::randomItemBackground(int r)
871 int i = r%6;
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 )
908 if (!_stackWidget)
909 return;
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
924 if ( row >= 0 )
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"