1 /*****************************************************************************
2 * customwidgets.cpp: Custom widgets
3 ****************************************************************************
4 * Copyright (C) 2006 the VideoLAN team
5 * Copyright (C) 2004 Daniel Molkentin <molkentin@kde.org>
8 * Authors: Clément Stenac <zorglub@videolan.org>
9 * The "ClickLineEdit" control is based on code by Daniel Molkentin
10 * <molkentin@kde.org> for libkdepim
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
31 #include "customwidgets.hpp"
32 #include "qt4.hpp" /*needed for qtr and CONNECT, but not necessary */
37 #include <QWheelEvent>
41 QFramelessButton::QFramelessButton( QWidget *parent )
42 : QPushButton( parent )
44 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
47 void QFramelessButton::paintEvent( QPaintEvent * )
49 QPainter painter( this );
50 QPixmap pix = icon().pixmap( size() );
51 QPoint pos( (width() - pix.width()) / 2, (height() - pix.height()) / 2 );
52 painter.drawPixmap( QRect( pos.x(), pos.y(), pix.width(), pix.height() ), pix );
55 QElidingLabel::QElidingLabel( const QString &s, Qt::TextElideMode mode, QWidget * parent )
56 : elideMode( mode ), QLabel( s, parent )
59 void QElidingLabel::setElideMode( Qt::TextElideMode mode )
65 void QElidingLabel::paintEvent( QPaintEvent * event )
68 int space = frameWidth() + margin();
69 QRect r = rect().adjusted( space, space, -space, -space );
70 p.drawText( r, fontMetrics().elidedText( text(), elideMode, r.width() ), alignment() );
73 QString QVLCDebugLevelSpinBox::textFromValue( int v ) const
75 QString const texts[] = {
76 /* Note that min level 0 is 'errors' in Qt Ui
77 FIXME: fix debug levels accordingly to documentation */
86 return QString( "%1 (%2)" ).arg( v ).arg( texts[v] );
89 /***************************************************************************
91 ***************************************************************************/
92 int qtKeyModifiersToVLC( QInputEvent* e )
94 int i_keyModifiers = 0;
95 if( e->modifiers() & Qt::ShiftModifier ) i_keyModifiers |= KEY_MODIFIER_SHIFT;
96 if( e->modifiers() & Qt::AltModifier ) i_keyModifiers |= KEY_MODIFIER_ALT;
97 if( e->modifiers() & Qt::ControlModifier ) i_keyModifiers |= KEY_MODIFIER_CTRL;
98 if( e->modifiers() & Qt::MetaModifier ) i_keyModifiers |= KEY_MODIFIER_META;
99 return i_keyModifiers;
108 static const vlc_qt_key_t keys[] =
110 { Qt::Key_Escape, KEY_ESC },
111 { Qt::Key_Tab, '\t', },
113 { Qt::Key_Backspace, '\b' },
114 { Qt::Key_Return, '\r' },
115 { Qt::Key_Enter, '\r' }, // numeric pad
116 { Qt::Key_Insert, KEY_INSERT },
117 { Qt::Key_Delete, KEY_DELETE },
122 { Qt::Key_Home, KEY_HOME },
123 { Qt::Key_End, KEY_END },
124 { Qt::Key_Left, KEY_LEFT },
125 { Qt::Key_Up, KEY_UP },
126 { Qt::Key_Right, KEY_RIGHT },
127 { Qt::Key_Down, KEY_DOWN },
128 { Qt::Key_PageUp, KEY_PAGEUP },
129 { Qt::Key_PageDown, KEY_PAGEDOWN },
136 // Qt::Key_ScrollLock
137 /* F1 - F35 - Qt goes to F35, VLC stops at F12 */
138 { Qt::Key_F1, KEY_F1 },
139 { Qt::Key_F2, KEY_F2 },
140 { Qt::Key_F3, KEY_F3 },
141 { Qt::Key_F4, KEY_F4 },
142 { Qt::Key_F5, KEY_F5 },
143 { Qt::Key_F6, KEY_F6 },
144 { Qt::Key_F7, KEY_F7 },
145 { Qt::Key_F8, KEY_F8 },
146 { Qt::Key_F9, KEY_F9 },
147 { Qt::Key_F10, KEY_F10 },
148 { Qt::Key_F11, KEY_F11 },
149 { Qt::Key_F12, KEY_F12 },
152 { Qt::Key_Menu, KEY_MENU },
156 // Qt::Key_Direction_L
157 // Qt::Key_Direction_R
161 // Qt::Key_SingleCandidate
162 // Qt::Key_MultipleCandidate
163 // Qt::Key_PreviousCandidate
164 // Qt::Key_Mode_switch
171 // Qt::Key_Hiragana_Katakana
174 // Qt::Key_Zenkaku_Hankaku
178 // Qt::Key_Kana_Shift
179 // Qt::Key_Eisu_Shift
180 // Qt::Key_Eisu_toggle
182 // Qt::Key_Hangul_Start
183 // Qt::Key_Hangul_End
184 // Qt::Key_Hangul_Hanja
185 // Qt::Key_Hangul_Jamo
186 // Qt::Key_Hangul_Romaja
187 // Qt::Key_Hangul_Jeonja
188 // Qt::Key_Hangul_Banja
189 // Qt::Key_Hangul_PreHanja
190 // Qt::Key_Hangul_PostHanja
191 // Qt::Key_Hangul_Special
192 // Qt::Key_Dead_Grave
193 // Qt::Key_Dead_Acute
194 // Qt::Key_Dead_Circumflex
195 // Qt::Key_Dead_Tilde
196 // Qt::Key_Dead_Macron
197 // Qt::Key_Dead_Breve
198 // Qt::Key_Dead_Abovedot
199 // Qt::Key_Dead_Diaeresis
200 // Qt::Key_Dead_Abovering
201 // Qt::Key_Dead_Doubleacute
202 // Qt::Key_Dead_Caron
203 // Qt::Key_Dead_Cedilla
204 // Qt::Key_Dead_Ogonek
206 // Qt::Key_Dead_Voiced_Sound
207 // Qt::Key_Dead_Semivoiced_Sound
208 // Qt::Key_Dead_Belowdot
211 { Qt::Key_Back, KEY_BROWSER_BACK },
212 { Qt::Key_Forward, KEY_BROWSER_FORWARD },
213 { Qt::Key_Stop, KEY_BROWSER_STOP },
214 { Qt::Key_Refresh, KEY_BROWSER_REFRESH },
215 { Qt::Key_VolumeDown, KEY_VOLUME_DOWN },
216 { Qt::Key_VolumeMute, KEY_VOLUME_MUTE },
217 { Qt::Key_VolumeUp, KEY_VOLUME_UP },
222 // Qt::Key_TrebleDown
223 { Qt::Key_MediaPlay, KEY_MEDIA_PLAY_PAUSE },
224 { Qt::Key_MediaStop, KEY_MEDIA_STOP },
225 { Qt::Key_MediaPrevious, KEY_MEDIA_PREV_TRACK },
226 { Qt::Key_MediaNext, KEY_MEDIA_NEXT_TRACK },
227 // Qt::Key_MediaRecord
228 { Qt::Key_HomePage, KEY_BROWSER_HOME },
229 { Qt::Key_Favorites, KEY_BROWSER_FAVORITES },
230 { Qt::Key_Search, KEY_BROWSER_SEARCH },
233 // Qt::Key_LaunchMail
234 // Qt::Key_LaunchMedia
235 /* Qt::Key_Launch0 through Qt::Key_LaunchF */
239 static int keycmp( const void *a, const void *b )
241 const int *q = (const int *)a;
242 const vlc_qt_key_t *m = (const vlc_qt_key_t *)b;
247 int qtEventToVLCKey( QKeyEvent *e )
254 /* VLC and X11 use lowercase whereas Qt uses uppercase, this
255 * method should be equal to towlower in case of latin1 */
256 if( qtk >= 'A' && qtk <= 'Z' ) i_vlck = qtk+32;
257 else if( qtk >= 0xC0 && qtk <= 0xDE && qtk != 0xD7) i_vlck = qtk+32;
262 const vlc_qt_key_t *map;
264 map = (const vlc_qt_key_t *)
265 bsearch( &qtk, (const void *)keys, sizeof(keys)/sizeof(keys[0]),
266 sizeof(*keys), keycmp );
271 /* Handle modifiers */
272 i_vlck |= qtKeyModifiersToVLC( e );
276 int qtWheelEventToVLCKey( QWheelEvent *e )
279 /* Handle modifiers */
280 i_vlck |= qtKeyModifiersToVLC( e );
281 if ( e->delta() > 0 )
282 i_vlck |= KEY_MOUSEWHEELUP;
284 i_vlck |= KEY_MOUSEWHEELDOWN;
288 QString VLCKeyToString( unsigned val )
290 char *base = vlc_keycode2str (val);
292 return qtr( "Unset" );
294 QString r = qfu( base );
301 /* Animated Icon implementation */
303 AnimatedIcon::AnimatedIcon( QWidget *parent )
304 : mTimer( this ), mIdleFrame( NULL )
306 mCurrentFrame = mRemainingLoops = 0;
307 connect( &mTimer, SIGNAL( timeout() ), this, SLOT( onTimerTick() ) );
310 AnimatedIcon::~AnimatedIcon()
312 // We don't need to destroy the timer, he's our child
314 foreach( QPixmap *frame, mFrames )
318 void AnimatedIcon::addFrame( const QPixmap &pxm, int index )
322 // Replace idle frame
324 mIdleFrame = new QPixmap( pxm );
325 setPixmap( *mIdleFrame );
328 QPixmap *copy = new QPixmap( pxm );
329 mFrames.insert( ( index < 0 || index > mFrames.size() ) ? mFrames.size() :
335 void AnimatedIcon::play( int loops, int interval )
340 printf( "AnimatedIcon::play(): interval is too short (%d ms)",
346 if( !mIdleFrame && ( mFrames.empty() | loops != 0 ) )
349 printf( "AnimatedIcon::play(): no frames to display" );
357 mCurrentFrame = mRemainingLoops = 0;
359 setPixmap( mIdleFrame != NULL ? *mIdleFrame : *mFrames.last() );
367 mRemainingLoops = loops;
368 mTimer.start( interval );
369 setPixmap( *mFrames.first() );
373 void AnimatedIcon::onTimerTick()
375 //assert( !mFrames.empty() );
376 if( ++mCurrentFrame > mFrames.size() )
378 if( mRemainingLoops != -1 )
380 if( --mRemainingLoops == 0 )
383 setPixmap( mIdleFrame ? *mIdleFrame : *mFrames.last() );
389 //assert( mCurrentFrame >= 1 && mCurrentFrame <= mFrames.size() );
390 setPixmap( *mFrames.at( mCurrentFrame - 1 ) );
394 /* SpinningIcon implementation */
396 SpinningIcon::SpinningIcon( QWidget *parent, bool noIdleFrame )
397 : AnimatedIcon( parent )
400 addFrame( QPixmap(), 0 );
402 addFrame( QPixmap( ":/util/wait0" ), 0 );
403 addFrame( QPixmap( ":/util/wait1" ) );
404 addFrame( QPixmap( ":/util/wait2" ) );
405 addFrame( QPixmap( ":/util/wait3" ) );
406 addFrame( QPixmap( ":/util/wait4" ) );
407 setScaledContents( true );
408 setFixedSize( 16, 16 );
411 SpinningIcon::~SpinningIcon()