2017-11-23 20:33:49 +01:00
|
|
|
#include "utils.hpp"
|
2017-04-23 15:05:48 +02:00
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QClipboard>
|
2017-05-13 23:33:36 +02:00
|
|
|
#include <QPainter>
|
2017-04-23 15:05:48 +02:00
|
|
|
#include <QPixmap>
|
2017-12-17 19:59:16 +01:00
|
|
|
#include <QProcess>
|
2017-04-23 15:05:48 +02:00
|
|
|
#include <QScreen>
|
2018-01-01 16:37:31 +01:00
|
|
|
#include <logger.hpp>
|
2017-05-13 23:33:36 +02:00
|
|
|
#include <platformbackend.hpp>
|
2017-12-17 19:59:16 +01:00
|
|
|
#include <settings.hpp>
|
2017-11-23 20:33:49 +01:00
|
|
|
|
|
|
|
QColor utils::invertColor(QColor color) {
|
|
|
|
return QColor(255 - color.red(), 255 - color.green(), 255 - color.blue());
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap utils::extend(QPixmap img, int extraSize, QColor hl) {
|
|
|
|
QPixmap newImg(img.width() + extraSize * 2, img.height() + extraSize * 2);
|
|
|
|
newImg.fill(hl);
|
|
|
|
QPainter ptr(&newImg);
|
|
|
|
ptr.drawPixmap(extraSize, extraSize, img);
|
|
|
|
ptr.end();
|
|
|
|
return newImg;
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap utils::fullscreen(bool cursor) {
|
2017-07-03 16:14:19 +02:00
|
|
|
QPixmap image;
|
2017-07-03 16:18:56 +02:00
|
|
|
QPainter painter;
|
2017-07-05 16:41:53 +02:00
|
|
|
QPoint smallestCoordinate = smallestScreenCoordinate();
|
2017-07-03 16:14:19 +02:00
|
|
|
|
2017-07-05 16:41:53 +02:00
|
|
|
// Hack for https://bugreports.qt.io/browse/QTBUG-58110
|
2017-07-03 16:25:54 +02:00
|
|
|
#ifdef Q_OS_LINUX
|
2017-07-05 16:41:53 +02:00
|
|
|
static QStringList qVer = QString(qVersion()).split('.');
|
2017-07-03 16:14:19 +02:00
|
|
|
if (qVer.at(0).toInt() == 5 && qVer.at(1).toInt() < 9) {
|
2017-07-03 16:23:44 +02:00
|
|
|
image = window(0);
|
|
|
|
painter.begin(&image);
|
|
|
|
} else {
|
2017-07-03 16:25:54 +02:00
|
|
|
#endif
|
2017-07-05 16:51:02 +02:00
|
|
|
int height = 0, width = 0;
|
|
|
|
int ox = smallestCoordinate.x() * -1, oy = smallestCoordinate.y() * -1;
|
2017-07-03 16:14:19 +02:00
|
|
|
for (QScreen *screen : QApplication::screens()) {
|
|
|
|
QRect geo = screen->geometry();
|
2017-07-05 16:51:02 +02:00
|
|
|
width = qMax(ox + geo.left() + geo.width(), width);
|
2017-07-09 14:23:52 +02:00
|
|
|
height = qMax(oy + geo.top() + geo.height(), height);
|
2017-07-03 16:14:19 +02:00
|
|
|
}
|
|
|
|
image = QPixmap(width, height);
|
|
|
|
image.fill(Qt::transparent);
|
|
|
|
width = 0;
|
2017-07-03 16:18:56 +02:00
|
|
|
painter.begin(&image);
|
2017-07-05 16:51:02 +02:00
|
|
|
painter.translate(ox, oy);
|
2017-07-03 16:14:19 +02:00
|
|
|
|
|
|
|
for (QScreen *screen : QApplication::screens()) {
|
|
|
|
QPixmap currentScreen = window(0, screen);
|
2017-07-09 14:23:52 +02:00
|
|
|
QRect geo = screen->geometry();
|
|
|
|
painter.drawPixmap(geo.left(), geo.top(), geo.width(), geo.height(), currentScreen);
|
2017-07-03 16:14:19 +02:00
|
|
|
width += screen->size().width();
|
|
|
|
}
|
2017-07-03 16:25:54 +02:00
|
|
|
#ifdef Q_OS_LINUX
|
2017-07-03 16:18:56 +02:00
|
|
|
}
|
2017-07-03 16:25:54 +02:00
|
|
|
#endif
|
|
|
|
|
2017-06-27 11:33:11 +02:00
|
|
|
#ifdef PLATFORM_CAPABILITY_CURSOR
|
2017-05-15 14:10:00 +02:00
|
|
|
if (cursor) {
|
|
|
|
auto cursorData = PlatformBackend::inst().getCursor();
|
|
|
|
painter.drawPixmap(QCursor::pos() - std::get<0>(cursorData), std::get<1>(cursorData));
|
|
|
|
}
|
2017-06-27 11:33:11 +02:00
|
|
|
#endif
|
2017-07-03 15:43:28 +02:00
|
|
|
painter.end();
|
2017-07-01 17:24:03 +02:00
|
|
|
return image;
|
2017-05-09 17:26:00 +02:00
|
|
|
}
|
2017-04-23 15:05:48 +02:00
|
|
|
|
2017-11-23 20:33:49 +01:00
|
|
|
QPixmap utils::window(WId wid, QScreen *w) {
|
2017-07-02 20:51:15 +02:00
|
|
|
return w->grabWindow(wid);
|
2017-04-23 15:05:48 +02:00
|
|
|
}
|
|
|
|
|
2017-11-23 20:33:49 +01:00
|
|
|
void utils::toClipboard(QString value) {
|
2017-05-09 17:26:00 +02:00
|
|
|
QApplication::clipboard()->setText(value);
|
2017-04-23 15:05:48 +02:00
|
|
|
}
|
2017-05-19 22:32:23 +02:00
|
|
|
|
2017-11-23 20:33:49 +01:00
|
|
|
QPixmap utils::fullscreenArea(bool cursor, qreal x, qreal y, qreal w, qreal h) {
|
2017-07-02 20:51:15 +02:00
|
|
|
return fullscreen(cursor).copy(x, y, w, h);
|
2017-05-19 22:32:23 +02:00
|
|
|
}
|
2017-07-05 16:41:53 +02:00
|
|
|
|
2017-11-23 20:33:49 +01:00
|
|
|
QPoint utils::smallestScreenCoordinate() {
|
2017-07-05 16:41:53 +02:00
|
|
|
QPoint smallestCoordinate;
|
|
|
|
for (QScreen *screen : QApplication::screens()) {
|
|
|
|
smallestCoordinate.rx() = qMin(smallestCoordinate.x(), screen->geometry().left());
|
|
|
|
smallestCoordinate.ry() = qMin(smallestCoordinate.y(), screen->geometry().top());
|
|
|
|
}
|
|
|
|
return smallestCoordinate;
|
|
|
|
}
|
2017-07-09 14:23:52 +02:00
|
|
|
|
2017-11-23 20:33:49 +01:00
|
|
|
QPixmap utils::renderText(QString toRender, int padding, QColor background, QColor pen, QFont font) {
|
2017-07-09 21:04:21 +02:00
|
|
|
QFontMetrics metric(font);
|
|
|
|
QStringList lines = toRender.replace("\r", "").split('\n');
|
|
|
|
QSize resultingSize(0, padding * 2);
|
|
|
|
int lineSpace = metric.leading();
|
|
|
|
for (QString line : lines) {
|
|
|
|
QRect br = metric.boundingRect(line);
|
|
|
|
resultingSize.rheight() += lineSpace + br.height();
|
|
|
|
resultingSize.rwidth() = qMax(br.width(), resultingSize.width());
|
|
|
|
}
|
|
|
|
resultingSize.rwidth() += padding * 2;
|
|
|
|
QPixmap renderred(resultingSize);
|
|
|
|
renderred.fill(background);
|
|
|
|
QPainter painter(&renderred);
|
|
|
|
painter.setPen(pen);
|
|
|
|
int y = padding;
|
|
|
|
for (QString line : lines) {
|
|
|
|
QRect br = metric.boundingRect(line);
|
|
|
|
painter.drawText(padding, y, br.width(), br.height(), 0, line);
|
|
|
|
y += lineSpace + br.height();
|
|
|
|
}
|
|
|
|
painter.end();
|
|
|
|
return renderred;
|
2017-07-09 14:23:52 +02:00
|
|
|
}
|
2017-12-17 19:59:16 +01:00
|
|
|
|
|
|
|
QString utils::randomString(int length) {
|
|
|
|
QString str;
|
|
|
|
str.resize(length);
|
|
|
|
for (int s = 0; s < length; s++) str[s] = QChar('A' + char(qrand() % ('Z' - 'A')));
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
void utils::externalScreenshot(std::function<void(QPixmap)> callback) {
|
|
|
|
QString cmd = settings::settings().value("command/fullscreenCommand", "").toString();
|
|
|
|
QStringList args = cmd.split(' ');
|
|
|
|
QString tempPath;
|
|
|
|
for (QString &arg : args) {
|
|
|
|
if (arg == "%FILE_PATH") {
|
|
|
|
if (tempPath.isEmpty()) tempPath = "KShare-Ext-Screenshot." + randomString(5);
|
|
|
|
arg = tempPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QProcess *process = new QProcess;
|
|
|
|
QObject::connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
|
|
[callback, process, tempPath](int code, QProcess::ExitStatus) {
|
|
|
|
if (code != 0) {
|
2018-02-18 02:35:29 +01:00
|
|
|
logger::fatal(QObject::tr("Failed to take external screenshot: \n") + process->readAllStandardError());
|
2017-12-17 20:37:56 +01:00
|
|
|
} else {
|
|
|
|
QPixmap pixmap;
|
|
|
|
if (!tempPath.isEmpty())
|
|
|
|
pixmap.load(tempPath);
|
|
|
|
else
|
|
|
|
pixmap.loadFromData(process->readAllStandardOutput());
|
|
|
|
callback(pixmap);
|
2017-12-17 19:59:16 +01:00
|
|
|
}
|
2017-12-21 20:08:56 +01:00
|
|
|
if (!tempPath.isEmpty()) QFile(tempPath).remove();
|
2017-12-17 19:59:16 +01:00
|
|
|
});
|
2017-12-20 01:19:07 +01:00
|
|
|
QObject::connect(process, &QProcess::errorOccurred, [](QProcess::ProcessError err) {
|
|
|
|
if (err == QProcess::FailedToStart) settings::settings().remove("command/fullscreenCommand");
|
|
|
|
});
|
2017-12-17 19:59:16 +01:00
|
|
|
process->start(args.takeFirst(), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
void utils::externalScreenshotActive(std::function<void(QPixmap)> callback) {
|
|
|
|
QString cmd = settings::settings().value("command/activeCommand", "").toString();
|
|
|
|
QStringList args = cmd.split(' ');
|
|
|
|
QString tempPath;
|
|
|
|
for (QString &arg : args) {
|
|
|
|
if (arg == "%FILE_PATH") {
|
|
|
|
if (tempPath.isEmpty()) tempPath = "KShare-Ext-Screenshot." + randomString(5);
|
|
|
|
arg = tempPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QProcess *process = new QProcess;
|
|
|
|
QObject::connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
|
|
[callback, process, tempPath](int code, QProcess::ExitStatus) {
|
|
|
|
if (code != 0) {
|
2018-02-18 02:35:29 +01:00
|
|
|
logger::fatal(QObject::tr("Failed to take external screenshot: \n") + process->readAllStandardError());
|
2017-12-17 20:37:56 +01:00
|
|
|
} else {
|
|
|
|
QPixmap pixmap;
|
|
|
|
if (!tempPath.isEmpty())
|
|
|
|
pixmap.load(tempPath);
|
|
|
|
else
|
|
|
|
pixmap.loadFromData(process->readAllStandardOutput());
|
|
|
|
callback(pixmap);
|
2017-12-17 19:59:16 +01:00
|
|
|
}
|
2017-12-21 20:08:56 +01:00
|
|
|
if (!tempPath.isEmpty()) QFile(tempPath).remove();
|
2017-12-17 19:59:16 +01:00
|
|
|
});
|
2017-12-20 01:19:07 +01:00
|
|
|
QObject::connect(process, &QProcess::errorOccurred, [](QProcess::ProcessError err) {
|
|
|
|
if (err == QProcess::FailedToStart) settings::settings().remove("command/activeCommand");
|
|
|
|
});
|
2017-12-17 19:59:16 +01:00
|
|
|
process->start(args.takeFirst(), args);
|
|
|
|
}
|
2018-05-09 20:40:57 +02:00
|
|
|
|
|
|
|
QIcon defaultIcon() {
|
|
|
|
static QIcon icon = QIcon(":/icons/icon.png");
|
|
|
|
return icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
QIcon infinity() {
|
|
|
|
static QIcon icon = QIcon(":/icons/infinity.png");
|
|
|
|
return icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
QIcon utils::getTrayIcon(int num) {
|
|
|
|
if (!num) {
|
|
|
|
return defaultIcon();
|
|
|
|
} else if (num < 100) {
|
|
|
|
QPixmap unscaled = utils::renderText(QString::number(num), 0, Qt::lightGray, Qt::black);
|
|
|
|
int dim = qMax(unscaled.width(), unscaled.height());
|
|
|
|
QPixmap scaled(dim, dim);
|
|
|
|
scaled.fill(Qt::lightGray);
|
|
|
|
QPainter *painter = new QPainter(&scaled);
|
|
|
|
painter->drawPixmap((dim / 2) - (unscaled.width() / 2), 0, unscaled);
|
|
|
|
delete painter;
|
|
|
|
return scaled;
|
|
|
|
} else {
|
|
|
|
return infinity();
|
|
|
|
}
|
|
|
|
}
|