feat: multitab and basic file saving
This commit is contained in:
358
tabwidget.cpp
Normal file
358
tabwidget.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
#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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user