608f5fab7a
This change also includes some visual updates which fixes the black corners issue for non composited tabbox (no idea why), the hughe black border in the prview is still visible (also no idea why). svn path=/trunk/KDE/kdebase/workspace/; revision=1070114
470 lines
16 KiB
C++
470 lines
16 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
|
|
// 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 <QTextStream>
|
|
#include <QGridLayout>
|
|
#include <QHeaderView>
|
|
#include <QKeyEvent>
|
|
#include <QSizePolicy>
|
|
#include <QPainter>
|
|
#include <QPropertyAnimation>
|
|
|
|
// KDE
|
|
#include <kephal/screens.h>
|
|
#include <Plasma/FrameSvg>
|
|
#include <KDebug>
|
|
|
|
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->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; i<m_tableView->model()->rowCount(); i++ )
|
|
m_tableView->setRowHeight( i, rowHeight );
|
|
|
|
// additional view
|
|
QSize additionalSize = m_additionalView->sizeHint();
|
|
for( int i=0; i<m_additionalView->model()->columnCount(); i++ )
|
|
m_additionalView->setColumnWidth( i, additionalSize.width() );
|
|
for( int i=0; i<m_additionalView->model()->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; i<m_tableView->model()->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; i<model()->columnCount(); i++ )
|
|
{
|
|
minWidth = qMin( minWidth, sizeHintForColumn( i ) );
|
|
maxWidth = qMax( maxWidth, sizeHintForColumn( i ) );
|
|
}
|
|
for( int i=0; i<model()->rowCount(); 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; i<model()->columnCount(); i++ )
|
|
{
|
|
minWidth = qMin( minWidth, sizeHintForColumn( i ) );
|
|
maxWidth = qMax( maxWidth, sizeHintForColumn( i ) );
|
|
}
|
|
for( int i=0; i<model()->rowCount(); 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"
|