|
35 | 35 | #include <QImage> |
36 | 36 | #include <QDate> |
37 | 37 | #include <QMenuBar> |
| 38 | +#include <QCheckBox> |
| 39 | +#include <QFile> |
| 40 | + |
| 41 | +#include "QsLog.h" |
38 | 42 |
|
39 | 43 | #ifdef use_unarr |
40 | 44 | #include "unarr.h" |
@@ -94,6 +98,7 @@ MainWindowViewer::~MainWindowViewer() |
94 | 98 | delete adjustToFullSizeAction; |
95 | 99 | delete fitToPageAction; |
96 | 100 | delete showFlowAction; |
| 101 | + delete deleteCurrentComicAction; |
97 | 102 | } |
98 | 103 | void MainWindowViewer::loadConfiguration() |
99 | 104 | { |
@@ -841,6 +846,7 @@ void MainWindowViewer::open(QString path, qint64 comicId, qint64 libraryId, YACR |
841 | 846 |
|
842 | 847 | if (success) { |
843 | 848 | isClient = true; |
| 849 | + currentComicFilePath = path + currentComicDB.path; |
844 | 850 | open(path + currentComicDB.path, currentComicDB, siblingComics); |
845 | 851 | } else { |
846 | 852 | isClient = false; |
@@ -869,6 +875,7 @@ void MainWindowViewer::openComic(QString pathFile) |
869 | 875 | { |
870 | 876 | QFileInfo fi(pathFile); |
871 | 877 | currentDirectory = fi.dir().absolutePath(); |
| 878 | + currentComicFilePath = fi.absoluteFilePath(); |
872 | 879 | getSiblingComics(fi.absolutePath(), fi.fileName()); |
873 | 880 |
|
874 | 881 | setWindowTitle("YACReader - " + fi.fileName()); |
@@ -1158,13 +1165,17 @@ void MainWindowViewer::setUpShortcutsManagement() |
1158 | 1165 | // Get current theme for initial icons |
1159 | 1166 | const auto &theme = ThemeManager::instance().getCurrentTheme(); |
1160 | 1167 |
|
| 1168 | + deleteCurrentComicAction = addActionWithShortcut(tr("Delete current comic"), DELETE_CURRENT_COMIC_ACTION_Y); |
| 1169 | + connect(deleteCurrentComicAction, &QAction::triggered, this, &MainWindowViewer::deleteCurrentComic); |
| 1170 | + |
1161 | 1171 | editShortcutsDialog->addActionsGroup(tr("Comics"), theme.shortcutsIcons.comicsIcon, |
1162 | 1172 | tmpList = { openAction, |
1163 | 1173 | openLatestComicAction, |
1164 | 1174 | openFolderAction, |
1165 | 1175 | saveImageAction, |
1166 | 1176 | openComicOnTheLeftAction, |
1167 | | - openComicOnTheRightAction }); |
| 1177 | + openComicOnTheRightAction, |
| 1178 | + deleteCurrentComicAction }); |
1168 | 1179 |
|
1169 | 1180 | allActions << tmpList; |
1170 | 1181 |
|
@@ -1325,6 +1336,126 @@ void MainWindowViewer::doubleMangaPageSwitch() |
1325 | 1336 | } |
1326 | 1337 | } |
1327 | 1338 |
|
| 1339 | +void MainWindowViewer::deleteCurrentComic() |
| 1340 | +{ |
| 1341 | + if (currentComicFilePath.isEmpty()) { |
| 1342 | + return; |
| 1343 | + } |
| 1344 | + |
| 1345 | + // Confirmation dialog |
| 1346 | + if (!skipDeleteConfirmation) { |
| 1347 | + QMessageBox msgBox(this); |
| 1348 | + msgBox.setWindowTitle(tr("Delete Comic")); |
| 1349 | + msgBox.setText(tr("Are you sure you want to delete the current comic?")); |
| 1350 | + msgBox.setInformativeText(QFileInfo(currentComicFilePath).fileName()); |
| 1351 | + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); |
| 1352 | + msgBox.setDefaultButton(QMessageBox::Cancel); |
| 1353 | + msgBox.setIcon(QMessageBox::Warning); |
| 1354 | + |
| 1355 | + auto *checkBox = new QCheckBox(tr("Don't ask again this session"), &msgBox); |
| 1356 | + msgBox.setCheckBox(checkBox); |
| 1357 | + |
| 1358 | + if (msgBox.exec() != QMessageBox::Yes) { |
| 1359 | + return; |
| 1360 | + } |
| 1361 | + |
| 1362 | + if (checkBox->isChecked()) { |
| 1363 | + skipDeleteConfirmation = true; |
| 1364 | + } |
| 1365 | + } |
| 1366 | + |
| 1367 | + // Determine navigation before deleting |
| 1368 | + bool hasNext = false; |
| 1369 | + bool hasPrevious = false; |
| 1370 | + |
| 1371 | + if (isClient && !siblingComics.isEmpty()) { |
| 1372 | + int currentIndex = siblingComics.indexOf(currentComicDB); |
| 1373 | + hasNext = (currentIndex + 1 < siblingComics.count()); |
| 1374 | + hasPrevious = (currentIndex - 1 >= 0); |
| 1375 | + } else { |
| 1376 | + hasNext = !nextComicPath.isEmpty(); |
| 1377 | + hasPrevious = !previousComicPath.isEmpty(); |
| 1378 | + } |
| 1379 | + |
| 1380 | + if (isClient) { |
| 1381 | + int currentIndex = siblingComics.indexOf(currentComicDB); |
| 1382 | + |
| 1383 | + // Close the comic to release the file handle |
| 1384 | + viewer->closeCurrentComic(); |
| 1385 | + |
| 1386 | + // Send delete request via IPC |
| 1387 | + YACReaderLocalClient client; |
| 1388 | + bool success = client.sendDeleteComic(libraryId, currentComicDB); |
| 1389 | + |
| 1390 | + if (!success) { |
| 1391 | + QMessageBox::warning(this, tr("Delete Comic"), tr("Unable to delete the comic file.")); |
| 1392 | + currentComicFilePath.clear(); |
| 1393 | + return; |
| 1394 | + } |
| 1395 | + |
| 1396 | + // Remove the comic from siblingComics |
| 1397 | + if (currentIndex >= 0 && currentIndex < siblingComics.count()) { |
| 1398 | + siblingComics.removeAt(currentIndex); |
| 1399 | + } |
| 1400 | + |
| 1401 | + currentComicFilePath.clear(); |
| 1402 | + |
| 1403 | + // Navigate to next/previous comic |
| 1404 | + if (hasNext && currentIndex < siblingComics.count()) { |
| 1405 | + currentComicDB = siblingComics.at(currentIndex); |
| 1406 | + currentComicFilePath = currentDirectory + currentComicDB.path; |
| 1407 | + open(currentDirectory + currentComicDB.path, currentComicDB, siblingComics); |
| 1408 | + } else if (hasPrevious && currentIndex - 1 >= 0) { |
| 1409 | + currentComicDB = siblingComics.at(currentIndex - 1); |
| 1410 | + currentComicFilePath = currentDirectory + currentComicDB.path; |
| 1411 | + open(currentDirectory + currentComicDB.path, currentComicDB, siblingComics); |
| 1412 | + } |
| 1413 | + } else { |
| 1414 | + // Standalone mode |
| 1415 | + QString pathToDelete = currentComicFilePath; |
| 1416 | + QString savedNextComicPath = nextComicPath; |
| 1417 | + QString savedPreviousComicPath = previousComicPath; |
| 1418 | + |
| 1419 | + viewer->closeCurrentComic(); |
| 1420 | + currentComicFilePath.clear(); |
| 1421 | + |
| 1422 | + QFileInfo fileCheck(pathToDelete); |
| 1423 | + bool fileDeleted = false; |
| 1424 | + QString errorDetail; |
| 1425 | + |
| 1426 | + if (!fileCheck.exists()) { |
| 1427 | + errorDetail = tr("File not found: %1").arg(pathToDelete); |
| 1428 | + } else if (!fileCheck.isWritable()) { |
| 1429 | + errorDetail = tr("File is not writable: %1").arg(pathToDelete); |
| 1430 | + } else { |
| 1431 | + fileDeleted = QFile::moveToTrash(pathToDelete); |
| 1432 | + if (fileDeleted) { |
| 1433 | + QLOG_INFO() << "Comic recycled:" << pathToDelete; |
| 1434 | + } else { |
| 1435 | + QFile f(pathToDelete); |
| 1436 | + fileDeleted = f.remove(); |
| 1437 | + if (fileDeleted) { |
| 1438 | + QLOG_INFO() << "Comic permanently deleted:" << pathToDelete; |
| 1439 | + } else { |
| 1440 | + errorDetail = tr("Could not delete: %1\n%2").arg(pathToDelete, f.errorString()); |
| 1441 | + QLOG_ERROR() << "Failed to delete comic:" << pathToDelete << f.errorString(); |
| 1442 | + } |
| 1443 | + } |
| 1444 | + } |
| 1445 | + |
| 1446 | + if (!fileDeleted) { |
| 1447 | + QMessageBox::warning(this, tr("Delete Comic"), errorDetail); |
| 1448 | + return; |
| 1449 | + } |
| 1450 | + |
| 1451 | + if (hasNext && !savedNextComicPath.isEmpty()) { |
| 1452 | + openSiblingComic(savedNextComicPath); |
| 1453 | + } else if (hasPrevious && !savedPreviousComicPath.isEmpty()) { |
| 1454 | + openSiblingComic(savedPreviousComicPath); |
| 1455 | + } |
| 1456 | + } |
| 1457 | +} |
| 1458 | + |
1328 | 1459 | void MainWindowViewer::toggleFitToWidthSlider() |
1329 | 1460 | { |
1330 | 1461 | int y; |
|
0 commit comments