Files
pineapple-notepad/tabwidget.cpp

382 lines
9.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}
}