- Change the object ownership semantics to take ownership of unique_ptr's rather than references

- Add helper functions for setting up config
- Add support for dynamically updating more config options (path related ones in particular)
This commit is contained in:
Alfred Reynolds
2021-08-11 14:01:18 +12:00
parent 8ac20f4b43
commit 24a4a07593
7 changed files with 121 additions and 81 deletions

View File

@@ -12,8 +12,8 @@
#include <algorithm> // std::shuffle #include <algorithm> // std::shuffle
#include <random> // std::default_random_engine #include <random> // std::default_random_engine
ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser): ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverserIn):
pathTraverser(pathTraverser) pathTraverser(std::move(pathTraverserIn))
{ {
} }

View File

@@ -21,7 +21,7 @@ protected:
ImageDetails populateImageDetails(const std::string&filename, const ImageDisplayOptions &baseOptions); ImageDetails populateImageDetails(const std::string&filename, const ImageDisplayOptions &baseOptions);
bool imageValidForAspect(const ImageDetails& imageDetails); bool imageValidForAspect(const ImageDetails& imageDetails);
bool imageMatchesFilter(const ImageDetails& imageDetails); bool imageMatchesFilter(const ImageDetails& imageDetails);
std::unique_ptr<PathTraverser>& pathTraverser; std::unique_ptr<PathTraverser> pathTraverser;
bool debugMode = false; bool debugMode = false;
}; };

View File

@@ -9,11 +9,11 @@
#include <stdlib.h> /* srand, rand */ #include <stdlib.h> /* srand, rand */
#include <time.h> /* time */ #include <time.h> /* time */
ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeoutMsec, std::shared_ptr<ImageSelector>& selector): ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeoutMsec, std::unique_ptr<ImageSelector>& selector):
QObject::QObject(), QObject::QObject(),
window(w), window(w),
timeout(timeoutMsec), timeout(timeoutMsec),
selector(selector), selector(std::move(selector)),
timer(this), timer(this),
timerNoContent(this) timerNoContent(this)
{ {
@@ -23,7 +23,7 @@ void ImageSwitcher::updateImage()
{ {
if(reloadConfigIfNeeded) if(reloadConfigIfNeeded)
{ {
reloadConfigIfNeeded(); reloadConfigIfNeeded(window, this, selector.get());
} }
ImageDetails imageDetails = selector->getNextImage(window.getBaseOptions()); ImageDetails imageDetails = selector->getNextImage(window.getBaseOptions());
if (imageDetails.filename == "") if (imageDetails.filename == "")
@@ -52,7 +52,7 @@ void ImageSwitcher::scheduleImageUpdate()
QTimer::singleShot(100, this, SLOT(updateImage())); QTimer::singleShot(100, this, SLOT(updateImage()));
} }
void ImageSwitcher::setConfigFileReloader(std::function<void()> reloadConfigIfNeededIn) void ImageSwitcher::setConfigFileReloader(std::function<void(MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector)> reloadConfigIfNeededIn)
{ {
reloadConfigIfNeeded = reloadConfigIfNeededIn; reloadConfigIfNeeded = reloadConfigIfNeededIn;
} }
@@ -62,3 +62,8 @@ void ImageSwitcher::setRotationTime(unsigned int timeoutMsecIn)
timeout = timeoutMsecIn; timeout = timeoutMsecIn;
timer.start(timeout); timer.start(timeout);
} }
void ImageSwitcher::setImageSelector(std::unique_ptr<ImageSelector>& selectorIn)
{
selector = std::move(selectorIn);
}

View File

