Files
pineapple-notepad/tabwidget.cpp

358 lines
8.9 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;
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;
// 设置编辑器内容
QString content = m_documentManager->getDocumentContent(docId);
editor->setText(content.toUtf8().constData());
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)
{
if (index < 0 || index >= count()) {
return false;
}
int docId = m_tabToDocumentId.value(index, -1);
if (docId == -1) {
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; // 取消关闭
}
}
// 移除标签页
QWidget *widget = this->widget(index);
removeTab(index);
// 清理映射关系
m_tabToDocumentId.remove(index);
m_documentIdToTab.remove(docId);
// 更新其他标签页的索引映射
QHash<int, int> newTabToDocumentId;
QHash<int, int> newDocumentIdToTab;
for (int i = 0; i < count(); ++i) {
int oldIndex = (i >= index) ? i + 1 : i;
int oldDocId = m_tabToDocumentId.value(oldIndex, -1);
if (oldDocId != -1) {
newTabToDocumentId[i] = oldDocId;
newDocumentIdToTab[oldDocId] = i;
}
}
m_tabToDocumentId = newTabToDocumentId;
m_documentIdToTab = newDocumentIdToTab;
// 清理编辑器和文档
if (m_editors.contains(docId)) {
SciEdit *editor = m_editors[docId];
disconnectEditorSignals(editor);
m_editors.remove(docId);
}
m_documentManager->closeDocument(docId);
if (widget) {
widget->deleteLater();
}
// 如果没有标签页了,创建一个新的
if (count() == 0) {
newDocument();
}
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)
{
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);
connectEditorSignals(editor);
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);
}
}