• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

ViewContainer.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the Konsole Terminal.
00003     
00004     Copyright 2006-2008 Robert Knight <robertknight@gmail.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301  USA.
00020 */
00021 
00022 // Own
00023 #include "ViewContainer.h"
00024 
00025 // Qt
00026 #include <QtCore/QHash>
00027 #include <QtGui/QLabel>
00028 #include <QtGui/QLineEdit>
00029 #include <QtGui/QBrush>
00030 #include <QtGui/QListWidget>
00031 #include <QtGui/QSplitter>
00032 #include <QtGui/QStackedWidget>
00033 #include <QtGui/QTabBar>
00034 #include <QtGui/QToolButton>
00035 #include <QtGui/QWidgetAction>
00036 
00037 #include <QtGui/QDrag>
00038 #include <QtGui/QDragMoveEvent>
00039 #include <QMimeData>
00040 
00041 // KDE 
00042 #include <KColorDialog>
00043 #include <kcolorscheme.h>
00044 #include <kcolorutils.h>
00045 #include <kdebug.h>
00046 #include <kconfiggroup.h>
00047 #include <KLocale>
00048 #include <KMenu>
00049 #include <KColorCollection>
00050 #include <KTabWidget>
00051 
00052 // Konsole
00053 #include "ViewProperties.h"
00054 
00055 // TODO Perhaps move everything which is Konsole-specific into different files
00056 #include "ProfileListWidget.h"
00057 
00058 using namespace Konsole;
00059 
00060 ViewContainer::ViewContainer(NavigationPosition position , QObject* parent)
00061     : QObject(parent)
00062     , _navigationDisplayMode(AlwaysShowNavigation)
00063     , _navigationPosition(position)
00064 {
00065 }
00066 ViewContainer::~ViewContainer()
00067 {
00068     foreach( QWidget* view , _views ) 
00069     {
00070         disconnect(view,SIGNAL(destroyed(QObject*)),this,SLOT(viewDestroyed(QObject*)));
00071     }
00072 
00073     emit destroyed(this);
00074 }
00075 void ViewContainer::moveViewWidget( int , int ) {}
00076 void ViewContainer::setFeatures(Features features)
00077 { _features = features; }
00078 ViewContainer::Features ViewContainer::features() const
00079 { return _features; }
00080 void ViewContainer::moveActiveView( MoveDirection direction )
00081 {
00082     const int currentIndex = _views.indexOf( activeView() ) ;
00083     int newIndex = -1; 
00084 
00085     switch ( direction )
00086     {
00087         case MoveViewLeft:
00088             newIndex = qMax( currentIndex-1 , 0 );
00089             break;
00090         case MoveViewRight:
00091             newIndex = qMin( currentIndex+1 , _views.count() -1 );
00092             break;
00093     }
00094 
00095     Q_ASSERT( newIndex != -1 );
00096 
00097     moveViewWidget( currentIndex , newIndex );   
00098 
00099     _views.swap(currentIndex,newIndex);
00100 
00101     setActiveView( _views[newIndex] );
00102 }
00103 
00104 void ViewContainer::setNavigationDisplayMode(NavigationDisplayMode mode)
00105 {
00106     _navigationDisplayMode = mode;
00107     navigationDisplayModeChanged(mode);
00108 }
00109 ViewContainer::NavigationPosition ViewContainer::navigationPosition() const
00110 {
00111     return _navigationPosition;
00112 }
00113 void ViewContainer::setNavigationPosition(NavigationPosition position)
00114 {
00115     // assert that this position is supported
00116     Q_ASSERT( supportedNavigationPositions().contains(position) );
00117 
00118     _navigationPosition = position;
00119 
00120     navigationPositionChanged(position);
00121 }
00122 QList<ViewContainer::NavigationPosition> ViewContainer::supportedNavigationPositions() const
00123 {
00124     return QList<NavigationPosition>() << NavigationPositionTop;
00125 }
00126 ViewContainer::NavigationDisplayMode ViewContainer::navigationDisplayMode() const
00127 {
00128     return _navigationDisplayMode;
00129 }
00130 void ViewContainer::addView(QWidget* view , ViewProperties* item, int index)
00131 {
00132     if (index == -1)
00133         _views.append(view);
00134     else
00135         _views.insert(index,view);
00136 
00137     _navigation[view] = item;
00138 
00139     connect( view , SIGNAL(destroyed(QObject*)) , this , SLOT( viewDestroyed(QObject*) ) );
00140 
00141     addViewWidget(view,index);
00142 
00143     emit viewAdded(view,item);
00144 }
00145 void ViewContainer::viewDestroyed(QObject* object)
00146 {
00147     QWidget* widget = static_cast<QWidget*>(object);
00148 
00149     _views.removeAll(widget);
00150     _navigation.remove(widget);
00151 
00152     // FIXME This can result in ViewContainerSubClass::removeViewWidget() being 
00153     // called after the the widget's parent has been deleted or partially deleted
00154     // in the ViewContainerSubClass instance's destructor.
00155     //
00156     // Currently deleteLater() is used to remove child widgets in the subclass 
00157     // constructors to get around the problem, but this is a hack and needs
00158     // to be fixed. 
00159     removeViewWidget(widget);
00160     
00161     emit viewRemoved(widget);
00162 
00163     if (_views.count() == 0)
00164         emit empty(this);
00165 }
00166 void ViewContainer::removeView(QWidget* view)
00167 {
00168     _views.removeAll(view);
00169     _navigation.remove(view);
00170 
00171     disconnect( view , SIGNAL(destroyed(QObject*)) , this , SLOT( viewDestroyed(QObject*) ) );
00172 
00173     removeViewWidget(view);
00174     
00175     emit viewRemoved(view);
00176 
00177     if (_views.count() == 0)
00178         emit empty(this);
00179 
00180 }
00181 
00182 const QList<QWidget*> ViewContainer::views()
00183 {
00184     return _views;
00185 }
00186 
00187 void ViewContainer::activateNextView()
00188 {
00189     QWidget* active = activeView();
00190 
00191     int index = _views.indexOf(active);
00192 
00193     if ( index == -1 )
00194         return;
00195 
00196     if ( index == _views.count() - 1 )
00197         index = 0;
00198     else
00199         index++;
00200 
00201     setActiveView( _views.at(index) );
00202 }
00203 
00204 void ViewContainer::activatePreviousView()
00205 {
00206     QWidget* active = activeView();
00207 
00208     int index = _views.indexOf(active);
00209 
00210     if ( index == -1 ) 
00211         return;
00212 
00213     if ( index == 0 )
00214         index = _views.count() - 1;
00215     else
00216         index--;
00217 
00218     setActiveView( _views.at(index) );
00219 }
00220 
00221 ViewProperties* ViewContainer::viewProperties( QWidget* widget )
00222 {
00223     Q_ASSERT( _navigation.contains(widget) );
00224 
00225     return _navigation[widget];    
00226 }
00227 
00228 QList<QWidget*> ViewContainer::widgetsForItem(ViewProperties* item) const
00229 {
00230     return _navigation.keys(item);
00231 }
00232 
00233 TabbedViewContainer::TabbedViewContainer(NavigationPosition position , QObject* parent) :
00234     ViewContainer(position,parent)
00235    ,_newSessionButton(0) 
00236    ,_tabContextMenu(0) 
00237    ,_tabSelectColorMenu(0)
00238    ,_tabColorSelector(0)
00239    ,_tabColorCells(0)
00240    ,_contextMenuTab(0) 
00241 {
00242     _tabWidget = new KTabWidget();
00243     _tabContextMenu = new KMenu(_tabWidget);   
00244 
00245     _newSessionButton = new QToolButton(_tabWidget);
00246     _newSessionButton->setAutoRaise(true);
00247     _newSessionButton->setIcon( KIcon("tab-new") );
00248     _newSessionButton->setText( i18n("New") );
00249     _newSessionButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00250     _newSessionButton->setPopupMode(QToolButton::MenuButtonPopup);
00251 
00252     QToolButton* closeButton = new QToolButton(_tabWidget);
00253     closeButton->setIcon( KIcon("tab-close") );
00254     closeButton->setAutoRaise(true);
00255     connect( closeButton , SIGNAL(clicked()) , this , SLOT(closeTabClicked()) );
00256 
00257     _tabWidget->setCornerWidget(_newSessionButton,Qt::TopLeftCorner);
00258     _tabWidget->setCornerWidget(closeButton,Qt::TopRightCorner);
00259 
00260      //Create a colour selection palette and fill it with a range of suitable colours
00261      QString paletteName;
00262      QStringList availablePalettes = KColorCollection::installedCollections();
00263 
00264      if (availablePalettes.contains("40.colors"))
00265         paletteName = "40.colors";
00266 
00267     KColorCollection palette(paletteName);
00268 
00269     //If the palette of colours was found, create a palette menu displaying those colors
00270     //which the user chooses from when they activate the "Select Tab Color" sub-menu.
00271     //
00272     //If the palette is empty, default back to the old behaviour where the user is shown
00273     //a color dialog when they click the "Select Tab Color" menu item.
00274     if ( palette.count() > 0 )
00275     {
00276         _tabColorCells = new KColorCells(_tabWidget,palette.count()/8,8);
00277 
00278         for (int i=0;i<palette.count();i++)
00279             _tabColorCells->setColor(i,palette.color(i));
00280 
00281 
00282         _tabSelectColorMenu = new KMenu(_tabWidget);
00283         connect( _tabSelectColorMenu, SIGNAL(aboutToShow()) , this, SLOT(prepareColorCells()) );
00284         _tabColorSelector = new QWidgetAction(_tabSelectColorMenu);
00285         _tabColorSelector->setDefaultWidget(_tabColorCells);
00286 
00287         _tabSelectColorMenu->addAction( _tabColorSelector );
00288 
00289         connect(_tabColorCells,SIGNAL(colorSelected(int)),this,SLOT(selectTabColor()));
00290         connect(_tabColorCells,SIGNAL(colorSelected(int)),_tabContextMenu,SLOT(hide()));
00291         
00292         QAction* action = _tabSelectColorMenu->menuAction(); 
00293             //_tabPopupMenu->addMenu(_tabSelectColorMenu);
00294         action->setIcon( KIcon("colors") );
00295         action->setText( i18n("Select &Tab Color") );
00296 
00297         _viewActions << action;
00298     }
00299     else
00300     {
00301       //  _viewActions << new KAction( KIcon("colors"),i18n("Select &Tab Color..."),this,
00302       //                  SLOT(slotTabSelectColor()));
00303     }
00304 
00305 
00306    connect( _tabWidget , SIGNAL(currentChanged(int)) , this , SLOT(currentTabChanged(int)) );
00307    connect( _tabWidget , SIGNAL(contextMenu(QWidget*,const QPoint&)),
00308                          SLOT(showContextMenu(QWidget*,const QPoint&))); 
00309 }
00310 
00311 
00312 
00313 void TabbedViewContainer::currentTabChanged(int tab)
00314 {
00315     if ( tab >= 0 )
00316     {
00317         emit activeViewChanged( _tabWidget->widget(tab) );
00318     }
00319 }
00320 
00321 void TabbedViewContainer::closeTabClicked()
00322 {
00323     emit closeRequest(_tabWidget->currentWidget());
00324 }
00325 
00326 TabbedViewContainer::~TabbedViewContainer()
00327 {
00328     _tabContextMenu->deleteLater();
00329     _tabWidget->deleteLater();
00330 }
00331 
00332 void TabbedViewContainer::setNewSessionMenu(QMenu* menu)
00333 {
00334     _newSessionButton->setMenu(menu);
00335 }
00336 void TabbedViewContainer::showContextMenu(QWidget* widget , const QPoint& position)
00337 {
00338     //TODO - Use the tab under the mouse, not just the active tab
00339     _contextMenuTab = _tabWidget->indexOf(widget);
00340     //NavigationItem* item = navigationItem( widget );
00341    
00342     _tabContextMenu->clear();
00343 //    _tabContextMenu->addActions( item->contextMenuActions(_viewActions) );
00344     _tabContextMenu->popup( position );
00345 }
00346 
00347 void TabbedViewContainer::prepareColorCells()
00348 {
00349  //set selected color in palette widget to color of active tab
00350 
00351     QColor activeTabColor = _tabWidget->tabTextColor( _contextMenuTab );
00352 
00353     for (int i=0;i<_tabColorCells->count();i++)
00354         if ( activeTabColor == _tabColorCells->color(i) )
00355         {
00356             _tabColorCells->setSelected(i);
00357             break;
00358         } 
00359 }
00360 
00361 void TabbedViewContainer::addViewWidget( QWidget* view , int )
00362 {
00363     ViewProperties* item = viewProperties(view);
00364     connect( item , SIGNAL(titleChanged(ViewProperties*)) , this , SLOT(updateTitle(ViewProperties*))); 
00365     connect( item , SIGNAL(iconChanged(ViewProperties*) ) , this ,SLOT(updateIcon(ViewProperties*)));          
00366     _tabWidget->addTab( view , item->icon() , item->title() );
00367 }
00368 void TabbedViewContainer::removeViewWidget( QWidget* view )
00369 {
00370     const int index = _tabWidget->indexOf(view);
00371 
00372     if ( index != -1 )
00373         _tabWidget->removeTab( index );
00374 }
00375 
00376 void TabbedViewContainer::updateIcon(ViewProperties* item)
00377 {
00378     QList<QWidget*> items = widgetsForItem(item);
00379     QListIterator<QWidget*> itemIter(items);
00380     
00381     while ( itemIter.hasNext() )
00382     {
00383         int index = _tabWidget->indexOf( itemIter.next() );
00384         _tabWidget->setTabIcon( index , item->icon() );
00385     }
00386 }
00387 void TabbedViewContainer::updateTitle(ViewProperties* item) 
00388 {
00389     QList<QWidget*> items = widgetsForItem(item);
00390     QListIterator<QWidget*> itemIter(items);
00391 
00392     while ( itemIter.hasNext() )
00393     {
00394         int index = _tabWidget->indexOf( itemIter.next() );
00395         _tabWidget->setTabText( index , item->title() );
00396     }
00397 
00398 }
00399 
00400 QWidget* TabbedViewContainer::containerWidget() const
00401 {
00402     return _tabWidget;
00403 }
00404 
00405 QWidget* TabbedViewContainer::activeView() const
00406 {
00407     return _tabWidget->widget(_tabWidget->currentIndex());
00408 }
00409 
00410 void TabbedViewContainer::setActiveView(QWidget* view)
00411 {
00412     _tabWidget->setCurrentWidget(view);
00413 }
00414 
00415 void TabbedViewContainer::selectTabColor()
00416 {
00417   QColor color;
00418   
00419   //If the color palette is available apply the current selected color to the tab, otherwise
00420   //default back to showing KDE's color dialog instead.
00421   if ( _tabColorCells )
00422   {
00423     color = _tabColorCells->color(_tabColorCells->selectedIndex());
00424 
00425     if (!color.isValid())
00426             return;
00427   }
00428   else
00429   {
00430     QColor defaultColor = _tabWidget->palette().color( QPalette::Foreground );
00431     QColor tempColor = _tabWidget->tabTextColor( _contextMenuTab );
00432 
00433     if ( KColorDialog::getColor(tempColor,defaultColor,_tabWidget) == KColorDialog::Accepted )
00434         color = tempColor;
00435     else
00436         return;
00437   }
00438 
00439   _tabWidget->setTabTextColor( _contextMenuTab , color );
00440 }
00441 
00442 ViewContainerTabBar::ViewContainerTabBar(QWidget* parent,TabbedViewContainerV2* container)
00443     : KTabBar(parent)
00444     , _container(container)
00445     , _dropIndicator(0)
00446     , _dropIndicatorIndex(-1)
00447     , _drawIndicatorDisabled(false)
00448 {
00449 }
00450 void ViewContainerTabBar::setDropIndicator(int index, bool drawDisabled)
00451 {
00452     if (!parentWidget() || _dropIndicatorIndex == index)
00453         return;
00454 
00455     _dropIndicatorIndex = index;
00456     const int ARROW_SIZE = 22;
00457     bool north = shape() == QTabBar::RoundedNorth || shape() == QTabBar::TriangularNorth;
00458 
00459     if (!_dropIndicator || _drawIndicatorDisabled != drawDisabled)
00460     {
00461         if (!_dropIndicator)
00462         {
00463             _dropIndicator = new QLabel(parentWidget());
00464             _dropIndicator->resize(ARROW_SIZE,ARROW_SIZE);
00465         }
00466 
00467         QIcon::Mode drawMode = drawDisabled ? QIcon::Disabled : QIcon::Normal;
00468         const QString iconName = north ? "arrow-up" : "arrow-down";
00469         _dropIndicator->setPixmap(KIcon(iconName).pixmap(ARROW_SIZE,ARROW_SIZE,drawMode));
00470         _drawIndicatorDisabled = drawDisabled;
00471     }
00472 
00473     if (index < 0)
00474     {
00475         _dropIndicator->hide();
00476         return;
00477     }
00478 
00479     const QRect rect = tabRect(index < count() ? index : index-1);
00480 
00481     QPoint pos;
00482     if (index < count())
00483         pos = rect.topLeft();
00484     else
00485         pos = rect.topRight();
00486 
00487     if (north)
00488         pos.ry() += ARROW_SIZE;
00489     else
00490         pos.ry() -= ARROW_SIZE; 
00491 
00492     pos.rx() -= ARROW_SIZE/2; 
00493 
00494     _dropIndicator->move(mapTo(parentWidget(),pos));
00495     _dropIndicator->show();
00496 
00497 }
00498 void ViewContainerTabBar::dragLeaveEvent(QDragLeaveEvent*)
00499 {
00500     setDropIndicator(-1);
00501 }
00502 void ViewContainerTabBar::dragEnterEvent(QDragEnterEvent* event)
00503 {
00504     if (event->mimeData()->hasFormat(ViewProperties::mimeType()) &&
00505         event->source() != 0)
00506         event->acceptProposedAction();  
00507 }
00508 void ViewContainerTabBar::dragMoveEvent(QDragMoveEvent* event)
00509 {
00510     if (event->mimeData()->hasFormat(ViewProperties::mimeType())
00511         && event->source() != 0)
00512     {
00513         int index = dropIndex(event->pos());
00514         if (index == -1)
00515             index = count();
00516 
00517         setDropIndicator(index,proposedDropIsSameTab(event));
00518 
00519         event->acceptProposedAction();
00520     }
00521 }
00522 int ViewContainerTabBar::dropIndex(const QPoint& pos) const
00523 {
00524     int tab = tabAt(pos);
00525     if (tab < 0)
00526         return tab;
00527 
00528     // pick the closest tab boundary 
00529     QRect rect = tabRect(tab);
00530     if ( (pos.x()-rect.left()) > (rect.width()/2) )
00531         tab++;
00532 
00533     if (tab == count())
00534         return -1;
00535 
00536     return tab;
00537 }
00538 bool ViewContainerTabBar::proposedDropIsSameTab(const QDropEvent* event) const
00539 {
00540     int index = dropIndex(event->pos());
00541     int droppedId = ViewProperties::decodeMimeData(event->mimeData());
00542     bool sameTabBar = event->source() == this;
00543 
00544     if (!sameTabBar)
00545         return false;
00546 
00547     const QList<QWidget*> viewList = _container->views();
00548     int sourceIndex = -1;
00549     for (int i=0;i<count();i++)
00550     {
00551         int idAtIndex = _container->viewProperties(viewList[i])->identifier();
00552         if (idAtIndex == droppedId)
00553             sourceIndex = i;
00554     }
00555 
00556     bool sourceAndDropAreLast = sourceIndex == count()-1 && index == -1;
00557     if (sourceIndex == index || sourceIndex == index-1 || sourceAndDropAreLast)
00558         return true;
00559     else
00560         return false;
00561 }
00562 void ViewContainerTabBar::dropEvent(QDropEvent* event)
00563 {
00564     setDropIndicator(-1);
00565 
00566     if (    !event->mimeData()->hasFormat(ViewProperties::mimeType())
00567         ||  proposedDropIsSameTab(event) )
00568     {
00569         event->ignore();
00570         return;
00571     }
00572 
00573     int index = dropIndex(event->pos());
00574     int droppedId = ViewProperties::decodeMimeData(event->mimeData());
00575     bool result = false;
00576     emit _container->moveViewRequest(index,droppedId,result);
00577     
00578     if (result)
00579         event->accept();
00580     else
00581         event->ignore();
00582 }
00583 
00584 QSize ViewContainerTabBar::tabSizeHint(int index) const
00585 {
00586      return QTabBar::tabSizeHint(index);
00587 }
00588 QPixmap ViewContainerTabBar::dragDropPixmap(int tab) 
00589 {
00590     Q_ASSERT(tab >= 0 && tab < count());
00591 
00592     // TODO - grabWidget() works except that it includes part
00593     // of the tab bar outside the tab itself if the tab has 
00594     // curved corners
00595     const QRect rect = tabRect(tab);
00596     const int borderWidth = 1;
00597 
00598     QPixmap tabPixmap(rect.width()+borderWidth,
00599                       rect.height()+borderWidth);
00600     QPainter painter(&tabPixmap);
00601     painter.drawPixmap(0,0,QPixmap::grabWidget(this,rect));
00602     QPen borderPen;
00603     borderPen.setBrush(palette().dark());
00604     borderPen.setWidth(borderWidth);
00605     painter.setPen(borderPen);
00606     painter.drawRect(0,0,rect.width(),rect.height());
00607     painter.end();
00608 
00609     return tabPixmap;
00610 }
00611 TabbedViewContainerV2::TabbedViewContainerV2(NavigationPosition position , QObject* parent) 
00612 : ViewContainer(position,parent)
00613 {
00614     _containerWidget = new QWidget;
00615     _stackWidget = new QStackedWidget();
00616     _tabBar = new ViewContainerTabBar(_containerWidget,this);
00617     _tabBar->setDrawBase(true);
00618 
00619     const int cornerButtonWidth = 50;
00620     _newTabButton = new KPushButton(KIcon("tab-new"),QString(),_containerWidget);
00621     // The button width here is hard coded, it would be better to use the value from
00622     // the current style (see QTabWidget::setUpLayout())
00623     _newTabButton->setFixedWidth(cornerButtonWidth);
00624     _newTabButton->setFlat(true);
00625     // new tab button is initially hidden, it will be shown when setFeatures() is called
00626     // with the QuickNewView flag enabled
00627     _newTabButton->setHidden(true);
00628    
00629     _closeTabButton = new KPushButton(KIcon("tab-close"),QString(),_containerWidget);
00630     _closeTabButton->setFixedWidth(cornerButtonWidth);
00631     _closeTabButton->setFlat(true);
00632     _closeTabButton->setHidden(true);
00633 
00634     connect( _tabBar , SIGNAL(currentChanged(int)) , this , SLOT(currentTabChanged(int)) );
00635     connect( _tabBar , SIGNAL(tabDoubleClicked(int)) , this , SLOT(tabDoubleClicked(int)) );
00636     connect( _tabBar , SIGNAL(newTabRequest()) , this , SIGNAL(newViewRequest()) );
00637     connect( _tabBar , SIGNAL(wheelDelta(int)) , this , SLOT(wheelScrolled(int)) );
00638     connect( _tabBar , SIGNAL(mouseMiddleClick(int)) , this , SLOT(closeTab(int)) );
00639     connect( _tabBar , SIGNAL(closeRequest(int)) , this , SLOT(closeTab(int)) );
00640     connect( _tabBar , SIGNAL(initiateDrag(int)) , this , SLOT(startTabDrag(int)) );
00641 
00642     connect( _newTabButton , SIGNAL(clicked()) , this , SIGNAL(newViewRequest()) );
00643     connect( _closeTabButton , SIGNAL(clicked()) , this , SLOT(closeCurrentTab()) );
00644 
00645     _layout = new TabbedViewContainerV2Layout;
00646     _layout->setSpacing(0);
00647     _layout->setMargin(0);
00648     _tabBarLayout = new QHBoxLayout;
00649     _tabBarLayout->setSpacing(0);
00650     _tabBarLayout->setMargin(0);
00651     _tabBarLayout->addWidget(_newTabButton);
00652     _tabBarLayout->addWidget(_tabBar);
00653     _tabBarLayout->addWidget(_closeTabButton); 
00654     _tabBarSpacer = new QSpacerItem(0,TabBarSpace);
00655 
00656     _layout->addWidget(_stackWidget);
00657     
00658     if ( position == NavigationPositionTop )
00659     {
00660         _layout->insertLayout(0,_tabBarLayout);
00661         _layout->insertItemAt(0,_tabBarSpacer);
00662         _tabBar->setShape(QTabBar::RoundedNorth);
00663     }
00664     else if ( position == NavigationPositionBottom )
00665     {
00666         _layout->insertLayout(-1,_tabBarLayout);
00667         _layout->insertItemAt(-1,_tabBarSpacer);
00668         _tabBar->setShape(QTabBar::RoundedSouth);
00669     }
00670     else
00671         Q_ASSERT(false); // position not supported
00672 
00673     _containerWidget->setLayout(_layout);
00674 }
00675 void TabbedViewContainerV2::setNewViewMenu(QMenu* menu)
00676 { _newTabButton->setDelayedMenu(menu); }
00677 ViewContainer::Features TabbedViewContainerV2::supportedFeatures() const
00678 { return QuickNewView|QuickCloseView; }
00679 void TabbedViewContainerV2::setFeatures(Features features)
00680 {
00681     ViewContainer::setFeatures(features);
00682 
00683     const bool tabBarHidden = _tabBar->isHidden();
00684     _newTabButton->setVisible(!tabBarHidden && (features & QuickNewView));
00685     _closeTabButton->setVisible(!tabBarHidden && (features & QuickCloseView));
00686 }
00687 void TabbedViewContainerV2::closeCurrentTab()
00688 {
00689     if (_stackWidget->currentIndex() != -1)
00690     {
00691         closeTab(_stackWidget->currentIndex());
00692     }
00693 }
00694 void TabbedViewContainerV2::closeTab(int tab)
00695 {
00696     Q_ASSERT(tab >= 0 && tab < _stackWidget->count());
00697     
00698     if (viewProperties(_stackWidget->widget(tab))->confirmClose())
00699         removeView(_stackWidget->widget(tab));
00700 }
00701 void TabbedViewContainerV2::setTabBarVisible(bool visible)
00702 {
00703     _tabBar->setVisible(visible);
00704     _newTabButton->setVisible(visible && (features() & QuickNewView));
00705     _closeTabButton->setVisible(visible && (features() & QuickCloseView));
00706     if ( visible )
00707     {
00708         _tabBarSpacer->changeSize(0,TabBarSpace);
00709     }
00710     else
00711     {
00712         _tabBarSpacer->changeSize(0,0);
00713     } 
00714 }
00715 QList<ViewContainer::NavigationPosition> TabbedViewContainerV2::supportedNavigationPositions() const
00716 {
00717     return QList<NavigationPosition>() << NavigationPositionTop << NavigationPositionBottom;
00718 }
00719 void TabbedViewContainerV2::navigationPositionChanged(NavigationPosition position)
00720 {
00721     // this method assumes that there are only three items 
00722     // in the layout
00723     Q_ASSERT( _layout->count() == 3 );
00724 
00725     // index of stack widget in the layout when tab bar is at the bottom
00726     const int StackIndexWithTabBottom = 0;
00727 
00728     if ( position == NavigationPositionTop 
00729             && _layout->indexOf(_stackWidget) == StackIndexWithTabBottom )
00730     {
00731         _layout->removeItem(_tabBarLayout);
00732         _layout->removeItem(_tabBarSpacer);
00733 
00734         _layout->insertLayout(0,_tabBarLayout);
00735         _layout->insertItemAt(0,_tabBarSpacer);
00736         _tabBar->setShape(QTabBar::RoundedNorth);
00737     }
00738     else if ( position == NavigationPositionBottom 
00739             && _layout->indexOf(_stackWidget) != StackIndexWithTabBottom )
00740     {
00741         _layout->removeItem(_tabBarLayout);
00742         _layout->removeItem(_tabBarSpacer);
00743 
00744         _layout->insertLayout(-1,_tabBarLayout);
00745         _layout->insertItemAt(-1,_tabBarSpacer);
00746         _tabBar->setShape(QTabBar::RoundedSouth);
00747     }
00748 }
00749 void TabbedViewContainerV2::navigationDisplayModeChanged(NavigationDisplayMode mode)
00750 {
00751     if ( mode == AlwaysShowNavigation && _tabBar->isHidden() )
00752         setTabBarVisible(true);
00753 
00754     if ( mode == AlwaysHideNavigation && !_tabBar->isHidden() )
00755         setTabBarVisible(false);
00756 
00757     if ( mode == ShowNavigationAsNeeded )
00758         dynamicTabBarVisibility();
00759 }
00760 void TabbedViewContainerV2::dynamicTabBarVisibility()
00761 {
00762     if ( _tabBar->count() > 1 && _tabBar->isHidden() )
00763         setTabBarVisible(true);
00764 
00765     if ( _tabBar->count() < 2 && !_tabBar->isHidden() )
00766         setTabBarVisible(false);    
00767 }
00768 TabbedViewContainerV2::~TabbedViewContainerV2()
00769 {
00770     _containerWidget->deleteLater();
00771 }
00772 
00773 void TabbedViewContainerV2::startTabDrag(int tab)
00774 {
00775     QDrag* drag = new QDrag(_tabBar);
00776     const QRect tabRect = _tabBar->tabRect(tab);
00777     QPixmap tabPixmap = _tabBar->dragDropPixmap(tab); 
00778 
00779     drag->setPixmap(tabPixmap);
00780     
00781     int id = viewProperties(views()[tab])->identifier();
00782     QWidget* view = views()[tab];
00783     drag->setMimeData(ViewProperties::createMimeData(id));
00784 
00785     // start drag, if drag-and-drop is successful the view at 'tab' will be
00786     // deleted
00787     //
00788     // if the tab was dragged onto another application
00789     // which blindly accepted the drop then ignore it
00790     if (drag->exec() == Qt::MoveAction && drag->target() != 0)
00791     {
00792         // Deleting the view may cause the view container to be deleted, which
00793         // will also delete the QDrag object.
00794         // This can cause a crash if Qt's internal drag-and-drop handling
00795         // tries to delete it later.  
00796         //
00797         // For now set the QDrag's parent to 0 so that it won't be deleted if 
00798         // this view container is destroyed.
00799         //
00800         // FIXME: Resolve this properly
00801         drag->setParent(0);
00802         removeView(view);
00803     }
00804 }
00805 void TabbedViewContainerV2::tabDoubleClicked(int tab)
00806 {
00807     viewProperties( views()[tab] )->rename();
00808 }
00809 void TabbedViewContainerV2::moveViewWidget( int fromIndex , int toIndex )
00810 {
00811     QString text = _tabBar->tabText(fromIndex);
00812     QIcon icon = _tabBar->tabIcon(fromIndex);
00813    
00814     // FIXME - This will lose properties of the tab other than
00815     // their text and icon when moving them
00816     
00817     _tabBar->removeTab(fromIndex);
00818     _tabBar->insertTab(toIndex,icon,text);
00819 
00820     QWidget* widget = _stackWidget->widget(fromIndex);
00821     _stackWidget->removeWidget(widget);
00822     _stackWidget->insertWidget(toIndex,widget);
00823 }
00824 void TabbedViewContainerV2::currentTabChanged(int index)
00825 {
00826     _stackWidget->setCurrentIndex(index);
00827     if (_stackWidget->widget(index))
00828         emit activeViewChanged(_stackWidget->widget(index));
00829 
00830     // clear activity indicators
00831     setTabActivity(index,false);
00832 }
00833 
00834 void TabbedViewContainerV2::wheelScrolled(int delta)
00835 {
00836     if ( delta < 0 )
00837     activateNextView();
00838     else
00839     activatePreviousView();
00840 }
00841 
00842 QWidget* TabbedViewContainerV2::containerWidget() const
00843 {
00844     return _containerWidget;
00845 }
00846 QWidget* TabbedViewContainerV2::activeView() const
00847 {
00848     return _stackWidget->currentWidget();
00849 }
00850 void TabbedViewContainerV2::setActiveView(QWidget* view)
00851 {
00852     const int index = _stackWidget->indexOf(view);
00853 
00854     Q_ASSERT( index != -1 );
00855 
00856    _stackWidget->setCurrentWidget(view);
00857    _tabBar->setCurrentIndex(index); 
00858 }
00859 void TabbedViewContainerV2::addViewWidget( QWidget* view , int index)
00860 {
00861     _stackWidget->insertWidget(index,view);
00862     _stackWidget->updateGeometry();
00863 
00864     ViewProperties* item = viewProperties(view);
00865     connect( item , SIGNAL(titleChanged(ViewProperties*)) , this , 
00866                     SLOT(updateTitle(ViewProperties*))); 
00867     connect( item , SIGNAL(iconChanged(ViewProperties*) ) , this , 
00868                     SLOT(updateIcon(ViewProperties*)));
00869     connect( item , SIGNAL(activity(ViewProperties*)) , this ,
00870                     SLOT(updateActivity(ViewProperties*)));
00871 
00872     _tabBar->insertTab( index , item->icon() , item->title() );
00873 
00874     if ( navigationDisplayMode() == ShowNavigationAsNeeded )
00875         dynamicTabBarVisibility();
00876 }
00877 void TabbedViewContainerV2::removeViewWidget( QWidget* view )
00878 {
00879     const int index = _stackWidget->indexOf(view);
00880 
00881     Q_ASSERT( index != -1 );
00882 
00883     _stackWidget->removeWidget(view);
00884     _tabBar->removeTab(index);
00885 
00886     if ( navigationDisplayMode() == ShowNavigationAsNeeded )
00887         dynamicTabBarVisibility();
00888 }
00889 
00890 void TabbedViewContainerV2::setTabActivity(int index , bool activity)
00891 {
00892     const QPalette& palette = _tabBar->palette();
00893     KColorScheme colorScheme(palette.currentColorGroup());
00894     const QColor colorSchemeActive = colorScheme.foreground(KColorScheme::ActiveText).color();    
00895     
00896     const QColor normalColor = palette.text().color();
00897     const QColor activityColor = KColorUtils::mix(normalColor,colorSchemeActive); 
00898     
00899     QColor color = activity ? activityColor : QColor();
00900 
00901     if ( color != _tabBar->tabTextColor(index) )
00902         _tabBar->setTabTextColor(index,color);
00903 }
00904 
00905 void TabbedViewContainerV2::updateActivity(ViewProperties* item)
00906 {
00907     QListIterator<QWidget*> iter(widgetsForItem(item));
00908     while ( iter.hasNext() )
00909     {
00910         const int index = _stackWidget->indexOf(iter.next());
00911 
00912         if ( index != _stackWidget->currentIndex() )
00913         {
00914             setTabActivity(index,true);
00915         } 
00916     }
00917 }
00918 
00919 void TabbedViewContainerV2::updateTitle(ViewProperties* item)
00920 {
00921     // prevent tab titles from becoming overly-long as this limits the number
00922     // of tabs which can fit in the tab bar.  
00923     //
00924     // if the view's title is overly long then trim it and select the 
00925     // right-most 20 characters (assuming they contain the most useful
00926     // information) and insert an elide at the front
00927     const int MAX_TAB_TEXT_LENGTH = 20;
00928 
00929     QListIterator<QWidget*> iter(widgetsForItem(item));
00930     while ( iter.hasNext() )
00931     {
00932         const int index = _stackWidget->indexOf( iter.next() );
00933 
00934         QString tabText = item->title();
00935         if (tabText.count() > MAX_TAB_TEXT_LENGTH)
00936             tabText = tabText.right(MAX_TAB_TEXT_LENGTH).prepend("...");
00937 
00938         _tabBar->setTabText( index , tabText );
00939     }
00940 }
00941 void TabbedViewContainerV2::updateIcon(ViewProperties* item)
00942 {
00943     QListIterator<QWidget*> iter(widgetsForItem(item));
00944     while ( iter.hasNext() )
00945     {
00946         const int index = _stackWidget->indexOf( iter.next() );
00947         _tabBar->setTabIcon( index , item->icon() );
00948     }
00949 }
00950 
00951 StackedViewContainer::StackedViewContainer(QObject* parent) 
00952 : ViewContainer(NavigationPositionTop,parent)
00953 {
00954     _stackWidget = new QStackedWidget;
00955 }
00956 StackedViewContainer::~StackedViewContainer()
00957 {
00958     _stackWidget->deleteLater();
00959 }
00960 QWidget* StackedViewContainer::containerWidget() const
00961 {
00962     return _stackWidget;
00963 }
00964 QWidget* StackedViewContainer::activeView() const
00965 {
00966     return _stackWidget->currentWidget();
00967 }
00968 void StackedViewContainer::setActiveView(QWidget* view)
00969 {
00970    _stackWidget->setCurrentWidget(view); 
00971 }
00972 void StackedViewContainer::addViewWidget( QWidget* view , int )
00973 {
00974     _stackWidget->addWidget(view);
00975 }
00976 void StackedViewContainer::removeViewWidget( QWidget* view )
00977 {
00978     const int index = _stackWidget->indexOf(view);
00979 
00980     Q_ASSERT( index != -1);
00981 
00982     _stackWidget->removeWidget(view);
00983 }
00984 
00985 ListViewContainer::ListViewContainer(NavigationPosition position,QObject* parent)
00986     : ViewContainer(position,parent)
00987 {
00988     _splitter = new QSplitter;
00989     _stackWidget = new QStackedWidget(_splitter);
00990     _listWidget = new ProfileListWidget(_splitter);
00991 
00992     // elide left is used because the most informative part of the session name is often
00993     // the rightmost part
00994     //
00995     // this means you get entries looking like:
00996     //
00997     // ...dirA ...dirB ...dirC  ( helpful )
00998     //
00999     // instead of
01000     //
01001     // johnSmith@comput... johnSmith@comput...  ( not so helpful )
01002     //
01003 
01004     _listWidget->setTextElideMode( Qt::ElideLeft );
01005     _listWidget->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
01006     _listWidget->setDragDropMode(QAbstractItemView::DragDrop);
01007     _splitter->addWidget(_listWidget);
01008     _splitter->addWidget(_stackWidget);
01009         
01010     connect( _listWidget , SIGNAL(currentRowChanged(int)) , this , SLOT(rowChanged(int)) ); 
01011 }
01012 
01013 ListViewContainer::~ListViewContainer()
01014 {
01015     _splitter->deleteLater();
01016 }
01017 
01018 QWidget* ListViewContainer::containerWidget() const
01019 {
01020     return _splitter;
01021 }
01022 
01023 QWidget* ListViewContainer::activeView() const
01024 {
01025     return _stackWidget->currentWidget();
01026 }
01027 
01028 QBrush ListViewContainer::randomItemBackground(int r)
01029 {
01030     int i = r%6;
01031 
01032     //and now for something truly unpleasant:
01033     static const int r1[] = {255,190,190,255,190,255};
01034     static const int r2[] = {255,180,180,255,180,255};
01035     static const int b1[] = {190,255,190,255,255,190};
01036     static const int b2[] = {180,255,180,255,255,180};
01037     static const int g1[] = {190,190,255,190,255,255};
01038     static const int g2[] = {180,180,255,180,255,255};
01039 
01040     // hardcoded assumes item height is 32px
01041     QLinearGradient gradient( QPoint(0,0) , QPoint(0,32) );
01042     gradient.setColorAt(0,QColor(r1[i],g1[i],b1[i],100));
01043     gradient.setColorAt(0.5,QColor(r2[i],g2[i],b2[i],100));
01044     gradient.setColorAt(1,QColor(r1[i],g1[i],b1[i],100));
01045     return QBrush(gradient);
01046 }
01047 
01048 void ListViewContainer::addViewWidget( QWidget* view , int )
01049 {
01050     _stackWidget->addWidget(view);
01051 
01052     ViewProperties* properties = viewProperties(view);
01053 
01054     QListWidgetItem* item = new QListWidgetItem(_listWidget);
01055     item->setText( properties->title() );
01056     item->setIcon( properties->icon() );
01057 
01058     const int randomIndex = _listWidget->count();
01059     item->setData( Qt::BackgroundRole , randomItemBackground(randomIndex) );
01060    
01061     connect( properties , SIGNAL(titleChanged(ViewProperties*)) , this , SLOT(updateTitle(ViewProperties*)));
01062     connect( properties , SIGNAL(iconChanged(ViewProperties*)) , this , SLOT(updateIcon(ViewProperties*)));
01063 }
01064 
01065 void ListViewContainer::removeViewWidget( QWidget* view )
01066 {
01067     int index = _stackWidget->indexOf(view);
01068     _stackWidget->removeWidget(view);
01069     delete _listWidget->takeItem( index );
01070 }
01071 
01072 void ListViewContainer::setActiveView( QWidget* view )
01073 {
01074     _stackWidget->setCurrentWidget(view);
01075     _listWidget->setCurrentRow(_stackWidget->indexOf(view));
01076 }
01077 
01078 void ListViewContainer::rowChanged( int row )
01079 {
01080     // row may be -1 if the last row has been removed from the model
01081     if ( row >= 0 )
01082     {
01083         _stackWidget->setCurrentIndex( row );
01084 
01085         emit activeViewChanged( _stackWidget->currentWidget() );
01086     }
01087 }
01088 
01089 void ListViewContainer::updateTitle( ViewProperties* properties )
01090 {
01091     QList<QWidget*> items = widgetsForItem(properties);
01092     QListIterator<QWidget*> itemIter(items);
01093 
01094     while ( itemIter.hasNext() )
01095     {
01096         int index = _stackWidget->indexOf( itemIter.next() );
01097         _listWidget->item( index )->setText( properties->title() );
01098     }
01099 }
01100 
01101 void ListViewContainer::updateIcon( ViewProperties* properties )
01102 {
01103     QList<QWidget*> items = widgetsForItem(properties);
01104     QListIterator<QWidget*> itemIter(items);
01105 
01106     while ( itemIter.hasNext() )
01107     {
01108         int index = _stackWidget->indexOf( itemIter.next() );
01109         _listWidget->item( index )->setIcon( properties->icon() );
01110     }
01111 }
01112 
01113 #include "ViewContainer.moc"

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal