#include "core/DocumentManager.h" #include #include #include #include #include DocumentManager::DocumentManager(QObject *parent) : QObject(parent) { QTimer *autosave = new QTimer(this); autosave->setInterval(m_autosaveMs); autosave->setSingleShot(false); connect(autosave, &QTimer::timeout, this, &DocumentManager::saveAll); autosave->start(); // Защита при выходе connect(qApp, &QCoreApplication::aboutToQuit, this, &DocumentManager::saveAll); } QStringList DocumentManager::openTabs() const { QStringList list; list.reserve(m_docs.size()); for (const Doc &d : m_docs) list.append(d.path); return list; } int DocumentManager::activeIndex() const { return m_active; } void DocumentManager::setActiveIndex(int index) { qDebug("setActiveIndex: from %d to %d", m_active, index); if (m_active == index) return; m_active = index; emit activeIndexChanged(); } int DocumentManager::secondaryIndex() const { return m_secondary; } void DocumentManager::setSecondaryIndex(int index) { if (m_secondary == index) return; m_secondary = index; emit secondaryIndexChanged(); } bool DocumentManager::sideBySide() const { return m_sideBySide; } void DocumentManager::setSideBySide(bool on) { if (m_sideBySide == on) return; m_sideBySide = on; emit sideBySideChanged(); } int DocumentManager::autosaveIntervalMs() const { return m_autosaveMs; } void DocumentManager::setAutosaveIntervalMs(int ms) { if (m_autosaveMs == ms) return; m_autosaveMs = ms; emit autosaveIntervalChanged(); } QString DocumentManager::lastStatus() const { return m_lastStatus; } int DocumentManager::openDocument(const QString &path) { const QString clean = QFileInfo(path).absoluteFilePath(); for (int i = 0; i < m_docs.size(); ++i) { if (m_docs[i].path == clean) { setActiveIndex(i); return i; } } bool ok = false; const QString content = readFile(clean, &ok); if (!ok) { m_lastStatus = QStringLiteral("Не удалось открыть файл: %1").arg(clean); emit lastStatusChanged(); return -1; } Doc doc; doc.path = clean; doc.content = content; doc.dirty = false; m_docs.append(doc); const int idx = m_docs.size() - 1; qDebug("openDocument: path=%s idx=%d content_len=%d", qPrintable(clean), idx, content.length()); setActiveIndex(idx); emit openTabsChanged(); return idx; } QString DocumentManager::readFile(const QString &path, bool *ok) const { QFile f(path); if (!f.open(QIODevice::ReadOnly)) { if (ok) *ok = false; return QString(); } const QByteArray bytes = f.readAll(); if (ok) *ok = true; return QString::fromUtf8(bytes); } QString DocumentManager::contentAt(int index) const { if (index < 0 || index >= m_docs.size()) return QString(); return m_docs[index].content; } QString DocumentManager::titleAt(int index) const { if (index < 0 || index >= m_docs.size()) return QString(); return QFileInfo(m_docs[index].path).fileName(); } QString DocumentManager::pathAt(int index) const { if (index < 0 || index >= m_docs.size()) return QString(); return m_docs[index].path; } bool DocumentManager::isDirty(int index) const { return index >= 0 && index < m_docs.size() && m_docs[index].dirty; } void DocumentManager::updateContent(int index, const QString &text) { if (index < 0 || index >= m_docs.size()) return; Doc &d = m_docs[index]; if (d.content == text) return; d.content = text; d.dirty = true; emit dirtyFlagChanged(index); emit contentChanged(index); } bool DocumentManager::isTextForEditor(const QString &path) const { const QString ext = QFileInfo(path).suffix().toLower(); static const QStringList textExts = { "md", "markdown", "txt", "log", "json", "yaml", "yml", "c", "h", "cpp", "hpp", "cc", "cxx", "py", "go", "rs", "js", "ts", "css", "sh", "bash", "xml", "ini", "csv", "svg" }; return ext.isEmpty() || textExts.contains(ext); } void DocumentManager::saveDocument(int index) { if (index < 0 || index >= m_docs.size()) return; Doc &d = m_docs[index]; if (!d.dirty) return; QSaveFile f(d.path); if (f.open(QIODevice::WriteOnly)) { f.write(d.content.toUtf8()); if (f.commit()) { d.dirty = false; emit dirtyFlagChanged(index); emit documentSaved(index, d.path); return; } } m_lastStatus = QStringLiteral("Не удалось сохранить: %1").arg(d.path); emit lastStatusChanged(); } void DocumentManager::saveAll() { for (int i = 0; i < m_docs.size(); ++i) saveDocument(i); } bool DocumentManager::closeTab(int index) { if (index < 0 || index >= m_docs.size()) return false; // При закрытии тоже сохраняем (защита от потери текста). saveDocument(index); m_docs.removeAt(index); if (m_active > index) --m_active; else if (m_active == index) m_active = m_docs.isEmpty() ? -1 : qMin(index, m_docs.size() - 1); if (m_secondary > index) --m_secondary; else if (m_secondary == index) m_secondary = -1; emit openTabsChanged(); emit activeIndexChanged(); emit secondaryIndexChanged(); return true; }