Files
Flora/src/core/DocumentManager.cpp
T

212 lines
5.3 KiB
C++
Raw Normal View History

#include "core/DocumentManager.h"
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QSaveFile>
#include <QTextStream>
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)
{
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;
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;
}