1 /* This file is part of the KDE project
2 
3    Copyright (C) 2007 - 2014 by Lukas Appelhans <l.appelhans@gmx.de>
4    Copyright (C) 2008 by Javier Goday <jgoday@gmail.com>
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 */
11 #include "core/transferhistorystore_xml_p.h"
12 
13 #include <QDomDocument>
14 #include <QFile>
15 #include <QTextStream>
16 
17 #include "kget_debug.h"
18 #include <QDebug>
19 
SaveThread(QObject * parent,const QString & url,const QList<TransferHistoryItem> & list)20 XmlStore::SaveThread::SaveThread(QObject *parent, const QString &url, const QList<TransferHistoryItem> &list) : QThread(parent),
21     m_url(url),
22     m_items(list),
23     m_item()
24 {
25 }
26 
SaveThread(QObject * parent,const QString & url,const TransferHistoryItem & item)27 XmlStore::SaveThread::SaveThread(QObject *parent, const QString &url, const TransferHistoryItem &item) : QThread(parent),
28     m_url(url),
29     m_items(),
30     m_item(item)
31 {
32 }
33 
run()34 void XmlStore::SaveThread::run()
35 {
36     QFile file(m_url);
37     QDomDocument *doc;
38     QDomElement root;
39 
40     if (!file.exists())
41     {
42         doc = new QDomDocument("Transfers");
43         root = doc->createElement("Transfers");
44         doc->appendChild(root);
45     }
46     else
47     {
48         doc = new QDomDocument();
49         doc->setContent(&file);
50         file.close();
51         root = doc->documentElement();
52         doc->appendChild(root);
53     }
54 
55     QDomElement e = doc->createElement("Transfer");
56     root.appendChild(e);
57 
58     e.setAttribute("Source", m_item.source());
59     e.setAttribute("Dest", m_item.dest());
60     e.setAttribute("Time", QDateTime::currentDateTime().toSecsSinceEpoch());
61     e.setAttribute("Size", QString::number(m_item.size()));
62     e.setAttribute("State", QString::number(m_item.state()));
63 
64     if (file.open(QFile::WriteOnly | QFile::Truncate)) {
65         QTextStream stream( &file );
66         doc->save( stream, 0 );
67         file.close();
68     }
69     delete doc;
70 }
71 
DeleteThread(QObject * parent,const QString & url,const TransferHistoryItem & item)72 XmlStore::DeleteThread::DeleteThread(QObject *parent, const QString &url, const TransferHistoryItem &item) : QThread(parent),
73     m_url(url),
74     m_item(item),
75     m_items()
76 {
77 }
78 
run()79 void XmlStore::DeleteThread::run()
80 {
81     QDomDocument doc("tempHistory");
82     QFile file(m_url);
83 
84     QString error;
85     int line;
86     int column;
87 
88     if (!doc.setContent(&file, &error, &line, &column))
89     {
90         qCDebug(KGET_DEBUG) << "Error1" << error << line << column;
91         return;
92     }
93     file.close();
94 
95     QDomElement root = doc.documentElement();
96 
97     QDomNodeList list = root.elementsByTagName("Transfer");
98 
99     int nItems = list.length();
100 
101     for (int i = 0 ; i < nItems ; i++) {
102         QDomElement element = list.item(i).toElement();
103 
104         if(QString::compare(element.attribute("Source"), m_item.source()) == 0) {
105             root.removeChild(element);
106         }
107         else {
108             TransferHistoryItem item;
109             item.setDest(element.attribute("Dest"));
110             item.setSource(element.attribute("Source"));
111             item.setSize(element.attribute("Size").toInt());
112             item.setDateTime(QDateTime::fromSecsSinceEpoch(element.attribute("Time").toUInt()));
113             item.setState(element.attribute("State").toInt());
114             m_items << item;
115         }
116     }
117 
118     if (file.open(QFile::WriteOnly | QFile::Truncate)) {
119         QTextStream stream( &file );
120         doc.save(stream, 0);
121         file.close();
122         doc.clear();
123     }
124 }
125 
LoadThread(QObject * parent,const QString & url)126 XmlStore::LoadThread::LoadThread(QObject *parent, const QString &url) : QThread(parent),
127     m_url(url)
128 {
129 }
130 
run()131 void XmlStore::LoadThread::run()
132 {
133     qRegisterMetaType<TransferHistoryItem>("TransferHistoryItem");
134     QDomDocument doc("tempHistory");
135     QFile file(m_url);
136 
137     QString error;
138     int line;
139     int column;
140     int total;
141 
142     if (!doc.setContent(&file, &error, &line, &column))
143     {
144         qCDebug(KGET_DEBUG) << "Error1" << error << line << column;
145         file.close();
146         return;
147     }
148 
149     QDomElement root = doc.documentElement();
150     total = root.childNodes().size();
151 
152     QDomNodeList list = root.elementsByTagName("Transfer");
153 
154     int nItems = list.length();
155 
156     for (int i = 0 ; i < nItems ; i++)
157     {
158         QDomElement dom = list.item(i).toElement();
159 
160         TransferHistoryItem item;
161         item.setDest(dom.attribute("Dest"));
162         item.setSource(dom.attribute("Source"));
163         item.setSize(dom.attribute("Size").toInt());
164         item.setDateTime(QDateTime::fromSecsSinceEpoch(dom.attribute("Time").toUInt()));
165         item.setState(dom.attribute("State").toInt());
166 
167         Q_EMIT elementLoaded(i, total, item);
168     }
169     doc.clear();
170     file.close();
171 }
172 
XmlStore(const QString & url)173 XmlStore::XmlStore(const QString &url) : TransferHistoryStore(),
174     m_storeUrl(url),
175     m_loadThread(nullptr),
176     m_saveThread(nullptr),
177     m_deleteThread(nullptr)
178 {
179 }
180 
~XmlStore()181 XmlStore::~XmlStore()
182 {
183     if(m_loadThread && m_loadThread->isRunning()) {
184         m_loadThread->terminate();
185     }
186 
187     if(m_saveThread && m_saveThread->isRunning()) {
188         m_saveThread->terminate();
189     }
190 
191     if(m_deleteThread && m_deleteThread->isRunning()) {
192         m_deleteThread->terminate();
193     }
194 
195     delete m_loadThread;
196     delete m_saveThread;
197     delete m_deleteThread;
198 }
199 
load()200 void XmlStore::load()
201 {
202     m_items.clear();
203     // TODO: only load if necessary
204     m_loadThread = new XmlStore::LoadThread(this, m_storeUrl);
205 
206     connect(m_loadThread, &QThread::finished, this, &TransferHistoryStore::loadFinished);
207     connect(m_loadThread, &LoadThread::elementLoaded,
208                         this, &TransferHistoryStore::elementLoaded);
209     connect(m_loadThread, &LoadThread::elementLoaded,
210                         this, &XmlStore::slotLoadElement);
211     m_loadThread->start();
212 }
213 
clear()214 void XmlStore::clear()
215 {
216     QFile::remove(m_storeUrl);
217 }
218 
saveItem(const TransferHistoryItem & item)219 void XmlStore::saveItem(const TransferHistoryItem &item)
220 {
221     m_saveThread = new XmlStore::SaveThread(this, m_storeUrl, item);
222 
223     connect(m_saveThread, &QThread::finished, this, &TransferHistoryStore::saveFinished);
224     connect(m_saveThread, &SaveThread::elementLoaded,
225                         this, &TransferHistoryStore::elementLoaded);
226     m_saveThread->start();
227 }
228 
deleteItem(const TransferHistoryItem & item)229 void XmlStore::deleteItem(const TransferHistoryItem &item)
230 {
231     Q_UNUSED(item)
232 
233     m_deleteThread = new XmlStore::DeleteThread(this, m_storeUrl, item);
234 
235     connect(m_deleteThread, &QThread::finished, this, &XmlStore::slotDeleteElement);
236 
237     m_deleteThread->start();
238 }
239 
slotLoadElement(int number,int total,const TransferHistoryItem & item)240 void XmlStore::slotLoadElement(int number, int total, const TransferHistoryItem &item)
241 {
242     Q_UNUSED(number)
243     Q_UNUSED(total)
244     m_items.append(item);
245 }
246 
slotDeleteElement()247 void XmlStore::slotDeleteElement()
248 {
249     m_items.clear();
250     m_items << m_deleteThread->items();
251 
252     Q_EMIT loadFinished();
253 }
254 
255 
256