Hey it only took me two days to fix a segfault!!!!

This commit is contained in:
ArsenArsen 2017-06-04 01:04:42 +02:00
parent 6128ac40b5
commit 8f5197b826
16 changed files with 216 additions and 26 deletions

View File

@ -48,7 +48,9 @@ SOURCES += main.cpp\
cropeditor/drawing/textitem.cpp \ cropeditor/drawing/textitem.cpp \
colorpicker/colorpickerscene.cpp \ colorpicker/colorpickerscene.cpp \
worker/worker.cpp \ worker/worker.cpp \
screenareaselector/screenareaselector.cpp screenareaselector/screenareaselector.cpp \
recording/recordingpreview.cpp \
recording/recordingcontroller.cpp
HEADERS += mainwindow.hpp \ HEADERS += mainwindow.hpp \
cropeditor/cropeditor.hpp \ cropeditor/cropeditor.hpp \
@ -78,7 +80,9 @@ HEADERS += mainwindow.hpp \
platformbackend.hpp \ platformbackend.hpp \
gif-h/gif.h \ gif-h/gif.h \
worker/worker.hpp \ worker/worker.hpp \
screenareaselector/screenareaselector.hpp screenareaselector/screenareaselector.hpp \
recording/recordingpreview.hpp \
recording/recordingcontroller.hpp
mac { mac {
SOURCES += $$PWD/platformspecifics/mac/macbackend.cpp SOURCES += $$PWD/platformspecifics/mac/macbackend.cpp

@ -1 +1 @@
Subproject commit 9eace8fbbd8dede95db623eea5e25403fd59b490 Subproject commit 2578b69dc51e3786402777e650181c5735015e1a

View File

@ -20,14 +20,14 @@ void hotkeying::hotkey(QString seqName, QKeySequence seq, std::function<void()>
} }
// forces the hotkey from settings // forces the hotkey from settings
void hotkeying::load(QString seqName, std::function<void()> func) { void hotkeying::load(QString seqName, std::function<void()> func, QString def) {
QHotkey *h; QHotkey *h;
QString name = seqName; QString name = seqName;
name.prepend("hotkey_"); name.prepend("hotkey_");
if (settings::settings().contains(name)) if (settings::settings().contains(name))
h = new QHotkey(QKeySequence(settings::settings().value(name).toString()), true); h = new QHotkey(QKeySequence(settings::settings().value(name).toString()), true);
else else
h = new QHotkey; h = new QHotkey(def.isNull() ? "" : def, true);
QObject::connect(h, &QHotkey::activated, func); QObject::connect(h, &QHotkey::activated, func);
hotkeys.insert(seqName, h); hotkeys.insert(seqName, h);
} }

View File

@ -8,7 +8,7 @@
namespace hotkeying { namespace hotkeying {
void hotkey(QString seqName, QKeySequence seq, std::function<void()> func); void hotkey(QString seqName, QKeySequence seq, std::function<void()> func);
bool valid(QString seq); bool valid(QString seq);
void load(QString seqName, std::function<void()> func); void load(QString seqName, std::function<void()> func, QString def = QString());
QString sequence(QString seqName); QString sequence(QString seqName);
} }

View File

@ -5,8 +5,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <iostream> #include <iostream>
#include <notifications.hpp> #include <notifications.hpp>
#include <screenareaselector/screenareaselector.hpp>
#include <stdio.h>
#include <worker/worker.hpp> #include <worker/worker.hpp>
bool verbose = false; bool verbose = false;
@ -63,6 +61,5 @@ int main(int argc, char *argv[]) {
Worker::init(); Worker::init();
a.connect(&a, &QApplication::aboutToQuit, Worker::end); a.connect(&a, &QApplication::aboutToQuit, Worker::end);
if (!parser.isSet(h)) w.show(); if (!parser.isSet(h)) w.show();
(new ScreenAreaSelector())->show();
return a.exec(); return a.exec();
} }

View File

