1 #include "archivelistwidget.h"
2 #include "archivelistwidgetitem.h"
3 #include "debug.h"
4 #include "restoredialog.h"
5
6 #include <QKeyEvent>
7 #include <QMessageBox>
8
9 #define DELETE_CONFIRMATION_THRESHOLD 10
10
ArchiveListWidget(QWidget * parent)11 ArchiveListWidget::ArchiveListWidget(QWidget *parent) : QListWidget(parent)
12 {
13 _filter.setCaseSensitivity(Qt::CaseInsensitive);
14 _filter.setPatternSyntax(QRegExp::Wildcard);
15 connect(this, &QListWidget::itemActivated, [&](QListWidgetItem *item) {
16 if(item)
17 {
18 ArchiveListWidgetItem *archiveItem =
19 static_cast<ArchiveListWidgetItem *>(item);
20 if(archiveItem && !archiveItem->archive()->deleteScheduled())
21 emit inspectArchive(archiveItem->archive());
22 }
23 });
24 }
25
~ArchiveListWidget()26 ArchiveListWidget::~ArchiveListWidget()
27 {
28 clear();
29 }
30
setArchives(QList<ArchivePtr> archives)31 void ArchiveListWidget::setArchives(QList<ArchivePtr> archives)
32 {
33 std::sort(archives.begin(), archives.end(),
34 [](const ArchivePtr &a, const ArchivePtr &b) {
35 return (a->timestamp() > b->timestamp());
36 });
37 setUpdatesEnabled(false);
38 clear();
39 foreach(ArchivePtr archive, archives)
40 insertArchive(archive, count());
41 setUpdatesEnabled(true);
42 }
43
addArchive(ArchivePtr archive)44 void ArchiveListWidget::addArchive(ArchivePtr archive)
45 {
46 if(!archive)
47 {
48 DEBUG << "Null ArchivePtr passed.";
49 return;
50 }
51
52 int pos = 0;
53 for(; pos < count(); ++pos)
54 {
55 ArchiveListWidgetItem *archiveItem =
56 static_cast<ArchiveListWidgetItem *>(item(pos));
57 if(archiveItem
58 && (archive->timestamp() > archiveItem->archive()->timestamp()))
59 {
60 break;
61 }
62 }
63 insertArchive(archive, pos);
64 }
65
deleteItem()66 void ArchiveListWidget::deleteItem()
67 {
68 ArchiveListWidgetItem *archiveItem =
69 qobject_cast<ArchiveListWidgetItem *>(sender());
70 if(archiveItem)
71 {
72 ArchivePtr archive = archiveItem->archive();
73 auto confirm = QMessageBox::question(this, tr("Confirm delete"),
74 tr("Are you sure you want to "
75 "delete archive %1 "
76 "(this cannot be undone)?")
77 .arg(archive->name()));
78 if(confirm == QMessageBox::Yes)
79 {
80 QList<ArchivePtr> archiveList;
81 archiveList.append(archive);
82 emit deleteArchives(archiveList);
83 }
84 }
85 }
86
deleteSelectedItems()87 void ArchiveListWidget::deleteSelectedItems()
88 {
89 if(selectedItems().isEmpty())
90 return;
91
92 QList<ArchiveListWidgetItem *> selectedListItems;
93 // Any archives pending deletion in the selection? if so deny action
94 foreach(QListWidgetItem *item, selectedItems())
95 {
96 ArchiveListWidgetItem *archiveItem =
97 static_cast<ArchiveListWidgetItem *>(item);
98 if(!archiveItem || archiveItem->archive()->deleteScheduled())
99 return;
100 else
101 selectedListItems << archiveItem;
102 }
103
104 int selectedItemsCount = selectedItems().count();
105 auto confirm =
106 QMessageBox::question(this, tr("Confirm delete"),
107 tr("Are you sure you want to delete %1 "
108 "selected archive(s) "
109 "(this cannot be undone)?")
110 .arg(selectedItemsCount));
111 if(confirm != QMessageBox::Yes)
112 return;
113
114 // Some more deletion confirmation, if count of archives to be
115 // removed is bigger than threshold
116 if(selectedItemsCount >= DELETE_CONFIRMATION_THRESHOLD)
117 {
118 // Inform of purge operation if all archives are to be removed
119 if(selectedItemsCount == count())
120 {
121 confirm =
122 QMessageBox::question(this, tr("Confirm delete"),
123 tr("Are you sure you want to delete "
124 "all of your archives?\nFor your "
125 "information, there's a purge "
126 "action in Settings -> Account "
127 "page that achieves the same "
128 "thing but more efficiently."));
129 }
130 else
131 {
132 confirm = QMessageBox::question(this, tr("Confirm delete"),
133 tr("This will permanently delete "
134 "the %1 selected archives. "
135 "Proceed?")
136 .arg(selectedItemsCount));
137 }
138 }
139
140 if(confirm == QMessageBox::Yes)
141 {
142 QList<ArchivePtr> archivesToDelete;
143 foreach(ArchiveListWidgetItem *archiveItem, selectedListItems)
144 {
145 archivesToDelete.append(archiveItem->archive());
146 }
147 if(!archivesToDelete.isEmpty())
148 emit deleteArchives(archivesToDelete);
149 }
150 }
151
inspectSelectedItem()152 void ArchiveListWidget::inspectSelectedItem()
153 {
154 if(!selectedItems().isEmpty())
155 {
156 ArchiveListWidgetItem *archiveItem =
157 static_cast<ArchiveListWidgetItem *>(selectedItems().first());
158 if(archiveItem && !archiveItem->archive()->deleteScheduled())
159 emit inspectArchive(archiveItem->archive());
160 }
161 }
162
restoreSelectedItem()163 void ArchiveListWidget::restoreSelectedItem()
164 {
165 if(!selectedItems().isEmpty())
166 {
167 ArchiveListWidgetItem *archiveItem =
168 static_cast<ArchiveListWidgetItem *>(selectedItems().first());
169 if(archiveItem && !archiveItem->archive()->deleteScheduled())
170 {
171 RestoreDialog *restoreDialog =
172 new RestoreDialog(this, archiveItem->archive());
173 restoreDialog->show();
174 connect(restoreDialog, &RestoreDialog::accepted, [=] {
175 emit restoreArchive(restoreDialog->archive(),
176 restoreDialog->getOptions());
177 });
178 }
179 }
180 }
181
setFilter(QString regex)182 void ArchiveListWidget::setFilter(QString regex)
183 {
184 setUpdatesEnabled(false);
185 clearSelection();
186 _filter.setPattern(regex);
187 for(int i = 0; i < count(); ++i)
188 {
189 ArchiveListWidgetItem *archiveItem =
190 static_cast<ArchiveListWidgetItem *>(item(i));
191 if(archiveItem)
192 {
193 if(archiveItem->archive()->name().contains(_filter))
194 archiveItem->setHidden(false);
195 else
196 archiveItem->setHidden(true);
197 }
198 }
199 setUpdatesEnabled(true);
200 emit countChanged(count(), visibleItemsCount());
201 }
202
removeItem()203 void ArchiveListWidget::removeItem()
204 {
205 ArchiveListWidgetItem *archiveItem =
206 qobject_cast<ArchiveListWidgetItem *>(sender());
207 if(archiveItem)
208 {
209 delete archiveItem; // Removes item from the list
210 emit countChanged(count(), visibleItemsCount());
211 }
212 }
213
insertArchive(ArchivePtr archive,int pos)214 void ArchiveListWidget::insertArchive(ArchivePtr archive, int pos)
215 {
216 if(!archive)
217 {
218 DEBUG << "Null ArchivePtr passed.";
219 return;
220 }
221
222 ArchiveListWidgetItem *item = new ArchiveListWidgetItem(archive);
223 connect(item, &ArchiveListWidgetItem::requestDelete, this,
224 &ArchiveListWidget::deleteItem);
225 connect(item, &ArchiveListWidgetItem::requestInspect, this,
226 &ArchiveListWidget::inspectItem);
227 connect(item, &ArchiveListWidgetItem::requestRestore, this,
228 &ArchiveListWidget::restoreItem);
229 connect(item, &ArchiveListWidgetItem::requestGoToJob, this,
230 &ArchiveListWidget::goToJob);
231 connect(item, &ArchiveListWidgetItem::removeItem, this,
232 &ArchiveListWidget::removeItem);
233 insertItem(pos, item);
234 setItemWidget(item, item->widget());
235 item->setHidden(!archive->name().contains(_filter));
236 emit countChanged(count(), visibleItemsCount());
237 }
238
visibleItemsCount()239 int ArchiveListWidget::visibleItemsCount()
240 {
241 int count = 0;
242 foreach(QListWidgetItem *item, findItems("*", Qt::MatchWildcard))
243 {
244 if(item && !item->isHidden())
245 count++;
246 }
247 return count;
248 }
249
inspectItem()250 void ArchiveListWidget::inspectItem()
251 {
252 if(sender())
253 emit inspectArchive(
254 qobject_cast<ArchiveListWidgetItem *>(sender())->archive());
255 }
256
restoreItem()257 void ArchiveListWidget::restoreItem()
258 {
259 ArchiveListWidgetItem *archiveItem =
260 qobject_cast<ArchiveListWidgetItem *>(sender());
261 if(archiveItem)
262 {
263 RestoreDialog *restoreDialog =
264 new RestoreDialog(this, archiveItem->archive());
265 restoreDialog->show();
266 connect(restoreDialog, &RestoreDialog::accepted, [=] {
267 emit restoreArchive(restoreDialog->archive(),
268 restoreDialog->getOptions());
269 });
270 }
271 }
272
goToJob()273 void ArchiveListWidget::goToJob()
274 {
275 if(sender())
276 emit displayJobDetails(
277 qobject_cast<ArchiveListWidgetItem *>(sender())->archive()->jobRef());
278 }
279
selectArchive(ArchivePtr archive)280 void ArchiveListWidget::selectArchive(ArchivePtr archive)
281 {
282 if(!archive)
283 {
284 DEBUG << "Null ArchivePtr passed.";
285 return;
286 }
287
288 for(int i = 0; i < count(); ++i)
289 {
290 ArchiveListWidgetItem *archiveItem =
291 static_cast<ArchiveListWidgetItem *>(item(i));
292 if(archiveItem
293 && (archiveItem->archive()->objectKey() == archive->objectKey()))
294 {
295 clearSelection();
296 setCurrentItem(archiveItem);
297 scrollToItem(currentItem(), QAbstractItemView::EnsureVisible);
298 break;
299 }
300 }
301 }
302
keyPressEvent(QKeyEvent * event)303 void ArchiveListWidget::keyPressEvent(QKeyEvent *event)
304 {
305 switch(event->key())
306 {
307 case Qt::Key_Delete:
308 deleteSelectedItems();
309 break;
310 case Qt::Key_Escape:
311 if(!selectedItems().isEmpty())
312 clearSelection();
313 else
314 QListWidget::keyPressEvent(event);
315 break;
316 default:
317 QListWidget::keyPressEvent(event);
318 }
319 }
320