Skip to content
Open

Kate #43

1 change: 1 addition & 0 deletions sdk/wlxplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define lc_newparams 2
#define lc_selectall 3
#define lc_setpercent 4
#define lc_focus 5

#define lcp_wraptext 1
#define lcp_fittowindow 2
Expand Down
10 changes: 5 additions & 5 deletions wlx/kate/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(rich_editor_qt VERSION 1.0 LANGUAGES CXX)
project(kate_qt6 VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -12,24 +12,24 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
find_package(KF6TextEditor REQUIRED)
find_package(KF6Config REQUIRED)

add_library(rich_editor_qt SHARED
add_library(kate_qt6 SHARED
src/wlx_plugin.cpp
src/editor_widget.cpp
)

target_compile_definitions(rich_editor_qt PRIVATE
target_compile_definitions(kate_qt6 PRIVATE
RICH_EDITOR_QT_LOG_DIR="${CMAKE_CURRENT_SOURCE_DIR}/logs"
)

target_link_libraries(rich_editor_qt PRIVATE
target_link_libraries(kate_qt6 PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
KF6::TextEditor
KF6::ConfigCore
)

set_target_properties(rich_editor_qt PROPERTIES
set_target_properties(kate_qt6 PROPERTIES
PREFIX ""
SUFFIX ".wlx"
)
4 changes: 2 additions & 2 deletions wlx/kate/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# rich_editor_qt
# kate_qt6

A premium, high-performance Double Commander WLX plugin based on Native Qt6 and KDE's `KTextEditor` framework.

Expand All @@ -25,4 +25,4 @@ make
```

## Installation
Copy `rich_editor_qt.wlx` to `~/.config/doublecmd/plugins/wlx/` and add it via Double Commander's Options -> Plugins -> WLX.
Copy `kate_qt6.wlx` to `~/.config/doublecmd/plugins/wlx/` and add it via Double Commander's Options -> Plugins -> WLX.
Binary file added wlx/kate/build/kate_qt6.wlx
Binary file not shown.
26 changes: 17 additions & 9 deletions wlx/kate/src/editor_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ EditorWidget::EditorWidget(QWidget *parent)
// Disable swap files as early as possible before the view is created.
forceDisableAutoReload();
m_view = m_doc->createView(this);
setFocusProxy(m_view);
m_zoomLevel = m_view->configValue(QStringLiteral("font")).value<QFont>().pointSize();

// Create UI Elements
Expand Down Expand Up @@ -239,8 +238,6 @@ EditorWidget::EditorWidget(QWidget *parent)
QWidget *focusTarget = m_view->focusProxy() ? m_view->focusProxy() : m_view;
focusTarget->setFocus(Qt::OtherFocusReason);
m_isRestoringFocus = false;
} else {
m_isActive = false;
}
});

Expand Down Expand Up @@ -330,12 +327,6 @@ KTextEditor::Cursor EditorWidget::findWordEnd(const KTextEditor::Cursor &cursor)
}

bool EditorWidget::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::FocusIn) {
if (obj == m_view || obj == m_view->focusProxy()) {
m_isActive = true;
}
}

// Detect clicks outside our editor panel so Double Commander can regain focus.
if (event->type() == QEvent::MouseButtonPress && m_isActive) {
auto *me = static_cast<QMouseEvent*>(event);
Expand Down Expand Up @@ -370,6 +361,7 @@ bool EditorWidget::eventFilter(QObject *obj, QEvent *event) {
(key == Qt::Key_Z && (mods & Qt::ControlModifier)) ||
(key == Qt::Key_Y && (mods & Qt::ControlModifier)) ||
(key == Qt::Key_W && (mods & Qt::ControlModifier)) ||
(key == Qt::Key_Q && (mods & Qt::ControlModifier)) ||
(key == Qt::Key_R && (mods & Qt::AltModifier) && (mods & Qt::ShiftModifier)) ||
(key == Qt::Key_P && (mods & Qt::ControlModifier)) ||
((key == Qt::Key_Plus || key == Qt::Key_Equal) && (mods & Qt::ControlModifier)) ||
Expand Down Expand Up @@ -495,6 +487,12 @@ bool EditorWidget::eventFilter(QObject *obj, QEvent *event) {
} else if (key == Qt::Key_W && (mods & Qt::ControlModifier)) {
toggleReadOnly();
triggered = true;
} else if (key == Qt::Key_Q && (mods & Qt::ControlModifier)) {
if (QWidget *w = window()) {
w->setFocus(Qt::OtherFocusReason);
QCoreApplication::postEvent(w, new QKeyEvent(QEvent::KeyPress, Qt::Key_Q, Qt::ControlModifier));
}
triggered = true;
} else if (key == Qt::Key_R && (mods & Qt::AltModifier) && (mods & Qt::ShiftModifier)) {
toggleReadOnly();
triggered = true;
Expand Down Expand Up @@ -1091,6 +1089,16 @@ bool EditorWidget::isModified() const {
return m_doc ? m_doc->isModified() : false;
}

void EditorWidget::hostSetFocus(bool focus) {
if (focus) {
setActive(true);
setFocus(Qt::OtherFocusReason);
if (m_view) m_view->setFocus(Qt::OtherFocusReason);
} else {
setActive(false);
}
}

void EditorWidget::setupMenu() {
// File
QMenu *fileMenu = m_menuBar->addMenu("&File");
Expand Down
1 change: 1 addition & 0 deletions wlx/kate/src/editor_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class EditorWidget : public QWidget {

void copySelection();
void selectAll();
void hostSetFocus(bool focus);
QString currentFilePath() const;
bool isModified() const;

Expand Down
76 changes: 73 additions & 3 deletions wlx/kate/src/wlx_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#include <QDir>
#include <QHash>
#include <QObject>
#include <QCoreApplication>
#include <KPluginMetaData>
#include <QMimeDatabase>
#include <QMimeType>
#include <QSet>
#include <QStringList>

static void logLoad(const QString &msg) {
const QString dir = QStringLiteral(RICH_EDITOR_QT_LOG_DIR);
Expand Down Expand Up @@ -117,9 +123,68 @@ void DCPCALL ListCloseWindow(HWND ListWin) {
}

void DCPCALL ListGetDetectString(char* DetectString, int maxlen) {
const char* detectStr = "EXT=\"TXT\" | EXT=\"PAS\" | EXT=\"C\" | EXT=\"CPP\" | EXT=\"H\" | EXT=\"PY\" | EXT=\"JS\" | EXT=\"HTML\" | EXT=\"CSS\" | EXT=\"JSON\" | EXT=\"XML\" | EXT=\"MD\" | EXT=\"SH\"";
strncpy(DetectString, detectStr, maxlen - 1);
DetectString[maxlen - 1] = '\0';
int argc = 0;
char **argv = nullptr;
bool appCreated = false;
if (!QCoreApplication::instance()) {
new QCoreApplication(argc, argv);
appCreated = true;
}

QSet<QString> allExts;
QMimeDatabase mimeDb;

QVector<KPluginMetaData> parts = KPluginMetaData::findPlugins(QStringLiteral("kf6/parts"));
for (const KPluginMetaData &part : parts) {
if (part.pluginId() == QLatin1String("katepart")) {
QStringList mimeTypes = part.mimeTypes();
for (const QString &mimeName : mimeTypes) {
QMimeType mimeType = mimeDb.mimeTypeForName(mimeName);
if (mimeType.isValid()) {
QStringList globs = mimeType.globPatterns();
for (const QString &glob : globs) {
if (glob.startsWith(QLatin1String("*."))) {
QString fExt = glob.mid(2);
int lDot = fExt.lastIndexOf(QLatin1Char('.'));
QString aExt = (lDot == -1) ? fExt : fExt.mid(lDot + 1);
aExt = aExt.toUpper();
if (!aExt.isEmpty()) {
allExts.insert(aExt);
}
}
}
}
}
}
}

if (allExts.isEmpty()) {
const char* detectStr = "EXT=\"TXT\" | EXT=\"PAS\" | EXT=\"C\" | EXT=\"CPP\" | EXT=\"H\" | EXT=\"PY\" | EXT=\"JS\" | EXT=\"HTML\" | EXT=\"CSS\" | EXT=\"JSON\" | EXT=\"XML\" | EXT=\"MD\" | EXT=\"SH\"";
strncpy(DetectString, detectStr, maxlen - 1);
DetectString[maxlen - 1] = '\0';
} else {
QStringList extList = allExts.values();
extList.sort();

QString result;
for (const QString &ext : extList) {
QString addition = QStringLiteral("EXT=\"%1\"").arg(ext);
if (!result.isEmpty()) addition = QLatin1String(" | ") + addition;

if (result.length() + addition.length() < maxlen - 1) {
result += addition;
} else {
break;
}
}

QByteArray utf8 = result.toUtf8();
qstrncpy(DetectString, utf8.constData(), maxlen);
}

if (appCreated) {
delete QCoreApplication::instance();
}
}

int DCPCALL ListSendCommand(HWND ListWin, int Command, int Parameter) {
Expand All @@ -142,6 +207,11 @@ int DCPCALL ListSendCommand(HWND ListWin, int Command, int Parameter) {
case lc_selectall:
editor->selectAll();
return LISTPLUGIN_OK;
case lc_focus:
// DC uses lc_focus to indicate focus gained/lost.
// Parameter: 1 = focus gained, 0 = focus lost (common convention).
editor->hostSetFocus(Parameter != 0);
return LISTPLUGIN_OK;
}

return LISTPLUGIN_ERROR;
Expand Down