initial commit

This commit is contained in:
Gary Wang 2024-06-22 20:01:42 +08:00
commit a75a4aeee8
No known key found for this signature in database
GPG Key ID: 5D30A4F15EA78760
10 changed files with 425 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Common build folder
[Bb]uild/
# IDE stuff
CMakeLists.txt.user*

51
CMakeLists.txt Normal file
View File

@ -0,0 +1,51 @@
# SPDX-FileCopyrightText: 2024 Gary Wang <git@blumia.net>
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
)

16
README.md Normal file
View File

@ -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 构造之前调用初始化,并且看上去需要配合什么别的东西才能做到颜色正确...

17
appsettings.kcfg Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="pineapple-notepadrc" />
<include>QFontDatabase</include>
<group name="Editor">
<entry name="tabWidth" type="int">
<default>4</default>
</entry>
<entry name="editorFont" type="Font" key="editor-font">
<default code="true">QFontDatabase::systemFont(QFontDatabase::FixedFont)</default>
</entry>
</group>
</kcfg>

8
appsettings.kcfgc Normal file
View File

@ -0,0 +1,8 @@
File=appsettings.kcfg
ClassName=AppSettings
Mutators=true
DefaultValueGetters=true
GenerateProperties=true
ParentInConstructor=true
Notifiers=true
Singleton=true

58
generalsettings.ui Normal file
View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GeneralSettings</class>
<widget class="QWidget" name="GeneralSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>406</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>tAB wIDTH</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="kcfg_tabWidth">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="value">
<number>4</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>eDITOR fONT</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="KFontRequester" name="kcfg_editorFont"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KFontRequester</class>
<extends>QWidget</extends>
<header>kfontrequester.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

35
main.cpp Normal file
View File

@ -0,0 +1,35 @@
#include <QApplication>
#include "mainwindow.h"
#include <KAboutData>
#include <KLocalizedString>
#include <KIconTheme>
#include <KStyleManager>
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();
}

149
mainwindow.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "mainwindow.h"
#include "appsettings.h"
#include <QApplication>
#include <QMenu>
#include <KActionCollection>
#include <KStandardAction>
#include <KActionMenu>
#include <KConfigDialog>
#include <KColorSchemeManager>
#include <KColorSchemeMenu>
#include <QSpinBox>
#include <Qsci/qsciscintilla.h>
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<Ui::GeneralSettings>(dialog), "Appearance", "preferences-desktop-theme-global");
connect(dialog, &KConfigDialog::settingsChanged, this, [](const QString &dialogName){
qDebug() << dialogName << "changed";
});
dialog->show();
}

35
mainwindow.h Normal file
View File

@ -0,0 +1,35 @@
#include <KXmlGuiWindow>
#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 <typename T>
class SettingsPage : public QWidget
{
public:
SettingsPage(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
private:
T ui;
};

51
pineapple-notepadui.rc Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DTD: https://github.com/KDE/kxmlgui/blob/master/src/kpartgui.dtd
Template: https://github.com/KDE/kxmlgui/blob/master/src/ui_standards.rc
-->
<gui name="pineapple-notepad"
version="1"
xmlns="http://www.kde.org/standards/kxmlgui/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd">
<MenuBar>
<Menu name="file" >
</Menu>
<Menu name="edit">
</Menu>
<Menu name="search"><text>&amp;Search</text>
<Action name="edit_find" />
<Action name="edit_find_next" />
<Action name="edit_find_prev" />
<Action name="edit_replace" />
</Menu>
<Menu name="view"><text>&amp;View</text>
<!-- <Menu><text>&amp;Zoom</text>
<Action name="view_zoom_in"/>
<Action name="view_zoom_out"/>
</Menu>-->
<Action name="toggle_wrap_mode" />
</Menu>
<Menu name="encoding"><text>E&amp;ncoding</text>
</Menu>
<Menu name="language"><text>&amp;Language</text>
<Action name="lexer_none" />
</Menu>
<Menu name="settings"><text>&amp;Settings</text>
<Action name="colorscheme_menu"/>
</Menu>
<!-- this is not enough, user can still see actions like About KDE from other places
<menu name="help" noMerge="1"><text>&amp;Help</text>
<Action name="open_kcommand_bar"/>
<Separator/>
<Action name="help_about_app"/>
</menu> -->
</MenuBar>
<ToolBar name="mainToolBar" >
<text>Main Toolbar</text>
<Action name="toggle_wrap_mode" />
<Action name="toggle_show_all_characters" />
<Action name="toggle_indent_guide" />
</ToolBar>
</gui>