| 1 | /* umplayer, GUI front-end for mplayer.
|
|---|
| 2 | Copyright (C) 2010 Ori Rejwan
|
|---|
| 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 | This program is distributed in the hope that it will be useful,
|
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 12 | GNU General Public License for more details.
|
|---|
| 13 |
|
|---|
| 14 | You should have received a copy of the GNU General Public License
|
|---|
| 15 | along with this program; if not, write to the Free Software
|
|---|
| 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|---|
| 17 | */
|
|---|
| 18 |
|
|---|
| 19 | #include "panelseeker.h"
|
|---|
| 20 | #include <QPainter>
|
|---|
| 21 | #include <QSlider>
|
|---|
| 22 | #include <QMouseEvent>
|
|---|
| 23 | #include <QDebug>
|
|---|
| 24 | #include <QToolTip>
|
|---|
| 25 | #include "global.h"
|
|---|
| 26 | #include "preferences.h"
|
|---|
| 27 | #include "config.h"
|
|---|
| 28 | #include "helper.h"
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 | using namespace Global;
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 | PanelSeeker::PanelSeeker(QWidget *parent) :
|
|---|
| 35 | QAbstractSlider(parent), isPressed(false), leftRightMargin(5), bufferingPixShift(0),
|
|---|
| 36 | frozen(false), delayPeriod(100), frozenPeriod(500)
|
|---|
| 37 | {
|
|---|
| 38 | setAttribute(Qt::WA_StyledBackground, true);
|
|---|
| 39 | setAttribute(Qt::WA_Hover, true);
|
|---|
| 40 | setEnabled(false);
|
|---|
| 41 | setState(Stopped, true);
|
|---|
| 42 | setTracking(pref->update_while_seeking);
|
|---|
| 43 | connect(this, SIGNAL(valueChanged(int)), this, SLOT(moved(int)));
|
|---|
| 44 | setRange(0, 100);
|
|---|
| 45 | freezeTimer = new QTimer(this);
|
|---|
| 46 | freezeTimer->setInterval(frozenPeriod);
|
|---|
| 47 | freezeTimer->setSingleShot(true);
|
|---|
| 48 | dragDelayTimer = new QTimer(this);
|
|---|
| 49 | dragDelayTimer->setInterval(delayPeriod);
|
|---|
| 50 | dragDelayTimer->setSingleShot(true);
|
|---|
| 51 | connect(freezeTimer, SIGNAL(timeout()), this, SLOT(stopFreeze()));
|
|---|
| 52 | connect(dragDelayTimer, SIGNAL(timeout()), this, SLOT(goToSliderPosition()));
|
|---|
| 53 | }
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 | void PanelSeeker::paintEvent(QPaintEvent * e)
|
|---|
| 57 | {
|
|---|
| 58 | QPainter p(this);
|
|---|
| 59 |
|
|---|
| 60 | p.drawPixmap( leftRightMargin, (height()- leftPix.height())/2 , leftPix );
|
|---|
| 61 | p.drawTiledPixmap(QRect(leftRightMargin + leftPix.width(), (height()- centerPix.height())/2 ,width() - 2*leftRightMargin - leftPix.width() - rightPix.width(),centerPix.height()), centerPix);
|
|---|
| 62 |
|
|---|
| 63 | p.drawPixmap( width()-rightPix.width() - leftRightMargin , (height()- rightPix.height())/2 , rightPix);
|
|---|
| 64 |
|
|---|
| 65 | if(state.testFlag(Buffering))
|
|---|
| 66 | {
|
|---|
| 67 | p.drawTiledPixmap(QRect(leftRightMargin + leftPix.width(), (height()- bufferingPix.height())/2, width() - 2*leftRightMargin -leftPix.width() - rightPix.width(), bufferingPix.height()), bufferingPix, QPoint(bufferingPixShift, 0) );
|
|---|
| 68 | }
|
|---|
| 69 | else
|
|---|
| 70 | {
|
|---|
| 71 | if(isEnabled())
|
|---|
| 72 | {
|
|---|
| 73 | p.drawTiledPixmap(QRect(leftRightMargin + leftPix.width(), (height()- progressPix.height())/2 , knobRect.center().x() - leftRightMargin - leftPix.width(), progressPix.height()), progressPix);
|
|---|
| 74 | }
|
|---|
| 75 | p.drawPixmap(knobRect.toRect(), knobCurrentPix );
|
|---|
| 76 | }
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 | }
|
|---|
| 80 |
|
|---|
| 81 | void PanelSeeker::setKnobIcon( QPixmap pix )
|
|---|
| 82 | {
|
|---|
| 83 | int w = pix.width();
|
|---|
| 84 | int h = pix.height();
|
|---|
| 85 | knobPix.setPixmap(pix.copy(0, 0, w, h/4 ), MyIcon::Normal, MyIcon::Off);
|
|---|
| 86 | knobPix.setPixmap(pix.copy(0, h/4, w, h/4 ), MyIcon::MouseOver, MyIcon::Off);
|
|---|
| 87 | knobPix.setPixmap(pix.copy(0, h/2, w, h/4 ), MyIcon::MouseDown, MyIcon::Off);
|
|---|
| 88 | knobPix.setPixmap(pix.copy(0, 3*h/4, w, h/4 ), MyIcon::Disabled, MyIcon::Off);
|
|---|
| 89 | knobCurrentPix = knobPix.pixmap(MyIcon::Normal, MyIcon::Off);
|
|---|
| 90 | setSliderValue(minimum());
|
|---|
| 91 | setState(Normal, true);
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | void PanelSeeker::setSingleKnobIcon(QPixmap pix)
|
|---|
| 95 | {
|
|---|
| 96 | knobPix.setPixmap(pix, MyIcon::Normal, MyIcon::Off);
|
|---|
| 97 | knobPix.setPixmap(pix, MyIcon::MouseOver, MyIcon::Off);
|
|---|
| 98 | knobPix.setPixmap(pix, MyIcon::MouseDown, MyIcon::Off);
|
|---|
| 99 | knobPix.setPixmap(pix, MyIcon::Disabled, MyIcon::Off);
|
|---|
| 100 | setSliderValue(minimum());
|
|---|
| 101 | setState(Normal, true);
|
|---|
| 102 | }
|
|---|
| 103 |
|
|---|
| 104 | void PanelSeeker::mousePressEvent(QMouseEvent *m)
|
|---|
| 105 | {
|
|---|
| 106 | m->accept();
|
|---|
| 107 | setTracking(pref->update_while_seeking);
|
|---|
| 108 | if(m->button() == Qt::LeftButton)
|
|---|
| 109 | {
|
|---|
| 110 | QPointF pos = m->posF();
|
|---|
| 111 | if(knobRect.contains(pos))
|
|---|
| 112 | {
|
|---|
| 113 | isPressed = true;
|
|---|
| 114 | mousePressPos = pos;
|
|---|
| 115 | mousePressDifference = pos.x() - knobRect.center().x();
|
|---|
| 116 | setSliderDown(true);
|
|---|
| 117 | setState(Pressed, true);
|
|---|
| 118 | }
|
|---|
| 119 | else
|
|---|
| 120 | {
|
|---|
| 121 | isPressed = false;
|
|---|
| 122 | knobAdjust( m->posF().x() - knobRect.center().x(), true);
|
|---|
| 123 | }
|
|---|
| 124 | }
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | void PanelSeeker::mouseMoveEvent(QMouseEvent *m)
|
|---|
| 128 | {
|
|---|
| 129 | m->accept();
|
|---|
| 130 | if(isPressed)
|
|---|
| 131 | {
|
|---|
| 132 | knobAdjust(m->posF().x() - knobRect.center().x() - mousePressDifference );
|
|---|
| 133 | }
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | void PanelSeeker::mouseReleaseEvent(QMouseEvent *m)
|
|---|
| 137 | {
|
|---|
| 138 | setSliderDown(false);
|
|---|
| 139 | if(isPressed)
|
|---|
| 140 | {
|
|---|
| 141 | isPressed = false;
|
|---|
| 142 | setState(Pressed, false);
|
|---|
| 143 | frozen = true;
|
|---|
| 144 | freezeTimer->start();
|
|---|
| 145 | /*if(mousePressPos == m->pos())
|
|---|
| 146 | {
|
|---|
| 147 | knobAdjust( m->posF().x() - knobRect.center().x(), true);
|
|---|
| 148 | triggerAction(SliderMove);
|
|---|
| 149 | } */
|
|---|
| 150 | }
|
|---|
| 151 | }
|
|---|
| 152 |
|
|---|
| 153 | void PanelSeeker::resetKnob( bool start)
|
|---|
| 154 | {
|
|---|
| 155 | if(start)
|
|---|
| 156 | {
|
|---|
| 157 | moved(minimum());
|
|---|
| 158 | }
|
|---|
| 159 | else
|
|---|
| 160 | {
|
|---|
| 161 | moved(maximum());
|
|---|
| 162 | }
|
|---|
| 163 | }
|
|---|
| 164 |
|
|---|
| 165 | void PanelSeeker::knobAdjust(qreal x, bool isSetValue)
|
|---|
| 166 | {
|
|---|
| 167 | if(state.testFlag(Buffering)) return;
|
|---|
| 168 | qreal value = minimum() + (knobRect.center().x() - (leftRightMargin + knobCurrentPix.width()/2) +x ) * (maximum() - minimum()) /(width() - (leftRightMargin) - (leftRightMargin) - knobCurrentPix.width()) ;
|
|---|
| 169 | if(isSetValue)
|
|---|
| 170 | {
|
|---|
| 171 | frozen = true;
|
|---|
| 172 | if( state.testFlag(Stopped) ) value = minimum();
|
|---|
| 173 | setValue(qRound(value));
|
|---|
| 174 | freezeTimer->start();
|
|---|
| 175 | }
|
|---|
| 176 | else {
|
|---|
| 177 | if(hasTracking())
|
|---|
| 178 | {
|
|---|
| 179 | blockSignals(true);
|
|---|
| 180 | moved(qRound(value));
|
|---|
| 181 | blockSignals(false);
|
|---|
| 182 | emit sliderMoved(qRound(value));
|
|---|
| 183 | if(!dragDelayTimer->isActive())
|
|---|
| 184 | dragDelayTimer->start();
|
|---|
| 185 | }
|
|---|
| 186 | else
|
|---|
| 187 | moved(qRound(value));
|
|---|
| 188 | }
|
|---|
| 189 | }
|
|---|
| 190 |
|
|---|
| 191 | bool PanelSeeker::event(QEvent *e)
|
|---|
| 192 | {
|
|---|
| 193 | if(e->type() == QEvent::HoverMove || e->type() == QEvent::HoverEnter )
|
|---|
| 194 | {
|
|---|
| 195 | QHoverEvent* he = static_cast<QHoverEvent*>(e);
|
|---|
| 196 | if( knobRect.contains(he->pos()) )
|
|---|
| 197 | {
|
|---|
| 198 | setState(Hovered, true);
|
|---|
| 199 | }
|
|---|
| 200 | else
|
|---|
| 201 | {
|
|---|
| 202 | setState(Hovered, false);
|
|---|
| 203 | }
|
|---|
| 204 | }
|
|---|
| 205 | if(e->type() == QEvent::HoverLeave)
|
|---|
| 206 | {
|
|---|
| 207 | setState(Hovered, false);
|
|---|
| 208 | }
|
|---|
| 209 | return QAbstractSlider::event(e);
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | qreal PanelSeeker::valueForPos(int pos)
|
|---|
| 213 | {
|
|---|
| 214 | qreal value = (qreal)( pos - (leftRightMargin + knobCurrentPix.width()/2) ) * maximum() /(width() - (leftRightMargin) - (leftRightMargin) - knobCurrentPix.width());
|
|---|
| 215 | return value;
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 | void PanelSeeker::setState(State st, bool on)
|
|---|
| 219 | {
|
|---|
| 220 | if(on)
|
|---|
| 221 | {
|
|---|
| 222 | if(state.testFlag(st)) return;
|
|---|
| 223 | state |= st;
|
|---|
| 224 | }
|
|---|
| 225 | else
|
|---|
| 226 | {
|
|---|
| 227 | if(!state.testFlag(st)) return;
|
|---|
| 228 | state &= ~st;
|
|---|
| 229 | }
|
|---|
| 230 | if(state.testFlag(Buffering))
|
|---|
| 231 | {
|
|---|
| 232 | startTimer(100);
|
|---|
| 233 | }
|
|---|
| 234 | if(state.testFlag(Disabled))
|
|---|
| 235 | {
|
|---|
| 236 | knobCurrentPix = knobPix.pixmap(MyIcon::Disabled, MyIcon::Off);
|
|---|
| 237 | }
|
|---|
| 238 | else if(state.testFlag(Pressed))
|
|---|
| 239 | {
|
|---|
| 240 | knobCurrentPix = knobPix.pixmap(MyIcon::MouseDown, MyIcon::Off);
|
|---|
| 241 | }
|
|---|
| 242 | else if(state.testFlag(Hovered))
|
|---|
| 243 | {
|
|---|
| 244 | knobCurrentPix = knobPix.pixmap(MyIcon::MouseOver, MyIcon::Off);
|
|---|
| 245 | }
|
|---|
| 246 | else
|
|---|
| 247 | {
|
|---|
| 248 | knobCurrentPix = knobPix.pixmap(MyIcon::Normal, MyIcon::Off);
|
|---|
| 249 | }
|
|---|
| 250 | update();
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | void PanelSeeker::moved( int value)
|
|---|
| 254 | {
|
|---|
| 255 | if(value > maximum()) value = maximum();
|
|---|
| 256 | if(value < minimum()) value = minimum();
|
|---|
| 257 | if( state.testFlag(Stopped) ) value = minimum();
|
|---|
| 258 |
|
|---|
| 259 | qreal ratio = (qreal)(value - minimum())/(maximum()-minimum());
|
|---|
| 260 | qreal centerPixel = ratio*(width() - (leftRightMargin ) - (leftRightMargin) - knobCurrentPix.width());
|
|---|
| 261 | QSize size = knobPix.size(MyIcon::Normal, MyIcon::Off);
|
|---|
| 262 | knobRect = QRectF(QPointF(centerPixel + (leftRightMargin + knobCurrentPix.width()/2) - size.width()/2, ( height() - size.height())/2 ), size );
|
|---|
| 263 | setSliderPosition(value);
|
|---|
| 264 | update();
|
|---|
| 265 | }
|
|---|
| 266 |
|
|---|
| 267 | void PanelSeeker::resizeEvent(QResizeEvent *)
|
|---|
| 268 | {
|
|---|
| 269 | setSliderValue(value());
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | void PanelSeeker::changeEvent(QEvent *e)
|
|---|
| 273 | {
|
|---|
| 274 | if(e->type() == QEvent::EnabledChange)
|
|---|
| 275 | {
|
|---|
| 276 | if(isEnabled())
|
|---|
| 277 | {
|
|---|
| 278 | setState(Disabled, false);
|
|---|
| 279 | setState(Stopped, false);
|
|---|
| 280 |
|
|---|
| 281 | }
|
|---|
| 282 | else
|
|---|
| 283 | {
|
|---|
| 284 | setState(Disabled, true);
|
|---|
| 285 | setState(Stopped, true);
|
|---|
| 286 | }
|
|---|
| 287 | }
|
|---|
| 288 | }
|
|---|
| 289 |
|
|---|
| 290 | void PanelSeeker::timerEvent(QTimerEvent *t)
|
|---|
| 291 | {
|
|---|
| 292 | if(!state.testFlag(Buffering))
|
|---|
| 293 | {
|
|---|
| 294 | killTimer(t->timerId());
|
|---|
| 295 | bufferingPixShift = 0;
|
|---|
| 296 | }
|
|---|
| 297 | else
|
|---|
| 298 | {
|
|---|
| 299 | bufferingPixShift +=1;
|
|---|
| 300 | bufferingPixShift = qRound(bufferingPixShift)% bufferingPix.width();
|
|---|
| 301 | update();
|
|---|
| 302 | }
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | void PanelSeeker::setSliderValue(int value)
|
|---|
| 306 | {
|
|---|
| 307 | if(!isPressed && !frozen)
|
|---|
| 308 | {
|
|---|
| 309 | blockSignals(true);
|
|---|
| 310 | moved(value);
|
|---|
| 311 | setValue(value);
|
|---|
| 312 | blockSignals(false);
|
|---|
| 313 | }
|
|---|
| 314 | }
|
|---|
| 315 |
|
|---|
| 316 | void PanelSeeker::stopFreeze()
|
|---|
| 317 | {
|
|---|
| 318 | frozen = false;
|
|---|
| 319 | update();
|
|---|
| 320 | }
|
|---|
| 321 |
|
|---|
| 322 | void PanelSeeker::goToSliderPosition()
|
|---|
| 323 | {
|
|---|
| 324 | emit valueChanged(sliderPosition());
|
|---|
| 325 | dragDelayTimer->stop();
|
|---|
| 326 | }
|
|---|
| 327 |
|
|---|
| 328 | void PanelSeeker::wheelEvent(QWheelEvent *e)
|
|---|
| 329 | {
|
|---|
| 330 | blockSignals(true);
|
|---|
| 331 | QAbstractSlider::wheelEvent(e);
|
|---|
| 332 | moved(value());
|
|---|
| 333 | blockSignals(false);
|
|---|
| 334 | frozen = true;
|
|---|
| 335 | freezeTimer->start();
|
|---|
| 336 | if(!dragDelayTimer->isActive())
|
|---|
| 337 | dragDelayTimer->start();
|
|---|
| 338 |
|
|---|
| 339 | }
|
|---|
| 340 |
|
|---|
| 341 | #include "moc_panelseeker.cpp"
|
|---|