commit c602bea0ae80c8079138be5fc51603f3f05d4c5d Author: Abigail Magalhães Date: Fri Jul 2 20:33:57 2021 -0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0daa57b --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + +build +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..18617e7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.14) + +project(reactionmanager VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED) + +set(PROJECT_SOURCES + src/main.cpp + src/clipboard.hpp + qml.qrc +) + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(reactionmanager + MANUAL_FINALIZATION + ${PROJECT_SOURCES} + ) +else() + if(ANDROID) + add_library(reactionmanager SHARED + ${PROJECT_SOURCES} + ) + else() + add_executable(reactionmanager + ${PROJECT_SOURCES} + ) + endif() +endif() + +target_compile_definitions(reactionmanager + PRIVATE $<$,$>:QT_QML_DEBUG>) +target_link_libraries(reactionmanager + PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick) + +set_target_properties(reactionmanager PROPERTIES + MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} +) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_import_qml_plugins(reactionmanager) + qt_finalize_executable(reactionmanager) +endif() diff --git a/README.md b/README.md new file mode 100644 index 0000000..73fc953 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +reactionmanager +=============== + +don't use this lol + +Building +-------- + +```sh +mkdir -p build; cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make +``` + +Usage +----- + +``` +reactionmanager path/to/directory +``` + +all of the files need to be in the same level of the directory hierarchy so if you like to organise things you're screwed \ No newline at end of file diff --git a/qml.qrc b/qml.qrc new file mode 100644 index 0000000..845bf60 --- /dev/null +++ b/qml.qrc @@ -0,0 +1,6 @@ + + + src/main.qml + src/widgets/Reaction.qml + + diff --git a/src/clipboard.hpp b/src/clipboard.hpp new file mode 100644 index 0000000..d2f0aa1 --- /dev/null +++ b/src/clipboard.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class Clipboard : public QObject { + Q_OBJECT + +public: + Clipboard(QGuiApplication *owner, const char *app) : _app(app), _owner(owner) { } + virtual ~Clipboard() {}; + + Q_INVOKABLE void setClipboard(QUrl str) { + QProcess proc; + proc.setProgram(QString(_app)); + + QStringList args{"clipboard", str.path()}; + proc.setArguments(args); + + qint64 pid; + proc.startDetached(&pid); + std::cout << "clipboard owner " << _app << " started: " << pid << std::endl; + + _owner->quit(); + } + +private: + const char *_app; + QGuiApplication *_owner; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..cf1fc0a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +#include "sys/stat.h" +#include "clipboard.hpp" + +int selection(int argc, char *argv[]) { + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; + + const QUrl url(QStringLiteral("qrc:/src/main.qml")); + + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + + engine.load(url); + engine.rootContext()->setContextProperty("clipboard", new Clipboard(&app, argv[0])); + + return app.exec(); +} + +int clipboard(int argc, char *argv[]) { + QGuiApplication app(argc, argv); + QClipboard *clip = QGuiApplication::clipboard(); + + struct stat buf; + if (stat(argv[2], &buf) == -1) { + perror("stat"); + exit(1); + } + + QString path(argv[2]); + QImage image(path); + clip->setImage(image); + clip->connect(clip, &QClipboard::dataChanged, [&]() { + app.quit(); + }); + + return app.exec(); +} + +int main(int argc, char *argv[]) { + if (argc >= 3 && strcmp(argv[1], "clipboard") == 0) { + return clipboard(argc, argv); + } else { + return selection(argc, argv); + } +} diff --git a/src/main.qml b/src/main.qml new file mode 100644 index 0000000..16e62bb --- /dev/null +++ b/src/main.qml @@ -0,0 +1,144 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.3 + +import Qt.labs.folderlistmodel 2.15 +import QtQml.Models 2.15 + +import "qrc:/src/widgets" + +Window { + width: 700 + height: 500 + visible: true + title: qsTr("reaction image manager") + flags: Qt.Dialog + id: window; + + Component { + id: delegate + + Item { + width: imageList.cellWidth + height: imageList.cellHeight + clip: true + + Column { + anchors.fill: parent + + Reaction { + anchors.horizontalCenter: parent.horizontalCenter + + path: fileUrl + width: Math.min(parent.width, parent.height) - label.height + height: Math.min(parent.width, parent.height) - label.height + } + + Text { + id: label + anchors.horizontalCenter: parent.horizontalCenter + text: fileName + } + } + } + } + + Column { + anchors.fill: parent + + TextField { + id: text + placeholderText: qsTr("Search") + focus: true + + height: 40 + width: parent.width + + onTextChanged: () => { + backingModel.nameFilters = makeFilter(text.text) + imageList.currentIndex = 0 + imageList.moveCurrentIndexRight() + } + + Keys.onPressed: { + if (event.key == Qt.Key_Tab || event.key == Qt.Key_Right) { + event.accepted = true + imageList.moveCurrentIndexRight() + } else if (event.key == Qt.Key_Up) { + event.accepted = true + imageList.moveCurrentIndexUp() + } else if (event.key == Qt.Key_Down) { + event.accepted = true + imageList.moveCurrentIndexDown() + } else if (event.key == Qt.Key_Left) { + event.accepted = true + imageList.moveCurrentIndexLeft() + } else if (event.key == Qt.Key_Escape) { + Qt.quit() + } + } + + onAccepted: { + clipboard.setClipboard(backingModel.get(imageList.currentIndex, 'fileUrl') || backingModel.get(0, 'fileUrl')); + } + } + + Row { + width: parent.width + height: parent.height - 40 + + Rectangle { + width: 2 * (parent.width / 3) + height: parent.height + + GridView { + id: imageList + anchors.fill: parent + + clip: true + + keyNavigationWraps: true + flickableDirection: Flickable.AutoFlickDirection + + cellWidth: parent.width / 3; + cellHeight: imageList.cellWidth + + snapMode: GridView.SnapToRow + + model: FolderListModel { + id: backingModel + nameFilters: makeFilter("") + folder: "file:" + Qt.application.arguments[1] + } + + delegate: delegate + + highlight: Rectangle { + color: "lightsteelblue" + radius: 5 + } + } + } + + Reaction { + width: parent.width / 3 + height: parent.height + path: backingModel.get(imageList.currentIndex, 'fileUrl') || backingModel.get(0, 'fileUrl') + } + } + } + + function makeFilter(text) { + if (text.indexOf("*") !== -1) { + return [text] + } + + return [ + "*" + text + "*.png", + "*" + text + "*.gif", + "*" + text + "*.jpg", + "*" + text + "*.jpeg", + ] + } +} \ No newline at end of file diff --git a/src/widgets/Reaction.qml b/src/widgets/Reaction.qml new file mode 100644 index 0000000..9638799 --- /dev/null +++ b/src/widgets/Reaction.qml @@ -0,0 +1,39 @@ +import QtQuick 2.15 + +Item { + id: container + property alias path: image.source + + MouseArea { + id: mouseArea + width: container.width; height: container.height + anchors.fill: container; + drag.target: image; + + AnimatedImage { + id: image + anchors.fill: parent + + fillMode: Image.PreserveAspectFit + + Drag.active: mouseArea.drag.active + Drag.hotSpot.x: 0 + Drag.hotSpot.y: 0 + Drag.mimeData: { + "text/uri-list": container.path + } + + Drag.dragType: Drag.Automatic + + Drag.onDragFinished: { + Qt.quit() + } + + onStatusChanged: { + if (image.status === Image.Failed) { + container.visible = false + } + } + } + } +} \ No newline at end of file