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