Fix create archive.
[kdepim.git] / kmail / dialog / archivefolderdialog.cpp
blob0e852bc5b2a0e05d66a4fdcc8423e464867e43c6
1 /* Copyright 2009 Klarälvdalens Datakonsult AB
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License as
5 published by the Free Software Foundation; either version 2 of
6 the License or (at your option) version 3 or any later version
7 accepted by the membership of KDE e.V. (or its successor approved
8 by the membership of KDE e.V.), which shall act as a proxy
9 defined in Section 14 of version 3 of the license.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "archivefolderdialog.h"
21 #include "MailCommon/BackupJob"
22 #include "kmkernel.h"
23 #include "kmmainwidget.h"
24 #include "MailCommon/FolderRequester"
25 #include "MessageViewer/MessageViewerUtil"
27 #include <AkonadiCore/Collection>
29 #include <KLocalizedString>
30 #include <kcombobox.h>
31 #include <kurlrequester.h>
32 #include <kmessagebox.h>
33 #include <KSeparator>
35 #include <qlabel.h>
36 #include <qcheckbox.h>
37 #include <QGridLayout>
38 #include <QStandardPaths>
39 #include <QMimeDatabase>
40 #include <KConfigGroup>
41 #include <QDialogButtonBox>
42 #include <QPushButton>
43 #include <QVBoxLayout>
45 using namespace KMail;
46 using namespace MailCommon;
48 QString ArchiveFolderDialog::standardArchivePath(const QString &folderName)
50 QString currentPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
51 QDir dir(currentPath);
52 if (!dir.exists()) {
53 currentPath = QDir::homePath();
55 return currentPath + QLatin1Char('/') +
56 i18nc("Start of the filename for a mail archive file", "Archive") + QLatin1Char('_') + folderName + QLatin1Char('_') + QDate::currentDate().toString(Qt::ISODate) + QLatin1String(".tar.bz2");
59 ArchiveFolderDialog::ArchiveFolderDialog(QWidget *parent)
60 : QDialog(parent), mParentWidget(parent)
62 setObjectName(QStringLiteral("archive_folder_dialog"));
63 setWindowTitle(i18nc("@title:window for archiving a folder", "Archive Folder"));
64 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
65 QVBoxLayout *topLayout = new QVBoxLayout;
66 setLayout(topLayout);
67 mOkButton = buttonBox->button(QDialogButtonBox::Ok);
68 mOkButton->setDefault(true);
69 mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
70 connect(buttonBox, &QDialogButtonBox::accepted, this, &ArchiveFolderDialog::slotAccepted);
71 connect(buttonBox, &QDialogButtonBox::rejected, this, &ArchiveFolderDialog::reject);
72 mOkButton->setDefault(true);
73 mOkButton->setText(i18nc("@action", "Archive"));
74 setModal(true);
75 QWidget *mainWidget = new QWidget(this);
76 topLayout->addWidget(mainWidget);
77 topLayout->addWidget(buttonBox);
78 QGridLayout *mainLayout = new QGridLayout(mainWidget);
80 int row = 0;
82 // TODO: Explaination label
84 QLabel *folderLabel = new QLabel(i18n("&Folder:"), mainWidget);
85 mainLayout->addWidget(folderLabel, row, 0);
86 mFolderRequester = new FolderRequester(mainWidget);
87 mFolderRequester->setMustBeReadWrite(false);
88 mFolderRequester->setNotAllowToCreateNewFolder(true);
89 connect(mFolderRequester, &FolderRequester::folderChanged, this, &ArchiveFolderDialog::slotFolderChanged);
90 folderLabel->setBuddy(mFolderRequester);
91 mainLayout->addWidget(mFolderRequester, row, 1);
92 row++;
94 QLabel *formatLabel = new QLabel(i18n("F&ormat:"), mainWidget);
95 mainLayout->addWidget(formatLabel, row, 0);
96 mFormatComboBox = new KComboBox(mainWidget);
97 formatLabel->setBuddy(mFormatComboBox);
99 // These combobox values have to stay in sync with the ArchiveType enum from BackupJob!
100 mFormatComboBox->addItem(i18n("Compressed Zip Archive (.zip)"));
101 mFormatComboBox->addItem(i18n("Uncompressed Archive (.tar)"));
102 mFormatComboBox->addItem(i18n("BZ2-Compressed Tar Archive (.tar.bz2)"));
103 mFormatComboBox->addItem(i18n("GZ-Compressed Tar Archive (.tar.gz)"));
104 mFormatComboBox->setCurrentIndex(2);
105 connect(mFormatComboBox, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), this, &ArchiveFolderDialog::slotFixFileExtension);
106 mainLayout->addWidget(mFormatComboBox, row, 1);
107 row++;
109 QLabel *fileNameLabel = new QLabel(i18n("&Archive File:"), mainWidget);
110 mainLayout->addWidget(fileNameLabel, row, 0);
111 mUrlRequester = new KUrlRequester(mainWidget);
112 mUrlRequester->setMode(KFile::LocalOnly | KFile::File);
113 mUrlRequester->setFilter(QStringLiteral("*.tar *.zip *.tar.gz *.tar.bz2"));
114 fileNameLabel->setBuddy(mUrlRequester);
115 connect(mUrlRequester, &KUrlRequester::urlSelected, this, &ArchiveFolderDialog::slotFixFileExtension);
116 connect(mUrlRequester, &KUrlRequester::textChanged, this, &ArchiveFolderDialog::slotUrlChanged);
117 mainLayout->addWidget(mUrlRequester, row, 1);
118 row++;
120 // TODO: Make this appear more dangerous!
121 mDeleteCheckBox = new QCheckBox(i18n("&Delete folder and subfolders after completion"), mainWidget);
122 mainLayout->addWidget(mDeleteCheckBox, row, 0, 1, 2, Qt::AlignLeft);
123 row++;
125 mRecursiveCheckBox = new QCheckBox(i18n("Archive all subfolders"), mainWidget);
126 connect(mRecursiveCheckBox, &QCheckBox::clicked, this, &ArchiveFolderDialog::slotRecursiveCheckboxClicked);
127 mainLayout->addWidget(mRecursiveCheckBox, row, 0, 1, 2, Qt::AlignLeft);
128 mRecursiveCheckBox->setChecked(true);
129 row++;
131 // TODO: what's this, tooltips
133 // TODO: Warn that user should do mail check for online IMAP and possibly cached IMAP as well
135 mainLayout->addWidget(new KSeparator(), row, 0, 1, 2);
136 row++;
137 mainLayout->setColumnStretch(1, 1);
138 mainLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding), row, 0);
140 // Make it a bit bigger, else the folder requester cuts off the text too early
141 resize(500, minimumSize().height());
144 bool canRemoveFolder(const Akonadi::Collection &col)
146 const QSharedPointer<FolderCollection> folder = FolderCollection::forCollection(col, false);
147 return folder
148 && col.isValid()
149 && !col.isVirtual()
150 && (col.rights() & Akonadi::Collection::CanDeleteCollection)
151 && !folder->isStructural()
152 && !folder->isSystemFolder();
155 void ArchiveFolderDialog::slotRecursiveCheckboxClicked()
157 slotFolderChanged(mFolderRequester->collection());
160 void ArchiveFolderDialog::slotFolderChanged(const Akonadi::Collection &folder)
162 mDeleteCheckBox->setEnabled(allowToDeleteFolders(folder));
165 bool ArchiveFolderDialog::allowToDeleteFolders(const Akonadi::Collection &folder) const
167 return canRemoveFolder(folder) && mRecursiveCheckBox->isChecked();
170 void ArchiveFolderDialog::setFolder(const Akonadi::Collection &defaultCollection)
172 mFolderRequester->setCollection(defaultCollection);
173 // TODO: what if the file already exists?
174 mUrlRequester->setUrl(standardArchivePath(defaultCollection.name()));
175 const QSharedPointer<FolderCollection> folder = FolderCollection::forCollection(defaultCollection, false);
176 mDeleteCheckBox->setEnabled(allowToDeleteFolders(defaultCollection));
177 mOkButton->setEnabled(defaultCollection.isValid() && folder && !folder->isStructural());
180 void ArchiveFolderDialog::slotAccepted()
182 if (!MessageViewer::Util::checkOverwrite(mUrlRequester->url(), this)) {
183 return;
186 if (!mFolderRequester->hasCollection()) {
187 KMessageBox::information(this, i18n("Please select the folder that should be archived."),
188 i18n("No folder selected"));
189 return;
192 MailCommon::BackupJob *backupJob = new MailCommon::BackupJob(mParentWidget);
193 backupJob->setRootFolder(mFolderRequester->collection());
194 backupJob->setSaveLocation(mUrlRequester->url());
195 backupJob->setArchiveType(static_cast<BackupJob::ArchiveType>(mFormatComboBox->currentIndex()));
196 backupJob->setDeleteFoldersAfterCompletion(mDeleteCheckBox->isEnabled() && mDeleteCheckBox->isChecked());
197 backupJob->setRecursive(mRecursiveCheckBox->isChecked());
198 backupJob->start();
199 accept();
202 void ArchiveFolderDialog::slotFixFileExtension()
204 const int numExtensions = 4;
205 // The extensions here are also sorted, like the enum order of BackupJob::ArchiveType
206 const char *extensions[numExtensions] = { ".zip", ".tar", ".tar.bz2", ".tar.gz" };
208 QString fileName = mUrlRequester->url().path();
209 if (fileName.isEmpty())
210 fileName = standardArchivePath(mFolderRequester->hasCollection() ?
211 mFolderRequester->collection().name() : QString());
213 QMimeDatabase db;
214 const QString extension = db.suffixForFileName(fileName);
215 if (!extension.isEmpty()) {
216 fileName = fileName.left(fileName.length() - extension.length() - 1);
219 // Now, we've got a filename without an extension, simply append the correct one
220 fileName += QLatin1String(extensions[mFormatComboBox->currentIndex()]);
221 mUrlRequester->setUrl(fileName);
224 void ArchiveFolderDialog::slotUrlChanged(const QString &url)
226 mOkButton->setEnabled(!url.isEmpty());