/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2009 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ // own #include "tabboxview.h" // tabbox #include "clientitemdelegate.h" #include "clientmodel.h" #include "desktopitemdelegate.h" #include "desktopmodel.h" #include "tabboxconfig.h" #include "tabboxhandler.h" // Qt #include #include #include #include #include #include #include // KDE #include #include #include namespace KWin { namespace TabBox { TabBoxView::TabBoxView( QWidget* parent ) : QWidget( parent ) , m_previewUpdate( false ) { setWindowFlags( Qt::X11BypassWindowManagerHint ); setAttribute( Qt::WA_TranslucentBackground ); QPalette pal = palette(); pal.setColor(backgroundRole(), Qt::transparent); setPalette(pal); m_clientModel = new ClientModel( this ); m_desktopModel = new DesktopModel( this ); m_delegate = new ClientItemDelegate( this ); m_additionalClientDelegate = new ClientItemDelegate( this ); m_additionalClientDelegate->setShowSelection( false ); m_desktopItemDelegate = new DesktopItemDelegate( this ); m_additionalDesktopDelegate = new DesktopItemDelegate( this ); m_tableView = new TabBoxMainView( this ); m_additionalView = new TabBoxAdditionalView( this ); // FrameSvg m_frame = new Plasma::FrameSvg( this ); m_frame->setImagePath( "dialogs/background" ); m_frame->setCacheAllRenderedFrames( true ); m_frame->setEnabledBorders( Plasma::FrameSvg::AllBorders ); m_selectionFrame = new Plasma::FrameSvg( this ); m_selectionFrame->setImagePath( "widgets/viewitem" ); m_selectionFrame->setElementPrefix( "hover" ); m_selectionFrame->setCacheAllRenderedFrames( true ); m_selectionFrame->setEnabledBorders( Plasma::FrameSvg::AllBorders ); m_animation = new QPropertyAnimation( this, "selectedItem", this ); m_animation->setDuration(250); m_animation->setEasingCurve( QEasingCurve::InOutQuad ); connect( tabBox, SIGNAL(configChanged()), this, SLOT(configChanged())); connect( m_animation, SIGNAL(valueChanged(QVariant)), SLOT(update())); connect( m_tableView, SIGNAL(activated(QModelIndex)), SLOT(setCurrentIndex(QModelIndex))); } TabBoxView::~TabBoxView() { } void TabBoxView::paintEvent(QPaintEvent* e) { // paint the background QPainter painter( this ); painter.setRenderHint(QPainter::Antialiasing); painter.setClipRect(e->rect()); m_frame->paintFrame( &painter ); // and the selection item if( m_previewUpdate ) { m_previewUpdate = false; setCurrentIndex( m_tableView->currentIndex() ); } m_selectionFrame->paintFrame( &painter, m_tableView->geometry().topLeft() + m_selectedItem.topLeft() ); QWidget::paintEvent(e); } bool TabBoxView::event( QEvent* event ) { if( event->type() == QEvent::Paint ) { QPainter p( this ); p.setCompositionMode( QPainter::CompositionMode_Source ); p.fillRect( rect(), Qt::transparent ); } return QWidget::event( event ); } void TabBoxView::resizeEvent(QResizeEvent* event) { m_frame->resizeFrame( event->size() ); setMask( m_frame->mask() ); QWidget::resizeEvent(event); } void TabBoxView::updateGeometry() { if( m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 0 ) return; QSize hint = sizeHint(); QRect screenRect = Kephal::ScreenUtils::screenGeometry( tabBox->activeScreen() ); int x = screenRect.x() + screenRect.width() * 0.5 - hint.width() * 0.5; int y = screenRect.y() + screenRect.height() * 0.5 - hint.height() * 0.5; setGeometry( x, y, hint.width(), hint.height() ); } QSize TabBoxView::sizeHint() const { if( m_tableView->model()->columnCount() == 0 || m_tableView->model()->rowCount() == 0 ) return QSize( 0, 0 ); // calculate width and height QSize tabBoxSize = m_tableView->sizeHint(); qreal columnWidth = tabBoxSize.width() / m_tableView->model()->columnCount(); qreal rowHeight = tabBoxSize.height() / m_tableView->model()->rowCount(); for( int i=0; imodel()->rowCount(); i++ ) m_tableView->setRowHeight( i, rowHeight ); // additional view QSize additionalSize = m_additionalView->sizeHint(); for( int i=0; imodel()->columnCount(); i++ ) m_additionalView->setColumnWidth( i, additionalSize.width() ); for( int i=0; imodel()->rowCount(); i++ ) m_additionalView->setRowHeight( i, additionalSize.height() ); // reserve some space for borders qreal top, bottom, left, right; m_frame->getMargins( left, top, right, bottom ); int width = columnWidth * m_tableView->model()->columnCount() + left + right; int height = rowHeight * m_tableView->model()->rowCount() + top + bottom; qreal addedWidth = left + right; // depending on layout of additional view we have to add some width or height switch( tabBox->config().selectedItemViewPosition() ) { case TabBoxConfig::AbovePosition: // fall through case TabBoxConfig::BelowPosition: if( additionalSize.width() + int(left + right) > width ) { addedWidth += (additionalSize.width() + int(left + right) - width); width = additionalSize.width() + int(left + right); } height = height + additionalSize.height(); break; case TabBoxConfig::LeftPosition: // fall through case TabBoxConfig::RightPosition: width = width + additionalSize.width(); addedWidth += additionalSize.width(); height = qMax( height, additionalSize.height() + int(top + bottom) ); break; default: // don't add break; } QRect screenRect = Kephal::ScreenUtils::screenGeometry( tabBox->activeScreen() ); width = qBound( screenRect.width() * tabBox->config().minWidth() / 100, width, screenRect.width() ); height = qBound( screenRect.height() * tabBox->config().minHeight() / 100, height, screenRect.height() ); if( width - addedWidth > tabBoxSize.width() ) { columnWidth = (width - addedWidth) / m_tableView->model()->columnCount(); } m_tableView->setMinimumWidth( width - addedWidth ); for( int i=0; imodel()->columnCount(); i++ ) m_tableView->setColumnWidth( i, columnWidth ); return QSize( width, height ); } void TabBoxView::setCurrentIndex( QModelIndex index ) { if( index.isValid() ) { m_tableView->setCurrentIndex( index ); const QRect visualRect = m_tableView->visualRect( index ); if( m_selectedItem.isNull() ) m_selectedItem = visualRect; if( m_animation->state() == QPropertyAnimation::Running ) { m_animation->stop(); m_selectedItem = visualRect; update(); } else { m_animation->setStartValue( m_selectedItem ); m_animation->setEndValue( visualRect ); m_animation->start(); } m_selectionFrame->resizeFrame( visualRect.size() ); m_additionalView->setCurrentIndex( index ); } } void TabBoxView::configChanged() { switch( tabBox->config().tabBoxMode() ) { case TabBoxConfig::ClientTabBox: m_tableView->setModel( m_clientModel ); m_tableView->setItemDelegate( m_delegate ); m_additionalView->setModel( m_clientModel ); m_additionalView->setItemDelegate( m_additionalClientDelegate ); break; case TabBoxConfig::DesktopTabBox: m_tableView->setModel( m_desktopModel ); m_tableView->setItemDelegate( m_desktopItemDelegate ); m_additionalView->setModel( m_desktopModel ); m_additionalView->setItemDelegate( m_additionalDesktopDelegate ); break; } QLayout* old = layout(); QLayoutItem *child; while( old && (child = old->takeAt( 0 )) != 0 ) { delete child; } delete old; QBoxLayout *layout; switch( tabBox->config().selectedItemViewPosition() ) { case TabBoxConfig::AbovePosition: { layout = new QVBoxLayout(); QHBoxLayout* horizontalLayout1 = new QHBoxLayout(); horizontalLayout1->addStretch(); horizontalLayout1->addWidget( m_additionalView ); horizontalLayout1->addStretch(); layout->addLayout( horizontalLayout1 ); layout->addStretch(); QHBoxLayout* horizontalLayout2 = new QHBoxLayout(); horizontalLayout2->addStretch(); horizontalLayout2->addWidget( m_tableView ); horizontalLayout2->addStretch(); layout->addLayout( horizontalLayout2 ); m_additionalView->show(); break; } case TabBoxConfig::BelowPosition: { layout = new QVBoxLayout(); QHBoxLayout* horizontalLayout1 = new QHBoxLayout(); horizontalLayout1->addStretch(); horizontalLayout1->addWidget( m_tableView ); horizontalLayout1->addStretch(); layout->addLayout( horizontalLayout1 ); layout->addStretch(); QHBoxLayout* horizontalLayout2 = new QHBoxLayout(); horizontalLayout2->addStretch(); horizontalLayout2->addWidget( m_additionalView ); horizontalLayout2->addStretch(); layout->addLayout( horizontalLayout2 ); m_additionalView->show(); break; } case TabBoxConfig::LeftPosition: { layout = new QHBoxLayout(); QVBoxLayout* verticalLayout1 = new QVBoxLayout(); verticalLayout1->addStretch(); verticalLayout1->addWidget( m_additionalView ); verticalLayout1->addStretch(); layout->addLayout( verticalLayout1 ); layout->addStretch(); QVBoxLayout* verticalLayout2 = new QVBoxLayout(); verticalLayout2->addStretch(); verticalLayout2->addWidget( m_tableView ); verticalLayout2->addStretch(); layout->addLayout( verticalLayout2 ); m_additionalView->show(); break; } case TabBoxConfig::RightPosition: { layout = new QHBoxLayout(); QVBoxLayout* verticalLayout1 = new QVBoxLayout(); verticalLayout1->addStretch(); verticalLayout1->addWidget( m_tableView ); verticalLayout1->addStretch(); layout->addLayout( verticalLayout1 ); layout->addStretch(); QVBoxLayout* verticalLayout2 = new QVBoxLayout(); verticalLayout2->addStretch(); verticalLayout2->addWidget( m_additionalView ); verticalLayout2->addStretch(); layout->addLayout( verticalLayout2 ); m_additionalView->show(); break; } default: { layout = new QVBoxLayout(); layout->addStretch(); layout->addWidget( m_tableView ); layout->addStretch(); m_additionalView->hide(); break; } } setLayout( layout ); if( m_preview ) m_previewUpdate = true; } QModelIndex TabBoxView::indexAt( QPoint pos ) { return m_tableView->indexAt( pos ); } void TabBoxView::setPreview( bool preview ) { m_preview = preview; if( preview ) m_frame->setImagePath( "dialogs/opaque/background" ); } /******************************************************** * TabBoxMainView ********************************************************/ TabBoxMainView::TabBoxMainView(QWidget* parent) : QTableView(parent) { setFrameStyle( QFrame::NoFrame ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); viewport()->setAutoFillBackground( false ); // adjust table view to needs of tabbox setShowGrid( false ); horizontalHeader()->hide(); verticalHeader()->hide(); setSelectionMode( QAbstractItemView::SingleSelection ); setSelectionBehavior( QAbstractItemView::SelectItems ); setHorizontalScrollMode( QAbstractItemView::ScrollPerItem ); setVerticalScrollMode( QAbstractItemView::ScrollPerItem ); setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); } TabBoxMainView::~TabBoxMainView() { } QSize TabBoxMainView::sizeHint() const { int maxWidth = 0; int minWidth = sizeHintForColumn( 0 ); int maxHeight = 0; int minHeight = sizeHintForRow( 0 ); for( int i=0; icolumnCount(); i++ ) { minWidth = qMin( minWidth, sizeHintForColumn( i ) ); maxWidth = qMax( maxWidth, sizeHintForColumn( i ) ); } for( int i=0; irowCount(); i++ ) { minHeight = qMin( minHeight, sizeHintForRow( i ) ); maxHeight = qMax( maxHeight, sizeHintForRow( i ) ); } qreal columnWidth = (minWidth + qreal(maxWidth - minWidth) / 2.0 ); qreal rowHeight = (minHeight + qreal(maxHeight - minHeight) / 2.0 ); return QSize( columnWidth * model()->columnCount(), rowHeight * model()->rowCount() ); } QModelIndex TabBoxMainView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers) { Q_UNUSED( cursorAction ) Q_UNUSED( modifiers ) return currentIndex(); } /******************************************************** * TabBoxAdditonalView ********************************************************/ TabBoxAdditionalView::TabBoxAdditionalView(QWidget* parent) : QTableView(parent) { setFrameStyle( QFrame::NoFrame ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); viewport()->setAutoFillBackground( false ); // adjust table view to needs of tabbox setShowGrid( false ); horizontalHeader()->hide(); verticalHeader()->hide(); setSelectionMode( QAbstractItemView::SingleSelection ); setSelectionBehavior( QAbstractItemView::SelectItems ); setHorizontalScrollMode( QAbstractItemView::ScrollPerItem ); setVerticalScrollMode( QAbstractItemView::ScrollPerItem ); setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); } TabBoxAdditionalView::~TabBoxAdditionalView() { } QSize TabBoxAdditionalView::sizeHint() const { int maxWidth = 0; int minWidth = sizeHintForColumn( 0 ); int maxHeight = 0; int minHeight = sizeHintForRow( 0 ); for( int i=0; icolumnCount(); i++ ) { minWidth = qMin( minWidth, sizeHintForColumn( i ) ); maxWidth = qMax( maxWidth, sizeHintForColumn( i ) ); } for( int i=0; irowCount(); i++ ) { minHeight = qMin( minHeight, sizeHintForRow( i ) ); maxHeight = qMax( maxHeight, sizeHintForRow( i ) ); } qreal columnWidth = (minWidth + qreal(maxWidth - minWidth) / 2.0 ); qreal rowHeight = (minHeight + qreal(maxHeight - minHeight) / 2.0 ); return QSize( columnWidth, rowHeight ); } QModelIndex TabBoxAdditionalView::moveCursor( QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) { Q_UNUSED( cursorAction ) Q_UNUSED( modifiers ) return currentIndex(); } void TabBoxAdditionalView::wheelEvent( QWheelEvent* event ) { Q_UNUSED( event ) } } // namespace Tabbox } // namespace KWin #include "tabboxview.moc"