1 /*****************************************************************************
2 * customwidgets.cpp: Custom widgets
3 ****************************************************************************
4 * Copyright (C) 2006-2011 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, but not necessary */
37 #include <QWheelEvent>
39 #include <QApplication>
42 QFramelessButton::QFramelessButton( QWidget *parent )
43 : QPushButton( parent )
45 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
48 void QFramelessButton::paintEvent( QPaintEvent * )
50 QPainter painter( this );
51 QPixmap pix = icon().pixmap( size() );
52 QPoint pos( (width() - pix.width()) / 2, (height() - pix.height()) / 2 );
53 painter.drawPixmap( QRect( pos.x(), pos.y(), pix.width(), pix.height() ), pix );
56 QElidingLabel::QElidingLabel( const QString &s, Qt::TextElideMode mode, QWidget * parent )
57 : QLabel( s, parent ), elideMode( mode )
60 void QElidingLabel::setElideMode( Qt::TextElideMode mode )
66 void QElidingLabel::paintEvent( QPaintEvent * )
69 int space = frameWidth() + margin();
70 QRect r = rect().adjusted( space, space, -space, -space );
71 p.drawText( r, fontMetrics().elidedText( text(), elideMode, r.width() ), alignment() );
74 QString QVLCDebugLevelSpinBox::textFromValue( int v ) const
76 QString const texts[] = {
77 /* Note that min level 0 is 'errors' in Qt Ui
78 FIXME: fix debug levels accordingly to documentation */
87 return QString( "%1 (%2)" ).arg( v ).arg( texts[v] );
90 VLCQDial::VLCQDial( QWidget *parent ) : QDial( parent )
95 void VLCQDial::paintEvent( QPaintEvent *event )
97 QDial::paintEvent( event );
98 QPainter painter( this );
99 painter.setPen( QPen( palette().color( QPalette::WindowText ) ) );
100 float radius = 0.5 * 0.707106 * qMin( size().width(), size().height() );
101 painter.drawText( QRectF( rect().center().x() + radius,
102 rect().center().y() + radius,
105 0, QString::number( value() ), 0 );
109 /***************************************************************************
111 ***************************************************************************/
112 int qtKeyModifiersToVLC( QInputEvent* e )
114 int i_keyModifiers = 0;
115 if( e->modifiers() & Qt::ShiftModifier ) i_keyModifiers |= KEY_MODIFIER_SHIFT;
116 if( e->modifiers() & Qt::AltModifier ) i_keyModifiers |= KEY_MODIFIER_ALT;
117 if( e->modifiers() & Qt::ControlModifier ) i_keyModifiers |= KEY_MODIFIER_CTRL;
118 if( e->modifiers() & Qt::MetaModifier ) i_keyModifiers |= KEY_MODIFIER_META;
119 return i_keyModifiers;
128 static const vlc_qt_key_t keys[] =
130 { Qt::Key_Escape, KEY_ESC },
131 { Qt::Key_Tab, '\t', },
133 { Qt::Key_Backspace, '\b' },
134 { Qt::Key_Return, '\r' },
135 { Qt::Key_Enter, '\r' }, // numeric pad
136 { Qt::Key_Insert, KEY_INSERT },
137 { Qt::Key_Delete, KEY_DELETE },
142 { Qt::Key_Home, KEY_HOME },
143 { Qt::Key_End, KEY_END },
144 { Qt::Key_Left, KEY_LEFT },
145 { Qt::Key_Up, KEY_UP },
146 { Qt::Key_Right, KEY_RIGHT },
147 { Qt::Key_Down, KEY_DOWN },
148 { Qt::Key_PageUp, KEY_PAGEUP },
149 { Qt::Key_PageDown, KEY_PAGEDOWN },
156 // Qt::Key_ScrollLock
157 /* F1 - F35 - Qt goes to F35, VLC stops at F12 */
158 { Qt::Key_F1, KEY_F1 },
159 { Qt::Key_F2, KEY_F2 },
160 { Qt::Key_F3, KEY_F3 },
161 { Qt::Key_F4, KEY_F4 },
162 { Qt::Key_F5, KEY_F5 },
163 { Qt::Key_F6, KEY_F6 },
164 { Qt::Key_F7, KEY_F7 },
165 { Qt::Key_F8, KEY_F8 },
166 { Qt::Key_F9, KEY_F9 },
167 { Qt::Key_F10, KEY_F10 },
168 { Qt::Key_F11, KEY_F11 },
169 { Qt::Key_F12, KEY_F12 },
172 { Qt::Key_Menu, KEY_MENU },
176 // Qt::Key_Direction_L
177 // Qt::Key_Direction_R
181 // Qt::Key_SingleCandidate
182 // Qt::Key_MultipleCandidate
183 // Qt::Key_PreviousCandidate
184 // Qt::Key_Mode_switch
191 // Qt::Key_Hiragana_Katakana
194 // Qt::Key_Zenkaku_Hankaku
198 // Qt::Key_Kana_Shift
199 // Qt::Key_Eisu_Shift
200 // Qt::Key_Eisu_toggle
202 // Qt::Key_Hangul_Start
203 // Qt::Key_Hangul_End
204 // Qt::Key_Hangul_Hanja
205 // Qt::Key_Hangul_Jamo
206 // Qt::Key_Hangul_Romaja
207 // Qt::Key_Hangul_Jeonja
208 // Qt::Key_Hangul_Banja
209 // Qt::Key_Hangul_PreHanja
210 // Qt::Key_Hangul_PostHanja
211 // Qt::Key_Hangul_Special
212 // Qt::Key_Dead_Grave
213 // Qt::Key_Dead_Acute
214 // Qt::Key_Dead_Circumflex
215 // Qt::Key_Dead_Tilde
216 // Qt::Key_Dead_Macron
217 // Qt::Key_Dead_Breve
218 // Qt::Key_Dead_Abovedot
219 // Qt::Key_Dead_Diaeresis
220 // Qt::Key_Dead_Abovering
221 // Qt::Key_Dead_Doubleacute
222 // Qt::Key_Dead_Caron
223 // Qt::Key_Dead_Cedilla
224 // Qt::Key_Dead_Ogonek
226 // Qt::Key_Dead_Voiced_Sound
227 // Qt::Key_Dead_Semivoiced_Sound
228 // Qt::Key_Dead_Belowdot
231 { Qt::Key_Back, KEY_BROWSER_BACK },
232 { Qt::Key_Forward, KEY_BROWSER_FORWARD },
233 { Qt::Key_Stop, KEY_BROWSER_STOP },
234 { Qt::Key_Refresh, KEY_BROWSER_REFRESH },
235 { Qt::Key_VolumeDown, KEY_VOLUME_DOWN },
236 { Qt::Key_VolumeMute, KEY_VOLUME_MUTE },
237 { Qt::Key_VolumeUp, KEY_VOLUME_UP },
242 // Qt::Key_TrebleDown
243 { Qt::Key_MediaPlay, KEY_MEDIA_PLAY_PAUSE },
244 { Qt::Key_MediaStop, KEY_MEDIA_STOP },
245 { Qt::Key_MediaPrevious, KEY_MEDIA_PREV_TRACK },
246 { Qt::Key_MediaNext, KEY_MEDIA_NEXT_TRACK },
247 // Qt::Key_MediaRecord
248 { Qt::Key_HomePage, KEY_BROWSER_HOME },
249 { Qt::Key_Favorites, KEY_BROWSER_FAVORITES },
250 { Qt::Key_Search, KEY_BROWSER_SEARCH },
253 // Qt::Key_LaunchMail
254 // Qt::Key_LaunchMedia
255 /* Qt::Key_Launch0 through Qt::Key_LaunchF */
257 { Qt::Key_Reload, KEY_BROWSER_REFRESH },
260 static int keycmp( const void *a, const void *b )
262 const int *q = (const int *)a;
263 const vlc_qt_key_t *m = (const vlc_qt_key_t *)b;
268 int qtEventToVLCKey( QKeyEvent *e )
275 /* VLC and X11 use lowercase whereas Qt uses uppercase, this
276 * method should be equal to towlower in case of latin1 */
277 if( qtk >= 'A' && qtk <= 'Z' ) i_vlck = qtk+32;
278 else if( qtk >= 0xC0 && qtk <= 0xDE && qtk != 0xD7) i_vlck = qtk+32;
283 const vlc_qt_key_t *map;
285 map = (const vlc_qt_key_t *)
286 bsearch( &qtk, (const void *)keys, sizeof(keys)/sizeof(keys[0]),
287 sizeof(*keys), keycmp );
292 /* Handle modifiers */
293 i_vlck |= qtKeyModifiersToVLC( e );
297 int qtWheelEventToVLCKey( QWheelEvent *e )
300 /* Handle modifiers */
301 i_vlck |= qtKeyModifiersToVLC( e );
302 if ( e->delta() > 0 )
303 i_vlck |= KEY_MOUSEWHEELUP;
305 i_vlck |= KEY_MOUSEWHEELDOWN;
309 QString VLCKeyToString( unsigned val, bool locale )
311 char *base = vlc_keycode2str (val, locale);
313 return qtr( "Unset" );
315 QString r = qfu( base );
321 PixmapAnimator::PixmapAnimator( QWidget *parent, QList<QString> frames )
322 : QAbstractAnimation( parent ), current_frame( 0 )
324 foreach( QString name, frames )
325 pixmaps.append( new QPixmap( name ) );
326 currentPixmap = pixmaps.at( 0 );
327 setFps( frames.count() ); /* default to 1 sec loop */
331 void PixmapAnimator::updateCurrentTime( int msecs )
333 int i = msecs / interval;
334 if ( i >= pixmaps.count() ) i = pixmaps.count() - 1; /* roundings */
335 if ( i != current_frame )
338 currentPixmap = pixmaps.at( current_frame );
339 emit pixmapReady( *currentPixmap );
343 /* Animated Icon implementation */
344 SpinningIcon::SpinningIcon( QWidget *parent ) : QLabel( parent )
346 QList<QString> frames;
347 frames << ":/util/wait1";
348 frames << ":/util/wait2";
349 frames << ":/util/wait3";
350 frames << ":/util/wait4";
351 animator = new PixmapAnimator( this, frames );
352 CONNECT( animator, pixmapReady( const QPixmap & ), this, setPixmap( const QPixmap & ) );
353 CONNECT( animator, pixmapReady( const QPixmap & ), this, repaint() );
354 setScaledContents( true );
355 setFixedSize( 16, 16 );
356 animator->setCurrentTime( 0 );
359 QToolButtonExt::QToolButtonExt(QWidget *parent, int ms )
360 : QToolButton( parent ),
364 setAutoRepeat( true );
365 /* default to twice the doubleclick delay */
366 setAutoRepeatDelay( ( ms > 0 )? ms : 2 * QApplication::doubleClickInterval() );
367 setAutoRepeatInterval( 100 );
368 connect( this, SIGNAL(released()), this, SLOT(releasedSlot()) );
369 connect( this, SIGNAL(clicked()), this, SLOT(clickedSlot()) );
372 /* table illustrating the different scenarios and the events generated
373 * ====================
378 * clicked false }= short click
380 * released false = cancelled click (mouse released outside of button area,
381 * before long click delay kicks in)
384 * clicked true }= long click (multiple of these generated)
385 * released false = stop long click (mouse released / moved outside of
387 * (clicked false) = stop long click (additional event if mouse released
388 * inside of button area)
391 void QToolButtonExt::releasedSlot()
395 // we are beginning a long click
403 // we are stopping a long click
409 // we are generating a short click
416 void QToolButtonExt::clickedSlot()
420 else if( shortClick )
424 YesNoCheckBox::YesNoCheckBox( QWidget *parent ) : QCheckBox( parent )
428 QCheckBox::indicator:unchecked:hover,\
429 QCheckBox::indicator:unchecked {\
430 image: url(:/menu/quit);\
432 QCheckBox::indicator:checked:hover,\
433 QCheckBox::indicator:checked {\
434 image: url(:/valid);\