1 | /* -*- C++ -*- |
2 | This file is part of ThreadWeaver. |
3 | |
4 | SPDX-FileCopyrightText: 2005-2014 Mirko Boehm <mirko@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #include <QApplication> |
10 | #include <QCheckBox> |
11 | #include <QCloseEvent> |
12 | #include <QFileDialog> |
13 | #include <QSettings> |
14 | #include <QSortFilterProxyModel> |
15 | #include <QString> |
16 | #include <QVariant> |
17 | |
18 | #include <ThreadWeaver/ThreadWeaver> |
19 | |
20 | #include "AverageLoadManager.h" |
21 | #include "ImageListFilter.h" |
22 | #include "ItemDelegate.h" |
23 | #include "MainWindow.h" |
24 | |
25 | #include "ui_MainWindow.h" |
26 | |
27 | const QString MainWindow::Setting_OpenLocation = QLatin1String("OpenFilesLocation" ); |
28 | const QString MainWindow::Setting_OutputLocation = QLatin1String("OutputLocation" ); |
29 | const QString MainWindow::Setting_WindowState = QLatin1String("WindowState" ); |
30 | const QString MainWindow::Setting_WindowGeometry = QLatin1String("WindowGeometry" ); |
31 | |
32 | using namespace ThreadWeaver; |
33 | |
34 | MainWindow::MainWindow(QWidget *parent) |
35 | : QMainWindow(parent) |
36 | , ui(new Ui::MainWindow) |
37 | , m_fileLoaderFilter(new ImageListFilter(Image::Step_LoadFile, this)) |
38 | , m_imageLoaderFilter(new ImageListFilter(Image::Step_LoadImage, this)) |
39 | , m_imageScalerFilter(new ImageListFilter(Image::Step_ComputeThumbNail, this)) |
40 | , m_imageWriterFilter(new ImageListFilter(Image::Step_SaveThumbNail, this)) |
41 | , m_averageLoadManager(new AverageLoadManager(this)) |
42 | { |
43 | ui->setupUi(this); |
44 | // The file loader list: |
45 | m_fileLoaderFilter->setSourceModel(&m_model); |
46 | ui->fileLoaderList->setModel(m_fileLoaderFilter); |
47 | ui->fileLoaderList->setItemDelegate(new ItemDelegate(this)); |
48 | ui->fileLoaderCap->setValue(m_model.fileLoaderCap()); |
49 | // The image loader list: |
50 | m_imageLoaderFilter->setSourceModel(&m_model); |
51 | ui->imageLoaderList->setModel(m_imageLoaderFilter); |
52 | ui->imageLoaderList->setItemDelegate(new ItemDelegate(this)); |
53 | ui->imageLoaderCap->setValue(m_model.imageLoaderCap()); |
54 | |
55 | // The image scaler list: |
56 | m_imageScalerFilter->setSourceModel(&m_model); |
57 | ui->imageScalerList->setModel(m_imageScalerFilter); |
58 | ui->imageScalerList->setItemDelegate(new ItemDelegate(this)); |
59 | ui->imageScalerCap->setValue(m_model.computeThumbNailCap()); |
60 | |
61 | // The image writer list: |
62 | m_imageWriterFilter->setSourceModel(&m_model); |
63 | ui->imageWriterList->setModel(m_imageWriterFilter); |
64 | ui->imageWriterList->setItemDelegate(new ItemDelegate(this)); |
65 | ui->fileWriterCap->setValue(m_model.saveThumbNailCap()); |
66 | |
67 | ui->workers->setValue(Queue::instance()->maximumNumberOfThreads()); |
68 | |
69 | // Configure average load manager: |
70 | ui->loadManager->setEnabled(m_averageLoadManager->available()); |
71 | connect(asender: ui->loadManager, SIGNAL(toggled(bool)), SLOT(slotEnableAverageLoadManager(bool))); |
72 | |
73 | connect(asender: ui->actionOpen_Files, SIGNAL(triggered()), SLOT(slotOpenFiles())); |
74 | connect(asender: ui->outputDirectory, SIGNAL(clicked()), SLOT(slotSelectOutputDirectory())); |
75 | connect(asender: ui->actionQuit, SIGNAL(triggered()), SLOT(slotQuit())); |
76 | connect(asender: &m_model, SIGNAL(progress(int, int)), SLOT(slotProgress(int, int))); |
77 | connect(asender: ui->fileLoaderCap, SIGNAL(valueChanged(int)), SLOT(slotFileLoaderCapChanged())); |
78 | connect(asender: ui->imageLoaderCap, SIGNAL(valueChanged(int)), SLOT(slotImageLoaderCapChanged())); |
79 | connect(asender: ui->imageScalerCap, SIGNAL(valueChanged(int)), SLOT(slotComputeThumbNailCapChanged())); |
80 | connect(asender: ui->fileWriterCap, SIGNAL(valueChanged(int)), SLOT(slotSaveThumbNailCapChanged())); |
81 | |
82 | connect(asender: ui->workers, SIGNAL(valueChanged(int)), SLOT(slotWorkerCapChanged())); |
83 | |
84 | QSettings settings; |
85 | m_outputDirectory = settings.value(key: Setting_OutputLocation).toString(); |
86 | if (!m_outputDirectory.isEmpty()) { |
87 | ui->outputDirectory->setText(m_outputDirectory); |
88 | } |
89 | restoreGeometry(geometry: settings.value(key: Setting_WindowGeometry).toByteArray()); |
90 | restoreState(state: settings.value(key: Setting_WindowState).toByteArray()); |
91 | |
92 | connect(asender: m_averageLoadManager, SIGNAL(recommendedWorkerCount(int)), SLOT(slotRecommendedWorkerCountChanged(int))); |
93 | } |
94 | |
95 | MainWindow::~MainWindow() |
96 | { |
97 | delete ui; |
98 | } |
99 | |
100 | void MainWindow::closeEvent(QCloseEvent *event) |
101 | { |
102 | event->ignore(); |
103 | QMainWindow::closeEvent(event); |
104 | slotQuit(); |
105 | } |
106 | |
107 | void MainWindow::slotProgress(int step, int total) |
108 | { |
109 | ui->progressBar->setMinimum(0); |
110 | ui->progressBar->setMaximum(total); |
111 | ui->progressBar->setValue(step); |
112 | ui->actionOpen_Files->setEnabled(step >= total); |
113 | } |
114 | |
115 | void MainWindow::slotOpenFiles() |
116 | { |
117 | QSettings settings; |
118 | const QString previousLocation = settings.value(key: Setting_OpenLocation, defaultValue: QDir::homePath()).toString(); |
119 | auto const files = QFileDialog::getOpenFileNames(parent: this, caption: tr(s: "Select images to convert" ), dir: previousLocation); |
120 | if (files.isEmpty()) { |
121 | return; |
122 | } |
123 | if (m_outputDirectory.isNull()) { |
124 | slotSelectOutputDirectory(); |
125 | } |
126 | m_model.clear(); |
127 | const QFileInfo fi(files.at(i: 0)); |
128 | settings.setValue(key: Setting_OpenLocation, value: fi.absolutePath()); |
129 | slotProgress(step: 0, total: files.count()); |
130 | m_model.queueUpConversion(files, outputDirectory: m_outputDirectory); |
131 | } |
132 | |
133 | void MainWindow::slotSelectOutputDirectory() |
134 | { |
135 | QSettings settings; |
136 | const QString previousLocation = settings.value(key: Setting_OutputLocation, defaultValue: QDir::homePath()).toString(); |
137 | auto directory = QFileDialog::getExistingDirectory(parent: this, caption: tr(s: "Select output directory..." )); |
138 | if (directory.isNull()) { |
139 | return; |
140 | } |
141 | m_outputDirectory = directory; |
142 | settings.setValue(key: Setting_OutputLocation, value: directory); |
143 | ui->outputDirectory->setText(directory); |
144 | } |
145 | |
146 | void MainWindow::slotFileLoaderCapChanged() |
147 | { |
148 | const int value = ui->fileLoaderCap->value(); |
149 | Q_ASSERT(value > 0); // limits set in UI file |
150 | m_model.setFileLoaderCap(value); |
151 | } |
152 | |
153 | void MainWindow::slotImageLoaderCapChanged() |
154 | { |
155 | const int value = ui->imageLoaderCap->value(); |
156 | Q_ASSERT(value > 0); // limits set in UI file |
157 | m_model.setImageLoaderCap(value); |
158 | } |
159 | |
160 | void MainWindow::slotComputeThumbNailCapChanged() |
161 | { |
162 | const int value = ui->imageScalerCap->value(); |
163 | Q_ASSERT(value > 0); // limits set in UI file |
164 | m_model.setComputeThumbNailCap(value); |
165 | } |
166 | |
167 | void MainWindow::slotSaveThumbNailCapChanged() |
168 | { |
169 | const int value = ui->fileWriterCap->value(); |
170 | Q_ASSERT(value > 0); // limits set in UI file |
171 | m_model.setSaveThumbNailCap(value); |
172 | } |
173 | |
174 | void MainWindow::slotWorkerCapChanged() |
175 | { |
176 | const int value = ui->workers->value(); |
177 | Q_ASSERT(value >= 0); // limits set in UI file |
178 | Queue::instance()->setMaximumNumberOfThreads(value); |
179 | } |
180 | |
181 | void MainWindow::slotEnableAverageLoadManager(bool enabled) |
182 | { |
183 | m_averageLoadManager->activate(enabled); |
184 | } |
185 | |
186 | void MainWindow::slotRecommendedWorkerCountChanged(int value) |
187 | { |
188 | auto const minMax = m_averageLoadManager->workersRange(); |
189 | ui->workersSlider->setRange(min: minMax.first, max: minMax.second); |
190 | ui->workersSlider->setValue(value); |
191 | ui->loadManager->setText(tr(s: "%1 workers" ).arg(a: value)); |
192 | ui->workersMin->setText(QString::number(minMax.first)); |
193 | ui->workersMax->setText(QString::number(minMax.second)); |
194 | Queue::instance()->setMaximumNumberOfThreads(value); |
195 | } |
196 | |
197 | void MainWindow::slotQuit() |
198 | { |
199 | QSettings settings; |
200 | settings.setValue(key: Setting_WindowGeometry, value: saveGeometry()); |
201 | settings.setValue(key: Setting_WindowState, value: saveState()); |
202 | ThreadWeaver::Queue::instance()->dequeue(); |
203 | ThreadWeaver::Queue::instance()->finish(); |
204 | QApplication::instance()->quit(); |
205 | } |
206 | |
207 | #include "moc_MainWindow.cpp" |
208 | |