Remove double margin
[kdepim.git] / kmail / src / dialog / archivefolderdialog.cpp
blob45f0b1ebeb6b3782d2932d21aa74d935d6c4ef0e
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);
79 mainLayout->setMargin(0);
81 int row = 0;
83 // TODO: Explaination label
85 QLabel *folderLabel = new QLabel(i18n("&Folder:"), mainWidget);
86 mainLayout->addWidget(folderLabel, row, 0);
87 mFolderRequester = new FolderRequester(mainWidget);
88 mFolderRequester->setMustBeReadWrite(false);
89 mFolderRequester->setNotAllowToCreateNewFolder(true);
90 connect(mFolderRequester, &FolderRequester::folderChanged, this, &ArchiveFolderDialog::slotFolderChanged);
91 folderLabel->setBuddy(mFolderRequester);
92 mainLayout->addWidget(mFolderRequester, row, 1);
93 row++;
95 QLabel *formatLabel = new QLabel(i18n("F&ormat:"), mainWidget);
96 mainLayout->addWidget(formatLabel, row, 0);
97 mFormatComboBox = new KComboBox(mainWidget);
98 formatLabel->setBuddy(mFormatComboBox);
100 // These combobox values have to stay in sync with the ArchiveType enum from BackupJob!
101 mFormatComboBox->addItem(i18n("Compressed Zip Archive (.zip)"));
102 mFormatComboBox->addItem(i18n("Uncompressed Archive (.tar)"));
103 mFormatComboBox->addItem(i18n("BZ2-Compressed Tar Archive (.tar.bz2)"));
104 mFormatComboBox->addItem(i18n("GZ-Compressed Tar Archive (.tar.gz)"));
105 mFormatComboBox->setCurrentIndex(2);
106 connect(mFormatComboBox, static_cast<void (KComboBox::*)(int)>(&KComboBox::activated), this, &ArchiveFolderDialog::slotFixFileExtension);
107 mainLayout->addWidget(mFormatComboBox, row, 1);
108 row++;
110 QLabel *fileNameLabel = new QLabel(i18n("&Archive File:"), mainWidget);
111 mainLayout->addWidget(fileNameLabel, row, 0);
112 mUrlRequester = new KUrlRequester(mainWidget);
113 mUrlRequester->setMode(KFile::LocalOnly | KFile::File);
114 mUrlRequester->setFilter(QStringLiteral("*.tar *.zip *.tar.gz *.tar.bz2"));
115 fileNameLabel->setBuddy(mUrlRequester);
116 connect(mUrlRequester, &KUrlRequester::urlSelected, this, &ArchiveFolderDialog::slotFixFileExtension);
117 connect(mUrlRequester, &KUrlRequester::textChanged, this, &ArchiveFolderDialog::slotUrlChanged);
118 mainLayout->addWidget(mUrlRequester, row, 1);
119 row++;
121 // TODO: Make this appear more dangerous!
122 mDeleteCheckBox = new QCheckBox(i18n("&Delete folder and subfolders after completion"), mainWidget);
123 mainLayout->addWidget(mDeleteCheckBox, row, 0, 1, 2, Qt::AlignLeft);
124 row++;
126 mRecursiveCheckBox = new QCheckBox(i18n("Archive all subfolders"), mainWidget);
127 connect(mRecursiveCheckBox, &QCheckBox::clicked, this, &ArchiveFolderDialog::slotRecursiveCheckboxClicked);
128 mainLayout->addWidget(mRecursiveCheckBox, row, 0, 1, 2, Qt::AlignLeft);
129 mRecursiveCheckBox->setChecked(true);
130 row++;
132 // TODO: what's this, tooltips
134 // TODO: Warn that user should do mail check for online IMAP and possibly cached IMAP as well
136 mainLayout->addWidget(new KSeparator(), row, 0, 1, 2);
137 row++;
138 mainLayout->setColumnStretch(1, 1);
139 mainLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding), row, 0);
141 // Make it a bit bigger, else the folder requester cuts off the text too early
142 resize(500, minimumSize().height());
145 bool canRemoveFolder(const Akonadi::Collection &col)
147 const QSharedPointer<FolderCollection> folder = FolderCollection::forCollection(col, false);
148 return folder
149 && col.isValid()
150 && !col.isVirtual()
151 && (col.rights() & Akonadi::Collection::CanDeleteCollection)
152 && !folder->isStructural()
153 && !folder->isSystemFolder();
156 void ArchiveFolderDialog::slotRecursiveCheckboxClicked()
158 slotFolderChanged(mFolderRequester->collection());
161 void ArchiveFolderDialog::slotFolderChanged(const Akonadi::Collection &folder)
163 mDeleteCheckBox->setEnabled(allowToDeleteFolders(folder));
166 bool ArchiveFolderDialog::allowToDeleteFolders(const Akonadi::Collection &folder) const
168 return canRemoveFolder(folder) && mRecursiveCheckBox->isChecked();
171 void ArchiveFolderDialog::setFolder(const Akonadi::Collection &defaultCollection)
173 mFolderRequester->setCollection(defaultCollection);
174 // TODO: what if the file already exists?
175 mUrlRequester->setUrl(QUrl::fromLocalFile(standardArchivePath(defaultCollection.name())));
176 const QSharedPointer<FolderCollection> folder = FolderCollection::forCollection(defaultCollection, false);
177 mDeleteCheckBox->setEnabled(allowToDeleteFolders(defaultCollection));
178 mOkButton->setEnabled(defaultCollection.isValid() && folder && !folder->isStructural());
181 void ArchiveFolderDialog::slotAccepted()
183 if (!MessageViewer::Util::checkOverwrite(mUrlRequester->url(), this)) {
184 return;
187 if (!mFolderRequester->hasCollection()) {
188 KMessageBox::information(this, i18n("Please select the folder that should be archived."),
189 i18n("No folder selected"));
190 return;
193 MailCommon::BackupJob *backupJob = new MailCommon::BackupJob(mParentWidget);
194 backupJob->setRootFolder(mFolderRequester->collection());
195 backupJob->setSaveLocation(mUrlRequester->url());
196 backupJob->setArchiveType(static_cast<BackupJob::ArchiveType>(mFormatComboBox->currentIndex()));
197 backupJob->setDeleteFoldersAfterCompletion(mDeleteCheckBox->isEnabled() && mDeleteCheckBox->isChecked());
198 backupJob->setRecursive(mRecursiveCheckBox->isChecked());
199 backupJob->start();
200 accept();
203 void ArchiveFolderDialog::slotFixFileExtension()
205 const int numExtensions = 4;
206 // The extensions here are also sorted, like the enum order of BackupJob::ArchiveType
207 const char *extensions[numExtensions] = { ".zip", ".tar", ".tar.bz2", ".tar.gz" };
209 QString fileName = mUrlRequester->url().path();
210 if (fileName.isEmpty())
211 fileName = standardArchivePath(mFolderRequester->hasCollection() ?
212 mFolderRequester->collection().name() : QString());
214 QMimeDatabase db;
215 const QString extension = db.suffixForFileName(fileName);
216 if (!extension.isEmpty()) {
217 fileName = fileName.left(fileName.length() - extension.length() - 1);
220 // Now, we've got a filename without an extension, simply append the correct one
221 fileName += QLatin1String(extensions[mFormatComboBox->currentIndex()]);
222 mUrlRequester->setUrl(QUrl::fromLocalFile(fileName));
225 void ArchiveFolderDialog::slotUrlChanged(const QString &url)
227 mOkButton->setEnabled(!url.isEmpty());