/* * Copyright (C) 2018 by J-P Nurmi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "slideshow.h" #include #include #include #include #include #define HASQT5_11 (QT_VERSION >= QT_VERSION_CHECK(5,11,0)) namespace OCC { static const int Spacing = 6; static const int SlideDuration = 1000; static const int SlideDistance = 400; SlideShow::SlideShow(QWidget *parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); } void SlideShow::addSlide(const QPixmap &pixmap, const QString &label) { _labels += label; _pixmaps += pixmap; updateGeometry(); } bool SlideShow::isActive() const { return _timer.isActive(); } int SlideShow::interval() const { return _interval; } void SlideShow::setInterval(int interval) { if (_interval == interval) return; _interval = interval; maybeRestartTimer(); } int SlideShow::currentSlide() const { return _currentIndex; } void SlideShow::setCurrentSlide(int index) { if (_currentIndex == index) return; if (!_animation) { _animation = new QVariantAnimation(this); _animation->setDuration(SlideDuration); _animation->setEasingCurve(QEasingCurve::OutCubic); _animation->setStartValue(static_cast(_currentIndex)); connect(_animation.data(), SIGNAL(valueChanged(QVariant)), this, SLOT(update())); } _animation->setEndValue(static_cast(index)); _animation->start(QAbstractAnimation::DeleteWhenStopped); _reverse = index < _currentIndex; _currentIndex = index; maybeRestartTimer(); update(); emit currentSlideChanged(index); } QSize SlideShow::sizeHint() const { QFontMetrics fm = fontMetrics(); QSize labelSize(0, fm.height()); for (const QString &label : _labels) { #if (HASQT5_11) labelSize.setWidth(std::max(fm.horizontalAdvance(label), labelSize.width())); #else labelSize.setWidth(std::max(fm.width(label), labelSize.width())); #endif } QSize pixmapSize; for (const QPixmap &pixmap : _pixmaps) { pixmapSize.setWidth(std::max(pixmap.width(), pixmapSize.width())); pixmapSize.setHeight(std::max(pixmap.height(), pixmapSize.height())); } return { std::max(labelSize.width(), pixmapSize.width()), labelSize.height() + Spacing + pixmapSize.height() }; } void SlideShow::startShow(int interval) { if (interval > 0) _interval = interval; _timer.start(_interval, this); } void SlideShow::stopShow() { _timer.stop(); } void SlideShow::nextSlide() { setCurrentSlide((_currentIndex + 1) % _labels.count()); _reverse = false; } void SlideShow::prevSlide() { setCurrentSlide((_currentIndex > 0 ? _currentIndex : _labels.count()) - 1); _reverse = true; } void SlideShow::reset() { stopShow(); _pixmaps.clear(); _labels.clear(); updateGeometry(); update(); } void SlideShow::mousePressEvent(QMouseEvent *event) { _pressPoint = event->pos(); } void SlideShow::mouseReleaseEvent(QMouseEvent *event) { if (!_animation && QLineF(_pressPoint, event->pos()).length() < QGuiApplication::styleHints()->startDragDistance()) emit clicked(); } void SlideShow::paintEvent(QPaintEvent *) { QPainter painter(this); if (_animation) { int from = _animation->startValue().toInt(); int to = _animation->endValue().toInt(); qreal progress = _animation->easingCurve().valueForProgress(_animation->currentTime() / static_cast(_animation->duration())); painter.save(); painter.setOpacity(1.0 - progress); painter.translate(progress * (_reverse ? SlideDistance : -SlideDistance), 0); drawSlide(&painter, from); painter.restore(); painter.setOpacity(progress); painter.translate((1.0 - progress) * (_reverse ? -SlideDistance : SlideDistance), 0); drawSlide(&painter, to); } else { drawSlide(&painter, _currentIndex); } } void SlideShow::timerEvent(QTimerEvent *event) { if (event->timerId() == _timer.timerId()) nextSlide(); } void SlideShow::maybeRestartTimer() { if (!isActive()) return; startShow(); } void SlideShow::drawSlide(QPainter *painter, int index) { QString label = _labels.value(index); QRect labelRect = style()->itemTextRect(fontMetrics(), rect(), Qt::AlignBottom | Qt::AlignHCenter, isEnabled(), label); style()->drawItemText(painter, labelRect, Qt::AlignCenter, palette(), isEnabled(), label, QPalette::WindowText); QPixmap pixmap = _pixmaps.value(index); QRect pixmapRect = style()->itemPixmapRect(QRect(0, 0, width(), labelRect.top() - Spacing), Qt::AlignCenter, pixmap); style()->drawItemPixmap(painter, pixmapRect, Qt::AlignCenter, pixmap); } } // namespace OCC