Krita Source Code Documentation
Loading...
Searching...
No Matches
recorder_snapshots_manager.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Dmitrii Utkin <loentar@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 */
6
7
9#include "ui_recorder_snapshots_manager.h"
11#include "recorder_const.h"
12
13#include <klocalizedstring.h>
14
15#include <QCloseEvent>
16#include <QDebug>
17#include <QDir>
18#include <QLocale>
19#include <QMessageBox>
20#include <QStandardItemModel>
21#include <QDialogButtonBox>
22
23namespace
24{
25
26constexpr int valueRole = Qt::UserRole + 1;
27constexpr int defaultColumnMargin = 16;
28
29enum Page
30{
31 PageProgress = 0,
32 PageSelection = 1
33};
34
35enum Column
36{
37 ColumnCheck = 0,
38 ColumnName = 1,
39 ColumnSize = 2,
40 ColumnDate = 3,
41 ColumnCount = ColumnDate + 1
42};
43
44class DataSortedItem : public QStandardItem
45{
46public:
47 DataSortedItem(const QString &text, qulonglong sortValue)
48 : QStandardItem(text)
49 {
50 setData(sortValue, valueRole);
51 }
52
53 bool operator<(const QStandardItem &other) const override
54 {
55 return data(valueRole).toULongLong() < other.data(valueRole).toULongLong();
56 }
57};
58
59class CheckedIconItem : public QStandardItem
60{
61public:
62 CheckedIconItem(const QString &imagePath, const QSize &iconSize)
63 {
64 setData(Qt::Unchecked, Qt::CheckStateRole);
65
66 QPixmap pixmap(imagePath);
67 const int minSide = qMin(pixmap.width(), pixmap.height());
68 setIcon(pixmap.copy((pixmap.width() - minSide) / 2, (pixmap.height() - minSide) / 2, minSide, minSide)
69 .scaled(iconSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
70 }
71};
72
73}
74
76 : QDialog(parent)
78 , scanner(new RecorderSnapshotsScanner)
79 , cleaner(nullptr)
80{
81 ui->setupUi(this);
82 cleanUpButton = new QPushButton(i18n("Clean Up"), ui->buttonBox);
83 ui->buttonBox->addButton(cleanUpButton, QDialogButtonBox::ActionRole);
84
85 ui->stackedWidget->setCurrentIndex(PageProgress);
86
87 connect(scanner, SIGNAL(scanningFinished(SnapshotDirInfoList)),
89 connect(ui->buttonSelectAll, SIGNAL(clicked()), this, SLOT(onButtonSelectAllClicked()));
90 connect(cleanUpButton, SIGNAL(clicked()), this, SLOT(onButtonCleanUpClicked()));
91 connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
92}
93
99
100void RecorderSnapshotsManager::execFor(const QString &snapshotsDirectory)
101{
102 scanner->setup(snapshotsDirectory);
104 exec();
105}
106
108{
109 abortCleanUp();
110 QDialog::closeEvent(event);
111}
112
114{
115 abortCleanUp();
116 QDialog::reject();
117}
118
120{
121 QStandardItemModel *model = new QStandardItemModel(this);
122 model->setColumnCount(ColumnCount);
123
124 QLocale locale = this->locale();
125 const QString &dateFormat = locale.dateTimeFormat(QLocale::ShortFormat);
126 for (const SnapshotDirInfo &info : snapshots) {
127 QStandardItem *nameCol = new QStandardItem(info.name);
128 nameCol->setData(info.path, valueRole);
129 model->appendRow({
130 new CheckedIconItem(info.thumbnail, ui->treeDirectories->iconSize()),
131 nameCol,
132 new DataSortedItem(locale.formattedDataSize(info.size), info.size),
133 new DataSortedItem(info.dateTime.toString(dateFormat), info.dateTime.toMSecsSinceEpoch())
134 });
135 }
136
137 model->setHorizontalHeaderItem(ColumnCheck,
138 new QStandardItem(i18nc("Header title for preview thumbnail", "Preview")));
139 model->setHorizontalHeaderItem(ColumnName,
140 new QStandardItem(i18nc("Header title for directory name column", "Name")));
141 model->setHorizontalHeaderItem(ColumnSize,
142 new QStandardItem(i18nc("Header title for size of directory column", "Size")));
143 model->setHorizontalHeaderItem(ColumnDate,
144 new QStandardItem(i18nc("Header title for last modified date/time column", "Last Modified")));
145
146 QAbstractItemModel *oldModel = ui->treeDirectories->model();
147 QItemSelectionModel *oldSelectionModel = ui->treeDirectories->selectionModel();
148 ui->treeDirectories->setModel(model);
149 if (oldModel != nullptr)
150 oldModel->deleteLater();
151 if (oldSelectionModel != nullptr)
152 oldSelectionModel->deleteLater();
153
154 cleanUpButton->setEnabled(false);
155 ui->stackedWidget->setCurrentIndex(PageSelection);
156
157 for(int col = 0; col < (ColumnCount - 1); ++col) {
158 ui->treeDirectories->resizeColumnToContents(col);
159 const int colWidth = ui->treeDirectories->columnWidth(col);
160 ui->treeDirectories->setColumnWidth(col, colWidth + defaultColumnMargin);
161 }
162
163 connect(ui->treeDirectories->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
164 this, SLOT(onSelectionChanged(QItemSelection,QItemSelection)), Qt::UniqueConnection);
165}
166
167void RecorderSnapshotsManager::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
168{
169 QAbstractItemModel *model = ui->treeDirectories->model();
170 for (const QModelIndex &index : selected.indexes())
171 model->setData(index.sibling(index.row(), ColumnCheck), Qt::Checked, Qt::CheckStateRole);
172 for (const QModelIndex &index : deselected.indexes())
173 model->setData(index.sibling(index.row(), ColumnCheck), Qt::Unchecked, Qt::CheckStateRole);
174
175 cleanUpButton->setEnabled(!ui->treeDirectories->selectionModel()->selectedIndexes().isEmpty());
176
178}
179
181{
182 ui->labelProgress->setText(i18nc("Label title, Scanning for directory, files, etc..", "Scanning..."));
183 ui->stackedWidget->setCurrentIndex(PageProgress);
184 scanner->start();
185}
186
188{
189 const QModelIndexList &indexes = ui->treeDirectories->selectionModel()->selectedRows(ColumnSize);
190 qulonglong totalSize = 0;
191 QAbstractItemModel *model = ui->treeDirectories->model();
192 for (const QModelIndex &index : indexes)
193 totalSize += model->data(index, valueRole).toULongLong();
194 ui->labelSpace->setText(locale().formattedDataSize(totalSize));
195 ui->buttonSelectAll->setText(indexes.size() != model->rowCount() ? i18n("Select All") : i18n("Select None"));
196}
197
199{
200 if (cleaner == nullptr)
201 return;
202
203 cleaner->stop();
204 cleaner->deleteLater();
205 cleaner = nullptr;
206}
207
209{
210 const QModelIndexList &selectedIndexes = ui->treeDirectories->selectionModel()->selectedRows(ColumnCheck);
211 QAbstractItemModel *model = ui->treeDirectories->model();
212 int rowCount = model->rowCount();
213 bool selectAll = selectedIndexes.size() != rowCount;
214 if (selectAll) {
215 ui->treeDirectories->selectAll();
216 } else {
217 ui->treeDirectories->clearSelection();
218 }
219}
220
222{
223 const QString confirmation(i18n("The selected recordings will be deleted"
224 " and you will not be able to export a timelapse for them again"
225 " (the already exported timelapses will be preserved though)."
226 "\nDo you wish to continue?"));
227 if (QMessageBox::question(this, windowTitle(), confirmation) != QMessageBox::Yes)
228 return;
229
230 QStringList directories;
231 const QModelIndexList &indexes = ui->treeDirectories->selectionModel()->selectedRows(ColumnName);
232 QAbstractItemModel *model = ui->treeDirectories->model();
233 for (const QModelIndex &index : indexes)
234 directories.append(model->data(index, valueRole).toString());
235
236 ui->labelProgress->setText(i18nc("Label title, Snapshot directory deleting is in progress", "Cleaning up..."));
237 ui->stackedWidget->setCurrentIndex(PageProgress);
238
239 Q_ASSERT(cleaner == nullptr);
240 cleaner = new RecorderDirectoryCleaner(directories);
241 connect(cleaner, SIGNAL(finished()), this, SLOT(onCleanUpFinished()));
242 cleaner->start();
243}
244
250
252{
253 cleaner->deleteLater();
254 cleaner = nullptr;
255
257}
bool operator<(KoSnapStrategy::SnapType lhs, KoSnapStrategy::SnapType rhs)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
int iconSize(qreal width, qreal height)
RecorderDirectoryCleaner * cleaner
void onScanningFinished(SnapshotDirInfoList snapshots)
RecorderSnapshotsManager(QWidget *parent=nullptr)
RecorderSnapshotsScanner * scanner
void closeEvent(QCloseEvent *event) override
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void execFor(const QString &snapshotsDirectory)
Ui::RecorderSnapshotsManager * ui
void setup(const QString &snapshotDirectory)