File indexing completed on 2024-06-23 05:14:18
0001 /* utils/overwritedialog.cpp 0002 0003 This file is part of Kleopatra, the KDE keymanager 0004 SPDX-FileCopyrightText: 2023 g10 Code GmbH 0005 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-kleopatra.h> 0011 0012 #include "overwritedialog.h" 0013 0014 #include <QFileInfo> 0015 #include <QHBoxLayout> 0016 #include <QLabel> 0017 #include <QLineEdit> 0018 #include <QMimeDatabase> 0019 #include <QPushButton> 0020 #include <QVBoxLayout> 0021 0022 #include <KFileUtils> 0023 #include <KGuiItem> 0024 #include <KLocalizedString> 0025 #include <KMessageBox> 0026 #include <KSeparator> 0027 #include <KStandardGuiItem> 0028 0029 using namespace Kleo; 0030 0031 class OverwriteDialog::Private 0032 { 0033 Kleo::OverwriteDialog *q; 0034 0035 public: 0036 Private(const QString &filePath, Kleo::OverwriteDialog *qq) 0037 : q{qq} 0038 , fileInfo{filePath} 0039 { 0040 } 0041 0042 void setRenameBoxText(const QString &fileName); 0043 void enableRenameButton(const QString &newName); 0044 void suggestNewNamePressed(); 0045 QString newFileName() const; 0046 0047 void renamePressed(); 0048 void renameAllPressed(); 0049 void skipPressed(); 0050 void skipAllPressed(); 0051 void overwritePressed(); 0052 void overwriteAllPressed(); 0053 void cancelPressed(); 0054 0055 void done(Result result) 0056 { 0057 q->done(static_cast<int>(result)); 0058 } 0059 0060 QLineEdit *newNameEdit = nullptr; 0061 QPushButton *suggestNewNameBtn = nullptr; 0062 QPushButton *renameBtn = nullptr; 0063 QPushButton *renameAllBtn = nullptr; 0064 QPushButton *skipBtn = nullptr; 0065 QPushButton *skipAllBtn = nullptr; 0066 QPushButton *overwriteBtn = nullptr; 0067 QPushButton *overwriteAllBtn = nullptr; 0068 QPushButton *cancelBtn = nullptr; 0069 QFileInfo fileInfo; 0070 }; 0071 0072 void OverwriteDialog::Private::setRenameBoxText(const QString &fileName) 0073 { 0074 // sets the text in file name line edit box, selecting the filename (but not the extension if there is one). 0075 QMimeDatabase db; 0076 const auto extension = db.suffixForFileName(fileName); 0077 newNameEdit->setText(fileName); 0078 0079 if (!extension.isEmpty()) { 0080 const int selectionLength = fileName.length() - extension.length() - 1; 0081 newNameEdit->setSelection(0, selectionLength); 0082 } else { 0083 newNameEdit->selectAll(); 0084 } 0085 } 0086 0087 void OverwriteDialog::Private::enableRenameButton(const QString &newName) 0088 { 0089 if (!newName.isEmpty() && (newName != fileInfo.fileName())) { 0090 renameBtn->setEnabled(true); 0091 renameBtn->setDefault(true); 0092 0093 if (renameAllBtn) { 0094 renameAllBtn->setEnabled(false); 0095 } 0096 if (overwriteBtn) { 0097 overwriteBtn->setEnabled(false); 0098 } 0099 if (overwriteAllBtn) { 0100 overwriteAllBtn->setEnabled(false); 0101 } 0102 } else { 0103 renameBtn->setEnabled(false); 0104 0105 if (renameAllBtn) { 0106 renameAllBtn->setEnabled(true); 0107 } 0108 if (overwriteBtn) { 0109 overwriteBtn->setEnabled(true); 0110 } 0111 if (overwriteAllBtn) { 0112 overwriteAllBtn->setEnabled(true); 0113 } 0114 } 0115 } 0116 0117 void OverwriteDialog::Private::suggestNewNamePressed() 0118 { 0119 if (!newNameEdit->text().isEmpty()) { 0120 setRenameBoxText(KFileUtils::suggestName(QUrl::fromLocalFile(fileInfo.absolutePath()), newNameEdit->text())); 0121 } else { 0122 setRenameBoxText(KFileUtils::suggestName(QUrl::fromLocalFile(fileInfo.absolutePath()), fileInfo.fileName())); 0123 } 0124 } 0125 0126 QString OverwriteDialog::Private::newFileName() const 0127 { 0128 return fileInfo.path() + QLatin1Char{'/'} + newNameEdit->text(); 0129 } 0130 0131 void OverwriteDialog::Private::renamePressed() 0132 { 0133 if (newNameEdit->text().isEmpty()) { 0134 return; 0135 } 0136 const auto fileName = newFileName(); 0137 if (QFileInfo::exists(fileName)) { 0138 KMessageBox::error(q, xi18nc("@info", "The file <filename>%1</filename> already exists. Please enter a different file name.", fileName)); 0139 return; 0140 } 0141 done(Result::Rename); 0142 } 0143 0144 void OverwriteDialog::Private::renameAllPressed() 0145 { 0146 done(Result::AutoRename); 0147 } 0148 0149 void OverwriteDialog::Private::skipPressed() 0150 { 0151 done(Result::Skip); 0152 } 0153 0154 void OverwriteDialog::Private::skipAllPressed() 0155 { 0156 done(Result::AutoSkip); 0157 } 0158 0159 void OverwriteDialog::Private::overwritePressed() 0160 { 0161 done(Result::Overwrite); 0162 } 0163 0164 void OverwriteDialog::Private::overwriteAllPressed() 0165 { 0166 done(Result::OverwriteAll); 0167 } 0168 0169 void OverwriteDialog::Private::cancelPressed() 0170 { 0171 done(Result::Cancel); 0172 } 0173 0174 OverwriteDialog::OverwriteDialog(QWidget *parent, const QString &title, const QString &fileName, Options options) 0175 : QDialog{parent} 0176 , d{new Private{fileName, this}} 0177 { 0178 setObjectName(QLatin1StringView("Kleo::OverwriteDialog")); 0179 0180 setWindowTitle(title); 0181 0182 auto mainLayout = new QVBoxLayout{this}; 0183 mainLayout->addStrut(400); // makes dlg at least that wide 0184 0185 mainLayout->addWidget(new QLabel{xi18nc("@info", "The file <filename>%1</filename> already exists.", fileName), this}); 0186 0187 if (options & AllowRename) { 0188 mainLayout->addSpacing(15); 0189 0190 auto label = new QLabel{i18nc("@label", "Rename:"), this}; 0191 mainLayout->addWidget(label); 0192 0193 auto hbox = new QHBoxLayout; 0194 0195 d->newNameEdit = new QLineEdit{this}; 0196 label->setBuddy(d->newNameEdit); 0197 hbox->addWidget(d->newNameEdit); 0198 0199 d->suggestNewNameBtn = new QPushButton{i18nc("@action:button", "Suggest New Name"), this}; 0200 d->suggestNewNameBtn->setToolTip(i18nc("@info:tooltip", "Suggest a file name that does not already exist.")); 0201 hbox->addWidget(d->suggestNewNameBtn); 0202 0203 mainLayout->addLayout(hbox); 0204 } 0205 0206 mainLayout->addWidget(new KSeparator{this}); 0207 0208 auto buttonLayout = new QHBoxLayout; 0209 0210 if (options & AllowRename) { 0211 d->renameBtn = new QPushButton{i18nc("@action:button", "Rename"), this}; 0212 d->renameBtn->setToolTip(i18nc("@info:tooltip", "Save the file with the given name.")); 0213 d->renameBtn->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); 0214 d->renameBtn->setEnabled(false); 0215 buttonLayout->addWidget(d->renameBtn); 0216 0217 if (options & MultipleItems) { 0218 d->renameAllBtn = new QPushButton{i18nc("@action:button", "Rename All"), this}; 0219 d->renameAllBtn->setIcon(d->renameBtn->icon()); 0220 d->renameAllBtn->setToolTip( 0221 i18nc("@info:tooltip", "Automatically save all files that would overwrite an already existing file with a different name.")); 0222 buttonLayout->addWidget(d->renameAllBtn); 0223 } 0224 } 0225 0226 if ((options & AllowSkip) && (options & MultipleItems)) { 0227 d->skipBtn = new QPushButton{i18nc("@action:button", "Skip"), this}; 0228 d->skipBtn->setIcon(QIcon::fromTheme(QStringLiteral("go-next-skip"))); 0229 d->skipBtn->setToolTip(i18nc("@info:tooltip", "Do not write this file, skip to the next one instead.")); 0230 buttonLayout->addWidget(d->skipBtn); 0231 0232 d->skipAllBtn = new QPushButton{i18nc("@action:button", "Skip All"), this}; 0233 d->skipAllBtn->setIcon(d->skipBtn->icon()); 0234 d->skipAllBtn->setToolTip(i18nc("@info:tooltip", "Do not write this file and any other files that would overwrite an already existing file.")); 0235 buttonLayout->addWidget(d->skipAllBtn); 0236 } 0237 0238 d->overwriteBtn = new QPushButton{i18nc("@action:button", "Overwrite"), this}; 0239 d->overwriteBtn->setIcon(KStandardGuiItem::overwrite().icon()); 0240 d->overwriteBtn->setToolTip(i18nc("@info:tooltip", "Overwrite the existing file.")); 0241 buttonLayout->addWidget(d->overwriteBtn); 0242 0243 if (options & MultipleItems) { 0244 d->overwriteAllBtn = new QPushButton{i18nc("@action:button", "Overwrite All"), this}; 0245 d->overwriteAllBtn->setIcon(d->overwriteBtn->icon()); 0246 d->overwriteAllBtn->setToolTip(i18nc("@info:tooltip", "Overwrite the existing file and any other files that already exist.")); 0247 buttonLayout->addWidget(d->overwriteAllBtn); 0248 } 0249 0250 d->cancelBtn = new QPushButton{this}; 0251 KGuiItem::assign(d->cancelBtn, KStandardGuiItem::cancel()); 0252 d->cancelBtn->setDefault(true); 0253 buttonLayout->addWidget(d->cancelBtn); 0254 0255 mainLayout->addLayout(buttonLayout); 0256 0257 if (d->newNameEdit) { 0258 d->setRenameBoxText(d->fileInfo.fileName()); 0259 connect(d->newNameEdit, &QLineEdit::textChanged, this, [this](const QString &text) { 0260 d->enableRenameButton(text); 0261 }); 0262 connect(d->suggestNewNameBtn, &QAbstractButton::clicked, this, [this]() { 0263 d->suggestNewNamePressed(); 0264 }); 0265 } 0266 if (d->renameBtn) { 0267 connect(d->renameBtn, &QAbstractButton::clicked, this, [this]() { 0268 d->renamePressed(); 0269 }); 0270 } 0271 if (d->renameAllBtn) { 0272 connect(d->renameAllBtn, &QAbstractButton::clicked, this, [this]() { 0273 d->renameAllPressed(); 0274 }); 0275 } 0276 if (d->skipBtn) { 0277 connect(d->skipBtn, &QAbstractButton::clicked, this, [this]() { 0278 d->skipPressed(); 0279 }); 0280 connect(d->skipAllBtn, &QAbstractButton::clicked, this, [this]() { 0281 d->skipAllPressed(); 0282 }); 0283 } 0284 connect(d->overwriteBtn, &QAbstractButton::clicked, this, [this]() { 0285 d->overwritePressed(); 0286 }); 0287 if (d->overwriteAllBtn) { 0288 connect(d->overwriteAllBtn, &QAbstractButton::clicked, this, [this]() { 0289 d->overwriteAllPressed(); 0290 }); 0291 } 0292 connect(d->cancelBtn, &QAbstractButton::clicked, this, [this]() { 0293 d->cancelPressed(); 0294 }); 0295 0296 if (d->newNameEdit) { 0297 d->newNameEdit->setFocus(); 0298 } 0299 0300 resize(sizeHint()); 0301 } 0302 0303 OverwriteDialog::~OverwriteDialog() = default; 0304 0305 QString OverwriteDialog::newFileName() const 0306 { 0307 if (result() == Result::Rename) { 0308 return d->newFileName(); 0309 } 0310 return {}; 0311 } 0312 0313 #include "moc_overwritedialog.cpp"