// Synchronize remote notebooks with the current database // If there is a conflict, the remote wins void SyncRunner::syncRemoteNotebooks(QList<Notebook> books, qint32 account) { QLOG_TRACE() << "Entering SyncRunner::syncRemoteNotebooks"; NotebookTable notebookTable(db); LinkedNotebookTable ltable(db); SharedNotebookTable stable(db); for (int i=0; i<books.size() && keepRunning; i++) { Notebook t = books.at(i); // There are a few to get the notebook. // We can get it by the guid, the share key, the uri, or the name. qint32 lid = account; if (lid == 0) lid = notebookTable.getLid(t.guid); if (lid == 0) lid = ltable.getLid(t.guid); if (lid == 0 && t.sharedNotebooks.isSet()) { QList<SharedNotebook> sharedNotebooks = t.sharedNotebooks; for (int j=0; j<sharedNotebooks.size() && lid == 0; j++) { lid = stable.findById(sharedNotebooks[j].id); } } Publishing publishing; if (t.publishing.isSet()) publishing = t.publishing; if (lid == 0 && publishing.uri.isSet()) { lid = notebookTable.findByUri(publishing.uri); } if (lid == 0) lid = notebookTable.findByName(t.name); if (lid > 0) { notebookTable.sync(lid, t); } else { lid = notebookTable.sync(t); } changedNotebooks.insert(t.guid, t.name); QString stack = ""; if (t.stack.isSet()) stack = t.stack; bool shared = false; if (t.sharedNotebookIds.isSet() || t.sharedNotebooks.isSet()) shared = true; if (account > 0) { LinkedNotebookTable ltb(db); LinkedNotebook lbook; ltb.get(lbook, account); if (lbook.username.isSet()) stack = QString::fromStdString(username); } if (!finalSync) { if (t.name.isSet()) emit notebookUpdated(lid, t.name, stack, false, shared); else emit notebookUpdated(lid, "", stack, false, shared); } } QLOG_TRACE() << "Leaving SyncRunner::syncRemoteNotebooks"; }
// Expunge deleted notebooks from the local database void SyncRunner::syncRemoteExpungedNotebooks(QList<Guid> guids) { QLOG_TRACE() << "Entering SyncRunner::syncRemoteExpungedNotebooks"; NotebookTable notebookTable(db); for (int i=0; i<guids.size(); i++) { int lid = notebookTable.getLid(guids[i]); notebookTable.expunge(guids[i]); if (!finalSync) emit notebookExpunged(lid); } QLOG_TRACE() << "Leaving SyncRunner::syncRemoteExpungedNotebooks"; }
// Rebuild the notebook tree view void NNotebookView::rebuildTree() { if (!this->rebuildNotebookTreeNeeded) return; // Go through all the widgets in the view. If // it should be hidden (because the notebook is closed // then hide it, othwise make it visible. If it has // a stack, then save the stack name later so we can // display stacks properly. NotebookTable notebookTable(global.db); QList<qint32> closedLids; notebookTable.getClosedNotebooks(closedLids); QHashIterator<qint32, NNotebookViewItem *> i(dataStore); while (i.hasNext()) { i.next(); NNotebookViewItem *widget = i.value(); if (widget != NULL) { if (closedLids.contains(widget->lid)) widget->setHidden(true); else widget->setHidden(false); if (i.value()->stack != "") { NNotebookViewItem *stackWidget = NULL; if (stackStore.contains(i.value()->stack)) { stackWidget = stackStore[i.value()->stack]; } else { NNotebookViewItem *stackWidget = new NNotebookViewItem(0); stackWidget->setData(NAME_POSITION, Qt::DisplayRole, i.value()->stack); stackWidget->setData(NAME_POSITION, Qt::UserRole, "STACK"); stackStore.insert(widget->stack, stackWidget); root->addChild(stackWidget); } i.value()->parent()->removeChild(i.value()); stackWidget->childrenLids.append(i.key()); stackWidget->addChild(i.value()); } } } // Remove any empty stacks QHashIterator<QString, NNotebookViewItem *> s(stackStore); while (s.hasNext()) { s.next(); if (s.value()->childCount() == 0) { root->removeChild(s.value()); stackStore.remove(s.key()); } } this->sortByColumn(NAME_POSITION, Qt::AscendingOrder); this->rebuildNotebookTreeNeeded = false; this->resetSize(); }
// Load up the data from the database void NNotebookView::loadData() { NSqlQuery query(global.db); NotebookTable notebookTable(global.db); QList<qint32> closedLids; notebookTable.getClosedNotebooks(closedLids); QHash<qint32, NNotebookViewItem*>::iterator i1; for (i1=dataStore.begin(); i1!=dataStore.end(); ++i1) { if (i1.value() != NULL) i1.value()->setHidden(true); } QHash<QString, NNotebookViewItem*>::iterator i2; for (i2=stackStore.begin(); i2!=stackStore.end(); ++i2) { if (i2.value() != NULL) i2.value()->setHidden(true); } dataStore.clear(); query.exec("Select lid, name, stack, username from NotebookModel order by username, name"); while (query.next()) { qint32 lid = query.value(0).toInt(); if (!notebookTable.isDeleted(query.value(0).toInt())) { NNotebookViewItem *newWidget = new NNotebookViewItem(lid); newWidget->setData(NAME_POSITION, Qt::DisplayRole, query.value(1).toString()); newWidget->setData(NAME_POSITION, Qt::UserRole, lid); if (closedLids.contains(lid)) newWidget->setHidden(true); QString username = query.value(3).toString(); if (username.trimmed() != "") newWidget->stack = username; else newWidget->stack = query.value(2).toString(); this->dataStore.insert(query.value(0).toInt(), newWidget); root->addChild(newWidget); if (newWidget->stack != "" && !stackStore.contains(newWidget->stack)) { NNotebookViewItem *stackWidget = new NNotebookViewItem(0); stackWidget->setData(NAME_POSITION, Qt::DisplayRole, newWidget->stack); stackWidget->setData(NAME_POSITION, Qt::UserRole, "STACK"); if (username != "") stackWidget->setType(NNotebookViewItem::LinkedStack); stackStore.insert(newWidget->stack, stackWidget); root->addChild(stackWidget); } } } query.finish(); this->rebuildTree(); this->resetSize(); }
// Called when the notebook has changed. If this is a non-linked notebook we // display all available tags owned by this user. If it is a linked notebook // we only show the tags that are connected to that notebook void NTagView::notebookSelectionChanged(qint32 notebookLid) { LinkedNotebookTable table(global.db); if (table.exists(notebookLid)) { accountFilter = notebookLid; NotebookTable notebookTable(global.db); Notebook notebook; notebookTable.get(notebook, notebookLid); root->setData(NAME_POSITION, Qt::DisplayRole, tr("Tags from ")+notebook.name); } else { root->setData(NAME_POSITION, Qt::DisplayRole, tr("Tags from Personal")); accountFilter = 0; } if (accountFilter > 0) { addAction->setEnabled(false); deleteAction->setEnabled(false); } else { addAction->setEnabled(true); deleteAction->setEnabled(true); } }
//*********************************************************** //* Process a <notebook> node //*********************************************************** void ImportData::processNotebookNode() { QLOG_DEBUG() << "Processing Notebook Node"; Notebook notebook; bool notebookIsDirty = false; bool notebookIsLocal = false; Publishing publishing; // bool notebookIsReadOnly = false; // notebookIcon = null; bool atEnd = false; // Loop through until we hit </notebook> while(!atEnd) { if (backup || importNotebooks) { if (reader->isStartElement()) { QString name = reader->name().toString().toLower(); if (name == "guid") { notebook.guid = textValue(); } if (name == "name") { notebook.name = textValue(); } if (name == "updatesequencenumber") { notebook.updateSequenceNum = intValue(); } if (name == "servicecreated") { notebook.serviceCreated = longValue(); } if (name == "serviceupdated") { notebook.serviceUpdated = longValue(); } if (name == "defaultnotebook") { notebook.defaultNotebook = booleanValue(); } if (name == "dirty") { if (booleanValue()) notebookIsDirty = true; } if (name == "localnotebook") { if (booleanValue()) notebookIsLocal = true; } if (name == "publishingpublicdescription") { publishing.publicDescription = textValue(); } if (name == "publishinguri") { publishing.uri = textValue(); } if (name == "publishingorder") { //notebook->publishing.order = // NoteSortOrder.; QLOG_DEBUG() << "!!!!!!!!!!!! PublishingOrder not completed in import"; } if (name == "PublishingAscending") { if (booleanValue()) publishing.ascending = true; else publishing.ascending = false; } if (name == "icon") { //byte[] b = textValue().getBytes(); // data binary //QByteArray hexData = new QByteArray(b); //QByteArray binData = new QByteArray(QByteArray.fromHex(hexData)); //notebookIcon = new QIcon(QPixmap.fromImage(QImage.fromData(binData))); } if (name == "stack") { notebook.stack = textValue(); } } } reader->readNext(); QString endName = reader->name().toString().toLower(); if (endName == "notebook" && reader->isEndElement()) atEnd = true; } notebook.publishing = publishing; // We are at the end. We should have a valid notebook now NotebookTable notebookTable(global.db); // Check if there is a notebook by this name already. // If one exists, we treat this as an update qint32 lid = notebookTable.findByName(notebook.name); if (lid <= 0) { lid = notebookTable.getLid(notebook.guid); } if (lid <= 0) { notebookTable.add(lid,notebook,notebookIsDirty, notebookIsLocal); } else { qint32 oldLid = notebookTable.getLid(notebook.guid); if (oldLid != lid) notebookTable.merge(oldLid, lid); notebookTable.sync(lid, notebook); // notebookTable.updateGuid(lid, notebook.guid); notebookTable.setDirty(lid, notebookIsDirty); } return; }
//*********************************************************** //* Process a <note> tag //*********************************************************** void BatchImport::addNoteNode() { Note note; note.title = QString(tr("Untitled Note")); QUuid uuid; QString newGuid = uuid.createUuid().toString().replace("{", "").replace("}", ""); note.guid = newGuid; QStringList tagNames; QStringList tagGuids; QString newNoteBody = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")+ QString("<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">")+ QString("<en-note style=\"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;\"><br/></en-note>"); note.active = true; note.content = newNoteBody; note.created = QDateTime::currentMSecsSinceEpoch(); note.updated = QDateTime::currentMSecsSinceEpoch(); bool atEnd = false; while(!atEnd) { QString name = reader->name().toString().toLower(); if (name == "title" && !reader->isEndElement()) { note.title = textValue(); } if (name == "created" && !reader->isEndElement()) { QString dateString = textValue(); //QDateTime date = QDateTime::fromString("2010-10-25T10:28:58.570Z", "yyyy-MM-ddTHH:mm:ss.zzzZ"); QDateTime date = QDateTime::fromString(dateString, "yyyy-MM-ddTHH:mm:ss.zzzZ"); note.created = date.toMSecsSinceEpoch(); } if (name == "updated" && !reader->isEndElement()) { QString dateString = textValue(); QDateTime date = QDateTime::fromString(dateString, "yyyy-MM-ddTHH:mm:ss.zzzZ"); note.updated = date.toMSecsSinceEpoch(); } if (name == "notebook" && !reader->isEndElement()) { QString notebookName = textValue(); NotebookTable notebookTable(global.db); qint32 lid = notebookTable.findByName(notebookName); QString notebookGuid; // Do we need to add the notebook? if (lid == 0) { Notebook book; book.name = notebookName; QUuid uuid; QString newGuid = uuid.createUuid().toString().replace("{", "").replace("}", ""); book.guid = newGuid; notebookGuid = newGuid; lid = notebookTable.add(0, book, true, false); } else { notebookTable.getGuid(notebookGuid, lid); } note.notebookGuid = notebookGuid; } if (name == "content" && !reader->isEndElement()) { note.content = textValue(); } if (name == "tag" && !reader->isEndElement()) { QString tagName = textValue(); TagTable tagTable(global.db); qint32 tagLid = tagTable.findByName(tagName, 0); QString tagGuid; // Do we need to add the tag? if (tagLid == 0) { Tag tag; tag.name = tagName; QUuid uuid; tagGuid = uuid.createUuid().toString().replace("{", "").replace("}", ""); tag.guid = tagGuid; tagTable.add(0, tag, true, 0); } else { tagTable.getGuid(tagGuid, tagLid); } tagNames.append(tagName); tagGuids.append(tagGuid); } reader->readNext(); QString endName = reader->name().toString().toLower(); if (endName == "noteadd" && reader->isEndElement()) { atEnd = true; note.tagGuids = tagGuids; note.tagNames = tagNames; NoteTable ntable(global.db); if (!note.notebookGuid.isSet()) { NotebookTable bookTable(global.db); QString book = bookTable.getDefaultNotebookGuid(); note.notebookGuid = book; } ntable.add(0, note, true); } } return; }
// Upload notes that belong to me qint32 SyncRunner::uploadPersonalNotes() { qint32 usn; qint32 maxUsn = 0; NotebookTable notebookTable(db); LinkedNotebookTable linkedNotebookTable(db); NoteTable noteTable(db); QList<qint32> lids, validLids, deletedLids, movedLids; noteTable.getAllDirty(lids); // Get a list of all notes that are both dirty and in an account we own and isn't deleted for (int i=0; i<lids.size(); i++) { qint32 notebookLid = noteTable.getNotebookLid(lids[i]); if (!linkedNotebookTable.exists(notebookLid)) { if (!notebookTable.isLocal(notebookLid)) { if (noteTable.isDeleted(lids[i])) deletedLids.append(lids[i]); else validLids.append(lids[i]); } else { // We have a note that is local. Check if it was once // synchronized. If so, it was moved to a local notebook // and now needs to be deleted on the remote end Note n; noteTable.get(n, lids[i], false, false); if (n.updateSequenceNum.isSet() && n.updateSequenceNum > 0) { movedLids.append(lids[i]); } } } } // Start deleting notes for (int i=0; i<deletedLids.size(); i++) { QString guid = noteTable.getGuid(deletedLids[i]); noteTable.setDirty(lids[i], false); usn = comm->deleteNote(guid); if (usn > maxUsn) { maxUsn = usn; noteTable.setUpdateSequenceNumber(deletedLids[i], usn); noteTable.setDirty(deletedLids[i], false); if (!finalSync) emit(noteSynchronized(deletedLids[i], false)); } } // Start handling notes moved to a local notebook. What // we do is to delete the note on Evernote, then give the // note in the local notebook a new GUID & set the // update sequence number to 0. for (int i=0; i<movedLids.size(); i++) { QUuid uuid; Guid newGuid = uuid.createUuid().toString().replace("{","").replace("}",""); QString guid = noteTable.getGuid(movedLids[i]); noteTable.setDirty(movedLids[i], false); noteTable.updateGuid(movedLids[i], newGuid); noteTable.setUpdateSequenceNumber(movedLids[0], 0); usn = comm->deleteNote(guid); if (usn > maxUsn) { maxUsn = usn; } if (!finalSync) emit(noteSynchronized(movedLids[i], false)); } // Start uploading notes for (int i=0; i<validLids.size(); i++) { Note note; noteTable.get(note, validLids[i],true, true); qint32 oldUsn=0; if (note.updateSequenceNum.isSet()) oldUsn = note.updateSequenceNum; usn = comm->uploadNote(note); if (usn == 0) { this->communicationErrorHandler(); error = true; return maxUsn; } if (usn > maxUsn) { maxUsn = usn; if (oldUsn == 0) noteTable.updateGuid(validLids[i], note.guid); noteTable.setUpdateSequenceNumber(validLids[i], usn); noteTable.setDirty(validLids[i], false); if (!finalSync) emit(noteSynchronized(validLids[i], false)); } else { error = true; } } return maxUsn; }