@ -23,11 +23,11 @@
MainWindow *MainWindow::instance; MainWindow *MainWindow::instance;
void addHotkeyItem(QString text, QString name, std::function<void()> *func) { void addHotkeyItem(QString text, QString name, std::function<void()> func, QString def = QString()) {
QListWidgetItem *item = new QListWidgetItem(text, MainWindow::inst()->ui->hotkeys); QListWidgetItem *item = new QListWidgetItem(text, MainWindow::inst()->ui->hotkeys);
item->setData(Qt::UserRole + 1, name); item->setData(Qt::UserRole + 1, name);
MainWindow::inst()->fncs.insert(name, func); 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) { 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); ui->hotkeys->setSelectionMode(QListWidget::SingleSelection);
addHotkeyItem("Fullscreen image", "fullscreen", new std::function<void()>([] { screenshotter::fullscreen(); })); addHotkeyItem("Fullscreen image", "fullscreen", [] { screenshotter::fullscreen(); });
addHotkeyItem("Area image", "area", new std::function<void()>([] { screenshotter::area(); })); addHotkeyItem("Area image", "area", [] { screenshotter::area(); });
addHotkeyItem("Color picker", "picker", new std::function<void()>([] { ColorPickerScene::showPicker(); })); addHotkeyItem("Color picker", "picker", [] { ColorPickerScene::showPicker(); });
addHotkeyItem("Stop Recording", "recordingstop", [&] { controller->end(); });
ui->quickMode->setChecked(settings::settings().value("quickMode", false).toBool()); ui->quickMode->setChecked(settings::settings().value("quickMode", false).toBool());
ui->hideToTray->setChecked(settings::settings().value("hideOnClose", true).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); QListWidgetItem *i = ui->hotkeys->selectedItems().at(0);
QString str = i->data(Qt::UserRole + 1).toString(); QString str = i->data(Qt::UserRole + 1).toString();
bool ok; bool ok;
QString seq = QInputDialog::getText(ui->centralWidget, "Hotkey Input", "Insert hotkey:", QLineEdit::Normal, hotkeying::sequence(str), &ok); QString seq = QInputDialog::getText(ui->centralWidget, "Hotkey Input", "Insert hotkey:", QLineEdit::Normal,
if (ok && hotkeying::valid(seq)) hotkeying::hotkey(str, QKeySequence(seq), *fncs.value(str)); hotkeying::sequence(str), &ok);
if (ok && hotkeying::valid(seq)) hotkeying::hotkey(str, QKeySequence(seq), fncs.value(str));
} }
} }

View File

@ -7,6 +7,7 @@
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <functional> #include <functional>
#include <recording/recordingcontroller.hpp>
#include <uploaders/uploader.hpp> #include <uploaders/uploader.hpp>
namespace Ui { namespace Ui {
@ -15,7 +16,7 @@ class MainWindow;
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
private slots: private slots:
void quit(); void quit();
void toggleVisible(); void toggleVisible();
void newUploader(Uploader *u); void newUploader(Uploader *u);
@ -33,7 +34,7 @@ class MainWindow : public QMainWindow {
void on_actionColor_Picker_triggered(); void on_actionColor_Picker_triggered();
void on_captureCursor_clicked(bool checked); void on_captureCursor_clicked(bool checked);
public: public:
explicit MainWindow(QWidget *parent = 0); explicit MainWindow(QWidget *parent = 0);
~MainWindow(); ~MainWindow();
Ui::MainWindow *ui; Ui::MainWindow *ui;
@ -43,12 +44,13 @@ class MainWindow : public QMainWindow {
QDoubleSpinBox *delay(); QDoubleSpinBox *delay();
static MainWindow *inst(); static MainWindow *inst();
QMap<QString, std::function<void()> *> fncs; QMap<QString, std::function<void()>> fncs;
private: private:
static MainWindow *instance; static MainWindow *instance;
RecordingController *controller = new RecordingController;
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
}; };

View File

@ -0,0 +1,68 @@
#include "recordingcontroller.hpp"
#include <QImage>
#include <QRect>
#include <QTimer>
#include <iostream>
#include <mainwindow.hpp>
#include <screenareaselector/screenareaselector.hpp>
#include <screenshotutil.hpp>
#include <settings.hpp>
#include <stdio.h>
#include <worker/worker.hpp>
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<QPixmap> 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());
}

