1 /*
2     SPDX-FileCopyrightText: 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
3     SPDX-FileCopyrightText: 2009, 2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
4     SPDX-FileCopyrightText: 2015 Elvis Angelaccio <elvis.angelaccio@kde.org>
5     SPDX-FileCopyrightText: 2016 Ragnar Thomsen <rthomsen6@gmail.com>
6 
7     SPDX-License-Identifier: BSD-2-Clause
8 */
9 
10 #include "createdialog.h"
11 #include "archiveformat.h"
12 #include "ark_debug.h"
13 #include "ui_createdialog.h"
14 #include "mimetypes.h"
15 
16 #include <KMessageBox>
17 #include <KSharedConfig>
18 
19 #include <QMimeDatabase>
20 #include <QUrl>
21 
22 namespace Kerfuffle
23 {
24 class CreateDialogUI: public QWidget, public Ui::CreateDialog
25 {
26     Q_OBJECT
27 
28 public:
CreateDialogUI(QWidget * parent=nullptr)29     CreateDialogUI(QWidget *parent = nullptr)
30             : QWidget(parent) {
31         setupUi(this);
32     }
33 };
34 
CreateDialog(QWidget * parent,const QString & caption,const QUrl & startDir)35 CreateDialog::CreateDialog(QWidget *parent,
36                            const QString &caption,
37                            const QUrl &startDir)
38         : QDialog(parent, Qt::Dialog)
39 {
40     setWindowTitle(caption);
41     setModal(true);
42 
43     m_supportedMimeTypes = m_pluginManger.supportedWriteMimeTypes(PluginManager::SortByComment);
44 
45     m_vlayout = new QVBoxLayout();
46     setLayout(m_vlayout);
47 
48     m_ui = new CreateDialogUI(this);
49     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
50 
51     m_ui->destFolderUrlRequester->setMode(KFile::Directory);
52     if (startDir.isEmpty()) {
53         m_ui->destFolderUrlRequester->setUrl(QUrl::fromLocalFile(QDir::currentPath() + QLatin1Char('/')));
54     } else {
55         m_ui->destFolderUrlRequester->setUrl(startDir);
56     }
57 
58     // Populate combobox with mimetypes.
59     for (const QString &type : std::as_const(m_supportedMimeTypes)) {
60         m_ui->mimeComboBox->addItem(QMimeDatabase().mimeTypeForName(type).comment());
61     }
62 
63     connect(m_ui->filenameLineEdit, &QLineEdit::textChanged, this, &CreateDialog::slotFileNameEdited);
64     connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
65     connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
66     connect(this, &QDialog::accepted, this, &CreateDialog::slotUpdateDefaultMimeType);
67     connect(m_ui->mimeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CreateDialog::slotUpdateWidgets);
68     connect(m_ui->mimeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CreateDialog::slotUpdateFilenameExtension);
69 
70     m_vlayout->addWidget(m_ui);
71 
72     m_ui->optionsWidget->setMimeType(currentMimeType());
73 
74     loadConfiguration();
75 
76     layout()->setSizeConstraint(QLayout::SetFixedSize);
77     m_ui->filenameLineEdit->setFocus();
78     slotUpdateFilenameExtension(m_ui->mimeComboBox->currentIndex());
79 }
80 
setFileName(const QString & fileName)81 void CreateDialog::setFileName(const QString &fileName)
82 {
83     m_ui->filenameLineEdit->setText(fileName);
84 
85     const QString detectedSuffix = QMimeDatabase().suffixForFileName(fileName);
86     if (currentMimeType().suffixes().contains(detectedSuffix)) {
87         m_ui->filenameLineEdit->setSelection(0, fileName.length() - detectedSuffix.length() - 1);
88     } else {
89         m_ui->filenameLineEdit->selectAll();
90     }
91 }
92 
slotFileNameEdited(const QString & fileName)93 void CreateDialog::slotFileNameEdited(const QString &fileName)
94 {
95     const QMimeType mimeFromFileName = QMimeDatabase().mimeTypeForFile(fileName, QMimeDatabase::MatchExtension);
96 
97     if (m_supportedMimeTypes.contains(mimeFromFileName.name())) {
98         setMimeType(mimeFromFileName.name());
99     }
100 
101     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!fileName.isEmpty());
102 }
103 
slotUpdateWidgets(int index)104 void CreateDialog::slotUpdateWidgets(int index)
105 {
106     m_ui->optionsWidget->setMimeType(QMimeDatabase().mimeTypeForName(m_supportedMimeTypes.at(index)));
107 }
108 
slotUpdateFilenameExtension(int index)109 void CreateDialog::slotUpdateFilenameExtension(int index)
110 {
111     m_ui->chkAddExtension->setText(i18nc("the argument is a file extension (the period is not a typo)", "Automatically add .%1",
112                                          QMimeDatabase().mimeTypeForName(m_supportedMimeTypes.at(index)).preferredSuffix()));
113 }
114 
selectedUrl() const115 QUrl CreateDialog::selectedUrl() const
116 {
117     QString fileName = m_ui->filenameLineEdit->text();
118     QString dir = m_ui->destFolderUrlRequester->url().toLocalFile();
119     if (dir.trimmed().endsWith(QLatin1Char('/'))) {
120         dir = dir.trimmed();
121     }
122 
123     if (m_ui->chkAddExtension->isChecked()) {
124         QString detectedSuffix = QMimeDatabase().suffixForFileName(m_ui->filenameLineEdit->text().trimmed());
125 
126         if (!currentMimeType().suffixes().contains(detectedSuffix)) {
127             if (!fileName.endsWith(QLatin1Char('.'))) {
128                 fileName.append(QLatin1Char('.'));
129             }
130             fileName.append(currentMimeType().preferredSuffix());
131         }
132     }
133 
134     if (!dir.endsWith(QLatin1Char('/'))) {
135         dir.append(QLatin1Char('/'));
136     }
137     return QUrl::fromLocalFile(dir + fileName);
138 }
139 
compressionLevel() const140 int CreateDialog::compressionLevel() const
141 {
142     return m_ui->optionsWidget->compressionLevel();
143 }
144 
compressionMethod() const145 QString CreateDialog::compressionMethod() const
146 {
147     return m_ui->optionsWidget->compressionMethod();
148 }
149 
encryptionMethod() const150 QString CreateDialog::encryptionMethod() const
151 {
152     return m_ui->optionsWidget->encryptionMethod();
153 }
154 
volumeSize() const155 ulong CreateDialog::volumeSize() const
156 {
157     return m_ui->optionsWidget->volumeSize();
158 }
159 
password() const160 QString CreateDialog::password() const
161 {
162     return m_ui->optionsWidget->password();
163 }
164 
isEncryptionAvailable() const165 bool CreateDialog::isEncryptionAvailable() const
166 {
167     return m_ui->optionsWidget->isEncryptionAvailable();
168 }
169 
isEncryptionEnabled() const170 bool CreateDialog::isEncryptionEnabled() const
171 {
172     return m_ui->optionsWidget->isEncryptionEnabled();
173 }
174 
isHeaderEncryptionAvailable() const175 bool CreateDialog::isHeaderEncryptionAvailable() const
176 {
177     return m_ui->optionsWidget->isHeaderEncryptionAvailable();
178 }
179 
isHeaderEncryptionEnabled() const180 bool CreateDialog::isHeaderEncryptionEnabled() const
181 {
182     return m_ui->optionsWidget->isHeaderEncryptionEnabled();
183 }
184 
accept()185 void CreateDialog::accept()
186 {
187     if (!isEncryptionEnabled()) {
188         QDialog::accept();
189         return;
190     }
191 
192     switch (m_ui->optionsWidget->passwordStatus()) {
193     case KNewPasswordWidget::WeakPassword:
194     case KNewPasswordWidget::StrongPassword:
195         QDialog::accept();
196         break;
197     case KNewPasswordWidget::PasswordNotVerified:
198         KMessageBox::error(nullptr, i18n("The chosen password does not match the given verification password."));
199         break;
200     default:
201         break;
202     }
203 }
204 
slotUpdateDefaultMimeType()205 void CreateDialog::slotUpdateDefaultMimeType()
206 {
207     m_config.writeEntry("LastMimeType", currentMimeType().name());
208 }
209 
loadConfiguration()210 void CreateDialog::loadConfiguration()
211 {
212     m_config = KConfigGroup(KSharedConfig::openConfig()->group("CreateDialog"));
213     QMimeType lastUsedMime = QMimeDatabase().mimeTypeForName(m_config.readEntry("LastMimeType", QStringLiteral("application/x-compressed-tar")));
214     setMimeType(lastUsedMime.name());
215 }
216 
currentMimeType() const217 QMimeType CreateDialog::currentMimeType() const
218 {
219     Q_ASSERT(m_supportedMimeTypes.size() > m_ui->mimeComboBox->currentIndex());
220     return QMimeDatabase().mimeTypeForName(m_supportedMimeTypes.at(m_ui->mimeComboBox->currentIndex()));
221 }
222 
setMimeType(const QString & mimeTypeName)223 bool CreateDialog::setMimeType(const QString &mimeTypeName)
224 {
225     int index = m_supportedMimeTypes.indexOf(mimeTypeName);
226     if (index == -1) {
227         return false;
228     }
229     m_ui->mimeComboBox->setCurrentIndex(index);
230 
231     // This is needed to make sure widgets get updated in case the mimetype is already selected.
232     slotUpdateWidgets(index);
233 
234     return true;
235 }
236 
237 }
238 
239 #include "createdialog.moc"
240