File indexing completed on 2024-04-28 17:05:55
0001 /* 0002 SPDX-FileCopyrightText: 2000 Shie Erlich <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2000 Rafi Yanai <krusader@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "packguibase.h" 0010 0011 // QtCore 0012 #include <QVariant> 0013 // QtGui 0014 #include <QGuiApplication> 0015 #include <QImage> 0016 #include <QKeyEvent> 0017 #include <QPixmap> 0018 // QtWidgets 0019 #include <QCheckBox> 0020 #include <QComboBox> 0021 #include <QFrame> 0022 #include <QGridLayout> 0023 #include <QHBoxLayout> 0024 #include <QLabel> 0025 #include <QLayout> 0026 #include <QLineEdit> 0027 #include <QPushButton> 0028 #include <QSlider> 0029 #include <QSpinBox> 0030 #include <QToolButton> 0031 #include <QVBoxLayout> 0032 0033 #include <KCompletion/KComboBox> 0034 #include <KConfigCore/KSharedConfig> 0035 #include <KI18n/KLocalizedString> 0036 #include <KIO/Global> 0037 #include <KWidgetsAddons/KMessageBox> 0038 #include <KWidgetsAddons/KStandardGuiItem> 0039 0040 #include "../GUI/krhistorycombobox.h" 0041 #include "../compat.h" 0042 #include "../defaults.h" 0043 #include "../icon.h" 0044 #include "../krglobal.h" 0045 0046 /* 0047 * Constructs a PackGUIBase which is a child of 'parent', with the 0048 * name 'name' and widget flags set to 'f' 0049 * 0050 * The dialog will by default be modeless, unless you set 'modal' to 0051 * TRUE to construct a modal dialog. 0052 */ 0053 PackGUIBase::PackGUIBase(QWidget *parent) 0054 : QDialog(parent) 0055 , expanded(false) 0056 { 0057 KConfigGroup group(krConfig, "Archives"); 0058 0059 setModal(true); 0060 resize(430, 140); 0061 setWindowTitle(i18n("Pack")); 0062 grid = new QGridLayout(this); 0063 grid->setSpacing(6); 0064 grid->setContentsMargins(11, 11, 11, 11); 0065 0066 hbox = new QHBoxLayout; 0067 hbox->setSpacing(6); 0068 hbox->setContentsMargins(0, 0, 0, 0); 0069 0070 TextLabel3 = new QLabel(this); 0071 TextLabel3->setText(i18n("To archive")); 0072 hbox->addWidget(TextLabel3); 0073 0074 nameData = new QLineEdit(this); 0075 hbox->addWidget(nameData); 0076 0077 typeData = new QComboBox(this); 0078 typeData->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed)); 0079 connect(typeData, QOverload<const QString &>::of(&QComboBox::QCOMBOBOX_ACTIVATED), this, &PackGUIBase::checkConsistency); 0080 connect(typeData, QOverload<const QString &>::of(&QComboBox::QCOMBOBOX_HIGHLIGHTED), this, &PackGUIBase::checkConsistency); 0081 hbox->addWidget(typeData); 0082 0083 grid->addLayout(hbox, 1, 0); 0084 0085 hbox_2 = new QHBoxLayout; 0086 hbox_2->setSpacing(6); 0087 hbox_2->setContentsMargins(0, 0, 0, 0); 0088 0089 TextLabel5 = new QLabel(this); 0090 TextLabel5->setText(i18n("In folder")); 0091 hbox_2->addWidget(TextLabel5); 0092 0093 dirData = new QLineEdit(this); 0094 hbox_2->addWidget(dirData); 0095 0096 browseButton = new QToolButton(this); 0097 browseButton->setIcon(Icon("document-open")); 0098 hbox_2->addWidget(browseButton); 0099 auto *spacer = new QSpacerItem(48, 20, QSizePolicy::Fixed, QSizePolicy::Fixed); 0100 hbox_2->addItem(spacer); 0101 0102 grid->addLayout(hbox_2, 2, 0); 0103 0104 hbox_3 = new QHBoxLayout; 0105 hbox_3->setSpacing(6); 0106 hbox_3->setContentsMargins(0, 0, 0, 0); 0107 0108 PixmapLabel1 = new QLabel(this); 0109 PixmapLabel1->setPixmap(Icon("package-x-generic").pixmap(32)); 0110 PixmapLabel1->setScaledContents(true); 0111 PixmapLabel1->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 0112 hbox_3->addWidget(PixmapLabel1); 0113 0114 TextLabel1 = new QLabel(this); 0115 TextLabel1->setText(i18n("Pack")); 0116 hbox_3->addWidget(TextLabel1); 0117 0118 grid->addLayout(hbox_3, 0, 0); 0119 0120 hbox_4 = new QHBoxLayout; 0121 hbox_4->setSpacing(6); 0122 hbox_4->setContentsMargins(0, 0, 0, 0); 0123 0124 auto *spacer_3 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Expanding); 0125 hbox_4->addItem(spacer_3); 0126 grid->addLayout(hbox_4, 3, 0); 0127 0128 advancedWidget = new QWidget(this); 0129 0130 hbox_5 = new QGridLayout(advancedWidget); 0131 hbox_5->setSpacing(6); 0132 hbox_5->setContentsMargins(0, 0, 0, 0); 0133 0134 auto *compressLayout = new QVBoxLayout; 0135 compressLayout->setSpacing(6); 0136 compressLayout->setContentsMargins(0, 0, 0, 0); 0137 0138 multipleVolume = new QCheckBox(i18n("Multiple volume archive"), advancedWidget); 0139 connect(multipleVolume, &QCheckBox::toggled, this, &PackGUIBase::checkConsistency); 0140 compressLayout->addWidget(multipleVolume, 0, Qt::Alignment()); 0141 0142 auto *volumeHbox = new QHBoxLayout; 0143 0144 auto *spacer_5 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed); 0145 volumeHbox->addItem(spacer_5); 0146 0147 TextLabel7 = new QLabel(i18n("Size:"), advancedWidget); 0148 volumeHbox->addWidget(TextLabel7); 0149 0150 volumeSpinBox = new QSpinBox(advancedWidget); 0151 volumeSpinBox->setMinimum(1); 0152 volumeSpinBox->setMaximum(9999); 0153 volumeSpinBox->setValue(1440); 0154 volumeHbox->addWidget(volumeSpinBox); 0155 0156 volumeUnitCombo = new QComboBox(advancedWidget); 0157 volumeUnitCombo->addItem("B"); 0158 volumeUnitCombo->addItem("KB"); 0159 volumeUnitCombo->addItem("MB"); 0160 volumeUnitCombo->setCurrentIndex(1); 0161 volumeHbox->addWidget(volumeUnitCombo); 0162 0163 compressLayout->addLayout(volumeHbox); 0164 0165 int level = group.readEntry("Compression level", _defaultCompressionLevel); 0166 setCompressionLevel = new QCheckBox(i18n("Set compression level"), advancedWidget); 0167 if (level != _defaultCompressionLevel) 0168 setCompressionLevel->setChecked(true); 0169 connect(setCompressionLevel, &QCheckBox::toggled, this, &PackGUIBase::checkConsistency); 0170 compressLayout->addWidget(setCompressionLevel, 0, Qt::Alignment()); 0171 0172 auto *sliderHbox = new QHBoxLayout; 0173 0174 auto *spacer_6 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed); 0175 sliderHbox->addItem(spacer_6); 0176 0177 QWidget *sliderVBoxWidget = new QWidget(advancedWidget); 0178 auto *sliderVBox = new QVBoxLayout(sliderVBoxWidget); 0179 0180 compressionSlider = new QSlider(Qt::Horizontal, sliderVBoxWidget); 0181 compressionSlider->setMinimum(1); 0182 compressionSlider->setMaximum(9); 0183 compressionSlider->setPageStep(1); 0184 compressionSlider->setValue(level); 0185 compressionSlider->setTickPosition(QSlider::TicksBelow); 0186 sliderVBox->addWidget(compressionSlider); 0187 0188 QWidget *minmaxWidget = new QWidget(sliderVBoxWidget); 0189 sliderVBox->addWidget(minmaxWidget); 0190 0191 auto *minmaxHbox = new QHBoxLayout(minmaxWidget); 0192 0193 minLabel = new QLabel(i18n("MIN"), minmaxWidget); 0194 maxLabel = new QLabel(i18n("MAX"), minmaxWidget); 0195 maxLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0196 0197 minmaxHbox->addWidget(minLabel); 0198 minmaxHbox->addWidget(maxLabel); 0199 0200 sliderHbox->addWidget(sliderVBoxWidget); 0201 0202 compressLayout->addLayout(sliderHbox); 0203 0204 compressLayout->addStretch(0); 0205 hbox_5->addLayout(compressLayout, 0, 0); 0206 0207 QFrame *vline = new QFrame(advancedWidget); 0208 vline->setFrameStyle(QFrame::VLine | QFrame::Sunken); 0209 vline->setMinimumWidth(20); 0210 hbox_5->addWidget(vline, 0, 1); 0211 0212 auto *passwordGrid = new QGridLayout; 0213 passwordGrid->setSpacing(6); 0214 passwordGrid->setContentsMargins(0, 0, 0, 0); 0215 0216 TextLabel4 = new QLabel(advancedWidget); 0217 TextLabel4->setText(i18n("Password")); 0218 passwordGrid->addWidget(TextLabel4, 0, 0); 0219 0220 password = new QLineEdit(advancedWidget); 0221 password->setEchoMode(QLineEdit::Password); 0222 connect(password, &QLineEdit::textChanged, this, &PackGUIBase::checkConsistency); 0223 0224 passwordGrid->addWidget(password, 0, 1); 0225 0226 TextLabel6 = new QLabel(advancedWidget); 0227 TextLabel6->setText(i18n("Again")); 0228 passwordGrid->addWidget(TextLabel6, 1, 0); 0229 0230 passwordAgain = new QLineEdit(advancedWidget); 0231 passwordAgain->setEchoMode(QLineEdit::Password); 0232 connect(passwordAgain, &QLineEdit::textChanged, this, &PackGUIBase::checkConsistency); 0233 0234 passwordGrid->addWidget(passwordAgain, 1, 1); 0235 0236 auto *consistencyHbox = new QHBoxLayout; 0237 0238 auto *spacer_cons = new QSpacerItem(48, 20, QSizePolicy::Expanding, QSizePolicy::Fixed); 0239 consistencyHbox->addItem(spacer_cons); 0240 0241 passwordConsistencyLabel = new QLabel(advancedWidget); 0242 consistencyHbox->addWidget(passwordConsistencyLabel); 0243 passwordGrid->addLayout(consistencyHbox, 2, 0, 1, 2); 0244 0245 encryptHeaders = new QCheckBox(i18n("Encrypt headers"), advancedWidget); 0246 passwordGrid->addWidget(encryptHeaders, 3, 0, 1, 2); 0247 0248 auto *spacer_psw = new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Expanding); 0249 passwordGrid->addItem(spacer_psw, 4, 0); 0250 0251 hbox_5->addLayout(passwordGrid, 0, 2); 0252 0253 hbox_7 = new QHBoxLayout; 0254 hbox_7->setSpacing(6); 0255 hbox_7->setContentsMargins(0, 0, 0, 0); 0256 0257 TextLabel8 = new QLabel(i18n("Command line switches:"), advancedWidget); 0258 TextLabel8->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0259 hbox_7->addWidget(TextLabel8); 0260 0261 commandLineSwitches = new KrHistoryComboBox(advancedWidget); 0262 commandLineSwitches->setMaxCount(25); // remember 25 items 0263 commandLineSwitches->setDuplicatesEnabled(false); 0264 commandLineSwitches->setMinimumContentsLength(10); 0265 0266 QStringList list = group.readEntry("Command Line Switches", QStringList()); 0267 commandLineSwitches->setHistoryItems(list); 0268 0269 hbox_7->addWidget(commandLineSwitches); 0270 0271 hbox_5->addLayout(hbox_7, 1, 0, 1, 3); 0272 0273 advancedWidget->hide(); 0274 checkConsistency(); 0275 0276 grid->addWidget(advancedWidget, 4, 0); 0277 0278 hbox_6 = new QHBoxLayout; 0279 hbox_6->setSpacing(6); 0280 hbox_6->setContentsMargins(0, 0, 0, 0); 0281 0282 advancedButton = new QPushButton(this); 0283 advancedButton->setText(i18n("&Advanced >>")); 0284 hbox_6->addWidget(advancedButton); 0285 0286 auto *spacer_2 = new QSpacerItem(140, 20, QSizePolicy::Expanding, QSizePolicy::Fixed); 0287 hbox_6->addItem(spacer_2); 0288 0289 okButton = new QPushButton(this); 0290 KStandardGuiItem::assign(okButton, KStandardGuiItem::Ok); 0291 okButton->setDefault(true); 0292 hbox_6->addWidget(okButton); 0293 0294 cancelButton = new QPushButton(this); 0295 KStandardGuiItem::assign(cancelButton, KStandardGuiItem::Cancel); 0296 hbox_6->addWidget(cancelButton); 0297 0298 grid->addLayout(hbox_6, 6, 0); 0299 0300 // signals and slots connections 0301 connect(okButton, &QPushButton::clicked, this, &PackGUIBase::accept); 0302 connect(advancedButton, &QPushButton::clicked, this, &PackGUIBase::expand); 0303 connect(cancelButton, &QPushButton::clicked, this, &PackGUIBase::reject); 0304 connect(browseButton, &QToolButton::clicked, this, &PackGUIBase::browse); 0305 } 0306 0307 /* 0308 * Destroys the object and frees any allocated resources 0309 */ 0310 PackGUIBase::~PackGUIBase() 0311 { 0312 // no need to delete child widgets, Qt does it all for us 0313 } 0314 0315 void PackGUIBase::browse() 0316 { 0317 qWarning("PackGUIBase::browse(): Not implemented yet!"); 0318 } 0319 0320 void PackGUIBase::expand() 0321 { 0322 expanded = !expanded; 0323 0324 advancedButton->setText(expanded ? i18n("&Advanced <<") : i18n("&Advanced >>")); 0325 0326 if (expanded) 0327 advancedWidget->show(); 0328 else { 0329 advancedWidget->hide(); 0330 layout()->activate(); 0331 QSize minSize = minimumSize(); 0332 resize(width(), minSize.height()); 0333 } 0334 show(); 0335 } 0336 0337 void PackGUIBase::checkConsistency() 0338 { 0339 QPalette p = QGuiApplication::palette(); 0340 QPalette pal = passwordConsistencyLabel->palette(); 0341 if (password->text().isEmpty() && passwordAgain->text().isEmpty()) { 0342 pal.setColor(passwordConsistencyLabel->foregroundRole(), p.color(QPalette::Active, QPalette::Text)); 0343 passwordConsistencyLabel->setText(i18n("No password specified")); 0344 } else if (password->text() == passwordAgain->text()) { 0345 pal.setColor(passwordConsistencyLabel->foregroundRole(), p.color(QPalette::Active, QPalette::Text)); 0346 passwordConsistencyLabel->setText(i18n("The passwords are equal")); 0347 } else { 0348 pal.setColor(passwordConsistencyLabel->foregroundRole(), Qt::red); 0349 passwordConsistencyLabel->setText(i18n("The passwords are different")); 0350 } 0351 passwordConsistencyLabel->setPalette(pal); 0352 0353 QString packer = typeData->currentText(); 0354 0355 bool passworded = false; 0356 if (packer == "7z" || packer == "rar" || packer == "zip" || packer == "arj") 0357 passworded = true; 0358 0359 passwordConsistencyLabel->setEnabled(passworded); 0360 password->setEnabled(passworded); 0361 passwordAgain->setEnabled(passworded); 0362 TextLabel4->setEnabled(passworded); 0363 TextLabel6->setEnabled(passworded); 0364 0365 encryptHeaders->setEnabled(packer == "rar"); 0366 0367 multipleVolume->setEnabled(packer == "rar" || packer == "arj"); 0368 bool volumeEnabled = multipleVolume->isEnabled() && multipleVolume->isChecked(); 0369 volumeSpinBox->setEnabled(volumeEnabled); 0370 volumeUnitCombo->setEnabled(volumeEnabled); 0371 TextLabel7->setEnabled(volumeEnabled); 0372 0373 /* TODO */ 0374 setCompressionLevel->setEnabled(packer == "rar" || packer == "arj" || packer == "zip" || packer == "7z"); 0375 bool sliderEnabled = setCompressionLevel->isEnabled() && setCompressionLevel->isChecked(); 0376 compressionSlider->setEnabled(sliderEnabled); 0377 minLabel->setEnabled(sliderEnabled); 0378 maxLabel->setEnabled(sliderEnabled); 0379 } 0380 0381 bool PackGUIBase::extraProperties(QMap<QString, QString> &inMap) 0382 { 0383 inMap.clear(); 0384 0385 KConfigGroup group(krConfig, "Archives"); 0386 0387 if (password->isEnabled() && passwordAgain->isEnabled()) { 0388 if (password->text() != passwordAgain->text()) { 0389 KMessageBox::error(this, i18n("Cannot pack, the passwords are different.")); 0390 return false; 0391 } 0392 0393 if (!password->text().isEmpty()) { 0394 inMap["Password"] = password->text(); 0395 0396 if (encryptHeaders->isEnabled() && encryptHeaders->isChecked()) 0397 inMap["EncryptHeaders"] = '1'; 0398 } 0399 } 0400 0401 if (multipleVolume->isEnabled() && multipleVolume->isChecked()) { 0402 KIO::filesize_t size = volumeSpinBox->value(); 0403 0404 switch (volumeUnitCombo->currentIndex()) { 0405 case 2: 0406 size *= 1000; 0407 #if __GNUC__ >= 7 0408 [[gnu::fallthrough]]; 0409 #endif 0410 case 1: 0411 size *= 1000; 0412 default: 0413 break; 0414 } 0415 0416 if (size < 10000) { 0417 KMessageBox::error(this, i18n("Invalid volume size.")); 0418 return false; 0419 } 0420 0421 QString sbuffer; 0422 sbuffer.asprintf("%llu", size); 0423 0424 inMap["VolumeSize"] = sbuffer; 0425 } 0426 0427 if (setCompressionLevel->isEnabled() && setCompressionLevel->isChecked()) { 0428 inMap["CompressionLevel"] = QString("%1").arg(compressionSlider->value()); 0429 int level = compressionSlider->value(); 0430 group.writeEntry("Compression level", level); 0431 } 0432 0433 QString cmdArgs = commandLineSwitches->currentText().trimmed(); 0434 if (!cmdArgs.isEmpty()) { 0435 bool firstChar = true; 0436 QChar quote = QChar::Null; 0437 0438 for (int i = 0; i < cmdArgs.length(); i++) { 0439 QChar ch(cmdArgs[i]); 0440 if (ch.isSpace()) 0441 continue; 0442 0443 if (ch == quote) { 0444 quote = QChar::Null; 0445 continue; 0446 } 0447 0448 if (firstChar && ch != QLatin1Char('-')) { 0449 KMessageBox::error(this, i18n("Invalid command line switch.\nA switch must start with '-'.")); 0450 return false; 0451 } 0452 0453 firstChar = false; 0454 0455 if (quote == QLatin1Char('"')) 0456 continue; 0457 if (quote == QChar::Null && (ch == QLatin1Char('\'') || ch == QLatin1Char('"'))) 0458 quote = ch; 0459 if (ch == QLatin1Char('\\')) { 0460 if (i == cmdArgs.length() - 1) { 0461 KMessageBox::error(this, i18n("Invalid command line switch.\nBackslashes cannot be the last character.")); 0462 return false; 0463 } 0464 i++; 0465 } 0466 } 0467 0468 if (quote != QChar::Null) { 0469 KMessageBox::error(this, i18n("Invalid command line switch.\nUnclosed quotation mark.")); 0470 return false; 0471 } 0472 0473 commandLineSwitches->addToHistory(cmdArgs); 0474 0475 inMap["CommandLineSwitches"] = cmdArgs; 0476 } 0477 0478 return true; 0479 }