View File

@ -0,0 +1,42 @@
#ifndef RECORDINGCONTROLLER_HPP
#define RECORDINGCONTROLLER_HPP
#include "recordingpreview.hpp"
#include <QImage>
#include <QRect>
#include <QTimer>
#include <functional>
#include <memory>
class RecordingContext {
public:
QImage::Format format;
std::function<void(QImage)> consumer;
std::function<void()> 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

View File

@ -0,0 +1,50 @@
#include "recordingpreview.hpp"
#include <QApplication>
#include <QDebug>
#include <QGridLayout>
#include <QLayout>
#include <QScreen>
#include <QTimer>
#include <hotkeying.hpp>
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"));
}

View File

@ -0,0 +1,23 @@
#ifndef RECORDINGPREVIEW_HPP
#define RECORDINGPREVIEW_HPP
#include <QLabel>
#include <QObject>
#include <QRect>
#include <QWidget>
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

View File

@ -19,6 +19,7 @@ ScreenAreaSelector::ScreenAreaSelector() {
move(rect.topLeft()); move(rect.topLeft());
} }
hintLabel->setText(QString::number(width()) + "x" + QString::number(height())); hintLabel->setText(QString::number(width()) + "x" + QString::number(height()));
show();
}); });
setLayout(new QStackedLayout()); setLayout(new QStackedLayout());
hintLabel = new QLabel(); hintLabel = new QLabel();

View File

@ -8,7 +8,7 @@
#include <settings.hpp> #include <settings.hpp>
void screenshotter::area() { 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) { QObject::connect(editor, &CropEditor::cropped, [&](QPixmap *pixmap) {
UploaderSingleton::inst().upload(pixmap); UploaderSingleton::inst().upload(pixmap);
QScopedPointer<CropEditor>(editor); QScopedPointer<CropEditor>(editor);

View File

@ -4,7 +4,7 @@
QSettings &settings::settings() { QSettings &settings::settings() {
static QDir configDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)); static QDir configDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation));
if (configDir.path() == QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)) { if (configDir.dirName() != "KShare") {
configDir.mkdir("KShare"); configDir.mkdir("KShare");
configDir.cd("KShare"); configDir.cd("KShare");
} }

View File

@ -4,6 +4,7 @@
Worker *Worker::inst = 0; Worker *Worker::inst = 0;
QMutex Worker::workerLock; QMutex Worker::workerLock;
QMutex Worker::lock;
// QPixmaps don't like existing on non GUI threads. // QPixmaps don't like existing on non GUI threads.
// Because of this we have to: // Because of this we have to:
@ -17,7 +18,7 @@ void Worker::queue(WorkerContext *context) {
c->image = context->pixmap.toImage(); c->image = context->pixmap.toImage();
c->consumer = context->consumer; c->consumer = context->consumer;
c->targetFormat = context->targetFormat; c->targetFormat = context->targetFormat;
qqueue.enqueue(c); inst->qqueue.enqueue(c);
} }
void Worker::init() { void Worker::init() {

View File

@ -24,13 +24,13 @@ struct _WorkerContext {
class Worker : public QObject { class Worker : public QObject {
Q_OBJECT Q_OBJECT
public: public:
void queue(WorkerContext *context); static void queue(WorkerContext *context);
static void init(); static void init();
private: private:
Worker(); Worker();
~Worker(); ~Worker();
QMutex lock; static QMutex lock;
QMutex endLock; QMutex endLock;
QThread *thr; QThread *thr;
QQueue<_WorkerContext *> qqueue; // Say that ten times as fast QQueue<_WorkerContext *> qqueue; // Say that ten times as fast