From 8f5197b8263e34b8fb6aaed6f3d88870bb8213a4 Mon Sep 17 00:00:00 2001 From: ArsenArsen Date: Sun, 4 Jun 2017 01:04:42 +0200 Subject: [PATCH] Hey it only took me two days to fix a segfault!!!! --- KShare.pro | 8 ++- QHotkey | 2 +- hotkeying.cpp | 4 +- hotkeying.hpp | 2 +- main.cpp | 3 - mainwindow.cpp | 16 +++--- mainwindow.hpp | 12 ++-- recording/recordingcontroller.cpp | 68 +++++++++++++++++++++++ recording/recordingcontroller.hpp | 42 ++++++++++++++ recording/recordingpreview.cpp | 50 +++++++++++++++++ recording/recordingpreview.hpp | 23 ++++++++ screenareaselector/screenareaselector.cpp | 1 + screenshotter.cpp | 2 +- settings.cpp | 2 +- worker/worker.cpp | 3 +- worker/worker.hpp | 4 +- 16 files changed, 216 insertions(+), 26 deletions(-) create mode 100644 recording/recordingcontroller.cpp create mode 100644 recording/recordingcontroller.hpp create mode 100644 recording/recordingpreview.cpp create mode 100644 recording/recordingpreview.hpp diff --git a/KShare.pro b/KShare.pro index a115114..02c0ae5 100644 --- a/KShare.pro +++ b/KShare.pro @@ -48,7 +48,9 @@ SOURCES += main.cpp\ cropeditor/drawing/textitem.cpp \ colorpicker/colorpickerscene.cpp \ worker/worker.cpp \ - screenareaselector/screenareaselector.cpp + screenareaselector/screenareaselector.cpp \ + recording/recordingpreview.cpp \ + recording/recordingcontroller.cpp HEADERS += mainwindow.hpp \ cropeditor/cropeditor.hpp \ @@ -78,7 +80,9 @@ HEADERS += mainwindow.hpp \ platformbackend.hpp \ gif-h/gif.h \ worker/worker.hpp \ - screenareaselector/screenareaselector.hpp + screenareaselector/screenareaselector.hpp \ + recording/recordingpreview.hpp \ + recording/recordingcontroller.hpp mac { SOURCES += $$PWD/platformspecifics/mac/macbackend.cpp diff --git a/QHotkey b/QHotkey index 9eace8f..2578b69 160000 --- a/QHotkey +++ b/QHotkey @@ -1 +1 @@ -Subproject commit 9eace8fbbd8dede95db623eea5e25403fd59b490 +Subproject commit 2578b69dc51e3786402777e650181c5735015e1a diff --git a/hotkeying.cpp b/hotkeying.cpp index 5a5b741..8bef764 100644 --- a/hotkeying.cpp +++ b/hotkeying.cpp @@ -20,14 +20,14 @@ void hotkeying::hotkey(QString seqName, QKeySequence seq, std::function } // forces the hotkey from settings -void hotkeying::load(QString seqName, std::function func) { +void hotkeying::load(QString seqName, std::function func, QString def) { QHotkey *h; QString name = seqName; name.prepend("hotkey_"); if (settings::settings().contains(name)) h = new QHotkey(QKeySequence(settings::settings().value(name).toString()), true); else - h = new QHotkey; + h = new QHotkey(def.isNull() ? "" : def, true); QObject::connect(h, &QHotkey::activated, func); hotkeys.insert(seqName, h); } diff --git a/hotkeying.hpp b/hotkeying.hpp index 14fab77..696a680 100644 --- a/hotkeying.hpp +++ b/hotkeying.hpp @@ -8,7 +8,7 @@ namespace hotkeying { void hotkey(QString seqName, QKeySequence seq, std::function func); bool valid(QString seq); -void load(QString seqName, std::function func); +void load(QString seqName, std::function func, QString def = QString()); QString sequence(QString seqName); } diff --git a/main.cpp b/main.cpp index 2562dfe..1e2d6f1 100644 --- a/main.cpp +++ b/main.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include bool verbose = false; @@ -63,6 +61,5 @@ int main(int argc, char *argv[]) { Worker::init(); a.connect(&a, &QApplication::aboutToQuit, Worker::end); if (!parser.isSet(h)) w.show(); - (new ScreenAreaSelector())->show(); return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 6325544..56e07fd 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -23,11 +23,11 @@ MainWindow *MainWindow::instance; -void addHotkeyItem(QString text, QString name, std::function *func) { +void addHotkeyItem(QString text, QString name, std::function func, QString def = QString()) { 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); + hotkeying::load(name, func, def); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { @@ -84,9 +84,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi ui->hotkeys->setSelectionMode(QListWidget::SingleSelection); - addHotkeyItem("Fullscreen image", "fullscreen", new std::function([] { screenshotter::fullscreen(); })); - addHotkeyItem("Area image", "area", new std::function([] { screenshotter::area(); })); - addHotkeyItem("Color picker", "picker", new std::function([] { ColorPickerScene::showPicker(); })); + addHotkeyItem("Fullscreen image", "fullscreen", [] { screenshotter::fullscreen(); }); + addHotkeyItem("Area image", "area", [] { screenshotter::area(); }); + addHotkeyItem("Color picker", "picker", [] { ColorPickerScene::showPicker(); }); + addHotkeyItem("Stop Recording", "recordingstop", [&] { controller->end(); }); ui->quickMode->setChecked(settings::settings().value("quickMode", false).toBool()); ui->hideToTray->setChecked(settings::settings().value("hideOnClose", true).toBool()); @@ -169,8 +170,9 @@ void MainWindow::on_hotkeys_doubleClicked(const QModelIndex &) { QListWidgetItem *i = ui->hotkeys->selectedItems().at(0); QString str = i->data(Qt::UserRole + 1).toString(); bool ok; - QString seq = QInputDialog::getText(ui->centralWidget, "Hotkey Input", "Insert hotkey:", QLineEdit::Normal, hotkeying::sequence(str), &ok); - if (ok && hotkeying::valid(seq)) hotkeying::hotkey(str, QKeySequence(seq), *fncs.value(str)); + QString seq = QInputDialog::getText(ui->centralWidget, "Hotkey Input", "Insert hotkey:", QLineEdit::Normal, + hotkeying::sequence(str), &ok); + if (ok && hotkeying::valid(seq)) hotkeying::hotkey(str, QKeySequence(seq), fncs.value(str)); } } diff --git a/mainwindow.hpp b/mainwindow.hpp index 1c844fe..c4404cb 100644 --- a/mainwindow.hpp +++ b/mainwindow.hpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace Ui { @@ -15,7 +16,7 @@ class MainWindow; class MainWindow : public QMainWindow { Q_OBJECT - private slots: +private slots: void quit(); void toggleVisible(); void newUploader(Uploader *u); @@ -33,7 +34,7 @@ class MainWindow : public QMainWindow { void on_actionColor_Picker_triggered(); void on_captureCursor_clicked(bool checked); - public: +public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); Ui::MainWindow *ui; @@ -43,12 +44,13 @@ class MainWindow : public QMainWindow { QDoubleSpinBox *delay(); static MainWindow *inst(); - QMap *> fncs; + QMap> fncs; - private: +private: static MainWindow *instance; + RecordingController *controller = new RecordingController; - protected: +protected: void closeEvent(QCloseEvent *event); }; diff --git a/recording/recordingcontroller.cpp b/recording/recordingcontroller.cpp new file mode 100644 index 0000000..15a6df8 --- /dev/null +++ b/recording/recordingcontroller.cpp @@ -0,0 +1,68 @@ +#include "recordingcontroller.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +RecordingController::RecordingController() : timer(this) { + connect(&timer, &QTimer::timeout, this, &RecordingController::timeout); +} + +bool RecordingController::isRunning() { + return timer.isActive(); +} + +bool RecordingController::start(RecordingContext *context) { + if (isRunning()) return false; + if (_context) delete _context; + _context = context; + ScreenAreaSelector *sel = new ScreenAreaSelector; + connect(sel, &ScreenAreaSelector::selectedArea, this, &RecordingController::startWithArea); + return true; +} + +bool RecordingController::end() { + if (!isRunning()) return false; + timer.stop(); + area = QRect(); + preview->close(); + preview = 0; + _context->finalizer(); + frame = 0; + time = 0; + return true; +} + +void RecordingController::timeout() { + if (isRunning()) { + time++; + int localTime = time * timer.interval() - 3000; + if (localTime > 0) { + QPixmap *pp = screenshotutil::fullscreenArea(settings::settings().value("captureCursor", true).toBool(), + area.x(), area.y(), area.width(), area.height()); + QScopedPointer p(pp); + WorkerContext *context = new WorkerContext; + context->consumer = _context->consumer; + context->targetFormat = _context->format; + context->pixmap = *pp; + frame++; + preview->setPixmap(*pp); + Worker::queue(context); + } + long second = localTime / 1000 % 60; + long minute = localTime / 60000; + preview->setTime(QString("%1:%2").arg(QString::number(minute)).arg(QString::number(second)), frame); + } +} + +void RecordingController::startWithArea(QRect newArea) { + area = newArea; + preview = new RecordingPreview(newArea); + timer.start(1000 / settings::settings().value("recording/framerate", 30).toInt()); +} diff --git a/recording/recordingcontroller.hpp b/recording/recordingcontroller.hpp new file mode 100644 index 0000000..08ecc9d --- /dev/null +++ b/recording/recordingcontroller.hpp @@ -0,0 +1,42 @@ +#ifndef RECORDINGCONTROLLER_HPP +#define RECORDINGCONTROLLER_HPP + +#include "recordingpreview.hpp" + +#include +#include +#include +#include +#include + +class RecordingContext { +public: + QImage::Format format; + std::function consumer; + std::function finalizer; +}; + +class RecordingController : public QObject { + Q_OBJECT +public: + RecordingController(); + bool isRunning(); +public slots: + // Returns false if isRunning + bool start(RecordingContext *context); + // Returns false if not running + bool end(); +private slots: + void timeout(); + void startWithArea(QRect newArea); + +private: + QRect area; + RecordingContext *_context = 0; + QTimer timer; + RecordingPreview *preview = nullptr; + unsigned int frame = 0; + unsigned int time = 0; +}; + +#endif // RECORDINGCONTROLLER_HPP diff --git a/recording/recordingpreview.cpp b/recording/recordingpreview.cpp new file mode 100644 index 0000000..91c53f0 --- /dev/null +++ b/recording/recordingpreview.cpp @@ -0,0 +1,50 @@ +#include "recordingpreview.hpp" +#include +#include +#include +#include +#include +#include +#include + +RecordingPreview::RecordingPreview(QRect area, QWidget *parent) : QWidget(parent) { + recordingArea = area; + setStyleSheet("background-color: rgba(0, 0, 0, 0.7);"); + setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_DeleteOnClose); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setWindowFlags(windowFlags() | Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); + QTimer::singleShot(0, [&] { + adjustSize(); + move(0, 0); + if (geometry().intersects(recordingArea)) // Formatter please + move(QApplication::primaryScreen()->size().width() - rect().width(), 0); + if (geometry().intersects(recordingArea)) // Formatter please + move(0, QApplication::primaryScreen()->size().height() - rect().height()); + if (geometry().intersects(recordingArea)) + move(QApplication::primaryScreen()->size().width() - rect().width(), + QApplication::primaryScreen()->size().height() - rect().height()); + if (!geometry().intersects(recordingArea)) show(); + }); + label = new QLabel; + hintLabel = new QLabel; + auto ly = new QGridLayout(this); + setLayout(ly); + layout()->addWidget(hintLabel); + layout()->addWidget(label); + hintLabel->setText(QString("Time: 00:00\nFrame: 0\nStop key: ") + hotkeying::sequence("recordingstop")); +} + +RecordingPreview::~RecordingPreview() { + // delete everything; + delete label; + delete hintLabel; +} + +void RecordingPreview::setPixmap(QPixmap map) { + label->setPixmap(map); +} +void RecordingPreview::setTime(QString time, int frame) { + hintLabel->setText(QString("Time: ") + time + "\nFrame: " + QString::number(frame) + + "\nStop key: " + hotkeying::sequence("recordingstop")); +} diff --git a/recording/recordingpreview.hpp b/recording/recordingpreview.hpp new file mode 100644 index 0000000..56d56aa --- /dev/null +++ b/recording/recordingpreview.hpp @@ -0,0 +1,23 @@ +#ifndef RECORDINGPREVIEW_HPP +#define RECORDINGPREVIEW_HPP + +#include +#include +#include +#include + +class RecordingPreview : public QWidget { + Q_OBJECT +public: + explicit RecordingPreview(QRect recordingArea, QWidget *parent = 0); + ~RecordingPreview(); + void setPixmap(QPixmap map); + void setTime(QString time, int frame); + +private: + QLabel *label; + QLabel *hintLabel; + QRect recordingArea; +}; + +#endif // RECORDINGPREVIEW_HPP diff --git a/screenareaselector/screenareaselector.cpp b/screenareaselector/screenareaselector.cpp index b599ae1..07300a2 100644 --- a/screenareaselector/screenareaselector.cpp +++ b/screenareaselector/screenareaselector.cpp @@ -19,6 +19,7 @@ ScreenAreaSelector::ScreenAreaSelector() { move(rect.topLeft()); } hintLabel->setText(QString::number(width()) + "x" + QString::number(height())); + show(); }); setLayout(new QStackedLayout()); hintLabel = new QLabel(); diff --git a/screenshotter.cpp b/screenshotter.cpp index 06eeff8..322ba31 100644 --- a/screenshotter.cpp +++ b/screenshotter.cpp @@ -8,7 +8,7 @@ #include void screenshotter::area() { - CropEditor *editor = new CropEditor(screenshotutil::fullscreen()); + CropEditor *editor = new CropEditor(screenshotutil::fullscreen(settings::settings().value("captureCursor", true).toBool())); QObject::connect(editor, &CropEditor::cropped, [&](QPixmap *pixmap) { UploaderSingleton::inst().upload(pixmap); QScopedPointer(editor); diff --git a/settings.cpp b/settings.cpp index e179a96..3a0ea99 100644 --- a/settings.cpp +++ b/settings.cpp @@ -4,7 +4,7 @@ QSettings &settings::settings() { static QDir configDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)); - if (configDir.path() == QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)) { + if (configDir.dirName() != "KShare") { configDir.mkdir("KShare"); configDir.cd("KShare"); } diff --git a/worker/worker.cpp b/worker/worker.cpp index ed5bf3b..e629ddb 100644 --- a/worker/worker.cpp +++ b/worker/worker.cpp @@ -4,6 +4,7 @@ Worker *Worker::inst = 0; QMutex Worker::workerLock; +QMutex Worker::lock; // QPixmaps don't like existing on non GUI threads. // Because of this we have to: @@ -17,7 +18,7 @@ void Worker::queue(WorkerContext *context) { c->image = context->pixmap.toImage(); c->consumer = context->consumer; c->targetFormat = context->targetFormat; - qqueue.enqueue(c); + inst->qqueue.enqueue(c); } void Worker::init() { diff --git a/worker/worker.hpp b/worker/worker.hpp index e47a631..6e82db2 100644 --- a/worker/worker.hpp +++ b/worker/worker.hpp @@ -24,13 +24,13 @@ struct _WorkerContext { class Worker : public QObject { Q_OBJECT public: - void queue(WorkerContext *context); + static void queue(WorkerContext *context); static void init(); private: Worker(); ~Worker(); - QMutex lock; + static QMutex lock; QMutex endLock; QThread *thr; QQueue<_WorkerContext *> qqueue; // Say that ten times as fast