1 /***************************************************************************
2 * Copyright (C) 2004, 2005 Max Howell <max.howell@methylblue.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 ***************************************************************************/
12 #include "amarokconfig.h"
13 #include "browserbar.h"
15 #include "enginecontroller.h"
16 #include "multitabbar.h" //m_tabBar
18 #include <kapplication.h> //kapp
20 #include <kiconloader.h> //multiTabBar icons
23 #include <QCursor> //for resize cursor
25 #include <QSignalMapper> //m_mapper
26 #include <QStyle> //Amarok::Splitter
27 #include <QStyleOption> //Amarok::Splitter
30 #include <QPaintEvent>
31 #include <QMouseEvent>
37 // we emulate a qsplitter, mostly for historic reasons, but there are still a few advantages
38 // mostly we can stop the browserbar getting resized too small so that switching browser looks wrong
43 class Splitter
: public QWidget
{
45 Splitter( BrowserBar
*w
) : QWidget( w
, "divider" )
47 setCursor( QCursor(Qt::SplitHCursor
) );
48 styleChange( style() );
51 virtual void paintEvent( QPaintEvent
* )
54 QStyleOptionFrame option
;
55 option
.initFrom( this ); //state,direction,rect,palette & fM
56 option
.state
= QStyle::State_None
; //it's vertical, not horizontal!
58 option
.state
|= QStyle::State_Enabled
;
60 parentWidget()->style()->drawControl( QStyle::CE_Splitter
, &option
, &p
, this );
63 virtual void styleChange( QStyle
*s
)
66 setFixedWidth( s
->pixelMetric( QStyle::PM_SplitterWidth
, 0, this ) );
69 virtual void mouseMoveEvent( QMouseEvent
*e
)
71 static_cast<BrowserBar
*>(parent())->mouseMovedOverSplitter( e
);
76 BrowserBar
* BrowserBar::s_instance
= 0;
78 BrowserBar::BrowserBar( QWidget
*parent
)
79 : QWidget( parent
, "BrowserBar" )
80 , EngineObserver( EngineController::instance() )
81 , m_playlistBox( new KVBox( this ) )
82 , m_divider( new Amarok::Splitter( this ) )
83 , m_browserBox( new KVBox( this ) )
84 , m_currentIndex( -1 )
86 , m_mapper( new QSignalMapper( this ) )
88 m_tabManagementButton
= new QPushButton( SmallIconSet(Amarok::icon( "configure" )), 0, this, "tab_managment_button" );
89 // connect( m_tabManagementButton, SIGNAL(clicked()), SLOT( showBrowserSelectionMenu()) );
90 // m_tabManagementButton->setMenu( );
92 m_tabManagementButton
->setToolTip( i18n("Manage tabs") );
95 m_tabBar
= new MultiTabBar( MultiTabBar::Vertical
, this );
98 m_tabManagementButton
->setFixedWidth(m_tabBar
->sizeHint().width());
99 m_tabManagementButton
->setFixedHeight(m_tabBar
->sizeHint().width());
103 m_pos
= m_tabBar
->sizeHint().width() + 5; //5 = esthetic spacing
105 m_tabBar
->setStyle( MultiTabBar::AMAROK
);
106 m_tabBar
->setPosition( MultiTabBar::Left
);
107 m_tabBar
->showActiveTabTexts( true );
108 m_tabBar
->setFixedWidth( m_pos
);
109 m_tabBar
->move( 0, 25 );
111 QVBoxLayout
*layout
= new QVBoxLayout( m_browserBox
);
112 layout
->addSpacing( 3 ); // aesthetics
113 layout
->setAutoAdd( true );
115 m_browserBox
->move( m_pos
, 0 );
116 m_browserBox
->hide();
118 m_playlistBox
->setSpacing( 1 );
120 connect( m_mapper
, SIGNAL(mapped( int )), SLOT(showHideBrowser( int )) );
126 //m_tabBar->appendButton( Amarok::icon( "configure" ), 1, 0, QString::null );
130 BrowserBar::~BrowserBar()
132 KSharedConfigPtr config
= Amarok::config( "BrowserBar" );
133 config
->writeEntry( "CurrentPane", m_currentIndex
!= -1 ? QString(currentBrowser()->name()) : QString() );
134 config
->writeEntry( "Width", m_browserBox
->width() );
138 BrowserBar::makeDropProxy( const QString
&name
, DropProxyTarget
*finalTarget
)
140 int id
= m_browserIds
[name
];
141 MultiTabBarButton
*button
= m_tabBar
->tab( id
);
143 button
->proxyDrops( finalTarget
);
147 BrowserBar::restoreWidth()
149 const int index
= indexForName( Amarok::config( "BrowserBar" )->readEntry( "CurrentPane" ) );
150 const int width
= Amarok::config( "BrowserBar" )->readEntry( "Width", browser( index
)->sizeHint().width() );
152 m_browserBox
->resize( width
, height() );
153 m_pos
= m_browserBox
->width() + m_tabBar
->width();
166 oldForeachType( BrowserList
, m_browsers
) {
167 const uint m
= (*it
)->minimumWidth();
171 warning() << "Browser is too large, mxcl says castrate the developer: " << (*it
)->name() << ", " << M
<< endl
;
176 m_browserBox
->setMinimumWidth( M
);
177 const int index
= restoreWidth();
180 // if we did it for -1 it ruins the browserBox size
181 showHideBrowser( index
);
185 BrowserBar::adjustWidgetSizes()
187 //TODO set the geometry of the PlaylistWindow before
188 // the browsers are loaded so this isn't called twice
190 const uint w
= width();
191 const uint h
= height();
192 const uint maxW
= maxBrowserWidth();
193 const uint p
= (m_pos
< maxW
) ? m_pos
: maxW
;
194 const uint ppw
= p
+ m_divider
->width();
195 const uint tbw
= m_tabBar
->width();
197 m_divider
->move( p
, 0 );
199 const uint offset
= !m_divider
->isHidden() ? ppw
: tbw
;
201 m_browserBox
->resize( p
- tbw
, h
);
202 m_playlistBox
->setGeometry( offset
, 0, w
- offset
, h
);
206 BrowserBar::mouseMovedOverSplitter( QMouseEvent
*e
)
208 const uint oldPos
= m_pos
;
209 const uint newPos
= mapFromGlobal( e
->globalPos() ).x();
210 const uint minWidth
= m_tabBar
->width() + m_browserBox
->minimumWidth();
211 const uint maxWidth
= maxBrowserWidth();
213 if( newPos
< minWidth
)
216 else if( newPos
> maxWidth
)
222 if( m_pos
!= oldPos
)
227 BrowserBar::event( QEvent
*e
)
231 case QEvent::LayoutHint
:
232 //FIXME include browserholder width
234 m_tabBar
->minimumWidth() +
235 m_divider
->minimumWidth() +
236 m_browserBox
->width() +
237 m_playlistBox
->minimumWidth() );
243 m_divider
->resize( 0, height() ); //Qt will set width
244 m_tabBar
->resize( 0, height() ); //Qt will set width
254 return QWidget::event( e
);
258 BrowserBar::addBrowser( const QString
&identifier
, QWidget
*widget
, const QString
&title
, const QString
& icon
)
260 const int id
= m_tabBar
->tabs()->count(); // the next available id
261 const QString
name( widget
->name() );
262 m_browserIds
[name
] = id
;
265 widget
->reparent( m_browserBox
, QPoint() );
268 m_tabBar
->appendTab( SmallIcon( icon
), id
, title
, identifier
);
269 tab
= m_tabBar
->tab( id
);
270 tab
->setFocusPolicy( Qt::NoFocus
); //FIXME you can focus on the tab, but they respond to no input!
272 //we use a SignalMapper to show/hide the corresponding browser when tabs are clicked
273 connect( tab
, SIGNAL(clicked()), m_mapper
, SLOT(map()) );
274 m_mapper
->setMapping( tab
, id
);
275 connect( tab
, SIGNAL(initiateDrag ( int ) ), this, SLOT( showBrowser( int )) );
277 m_browsers
.push_back( widget
);
281 BrowserBar::removeMediaBrowser( QWidget
*widget
)
283 BrowserList::iterator it
= qFind( m_browsers
.begin(), m_browsers
.end(), widget
);
284 if( it
!= m_browsers
.end() )
285 m_browsers
.erase( it
);
287 tab
= m_tabBar
->tab( m_browserIds
["MediaBrowser"] );
288 m_mapper
->removeMappings( tab
);
289 m_tabBar
->removeTab( m_browserIds
["MediaBrowser"] );
293 BrowserBar::showHideBrowser( int index
)
295 const int prevIndex
= m_currentIndex
;
297 if( m_currentIndex
!= -1 ) {
298 ///first we need to hide the currentBrowser
300 m_currentIndex
= -1; //to prevent race condition, see CVS history
302 m_browsers
[prevIndex
]->hide();
303 m_tabBar
->setTab( prevIndex
, false );
306 if( index
== prevIndex
) {
307 ///close the BrowserBar
309 m_browserBox
->hide();
315 else if( (uint
)index
< m_browsers
.count() ) {
318 QWidget
* const target
= m_browsers
[index
];
319 m_currentIndex
= index
;
324 m_browserBox
->show();
325 m_tabBar
->setTab( index
, true );
327 if( prevIndex
== -1 ) {
328 // we need to show the browserBox
329 // m_pos dictates how everything will be sized in adjustWidgetSizes()
330 m_pos
= m_browserBox
->width() + m_tabBar
->width();
335 emit
browserActivated( index
);
339 BrowserBar::showHideVisibleBrowser( int index
)
342 Q3PtrList
<MultiTabBarTab
> tabs
= *m_tabBar
->tabs();
343 for( int i
= 0, n
= tabs
.count(); i
< n
; ++i
)
345 if( tabs
.at( i
)->visible() )
355 showHideBrowser( realindex
);
359 BrowserBar::browser( const QString
&name
) const
361 oldForeachType( BrowserList
, m_browsers
)
362 if( name
== (*it
)->name() )
369 BrowserBar::visibleCount() const
372 Q3PtrList
<MultiTabBarTab
> tabs
= *m_tabBar
->tabs();
373 for( int i
= 0, n
= tabs
.count(); i
< n
; ++i
)
375 if( tabs
.at( i
)->visible() )
383 BrowserBar::indexForName( const QString
&name
) const
385 for( uint x
= 0; x
< m_browsers
.count(); ++x
)
386 if( name
== m_browsers
[x
]->name() )
392 BrowserBar::showBrowserSelectionMenu()
394 m_tabBar
->showTabSelectionMenu(mapToGlobal(QPoint(m_tabManagementButton
->pos().x(), m_tabManagementButton
->pos().y() +m_tabManagementButton
->height() )));
397 #include "browserbar.moc"