Fix a memory leak with the crop editor

I did not properly handle deleting the editor so it would stay in memory permanently.
This commit is contained in:
ArsenArsen 2017-07-02 20:51:15 +02:00
parent 774aecaf21
commit d44aae4f43
16 changed files with 49 additions and 83 deletions

View File

@ -6,7 +6,7 @@
#include <QGraphicsTextItem> #include <QGraphicsTextItem>
#include <QTimer> #include <QTimer>
ColorPickerScene::ColorPickerScene(QPixmap *pixmap, QWidget *parentWidget) ColorPickerScene::ColorPickerScene(QPixmap pixmap, QWidget *parentWidget)
: QGraphicsScene(), QGraphicsView(this, parentWidget) { : QGraphicsScene(), QGraphicsView(this, parentWidget) {
setFrameShape(QFrame::NoFrame); // Time taken to solve: A george99g and 38 minutes. setFrameShape(QFrame::NoFrame); // Time taken to solve: A george99g and 38 minutes.
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -16,7 +16,7 @@ ColorPickerScene::ColorPickerScene(QPixmap *pixmap, QWidget *parentWidget)
setCursor(QCursor(Qt::CrossCursor)); setCursor(QCursor(Qt::CrossCursor));
setMouseTracking(true); setMouseTracking(true);
pItem = addPixmap(*pixmap); pItem = addPixmap(pixmap);
pItem->setZValue(-2); pItem->setZValue(-2);
ellipse = addEllipse(QRectF(QCursor::pos(), QSize(20, 20)), QPen(Qt::cyan), Qt::NoBrush); ellipse = addEllipse(QRectF(QCursor::pos(), QSize(20, 20)), QPen(Qt::cyan), Qt::NoBrush);
QFont font("Monospace"); QFont font("Monospace");

View File

@ -12,7 +12,7 @@
class ColorPickerScene : public QGraphicsScene, public QGraphicsView { class ColorPickerScene : public QGraphicsScene, public QGraphicsView {
public: public:
ColorPickerScene(QPixmap *pixmap, QWidget *parentWidget); ColorPickerScene(QPixmap pixmap, QWidget *parentWidget);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override;

View File

@ -9,33 +9,31 @@
#include <QTimer> #include <QTimer>
#include <settings.hpp> #include <settings.hpp>
CropEditor::CropEditor(QPixmap *image, QObject *parent) : QObject(parent) { CropEditor::CropEditor(QPixmap image, QObject *parent) : QObject(parent) {
scene = new CropScene(parent, image); scene = new CropScene(parent, image);
view = new CropView(scene); view = new CropView(scene);
qreal ratio = QApplication::primaryScreen()->devicePixelRatio(); qreal ratio = QApplication::primaryScreen()->devicePixelRatio();
pixmapItem = new QGraphicsPixmapItem(*image); QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(image);
pixmapItem->setZValue(-1); pixmapItem->setZValue(-1);
pixmapItem->setScale(1 / ratio); pixmapItem->setScale(1 / ratio);
scene->addItem(pixmapItem); scene->addItem(pixmapItem);
scene->setSceneRect(image->rect()); scene->setSceneRect(image.rect());
view->resize(image->width(), image->height()); view->resize(image.width(), image.height());
view->setMinimumSize(image->size()); view->setMinimumSize(image.size());
view->move(0, 0); view->move(0, 0);
view->setWindowTitle("KShare Crop Editor"); view->setWindowTitle("KShare Crop Editor");
view->show(); view->show();
connect(scene, &CropScene::closedWithRect, this, &CropEditor::crop); connect(scene, &CropScene::closedWithRect, this, &CropEditor::crop);
} }
CropEditor::~CropEditor() { CropEditor::~CropEditor() {
delete scene; scene->deleteLater();
delete view; view->deleteLater();
} }
void CropEditor::crop(QRect rect) { void CropEditor::crop(QRect rect) {
QPixmap map = view->grab(rect); if (rect.isValid()) emit cropped(view->grab(rect));
QPixmap *cropp = new QPixmap; deleteLater();
map.swap(*cropp);
delete view;
emit cropped(cropp);
} }

View File

@ -11,16 +11,15 @@
class CropEditor : public QObject { class CropEditor : public QObject {
Q_OBJECT Q_OBJECT
public: public:
CropEditor(QPixmap *image, QObject *parent = 0); CropEditor(QPixmap image, QObject *parent = 0);
~CropEditor(); ~CropEditor();
signals: signals:
QPixmap *cropped(QPixmap *pixmap); QPixmap *cropped(QPixmap pixmap);
private: private:
void crop(QRect rect); void crop(QRect rect);
CropScene *scene = nullptr; CropScene *scene = nullptr;
CropView *view = nullptr; CropView *view = nullptr;
QGraphicsPixmapItem *pixmapItem = nullptr;
}; };
#endif // CROPEDITOR_HPP #endif // CROPEDITOR_HPP

View File

@ -20,7 +20,7 @@
#include <functional> #include <functional>
#include <settings.hpp> #include <settings.hpp>
CropScene::CropScene(QObject *parent, QPixmap *pixmap) CropScene::CropScene(QObject *parent, QPixmap pixmap)
: QGraphicsScene(parent), drawingSelectionMaker([] { return nullptr; }), prevButtons(Qt::NoButton), : QGraphicsScene(parent), drawingSelectionMaker([] { return nullptr; }), prevButtons(Qt::NoButton),
_brush(Qt::SolidPattern), _font(settings::settings().value("font", QFont()).value<QFont>()) { _brush(Qt::SolidPattern), _font(settings::settings().value("font", QFont()).value<QFont>()) {
_pixmap = pixmap; _pixmap = pixmap;
@ -65,7 +65,7 @@ CropScene::CropScene(QObject *parent, QPixmap *pixmap)
}); });
menu.addAction(settings); menu.addAction(settings);
magnifier = addPixmap(pixmap->copy(0, 0, 11, 11).scaled(110, 110)); magnifier = addPixmap(pixmap.copy(0, 0, 11, 11).scaled(110, 110));
magnifierBox = addRect(magnifier->boundingRect(), QPen(Qt::cyan)); magnifierBox = addRect(magnifier->boundingRect(), QPen(Qt::cyan));
magnifier->setZValue(1); magnifier->setZValue(1);
magnifierBox->setZValue(1.1); magnifierBox->setZValue(1.1);
@ -257,7 +257,7 @@ void CropScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *e) {
} }
void CropScene::keyReleaseEvent(QKeyEvent *event) { void CropScene::keyReleaseEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) done(); // Segfault if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter || event->key() == Qt::Key_Escape) done();
} }
void CropScene::updateMag(QPointF scenePos) { void CropScene::updateMag(QPointF scenePos) {
@ -275,7 +275,7 @@ void CropScene::updateMag(QPointF scenePos) {
QPointF magnifierPos = scenePos + QPointF(5, 5); QPointF magnifierPos = scenePos + QPointF(5, 5);
magnifier->setPos(magnifierPos); magnifier->setPos(magnifierPos);
magnifier->setPixmap(_pixmap->copy(magnifierTopLeft.x(), magnifierTopLeft.y(), pixCnt, pixCnt).scaled(110, 110)); magnifier->setPixmap(_pixmap.copy(magnifierTopLeft.x(), magnifierTopLeft.y(), pixCnt, pixCnt).scaled(110, 110));
QPointF bottomRight = magnifierHintBox->sceneBoundingRect().bottomRight(); QPointF bottomRight = magnifierHintBox->sceneBoundingRect().bottomRight();
if (magnifier->sceneBoundingRect().bottom() > bottomRight.y()) if (magnifier->sceneBoundingRect().bottom() > bottomRight.y())
bottomRight.setY(magnifier->sceneBoundingRect().bottom()); bottomRight.setY(magnifier->sceneBoundingRect().bottom());
@ -319,5 +319,6 @@ void CropScene::done() {
magnifierHint->setVisible(false); magnifierHint->setVisible(false);
magnifierHintBox->setVisible(false); magnifierHintBox->setVisible(false);
emit closedWithRect(rect->rect().toRect()); emit closedWithRect(rect->rect().toRect());
} } else
emit closedWithRect(QRect());
} }

