From a75a4aeee84e09432c16830ee8d2d6a9d90df8f0 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Sat, 22 Jun 2024 20:01:42 +0800 Subject: [PATCH] initial commit --- .gitignore | 5 ++ CMakeLists.txt | 51 ++++++++++++++ README.md | 16 +++++ appsettings.kcfg | 17 +++++ appsettings.kcfgc | 8 +++ generalsettings.ui | 58 ++++++++++++++++ main.cpp | 35 ++++++++++ mainwindow.cpp | 149 +++++++++++++++++++++++++++++++++++++++++ mainwindow.h | 35 ++++++++++ pineapple-notepadui.rc | 51 ++++++++++++++ 10 files changed, 425 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 appsettings.kcfg create mode 100644 appsettings.kcfgc create mode 100644 generalsettings.ui create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 pineapple-notepadui.rc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca54a51 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Common build folder +[Bb]uild/ + +# IDE stuff +CMakeLists.txt.user* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0cc7114 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +# SPDX-FileCopyrightText: 2024 Gary Wang + +cmake_minimum_required(VERSION 3.9.5) + +project(pineapple-notepad) + +find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) # kconfig generated header file is in binary dir + +find_package(Qt6 6.4 REQUIRED + COMPONENTS Widgets +) + +find_package(KF6 6.3 REQUIRED + COMPONENTS XmlGui ConfigWidgets CoreAddons I18n IconThemes +) + +add_executable(pineapple-notepad + generalsettings.ui) + +target_sources(pineapple-notepad +PRIVATE + main.cpp + mainwindow.cpp mainwindow.h + generalsettings.ui + + appsettings.kcfg +) + +qt_add_resources(pineapple-notepad xmlgui.qrc + PREFIX "/kxmlgui5/pineapple-notepad" + FILES pineapple-notepadui.rc +) + +kconfig_add_kcfg_files(pineapple-notepad GENERATE_MOC appsettings.kcfgc) + +target_link_libraries(pineapple-notepad +PRIVATE + Qt6::Widgets + KF6::XmlGui + KF6::CoreAddons + KF6::I18n + KF6::ConfigWidgets + KF6::IconThemes + qscintilla2_qt6 +) diff --git a/README.md b/README.md new file mode 100644 index 0000000..dcc3f99 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Pineapple Notepad? + +## 说明 + +这是一个用来实验 KDE Framework 的项目(主要是 Widgets 相关的组件),此项目本身(至少目前)不是一个能用的文本编辑器,甚至可以说实际上什么功能都没有。 + +现阶段,MSYS2 仓库的 KF6 组件已足以构建基本的应用程序,并包括一些优点。 + +- KXmlGui: 提供了一个便于创建与管理 QAction 的框架,可以便于将 Action 注册到菜单栏、工具栏,甚至还有一个命令搜索条。工具栏中的项目可由用户自由调整。`xxxxui.rc` +- KConfig: 提供了一个基于 XML 文件生成配置管理工具类的解决方案。`xxx.kcfg`(配置文件结构本体)与 `xxx.kcfgc`(如何生成工具类的配置) +- KConfigWidgets: 一系列配套组件,包括: + - KConfigDialog: 提供一个包括多个页的配置对话框,将若干页面加入此对话框,且根据 KConfig 生成的工具类自动更新每个页面的控件(页面内的控件需使用 `kcfg_配置名称` 作为对象名称)。 + - KHamburgerMenu: 汉堡菜单 + - KStyleManager: 用于初始化 breeze 主题(和配置似乎没啥关系..) + - KColorSchemeMenu: 提供切换主题的菜单项(MSYS2 下,KColorSchemeMenu 实际列出的可用主题只有默认和暗色两个?) +- KIconTheme: 初始化图标主题,需要在 QApplication 构造之前调用初始化,并且看上去需要配合什么别的东西才能做到颜色正确... diff --git a/appsettings.kcfg b/appsettings.kcfg new file mode 100644 index 0000000..bf03ead --- /dev/null +++ b/appsettings.kcfg @@ -0,0 +1,17 @@ + + + + + QFontDatabase + + + 4 + + + QFontDatabase::systemFont(QFontDatabase::FixedFont) + + + diff --git a/appsettings.kcfgc b/appsettings.kcfgc new file mode 100644 index 0000000..2353954 --- /dev/null +++ b/appsettings.kcfgc @@ -0,0 +1,8 @@ +File=appsettings.kcfg +ClassName=AppSettings +Mutators=true +DefaultValueGetters=true +GenerateProperties=true +ParentInConstructor=true +Notifiers=true +Singleton=true diff --git a/generalsettings.ui b/generalsettings.ui new file mode 100644 index 0000000..594093c --- /dev/null +++ b/generalsettings.ui @@ -0,0 +1,58 @@ + + + GeneralSettings + + + + 0 + 0 + 406 + 300 + + + + Form + + + + + + tAB wIDTH + + + + + + + 1 + + + 16 + + + 4 + + + + + + + eDITOR fONT + + + + + + + + + + + KFontRequester + QWidget +
kfontrequester.h
+
+
+ + +
diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..49e87f6 --- /dev/null +++ b/main.cpp @@ -0,0 +1,35 @@ +#include + +#include "mainwindow.h" + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + KIconTheme::initTheme(); + + QApplication a(argc, argv); + + KStyleManager::initStyle(); + + KLocalizedString::setApplicationDomain(QByteArrayLiteral("pineapple-notepad")); + + KAboutData aboutData(QStringLiteral("pineapple-notepad"), + "Pineapple Notepad(迫真)", + QStringLiteral("0.1"), + "A Scintilla-based Text Editor", + KAboutLicense::Unknown, + QString(), + QString(), + QStringLiteral("https://blumia.net")); + KAboutData::setApplicationData(aboutData); + a.setWindowIcon(QIcon::fromTheme(QStringLiteral("accessories-text-editor"))); + + MainWindow mw; + mw.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..7925bbf --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,149 @@ +#include "mainwindow.h" + +#include "appsettings.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +MainWindow::MainWindow(QWidget *parent) + : KXmlGuiWindow(parent) + , m_editor(new QsciScintilla(this)) +{ + setCentralWidget(m_editor); + + QFont font(AppSettings::self()->editorFont()); + m_editor->setFont(font); + m_editor->setMarginsFont(font); + + m_editor->setMarginLineNumbers(1, true); + m_editor->setMarginWidth(1, 40); + m_editor->setBraceMatching(QsciScintilla::SloppyBraceMatch); + + m_editor->setTabWidth(AppSettings::self()->tabWidth()); + m_editor->setEolMode(QsciScintilla::EolUnix); + + setupActions(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::setupActions() +{ + using namespace Qt::Literals::StringLiterals; + + // "File" menu + KStandardAction::openNew(this, [](){}, actionCollection()); + KStandardAction::open(this, [](){}, actionCollection()); + KStandardAction::save(this, [](){}, actionCollection()); + KStandardAction::close(this, [](){}, actionCollection()); + KStandardAction::quit(qApp, &QApplication::quit, actionCollection()); + + // "Edit" menu + KStandardAction::undo(this, [this](){ + m_editor->undo(); + }, actionCollection()); + KStandardAction::redo(this, [this](){ + m_editor->redo(); + }, actionCollection()); + KStandardAction::cut(this, [this](){ + m_editor->cut(); + }, actionCollection()); + KStandardAction::copy(this, [this](){ + m_editor->copy(); + }, actionCollection()); + KStandardAction::paste(this, [this](){ + m_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); + }); + + // Toolbar actions + KStandardAction::zoomIn(this, [this](){ + m_editor->zoomIn(); + }, actionCollection()); + KStandardAction::zoomOut(this, [this](){ + m_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](){ + bool switchToWrapNone = m_editor->wrapMode() == QsciScintilla::WrapWord; + m_editor->setWrapMode(switchToWrapNone ? QsciScintilla::WrapNone : QsciScintilla::WrapWord); + 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](){ + bool switchToVisible = m_editor->whitespaceVisibility() == QsciScintilla::WsInvisible; + m_editor->setWhitespaceVisibility(switchToVisible ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible); + m_editor->setEolVisibility(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 = new KColorSchemeManager(this); + 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(); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..b9a15b2 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,35 @@ +#include + +#include "ui_GeneralSettings.h" + +class QsciScintilla; +class MainWindow : public KXmlGuiWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + void setupActions(); + void showSettings(); + + QsciScintilla * m_editor; +}; + +// plainly for KConfigDialog +// void setupUi(QWidget *GeneralSettings) +template +class SettingsPage : public QWidget +{ +public: + SettingsPage(QWidget *parent) + : QWidget(parent) + { + ui.setupUi(this); + } + +private: + T ui; +}; diff --git a/pineapple-notepadui.rc b/pineapple-notepadui.rc new file mode 100644 index 0000000..8cc0f6e --- /dev/null +++ b/pineapple-notepadui.rc @@ -0,0 +1,51 @@ + + + + + + + + + &Search + + + + + + &View + + + + E&ncoding + + &Language + + + &Settings + + + + + + Main Toolbar + + + + +