browserbar.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 409 行
CPP
409 行
/*************************************************************************** * Copyright (C) 2004, 2005 Max Howell <max.howell@methylblue.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. * * * ***************************************************************************/#include "amarok.h"#include "amarokconfig.h"#include "browserbar.h"#include "debug.h"#include "enginecontroller.h"#include "multitabbar.h" //m_tabBar#include <kapplication.h> //kapp#include <kconfig.h>#include <kiconloader.h> //multiTabBar icons#include <klocale.h>#include <qcursor.h> //for resize cursor#include <qpainter.h>#include <qsignalmapper.h> //m_mapper#include <qstyle.h> //Amarok::Splitter#include <qtooltip.h>// we emulate a qsplitter, mostly for historic reasons, but there are still a few advantages// mostly we can stop the browserbar getting resized too small so that switching browser looks wrongnamespace Amarok{ class Splitter : public QWidget { public: Splitter( BrowserBar *w ) : QWidget( w, "divider" ) { setCursor( QCursor(SplitHCursor) ); styleChange( style() ); } virtual void paintEvent( QPaintEvent* ) { QPainter p( this ); parentWidget()->style().drawPrimitive( QStyle::PE_Splitter, &p, rect(), colorGroup(), QStyle::Style_Horizontal ); } virtual void styleChange( QStyle& ) { setFixedWidth( style().pixelMetric( QStyle::PM_SplitterWidth, this ) ); } virtual void mouseMoveEvent( QMouseEvent *e ) { static_cast<BrowserBar*>(parent())->mouseMovedOverSplitter( e ); } };}BrowserBar* BrowserBar::s_instance = 0;BrowserBar::BrowserBar( QWidget *parent ) : QWidget( parent, "BrowserBar" ) , EngineObserver( EngineController::instance() ) , m_playlistBox( new QVBox( this ) ) , m_divider( new Amarok::Splitter( this ) ) , m_browserBox( new QVBox( this ) ) , m_currentIndex( -1 ) , m_lastIndex( -1 ) , m_mapper( new QSignalMapper( this ) ){ m_tabManagementButton = new QPushButton( SmallIconSet(Amarok::icon( "configure" )), 0, this, "tab_managment_button" ); connect (m_tabManagementButton, SIGNAL(clicked()), SLOT(showBrowserSelectionMenu())); m_tabManagementButton->setIsMenuButton ( true ); //deprecated, but since I cannot add menu directly to button it is needed. QToolTip::add (m_tabManagementButton, i18n("Manage tabs")); m_tabBar = new MultiTabBar( MultiTabBar::Vertical, this ); m_tabManagementButton->setFixedWidth(m_tabBar->sizeHint().width()); m_tabManagementButton->setFixedHeight(m_tabBar->sizeHint().width()); s_instance = this; m_pos = m_tabBar->sizeHint().width() + 5; //5 = esthetic spacing m_tabBar->setStyle( MultiTabBar::AMAROK ); m_tabBar->setPosition( MultiTabBar::Left ); m_tabBar->showActiveTabTexts( true ); m_tabBar->setFixedWidth( m_pos ); m_tabBar->move( 0, 25 ); QVBoxLayout *layout = new QVBoxLayout( m_browserBox ); layout->addSpacing( 3 ); // aesthetics layout->setAutoAdd( true ); m_browserBox->move( m_pos, 0 ); m_browserBox->hide(); m_divider->hide(); m_playlistBox->setSpacing( 1 ); connect( m_mapper, SIGNAL(mapped( int )), SLOT(showHideBrowser( int )) ); //m_tabBar->appendButton( Amarok::icon( "configure" ), 1, 0, QString::null );}BrowserBar::~BrowserBar(){ KConfig* const config = Amarok::config( "BrowserBar" ); config->writeEntry( "CurrentPane", m_currentIndex != -1 ? QString(currentBrowser()->name()) : QString::null ); config->writeEntry( "Width", m_browserBox->width() );}voidBrowserBar::makeDropProxy( const QString &name, DropProxyTarget *finalTarget ){ int id = m_browserIds[name]; MultiTabBarButton *button = m_tabBar->tab( id ); if( button ) button->proxyDrops( finalTarget );}intBrowserBar::restoreWidth(){ const int index = indexForName( Amarok::config( "BrowserBar" )->readEntry( "CurrentPane" ) ); const int width = Amarok::config( "BrowserBar" )->readNumEntry( "Width", browser( index )->sizeHint().width() ); m_browserBox->resize( width, height() ); m_pos = m_browserBox->width() + m_tabBar->width(); return index;}voidBrowserBar::polish(){ DEBUG_FUNC_INFO QWidget::polish(); uint M = 0; foreachType( BrowserList, m_browsers ) { const uint m = (*it)->minimumWidth(); if (m > M) M = m; if (m > 250) { warning() << "Browser is too large, mxcl says castrate the developer: " << (*it)->name() << ", " << M << endl; M = 250; } } m_browserBox->setMinimumWidth( M ); const int index = restoreWidth(); if (index != -1) // if we did it for -1 it ruins the browserBox size showHideBrowser( index );}voidBrowserBar::adjustWidgetSizes(){ //TODO set the geometry of the PlaylistWindow before // the browsers are loaded so this isn't called twice const uint w = width(); const uint h = height(); const uint maxW = maxBrowserWidth(); const uint p = (m_pos < maxW) ? m_pos : maxW; const uint ppw = p + m_divider->width(); const uint tbw = m_tabBar->width(); m_divider->move( p, 0 ); const uint offset = !m_divider->isHidden() ? ppw : tbw; m_browserBox->resize( p - tbw, h ); m_playlistBox->setGeometry( offset, 0, w - offset, h );}voidBrowserBar::mouseMovedOverSplitter( QMouseEvent *e ){ const uint oldPos = m_pos; const uint newPos = mapFromGlobal( e->globalPos() ).x(); const uint minWidth = m_tabBar->width() + m_browserBox->minimumWidth(); const uint maxWidth = maxBrowserWidth(); if( newPos < minWidth ) m_pos = minWidth; else if( newPos > maxWidth ) m_pos = maxWidth; else m_pos = newPos; if( m_pos != oldPos ) adjustWidgetSizes();}boolBrowserBar::event( QEvent *e ){ switch( e->type() ) { case QEvent::LayoutHint: //FIXME include browserholder width setMinimumWidth( m_tabBar->minimumWidth() + m_divider->minimumWidth() + m_browserBox->width() + m_playlistBox->minimumWidth() ); break; case QEvent::Resize:// DEBUG_LINE_INFO m_divider->resize( 0, height() ); //Qt will set width m_tabBar->resize( 0, height() ); //Qt will set width adjustWidgetSizes(); return true; default: ; } return QWidget::event( e );}voidBrowserBar::addBrowser( const QString &identifier, QWidget *widget, const QString &title, const QString& icon ){ const int id = m_tabBar->tabs()->count(); // the next available id const QString name( widget->name() ); m_browserIds[name] = id; QWidget *tab; widget->reparent( m_browserBox, QPoint() ); widget->hide(); m_tabBar->appendTab( SmallIcon( icon ), id, title, identifier ); tab = m_tabBar->tab( id ); tab->setFocusPolicy( QWidget::NoFocus ); //FIXME you can focus on the tab, but they respond to no input! //we use a SignalMapper to show/hide the corresponding browser when tabs are clicked connect( tab, SIGNAL(clicked()), m_mapper, SLOT(map()) ); m_mapper->setMapping( tab, id ); connect( tab, SIGNAL(initiateDrag ( int ) ), this, SLOT( showBrowser( int )) ); m_browsers.push_back( widget );}voidBrowserBar::removeMediaBrowser( QWidget *widget ){ BrowserList::iterator it = qFind( m_browsers.begin(), m_browsers.end(), widget ); if( it != m_browsers.end() ) m_browsers.erase( it ); QWidget *tab; tab = m_tabBar->tab( m_browserIds["MediaBrowser"] ); m_mapper->removeMappings( tab ); m_tabBar->removeTab( m_browserIds["MediaBrowser"] );}voidBrowserBar::showHideBrowser( int index ){ const int prevIndex = m_currentIndex; if( m_currentIndex != -1 ) { ///first we need to hide the currentBrowser m_currentIndex = -1; //to prevent race condition, see CVS history m_browsers[prevIndex]->hide(); m_tabBar->setTab( prevIndex, false ); } if( index == prevIndex ) { ///close the BrowserBar m_browserBox->hide(); m_divider->hide(); adjustWidgetSizes(); } else if( (uint)index < m_browsers.count() ) { ///open up target QWidget* const target = m_browsers[index]; m_currentIndex = index; m_divider->show(); target->show(); target->setFocus(); m_browserBox->show(); m_tabBar->setTab( index, true ); if( prevIndex == -1 ) { // we need to show the browserBox // m_pos dictates how everything will be sized in adjustWidgetSizes() m_pos = m_browserBox->width() + m_tabBar->width(); adjustWidgetSizes(); } } emit browserActivated( index );}voidBrowserBar::showHideVisibleBrowser( int index ){ int realindex = -1; QPtrList<MultiTabBarTab> tabs = *m_tabBar->tabs(); for( int i = 0, n = tabs.count(); i < n; ++i ) { if( tabs.at( i )->visible() ) index--; if( index < 0 ) { realindex = i; break; } } if( realindex >= 0 ) showHideBrowser( realindex );}QWidget*BrowserBar::browser( const QString &name ) const{ foreachType( BrowserList, m_browsers ) if( name == (*it)->name() ) return *it; return 0;}intBrowserBar::visibleCount() const{ int num = 0; QPtrList<MultiTabBarTab> tabs = *m_tabBar->tabs(); for( int i = 0, n = tabs.count(); i < n; ++i ) { if( tabs.at( i )->visible() ) num++; } return num;}intBrowserBar::indexForName( const QString &name ) const{ for( uint x = 0; x < m_browsers.count(); ++x ) if( name == m_browsers[x]->name() ) return x; return -1;}voidBrowserBar::showBrowserSelectionMenu(){ m_tabBar->showTabSelectionMenu(mapToGlobal(QPoint(m_tabManagementButton->pos().x(), m_tabManagementButton->pos().y() +m_tabManagementButton->height() )));}voidBrowserBar::engineStateChanged( Engine::State state, Engine::State oldState ){ if( !AmarokConfig::autoShowContextBrowser() || m_currentIndex == -1 ) return; switch( state ) { case Engine::Playing: if( oldState != Engine::Paused && m_currentIndex != -1 ) { m_lastIndex = m_currentIndex; showBrowser( "ContextBrowser" ); } break; case Engine::Empty: if( m_lastIndex >= 0 ) showBrowser( m_lastIndex ); default: ; }}#include "browserbar.moc"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?