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"
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>
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
);
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
;
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"));
75 QWidget
*mainWidget
= new QWidget(this);
76 topLayout
->addWidget(mainWidget
);
77 topLayout
->addWidget(buttonBox
);
78 QGridLayout
*mainLayout
= new QGridLayout(mainWidget
);
79 mainLayout
->setMargin(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);
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);
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);
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
);
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);
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);
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);
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)) {
187 if (!mFolderRequester
->hasCollection()) {
188 KMessageBox::information(this, i18n("Please select the folder that should be archived."),
189 i18n("No folder selected"));
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());
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());
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());