Merge pull request #12 from NautiluX/split_traverser_selector
Enable shuffle mode
This commit is contained in:
13
README.md
13
README.md
@@ -46,3 +46,16 @@ qmake ../src/slide.pro
|
|||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
Prerequisite: brew
|
||||||
|
|
||||||
|
```
|
||||||
|
brew install qt5
|
||||||
|
brew install libexif
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
qmake ../src/slide.pro
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "imageselector.h"
|
#include "imageselector.h"
|
||||||
|
#include "pathtraverser.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -7,59 +8,86 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdlib.h> /* srand, rand */
|
#include <stdlib.h> /* srand, rand */
|
||||||
#include <time.h> /* time */
|
#include <time.h> /* time */
|
||||||
|
#include <algorithm> // std::shuffle
|
||||||
|
#include <random> // std::default_random_engine
|
||||||
|
|
||||||
ImageSelector::ImageSelector(std::string path, bool recursive):
|
ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
|
||||||
path(path),
|
pathTraverser(pathTraverser)
|
||||||
recursive(recursive)
|
|
||||||
{
|
{
|
||||||
srand (time(NULL));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ImageSelector::getNextImage() const
|
ImageSelector::~ImageSelector(){}
|
||||||
|
|
||||||
|
RandomImageSelector::RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
|
||||||
|
ImageSelector(pathTraverser)
|
||||||
{
|
{
|
||||||
QDir directory(path.c_str());
|
srand (time(NULL));
|
||||||
std:: string filename;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (recursive)
|
|
||||||
{
|
|
||||||
QStringList images = listImagesRecursive();
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(const std::string& err)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: " << err << std::endl;
|
|
||||||
}
|
|
||||||
std::cout << "updating image: " << filename << std::endl;
|
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ImageSelector::selectRandom(const QStringList& images) const
|
RandomImageSelector::~RandomImageSelector(){}
|
||||||
|
|
||||||
|
std::string RandomImageSelector::getNextImage()
|
||||||
{
|
{
|
||||||
std::cout << "images: " << images.size() << std::endl;
|
std:: string filename;
|
||||||
if (images.size() == 0)
|
try
|
||||||
{
|
{
|
||||||
throw std::string("No jpg images found in folder " + path);
|
QStringList images = pathTraverser->getImages();
|
||||||
}
|
unsigned int selectedImage = selectRandom(images);
|
||||||
return rand() % images.size();
|
filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString());
|
||||||
|
}
|
||||||
|
catch(const std::string& err)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: " << err << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "updating image: " << filename << std::endl;
|
||||||
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int RandomImageSelector::selectRandom(const QStringList& images) const
|
||||||
QStringList ImageSelector::listImagesRecursive() const
|
|
||||||
{
|
{
|
||||||
QDirIterator it(QString(path.c_str()), QStringList() << "*.jpg" << "*.JPG", QDir::Files, QDirIterator::Subdirectories);
|
std::cout << "images: " << images.size() << std::endl;
|
||||||
QStringList files;
|
if (images.size() == 0)
|
||||||
while (it.hasNext())
|
{
|
||||||
{
|
throw std::string("No jpg images found in given folder");
|
||||||
files.append(it.next());
|
}
|
||||||
}
|
return rand() % images.size();
|
||||||
return files;
|
}
|
||||||
|
|
||||||
|
ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
|
||||||
|
ImageSelector(pathTraverser),
|
||||||
|
current_image_shuffle(-1),
|
||||||
|
images()
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,44 @@
|
|||||||
#define IMAGESELECTOR_H
|
#define IMAGESELECTOR_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
class PathTraverser;
|
||||||
|
|
||||||
class ImageSelector
|
class ImageSelector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageSelector(std::string path, bool recursive);
|
ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
|
||||||
std::string getNextImage() const;
|
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:
|
private:
|
||||||
QStringList listImagesRecursive() const;
|
|
||||||
unsigned int selectRandom(const QStringList& images) 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
|
#endif // IMAGESELECTOR_H
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <stdlib.h> /* srand, rand */
|
#include <stdlib.h> /* srand, rand */
|
||||||
#include <time.h> /* time */
|
#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(),
|
QObject::QObject(),
|
||||||
window(w),
|
window(w),
|
||||||
timeout(timeout),
|
timeout(timeout),
|
||||||
@@ -20,7 +20,7 @@ ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeout, const ImageSel
|
|||||||
|
|
||||||
void ImageSwitcher::updateImage()
|
void ImageSwitcher::updateImage()
|
||||||
{
|
{
|
||||||
std::string filename(selector.getNextImage());
|
std::string filename(selector->getNextImage());
|
||||||
if (filename == "")
|
if (filename == "")
|
||||||
{
|
{
|
||||||
window.warn("No image found.");
|
window.warn("No image found.");
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class ImageSelector;
|
class ImageSelector;
|
||||||
@@ -11,7 +12,7 @@ class ImageSwitcher : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ImageSwitcher(MainWindow& w, unsigned int timeout, const ImageSelector& selector);
|
ImageSwitcher(MainWindow& w, unsigned int timeout, std::unique_ptr<ImageSelector>& selector);
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -19,7 +20,7 @@ public slots:
|
|||||||
private:
|
private:
|
||||||
MainWindow& window;
|
MainWindow& window;
|
||||||
unsigned int timeout;
|
unsigned int timeout;
|
||||||
const ImageSelector& selector;
|
std::unique_ptr<ImageSelector>& selector;
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
100
src/main.cpp
100
src/main.cpp
@@ -1,6 +1,7 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "imageselector.h"
|
#include "imageselector.h"
|
||||||
#include "imageswitcher.h"
|
#include "imageswitcher.h"
|
||||||
|
#include "pathtraverser.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
void usage(std::string programName) {
|
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;
|
std::cerr << "Usage: " << programName << " [-t rotation_seconds] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder -r" << std::endl;
|
||||||
@@ -16,46 +18,72 @@ void usage(std::string programName) {
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
unsigned int rotationSeconds = 30;
|
unsigned int rotationSeconds = 30;
|
||||||
std::string path = "";
|
std::string path = "";
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
int opt;
|
int opt;
|
||||||
bool recursive = false;
|
bool recursive = false;
|
||||||
while ((opt = getopt(argc, argv, "b:p:t:o:r")) != -1) {
|
bool shuffle = false;
|
||||||
switch (opt) {
|
while ((opt = getopt(argc, argv, "b:p:t:o:rs")) != -1) {
|
||||||
case 'p':
|
switch (opt) {
|
||||||
path = optarg;
|
case 'p':
|
||||||
break;
|
path = optarg;
|
||||||
case 't':
|
break;
|
||||||
rotationSeconds = atoi(optarg);
|
case 't':
|
||||||
break;
|
rotationSeconds = atoi(optarg);
|
||||||
case 'b':
|
break;
|
||||||
w.setBlurRadius(atoi(optarg));
|
case 'b':
|
||||||
break;
|
w.setBlurRadius(atoi(optarg));
|
||||||
case 'o':
|
break;
|
||||||
w.setBackgroundOpacity(atoi(optarg));
|
case 'o':
|
||||||
break;
|
w.setBackgroundOpacity(atoi(optarg));
|
||||||
case 'r':
|
break;
|
||||||
recursive = true;
|
case 'r':
|
||||||
break;
|
recursive = true;
|
||||||
default: /* '?' */
|
break;
|
||||||
usage(argv[0]);
|
case 's':
|
||||||
return 1;
|
shuffle = true;
|
||||||
}
|
std::cout << "Shuffle mode is on." << std::endl;
|
||||||
}
|
break;
|
||||||
|
default: /* '?' */
|
||||||
if (path.empty()) {
|
|
||||||
std::cout << "Error: Path expected." << std::endl;
|
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
w.show();
|
}
|
||||||
|
|
||||||
ImageSelector selector(path, recursive);
|
if (path.empty())
|
||||||
ImageSwitcher switcher(w, rotationSeconds * 1000, selector);
|
{
|
||||||
switcher.start();
|
std::cout << "Error: Path expected." << std::endl;
|
||||||
return a.exec();
|
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();
|
||||||
|
|
||||||
|
ImageSwitcher switcher(w, rotationSeconds * 1000, selector);
|
||||||
|
switcher.start();
|
||||||
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
55
src/pathtraverser.cpp
Normal file
55
src/pathtraverser.cpp
Normal 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
41
src/pathtraverser.h
Normal 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
|
||||||
@@ -22,16 +22,22 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
# 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
|
#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 += \
|
SOURCES += \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp \
|
mainwindow.cpp \
|
||||||
imageswitcher.cpp \
|
imageswitcher.cpp \
|
||||||
|
pathtraverser.cpp \
|
||||||
imageselector.cpp
|
imageselector.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
imageselector.h \
|
imageselector.h \
|
||||||
|
pathtraverser.h \
|
||||||
imageswitcher.h
|
imageswitcher.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|||||||
Reference in New Issue
Block a user