382 lines
9.8 KiB
C++
382 lines
9.8 KiB
C++
#include "tabwidget.h"
|
||
#include "sciedit.h"
|
||
#include "documentmanager.h"
|
||
|
||
#include <QFileDialog>
|
||
#include <QMessageBox>
|
||
#include <QDebug>
|
||
|
||
TabWidget::TabWidget(DocumentManager *documentManager, QWidget *parent)
|
||
: QTabWidget(parent)
|
||
, m_documentManager(documentManager)
|
||
{
|
||
setTabsClosable(true);
|
||
setMovable(true);
|
||
setUsesScrollButtons(true);
|
||
|
||
// 连接信号
|
||
connect(this, &QTabWidget::currentChanged, this, &TabWidget::onCurrentChanged);
|
||
connect(this, &QTabWidget::tabCloseRequested, this, &TabWidget::onTabCloseRequested);
|
||
|
||
// 连接文档管理器信号
|
||
connect(m_documentManager, &DocumentManager::documentModified,
|
||
this, &TabWidget::onDocumentModified);
|
||
connect(m_documentManager, &DocumentManager::documentTitleChanged,
|
||
this, &TabWidget::onDocumentTitleChanged);
|
||
|
||
// 创建第一个文档
|
||
newDocument();
|
||
}
|
||
|
||
TabWidget::~TabWidget()
|
||
{
|
||
}
|
||
|
||
int TabWidget::newDocument()
|
||
{
|
||
int docId = m_documentManager->createNewDocument();
|
||
if (docId == -1) {
|
||
return -1;
|
||
}
|
||
|
||
SciEdit *editor = createEditor();
|
||
m_editors[docId] = editor;
|
||
|
||
// 连接信号
|
||
connectEditorSignals(editor);
|
||
|
||
QString title = m_documentManager->getDocumentTitle(docId);
|
||
int tabIndex = addTab(editor, title);
|
||
|
||
m_tabToDocumentId[tabIndex] = docId;
|
||
m_documentIdToTab[docId] = tabIndex;
|
||
|
||
setCurrentIndex(tabIndex);
|
||
|
||
return docId;
|
||
}
|
||
|
||
int TabWidget::openDocument(const QString &filePath)
|
||
{
|
||
int docId = m_documentManager->openDocument(filePath);
|
||
if (docId == -1) {
|
||
QMessageBox::warning(this, "Error", "Failed to open file: " + filePath);
|
||
return -1;
|
||
}
|
||
|
||
SciEdit *editor = createEditor();
|
||
m_editors[docId] = editor;
|
||
|
||
// 临时断开信号连接,避免setText触发textChanged导致文档被标记为已修改
|
||
disconnectEditorSignals(editor);
|
||
|
||
// 设置编辑器内容
|
||
QString content = m_documentManager->getDocumentContent(docId);
|
||
editor->setText(content.toUtf8().constData());
|
||
|
||
// 重新连接信号
|
||
connectEditorSignals(editor);
|
||
|
||
QString title = m_documentManager->getDocumentTitle(docId);
|
||
int tabIndex = addTab(editor, title);
|
||
|
||
m_tabToDocumentId[tabIndex] = docId;
|
||
m_documentIdToTab[docId] = tabIndex;
|
||
|
||
setCurrentIndex(tabIndex);
|
||
|
||
return docId;
|
||
}
|
||
|
||
bool TabWidget::saveCurrentDocument()
|
||
{
|
||
SciEdit *editor = currentEditor();
|
||
if (!editor) {
|
||
return false;
|
||
}
|
||
|
||
int docId = currentDocumentId();
|
||
if (docId == -1) {
|
||
return false;
|
||
}
|
||
|
||
// 更新文档内容
|
||
QByteArray content = editor->getText(editor->textLength());
|
||
m_documentManager->setDocumentContent(docId, QString::fromUtf8(content));
|
||
|
||
if (m_documentManager->isDocumentUntitled(docId)) {
|
||
return saveCurrentDocumentAs();
|
||
}
|
||
|
||
return m_documentManager->saveDocument(docId);
|
||
}
|
||
|
||
bool TabWidget::saveCurrentDocumentAs()
|
||
{
|
||
SciEdit *editor = currentEditor();
|
||
if (!editor) {
|
||
return false;
|
||
}
|
||
|
||
int docId = currentDocumentId();
|
||
if (docId == -1) {
|
||
return false;
|
||
}
|
||
|
||
QString fileName = QFileDialog::getSaveFileName(this,
|
||
"Save File",
|
||
m_documentManager->getDocumentTitle(docId),
|
||
"All Files (*.*)");
|
||
|
||
if (fileName.isEmpty()) {
|
||
return false;
|
||
}
|
||
|
||
// 更新文档内容
|
||
QByteArray content = editor->getText(editor->textLength());
|
||
m_documentManager->setDocumentContent(docId, QString::fromUtf8(content));
|
||
|
||
return m_documentManager->saveDocumentAs(docId, fileName);
|
||
}
|
||
|
||
void TabWidget::closeCurrentTab()
|
||
{
|
||
int index = currentIndex();
|
||
if (index >= 0) {
|
||
closeTab(index);
|
||
}
|
||
}
|
||
|
||
bool TabWidget::closeTab(int index)
|
||
{
|
||
qDebug() << "closeTab called with index:" << index << "count:" << count();
|
||
|
||
if (index < 0 || index >= count()) {
|
||
qDebug() << "Invalid index, returning false";
|
||
return false;
|
||
}
|
||
|
||
int docId = m_tabToDocumentId.value(index, -1);
|
||
qDebug() << "Document ID for index" << index << "is" << docId;
|
||
|
||
if (docId == -1) {
|
||
qDebug() << "No document ID found for index, returning false";
|
||
return false;
|
||
}
|
||
|
||
// 检查是否需要保存
|
||
if (m_documentManager->isDocumentModified(docId)) {
|
||
QString title = m_documentManager->getDocumentTitle(docId);
|
||
int ret = QMessageBox::question(this, "Save Changes",
|
||
QString("The document '%1' has been modified.\nDo you want to save your changes?").arg(title),
|
||
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||
|
||
if (ret == QMessageBox::Save) {
|
||
// 更新文档内容
|
||
SciEdit *editor = editorAt(index);
|
||
if (editor) {
|
||
QByteArray content = editor->getText(editor->textLength());
|
||
m_documentManager->setDocumentContent(docId, QString::fromUtf8(content));
|
||
}
|
||
|
||
bool saved = false;
|
||
if (m_documentManager->isDocumentUntitled(docId)) {
|
||
QString fileName = QFileDialog::getSaveFileName(this,
|
||
"Save File",
|
||
title,
|
||
"All Files (*.*)");
|
||
if (!fileName.isEmpty()) {
|
||
saved = m_documentManager->saveDocumentAs(docId, fileName);
|
||
}
|
||
} else {
|
||
saved = m_documentManager->saveDocument(docId);
|
||
}
|
||
|
||
if (!saved) {
|
||
return false; // 保存失败,不关闭标签页
|
||
}
|
||
} else if (ret == QMessageBox::Cancel) {
|
||
return false; // 取消关闭
|
||
}
|
||
}
|
||
|
||
qDebug() << "Proceeding to close tab";
|
||
|
||
// 清理编辑器和文档
|
||
if (m_editors.contains(docId)) {
|
||
SciEdit *editor = m_editors[docId];
|
||
disconnectEditorSignals(editor);
|
||
m_editors.remove(docId);
|
||
}
|
||
|
||
m_documentManager->closeDocument(docId);
|
||
|
||
// 移除标签页
|
||
QWidget *widget = this->widget(index);
|
||
removeTab(index);
|
||
|
||
// 清理和更新映射关系
|
||
m_tabToDocumentId.remove(index);
|
||
m_documentIdToTab.remove(docId);
|
||
|
||
// 更新后续标签页的索引映射(索引减1)
|
||
QHash<int, int> newTabToDocumentId;
|
||
QHash<int, int> newDocumentIdToTab;
|
||
|
||
for (auto it = m_tabToDocumentId.begin(); it != m_tabToDocumentId.end(); ++it) {
|
||
int tabIndex = it.key();
|
||
int documentId = it.value();
|
||
|
||
if (tabIndex > index) {
|
||
// 后续标签页的索引需要减1
|
||
newTabToDocumentId[tabIndex - 1] = documentId;
|
||
newDocumentIdToTab[documentId] = tabIndex - 1;
|
||
} else {
|
||
// 前面的标签页索引不变
|
||
newTabToDocumentId[tabIndex] = documentId;
|
||
newDocumentIdToTab[documentId] = tabIndex;
|
||
}
|
||
}
|
||
|
||
m_tabToDocumentId = newTabToDocumentId;
|
||
m_documentIdToTab = newDocumentIdToTab;
|
||
|
||
if (widget) {
|
||
widget->deleteLater();
|
||
}
|
||
|
||
// 如果没有标签页了,创建一个新的
|
||
if (count() == 0) {
|
||
newDocument();
|
||
}
|
||
|
||
qDebug() << "Tab closed successfully";
|
||
return true;
|
||
}
|
||
|
||
void TabWidget::closeAllTabs()
|
||
{
|
||
while (count() > 0) {
|
||
closeTab(0);
|
||
}
|
||
}
|
||
|
||
SciEdit *TabWidget::currentEditor() const
|
||
{
|
||
int docId = currentDocumentId();
|
||
return m_editors.value(docId, nullptr);
|
||
}
|
||
|
||
SciEdit *TabWidget::editorAt(int index) const
|
||
{
|
||
int docId = m_tabToDocumentId.value(index, -1);
|
||
return m_editors.value(docId, nullptr);
|
||
}
|
||
|
||
int TabWidget::currentDocumentId() const
|
||
{
|
||
int index = currentIndex();
|
||
return m_tabToDocumentId.value(index, -1);
|
||
}
|
||
|
||
int TabWidget::documentIdAt(int index) const
|
||
{
|
||
return m_tabToDocumentId.value(index, -1);
|
||
}
|
||
|
||
void TabWidget::setCurrentTab(int index)
|
||
{
|
||
if (index >= 0 && index < count()) {
|
||
setCurrentIndex(index);
|
||
}
|
||
}
|
||
|
||
int TabWidget::findTabByDocumentId(int docId) const
|
||
{
|
||
return m_documentIdToTab.value(docId, -1);
|
||
}
|
||
|
||
void TabWidget::onCurrentChanged(int index)
|
||
{
|
||
SciEdit *editor = editorAt(index);
|
||
emit currentEditorChanged(editor);
|
||
}
|
||
|
||
void TabWidget::onTabCloseRequested(int index)
|
||
{
|
||
qDebug() << "Tab close requested for index:" << index;
|
||
closeTab(index);
|
||
}
|
||
|
||
void TabWidget::onDocumentModified(int docId, bool modified)
|
||
{
|
||
int tabIndex = findTabByDocumentId(docId);
|
||
if (tabIndex >= 0) {
|
||
updateTabTitle(tabIndex);
|
||
}
|
||
}
|
||
|
||
void TabWidget::onDocumentTitleChanged(int docId, const QString &title)
|
||
{
|
||
int tabIndex = findTabByDocumentId(docId);
|
||
if (tabIndex >= 0) {
|
||
updateTabTitle(tabIndex);
|
||
}
|
||
}
|
||
|
||
void TabWidget::onEditorTextChanged()
|
||
{
|
||
SciEdit *editor = qobject_cast<SciEdit*>(sender());
|
||
if (!editor) {
|
||
return;
|
||
}
|
||
|
||
// 找到对应的文档ID
|
||
int docId = -1;
|
||
for (auto it = m_editors.begin(); it != m_editors.end(); ++it) {
|
||
if (it.value() == editor) {
|
||
docId = it.key();
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (docId != -1) {
|
||
QByteArray content = editor->getText(editor->textLength());
|
||
m_documentManager->setDocumentContent(docId, QString::fromUtf8(content));
|
||
}
|
||
}
|
||
|
||
SciEdit *TabWidget::createEditor()
|
||
{
|
||
SciEdit *editor = new SciEdit(this);
|
||
return editor;
|
||
}
|
||
|
||
void TabWidget::updateTabTitle(int tabIndex)
|
||
{
|
||
int docId = m_tabToDocumentId.value(tabIndex, -1);
|
||
if (docId == -1) {
|
||
return;
|
||
}
|
||
|
||
QString title = m_documentManager->getDocumentTitle(docId);
|
||
if (m_documentManager->isDocumentModified(docId)) {
|
||
title += " *";
|
||
}
|
||
|
||
setTabText(tabIndex, title);
|
||
}
|
||
|
||
void TabWidget::connectEditorSignals(SciEdit *editor)
|
||
{
|
||
if (editor) {
|
||
connect(editor, &SciEdit::textChanged, this, &TabWidget::onEditorTextChanged);
|
||
}
|
||
}
|
||
|
||
void TabWidget::disconnectEditorSignals(SciEdit *editor)
|
||
{
|
||
if (editor) {
|
||
disconnect(editor, &SciEdit::textChanged, this, &TabWidget::onEditorTextChanged);
|
||
}
|
||
} |