diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..98760cf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "QHotkey"] + path = QHotkey + url = https://github.com/Skycoder42/QHotkey.git diff --git a/KShare.pro b/KShare.pro index 34d4bf8..051090f 100644 --- a/KShare.pro +++ b/KShare.pro @@ -37,7 +37,9 @@ SOURCES += main.cpp\ uploaders/default/clipboarduploader.cpp \ formatter.cpp \ uploaders/customuploader.cpp \ - notifications.cpp + notifications.cpp \ + hotkeying.cpp \ + sequencedialog.cpp HEADERS += mainwindow.hpp \ cropeditor/cropeditor.hpp \ @@ -53,7 +55,9 @@ HEADERS += mainwindow.hpp \ uploaders/default/clipboarduploader.hpp \ formatter.hpp \ uploaders/customuploader.hpp \ - notifications.hpp + notifications.hpp \ + hotkeying.hpp \ + sequencedialog.hpp FORMS += mainwindow.ui @@ -68,3 +72,5 @@ ICON = icons/favicon.ico # Enable debug symbols QMAKE_CFLAGS_DEBUG += -g + +include(QHotkey/qhotkey.pri) diff --git a/QHotkey b/QHotkey new file mode 160000 index 0000000..040cf5e --- /dev/null +++ b/QHotkey @@ -0,0 +1 @@ +Subproject commit 040cf5ec0cf2ed605c39d7bc4d0164ab7c54d6bf diff --git a/README.md b/README.md index d90b54d..2e13069 100644 --- a/README.md +++ b/README.md @@ -7,22 +7,27 @@ A [ShareX](https://github.com/ShareX/) clone written in Qt. Should be cross plat * Qt 5 Widgets * Qt 5 GUI * Qt 5 Network +* (QHotkey)[https://github.com/Skycoder42/QHotkey] Despite the name implying so, this project does not depend on the KDE API at all. ## Goals * Same support for Windows, Linux and Mac (if I ever get testers) * Screenshotting: -* 1. Fullscreen, -* 2. Area; +* 1. Fullscreen, [target: 1.0] [done] +* 2. Area; [target: 1.0] [done] * Screen recording, same options as above: * 1. WebM * 2. GIF (nopls) -* Custom uploader support +* Custom uploader support [target: 1.0] [done] * Default uploaders, including: -* 1. imgur -* 2. Clipboard (not an uploader) +* 1. imgur [target: 1.0] [done] +* 2. Clipboard (not an uploader) [target: 1.0] [done] * 3. (S)FTP -* Oh, and a good icon. +* Oh, and a good icon. [looks good to me, but to noone else] + +## Wayland Support + +If it's requested enough, I will make a pull request towards QHotkey to support Wayland. Or open an issue, depending on my mood. But Qt _should_ still work on Wayland. ###### Started on 19th of April 2017 to bring some attention and improvement to Linux screenshotting. diff --git a/cropeditor/cropeditor.cpp b/cropeditor/cropeditor.cpp index 2b12978..4d89cd2 100644 --- a/cropeditor/cropeditor.cpp +++ b/cropeditor/cropeditor.cpp @@ -13,6 +13,7 @@ CropEditor::CropEditor(QPixmap *image, QObject *parent) : QObject(parent) view = new CropView(scene); pixmapItem = new QGraphicsPixmapItem(*pixmap); + pixmapItem->setZValue(-1); scene->addItem(pixmapItem); scene->setSceneRect(pixmap->rect()); diff --git a/cropeditor/cropscene.cpp b/cropeditor/cropscene.cpp index 17c0125..0aef096 100644 --- a/cropeditor/cropscene.cpp +++ b/cropeditor/cropscene.cpp @@ -1,9 +1,22 @@ #include "cropscene.hpp" #include +#include #include +#include CropScene::CropScene(QObject *parent) : QGraphicsScene(parent), prevButtons(Qt::NoButton) { + QTimer::singleShot(0, [&] { + QPolygonF poly; + poly.append(sceneRect().topLeft()); + poly.append(sceneRect().topRight()); + poly.append(sceneRect().bottomRight()); + poly.append(sceneRect().bottomLeft()); + polyItem = new QGraphicsPolygonItem(poly); + polyItem->setBrush(QBrush(QColor(0, 0, 0, 191))); + polyItem->setPen(QPen(Qt::NoPen)); + addItem(polyItem); + }); } CropScene::~CropScene() @@ -35,10 +48,26 @@ void CropScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) } else { - rect->setRect(QRect(qMin(initPos.x(), p.x()), qMin(initPos.y(), p.y()), - qAbs(initPos.x() - p.x()), qAbs(initPos.y() - p.y()))); + rect->setRect(QRect(qMin(initPos.x(), p.x()), qMin(initPos.y(), p.y()), qAbs(initPos.x() - p.x()), + qAbs(initPos.y() - p.y()))); } } + QPolygonF poly; + QPointF theMagicWikipediaPoint(rect->rect().right(), sceneRect().bottom()); + poly << sceneRect().topLeft(); + poly << sceneRect().topRight(); + poly << sceneRect().bottomRight(); + poly << theMagicWikipediaPoint; + poly << rect->rect().bottomRight(); + poly << rect->rect().topRight(); + poly << rect->rect().topLeft(); + poly << rect->rect().bottomLeft(); + poly << rect->rect().bottomRight(); + poly << theMagicWikipediaPoint; + poly << sceneRect().bottomLeft(); + poly << sceneRect().topLeft(); + + this->polyItem->setPolygon(poly); e->accept(); } else diff --git a/cropeditor/cropscene.hpp b/cropeditor/cropscene.hpp index cbd4723..44cfefa 100644 --- a/cropeditor/cropscene.hpp +++ b/cropeditor/cropscene.hpp @@ -27,6 +27,7 @@ class CropScene : public QGraphicsScene QFlags prevButtons; QGraphicsRectItem *rect = nullptr; QPointF initPos; + QGraphicsPolygonItem *polyItem = nullptr; }; #endif // CROPSCENE_HPP diff --git a/hotkeying.cpp b/hotkeying.cpp new file mode 100644 index 0000000..4066c68 --- /dev/null +++ b/hotkeying.cpp @@ -0,0 +1,43 @@ +#include "hotkeying.hpp" + +#include +#include +#include + +QMap hotkeys; + +// func gets bound only on first set, or load +void hotkeying::hotkey(QString seqName, QKeySequence seq, std::function func) +{ + if (hotkeys.contains(seqName)) + hotkeys.value(seqName)->setShortcut(seq, true); + else + { + QHotkey *hotkey = new QHotkey(seq, true); + QObject::connect(hotkey, &QHotkey::activated, func); + hotkeys.insert(seqName, hotkey); + } + settings::settings().setValue(seqName.prepend("hotkey_"), seq.toString()); +} + +// forces the hotkey from settings +void hotkeying::load(QString seqName, std::function func) +{ + QHotkey *h; + if (settings::settings().contains(seqName.prepend("hotkey_"))) + h = new QHotkey(QKeySequence(settings::settings().value(seqName.prepend("hotkey_")).toString()), true); + else + h = new QHotkey; + QObject::connect(h, &QHotkey::activated, func); + hotkeys.insert(seqName, h); +} + +bool hotkeying::valid(QString seq) +{ + return !QKeySequence(seq).toString().isEmpty(); +} + +QString hotkeying::sequence(QString seqName) +{ + return hotkeys.contains(seqName) ? hotkeys.value(seqName)->shortcut().toString() : ""; +} diff --git a/hotkeying.hpp b/hotkeying.hpp new file mode 100644 index 0000000..c45ace4 --- /dev/null +++ b/hotkeying.hpp @@ -0,0 +1,16 @@ +#ifndef HOTKEYING_HPP +#define HOTKEYING_HPP + +#include +#include +#include + +namespace hotkeying +{ +void hotkey(QString seqName, QKeySequence seq, std::function func); +bool valid(QString seq); +void load(QString seqName, std::function func); +QString sequence(QString seqName); +} + +#endif // HOTKEYING_HPP diff --git a/main.cpp b/main.cpp index b028975..79e0544 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ #include "mainwindow.hpp" +#include "sequencedialog.hpp" #include int main(int argc, char *argv[]) @@ -7,6 +8,7 @@ int main(int argc, char *argv[]) a.setApplicationName("KShare"); a.setOrganizationName("ArsenArsen"); a.setApplicationVersion("1.0"); + MainWindow w; w.show(); return a.exec(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 55f91d8..7e41346 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -11,11 +11,23 @@ #include #include #include +#include +#include +#include #include #include MainWindow *MainWindow::instance; +void addHotkeyItem(QString text, QString name, std::function *func) +{ + QListWidgetItem *item = new QListWidgetItem(text, MainWindow::inst()->ui->hotkeys); + item->setData(Qt::UserRole + 1, name); + MainWindow::inst()->fncs.insert(name, func); + hotkeying::load(name, *func); +} + + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { instance = this; @@ -62,6 +74,15 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi ui->delay->setValue(settings::settings().value("delay").toDouble()); else ui->delay->setValue(0.25); + + // keys are hot, wait what + hotkeying::load("fullscreen", [this] { on_actionFullscreen_triggered(); }); + hotkeying::load("area", [this] { on_actionArea_triggered(); }); + + ui->hotkeys->setSelectionMode(QListWidget::SingleSelection); + + addHotkeyItem("Fullscreen image", "fullscreen", new std::function([&] { on_actionFullscreen_triggered(); })); + addHotkeyItem("Area image", "area", new std::function([&] { on_actionArea_triggered(); })); } MainWindow::~MainWindow() @@ -141,3 +162,15 @@ void MainWindow::on_delay_valueChanged(double arg1) { settings::settings().setValue("delay", arg1); } + +void MainWindow::on_hotkeys_doubleClicked(const QModelIndex &) +{ + if (ui->hotkeys->selectedItems().length() == 1) + { + QListWidgetItem *i = ui->hotkeys->selectedItems().at(0); + QString str = i->data(Qt::UserRole + 1).toString(); + QString seq = QInputDialog::getText(ui->centralWidget, "Hotkey Input", "Insert hotkey:", QLineEdit::Normal, + hotkeying::sequence(str)); + if (hotkeying::valid(seq)) hotkeying::hotkey(str, QKeySequence(seq), *fncs.value(str)); + } +} diff --git a/mainwindow.hpp b/mainwindow.hpp index 5cd6d20..679913a 100644 --- a/mainwindow.hpp +++ b/mainwindow.hpp @@ -3,7 +3,9 @@ #include #include +#include #include +#include #include @@ -28,18 +30,21 @@ class MainWindow : public QMainWindow void on_delay_valueChanged(double arg1); + void on_hotkeys_doubleClicked(const QModelIndex &index); + public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + Ui::MainWindow *ui; QSystemTrayIcon *tray; void setScheme(QString scheme); QDoubleSpinBox *delay(); static MainWindow *inst(); + QMap *> fncs; private: - Ui::MainWindow *ui; static MainWindow *instance; protected: diff --git a/mainwindow.ui b/mainwindow.ui index c1443f2..3b92ba7 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 471 - 315 + 512 + 353 @@ -56,13 +56,6 @@ - - - - s - - - @@ -76,6 +69,36 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + s + + + + + + + Hotkeys + + + + + + @@ -83,7 +106,7 @@ 0 0 - 471 + 512 24