#include "mainwindow.h" #include "sciedit.h" #include "tabwidget.h" #include "documentmanager.h" #include "appsettings.h" #include "editorviewhelper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent) , m_documentManager(new DocumentManager(this)) , m_tabWidget(new TabWidget(m_documentManager, this)) , m_cursorPosStatusLabel(new QLabel(QString("Ln: ? Col: ?"), this)) , m_encodingStatusLabel(new QLabel(QString("UTF-8"), this)) , m_languageStatusLabel(new QLabel(QString("Plain Text"), this)) { setCentralWidget(m_tabWidget); // 设置状态栏 statusBar()->addPermanentWidget(m_cursorPosStatusLabel); statusBar()->addPermanentWidget(m_encodingStatusLabel); statusBar()->addPermanentWidget(m_languageStatusLabel); // 连接标签页信号 connect(m_tabWidget, &TabWidget::currentEditorChanged, this, &MainWindow::onCurrentEditorChanged); // 连接文档管理器信号 connect(m_documentManager, &DocumentManager::documentModified, this, &MainWindow::onDocumentModified); setupActions(); // 创建第一个标签页 newFile(); } MainWindow::~MainWindow() { } void MainWindow::setupActions() { using namespace Qt::Literals::StringLiterals; // "File" menu KStandardAction::openNew(this, &MainWindow::newFile, actionCollection()); KStandardAction::open(this, &MainWindow::openFile, actionCollection()); KStandardAction::save(this, &MainWindow::saveFile, actionCollection()); KStandardAction::close(this, &MainWindow::closeFile, actionCollection()); KStandardAction::quit(qApp, &QApplication::quit, actionCollection()); // 添加另存为动作 QAction *saveAsAction = KStandardAction::saveAs(this, &MainWindow::saveAsFile, actionCollection()); // "Edit" menu KStandardAction::undo(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->undo(); } }, actionCollection()); KStandardAction::redo(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->redo(); } }, actionCollection()); KStandardAction::cut(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->cut(); } }, actionCollection()); KStandardAction::copy(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->copy(); } }, actionCollection()); KStandardAction::paste(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->paste(); } }, actionCollection()); // "Search" menu KStandardAction::find(this, [](){}, actionCollection()); KStandardAction::findNext(this, [](){}, actionCollection()); KStandardAction::findPrev(this, [](){}, actionCollection()); KStandardAction::replace(this, [](){}, actionCollection()); qDebug() << KStandardAction::name(KStandardAction::Replace); // "Language" menu QAction *lexerNoneAction = new QAction(this); lexerNoneAction->setText("None (Normal Text)"); actionCollection()->addAction(u"lexer_none"_s, lexerNoneAction); connect(lexerNoneAction, &QAction::triggered, this, [this](){ // m_editor->setLexer(nullptr); }); for (const QChar & group : LexerGroupActionMenu::groups()) { LexerGroupActionMenu *lexerGroupMenu = new LexerGroupActionMenu(group.toUpper(), group, this); actionCollection()->addAction(QStringLiteral("lexer_group_") % group, lexerGroupMenu); connect(lexerGroupMenu, &LexerGroupActionMenu::lexerSelected, this, &MainWindow::applyLexer); } // Toolbar actions KStandardAction::zoomIn(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->zoomIn(); } }, actionCollection()); KStandardAction::zoomOut(this, [this](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { editor->zoomOut(); } }, actionCollection()); KStandardAction::preferences(this, &MainWindow::showSettings, actionCollection()); QAction *toggleWrapModeAction = new QAction(this); toggleWrapModeAction->setText("Toggle Wrap Mode"); toggleWrapModeAction->setIcon(QIcon::fromTheme(u"text-wrap"_s)); toggleWrapModeAction->setCheckable(true); actionCollection()->addAction(u"toggle_wrap_mode"_s, toggleWrapModeAction); connect(toggleWrapModeAction, &QAction::triggered, this, [this, toggleWrapModeAction](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { bool switchToWrapNone = editor->wrapMode() == SC_WRAP_WORD; editor->setWrapMode(switchToWrapNone ? SC_WRAP_NONE : SC_WRAP_WORD); toggleWrapModeAction->setChecked(!switchToWrapNone); } }); QAction *toggleWhitespaceVisibilityAction = new QAction(this); toggleWhitespaceVisibilityAction->setText("Show All Characters"); toggleWhitespaceVisibilityAction->setCheckable(true); // toggleWhitespaceVisibilityAction->setIcon(QIcon::fromTheme(u"text-wrap"_s)); actionCollection()->addAction(u"toggle_show_all_characters"_s, toggleWhitespaceVisibilityAction); connect(toggleWhitespaceVisibilityAction, &QAction::triggered, this, [this, toggleWhitespaceVisibilityAction](){ if (SciEdit *editor = m_tabWidget->currentEditor()) { bool switchToVisible = editor->viewWS() == SCWS_INVISIBLE; editor->setViewWS(switchToVisible ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE); editor->setViewEOL(switchToVisible); toggleWhitespaceVisibilityAction->setChecked(switchToVisible); } }); QAction *toggleIndentGuideAction = new QAction(this); toggleIndentGuideAction->setText("Toggle Indent Guide"); toggleIndentGuideAction->setIcon(QIcon::fromTheme(u"show-guides"_s)); actionCollection()->addAction(u"toggle_indent_guide"_s, toggleIndentGuideAction); connect(toggleIndentGuideAction, &QAction::triggered, this, [this](){ // m_editor->setIndentationGuides(!m_editor->indentationGuides()); }); // Load themes KColorSchemeManager *manager = KColorSchemeManager::instance(); auto *colorSelectionMenu = KColorSchemeMenu::createMenu(manager, this); colorSelectionMenu->menu()->setTitle("&Window Color Scheme"); actionCollection()->addAction(QStringLiteral("colorscheme_menu"), colorSelectionMenu); setupGUI(); } void MainWindow::showSettings() { if (KConfigDialog::showDialog(QStringLiteral("settings"))) { return; } KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral("settings"), AppSettings::self()); dialog->setFaceType(KPageDialog::FlatList); dialog->addPage(new SettingsPage(dialog), "Appearance", "preferences-desktop-theme-global"); connect(dialog, &KConfigDialog::settingsChanged, this, [](const QString &dialogName){ qDebug() << dialogName << "changed"; }); dialog->show(); } void MainWindow::applyLexer(const QString &lexerName) { if (SciEdit *editor = m_tabWidget->currentEditor()) { Scintilla::ILexer5 * lexer = CreateLexer(lexerName.toStdString().c_str()); editor->setLexer(lexer); } } void MainWindow::newFile() { m_tabWidget->newDocument(); } void MainWindow::openFile() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(), tr("All Files (*.*)")); if (!fileName.isEmpty()) { m_tabWidget->openDocument(fileName); } } void MainWindow::saveFile() { m_tabWidget->saveCurrentDocument(); } void MainWindow::saveAsFile() { m_tabWidget->saveCurrentDocumentAs(); } void MainWindow::closeFile() { m_tabWidget->closeCurrentTab(); } void MainWindow::onCurrentTabChanged() { updateWindowTitle(); updateStatusBar(); updateActions(); } void MainWindow::onCurrentEditorChanged(SciEdit *editor) { Q_UNUSED(editor) updateWindowTitle(); updateStatusBar(); updateActions(); // 连接当前编辑器的光标位置变化信号 if (editor) { connect(editor, &SciEdit::cursorPosChanged, this, [this](int line, int column) { m_cursorPosStatusLabel->setText(QString("Ln: %1 Col: %2").arg(line).arg(column)); }); } } void MainWindow::onDocumentModified(int docIndex, bool modified) { Q_UNUSED(docIndex) Q_UNUSED(modified) updateWindowTitle(); } void MainWindow::updateWindowTitle() { QString title = "Pineapple Notepad"; if (SciEdit *editor = m_tabWidget->currentEditor()) { int docId = m_tabWidget->currentDocumentId(); if (docId >= 0) { QString fileName = m_documentManager->getDocumentTitle(docId); bool isModified = m_documentManager->isDocumentModified(docId); title = QString("%1%2 - Pineapple Notepad") .arg(fileName) .arg(isModified ? "*" : ""); } } setWindowTitle(title); } void MainWindow::updateStatusBar() { if (SciEdit *editor = m_tabWidget->currentEditor()) { int docId = m_tabWidget->currentDocumentId(); if (docId >= 0) { QString encoding = m_documentManager->getDocumentEncoding(docId); QString language = m_documentManager->getDocumentLanguage(docId); m_encodingStatusLabel->setText(encoding); m_languageStatusLabel->setText(language); } } else { m_encodingStatusLabel->setText("UTF-8"); m_languageStatusLabel->setText("Plain Text"); } } void MainWindow::updateActions() { bool hasEditor = (m_tabWidget->currentEditor() != nullptr); // 更新编辑相关的动作状态 if (QAction *undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo))) { undoAction->setEnabled(hasEditor); } if (QAction *redoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Redo))) { redoAction->setEnabled(hasEditor); } if (QAction *cutAction = actionCollection()->action(KStandardAction::name(KStandardAction::Cut))) { cutAction->setEnabled(hasEditor); } if (QAction *copyAction = actionCollection()->action(KStandardAction::name(KStandardAction::Copy))) { copyAction->setEnabled(hasEditor); } if (QAction *pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste))) { pasteAction->setEnabled(hasEditor); } }