Merge pull request #12 from NautiluX/split_traverser_selector

Enable shuffle mode
This commit is contained in:
Manuel Dewald
2020-02-14 23:16:58 +01:00
committed by GitHub
9 changed files with 286 additions and 90 deletions

View File

@@ -46,3 +46,16 @@ qmake ../src/slide.pro
make
sudo make install
```
### macOS
Prerequisite: brew
```
brew install qt5
brew install libexif
mkdir -p build
cd build
qmake ../src/slide.pro
make
```

View File

@@ -1,4 +1,5 @@
#include "imageselector.h"
#include "pathtraverser.h"
#include "mainwindow.h"
#include <QDirIterator>
#include <QTimer>
@@ -7,32 +8,32 @@
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <algorithm> // std::shuffle
#include <random> // std::default_random_engine
ImageSelector::ImageSelector(std::string path, bool recursive):
path(path),
recursive(recursive)
ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
pathTraverser(pathTraverser)
{
}
ImageSelector::~ImageSelector(){}
RandomImageSelector::RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
ImageSelector(pathTraverser)
{
srand (time(NULL));
}
std::string ImageSelector::getNextImage() const
RandomImageSelector::~RandomImageSelector(){}
std::string RandomImageSelector::getNextImage()
{
QDir directory(path.c_str());
std:: string filename;
try
{
if (recursive)
{
QStringList images = listImagesRecursive();
QStringList images = pathTraverser->getImages();
unsigned int selectedImage = selectRandom(images);
filename = images.at(selectedImage).toStdString();
}
else
{
QStringList images = directory.entryList(QStringList() << "*.jpg" << "*.JPG", QDir::Files);
unsigned int selectedImage = selectRandom(images);
filename = directory.filePath(images.at(selectedImage)).toStdString();
}
filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString());
}
catch(const std::string& err)
{
@@ -42,24 +43,51 @@ std::string ImageSelector::getNextImage() const
return filename;
}
unsigned int ImageSelector::selectRandom(const QStringList& images) const
unsigned int RandomImageSelector::selectRandom(const QStringList& images) const
{
std::cout << "images: " << images.size() << std::endl;
if (images.size() == 0)
{
throw std::string("No jpg images found in folder " + path);
throw std::string("No jpg images found in given folder");
}
return rand() % images.size();
}
QStringList ImageSelector::listImagesRecursive() const
ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
ImageSelector(pathTraverser),
current_image_shuffle(-1),
images()
{
QDirIterator it(QString(path.c_str()), QStringList() << "*.jpg" << "*.JPG", QDir::Files, QDirIterator::Subdirectories);
QStringList files;
while (it.hasNext())
{
files.append(it.next());
}
return files;
srand (time(NULL));
}
ShuffleImageSelector::~ShuffleImageSelector()
{
}
std::string ShuffleImageSelector::getNextImage()
{
if (images.size() == 0 || current_image_shuffle >= images.size())
{
current_image_shuffle = 0;
images = pathTraverser->getImages();
std::cout << "Shuffling " << images.size() << " images." << std::endl;
std::random_device rd;
std::mt19937 randomizer(rd());
std::shuffle(images.begin(), images.end(), randomizer);
}
if (images.size() == 0)
{
return "";
}
std::string filename = pathTraverser->getImagePath(images.at(current_image_shuffle).toStdString());
if(!QFileInfo::exists(QString(filename.c_str())))
{
std::cout << "file not found: " << filename << std::endl;
current_image_shuffle = images.size();
return getNextImage();
}
std::cout << "updating image: " << filename << std::endl;
current_image_shuffle = current_image_shuffle + 1;
return filename;
}

View File

@@ -2,20 +2,44 @@
#define IMAGESELECTOR_H
#include <iostream>
#include <memory>
#include <QStringList>
class MainWindow;
class PathTraverser;
class ImageSelector
{
public:
ImageSelector(std::string path, bool recursive);
std::string getNextImage() const;
ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~ImageSelector();
virtual std::string getNextImage() = 0;
protected:
std::unique_ptr<PathTraverser>& pathTraverser;
};
class RandomImageSelector : public ImageSelector
{
public:
RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~RandomImageSelector();
virtual std::string getNextImage();
private:
QStringList listImagesRecursive() const;
unsigned int selectRandom(const QStringList& images) const;
std::string path;
bool recursive;
};
class ShuffleImageSelector : public ImageSelector
{
public:
ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~ShuffleImageSelector();
virtual std::string getNextImage();
private:
int current_image_shuffle;
QStringList images;
};
#endif // IMAGESELECTOR_H

View File

@@ -4,12 +4,12 @@
#include <QDirIterator>
#include <QTimer>
#include <QApplication>
#include <QDir>
#include <iostream>
#include <memory>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeout, const ImageSelector& selector):
ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeout, std::unique_ptr<ImageSelector>& selector):
QObject::QObject(),
window(w),
timeout(timeout),
@@ -20,7 +20,7 @@ ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeout, const ImageSel
void ImageSwitcher::updateImage()
{
std::string filename(selector.getNextImage());
std::string filename(selector->getNextImage());
if (filename == "")
{
window.warn("No image found.");

View File

@@ -4,6 +4,7 @@
#include <QObject>
#include <QTimer>
#include <iostream>
#include <memory>
class MainWindow;
class ImageSelector;
@@ -11,7 +12,7 @@ class ImageSwitcher : public QObject
{
Q_OBJECT
public:
ImageSwitcher(MainWindow& w, unsigned int timeout, const ImageSelector& selector);
ImageSwitcher(MainWindow& w, unsigned int timeout, std::unique_ptr<ImageSelector>& selector);
void start();
public slots:
@@ -19,7 +20,7 @@ public slots:
private:
MainWindow& window;
unsigned int timeout;
const ImageSelector& selector;
std::unique_ptr<ImageSelector>& selector;
QTimer timer;
};

View File

@@ -1,6 +1,7 @@
#include "mainwindow.h"
#include "imageselector.h"
#include "imageswitcher.h"
#include "pathtraverser.h"
#include <QApplication>
#include <iostream>
#include <sys/file.h>
@@ -9,6 +10,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory>
void usage(std::string programName) {
std::cerr << "Usage: " << programName << " [-t rotation_seconds] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder -r" << std::endl;
@@ -24,7 +26,8 @@ int main(int argc, char *argv[])
MainWindow w;
int opt;
bool recursive = false;
while ((opt = getopt(argc, argv, "b:p:t:o:r")) != -1) {
bool shuffle = false;
while ((opt = getopt(argc, argv, "b:p:t:o:rs")) != -1) {
switch (opt) {
case 'p':
path = optarg;
@@ -41,20 +44,45 @@ int main(int argc, char *argv[])
case 'r':
recursive = true;
break;
case 's':
shuffle = true;
std::cout << "Shuffle mode is on." << std::endl;
break;
default: /* '?' */
usage(argv[0]);
return 1;
}
}
if (path.empty()) {
if (path.empty())
{
std::cout << "Error: Path expected." << std::endl;
usage(argv[0]);
return 1;
}
std::unique_ptr<PathTraverser> pathTraverser;
if (recursive)
{
pathTraverser = std::unique_ptr<PathTraverser>(new RecursivePathTraverser(path));
}
else
{
pathTraverser = std::unique_ptr<PathTraverser>(new DefaultPathTraverser(path));
}
std::unique_ptr<ImageSelector> selector;
if (shuffle)
{
selector = std::unique_ptr<ImageSelector>(new ShuffleImageSelector(pathTraverser));
}
else
{
selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser));
}
w.show();
ImageSelector selector(path, recursive);
ImageSwitcher switcher(w, rotationSeconds * 1000, selector);
switcher.start();
return a.exec();

55
src/pathtraverser.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "pathtraverser.h"
#include "mainwindow.h"
#include <QDirIterator>
#include <QTimer>
#include <QApplication>
#include <QDir>
#include <iostream>
#include <stdlib.h> /* srand, rand */
PathTraverser::PathTraverser(const std::string path):
path(path)
{}
PathTraverser::~PathTraverser() {}
RecursivePathTraverser::RecursivePathTraverser(const std::string path):
PathTraverser(path)
{}
RecursivePathTraverser::~RecursivePathTraverser() {}
QStringList RecursivePathTraverser::getImages() const
{
QDirIterator it(QString(path.c_str()), QStringList() << "*.jpg" << "*.JPG", QDir::Files, QDirIterator::Subdirectories);
QStringList files;
while (it.hasNext())
{
files.append(it.next());
}
return files;
}
const std::string RecursivePathTraverser::getImagePath(const std::string image) const
{
return image;
}
DefaultPathTraverser::DefaultPathTraverser(const std::string path):
PathTraverser(path),
directory(path.c_str())
{}
DefaultPathTraverser::~DefaultPathTraverser() {}
QStringList DefaultPathTraverser::getImages() const
{
return directory.entryList(QStringList() << "*.jpg" << "*.JPG", QDir::Files);
}
const std::string DefaultPathTraverser::getImagePath(const std::string image) const
{
return directory.filePath(QString(image.c_str())).toStdString();
}

41
src/pathtraverser.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef PATHTRAVERSER_H
#define PATHTRAVERSER_H
#include <iostream>
#include <QDir>
#include <QStringList>
class MainWindow;
class PathTraverser
{
public:
PathTraverser(const std::string path);
virtual ~PathTraverser();
virtual QStringList getImages() const = 0;
virtual const std::string getImagePath(const std::string image) const = 0;
protected:
const std::string path;
};
class RecursivePathTraverser : public PathTraverser
{
public:
RecursivePathTraverser(const std::string path);
virtual ~RecursivePathTraverser();
QStringList getImages() const;
virtual const std::string getImagePath(const std::string image) const;
};
class DefaultPathTraverser : public PathTraverser
{
public:
DefaultPathTraverser(const std::string path);
virtual ~DefaultPathTraverser();
QStringList getImages() const;
virtual const std::string getImagePath(const std::string image) const;
private:
QDir directory;
};
#endif // PATHTRAVERSER_H

View File

@@ -22,16 +22,22 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
mac: INCLUDEPATH += $$system(brew --prefix libexif)/include/
mac: QMAKE_LFLAGS += -L$$system(brew --prefix libexif)/lib
SOURCES += \
main.cpp \
mainwindow.cpp \
imageswitcher.cpp \
pathtraverser.cpp \
imageselector.cpp
HEADERS += \
mainwindow.h \
imageselector.h \
pathtraverser.h \
imageswitcher.h
FORMS += \