1 /*
2 SPDX-FileCopyrightText: 2013-2021 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "selectiontypetreewidget.h"
8 #include "core/utils.h"
9 #include "core/xml/templateselection.h"
10
11 #include <PimCommon/PimUtil>
12
13 #include <QFileDialog>
14
15 #include <KLocalizedString>
16 #include <QTemporaryFile>
17
18 #include "gui/pimdataexportgui_debug.h"
19 #include <QHeaderView>
20 #include <QPointer>
21 #include <QTreeWidgetItem>
22
SelectionTypeTreeWidget(bool backupData,QWidget * parent)23 SelectionTypeTreeWidget::SelectionTypeTreeWidget(bool backupData, QWidget *parent)
24 : QTreeWidget(parent)
25 {
26 initialize(backupData);
27 expandAll();
28 header()->hide();
29 }
30
~SelectionTypeTreeWidget()31 SelectionTypeTreeWidget::~SelectionTypeTreeWidget()
32 {
33 }
34
initialize(bool backupData)35 void SelectionTypeTreeWidget::initialize(bool backupData)
36 {
37 mKmailItem = new QTreeWidgetItem(this);
38 mKmailItem->setCheckState(0, Qt::Checked);
39 mKmailItem->setText(0, Utils::appTypeToI18n(Utils::KMail));
40 createSubItem(mKmailItem, Utils::Identity);
41 createSubItem(mKmailItem, Utils::Mails);
42 createSubItem(mKmailItem, Utils::MailTransport);
43 createSubItem(mKmailItem, Utils::Resources);
44 createSubItem(mKmailItem, Utils::Config);
45
46 mKaddressbookItem = new QTreeWidgetItem(this);
47 mKaddressbookItem->setText(0, Utils::appTypeToI18n(Utils::KAddressBook));
48 mKaddressbookItem->setCheckState(0, Qt::Checked);
49 createSubItem(mKaddressbookItem, Utils::Resources);
50 createSubItem(mKaddressbookItem, Utils::Config);
51
52 mKalarmItem = new QTreeWidgetItem(this);
53 mKalarmItem->setText(0, Utils::appTypeToI18n(Utils::KAlarm));
54 mKalarmItem->setCheckState(0, Qt::Checked);
55 createSubItem(mKalarmItem, Utils::Resources);
56 createSubItem(mKalarmItem, Utils::Config);
57
58 mKorganizerItem = new QTreeWidgetItem(this);
59 mKorganizerItem->setText(0, Utils::appTypeToI18n(Utils::KOrganizer));
60 mKorganizerItem->setCheckState(0, Qt::Checked);
61 createSubItem(mKorganizerItem, Utils::Resources);
62 createSubItem(mKorganizerItem, Utils::Config);
63
64 mKNotesItem = new QTreeWidgetItem(this);
65 mKNotesItem->setText(0, Utils::appTypeToI18n(Utils::KNotes));
66 mKNotesItem->setCheckState(0, Qt::Checked);
67 createSubItem(mKNotesItem, Utils::Resources);
68 createSubItem(mKNotesItem, Utils::Config);
69 if (!backupData) {
70 createSubItem(mKNotesItem, Utils::Data);
71 }
72
73 mAkregatorItem = new QTreeWidgetItem(this);
74 mAkregatorItem->setText(0, Utils::appTypeToI18n(Utils::Akregator));
75 mAkregatorItem->setCheckState(0, Qt::Checked);
76 createSubItem(mAkregatorItem, Utils::Config);
77 createSubItem(mAkregatorItem, Utils::Data);
78
79 connect(this, &SelectionTypeTreeWidget::itemChanged, this, &SelectionTypeTreeWidget::slotItemChanged);
80 }
81
removeNotSelectedItems()82 void SelectionTypeTreeWidget::removeNotSelectedItems()
83 {
84 if (!removeNotSelectedItem(mKmailItem)) {
85 delete mKmailItem;
86 mKmailItem = nullptr;
87 }
88 if (!removeNotSelectedItem(mKalarmItem)) {
89 delete mKalarmItem;
90 mKalarmItem = nullptr;
91 }
92 if (!removeNotSelectedItem(mKaddressbookItem)) {
93 delete mKaddressbookItem;
94 mKaddressbookItem = nullptr;
95 }
96 if (!removeNotSelectedItem(mKorganizerItem)) {
97 delete mKorganizerItem;
98 mKorganizerItem = nullptr;
99 }
100 if (!removeNotSelectedItem(mKNotesItem)) {
101 delete mKNotesItem;
102 mKNotesItem = nullptr;
103 }
104 if (!removeNotSelectedItem(mAkregatorItem)) {
105 delete mAkregatorItem;
106 mAkregatorItem = nullptr;
107 }
108 }
109
removeNotSelectedItem(QTreeWidgetItem * parent)110 bool SelectionTypeTreeWidget::removeNotSelectedItem(QTreeWidgetItem *parent)
111 {
112 for (int i = parent->childCount() - 1; i >= 0; --i) {
113 QTreeWidgetItem *item = parent->child(i);
114 if (item->checkState(0) == Qt::Unchecked) {
115 delete item;
116 }
117 }
118 bool hasChildren = (parent->childCount() != 0);
119 if (hasChildren) {
120 parent->setCheckState(0, Qt::Checked);
121 }
122 return hasChildren;
123 }
124
storedType() const125 QHash<Utils::AppsType, Utils::importExportParameters> SelectionTypeTreeWidget::storedType() const
126 {
127 QHash<Utils::AppsType, Utils::importExportParameters> stored;
128 Utils::importExportParameters var = typeChecked(mKmailItem);
129 if (!var.isEmpty()) {
130 stored.insert(Utils::KMail, var);
131 }
132 var = typeChecked(mKalarmItem);
133 if (!var.isEmpty()) {
134 stored.insert(Utils::KAlarm, var);
135 }
136 var = typeChecked(mKaddressbookItem);
137 if (!var.isEmpty()) {
138 stored.insert(Utils::KAddressBook, var);
139 }
140 var = typeChecked(mKorganizerItem);
141 if (!var.isEmpty()) {
142 stored.insert(Utils::KOrganizer, var);
143 }
144 var = typeChecked(mKNotesItem);
145 if (!var.isEmpty()) {
146 stored.insert(Utils::KNotes, var);
147 }
148 var = typeChecked(mAkregatorItem);
149 if (!var.isEmpty()) {
150 stored.insert(Utils::Akregator, var);
151 }
152 return stored;
153 }
154
typeChecked(QTreeWidgetItem * parent) const155 Utils::importExportParameters SelectionTypeTreeWidget::typeChecked(QTreeWidgetItem *parent) const
156 {
157 Utils::importExportParameters parameters;
158 if (parent) {
159 int numberOfStep = 0;
160 Utils::StoredTypes types = Utils::None;
161 for (int i = 0; i < parent->childCount(); ++i) {
162 QTreeWidgetItem *item = parent->child(i);
163 if (item->checkState(0) == Qt::Checked) {
164 types |= static_cast<Utils::StoredType>(item->data(0, action).toInt());
165 ++numberOfStep;
166 }
167 }
168 parameters.types = types;
169 parameters.numberSteps = numberOfStep;
170 }
171 return parameters;
172 }
173
createSubItem(QTreeWidgetItem * parent,Utils::StoredType type)174 void SelectionTypeTreeWidget::createSubItem(QTreeWidgetItem *parent, Utils::StoredType type)
175 {
176 switch (type) {
177 case Utils::None:
178 break;
179 case Utils::Identity: {
180 auto item = new QTreeWidgetItem(parent);
181 item->setText(0, Utils::storedTypeToI18n(Utils::Identity));
182 item->setCheckState(0, Qt::Checked);
183 item->setData(0, action, type);
184 break;
185 }
186 case Utils::Mails: {
187 auto item = new QTreeWidgetItem(parent);
188 item->setText(0, Utils::storedTypeToI18n(Utils::Mails));
189 item->setCheckState(0, Qt::Checked);
190 item->setData(0, action, type);
191 break;
192 }
193 case Utils::MailTransport: {
194 auto item = new QTreeWidgetItem(parent);
195 item->setText(0, Utils::storedTypeToI18n(Utils::MailTransport));
196 item->setCheckState(0, Qt::Checked);
197 item->setData(0, action, type);
198 break;
199 }
200 case Utils::Resources: {
201 auto item = new QTreeWidgetItem(parent);
202 item->setText(0, Utils::storedTypeToI18n(Utils::Resources));
203 item->setCheckState(0, Qt::Checked);
204 item->setData(0, action, type);
205 break;
206 }
207 case Utils::Config: {
208 auto item = new QTreeWidgetItem(parent);
209 item->setText(0, Utils::storedTypeToI18n(Utils::Config));
210 item->setCheckState(0, Qt::Checked);
211 item->setData(0, action, type);
212 break;
213 }
214 case Utils::Data: {
215 auto item = new QTreeWidgetItem(parent);
216 item->setText(0, Utils::storedTypeToI18n(Utils::Data));
217 item->setCheckState(0, Qt::Checked);
218 item->setData(0, action, type);
219 break;
220 }
221 }
222 }
223
selectAllItems()224 void SelectionTypeTreeWidget::selectAllItems()
225 {
226 setSelectItems(true);
227 }
228
unSelectAllItems()229 void SelectionTypeTreeWidget::unSelectAllItems()
230 {
231 setSelectItems(false);
232 }
233
setSelectItems(bool b)234 void SelectionTypeTreeWidget::setSelectItems(bool b)
235 {
236 changeState(mKmailItem, b);
237 changeState(mKalarmItem, b);
238 changeState(mKaddressbookItem, b);
239 changeState(mKorganizerItem, b);
240 changeState(mKNotesItem, b);
241 changeState(mAkregatorItem, b);
242 }
243
changeState(QTreeWidgetItem * item,bool b)244 void SelectionTypeTreeWidget::changeState(QTreeWidgetItem *item, bool b)
245 {
246 if (item) {
247 blockSignals(true);
248 item->setCheckState(0, b ? Qt::Checked : Qt::Unchecked);
249 for (int i = 0; i < item->childCount(); ++i) {
250 item->child(i)->setCheckState(0, b ? Qt::Checked : Qt::Unchecked);
251 }
252 blockSignals(false);
253 }
254 }
255
slotItemChanged(QTreeWidgetItem * item,int column)256 void SelectionTypeTreeWidget::slotItemChanged(QTreeWidgetItem *item, int column)
257 {
258 if (column != 0) {
259 return;
260 }
261 // Parent
262 if (item->childCount() != 0) {
263 changeState(item, item->checkState(0) == Qt::Checked);
264 } else { // child
265 blockSignals(true);
266 QTreeWidgetItem *parent = item->parent();
267 Qt::CheckState state = Qt::PartiallyChecked;
268 for (int i = 0; i < parent->childCount(); ++i) {
269 if (i == 0) {
270 state = parent->child(i)->checkState(0);
271 } else {
272 if (state != parent->child(i)->checkState(0)) {
273 state = Qt::PartiallyChecked;
274 break;
275 }
276 }
277 }
278 parent->setCheckState(0, state);
279 blockSignals(false);
280 }
281 }
282
loadFileName(const QString & fileName)283 void SelectionTypeTreeWidget::loadFileName(const QString &fileName)
284 {
285 unSelectAllItems();
286 TemplateSelection templateSelection;
287 const QHash<Utils::AppsType, Utils::importExportParameters> params = templateSelection.loadTemplate(fileName);
288 setParameters(params);
289 }
290
loadDefaultTemplate()291 void SelectionTypeTreeWidget::loadDefaultTemplate()
292 {
293 // Keep old name for compatibility
294 QString ret = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/pimsettingexporter/defaulttemplate.xml"));
295 if (ret.isEmpty()) {
296 ret = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/pimdataexporter/defaulttemplate.xml"));
297 }
298 if (!ret.isEmpty()) {
299 loadFileName(ret);
300 }
301 }
302
loadTemplate(const QString & fileName)303 void SelectionTypeTreeWidget::loadTemplate(const QString &fileName)
304 {
305 if (fileName.isEmpty()) {
306 QPointer<QFileDialog> dlg = new QFileDialog(this, QString(), QString(), QStringLiteral("*.xml"));
307 dlg->setFileMode(QFileDialog::ExistingFile);
308 if (dlg->exec()) {
309 const QStringList file = dlg->selectedFiles();
310 loadFileName(file.at(0));
311 }
312 delete dlg;
313 } else {
314 loadFileName(fileName);
315 }
316 }
317
exportedFileInfo()318 QString SelectionTypeTreeWidget::exportedFileInfo()
319 {
320 const QString templateStr = templateSelectionToString();
321 QTemporaryFile tmp;
322 tmp.open();
323 tmp.setAutoRemove(false);
324 PimCommon::Util::saveToFile(tmp.fileName(), templateStr);
325 return tmp.fileName();
326 }
327
templateSelectionToString()328 QString SelectionTypeTreeWidget::templateSelectionToString()
329 {
330 TemplateSelection templateSelection;
331 templateSelection.createTemplate(storedType());
332 const QString templateStr = templateSelection.saveTemplate();
333 return templateStr;
334 }
335
saveAsDefaultTemplate()336 void SelectionTypeTreeWidget::saveAsDefaultTemplate()
337 {
338 const QString templateStr = templateSelectionToString();
339 QString ret = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/pimdataexporter/");
340 QDir().mkpath(ret);
341
342 PimCommon::Util::saveToFile(ret + QStringLiteral("defaulttemplate.xml"), templateStr);
343 }
344
saveAsTemplate()345 void SelectionTypeTreeWidget::saveAsTemplate()
346 {
347 const QString templateStr = templateSelectionToString();
348 const QString filter(i18n("Template Files (*.xml)"));
349 PimCommon::Util::saveTextAs(templateStr, filter, this);
350 }
351
initializeSubItem(QTreeWidgetItem * item,Utils::StoredTypes types)352 void SelectionTypeTreeWidget::initializeSubItem(QTreeWidgetItem *item, Utils::StoredTypes types)
353 {
354 for (int i = 0; i < item->childCount(); ++i) {
355 QTreeWidgetItem *child = item->child(i);
356 if (types & static_cast<Utils::StoredType>(child->data(0, action).toInt())) {
357 child->setCheckState(0, Qt::Checked);
358 } else {
359 child->setCheckState(0, Qt::Unchecked);
360 }
361 }
362 }
363
setParameters(const QHash<Utils::AppsType,Utils::importExportParameters> & params)364 void SelectionTypeTreeWidget::setParameters(const QHash<Utils::AppsType, Utils::importExportParameters> ¶ms)
365 {
366 QHash<Utils::AppsType, Utils::importExportParameters>::const_iterator i = params.constBegin();
367 while (i != params.constEnd()) {
368 switch (i.key()) {
369 case Utils::KMail:
370 initializeSubItem(mKmailItem, i.value().types);
371 break;
372 case Utils::KAddressBook:
373 initializeSubItem(mKaddressbookItem, i.value().types);
374 break;
375 case Utils::KAlarm:
376 initializeSubItem(mKalarmItem, i.value().types);
377 break;
378 case Utils::KOrganizer:
379 initializeSubItem(mKorganizerItem, i.value().types);
380 break;
381 case Utils::KNotes:
382 initializeSubItem(mKNotesItem, i.value().types);
383 break;
384 case Utils::Akregator:
385 initializeSubItem(mAkregatorItem, i.value().types);
386 break;
387 case Utils::Unknown:
388 break;
389 }
390 ++i;
391 }
392 }
393