View File

@ -16,13 +16,13 @@ class CropScene;
class CropScene : public QGraphicsScene { class CropScene : public QGraphicsScene {
Q_OBJECT Q_OBJECT
public: public:
CropScene(QObject *parent, QPixmap *pixmap); CropScene(QObject *parent, QPixmap pixmap);
~CropScene(); ~CropScene();
QPen &pen(); QPen &pen();
QBrush &brush(); QBrush &brush();
QFont &font(); QFont &font();
void setDrawingSelection(QString name, std::function<DrawItem *()> drawAction); void setDrawingSelection(QString name, std::function<DrawItem *()> drawAction);
QPixmap *pixmap() { QPixmap pixmap() {
return _pixmap; return _pixmap;
} }
QGraphicsPolygonItem *polyItm() { QGraphicsPolygonItem *polyItm() {
@ -58,7 +58,7 @@ private:
bool fullscreen; bool fullscreen;
std::function<DrawItem *()> drawingSelectionMaker; std::function<DrawItem *()> drawingSelectionMaker;
QFlags<Qt::MouseButton> prevButtons; QFlags<Qt::MouseButton> prevButtons;
QPixmap *_pixmap; QPixmap _pixmap;
QGraphicsRectItem *rect = nullptr; QGraphicsRectItem *rect = nullptr;
QGraphicsPixmapItem *magnifier = nullptr; QGraphicsPixmapItem *magnifier = nullptr;
QGraphicsRectItem *magnifierBox = nullptr; QGraphicsRectItem *magnifierBox = nullptr;

View File

@ -10,12 +10,3 @@ CropView::CropView(QGraphicsScene *scene) : QGraphicsView(scene) {
setMouseTracking(true); setMouseTracking(true);
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
} }
void CropView::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Escape) {
close();
e->accept();
return;
}
QGraphicsView::keyPressEvent(e);
}

View File

@ -7,9 +7,6 @@
class CropView : public QGraphicsView { class CropView : public QGraphicsView {
public: public:
CropView(QGraphicsScene *scene); CropView(QGraphicsScene *scene);
protected:
void keyPressEvent(QKeyEvent *e) override;
}; };
#endif // CROPVIEW_HPP #endif // CROPVIEW_HPP

View File

@ -17,14 +17,14 @@ void BlurItem::mouseDragEvent(QGraphicsSceneMouseEvent *e, CropScene *scene) {
if (pos.isNull()) { if (pos.isNull()) {
pos = e->scenePos(); pos = e->scenePos();
rect = scene->addRect(QRect(e->scenePos().toPoint(), QSize(1, 1)), QPen(Qt::cyan), Qt::NoBrush); rect = scene->addRect(QRect(e->scenePos().toPoint(), QSize(1, 1)), QPen(Qt::cyan), Qt::NoBrush);
pixmap = scene->addPixmap(scene->pixmap()->copy(rect->rect().toRect())); pixmap = scene->addPixmap(scene->pixmap().copy(rect->rect().toRect()));
pixmap->setPos(e->scenePos()); pixmap->setPos(e->scenePos());
pixmap->setZValue(rect->zValue() - 0.1); pixmap->setZValue(rect->zValue() - 0.1);
pixmap->setGraphicsEffect(effect); pixmap->setGraphicsEffect(effect);
} else { } else {
QPointF p = e->scenePos(); QPointF p = e->scenePos();
rect->setRect(QRect(qMin(pos.x(), p.x()), qMin(pos.y(), p.y()), qAbs(pos.x() - p.x()), qAbs(pos.y() - p.y()))); rect->setRect(QRect(qMin(pos.x(), p.x()), qMin(pos.y(), p.y()), qAbs(pos.x() - p.x()), qAbs(pos.y() - p.y())));
pixmap->setPixmap(scene->pixmap()->copy(rect->rect().toRect())); pixmap->setPixmap(scene->pixmap().copy(rect->rect().toRect()));
pixmap->setPos(rect->rect().topLeft()); pixmap->setPos(rect->rect().topLeft());
} }
} }

