add check for role to data()
[amarok.git] / src / browserbar.cpp
blobad91b8e1e3679deafba43f635f2eb49a402a425e
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 Max Howell <max.howell@methylblue.com> *
3 * *
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. *
8 * *
9 ***************************************************************************/
11 #include "amarok.h"
12 #include "amarokconfig.h"
13 #include "browserbar.h"
14 #include "debug.h"
15 #include "enginecontroller.h"
16 #include "multitabbar.h" //m_tabBar
18 #include <kapplication.h> //kapp
19 #include <kconfig.h>
20 #include <kiconloader.h> //multiTabBar icons
21 #include <klocale.h>
23 #include <QCursor> //for resize cursor
24 #include <QPainter>
25 #include <QSignalMapper> //m_mapper
26 #include <QStyle> //Amarok::Splitter
27 #include <QStyleOption> //Amarok::Splitter
28 #include <QToolTip>
29 //Added by qt3to4:
30 #include <QPaintEvent>
31 #include <QMouseEvent>
32 #include <Q3PtrList>
33 #include <QEvent>
34 #include <KVBox>
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
41 namespace Amarok
43 class Splitter : public QWidget {
44 public:
45 Splitter( BrowserBar *w ) : QWidget( w, "divider" )
47 setCursor( QCursor(Qt::SplitHCursor) );
48 styleChange( style() );
51 virtual void paintEvent( QPaintEvent* )
53 QPainter p( this );
54 QStyleOptionFrame option;
55 option.initFrom( this ); //state,direction,rect,palette & fM
56 option.state = QStyle::State_None; //it's vertical, not horizontal!
57 if( isEnabled() )
58 option.state |= QStyle::State_Enabled;
60 parentWidget()->style()->drawControl( QStyle::CE_Splitter, &option, &p, this );
63 virtual void styleChange( QStyle *s )
65 if( 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 )
85 , m_lastIndex( -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());
102 s_instance = this;
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();
117 m_divider->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() );
137 void
138 BrowserBar::makeDropProxy( const QString &name, DropProxyTarget *finalTarget )
140 int id = m_browserIds[name];
141 MultiTabBarButton *button = m_tabBar->tab( id );
142 if( button )
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();
155 return index;
158 void
159 BrowserBar::polish()
161 DEBUG_FUNC_INFO
163 QWidget::polish();
165 uint M = 0;
166 oldForeachType( BrowserList, m_browsers ) {
167 const uint m = (*it)->minimumWidth();
168 if (m > M)
169 M = m;
170 if (m > 250) {
171 warning() << "Browser is too large, mxcl says castrate the developer: " << (*it)->name() << ", " << M << endl;
172 M = 250;
176 m_browserBox->setMinimumWidth( M );
177 const int index = restoreWidth();
179 if (index != -1)
180 // if we did it for -1 it ruins the browserBox size
181 showHideBrowser( index );
184 void
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 );
205 void
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 )
214 m_pos = minWidth;
216 else if( newPos > maxWidth )
217 m_pos = maxWidth;
219 else
220 m_pos = newPos;
222 if( m_pos != oldPos )
223 adjustWidgetSizes();
226 bool
227 BrowserBar::event( QEvent *e )
229 switch( e->type() )
231 case QEvent::LayoutHint:
232 //FIXME include browserholder width
233 setMinimumWidth(
234 m_tabBar->minimumWidth() +
235 m_divider->minimumWidth() +
236 m_browserBox->width() +
237 m_playlistBox->minimumWidth() );
238 break;
240 case QEvent::Resize:
241 // DEBUG_LINE_INFO
243 m_divider->resize( 0, height() ); //Qt will set width
244 m_tabBar->resize( 0, height() ); //Qt will set width
246 adjustWidgetSizes();
248 return true;
250 default:
254 return QWidget::event( e );
257 void
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;
263 QWidget *tab;
265 widget->reparent( m_browserBox, QPoint() );
266 widget->hide();
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 );
280 void
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 );
286 QWidget *tab;
287 tab = m_tabBar->tab( m_browserIds["MediaBrowser"] );
288 m_mapper->removeMappings( tab );
289 m_tabBar->removeTab( m_browserIds["MediaBrowser"] );
292 void
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();
310 m_divider->hide();
312 adjustWidgetSizes();
315 else if( (uint)index < m_browsers.count() ) {
316 ///open up target
318 QWidget* const target = m_browsers[index];
319 m_currentIndex = index;
321 m_divider->show();
322 target->show();
323 target->setFocus();
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();
331 adjustWidgetSizes();
335 emit browserActivated( index );
338 void
339 BrowserBar::showHideVisibleBrowser( int index )
341 int realindex = -1;
342 Q3PtrList<MultiTabBarTab> tabs = *m_tabBar->tabs();
343 for( int i = 0, n = tabs.count(); i < n; ++i )
345 if( tabs.at( i )->visible() )
346 index--;
347 if( index < 0 )
349 realindex = i;
350 break;
354 if( realindex >= 0 )
355 showHideBrowser( realindex );
358 QWidget*
359 BrowserBar::browser( const QString &name ) const
361 oldForeachType( BrowserList, m_browsers )
362 if( name == (*it)->name() )
363 return *it;
365 return 0;
369 BrowserBar::visibleCount() const
371 int num = 0;
372 Q3PtrList<MultiTabBarTab> tabs = *m_tabBar->tabs();
373 for( int i = 0, n = tabs.count(); i < n; ++i )
375 if( tabs.at( i )->visible() )
376 num++;
379 return num;
383 BrowserBar::indexForName( const QString &name ) const
385 for( uint x = 0; x < m_browsers.count(); ++x )
386 if( name == m_browsers[x]->name() )
387 return x;
388 return -1;
391 void
392 BrowserBar::showBrowserSelectionMenu()
394 m_tabBar->showTabSelectionMenu(mapToGlobal(QPoint(m_tabManagementButton->pos().x(), m_tabManagementButton->pos().y() +m_tabManagementButton->height() )));
397 #include "browserbar.moc"