add purposeplugin for kde
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,4 @@
|
||||
.env
|
||||
__pycache__/
|
||||
*.so
|
||||
*.moc
|
||||
|
||||
@@ -9,6 +9,7 @@ A modern, high-contrast **KDE Plasma System Tray Uploader** and desktop integrat
|
||||
- **System Tray App with Live Progress**: Dynamic system tray icon displaying live upload percentage (`0`–`99`%).
|
||||
- **Single-Instance IPC Architecture**: 100% Python-based daemon (`PySide6`). Multiple invocations (hotkeys, Dolphin context menu) delegate directly to the running tray instance without spawning duplicates.
|
||||
- **Dolphin Context Menu Integration**: Right-click any file in Dolphin -> **Actions** -> **Upload to f0ckm**.
|
||||
- **Gwenview / KDE Share Menu Integration**: Native KDE Purpose plugin adding **Upload to f0ckm** directly to the **Share** menu in Gwenview, Spectacle, Okular, and other KDE apps.
|
||||
- **Spectacle Screenshot Capture**: Region capture integration via hotkeys or menu trigger (`f0ckm-uploader-gui --spectacle`).
|
||||
- **Browser Extension Addon (ShareX Style)**: Right-click any image, video, link, or URL on the web in Chrome, Firefox, Brave, or Edge -> **Upload with f0ckm**.
|
||||
- **Custom Protocol Scheme (`f0ckm://`)**: Seamless URL handling (`f0ckm://upload?url=...`) delegating background remote file downloading & live tray progress directly to the system tray app.
|
||||
@@ -99,6 +100,10 @@ To bind a keyboard shortcut to capture a screen region and upload it immediately
|
||||
|
||||
- Right-click any file -> **Actions** -> **Upload to f0ckm**.
|
||||
|
||||
### Gwenview & KDE Apps (Share Menu)
|
||||
|
||||
- Click the **Share** button in Gwenview, Spectacle, or Okular -> select **Upload to f0ckm**.
|
||||
|
||||
### Command Line Interface (CLI)
|
||||
|
||||
```bash
|
||||
|
||||
39
install.sh
39
install.sh
@@ -128,7 +128,41 @@ chmod +x "$SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
||||
sed "s|__EXEC_PATH__|$INSTALL_DIR/f0ckm-uploader-gui --upload|g" f0ckm-uploader-servicemenu.desktop > "$LEGACY_SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
||||
chmod +x "$LEGACY_SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
||||
|
||||
# 5. Migrate config to config.json if not present
|
||||
# 5. Build and install KDE Purpose plugin (for Gwenview / KDE Share menu)
|
||||
if [ -f "purpose_plugin/build_plugin.sh" ]; then
|
||||
echo "Building KDE Purpose plugin for Gwenview Share Menu..."
|
||||
bash purpose_plugin/build_plugin.sh purpose_plugin &> /dev/null || true
|
||||
if [ -f "purpose_plugin/f0ckmpurposeplugin.so" ]; then
|
||||
PURPOSE_USER_DIR64="$HOME/.local/lib64/qt6/plugins/kf6/purpose"
|
||||
PURPOSE_USER_DIR32="$HOME/.local/lib/qt6/plugins/kf6/purpose"
|
||||
mkdir -p "$PURPOSE_USER_DIR64" "$PURPOSE_USER_DIR32"
|
||||
cp "purpose_plugin/f0ckmpurposeplugin.so" "$PURPOSE_USER_DIR64/f0ckmpurposeplugin.so"
|
||||
cp "purpose_plugin/f0ckmpurposeplugin.so" "$PURPOSE_USER_DIR32/f0ckmpurposeplugin.so"
|
||||
|
||||
if [ -w "/usr/lib64/qt6/plugins/kf6/purpose" ]; then
|
||||
cp "purpose_plugin/f0ckmpurposeplugin.so" "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
||||
elif sudo -n true 2>/dev/null; then
|
||||
sudo cp "purpose_plugin/f0ckmpurposeplugin.so" "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
||||
fi
|
||||
|
||||
ENV_DIR="$HOME/.config/environment.d"
|
||||
mkdir -p "$ENV_DIR"
|
||||
cat << 'ENVCONF' > "$ENV_DIR/10-qt-plugins.conf"
|
||||
QT_PLUGIN_PATH="${HOME}/.local/lib64/qt6/plugins:${HOME}/.local/lib/qt6/plugins:/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins"
|
||||
ENVCONF
|
||||
|
||||
PLASMA_ENV_DIR="$HOME/.config/plasma-workspace/env"
|
||||
mkdir -p "$PLASMA_ENV_DIR"
|
||||
cat << 'PLASMAENV' > "$PLASMA_ENV_DIR/10-qt-plugins.sh"
|
||||
export QT_PLUGIN_PATH="${HOME}/.local/lib64/qt6/plugins:${HOME}/.local/lib/qt6/plugins:${QT_PLUGIN_PATH}:/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins"
|
||||
PLASMAENV
|
||||
chmod +x "$PLASMA_ENV_DIR/10-qt-plugins.sh"
|
||||
|
||||
echo " -> Gwenview / KDE Share Menu plugin installed (Upload to f0ckm)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 6. Migrate config to config.json if not present
|
||||
CONFIG_DIR="$HOME/.config/f0ckm-uploader"
|
||||
CONFIG_FILE="$CONFIG_DIR/config.json"
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
@@ -149,7 +183,7 @@ EOF
|
||||
echo "Initial configuration created at $CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# 6. Ensure autostart state matches config.json
|
||||
# 7. Ensure autostart state matches config.json
|
||||
python3 -c '
|
||||
import json, os
|
||||
try:
|
||||
@@ -192,6 +226,7 @@ echo " f0ckm Uploader Installation Complete!"
|
||||
echo "========================================================"
|
||||
echo " -> Executable installed: $INSTALL_DIR/f0ckm-uploader-gui"
|
||||
echo " -> Dolphin context menu registered (Right-click file -> Actions -> Upload to f0ckm)"
|
||||
echo " -> Gwenview / KDE Share menu integration enabled (Upload to f0ckm)"
|
||||
echo " -> Spectacle screenshot export integration enabled"
|
||||
echo " -> Browser extension helper API ready on http://127.0.0.1:18739"
|
||||
echo "========================================================"
|
||||
|
||||
24
purpose_plugin/CMakeLists.txt
Normal file
24
purpose_plugin/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(f0ckmpurposeplugin)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
find_package(ECM REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui)
|
||||
find_package(KF6 REQUIRED COMPONENTS Purpose CoreAddons)
|
||||
|
||||
kcoreaddons_add_plugin(f0ckmpurposeplugin
|
||||
SOURCES f0ckmplugin.cpp
|
||||
INSTALL_NAMESPACE "kf6/purpose"
|
||||
)
|
||||
|
||||
target_link_libraries(f0ckmpurposeplugin
|
||||
PRIVATE
|
||||
Qt6::Core
|
||||
KF6::Purpose
|
||||
KF6::CoreAddons
|
||||
)
|
||||
69
purpose_plugin/build_plugin.sh
Executable file
69
purpose_plugin/build_plugin.sh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
OUTPUT_TARGET="${1:-$SCRIPT_DIR}"
|
||||
mkdir -p "$OUTPUT_TARGET"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_TARGET" && pwd)"
|
||||
|
||||
MOC_BIN=""
|
||||
for candidate in /usr/libexec/qt6/moc /usr/lib64/qt6/libexec/moc moc-qt6 moc; do
|
||||
if command -v "$candidate" &>/dev/null; then
|
||||
MOC_BIN="$candidate"
|
||||
break
|
||||
elif [ -x "$candidate" ]; then
|
||||
MOC_BIN="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$MOC_BIN" ]; then
|
||||
echo "Warning: Qt6 moc compiler not found. Skipping Purpose plugin compilation."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Detect header search paths
|
||||
INC_ARGS=()
|
||||
if [ -d "/usr/include/KF6/Purpose" ]; then
|
||||
INC_ARGS+=("-I/usr/include/KF6/Purpose" "-I/usr/include/KF6/KCoreAddons" "-I/usr/include/KF6")
|
||||
elif [ -d "/tmp/purpose_devel/usr/include/KF6/Purpose" ]; then
|
||||
INC_ARGS+=("-I/tmp/purpose_devel/usr/include/KF6/Purpose" "-I/tmp/purpose_devel/usr/include/KF6/KCoreAddons" "-I/tmp/purpose_devel/usr/include/KF6")
|
||||
fi
|
||||
|
||||
if [ -d "/usr/include/qt6" ]; then
|
||||
INC_ARGS+=("-I/usr/include/qt6" "-I/usr/include/qt6/QtCore" "-I/usr/include/qt6/QtGui")
|
||||
fi
|
||||
|
||||
if [ ${#INC_ARGS[@]} -eq 0 ]; then
|
||||
echo "Warning: KF6 Purpose headers not found. Skipping Purpose plugin compilation."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LIB_ARGS=()
|
||||
if [ -f "/usr/lib64/libKF6Purpose.so.6" ]; then
|
||||
LIB_ARGS+=("/usr/lib64/libKF6Purpose.so.6")
|
||||
elif [ -f "/usr/lib/libKF6Purpose.so.6" ]; then
|
||||
LIB_ARGS+=("/usr/lib/libKF6Purpose.so.6")
|
||||
fi
|
||||
|
||||
if [ -f "/usr/lib64/libKF6CoreAddons.so.6" ]; then
|
||||
LIB_ARGS+=("/usr/lib64/libKF6CoreAddons.so.6")
|
||||
elif [ -f "/usr/lib/libKF6CoreAddons.so.6" ]; then
|
||||
LIB_ARGS+=("/usr/lib/libKF6CoreAddons.so.6")
|
||||
fi
|
||||
|
||||
BUILD_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$BUILD_DIR"' EXIT
|
||||
|
||||
cp "$SCRIPT_DIR/f0ckmplugin.cpp" "$SCRIPT_DIR/f0ckmplugin.json" "$BUILD_DIR/"
|
||||
|
||||
pushd "$BUILD_DIR" >/dev/null
|
||||
"$MOC_BIN" "${INC_ARGS[@]}" f0ckmplugin.cpp -o f0ckmplugin.moc
|
||||
g++ -shared -fPIC -O2 f0ckmplugin.cpp \
|
||||
"${INC_ARGS[@]}" \
|
||||
"${LIB_ARGS[@]}" \
|
||||
-lQt6Core \
|
||||
-o "$OUTPUT_DIR/f0ckmpurposeplugin.so"
|
||||
popd >/dev/null
|
||||
|
||||
echo "Successfully built f0ckmpurposeplugin.so at $OUTPUT_DIR/f0ckmpurposeplugin.so"
|
||||
65
purpose_plugin/f0ckmplugin.cpp
Normal file
65
purpose_plugin/f0ckmplugin.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <purpose/pluginbase.h>
|
||||
#include <purpose/job.h>
|
||||
#include <KPluginFactory>
|
||||
#include <QProcess>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QDebug>
|
||||
|
||||
class F0ckmJob : public Purpose::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit F0ckmJob(QObject *parent = nullptr) : Purpose::Job(parent) {}
|
||||
|
||||
void start() override {
|
||||
QJsonObject d = data();
|
||||
QJsonArray urls = d.value(QStringLiteral("urls")).toArray();
|
||||
QStringList args;
|
||||
args << QStringLiteral("--upload");
|
||||
|
||||
for (const QJsonValue &val : urls) {
|
||||
QUrl url(val.toString());
|
||||
if (url.isLocalFile()) {
|
||||
args << url.toLocalFile();
|
||||
} else {
|
||||
args << val.toString();
|
||||
}
|
||||
}
|
||||
|
||||
QString execPath = QStandardPaths::findExecutable(QStringLiteral("f0ckm-uploader-gui"));
|
||||
if (execPath.isEmpty()) {
|
||||
execPath = QDir::homePath() + QStringLiteral("/.local/bin/f0ckm-uploader-gui");
|
||||
}
|
||||
|
||||
bool ok = QProcess::startDetached(execPath, args);
|
||||
if (!ok) {
|
||||
setError(1);
|
||||
setErrorText(QStringLiteral("Failed to launch f0ckm-uploader-gui"));
|
||||
}
|
||||
|
||||
emitResult();
|
||||
}
|
||||
};
|
||||
|
||||
class F0ckmPlugin : public Purpose::PluginBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit F0ckmPlugin(QObject *parent = nullptr, const QVariantList &args = QVariantList())
|
||||
: Purpose::PluginBase(parent)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
}
|
||||
|
||||
Purpose::Job *createJob() const override {
|
||||
return new F0ckmJob();
|
||||
}
|
||||
};
|
||||
|
||||
K_PLUGIN_CLASS_WITH_JSON(F0ckmPlugin, "f0ckmplugin.json")
|
||||
|
||||
#include "f0ckmplugin.moc"
|
||||
30
purpose_plugin/f0ckmplugin.json
Normal file
30
purpose_plugin/f0ckmplugin.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Name": "Upload to f0ckm",
|
||||
"Description": "Upload images or videos to f0ckm",
|
||||
"Icon": "f0ckm-uploader",
|
||||
"Category": "Utilities"
|
||||
},
|
||||
"X-Purpose-PluginTypes": [
|
||||
"Export"
|
||||
],
|
||||
"X-Purpose-Constraints": [
|
||||
[
|
||||
"mimeType:image/jpeg",
|
||||
"mimeType:image/png",
|
||||
"mimeType:image/gif",
|
||||
"mimeType:image/webp",
|
||||
"mimeType:image/bmp",
|
||||
"mimeType:image/svg+xml",
|
||||
"mimeType:image/tiff",
|
||||
"mimeType:image/x-xcf",
|
||||
"mimeType:video/mp4",
|
||||
"mimeType:video/webm",
|
||||
"mimeType:video/x-matroska",
|
||||
"mimeType:video/quicktime",
|
||||
"mimeType:video/x-msvideo",
|
||||
"mimeType:video/mpeg"
|
||||
]
|
||||
],
|
||||
"X-Purpose-ActionDisplay": "Upload to f0ckm"
|
||||
}
|
||||
12
uninstall.sh
12
uninstall.sh
@@ -22,7 +22,17 @@ rm -f "$SERVICE_MENU_DIR/kde-uploader-servicemenu.desktop" "$SERVICE_MENU_DIR/f0
|
||||
rm -f "$LEGACY_SERVICE_MENU_DIR/kde-uploader-servicemenu.desktop" "$LEGACY_SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
||||
echo "Removed service menu entries"
|
||||
|
||||
# 4. Remove autostart entry
|
||||
# 4. Remove KDE Purpose plugin
|
||||
rm -f "$HOME/.local/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" "$HOME/.local/lib/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so"
|
||||
rm -f "$HOME/.config/environment.d/10-qt-plugins.conf" "$HOME/.config/plasma-workspace/env/10-qt-plugins.sh"
|
||||
if [ -w "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" ]; then
|
||||
rm -f "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
||||
elif sudo -n true 2>/dev/null; then
|
||||
sudo rm -f "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
||||
fi
|
||||
echo "Removed KDE Purpose plugin (Gwenview Share menu)"
|
||||
|
||||
# 5. Remove autostart entry
|
||||
rm -f "$HOME/.config/autostart/kde-uploader-gui.desktop" "$HOME/.config/autostart/f0ckm-uploader-gui.desktop"
|
||||
echo "Removed autostart entries"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user