@@ -6,29 +6,30 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include "imageselector.h"
class MainWindow; class MainWindow;
class ImageSelector;
class ImageSwitcher : public QObject class ImageSwitcher : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
ImageSwitcher(MainWindow& w, unsigned int timeoutMsec, std::shared_ptr<ImageSelector>& selector); ImageSwitcher(MainWindow& w, unsigned int timeoutMsec, std::unique_ptr<ImageSelector>& selector);
void start(); void start();
void scheduleImageUpdate(); void scheduleImageUpdate();
void setConfigFileReloader(std::function<void()> reloadConfigIfNeededIn); void setConfigFileReloader(std::function<void(MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector)> reloadConfigIfNeededIn);
void setRotationTime(unsigned int timeoutMsec); void setRotationTime(unsigned int timeoutMsec);
void setImageSelector(std::unique_ptr<ImageSelector>& selector);
public slots: public slots:
void updateImage(); void updateImage();
private: private:
MainWindow& window; MainWindow& window;
unsigned int timeout; unsigned int timeout;
std::shared_ptr<ImageSelector>& selector; std::unique_ptr<ImageSelector> selector;
QTimer timer; QTimer timer;
const unsigned int timeoutNoContent = 5 * 1000; // 5 sec const unsigned int timeoutNoContent = 5 * 1000; // 5 sec
QTimer timerNoContent; QTimer timerNoContent;
std::function<void()> reloadConfigIfNeeded; std::function<void(MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector)> reloadConfigIfNeeded;
}; };
#endif // IMAGESWITCHER_H #endif // IMAGESWITCHER_H

View File

