multitabbar.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,309 行 · 第 1/3 页

CPP
1,309
字号
/***************************************************************************                       kmultitabbar.cpp -  description                           -------------------   begin                :  2001   copyright            : (C) 2001,2002,2003 by Joseph Wenninger <jowenn@kde.org>                          (C) 2005           by Mark Kretschmann <markey@web.de>***************************************************************************//***************************************************************************    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library 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    Library General Public License for more details.    You should have received a copy of the GNU Library General Public License    along with this library; see the file COPYING.LIB.  If not, write to    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,    Boston, MA 02111-1307, USA.***************************************************************************/#include "debug.h"#include "multitabbar.h"#include "multitabbar.moc"#include "multitabbar_p.h"#include "multitabbar_p.moc"#include <math.h>#include <qbutton.h>#include <qfontmetrics.h>#include <qlayout.h>#include <qpainter.h>#include <qpopupmenu.h>#include <qstyle.h>#include <qtimer.h>#include <kapplication.h>#include <kconfig.h>#include <kdebug.h>#include <kiconeffect.h>#include <kiconloader.h>#include <klocale.h>#include <kpopupmenu.h>#include <kstringhandler.h>#define NEARBYINT(i) ((int(float(i) + 0.5)))namespace Amarok { extern KConfig *config( const QString& ); }class MultiTabBarTabPrivate{    public:        QPixmap pix;};class MultiTabBarButtonPrivate{    public:        MultiTabBarButtonPrivate() : finalDropTarget( 0 ) {}        DropProxyTarget *finalDropTarget;};MultiTabBarInternal::MultiTabBarInternal( QWidget *parent, MultiTabBar::MultiTabBarMode bm ) : QScrollView( parent ){    m_expandedTabSize = -1;    m_showActiveTabTexts = false;    m_tabs.setAutoDelete( true );    m_barMode = bm;    setHScrollBarMode( AlwaysOff );    setVScrollBarMode( AlwaysOff );    if ( bm == MultiTabBar::Vertical ) {        box = new QWidget( viewport() );        mainLayout = new QVBoxLayout( box );        mainLayout->setAutoAdd( true );        box->setFixedWidth( 24 );        setFixedWidth( 24 );    } else {        box = new QWidget( viewport() );        mainLayout = new QHBoxLayout( box );        mainLayout->setAutoAdd( true );        box->setFixedHeight( 24 );        setFixedHeight( 24 );    }    addChild( box );    setFrameStyle( NoFrame );    viewport() ->setBackgroundMode( Qt::PaletteBackground );    /*  box->setPaletteBackgroundColor(Qt::red);        setPaletteBackgroundColor(Qt::green);*/}void MultiTabBarInternal::setStyle( enum MultiTabBar::MultiTabBarStyle style ){    m_style = style;    for ( uint i = 0;i < m_tabs.count();i++ )        m_tabs.at( i ) ->setStyle( m_style );    if ( ( m_style == MultiTabBar::KDEV3 ) ||            ( m_style == MultiTabBar::KDEV3ICON ) ||            ( m_style == MultiTabBar::AMAROK ) ) {        delete mainLayout;        mainLayout = 0;        resizeEvent( 0 );    } else if ( mainLayout == 0 ) {        if ( m_barMode == MultiTabBar::Vertical ) {            box = new QWidget( viewport() );            mainLayout = new QVBoxLayout( box );            box->setFixedWidth( 24 );            setFixedWidth( 24 );        } else {            box = new QWidget( viewport() );            mainLayout = new QHBoxLayout( box );            box->setFixedHeight( 24 );            setFixedHeight( 24 );        }        addChild( box );        for ( uint i = 0;i < m_tabs.count();i++ )            mainLayout->add( m_tabs.at( i ) );        mainLayout->setAutoAdd( true );    }    viewport() ->repaint();}void MultiTabBarInternal::drawContents ( QPainter * paint, int clipx, int clipy, int clipw, int cliph ){    QScrollView::drawContents ( paint , clipx, clipy, clipw, cliph );    if ( m_position == MultiTabBar::Right ) {        paint->setPen( colorGroup().shadow() );        paint->drawLine( 0, 0, 0, viewport() ->height() );        paint->setPen( colorGroup().background().dark( 120 ) );        paint->drawLine( 1, 0, 1, viewport() ->height() );    } else        if ( m_position == MultiTabBar::Left ) {            paint->setPen( colorGroup().light() );            paint->drawLine( 23, 0, 23, viewport() ->height() );            paint->drawLine( 22, 0, 22, viewport() ->height() );            paint->setPen( colorGroup().shadow() );            paint->drawLine( 0, 0, 0, viewport() ->height() );        } else            if ( m_position == MultiTabBar::Bottom ) {                paint->setPen( colorGroup().shadow() );                paint->drawLine( 0, 0, viewport() ->width(), 0 );                paint->setPen( colorGroup().background().dark( 120 ) );                paint->drawLine( 0, 1, viewport() ->width(), 1 );            } else {                paint->setPen( colorGroup().light() );                paint->drawLine( 0, 23, viewport() ->width(), 23 );                paint->drawLine( 0, 22, viewport() ->width(), 22 );                /*                paint->setPen(colorGroup().shadow());                                paint->drawLine(0,0,0,viewport()->height());*/            }}void MultiTabBarInternal::contentsMousePressEvent( QMouseEvent *ev ){    ev->ignore();}void MultiTabBarInternal::showTabSelectionMenu(QPoint pos){    KPopupMenu popup;    popup.insertTitle(  i18n("Browsers") , /*id*/ -1, /*index*/ 1 );    popup.setCheckable( true );    for( uint i = 0; i < m_tabs.count(); i++ ) {        MultiTabBarTab* tab = m_tabs.at( i );        popup.insertItem( tab->text(), i );        popup.setItemChecked(i, tab->visible() ? true : false);    }    int col = popup.exec(pos);    if ( col >= 0 )        setTabVisible( col, !popup.isItemChecked(col) );}void MultiTabBarInternal::mousePressEvent( QMouseEvent *ev ){    if ( ev->button() != QMouseEvent::RightButton ){        ev->ignore();        return;    }    // right button pressed    showTabSelectionMenu(ev->globalPos());}#define CALCDIFF(m_tabs,diff,i) if (m_lines>(int)lines) {\                    /*kdDebug()<<"i="<<i<<" visibleTabCount="<<visibleTabCount()<<" space="<<space<<endl;*/ \                    uint ulen=0;\                    diff=0; \                    for (uint i2=i;i2<visibleTabCount();i2++) {\                        uint l1=sizePerTab();\                        if ((ulen+l1)>space){\                            if (ulen==0) diff=0;\                            else diff=((float)(space-ulen))/(i2-i);\                            break;\                        }\                        ulen+=l1;\                    }\                } else {diff=0; }void MultiTabBarInternal::resizeEvent( QResizeEvent *ev ){    /*  kdDebug()<<"MultiTabBarInternal::resizeEvent"<<endl;        kdDebug()<<"MultiTabBarInternal::resizeEvent - box geometry"<<box->geometry()<<endl;        kdDebug()<<"MultiTabBarInternal::resizeEvent - geometry"<<geometry()<<endl;*/    if ( ev ) QScrollView::resizeEvent( ev );    if ( ( m_style == MultiTabBar::KDEV3 ) ||            ( m_style == MultiTabBar::KDEV3ICON ) ||            ( m_style == MultiTabBar::AMAROK ) ) {        box->setGeometry( 0, 0, width(), height() );        int lines = 1;        uint space;        float tmp = 0;        if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) )            space = width();        else            space = height(); // made space for tab management button        int cnt = 0;        //CALCULATE LINES        const uint tabCount = m_tabs.count();        for ( uint i = 0;i < tabCount;i++ ) {            if ( ! m_tabs.at( i ) ->visible() ) continue;            cnt++;            tmp += sizePerTab();            if ( tmp > space ) {                if ( cnt > 1 ) i--;                else if ( i == ( tabCount - 1 ) ) break;                cnt = 0;                tmp = 0;                lines++;            }        }        //SET SIZE & PLACE        float diff = 0;        cnt = 0;        if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) ) {            setFixedHeight( lines * 24 );            box->setFixedHeight( lines * 24 );            m_lines = height() / 24 - 1;            lines = 0;            CALCDIFF( m_tabs, diff, 0 )            tmp = -diff;            //kdDebug()<<"m_lines recalculated="<<m_lines<<endl;            for ( uint i = 0;i < tabCount;i++ ) {                MultiTabBarTab *tab = m_tabs.at( i );                if ( ! tab->visible() ) continue;                cnt++;                tmp += sizePerTab() + diff;                if ( tmp > space ) {                    //kdDebug()<<"about to start new line"<<endl;                    if ( cnt > 1 ) {                        CALCDIFF( m_tabs, diff, i )                        i--;                    } else {                        //kdDebug()<<"placing line on old line"<<endl;                        kdDebug() << "diff=" << diff << endl;                        tab->removeEventFilter( this );                        tab->move( NEARBYINT( tmp - sizePerTab() ), lines * 24 );                        //						tab->setFixedWidth(tab->neededSize()+diff);                        tab->setFixedWidth( NEARBYINT( tmp + diff ) - tab->x() );;                        tab->installEventFilter( this );                        CALCDIFF( m_tabs, diff, ( i + 1 ) )                    }                    tmp = -diff;                    cnt = 0;                    lines++;                    //kdDebug()<<"starting new line:"<<lines<<endl;                } else {                    //kdDebug()<<"Placing line on line:"<<lines<<" pos: (x/y)=("<<tmp-m_tabs.at(i)->neededSize()<<"/"<<lines*24<<")"<<endl;                    //kdDebug()<<"diff="<<diff<<endl;                    tab->removeEventFilter( this );                    tab->move( NEARBYINT( tmp - sizePerTab() ), lines * 24 );                    tab->setFixedWidth( NEARBYINT( tmp + diff ) - tab->x() );;                    //tab->setFixedWidth(tab->neededSize()+diff);                    tab->installEventFilter( this );                }            }        } else {            // Left or Right            setFixedWidth( lines * 24 );            box->setFixedWidth( lines * 24 );            m_lines = lines = width() / 24;            lines = 0;            CALCDIFF( m_tabs, diff, 0 )            tmp = -diff;            for ( uint i = 0;i < tabCount;i++ ) {                MultiTabBarTab *tab = m_tabs.at( i );                if ( ! tab->visible() ) continue;                cnt++;                tmp += sizePerTab() + diff;                if ( tmp > space ) {                    if ( cnt > 1 ) {                        CALCDIFF( m_tabs, diff, i );                        tmp = -diff;                        i--;                    } else {                        tab->removeEventFilter( this );                        tab->move( lines * 24, NEARBYINT( tmp - sizePerTab() ) );                        tab->setFixedHeight( NEARBYINT( tmp + diff ) - tab->y() );;                        tab->installEventFilter( this );                    }                    cnt = 0;                    tmp = -diff;                    lines++;                } else {                    tab->removeEventFilter( this );                    tab->move( lines * 24, NEARBYINT( tmp - sizePerTab() ) );                    tab->setFixedHeight( NEARBYINT( tmp + diff ) - tab->y() );                    tab->installEventFilter( this );                }            }        }        //kdDebug()<<"needed lines:"<<m_lines<<endl;    } else {        int size = 0; /*move the calculation into another function and call it only on add tab and tab click events*/        for ( int i = 0;i < ( int ) m_tabs.count();i++ )            size += ( m_barMode == MultiTabBar::Vertical ? m_tabs.at( i ) ->height() : m_tabs.at( i ) ->width() );        if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) )            box->setGeometry( 0, 0, size, height() );        else box->setGeometry( 0, 0, width(), size );    }}void MultiTabBarInternal::showActiveTabTexts( bool show ){    m_showActiveTabTexts = show;}MultiTabBarTab* MultiTabBarInternal::tab( int id ) const{    for ( QPtrListIterator<MultiTabBarTab> it( m_tabs );it.current();++it ) {        if ( it.current() ->id() == id ) return it.current();    }    return 0;}bool MultiTabBarInternal::eventFilter( QObject *, QEvent *e ){    if ( e->type() == QEvent::Resize )        resizeEvent( 0 );    //PATCH by markey: Allow switching of tabs with mouse wheel    if ( e->type() == QEvent::Wheel ) {        QWheelEvent* event = static_cast<QWheelEvent*>( e );        const int delta = event->delta() / 120;        // Determine which tab is currently active        uint i;        for( i = 0; i < m_tabs.count(); i++ )            if ( m_tabs.at( i )->isOn() ) break;        // Calculate index of the new tab to activate        int newTab = i - delta;        while (true) {            if ( newTab < 0 ) {                newTab = i;                break;            }            if ( newTab > (int)m_tabs.count() - 1 ) {                newTab = i;                break;            }            if ( m_tabs.at( newTab )->visible() && m_tabs.at( newTab )->isEnabled() )                break;            // try one tab more            newTab -= delta;        }        if ( i < m_tabs.count() && newTab != (int)i )            m_tabs.at( newTab )->animateClick();        // Must return true here for the wheel to work properly        return true;    }    return false;}int MultiTabBarInternal::appendTab( const QPixmap &pic , int id, const QString& text, const QString& identifier ){    MultiTabBarTab * tab;    m_tabs.append( tab = new MultiTabBarTab( pic, text, id, box, m_position, m_style ) );    tab->setIdentifier( identifier );    tab->installEventFilter( this );    tab->showActiveTabText( m_showActiveTabTexts );    tab->setVisible( Amarok::config( "BrowserBar" )->readBoolEntry( identifier, true ) );    if ( m_style == MultiTabBar::KONQSBC ) {        if ( m_expandedTabSize < tab->neededSize() ) {            m_expandedTabSize = tab->neededSize();            for ( uint i = 0;i < m_tabs.count();i++ )                m_tabs.at( i ) ->setSize( m_expandedTabSize );        } else tab->setSize( m_expandedTabSize );    } else tab->updateState();    if ( tab->visible() ) {        tab->show();        resizeEvent( 0 );    } else tab->hide();    return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?