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
);
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);
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);
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);
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
);
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);
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);
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);
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)) {
186 if (!mFolderRequester
->hasCollection()) {
187 KMessageBox::information(this, i18n("Please select the folder that should be archived."),
188 i18n("No folder selected"));
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());
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());
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());