File indexing completed on 2024-05-12 16:28:28

0001 /* This file is part of the KDE project
0002    Copyright (C) 2010 KO GmbH <jos.van.den.oever@kogmbh.com>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 #ifndef DIRSLIDELOADER_H
0020 #define DIRSLIDELOADER_H
0021 
0022 #include "slideloader.h"
0023 #include <QFileSystemWatcher>
0024 #include <QDir>
0025 #include <QTimer>
0026 #include <QDateTime>
0027 #include <QDebug>
0028 
0029 class DirSlideLoader : public SlideLoader {
0030 private:
0031 Q_OBJECT
0032 
0033     class Slide {
0034     private:
0035         QImage image;
0036     public:
0037         int version;
0038         QDateTime lastModified;
0039         QString path;
0040         QImage scaledImage;
0041 
0042         Slide() :version(0) {}
0043         Slide(const Slide& s) { version = 0; *this = s; }
0044         explicit Slide(const QString& p) {
0045             path = p;
0046             lastModified = QFileInfo(path).lastModified();
0047             version = 1;
0048         }
0049         bool operator==(const Slide& slide) const {
0050             return slide.lastModified == lastModified
0051                 && slide.path == path;
0052         }
0053         bool operator!=(const Slide& slide) const {
0054             return !(slide == *this);
0055         }
0056         void operator=(const Slide& slide) {
0057             if (slide != *this) {
0058                 version++;
0059                 path = slide.path;
0060                 lastModified = slide.lastModified;
0061                 image = QImage();
0062                 scaledImage = QImage();
0063             }
0064         }
0065         const QImage& getImage() {
0066             if (image.isNull()) {
0067                 image.load(path);
0068             }
0069             return image;
0070         }
0071         QPixmap getPixmap(const QSize& maxsize) {
0072             QPixmap pixmap;
0073             const QImage& image = getImage();
0074             if (image.isNull()) return pixmap;
0075             if (image.width() > maxsize.width()) {
0076                 // scale to a smaller pixmap
0077                 if (scaledImage.width() != maxsize.width()) {
0078                     scaledImage = image.scaled(maxsize, Qt::KeepAspectRatio,
0079                                                Qt::SmoothTransformation);
0080                 }
0081                 pixmap = QPixmap::fromImage(scaledImage);
0082             } else {
0083                 pixmap = QPixmap::fromImage(image);
0084             }
0085             return pixmap; 
0086         }
0087     };
0088 
0089     QString slidedir;
0090     QString slideNamePattern;
0091     QFileSystemWatcher watcher;
0092     QTimer fileSystemDelay;
0093     QVector<Slide> slides;
0094     int numberofslides;
0095     QSize slidesize;
0096 
0097     QSize calculateSlideSize() {
0098         QSize size;
0099         for (int i=0; size.isEmpty() && i<slides.size(); ++i) {
0100             size = slides[i].getImage().size();
0101         }
0102         return size;
0103     }
0104 private Q_SLOTS:
0105     void slotDirectoryChanged(const QString &) {
0106         if (!fileSystemDelay.isActive()) {
0107             fileSystemDelay.setSingleShot(true);
0108             fileSystemDelay.start(100);
0109             connect(&fileSystemDelay, SIGNAL(timeout()),
0110                     this, SLOT(slotUpdateSlides()));
0111         }
0112     }
0113     void slotUpdateSlides() {
0114         QDir dir(slidedir);
0115         QVector<Slide> newslides;
0116         if (numberofslides >= 0) {
0117             newslides.resize(numberofslides);
0118             // loop over all files
0119             for (int slideNumber=0; slideNumber<numberofslides; ++slideNumber) {
0120                 QString name = slideNamePattern.arg(slideNumber);
0121                 if (dir.exists(name)) {
0122                     newslides[slideNumber] = dir.absoluteFilePath(name);
0123                 }
0124             }
0125         } else {
0126             QRegExp pattern(QString(slideNamePattern).replace("%1", "(\\d+)"));
0127             foreach (const QString& name, dir.entryList()) {
0128                 if (pattern.indexIn(name) != -1) {
0129                     bool ok;
0130                     int slideNumber = pattern.cap(1).toInt(&ok);
0131                     if (ok) {
0132                         if (newslides.size() <= slideNumber) {
0133                            newslides.resize(slideNumber+1);
0134                         }
0135                         newslides[slideNumber] = dir.absoluteFilePath(name);
0136                     }
0137                 }
0138             }
0139         }
0140         if (slides != newslides) {
0141             slides = newslides;
0142             emit slidesChanged();
0143         }
0144     }
0145 public:
0146     DirSlideLoader(QObject* parent = 0) :SlideLoader(parent), watcher(this) {
0147         numberofslides = -1;
0148         connect(&watcher, SIGNAL(directoryChanged(QString)),
0149                this, SLOT(slotDirectoryChanged(QString)));
0150     }
0151     void setSlideDir(const QString& path) {
0152         if (slidedir != path) {
0153             if (!slidedir.isEmpty()) {
0154                 watcher.removePath(slidedir);
0155             }
0156             watcher.addPath(path);
0157             slidedir = path;
0158             slotDirectoryChanged(path);
0159         }
0160     }
0161     void setSlideNamePattern(const QString& pattern) {
0162         slideNamePattern = pattern;
0163         slotDirectoryChanged(slidedir);
0164     }
0165     void setNumberOfSlides(int n) {
0166         numberofslides = n;
0167         slotUpdateSlides();
0168     }
0169     int numberOfSlides() {
0170         return (numberofslides >= 0) ?numberofslides :slides.size();
0171     }
0172     void setSlideSize(const QSize& size) {
0173         slidesize = size;
0174     }
0175     QSize slideSize() {
0176         if (slidesize.isEmpty()) {
0177             return calculateSlideSize();
0178         }
0179         return slidesize;
0180     }
0181     int slideVersion(int position) {
0182         return slides.value(position).version;
0183     }
0184     QPixmap loadSlide(int position, const QSize& maxsize) {
0185         if (position < 0 || position >= slides.size()) return QPixmap();
0186         return slides[position].getPixmap(maxsize);
0187     }
0188 };
0189 
0190 #endif