Redesigned uploaders a bit to support more stuff.

Added a functionality of uploading byte arrays and even files. Created RecordingFormat, which allows me to create states, I guess??, for RecordingContex's. Needed for, eg. gifs, which are horrible and I strongly suggest against, which will actually be stored as files per frame which are QImages encoded with QImage::Format_RGB888 (confirmation needed).
This commit is contained in:
ArsenArsen 2017-06-04 22:58:29 +02:00
parent 8f5197b826
commit 34624e5762
16 changed files with 168 additions and 63 deletions

View File

@ -50,7 +50,8 @@ SOURCES += main.cpp\
worker/worker.cpp \
screenareaselector/screenareaselector.cpp \
recording/recordingpreview.cpp \
recording/recordingcontroller.cpp
recording/recordingcontroller.cpp \
recording/recordingformats.cpp
HEADERS += mainwindow.hpp \
cropeditor/cropeditor.hpp \
@ -82,7 +83,8 @@ HEADERS += mainwindow.hpp \
worker/worker.hpp \
screenareaselector/screenareaselector.hpp \
recording/recordingpreview.hpp \
recording/recordingcontroller.hpp
recording/recordingcontroller.hpp \
recording/recordingformats.hpp
mac {
SOURCES += $$PWD/platformspecifics/mac/macbackend.cpp

View File

@ -37,5 +37,7 @@ bool hotkeying::valid(QString seq) {
}
QString hotkeying::sequence(QString seqName) {
return hotkeys.contains(seqName) ? hotkeys.value(seqName)->shortcut().toString() : "";
return hotkeys.contains(seqName) ?
hotkeys.value(seqName)->isRegistered() ? hotkeys.value(seqName)->shortcut().toString() : "" :
"";
}

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>512</width>
<height>399</height>
<height>410</height>
</rect>
</property>
<property name="windowTitle">
@ -25,6 +25,18 @@
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="9" column="1">
<widget class="QComboBox" name="comboBox">
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>Recording disabled</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="nameScheme">
<property name="toolTip">
@ -63,7 +75,7 @@
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<item row="11" column="0" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&lt;a href=&quot;https://github.com/ArsenArsen/KShare&quot;&gt;Source code available free for everyone. Forever.&lt;/a&gt;
@ -92,13 +104,6 @@
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="hideToTray">
<property name="text">
<string>Pressing &lt;X&gt; hides to tray</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="5">
<widget class="QListWidget" name="hotkeys"/>
</item>
@ -112,13 +117,27 @@
<item row="1" column="0">
<widget class="QListWidget" name="uploaderList"/>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QCheckBox" name="captureCursor">
<property name="text">
<string>Capture cursor</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="hideToTray">
<property name="text">
<string>Pressing &lt;X&gt; hides to tray</string>
</property>
</widget>
</item>
<item row="7" column="1" rowspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Recording format</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
@ -127,7 +146,7 @@
<x>0</x>
<y>0</y>
<width>512</width>
<height>24</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">

View File

@ -8,6 +8,7 @@
#include <screenshotutil.hpp>
#include <settings.hpp>
#include <stdio.h>
#include <uploaders/uploadersingleton.hpp>
#include <worker/worker.hpp>
RecordingController::RecordingController() : timer(this) {
@ -33,7 +34,7 @@ bool RecordingController::end() {
area = QRect();
preview->close();
preview = 0;
_context->finalizer();
UploaderSingleton::inst().upload(_context->finalizer());
frame = 0;
time = 0;
return true;

View File

@ -3,6 +3,7 @@
#include "recordingpreview.hpp"
#include <QFile>
#include <QImage>
#include <QRect>
#include <QTimer>
@ -13,7 +14,7 @@ class RecordingContext {
public:
QImage::Format format;
std::function<void(QImage)> consumer;
std::function<void()> finalizer;
std::function<QFile()> finalizer;
};
class RecordingController : public QObject {

View File

@ -0,0 +1,35 @@
#include "recordingformats.hpp"
#include <QFile>
RecordingFormats::RecordingFormats(RecordingFormats::Format f) {
switch (f) {
case GIF:
// TODO
break;
default:
break;
}
}
std::function<void(QImage)> RecordingFormats::getConsumer() {
return consumer;
}
std::function<QFile()> RecordingFormats::getFinalizer() {
return finalizer;
}
QString RecordingFormats::getPrettyName(RecordingFormats::Format f) {
switch (f) {
case None:
return "None";
break;
case GIF:
return "gif";
break;
default:
return QString();
break;
}
}

View File

@ -0,0 +1,23 @@
#ifndef RECORDINGFORMATS_HPP
#define RECORDINGFORMATS_HPP
#include <QFile>
#include <QImage>
#include <QString>
#include <functional>
class RecordingFormats {
public:
enum Format { None, GIF };
RecordingFormats(Format f);
std::function<void(QImage)> getConsumer();
std::function<QByteArray()> getFinalizer();
static QString getPrettyName(Format f);
private:
std::function<void(QImage)> consumer;
std::function<QByteArray()> finalizer;
};
#endif // RECORDINGFORMATS_HPP

View File

@ -64,11 +64,11 @@ CustomUploader::CustomUploader(QString absFilePath) {
if (formatValue.isString()) {
QString formatString = formatValue.toString().toLower();
if (formatString == "x-www-form-urlencoded")
format = RequestFormat::X_WWW_FORM_URLENCODED;
rFormat = RequestFormat::X_WWW_FORM_URLENCODED;
else if (formatString == "json")
format = RequestFormat::JSON;
rFormat = RequestFormat::JSON;
else if (formatString == "plain")
format = RequestFormat::PLAIN;
rFormat = RequestFormat::PLAIN;
else
error(absFilePath, "format invalid");
}
@ -85,7 +85,7 @@ CustomUploader::CustomUploader(QString absFilePath) {
} else
error(absFilePath, "imageformat invalid");
QJsonValue bodyValue = obj["body"];
if (format != RequestFormat::PLAIN) {
if (rFormat != RequestFormat::PLAIN) {
if (bodyValue.isUndefined()) error(absFilePath, "body not set");
if (bodyValue.isObject())
body = bodyValue;
@ -123,6 +123,10 @@ QString CustomUploader::description() {
return desc;
}
std::tuple<QString, QString> CustomUploader::format() {
return std::tuple<QString, QString>(getFormatString(false), getFormatString(true));
}
QString getCType(RequestFormat format, QString plainType) {
switch (format) {
case RequestFormat::X_WWW_FORM_URLENCODED:
@ -149,14 +153,6 @@ QList<QPair<QString, QString>> getHeaders(QJsonObject h, QString imageFormat, QM
return headers;
}
QByteArray imageBytes(QPixmap *pixmap, QString format) {
QByteArray returnVal;
QBuffer buff(&returnVal);
buff.open(QIODevice::WriteOnly);
pixmap->save(&buff, format.toUpper().toLocal8Bit().constData());
return returnVal;
}
QString CustomUploader::getFormatString(bool animated) {
if (iFormat == "base64")
return animated ? "GIF" : "PNG";
@ -238,13 +234,12 @@ void parseResult(QJsonDocument result, QByteArray data, QString returnPathspec,
}
}
void CustomUploader::doUpload(QPixmap *pixmap) {
auto h = getHeaders(headers, getFormatString(false), types, this->format);
void CustomUploader::doUpload(QByteArray imgData) {
auto h = getHeaders(headers, getFormatString(false), types, this->rFormat);
QString format = getFormatString(false); // Soon:tm:
QByteArray data;
QByteArray imgData = imageBytes(pixmap, format);
if (iFormat == "base64" || QRegExp("base64\\([^+]\\+[^+]\\)").exactMatch(iFormat)) imgData = imgData.toBase64();
switch (this->format) {
switch (this->rFormat) {
case RequestFormat::PLAIN: {
data = imgData;
} break;

View File

@ -11,19 +11,20 @@ enum class HttpMethod { POST };
enum class RequestFormat { X_WWW_FORM_URLENCODED, JSON, PLAIN };
class CustomUploader : public Uploader {
public:
public:
CustomUploader(QString absFilePath);
QString name();
QString description();
void doUpload(QPixmap *pixmap);
std::tuple<QString, QString> format();
void doUpload(QByteArray imgData);
QString getFormatString(bool animated);
QMap<QString, QString> types;
private:
private:
double limit = -1;
QString desc;
QString uName;
RequestFormat format = RequestFormat::JSON;
RequestFormat rFormat = RequestFormat::JSON;
HttpMethod method = HttpMethod::POST;
QUrl target;
QJsonValue body;

View File

@ -4,7 +4,7 @@
#include <QClipboard>
#include <notifications.hpp>
void ClipboardUploader::doUpload(QPixmap *pixmap) {
QApplication::clipboard()->setImage(pixmap->toImage());
void ClipboardUploader::doUpload(QByteArray imgData) {
QApplication::clipboard()->setImage(QImage::fromData(imgData, std::get<0>(format()).toLocal8Bit().constData()));
notifications::notify("KShare", "Copied to clipboard!");
}

View File

@ -5,14 +5,18 @@
#include <uploaders/uploader.hpp>
class ClipboardUploader : public Uploader {
public:
public:
QString name() {
return "clipboard";
}
QString description() {
return "Copies the image to clipboard";
}
void doUpload(QPixmap *pixmap);
std::tuple<QString, QString> format() {
return std::tuple<QString, QString>("PNG", "MP4");
}
void doUpload(QByteArray imgData);
};
#endif // CLIPBOARDUPLOADER_HPP

View File

@ -7,20 +7,19 @@
#include <notifications.hpp>
#include <screenshotutil.hpp>
void ImgurUploader::doUpload(QPixmap *pixmap) {
QByteArray byteArray;
QBuffer buffer(&byteArray);
pixmap->save(&buffer, "PNG");
if (buffer.size() > 1e+7) {
void ImgurUploader::doUpload(QByteArray byteArray) {
if (byteArray.size() > 1e+7) {
notifications::notify("KShare imgur Uploader ", "Failed upload! Image too big");
return;
}
ioutils::postJson(QUrl("https://api.imgur.com/3/image"),
QList<QPair<QString, QString>>() << QPair<QString, QString>("Content-Type", "application/x-www-form-urlencoded")
<< QPair<QString, QString>("Authorization", "Client-ID 8a98f183fc895da"),
QList<QPair<QString, QString>>()
<< QPair<QString, QString>("Content-Type", "application/x-www-form-urlencoded")
<< QPair<QString, QString>("Authorization", "Client-ID 8a98f183fc895da"),
byteArray, [](QJsonDocument res, QByteArray, QNetworkReply *) {
QString result = res.object()["data"].toObject()["link"].toString();
screenshotutil::toClipboard(result);
notifications::notify("KShare imgur Uploader ", result.isEmpty() ? "Failed upload!" : "Uploaded to imgur!");
notifications::notify("KShare imgur Uploader ",
result.isEmpty() ? "Failed upload!" : "Uploaded to imgur!");
});
}

View File

@ -4,14 +4,17 @@
#include "../uploader.hpp"
class ImgurUploader : public Uploader {
public:
public:
QString name() {
return "imgur";
}
QString description() {
return "imgur.com uploader";
}
void doUpload(QPixmap *pixmap);
std::tuple<QString, QString> format() {
return std::tuple<QString, QString>("PNG", "MP4");
}
void doUpload(QByteArray byteArray);
};
#endif // IMGURUPLOADER_HPP

View File

@ -5,10 +5,11 @@
#include <QString>
class Uploader {
public:
virtual void doUpload(QPixmap *pixmap) = 0;
public:
virtual void doUpload(QByteArray imgData) = 0;
virtual QString name() = 0;
virtual QString description() = 0;
virtual std::tuple<QString, QString> format() = 0;
};
#endif // UPLOADER_HPP

View File

@ -2,13 +2,15 @@
#include "customuploader.hpp"
#include "default/clipboarduploader.hpp"
#include "default/imguruploader.hpp"
#include <QBuffer>
#include <QDebug>
#include <QDir>
#include <QStandardPaths>
#include <formatter.hpp>
#include <settings.hpp>
UploaderSingleton::UploaderSingleton() : QObject(), saveDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)) {
UploaderSingleton::UploaderSingleton()
: QObject(), saveDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)) {
if (QStandardPaths::writableLocation(QStandardPaths::PicturesLocation).isEmpty()) {
qFatal("Cannot determine location for pictures");
}
@ -54,16 +56,30 @@ void UploaderSingleton::registerUploader(Uploader *uploader) {
}
void UploaderSingleton::upload(QPixmap *pixmap) {
if (settings::settings().contains("fileFormat")) {
QString format = settings::settings().value("fileFormat").toString();
if (!format.isEmpty()) {
pixmap->save(saveDir.absoluteFilePath(formatter::format(format) + ".png"), "PNG");
}
}
uploaders.value(uploader)->doUpload(pixmap);
auto u = uploaders.value(uploader);
QByteArray arr;
QBuffer data(&arr);
pixmap->save(&data, std::get<0>(u->format()).toLocal8Bit().constData());
u->doUpload(arr);
data.close();
delete pixmap;
}
void UploaderSingleton::upload(QByteArray img) {
uploaders.value(uploader)->doUpload(img);
}
void UploaderSingleton::upload(QFile img) {
if (img.open(QIODevice::ReadOnly)) {
uploaders.value(uploader)->doUpload(img.readAll());
img.close();
}
}
std::tuple<QString, QString> UploaderSingleton::format() {
return uploaders.value(uploader)->format();
}
QList<Uploader *> UploaderSingleton::uploaderList() {
return uploaders.values();
}

View File

@ -7,21 +7,24 @@
class UploaderSingleton : public QObject {
Q_OBJECT
public:
public:
static UploaderSingleton &inst() {
static UploaderSingleton inst;
return inst;
}
void registerUploader(Uploader *uploader);
void upload(QPixmap *pixmap);
void upload(QByteArray img);
void upload(QFile img);
virtual std::tuple<QString, QString> format();
QList<Uploader *> uploaderList();
void set(QString uploader);
QString selectedUploader();
QList<std::runtime_error> errors();
signals:
signals:
void newUploader(Uploader *u);
private:
private:
QDir saveDir;
UploaderSingleton();
QMap<QString, Uploader *> uploaders;