File indexing completed on 2024-05-05 17:57:24

0001 /*
0002     SPDX-FileCopyrightText: 2003 Csaba Karai <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "splittergui.h"
0009 
0010 #include "../FileSystem/filesystem.h"
0011 
0012 // QtCore
0013 #include <QDebug>
0014 // QtGui
0015 #include <QKeyEvent>
0016 #include <QValidator>
0017 // QtWidgets
0018 #include <QCheckBox>
0019 #include <QComboBox>
0020 #include <QDialogButtonBox>
0021 #include <QDoubleSpinBox>
0022 #include <QFrame>
0023 #include <QGridLayout>
0024 #include <QHBoxLayout>
0025 #include <QLabel>
0026 #include <QLayout>
0027 #include <QLineEdit>
0028 
0029 #include <KConfigCore/KConfigGroup>
0030 #include <KConfigCore/KSharedConfig>
0031 #include <KI18n/KLocalizedString>
0032 #include <KWidgetsAddons/KMessageBox>
0033 #include <utility>
0034 
0035 struct SplitterGUI::PredefinedDevice {
0036     PredefinedDevice(QString name, KIO::filesize_t capacity)
0037         : name(std::move(name))
0038         , capacity(capacity)
0039     {
0040     }
0041     PredefinedDevice(const PredefinedDevice &other)
0042         : name(other.name)
0043         , capacity(other.capacity)
0044     {
0045     }
0046     PredefinedDevice &operator=(const PredefinedDevice &other);
0047 
0048     QString name;
0049     KIO::filesize_t capacity;
0050 };
0051 
0052 const QList<SplitterGUI::PredefinedDevice> &SplitterGUI::predefinedDevices()
0053 {
0054     static QList<PredefinedDevice> list;
0055     if (!list.count()) {
0056         list << PredefinedDevice(i18n("1.44 MB (3.5\")"), 1457664);
0057         list << PredefinedDevice(i18n("1.2 MB (5.25\")"), 1213952);
0058         list << PredefinedDevice(i18n("720 kB (3.5\")"), 730112);
0059         list << PredefinedDevice(i18n("360 kB (5.25\")"), 362496);
0060         list << PredefinedDevice(i18n("100 MB (ZIP)"), 100431872);
0061         list << PredefinedDevice(i18n("250 MB (ZIP)"), 250331136);
0062         list << PredefinedDevice(i18n("650 MB (CD-R)"), 650 * 0x100000);
0063         list << PredefinedDevice(i18n("700 MB (CD-R)"), 700 * 0x100000);
0064     }
0065     return list;
0066 }
0067 
0068 SplitterGUI::SplitterGUI(QWidget *parent, const QUrl &fileURL, const QUrl &defaultDir)
0069     : QDialog(parent)
0070     , userDefinedSize(0x100000)
0071     , lastSelectedDevice(-1)
0072     , division(1)
0073 {
0074     setModal(true);
0075 
0076     auto *grid = new QGridLayout(this);
0077     grid->setSpacing(6);
0078     grid->setContentsMargins(11, 11, 11, 11);
0079 
0080     QLabel *splitterLabel = new QLabel(this);
0081     splitterLabel->setText(i18n("Split the file %1 to folder:", fileURL.toDisplayString(QUrl::PreferLocalFile)));
0082     splitterLabel->setMinimumWidth(400);
0083     grid->addWidget(splitterLabel, 0, 0);
0084 
0085     urlReq = new KUrlRequester(this);
0086     urlReq->setUrl(defaultDir);
0087     urlReq->setMode(KFile::Directory);
0088     grid->addWidget(urlReq, 1, 0);
0089 
0090     QWidget *splitSizeLine = new QWidget(this);
0091     auto *splitSizeLineLayout = new QHBoxLayout;
0092     splitSizeLineLayout->setContentsMargins(0, 0, 0, 0);
0093     splitSizeLine->setLayout(splitSizeLineLayout);
0094 
0095     deviceCombo = new QComboBox(splitSizeLine);
0096     for (int i = 0; i != predefinedDevices().count(); i++)
0097         deviceCombo->addItem(predefinedDevices()[i].name);
0098     deviceCombo->addItem(i18n("User Defined"));
0099     splitSizeLineLayout->addWidget(deviceCombo);
0100 
0101     QLabel *spacer = new QLabel(splitSizeLine);
0102     spacer->setText(" ");
0103     spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
0104     splitSizeLineLayout->addWidget(spacer);
0105 
0106     QLabel *bytesPerFile = new QLabel(splitSizeLine);
0107     bytesPerFile->setText(i18n("Max file size:"));
0108     splitSizeLineLayout->addWidget(bytesPerFile);
0109 
0110     spinBox = new QDoubleSpinBox(splitSizeLine);
0111     spinBox->setMaximum(9999999999.0);
0112     spinBox->setMinimumWidth(85);
0113     spinBox->setEnabled(false);
0114     splitSizeLineLayout->addWidget(spinBox);
0115 
0116     sizeCombo = new QComboBox(splitSizeLine);
0117     sizeCombo->addItem(i18n("Byte"));
0118     sizeCombo->addItem(i18n("kByte"));
0119     sizeCombo->addItem(i18n("MByte"));
0120     sizeCombo->addItem(i18n("GByte"));
0121     splitSizeLineLayout->addWidget(sizeCombo);
0122 
0123     grid->addWidget(splitSizeLine, 2, 0);
0124 
0125     overwriteCb = new QCheckBox(i18n("Overwrite files without confirmation"), this);
0126     grid->addWidget(overwriteCb, 3, 0);
0127 
0128     QFrame *separator = new QFrame(this);
0129     separator->setFrameStyle(QFrame::HLine | QFrame::Sunken);
0130     separator->setFixedHeight(separator->sizeHint().height());
0131 
0132     grid->addWidget(separator, 4, 0);
0133 
0134     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0135     buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("&Split"));
0136 
0137     grid->addWidget(buttonBox, 5, 0);
0138 
0139     setWindowTitle(i18n("Krusader::Splitter"));
0140 
0141     KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Splitter"));
0142     overwriteCb->setChecked(cfg.readEntry("OverWriteFiles", false));
0143 
0144     connect(sizeCombo, QOverload<int>::of(&QComboBox::activated), this, &SplitterGUI::sizeComboActivated);
0145     connect(deviceCombo, QOverload<int>::of(&QComboBox::activated), this, &SplitterGUI::predefinedComboActivated);
0146     connect(buttonBox, &QDialogButtonBox::rejected, this, &SplitterGUI::reject);
0147     connect(buttonBox, &QDialogButtonBox::accepted, this, &SplitterGUI::splitPressed);
0148 
0149     predefinedComboActivated(0);
0150 }
0151 
0152 SplitterGUI::~SplitterGUI()
0153 {
0154     KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Splitter"));
0155     cfg.writeEntry("OverWriteFiles", overwriteCb->isChecked());
0156 }
0157 
0158 KIO::filesize_t SplitterGUI::getSplitSize()
0159 {
0160     if (deviceCombo->currentIndex() < predefinedDevices().count()) // predefined size selected
0161         return predefinedDevices()[deviceCombo->currentIndex()].capacity;
0162     // user defined size selected
0163     return static_cast<KIO::filesize_t>(spinBox->value()) * division;
0164 }
0165 
0166 bool SplitterGUI::overWriteFiles()
0167 {
0168     return overwriteCb->isChecked();
0169 }
0170 
0171 void SplitterGUI::sizeComboActivated(int item)
0172 {
0173     KIO::filesize_t prevDivision = division;
0174     switch (item) {
0175     case 0:
0176         division = 1; /* byte */
0177         break;
0178     case 1:
0179         division = 0x400; /* kbyte */
0180         break;
0181     case 2:
0182         division = 0x100000; /* Mbyte */
0183         break;
0184     case 3:
0185         division = 0x40000000; /* Gbyte */
0186         break;
0187     }
0188     long double value;
0189     if (deviceCombo->currentIndex() < predefinedDevices().count()) // predefined size selected
0190         value = static_cast<long double>(predefinedDevices()[deviceCombo->currentIndex()].capacity) / division;
0191     else { // use defined size selected
0192         value = (static_cast<long double>(spinBox->value()) * prevDivision) / division;
0193         if (value < 1)
0194             value = 1;
0195     }
0196     spinBox->setValue(static_cast<double>(value));
0197 }
0198 
0199 void SplitterGUI::predefinedComboActivated(int item)
0200 {
0201     if (item == lastSelectedDevice)
0202         return;
0203 
0204     KIO::filesize_t capacity = userDefinedSize;
0205 
0206     if (lastSelectedDevice == predefinedDevices().count()) // user defined was selected previously
0207         userDefinedSize = static_cast<KIO::filesize_t>(spinBox->value()) * division; // remember user defined size
0208 
0209     if (item < predefinedDevices().count()) { // predefined size selected
0210         capacity = predefinedDevices()[item].capacity;
0211         spinBox->setEnabled(false);
0212     } else // user defined size selected
0213         spinBox->setEnabled(true);
0214 
0215     // qDebug() << capacity;
0216 
0217     if (capacity >= 0x40000000) { /* Gbyte */
0218         sizeCombo->setCurrentIndex(3);
0219         division = 0x40000000;
0220     } else if (capacity >= 0x100000) { /* Mbyte */
0221         sizeCombo->setCurrentIndex(2);
0222         division = 0x100000;
0223     } else if (capacity >= 0x400) { /* kbyte */
0224         sizeCombo->setCurrentIndex(1);
0225         division = 0x400;
0226     } else {
0227         sizeCombo->setCurrentIndex(0); /* byte */
0228         division = 1;
0229     }
0230 
0231     spinBox->setValue(static_cast<double>(capacity) / static_cast<double>(division));
0232 
0233     lastSelectedDevice = item;
0234 }
0235 
0236 void SplitterGUI::splitPressed()
0237 {
0238     if (!urlReq->url().isValid()) {
0239         KMessageBox::error(this, i18n("The folder path URL is malformed."));
0240         return;
0241     }
0242     if (getSplitSize() > 0)
0243         accept();
0244 }
0245 
0246 void SplitterGUI::keyPressEvent(QKeyEvent *e)
0247 {
0248     switch (e->key()) {
0249     case Qt::Key_Enter:
0250     case Qt::Key_Return:
0251         splitPressed();
0252         return;
0253     default:
0254         QDialog::keyPressEvent(e);
0255     }
0256 }