View File

@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
Worker::init(); Worker::init();
a.connect(&a, &QApplication::aboutToQuit, Worker::end); a.connect(&a, &QApplication::aboutToQuit, Worker::end);
a.connect(&a, &QApplication::aboutToQuit, [] { stillAlive = false; }); a.connect(&a, &QApplication::aboutToQuit, [] { stillAlive = false; });
screenshotutil::fullscreen()->save("/home/arsen/test.png", "PNG");
if (!parser.isSet(h)) w.show(); if (!parser.isSet(h)) w.show();
return a.exec(); return a.exec();
} }

View File

@ -78,15 +78,14 @@ void RecordingController::timeout() {
time++; time++;
int localTime = time * timer.interval() - 3000; int localTime = time * timer.interval() - 3000;
if (localTime > 0) { if (localTime > 0) {
QPixmap *pp = screenshotutil::fullscreenArea(settings::settings().value("captureCursor", true).toBool(), QPixmap pp = screenshotutil::fullscreenArea(settings::settings().value("captureCursor", true).toBool(),
area.x(), area.y(), area.width(), area.height()); area.x(), area.y(), area.width(), area.height());
QScopedPointer<QPixmap> p(pp);
WorkerContext *context = new WorkerContext; WorkerContext *context = new WorkerContext;
context->consumer = _context->consumer; context->consumer = _context->consumer;
context->targetFormat = _context->format; context->targetFormat = _context->format;
context->pixmap = *pp; context->pixmap = pp;
frame++; frame++;
preview->setPixmap(*pp); preview->setPixmap(pp);
Worker::queue(context); Worker::queue(context);
} }
long second = localTime / 1000 % 60; long second = localTime / 1000 % 60;

View File

@ -10,10 +10,7 @@
void screenshotter::area() { void screenshotter::area() {
CropEditor *editor = new CropEditor(screenshotutil::fullscreen(settings::settings().value("captureCursor", true).toBool())); 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);
});
} }
void screenshotter::fullscreen() { void screenshotter::fullscreen() {

View File

@ -7,55 +7,40 @@
#include <QScreen> #include <QScreen>
#include <platformbackend.hpp> #include <platformbackend.hpp>
QPixmap *screenshotutil::fullscreen(bool cursor) { QPixmap screenshotutil::fullscreen(bool cursor) {
int height = 0, width = 0; int height = 0, width = 0;
for (QScreen *screen : QApplication::screens()) { for (QScreen *screen : QApplication::screens()) {
width += screen->size().width(); width += screen->size().width();
int h = screen->size().height(); int h = screen->size().height();
height = h > height ? h : height; height = h > height ? h : height;
} }
QPixmap *image = new QPixmap(width, height); QPixmap image(width, height);
image->fill(Qt::transparent); image.fill(Qt::transparent);
QPainter painter(image); QPainter painter(&image);
width = 0; width = 0;
for (QScreen *screen : QApplication::screens()) { for (QScreen *screen : QApplication::screens()) {
QPixmap currentScreen = window(0, screen);
QPixmap *currentScreen = window(0, screen); painter.drawPixmap(width, 0, currentScreen);
painter.drawPixmap(width, 0, currentScreen->copy());
delete currentScreen;
width += screen->size().width(); width += screen->size().width();
} }
painter.end();
#ifdef PLATFORM_CAPABILITY_CURSOR #ifdef PLATFORM_CAPABILITY_CURSOR
if (cursor) { if (cursor) {
QPixmap *noCursor = image;
QScopedPointer<QPixmap> p(noCursor);
QPixmap *withCursor = new QPixmap(*noCursor);
QPainter painter(withCursor);
auto cursorData = PlatformBackend::inst().getCursor(); auto cursorData = PlatformBackend::inst().getCursor();
painter.drawPixmap(QCursor::pos() - std::get<0>(cursorData), std::get<1>(cursorData)); painter.drawPixmap(QCursor::pos() - std::get<0>(cursorData), std::get<1>(cursorData));
painter.end();
return withCursor;
} }
painter.end();
#endif #endif
return image; return image;
} }
QPixmap *screenshotutil::window(WId wid, QScreen *w) { QPixmap screenshotutil::window(WId wid, QScreen *w) {
QPixmap screen = w->grabWindow(wid); return w->grabWindow(wid);
QPixmap *pm = new QPixmap(screen.size());
screen.swap(*pm);
return pm;
} }
void screenshotutil::toClipboard(QString value) { void screenshotutil::toClipboard(QString value) {
QApplication::clipboard()->setText(value); QApplication::clipboard()->setText(value);
} }
QPixmap *screenshotutil::fullscreenArea(bool cursor, qreal x, qreal y, qreal w, qreal h) { QPixmap screenshotutil::fullscreenArea(bool cursor, qreal x, qreal y, qreal w, qreal h) {
QPixmap *cropped = new QPixmap; return fullscreen(cursor).copy(x, y, w, h);
QPixmap *scr = fullscreen(cursor);
scr->copy(x, y, w, h).swap(*cropped);
delete scr;
return cropped;
} }

View File

@ -5,9 +5,9 @@
#include <QWidget> #include <QWidget>
namespace screenshotutil { namespace screenshotutil {
QPixmap *fullscreen(bool cursor = true); QPixmap fullscreen(bool cursor = true);
QPixmap *fullscreenArea(bool cursor = true, qreal x = 0, qreal y = 0, qreal w = -1, qreal h = -1); QPixmap fullscreenArea(bool cursor = true, qreal x = 0, qreal y = 0, qreal w = -1, qreal h = -1);
QPixmap *window(WId wid, QScreen *w = QApplication::primaryScreen()); QPixmap window(WId wid, QScreen *w = QApplication::primaryScreen());
void toClipboard(QString value); void toClipboard(QString value);
} }

View File

@ -59,7 +59,7 @@ void UploaderSingleton::registerUploader(Uploader *uploader) {
emit newUploader(uploader); emit newUploader(uploader);
} }
void UploaderSingleton::upload(QPixmap *pixmap) { void UploaderSingleton::upload(QPixmap pixmap) {
auto u = uploaders.value(uploader); auto u = uploaders.value(uploader);
if (!u->validate()) { if (!u->validate()) {
u = uploaders.value("imgur"); u = uploaders.value("imgur");
@ -72,12 +72,11 @@ void UploaderSingleton::upload(QPixmap *pixmap) {
format.toLower()))); format.toLower())));
if (file.open(QFile::ReadWrite)) { if (file.open(QFile::ReadWrite)) {
pixmap->save(&file, format.toLocal8Bit().constData(), settings::settings().value("imageQuality", -1).toInt()); pixmap.save(&file, format.toLocal8Bit().constData(), settings::settings().value("imageQuality", -1).toInt());
file.seek(0); file.seek(0);
u->doUpload(file.readAll(), format); u->doUpload(file.readAll(), format);
} else } else
notifications::notify("KShare - Failed to save picture", file.errorString(), QSystemTrayIcon::Warning); notifications::notify("KShare - Failed to save picture", file.errorString(), QSystemTrayIcon::Warning);
delete pixmap;
} }
void UploaderSingleton::upload(QByteArray img, QString format) { void UploaderSingleton::upload(QByteArray img, QString format) {

View File

@ -13,7 +13,7 @@ public:
return inst; return inst;
} }
void registerUploader(Uploader *uploader); void registerUploader(Uploader *uploader);
void upload(QPixmap *pixmap); void upload(QPixmap pixmap);
void upload(QByteArray img, QString format); void upload(QByteArray img, QString format);
void upload(QFile &img, QString format); void upload(QFile &img, QString format);
void showSettings(); void showSettings();