void SwapFile::fileLoaded(const QString&) { // look for swap file if (!updateFileName()) return; if (!m_swapfile.exists()) { kDebug (13020) << "No swap file"; return; } if (!QFileInfo(m_swapfile).isReadable()) { kWarning( 13020 ) << "Can't open swap file (missing permissions)"; return; } // sanity check QFile peekFile(fileName()); if (peekFile.open(QIODevice::ReadOnly)) { QDataStream stream(&peekFile); if (!isValidSwapFile(stream, true)) { removeSwapFile(); return; } peekFile.close(); } else { kWarning( 13020 ) << "Can't open swap file:" << fileName(); return; } // show swap file message m_document->setReadWrite(false); showSwapFileMessage(); }
bool SwapFile::recover(QDataStream& stream, bool checkDigest) { if (!isValidSwapFile(stream, checkDigest)) { return false; } // disconnect current signals setTrackingEnabled(false); // needed to set undo/redo cursors in a sane way bool firstEditInGroup = false; KTextEditor::Cursor undoCursor = KTextEditor::Cursor::invalid(); KTextEditor::Cursor redoCursor = KTextEditor::Cursor::invalid(); // replay swapfile bool editRunning = false; bool brokenSwapFile = false; while (!stream.atEnd()) { if (brokenSwapFile) break; qint8 type; stream >> type; switch (type) { case EA_StartEditing: { m_document->editStart(); editRunning = true; firstEditInGroup = true; undoCursor = KTextEditor::Cursor::invalid(); redoCursor = KTextEditor::Cursor::invalid(); break; } case EA_FinishEditing: { m_document->editEnd(); // empty editStart() / editEnd() groups exist: only set cursor if required if (!firstEditInGroup) { // set undo/redo cursor of last KateUndoGroup of the undo manager m_document->undoManager()->setUndoRedoCursorsOfLastGroup(undoCursor, redoCursor); m_document->undoManager()->undoSafePoint(); } firstEditInGroup = false; editRunning = false; break; } case EA_WrapLine: { if (!editRunning) { brokenSwapFile = true; break; } int line = 0, column = 0; stream >> line >> column; // emulate buffer unwrapLine with document m_document->editWrapLine(line, column, true); // track undo/redo cursor if (firstEditInGroup) { firstEditInGroup = false; undoCursor = KTextEditor::Cursor(line, column); } redoCursor = KTextEditor::Cursor(line + 1, 0); break; } case EA_UnwrapLine: { if (!editRunning) { brokenSwapFile = true; break; } int line = 0; stream >> line; // assert valid line Q_ASSERT (line > 0); const int undoColumn = m_document->lineLength(line - 1); // emulate buffer unwrapLine with document m_document->editUnWrapLine(line - 1, true, 0); // track undo/redo cursor if (firstEditInGroup) { firstEditInGroup = false; undoCursor = KTextEditor::Cursor(line, 0); } redoCursor = KTextEditor::Cursor(line - 1, undoColumn); break; } case EA_InsertText: { if (!editRunning) { brokenSwapFile = true; break; } int line, column; QByteArray text; stream >> line >> column >> text; m_document->insertText(KTextEditor::Cursor(line, column), QString::fromUtf8 (text.data (), text.size())); // track undo/redo cursor if (firstEditInGroup) { firstEditInGroup = false; undoCursor = KTextEditor::Cursor(line, column); } redoCursor = KTextEditor::Cursor(line, column + text.size()); break; } case EA_RemoveText: { if (!editRunning) { brokenSwapFile = true; break; } int line, startColumn, endColumn; stream >> line >> startColumn >> endColumn; m_document->removeText (KTextEditor::Range(KTextEditor::Cursor(line, startColumn), KTextEditor::Cursor(line, endColumn))); // track undo/redo cursor if (firstEditInGroup) { firstEditInGroup = false; undoCursor = KTextEditor::Cursor(line, endColumn); } redoCursor = KTextEditor::Cursor(line, startColumn); break; } default: { kWarning( 13020 ) << "Unknown type:" << type; } } } // balanced editStart and editEnd? if (editRunning) { brokenSwapFile = true; m_document->editEnd(); } // warn the user if the swap file is not complete if (brokenSwapFile) { kWarning ( 13020 ) << "Some data might be lost"; } else { // set sane final cursor, if possible KTextEditor::View * view = m_document->activeView(); redoCursor = m_document->undoManager()->lastRedoCursor(); if (view && redoCursor.isValid()) { view->setCursorPosition(redoCursor); } } // reconnect the signals setTrackingEnabled(true); return true; }
bool SwapFile::recover(QDataStream& stream, bool checkDigest) { if (!isValidSwapFile(stream, checkDigest)) { return false; } // disconnect current signals setTrackingEnabled(false); // replay swapfile bool editStarted = false; bool brokenSwapFile = false; while (!stream.atEnd()) { if (brokenSwapFile) break; qint8 type; stream >> type; switch (type) { case EA_StartEditing: { m_document->editStart(); editStarted = true; break; } case EA_FinishEditing: { m_document->editEnd(); editStarted = false; break; } case EA_WrapLine: { if (!editStarted) { brokenSwapFile = true; break; } int line = 0, column = 0; stream >> line >> column; // emulate buffer unwrapLine with document m_document->editWrapLine(line, column, true); break; } case EA_UnwrapLine: { if (!editStarted) { brokenSwapFile = true; break; } int line = 0; stream >> line; // assert valid line Q_ASSERT (line > 0); // emulate buffer unwrapLine with document m_document->editUnWrapLine(line - 1, true, 0); break; } case EA_InsertText: { if (!editStarted) { brokenSwapFile = true; break; } int line, column; QByteArray text; stream >> line >> column >> text; m_document->insertText(KTextEditor::Cursor(line, column), QString::fromUtf8 (text.data (), text.size())); break; } case EA_RemoveText: { if (!editStarted) { brokenSwapFile = true; break; } int line, startColumn, endColumn; stream >> line >> startColumn >> endColumn; m_document->removeText (KTextEditor::Range(KTextEditor::Cursor(line, startColumn), KTextEditor::Cursor(line, endColumn))); break; } default: { kWarning( 13020 ) << "Unknown type:" << type; } } } // balance editStart and editEnd if (editStarted) { brokenSwapFile = true; m_document->editEnd(); } // warn the user if the swap file is not complete if (brokenSwapFile) { kWarning ( 13020 ) << "Some data might be lost"; } // reconnect the signals setTrackingEnabled(true); return true; }