File indexing completed on 2024-05-12 15:50:11

0001 /* -*- C++ -*-
0002     This file is part of ThreadWeaver.
0003 
0004     SPDX-FileCopyrightText: 2005-2014 Mirko Boehm <mirko@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include <QApplication>
0010 #include <QCheckBox>
0011 #include <QCloseEvent>
0012 #include <QFileDialog>
0013 #include <QSettings>
0014 #include <QSortFilterProxyModel>
0015 #include <QString>
0016 #include <QVariant>
0017 
0018 #include <ThreadWeaver/ThreadWeaver>
0019 
0020 #include "AverageLoadManager.h"
0021 #include "ImageListFilter.h"
0022 #include "ItemDelegate.h"
0023 #include "MainWindow.h"
0024 
0025 #include "ui_MainWindow.h"
0026 
0027 const QString MainWindow::Setting_OpenLocation = QLatin1String("OpenFilesLocation");
0028 const QString MainWindow::Setting_OutputLocation = QLatin1String("OutputLocation");
0029 const QString MainWindow::Setting_WindowState = QLatin1String("WindowState");
0030 const QString MainWindow::Setting_WindowGeometry = QLatin1String("WindowGeometry");
0031 
0032 using namespace ThreadWeaver;
0033 
0034 MainWindow::MainWindow(QWidget *parent)
0035     : QMainWindow(parent)
0036     , ui(new Ui::MainWindow)
0037     , m_fileLoaderFilter(new ImageListFilter(Image::Step_LoadFile, this))
0038     , m_imageLoaderFilter(new ImageListFilter(Image::Step_LoadImage, this))
0039     , m_imageScalerFilter(new ImageListFilter(Image::Step_ComputeThumbNail, this))
0040     , m_imageWriterFilter(new ImageListFilter(Image::Step_SaveThumbNail, this))
0041     , m_averageLoadManager(new AverageLoadManager(this))
0042 {
0043     ui->setupUi(this);
0044     // The file loader list:
0045     m_fileLoaderFilter->setSourceModel(&m_model);
0046     ui->fileLoaderList->setModel(m_fileLoaderFilter);
0047     ui->fileLoaderList->setItemDelegate(new ItemDelegate(this));
0048     ui->fileLoaderCap->setValue(m_model.fileLoaderCap());
0049     // The image loader list:
0050     m_imageLoaderFilter->setSourceModel(&m_model);
0051     ui->imageLoaderList->setModel(m_imageLoaderFilter);
0052     ui->imageLoaderList->setItemDelegate(new ItemDelegate(this));
0053     ui->imageLoaderCap->setValue(m_model.imageLoaderCap());
0054 
0055     // The image scaler list:
0056     m_imageScalerFilter->setSourceModel(&m_model);
0057     ui->imageScalerList->setModel(m_imageScalerFilter);
0058     ui->imageScalerList->setItemDelegate(new ItemDelegate(this));
0059     ui->imageScalerCap->setValue(m_model.computeThumbNailCap());
0060 
0061     // The image writer list:
0062     m_imageWriterFilter->setSourceModel(&m_model);
0063     ui->imageWriterList->setModel(m_imageWriterFilter);
0064     ui->imageWriterList->setItemDelegate(new ItemDelegate(this));
0065     ui->fileWriterCap->setValue(m_model.saveThumbNailCap());
0066 
0067     ui->workers->setValue(Queue::instance()->maximumNumberOfThreads());
0068 
0069     // Configure average load manager:
0070     ui->loadManager->setEnabled(m_averageLoadManager->available());
0071     connect(ui->loadManager, SIGNAL(toggled(bool)), SLOT(slotEnableAverageLoadManager(bool)));
0072 
0073     connect(ui->actionOpen_Files, SIGNAL(triggered()), SLOT(slotOpenFiles()));
0074     connect(ui->outputDirectory, SIGNAL(clicked()), SLOT(slotSelectOutputDirectory()));
0075     connect(ui->actionQuit, SIGNAL(triggered()), SLOT(slotQuit()));
0076     connect(&m_model, SIGNAL(progress(int, int)), SLOT(slotProgress(int, int)));
0077     connect(ui->fileLoaderCap, SIGNAL(valueChanged(int)), SLOT(slotFileLoaderCapChanged()));
0078     connect(ui->imageLoaderCap, SIGNAL(valueChanged(int)), SLOT(slotImageLoaderCapChanged()));
0079     connect(ui->imageScalerCap, SIGNAL(valueChanged(int)), SLOT(slotComputeThumbNailCapChanged()));
0080     connect(ui->fileWriterCap, SIGNAL(valueChanged(int)), SLOT(slotSaveThumbNailCapChanged()));
0081 
0082     connect(ui->workers, SIGNAL(valueChanged(int)), SLOT(slotWorkerCapChanged()));
0083 
0084     QSettings settings;
0085     m_outputDirectory = settings.value(Setting_OutputLocation).toString();
0086     if (!m_outputDirectory.isEmpty()) {
0087         ui->outputDirectory->setText(m_outputDirectory);
0088     }
0089     restoreGeometry(settings.value(Setting_WindowGeometry).toByteArray());
0090     restoreState(settings.value(Setting_WindowState).toByteArray());
0091 
0092     connect(m_averageLoadManager, SIGNAL(recommendedWorkerCount(int)), SLOT(slotRecommendedWorkerCountChanged(int)));
0093 }
0094 
0095 MainWindow::~MainWindow()
0096 {
0097     delete ui;
0098 }
0099 
0100 void MainWindow::closeEvent(QCloseEvent *event)
0101 {
0102     event->ignore();
0103     QMainWindow::closeEvent(event);
0104     slotQuit();
0105 }
0106 
0107 void MainWindow::slotProgress(int step, int total)
0108 {
0109     ui->progressBar->setMinimum(0);
0110     ui->progressBar->setMaximum(total);
0111     ui->progressBar->setValue(step);
0112     ui->actionOpen_Files->setEnabled(step >= total);
0113 }
0114 
0115 void MainWindow::slotOpenFiles()
0116 {
0117     QSettings settings;
0118     const QString previousLocation = settings.value(Setting_OpenLocation, QDir::homePath()).toString();
0119     auto const files = QFileDialog::getOpenFileNames(this, tr("Select images to convert"), previousLocation);
0120     if (files.isEmpty()) {
0121         return;
0122     }
0123     if (m_outputDirectory.isNull()) {
0124         slotSelectOutputDirectory();
0125     }
0126     m_model.clear();
0127     const QFileInfo fi(files.at(0));
0128     settings.setValue(Setting_OpenLocation, fi.absolutePath());
0129     slotProgress(0, files.count());
0130     m_model.queueUpConversion(files, m_outputDirectory);
0131 }
0132 
0133 void MainWindow::slotSelectOutputDirectory()
0134 {
0135     QSettings settings;
0136     const QString previousLocation = settings.value(Setting_OutputLocation, QDir::homePath()).toString();
0137     auto directory = QFileDialog::getExistingDirectory(this, tr("Select output directory..."));
0138     if (directory.isNull()) {
0139         return;
0140     }
0141     m_outputDirectory = directory;
0142     settings.setValue(Setting_OutputLocation, directory);
0143     ui->outputDirectory->setText(directory);
0144 }
0145 
0146 void MainWindow::slotFileLoaderCapChanged()
0147 {
0148     const int value = ui->fileLoaderCap->value();
0149     Q_ASSERT(value > 0); // limits set in UI file
0150     m_model.setFileLoaderCap(value);
0151 }
0152 
0153 void MainWindow::slotImageLoaderCapChanged()
0154 {
0155     const int value = ui->imageLoaderCap->value();
0156     Q_ASSERT(value > 0); // limits set in UI file
0157     m_model.setImageLoaderCap(value);
0158 }
0159 
0160 void MainWindow::slotComputeThumbNailCapChanged()
0161 {
0162     const int value = ui->imageScalerCap->value();
0163     Q_ASSERT(value > 0); // limits set in UI file
0164     m_model.setComputeThumbNailCap(value);
0165 }
0166 
0167 void MainWindow::slotSaveThumbNailCapChanged()
0168 {
0169     const int value = ui->fileWriterCap->value();
0170     Q_ASSERT(value > 0); // limits set in UI file
0171     m_model.setSaveThumbNailCap(value);
0172 }
0173 
0174 void MainWindow::slotWorkerCapChanged()
0175 {
0176     const int value = ui->workers->value();
0177     Q_ASSERT(value >= 0); // limits set in UI file
0178     Queue::instance()->setMaximumNumberOfThreads(value);
0179 }
0180 
0181 void MainWindow::slotEnableAverageLoadManager(bool enabled)
0182 {
0183     m_averageLoadManager->activate(enabled);
0184 }
0185 
0186 void MainWindow::slotRecommendedWorkerCountChanged(int value)
0187 {
0188     auto const minMax = m_averageLoadManager->workersRange();
0189     ui->workersSlider->setRange(minMax.first, minMax.second);
0190     ui->workersSlider->setValue(value);
0191     ui->loadManager->setText(tr("%1 workers").arg(value));
0192     ui->workersMin->setText(QString::number(minMax.first));
0193     ui->workersMax->setText(QString::number(minMax.second));
0194     Queue::instance()->setMaximumNumberOfThreads(value);
0195 }
0196 
0197 void MainWindow::slotQuit()
0198 {
0199     QSettings settings;
0200     settings.setValue(Setting_WindowGeometry, saveGeometry());
0201     settings.setValue(Setting_WindowState, saveState());
0202     ThreadWeaver::Queue::instance()->dequeue();
0203     ThreadWeaver::Queue::instance()->finish();
0204     QApplication::instance()->quit();
0205 }
0206 
0207 #include "moc_MainWindow.cpp"