Commit d0af9b9d authored by Nicolas Fella's avatar Nicolas Fella
Browse files

[applets/comic] Remove ability to ceate comic book archives

This feature is supposed to download a set of comics from a given provider and create a bundle file

While the idea is sound enough the implementation and UX is rather broken

Attempting to actually create a bundle results in a crash or just doesn't work

Even if those bugs were fixed there are still some UX problems:

When creating a bundle from all items the user is not aware that they will potentially download thousands of images from the internet

When limiting to a subset the user has to define a range based on identifiers. These identifiers are different between different sources.

Some use numerical indices, some alphanumerical, some use dates.

The UI doesn't indicate that in any way, leaving the user guessing how it is supposed to work.

While all of those issues are fixable in theory I am not sure it is worth the effort for a somewhat niche feature
parent 355c1a33
Pipeline #209311 passed with stage
in 3 minutes and 33 seconds
......@@ -6,8 +6,6 @@ set(comic_SRCS
comic.cpp
comicmodel.cpp
comicupdater.cpp
comicarchivejob.cpp
comicarchivedialog.cpp
checknewstrips.cpp
comicdata.cpp
comicinfo.cpp
......@@ -16,9 +14,6 @@ set(comic_SRCS
activecomicmodel.cpp
)
ki18n_wrap_ui(comic_SRCS comicarchivedialog.ui
)
kcoreaddons_add_plugin(org.kde.plasma.comic SOURCES ${comic_SRCS} INSTALL_NAMESPACE "plasma/applets")
target_link_libraries(org.kde.plasma.comic
......
......@@ -12,8 +12,6 @@
#include "comic.h"
#include "checknewstrips.h"
#include "comic_debug.h"
#include "comicarchivedialog.h"
#include "comicarchivejob.h"
#include "comicsaver.h"
#include "stripselector.h"
......@@ -31,6 +29,7 @@
#include <KApplicationTrader>
#include <KConfigDialog>
#include <KIO/OpenUrlJob>
#include <KLocalizedString>
#include <KNotification>
#include <KService>
#include <KStandardShortcut>
......@@ -124,10 +123,6 @@ void ComicApplet::init()
mActions.append(mActionSaveComicAs);
connect(mActionSaveComicAs, &QAction::triggered, this, &ComicApplet::slotSaveComicAs);
mActionCreateComicBook = new QAction(QIcon::fromTheme(QStringLiteral("application-epub+zip")), i18nc("@action", "&Create Comic Book Archive…"), this);
mActions.append(mActionCreateComicBook);
connect(mActionCreateComicBook, &QAction::triggered, this, &ComicApplet::createComicBook);
mActionScaleContent = new QAction(QIcon::fromTheme(QStringLiteral("zoom-original")), //
i18nc("@option:check Context menu of comic image", "&Actual Size"),
this);
......@@ -435,49 +430,6 @@ void ComicApplet::slotShop()
job->start();
}
void ComicApplet::createComicBook()
{
ComicArchiveDialog *dialog = new ComicArchiveDialog(mCurrent.id(), //
mCurrent.title(),
mCurrent.type(),
mCurrent.current(),
mCurrent.first(),
mSavingDir->getDir());
dialog->setAttribute(Qt::WA_DeleteOnClose); // to have destroyed emitted upon closing
connect(dialog, &ComicArchiveDialog::archive, this, &ComicApplet::slotArchive);
dialog->show();
}
void ComicApplet::slotArchive(int archiveType, const QUrl &dest, const QString &fromIdentifier, const QString &toIdentifier)
{
if (!mEngine) {
return;
}
mSavingDir->setDir(dest.path());
const QString id = mCurrent.id();
qDebug() << "Archiving:" << id << archiveType << dest << fromIdentifier << toIdentifier;
ComicArchiveJob *job = new ComicArchiveJob(dest, mEngine, static_cast<ComicArchiveJob::ArchiveType>(archiveType), mCurrent.type(), id, this);
job->setFromIdentifier(id + QLatin1Char(':') + fromIdentifier);
job->setToIdentifier(id + QLatin1Char(':') + toIdentifier);
if (job->isValid()) {
connect(job, &ComicArchiveJob::finished, this, &ComicApplet::slotArchiveFinished);
KIO::getJobTracker()->registerJob(job);
job->start();
} else {
qWarning() << "Archiving job is not valid.";
delete job;
}
}
void ComicApplet::slotArchiveFinished(KJob *job)
{
if (job->error()) {
KNotification::event(KNotification::Warning, i18n("Archiving comic failed"), job->errorText(), QStringLiteral("dialog-warning"));
}
}
QList<QAction *> ComicApplet::contextualActions()
{
return mActions;
......@@ -526,7 +478,6 @@ void ComicApplet::updateContextMenu()
mActionStorePosition->setEnabled(false);
mActionGoJump->setEnabled(false);
mActionSaveComicAs->setEnabled(false);
mActionCreateComicBook->setEnabled(false);
mActionScaleContent->setChecked(false);
} else {
mActionGoFirst->setVisible(mCurrent.hasFirst());
......@@ -538,7 +489,6 @@ void ComicApplet::updateContextMenu()
mActionStorePosition->setEnabled(true);
mActionGoJump->setEnabled(true);
mActionSaveComicAs->setEnabled(true);
mActionCreateComicBook->setEnabled(true);
}
}
......
......@@ -134,9 +134,6 @@ private Q_SLOTS:
void slotWebsite();
void slotStorePosition();
void checkDayChanged();
void createComicBook();
void slotArchive(int archiveType, const QUrl &dest, const QString &fromIdentifier, const QString &toIdentifier);
void slotArchiveFinished(KJob *job);
public Q_SLOTS:
void configChanged() override;
......
/*
* SPDX-FileCopyrightText: 2011 Matthias Fuchs <mat69@gmx.net>
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "comicarchivedialog.h"
#include "comicarchivejob.h"
ComicArchiveDialog::ComicArchiveDialog(const QString &pluginName,
const QString &comicName,
IdentifierType identifierType,
const QString &currentIdentifierSuffix,
const QString &firstIdentifierSuffix,
const QString &savingDir,
QWidget *parent)
: QDialog(parent)
, mIdentifierType(identifierType)
, mPluginName(pluginName)
{
ui.setupUi(this);
setWindowTitle(i18nc("@title:window", "Create %1 Comic Book Archive", comicName));
connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &ComicArchiveDialog::slotOkClicked);
connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &ComicArchiveDialog::reject);
switch (mIdentifierType) {
case IdentifierType::DateIdentifier: {
const QDate current = QDate::fromString(currentIdentifierSuffix, QStringLiteral("yyyy-MM-dd"));
const QDate first = QDate::fromString(firstIdentifierSuffix, QStringLiteral("yyyy-MM-dd"));
const QDate today = QDate::currentDate();
QDate maxDate = today;
if (current.isValid()) {
ui.fromDate->setDate(current);
ui.toDate->setDate(current);
maxDate = (today > current ? today : current);
}
if (first.isValid()) {
ui.fromDate->setMinimumDate(first);
ui.toDate->setMinimumDate(first);
}
connect(ui.fromDate, &QDateTimeEdit::dateChanged, this, &ComicArchiveDialog::fromDateChanged);
connect(ui.toDate, &QDateTimeEdit::dateChanged, this, &ComicArchiveDialog::toDateChanged);
break;
}
case IdentifierType::NumberIdentifier: {
bool ok;
const int current = currentIdentifierSuffix.toInt(&ok);
if (ok) {
ui.fromNumber->setValue(current);
ui.toNumber->setValue(current);
}
const int first = firstIdentifierSuffix.toInt(&ok);
if (ok) {
ui.fromNumber->setMinimum(first);
ui.toNumber->setMinimum(first);
}
break;
}
case IdentifierType::StringIdentifier: {
ui.fromString->setText(currentIdentifierSuffix);
ui.toString->setText(currentIdentifierSuffix);
connect(ui.fromString, &QLineEdit::textEdited, this, &ComicArchiveDialog::updateOkButton);
connect(ui.toString, &QLineEdit::textEdited, this, &ComicArchiveDialog::updateOkButton);
break;
}
}
ui.types->setCurrentIndex((int)mIdentifierType);
archiveTypeChanged(ComicArchiveJob::ArchiveAll);
// TODO suggest file name!
ui.dest->setAcceptMode(QFileDialog::AcceptSave);
if (!savingDir.isEmpty()) {
ui.dest->setStartDir(QUrl::fromLocalFile(savingDir));
}
connect(ui.archiveType, qOverload<int>(&KComboBox::currentIndexChanged), this, &ComicArchiveDialog::archiveTypeChanged);
connect(ui.dest, &KUrlRequester::textChanged, this, &ComicArchiveDialog::updateOkButton);
}
void ComicArchiveDialog::archiveTypeChanged(int newType)
{
switch (newType) {
case ComicArchiveJob::ArchiveAll:
setFromVisible(false);
setToVisibile(false);
break;
break;
case ComicArchiveJob::ArchiveEndTo:
case ComicArchiveJob::ArchiveStartTo:
setFromVisible(false);
setToVisibile(true);
break;
case ComicArchiveJob::ArchiveFromTo:
setFromVisible(true);
setToVisibile(true);
break;
}
updateOkButton();
}
void ComicArchiveDialog::fromDateChanged(const QDate &newDate)
{
if (ui.toDate->date() < newDate) {
ui.toDate->setDate(newDate);
}
updateOkButton();
}
void ComicArchiveDialog::toDateChanged(const QDate &newDate)
{
if (ui.fromDate->date() > newDate) {
ui.fromDate->setDate(newDate);
}
updateOkButton();
}
void ComicArchiveDialog::updateOkButton()
{
const int archiveType = ui.archiveType->currentIndex();
bool okEnabled = true;
// string is handled here, as it is the only identifier which can be invalid (empty)
if (mIdentifierType == IdentifierType::StringIdentifier) {
if (archiveType == ComicArchiveJob::ArchiveAll) {
okEnabled = true;
} else if (ui.archiveType->currentIndex() == ComicArchiveJob::ArchiveFromTo) {
okEnabled = !ui.fromString->text().isEmpty() && !ui.toString->text().isEmpty();
} else {
okEnabled = !ui.toString->text().isEmpty();
}
}
okEnabled = (okEnabled && !ui.dest->url().isEmpty());
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(okEnabled);
}
void ComicArchiveDialog::slotOkClicked()
{
const int archiveType = ui.archiveType->currentIndex();
QString fromIdentifier;
QString toIdentifier;
switch (mIdentifierType) {
case IdentifierType::DateIdentifier:
fromIdentifier = ui.fromDate->date().toString(QStringLiteral("yyyy-MM-dd"));
toIdentifier = ui.toDate->date().toString(QStringLiteral("yyyy-MM-dd"));
break;
case IdentifierType::NumberIdentifier: {
fromIdentifier = QString::number(ui.fromNumber->value());
toIdentifier = QString::number(ui.toNumber->value());
// the user entered from and to wrong, swap them
if ((archiveType == ComicArchiveJob::ArchiveFromTo) && (ui.toNumber->value() < ui.fromNumber->value())) {
QString temp = fromIdentifier;
fromIdentifier = toIdentifier;
toIdentifier = temp;
}
break;
}
case IdentifierType::StringIdentifier:
fromIdentifier = ui.fromString->text();
toIdentifier = ui.toString->text();
break;
}
Q_EMIT archive(archiveType, ui.dest->url(), fromIdentifier, toIdentifier);
accept();
}
void ComicArchiveDialog::setFromVisible(bool visible)
{
ui.fromDateLabel->setVisible(visible);
ui.fromDate->setVisible(visible);
ui.fromNumberLabel->setVisible(visible);
ui.fromNumber->setVisible(visible);
ui.fromStringLabel->setVisible(visible);
ui.fromString->setVisible(visible);
}
void ComicArchiveDialog::setToVisibile(bool visible)
{
ui.toDateLabel->setVisible(visible);
ui.toDate->setVisible(visible);
ui.toNumberLabel->setVisible(visible);
ui.toNumber->setVisible(visible);
ui.toStringLabel->setVisible(visible);
ui.toString->setVisible(visible);
}
/*
* SPDX-FileCopyrightText: 2011 Matthias Fuchs <mat69@gmx.net>
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef COMIC_ARCHIVE_DIALOG_H
#define COMIC_ARCHIVE_DIALOG_H
#include "comicinfo.h"
#include "engine/types.h"
#include "ui_comicarchivedialog.h"
#include <QDialog>
class ComicArchiveDialog : public QDialog
{
Q_OBJECT
public:
ComicArchiveDialog(const QString &pluginName,
const QString &comicName,
IdentifierType identifierType,
const QString &currentIdentifierSuffix,
const QString &firstIdentifierSuffix,
const QString &savingDir = QString(),
QWidget *parent = nullptr);
Q_SIGNALS:
void archive(int archiveType, const QUrl &dest, const QString &fromIdentifier, const QString &toIdentifier);
private Q_SLOTS:
void archiveTypeChanged(int newType);
void fromDateChanged(const QDate &newDate);
void toDateChanged(const QDate &newDate);
void slotOkClicked();
void updateOkButton();
private:
void setFromVisible(bool visible);
void setToVisibile(bool visible);
private:
Ui::ComicArchiveDialog ui;
IdentifierType mIdentifierType;
QString mPluginName;
};
#endif
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ComicArchiveDialog</class>
<widget class="QDialog" name="ComicArchiveDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>469</width>
<height>213</height>
</rect>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Destination:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KUrlRequester" name="dest">
<property name="filter">
<string>*.cbz|Comic Book Archive (Zip)</string>
</property>
<property name="mode">
<set>KFile::File|KFile::LocalOnly</set>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="statusTip">
<string>The range of comic strips to archive.</string>
</property>
<property name="text">
<string>Range:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="KComboBox" name="archiveType">
<item>
<property name="text">
<string>All</string>
</property>
</item>
<item>
<property name="text">
<string>From beginning to …</string>
</property>
</item>
<item>
<property name="text">
<string>From end to …</string>
</property>
</item>
<item>
<property name="text">
<string>Manual range</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QStackedWidget" name="types">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="date">
<layout class="QFormLayout" name="formLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="fromDateLabel">
<property name="text">
<string comment="in a range: from to">From:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="toDateLabel">
<property name="text">
<string comment="in a range: from to">To:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDateEdit" name="fromDate">
<property name="displayFormat">
<string>dd.MM.yyyy</string>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDateEdit" name="toDate">
<property name="displayFormat">
<string>dd.MM.yyyy</string>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="number">
<layout class="QFormLayout" name="formLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="fromNumberLabel">
<property name="text">
<string comment="in a range: from to">From:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="toNumberLabel">
<property name="text">
<string comment="in a range: from to">To:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="toNumber">
<property name="maximum">
<number>100000</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="fromNumber">
<property name="maximum">
<number>100000</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="string">
<layout class="QFormLayout" name="formLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="fromStringLabel">
<property name="text">
<string comment="in a range: from to">From:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="toStringLabel">
<property name="text">
<string comment="in a range: from to">To:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KLineEdit" name="fromString"/>
</item>
<item row="1" column="1">
<widget class="KLineEdit" name="toString"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>