@@ -24,22 +24,34 @@ void usage(std::string programName) {
} }
struct Config { struct Config {
std::string path = ""; public:
std::string configPath = ""; std::string path = "";
unsigned int rotationSeconds = 30; std::string configPath = "";
int blurRadius = -1; unsigned int rotationSeconds = 30;
int backgroundOpacity = -1; int blurRadius = -1;
bool recursive = false; int backgroundOpacity = -1;
bool shuffle = false; bool recursive = false;
bool sorted = false; bool shuffle = false;
bool debugMode = false; bool sorted = false;
ImageDisplayOptions baseDisplayOptions; bool debugMode = false;
std::string valid_aspects = "alpm"; // all, landscape, portait ImageDisplayOptions baseDisplayOptions;
std::string overlay = ""; static const std::string valid_aspects;
std::string imageList = ""; // comma delimited list of images to show std::string overlay = "";
QDateTime loadTime; std::string imageList = ""; // comma delimited list of images to show
QDateTime loadTime;
public:
bool PathOptionsChanged(Config &other) {
if ( other.recursive != recursive || other.shuffle != shuffle
|| other.sorted != sorted)
return true;
if ( other.path != path || other.imageList != imageList )
return true;
return false;
}
}; };
const std::string Config::valid_aspects = "alpm"; // all, landscape, portait, monitor
ImageAspect parseAspectFromString(char aspect) { ImageAspect parseAspectFromString(char aspect) {
switch(aspect) switch(aspect)
{ {
@@ -243,7 +255,58 @@ bool parseCommandLine(Config &appConfig, int argc, char *argv[]) {
return true; return true;
} }
void ReloadConfigIfNeeded(Config &appConfig, MainWindow &w, ImageSwitcher &switcher, std::shared_ptr<ImageSelector> &selector) void ConfigureWindowFromSettings(MainWindow &w, const Config &appConfig)
{
if (appConfig.blurRadius>= 0)
{
w.setBlurRadius(appConfig.blurRadius);
}
if (appConfig.backgroundOpacity>= 0)
{
w.setBackgroundOpacity(appConfig.backgroundOpacity);
}
std::unique_ptr<Overlay> o = std::unique_ptr<Overlay>(new Overlay(appConfig.overlay));
o->setDebugMode(appConfig.debugMode);
w.setDebugMode(appConfig.debugMode);
w.setOverlay(o);
w.setBaseOptions(appConfig.baseDisplayOptions);
}
std::unique_ptr<ImageSelector> GetSelectorForConfig(const Config &appConfig)
{
std::unique_ptr<PathTraverser> pathTraverser;
if (!appConfig.imageList.empty())
{
pathTraverser = std::unique_ptr<PathTraverser>(new ImageListPathTraverser(appConfig.imageList, appConfig.debugMode));
}
else if (appConfig.recursive)
{
pathTraverser = std::unique_ptr<PathTraverser>(new RecursivePathTraverser(appConfig.path, appConfig.debugMode));
}
else
{
pathTraverser = std::unique_ptr<PathTraverser>(new DefaultPathTraverser(appConfig.path, appConfig.debugMode));
}
std::unique_ptr<ImageSelector> selector;
if (appConfig.sorted)
{
selector = std::unique_ptr<ImageSelector>(new SortedImageSelector(pathTraverser));
}
else if (appConfig.shuffle)
{
selector = std::unique_ptr<ImageSelector>(new ShuffleImageSelector(pathTraverser));
}
else
{
selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser));
}
return selector;
}
void ReloadConfigIfNeeded(Config &appConfig, MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector)
{ {
QString jsonFile = getConfigFilePath(appConfig.configPath); QString jsonFile = getConfigFilePath(appConfig.configPath);
QDir directory; QDir directory;
@@ -254,13 +317,21 @@ void ReloadConfigIfNeeded(Config &appConfig, MainWindow &w, ImageSwitcher &switc
if(appConfig.loadTime < QFileInfo(jsonFile).lastModified()) if(appConfig.loadTime < QFileInfo(jsonFile).lastModified())
{ {
const std::string oldPath = appConfig.path;
const std::string oldImageList = appConfig.imageList;
Config oldConfig = appConfig;
appConfig = loadConfiguration(appConfig); appConfig = loadConfiguration(appConfig);
w.setBaseOptions(appConfig.baseDisplayOptions);
w.setDebugMode(appConfig.debugMode); ConfigureWindowFromSettings(w, appConfig);
if(appConfig.PathOptionsChanged(oldConfig))
{
std::unique_ptr<ImageSelector> selector = GetSelectorForConfig(appConfig);
switcher->setImageSelector(selector);
}
selector->setDebugMode(appConfig.debugMode); selector->setDebugMode(appConfig.debugMode);
//Overlay o(appConfig.overlay); switcher->setRotationTime(appConfig.rotationSeconds * 1000);
//w.setOverlay(&o);
switcher.setRotationTime(appConfig.rotationSeconds * 1000);
} }
} }
@@ -268,7 +339,6 @@ int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w;
Config commandLineAppConfig; Config commandLineAppConfig;
if (!parseCommandLine(commandLineAppConfig, argc, argv)) if (!parseCommandLine(commandLineAppConfig, argc, argv))
{ {
@@ -285,58 +355,22 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
if (appConfig.blurRadius>= 0)
{
w.setBlurRadius(appConfig.blurRadius);
}
if (appConfig.backgroundOpacity>= 0)
{
w.setBackgroundOpacity(appConfig.backgroundOpacity);
}
std::unique_ptr<PathTraverser> pathTraverser;
if (!appConfig.imageList.empty())
{
pathTraverser = std::unique_ptr<PathTraverser>(new ImageListPathTraverser(appConfig.imageList, appConfig.debugMode));
}
else if (appConfig.recursive)
{
pathTraverser = std::unique_ptr<PathTraverser>(new RecursivePathTraverser(appConfig.path, appConfig.debugMode));
}
else
{
pathTraverser = std::unique_ptr<PathTraverser>(new DefaultPathTraverser(appConfig.path, appConfig.debugMode));
}
std::shared_ptr<ImageSelector> selector;
if (appConfig.sorted)
{
selector = std::shared_ptr<ImageSelector>(new SortedImageSelector(pathTraverser));
}
else if (appConfig.shuffle)
{
selector = std::shared_ptr<ImageSelector>(new ShuffleImageSelector(pathTraverser));
}
else
{
selector = std::shared_ptr<ImageSelector>(new RandomImageSelector(pathTraverser));
}
selector->setDebugMode(appConfig.debugMode);
if(appConfig.debugMode) if(appConfig.debugMode)
{ {
std::cout << "Rotation Time: " << appConfig.rotationSeconds << std::endl; std::cout << "Rotation Time: " << appConfig.rotationSeconds << std::endl;
std::cout << "Overlay input: " << appConfig.overlay << std::endl; std::cout << "Overlay input: " << appConfig.overlay << std::endl;
} }
Overlay o(appConfig.overlay);
o.setDebugMode(appConfig.debugMode); MainWindow w;
w.setOverlay(&o); ConfigureWindowFromSettings(w, appConfig);
w.setBaseOptions(appConfig.baseDisplayOptions);
w.show(); w.show();
std::unique_ptr<ImageSelector> selector = GetSelectorForConfig(appConfig);
selector->setDebugMode(appConfig.debugMode);
ImageSwitcher switcher(w, appConfig.rotationSeconds * 1000, selector); ImageSwitcher switcher(w, appConfig.rotationSeconds * 1000, selector);
w.setImageSwitcher(&switcher); w.setImageSwitcher(&switcher);
std::function<void()> reloader = [&appConfig, &w, &switcher, &selector]() { ReloadConfigIfNeeded(appConfig, w, switcher, selector); }; std::function<void(MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector)> reloader = [&appConfig](MainWindow &w, ImageSwitcher *switcher, ImageSelector *selector) { ReloadConfigIfNeeded(appConfig, w, switcher, selector); };
switcher.setConfigFileReloader(reloader); switcher.setConfigFileReloader(reloader);
switcher.start(); switcher.start();
return a.exec(); return a.exec();

View File

@@ -194,7 +194,7 @@ void MainWindow::updateImage(bool immediately)
QPixmap background = getBlurredBackground(rotated, scaled); QPixmap background = getBlurredBackground(rotated, scaled);
drawForeground(background, scaled); drawForeground(background, scaled);
if (overlay != NULL) if (overlay != nullptr)
{ {
drawText(background, overlay->getMarginTopLeft(), overlay->getFontsizeTopLeft(), overlay->getRenderedTopLeft(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignLeft); drawText(background, overlay->getMarginTopLeft(), overlay->getFontsizeTopLeft(), overlay->getRenderedTopLeft(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignLeft);
drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignRight); drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignRight);
@@ -254,9 +254,9 @@ void MainWindow::drawForeground(QPixmap& background, const QPixmap& foreground)
pt.drawPixmap((background.width()-foreground.width())/2, (background.height()-foreground.height())/2, foreground); pt.drawPixmap((background.width()-foreground.width())/2, (background.height()-foreground.height())/2, foreground);
} }
void MainWindow::setOverlay(Overlay* o) void MainWindow::setOverlay(std::unique_ptr<Overlay> &o)
{ {
overlay = o; overlay = std::move(o);
} }
QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled) QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled)

View File

@@ -28,7 +28,7 @@ public:
void setBlurRadius(unsigned int blurRadius); void setBlurRadius(unsigned int blurRadius);
void setBackgroundOpacity(unsigned int opacity); void setBackgroundOpacity(unsigned int opacity);
void warn(std::string text); void warn(std::string text);
void setOverlay(Overlay* overlay); void setOverlay(std::unique_ptr<Overlay> &overlay);
void setDebugMode(bool debugModeIn); void setDebugMode(bool debugModeIn);
void setBaseOptions(const ImageDisplayOptions &baseOptionsIn); void setBaseOptions(const ImageDisplayOptions &baseOptionsIn);
const ImageDisplayOptions &getBaseOptions(); const ImageDisplayOptions &getBaseOptions();
@@ -46,7 +46,7 @@ private:
bool debugMode = false; bool debugMode = false;
QSize lastScreenSize = {0,0}; QSize lastScreenSize = {0,0};
Overlay* overlay = nullptr; std::unique_ptr<Overlay> overlay;
ImageSwitcher *switcher = nullptr; ImageSwitcher *switcher = nullptr;
void drawText(QPixmap& image, int margin, int fontsize, QString text, int alignment); void drawText(QPixmap& image, int margin, int fontsize, QString text, int alignment);