PageRenderTime 77ms CodeModel.GetById 14ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/colonydatamerger.cpp

https://github.com/samcrow/ColonyDataMerger
C++ | 327 lines | 228 code | 75 blank | 24 comment | 39 complexity | d2d12c554eafdd72dcae6f6667a60560 MD5 | raw file
  1#include "colonydatamerger.hpp"
  2#include "ui_colonydatamerger.h"
  3
  4
  5ColonyDataMerger::ColonyDataMerger(QWidget *parent) :
  6    QMainWindow(parent),
  7    ui(new Ui::ColonyDataMerger)
  8{
  9    ui->setupUi(this);
 10    qInstallMsgHandler(&handleConsoleMessage);
 11    //Fix warning about handleConsoleMessage defined but not used
 12    handleConsoleMessage(QtDebugMsg, "Starting up");
 13
 14    LIBMTP_Init();
 15
 16    qDebug() << "It works!";
 17}
 18
 19void ColonyDataMerger::showConsoleDialog() {
 20    if(!activeDialog) {
 21        activeDialog = new ConsoleDialog(this);
 22    }
 23    activeDialog->show();
 24    activeDialog->raise();
 25    activeDialog->activateWindow();
 26}
 27
 28QList<Colony *> *ColonyDataMerger::mergeColonyLists(QList<Colony *> *list1, QList<Colony *> *list2) {
 29
 30    //TODO sometime: Find a better algorithm. This one is not very scalable (probably O(n^2))
 31
 32    QList<Colony *> *finalList = new QList<Colony *>();
 33
 34    //Add every colony from both lists to the final list
 35    for(int i = 0, max = list1->length(); i < max; i++) {
 36        finalList->append(list1->at(i));
 37    }
 38    for(int i = 0, max = list2->length(); i < max; i++) {
 39        finalList->append(list2->at(i));
 40    }
 41
 42    //Go through the list and remove duplicates
 43    for(int i = 0, max = finalList->length(); i < max; i++) {
 44        Colony *flColony = finalList->at(i);
 45        int flId = flColony->getID();
 46
 47        //Try to find other colonies in the list with this ID
 48        for(int j = 0, jmax = finalList->length(); j < jmax; j++) {
 49            Colony *innerFlColony = finalList->at(i);
 50
 51            //If another colony was found with the same ID
 52            // (that is not the same colony object as this one
 53            if(innerFlColony->getID() == flId && innerFlColony != flColony) {
 54                //We have two colony pointers, same ID, one of them is better
 55
 56                Colony *chosenColony = chooseColony(flColony, innerFlColony);
 57
 58                //chosenColony is either flColony or innerFlColony
 59                //Remove from the final list the one that was not chosen
 60                if(chosenColony == flColony) {
 61                    finalList->removeOne(innerFlColony);
 62                }
 63                else {
 64                    //chosenColony == innerFlColony
 65                    finalList->removeOne(flColony);
 66                }
 67            }
 68        }
 69    }
 70
 71    return finalList;
 72}
 73
 74Colony *ColonyDataMerger::chooseColony(Colony *colony1, Colony *colony2) {
 75    QDateTime date1 = colony1->getModifiedDate();
 76    QDateTime date2 = colony2->getModifiedDate();
 77
 78    //Case 0: both are valid
 79    if(date1.isValid() && date2.isValid()) {
 80        //Colony 1 updated after colony 2
 81        if(date1 > date2) {
 82            return colony1;
 83        }
 84        //Colony 1 updated before colony 2
 85        else if(date1 < date2) {
 86            return colony2;
 87        }
 88        //Same date/time, arbitrarily return colony 1
 89        else {
 90            return colony1;
 91        }
 92    }
 93
 94    //Case 1: One date is valid; return the colony with the valid date
 95    else if(date1.isValid() && !date2.isValid()) {
 96        return colony1;
 97    }
 98    else if(date2.isValid() && !date1.isValid()) {
 99        return colony2;
100    }
101
102    //Case 2: neither is valid
103    return colony1;
104}
105
106ColonyDataMerger::~ColonyDataMerger()
107{
108    delete ui;
109}
110
111void ColonyDataMerger::on_uploadButton_clicked()
112{
113    showConsoleDialog();
114    //Disable the upload button so it can't be clicked again this time the application is run
115    ui->uploadButton->setEnabled(false);
116
117    //Upload the file
118
119    QList<MobileDevice *> *devices = MobileDevice::getDevices();
120
121    if(!devices) {
122        qWarning() << "NULL mobile device set! Exiting.";
123        return;
124    }
125
126    qDebug() << "Connected to" << devices->count() << "device(s).";
127
128    QString fileName = QFileDialog::getOpenFileName(activeDialog, "Choose a CSV file to upload", QDir::homePath(), "CSV files (*.csv)");
129
130    qDebug() << "CSV file:" << fileName;
131
132    if(fileName.isEmpty()) {
133        qWarning() << "No CSV file selected. Exiting.";
134        return;
135    }
136
137    foreach(MobileDevice *device, *devices) {
138        QFile csv(fileName);
139        csv.open(QIODevice::ReadOnly | QIODevice::Text);
140        if(!csv.isOpen()) {
141            qWarning() << "Could not open CSV file. Exiting.";
142            return;
143        }
144
145        qDebug() << "Uploading to a device...";
146        device->uploadCSV(&csv);
147
148        if(csv.isOpen()) {
149            csv.close();
150        }
151    }
152
153    //Clean up
154    foreach(MobileDevice *device, *devices) {
155        delete device;
156    }
157    delete devices;
158    qDebug() << "Operation successfully completed.";
159}
160
161void ColonyDataMerger::on_downloadButton_clicked()
162{
163    showConsoleDialog();
164    ui->downloadButton->setEnabled(false);
165
166    QList<MobileDevice *> *devices = MobileDevice::getDevices();
167
168    if(!devices) {
169        qWarning() << "NULL mobile device set! Exiting.";
170        return;
171    }
172    qDebug() << "Connected to" << devices->count() << "device(s).";
173
174    foreach(MobileDevice *device, *devices) {
175
176        QString jsonText = device->getJsonText();
177
178        QString fileName = QFileDialog::getSaveFileName(this, "Choose where to save this JSON file", QDir::homePath(), "JSON files (*.json)");
179
180        if(fileName.isEmpty()) {
181            qDebug() << "Emtpy file name. Exiting.";
182            return;
183        }
184
185        QFile file(fileName);
186        file.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text);
187        if(!file.isOpen()) {
188            qDebug() << "File opening failed. Exiting.";
189            return;
190        }
191        if(!file.isWritable()) {
192            qDebug() << "File is not writable. Exiting.";
193        }
194
195        file.write(jsonText.toUtf8());
196        file.close();
197
198        qDebug() << "Done writing file" << file.fileName();
199    }
200
201    //Clean up
202    foreach(MobileDevice *device, *devices) {
203        delete device;
204    }
205    delete devices;
206    qDebug() << "Operation successfully completed.";
207}
208
209void ColonyDataMerger::on_mergeButton_clicked()
210{
211    showConsoleDialog();
212
213    QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose JSON files to merge & export", QDir::homePath(), "JSON files (*.json)");
214
215    QList<QList<Colony *> *> colonyLists;
216
217    foreach(QString fileName, fileNames) {
218        qDebug() << "Opening" << fileName;
219        QFile file(fileName);
220        file.open(QIODevice::ReadOnly | QIODevice::Text);
221        if(!file.isOpen()) {
222            qDebug() << "File opening failed. Exiting.";
223            return;
224        }
225
226        QList<Colony *> *thisFileList = jsonToColonyList(parseJson(QString(file.readAll())));
227
228        colonyLists.append(thisFileList);
229    }
230
231    QList<Colony *> *workingList = new QList<Colony *>();
232
233    qDebug() << "Merging colony lists...";
234    for(int i = 0, max = colonyLists.length(); i < max; i++ ) {
235        QList<Colony *> *list = colonyLists[i];
236        workingList = mergeColonyLists(list, workingList);
237    }
238
239    qDebug() << "Merging done.";
240    //Convert it to CSV
241    QString csvText = toCSV(workingList);
242
243    QString csvPath = QFileDialog::getSaveFileName(this, "Choose where to export the CSV file", QDir::homePath(), "CSV files (*.csv)");
244
245    if(!csvPath.isEmpty()) {
246
247        QFile csv(csvPath);
248        csv.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text);
249
250        csv.write(csvText.toUtf8());
251        csv.close();
252        qDebug() << "Done writing CSV file.";
253    }
254
255    //Clean up
256    delete workingList;
257    QListIterator<QList<Colony *> *> listsIterator(colonyLists);
258    while(listsIterator.hasNext()) {
259        QList<Colony *> *list = listsIterator.next();
260        QListIterator<Colony *> colonyIterator(*list);
261        while(colonyIterator.hasNext()) {
262            delete colonyIterator.next();
263        }
264        delete list;
265    }
266    qDebug() << "Operation successfully completed.";
267}
268
269QList<Colony *> *ColonyDataMerger::jsonToColonyList(QVariantMap json) {
270
271    QVariantList jsonColonies = json.value("colonies").toList();
272
273    QList<Colony *> *colonies = new QList<Colony *>();
274
275    for(int i = 0, max = jsonColonies.length(); i < max; i++) {
276        QVariant jsonColony = jsonColonies.at(i);
277        QVariantMap colonyMap = jsonColony.toMap();
278
279        Colony *colony = new Colony();
280        colony->fromVariant(colonyMap);
281
282        //Ensure that the colony's marked as visited if it is active
283        if(colony->isActive()) {
284            colony->setVisited(true);
285        }
286
287        colonies->append(colony);
288    }
289
290    qDebug() << "Got" << colonies->length() << "colonies.";
291    return colonies;
292}
293
294QVariantMap ColonyDataMerger::parseJson(QString jsonText) {
295
296    QJson::Parser parser;
297
298    QVariant variant = parser.parse(jsonText.toUtf8());
299
300    return variant.toMap();
301}
302
303QString ColonyDataMerger::toCSV(QList<Colony *> *list) {
304    QString csv;
305
306    csv += "col,E,N,active,visted,\n";
307
308    for(int i = 0, max = list->size(); i < max; i++) {
309        Colony *colony = list->at(i);
310
311        if(colony->isVisited()) {
312
313            csv += QString::number(colony->getID());
314            csv += ",";
315            csv += QString::number(colony->getX());
316            csv += ",";
317            csv += QString::number(colony->getY());
318            csv += ",";
319            csv += colony->isActive() ? "A" : "NA";
320            csv += ",";
321            csv += colony->isVisited() ? "true" : "false";
322            csv += ",\n";
323        }
324    }
325
326    return csv;
327}