Changed clang format to new agreement

This commit is contained in:
Jeremy Borgman
2020-09-23 20:39:30 -05:00
committed by borgmanJeremy
parent 2cbccc3d0a
commit 0d5386edd4
167 changed files with 8567 additions and 9081 deletions

View File

@@ -1,2 +1,6 @@
Language: Cpp Language: Cpp
BasedOnStyle: Mozilla BasedOnStyle: Mozilla
IndentWidth: 4
AccessModifierOffset: -4
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None

View File

@@ -14,4 +14,4 @@ jobs:
#exclude: './third_party ./external' #exclude: './third_party ./external'
extensions: 'h,cpp' extensions: 'h,cpp'
clangFormatVersion: 11 clangFormatVersion: 11
style: mozilla style: file

View File

@@ -24,59 +24,57 @@
namespace color_widgets { namespace color_widgets {
namespace detail { namespace detail {
QColor QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha)
color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha)
{ {
qreal h1 = hue * 6; qreal h1 = hue * 6;
qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1)); qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1));
QColor col; QColor col;
if (h1 >= 0 && h1 < 1) if (h1 >= 0 && h1 < 1)
col = QColor::fromRgbF(chroma, x, 0); col = QColor::fromRgbF(chroma, x, 0);
else if (h1 < 2) else if (h1 < 2)
col = QColor::fromRgbF(x, chroma, 0); col = QColor::fromRgbF(x, chroma, 0);
else if (h1 < 3) else if (h1 < 3)
col = QColor::fromRgbF(0, chroma, x); col = QColor::fromRgbF(0, chroma, x);
else if (h1 < 4) else if (h1 < 4)
col = QColor::fromRgbF(0, x, chroma); col = QColor::fromRgbF(0, x, chroma);
else if (h1 < 5) else if (h1 < 5)
col = QColor::fromRgbF(x, 0, chroma); col = QColor::fromRgbF(x, 0, chroma);
else if (h1 < 6) else if (h1 < 6)
col = QColor::fromRgbF(chroma, 0, x); col = QColor::fromRgbF(chroma, 0, x);
qreal m = luma - color_lumaF(col); qreal m = luma - color_lumaF(col);
return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0), return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0),
qBound(0.0, col.greenF() + m, 1.0), qBound(0.0, col.greenF() + m, 1.0),
qBound(0.0, col.blueF() + m, 1.0), qBound(0.0, col.blueF() + m, 1.0),
alpha); alpha);
} }
QColor QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha)
color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha)
{ {
qreal chroma = (1 - qAbs(2 * lig - 1)) * sat; qreal chroma = (1 - qAbs(2 * lig - 1)) * sat;
qreal h1 = hue * 6; qreal h1 = hue * 6;
qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1)); qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1));
QColor col; QColor col;
if (h1 >= 0 && h1 < 1) if (h1 >= 0 && h1 < 1)
col = QColor::fromRgbF(chroma, x, 0); col = QColor::fromRgbF(chroma, x, 0);
else if (h1 < 2) else if (h1 < 2)
col = QColor::fromRgbF(x, chroma, 0); col = QColor::fromRgbF(x, chroma, 0);
else if (h1 < 3) else if (h1 < 3)
col = QColor::fromRgbF(0, chroma, x); col = QColor::fromRgbF(0, chroma, x);
else if (h1 < 4) else if (h1 < 4)
col = QColor::fromRgbF(0, x, chroma); col = QColor::fromRgbF(0, x, chroma);
else if (h1 < 5) else if (h1 < 5)
col = QColor::fromRgbF(x, 0, chroma); col = QColor::fromRgbF(x, 0, chroma);
else if (h1 < 6) else if (h1 < 6)
col = QColor::fromRgbF(chroma, 0, x); col = QColor::fromRgbF(chroma, 0, x);
qreal m = lig - chroma / 2; qreal m = lig - chroma / 2;
return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0), return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0),
qBound(0.0, col.greenF() + m, 1.0), qBound(0.0, col.greenF() + m, 1.0),
qBound(0.0, col.blueF() + m, 1.0), qBound(0.0, col.blueF() + m, 1.0),
alpha); alpha);
} }
} // namespace detail } // namespace detail

View File

@@ -34,9 +34,9 @@ namespace color_widgets {
enum MouseStatus enum MouseStatus
{ {
Nothing, Nothing,
DragCircle, DragCircle,
DragSquare DragSquare
}; };
static const ColorWheel::DisplayFlags hard_default_flags = static const ColorWheel::DisplayFlags hard_default_flags =
@@ -48,517 +48,499 @@ static const double selector_radius = 6;
class ColorWheel::Private class ColorWheel::Private
{ {
private: private:
ColorWheel* const w; ColorWheel* const w;
public: public:
qreal hue, sat, val; qreal hue, sat, val;
qreal bgBrightness; qreal bgBrightness;
unsigned int wheel_width; unsigned int wheel_width;
MouseStatus mouse_status; MouseStatus mouse_status;
QPixmap hue_ring; QPixmap hue_ring;
QImage inner_selector; QImage inner_selector;
DisplayFlags display_flags; DisplayFlags display_flags;
QColor (*color_from)(qreal, qreal, qreal, qreal); QColor (*color_from)(qreal, qreal, qreal, qreal);
QColor (*rainbow_from_hue)(qreal); QColor (*rainbow_from_hue)(qreal);
int max_size = 128; int max_size = 128;
explicit Private(ColorWheel* widget) explicit Private(ColorWheel* widget)
: w(widget) : w(widget)
, hue(0) , hue(0)
, sat(0) , sat(0)
, val(0) , val(0)
, wheel_width(20) , wheel_width(20)
, mouse_status(Nothing) , mouse_status(Nothing)
, display_flags(FLAGS_DEFAULT) , display_flags(FLAGS_DEFAULT)
, color_from(&QColor::fromHsvF) , color_from(&QColor::fromHsvF)
, rainbow_from_hue(&detail::rainbow_hsv) , rainbow_from_hue(&detail::rainbow_hsv)
{ {
QColor bgColor = widget->palette().window().color(); QColor bgColor = widget->palette().window().color();
bgBrightness = color_widgets::detail::color_lumaF(bgColor); bgBrightness = color_widgets::detail::color_lumaF(bgColor);
}
/// Calculate outer wheel radius from idget center
qreal outer_radius() const
{
return qMin(w->geometry().width(), w->geometry().height()) / 2;
}
/// Calculate inner wheel radius from idget center
qreal inner_radius() const { return outer_radius() - wheel_width; }
/// Calculate the edge length of the inner square
qreal square_size() const { return inner_radius() * qSqrt(2); }
/// Calculate the height of the inner triangle
qreal triangle_height() const { return inner_radius() * 3 / 2; }
/// Calculate the side of the inner triangle
qreal triangle_side() const { return inner_radius() * qSqrt(3); }
/// return line from center to given point
QLineF line_to_point(const QPoint& p) const
{
return QLineF(
w->geometry().width() / 2, w->geometry().height() / 2, p.x(), p.y());
}
void render_square()
{
int width = qMin<int>(square_size(), max_size);
QSize size(width, width);
inner_selector = QImage(size, QImage::Format_RGB32);
for (int y = 0; y < width; ++y) {
for (int x = 0; x < width; ++x) {
inner_selector.setPixel(
x, y, color_from(hue, double(x) / width, double(y) / width, 1).rgb());
}
}
}
/**
* \brief renders the selector as a triangle
* \note It's the same as a square with the edge with value=0 collapsed to a
* single point
*/
void render_triangle()
{
QSizeF size = selector_size();
if (size.height() > max_size)
size *= max_size / size.height();
qreal ycenter = size.height() / 2;
inner_selector = QImage(size.toSize(), QImage::Format_RGB32);
for (int x = 0; x < inner_selector.width(); x++) {
qreal pval = x / size.height();
qreal slice_h = size.height() * pval;
for (int y = 0; y < inner_selector.height(); y++) {
qreal ymin = ycenter - slice_h / 2;
qreal psat = qBound(0.0, (y - ymin) / slice_h, 1.0);
inner_selector.setPixel(x, y, color_from(hue, psat, pval, 1).rgb());
}
}
}
/// Updates the inner image that displays the saturation-value selector
void render_inner_selector()
{
if (display_flags & ColorWheel::SHAPE_TRIANGLE)
render_triangle();
else
render_square();
}
/// Offset of the selector image
QPointF selector_image_offset()
{
if (display_flags & SHAPE_TRIANGLE)
return QPointF(-inner_radius(), -triangle_side() / 2);
return QPointF(-square_size() / 2, -square_size() / 2);
}
/**
* \brief Size of the selector when rendered to the screen
*/
QSizeF selector_size()
{
if (display_flags & SHAPE_TRIANGLE)
return QSizeF(triangle_height(), triangle_side());
return QSizeF(square_size(), square_size());
}
/// Rotation of the selector image
qreal selector_image_angle()
{
if (display_flags & SHAPE_TRIANGLE) {
if (display_flags & ANGLE_ROTATING)
return -hue * 360 - 60;
return -150;
} else {
if (display_flags & ANGLE_ROTATING)
return -hue * 360 - 45;
else
return 180;
}
}
/// Updates the outer ring that displays the hue selector
void render_ring()
{
hue_ring = QPixmap(outer_radius() * 2, outer_radius() * 2);
hue_ring.fill(Qt::transparent);
QPainter painter(&hue_ring);
painter.setRenderHint(QPainter::Antialiasing);
painter.setCompositionMode(QPainter::CompositionMode_Source);
const int hue_stops = 24;
QConicalGradient gradient_hue(0, 0, 0);
if (gradient_hue.stops().size() < hue_stops) {
for (double a = 0; a < 1.0; a += 1.0 / (hue_stops - 1)) {
gradient_hue.setColorAt(a, rainbow_from_hue(a));
}
gradient_hue.setColorAt(1, rainbow_from_hue(0));
} }
painter.translate(outer_radius(), outer_radius()); /// Calculate outer wheel radius from idget center
qreal outer_radius() const
painter.setPen(Qt::NoPen); {
painter.setBrush(QBrush(gradient_hue)); return qMin(w->geometry().width(), w->geometry().height()) / 2;
painter.drawEllipse(QPointF(0, 0), outer_radius(), outer_radius()); }
painter.setBrush(Qt::transparent); // palette().background()); /// Calculate inner wheel radius from idget center
painter.drawEllipse(QPointF(0, 0), inner_radius(), inner_radius()); qreal inner_radius() const { return outer_radius() - wheel_width; }
}
/// Calculate the edge length of the inner square
void set_color(const QColor& c) qreal square_size() const { return inner_radius() * qSqrt(2); }
{
if (display_flags & ColorWheel::COLOR_HSV) { /// Calculate the height of the inner triangle
hue = qMax(0.0, c.hsvHueF()); qreal triangle_height() const { return inner_radius() * 3 / 2; }
sat = c.hsvSaturationF();
val = c.valueF(); /// Calculate the side of the inner triangle
} else if (display_flags & ColorWheel::COLOR_HSL) { qreal triangle_side() const { return inner_radius() * qSqrt(3); }
hue = qMax(0.0, c.hueF());
sat = detail::color_HSL_saturationF(c); /// return line from center to given point
val = detail::color_lightnessF(c); QLineF line_to_point(const QPoint& p) const
} else if (display_flags & ColorWheel::COLOR_LCH) { {
hue = qMax(0.0, c.hsvHueF()); return QLineF(
sat = detail::color_chromaF(c); w->geometry().width() / 2, w->geometry().height() / 2, p.x(), p.y());
val = detail::color_lumaF(c); }
void render_square()
{
int width = qMin<int>(square_size(), max_size);
QSize size(width, width);
inner_selector = QImage(size, QImage::Format_RGB32);
for (int y = 0; y < width; ++y) {
for (int x = 0; x < width; ++x) {
inner_selector.setPixel(
x,
y,
color_from(hue, double(x) / width, double(y) / width, 1)
.rgb());
}
}
}
/**
* \brief renders the selector as a triangle
* \note It's the same as a square with the edge with value=0 collapsed to a
* single point
*/
void render_triangle()
{
QSizeF size = selector_size();
if (size.height() > max_size)
size *= max_size / size.height();
qreal ycenter = size.height() / 2;
inner_selector = QImage(size.toSize(), QImage::Format_RGB32);
for (int x = 0; x < inner_selector.width(); x++) {
qreal pval = x / size.height();
qreal slice_h = size.height() * pval;
for (int y = 0; y < inner_selector.height(); y++) {
qreal ymin = ycenter - slice_h / 2;
qreal psat = qBound(0.0, (y - ymin) / slice_h, 1.0);
inner_selector.setPixel(
x, y, color_from(hue, psat, pval, 1).rgb());
}
}
}
/// Updates the inner image that displays the saturation-value selector
void render_inner_selector()
{
if (display_flags & ColorWheel::SHAPE_TRIANGLE)
render_triangle();
else
render_square();
}
/// Offset of the selector image
QPointF selector_image_offset()
{
if (display_flags & SHAPE_TRIANGLE)
return QPointF(-inner_radius(), -triangle_side() / 2);
return QPointF(-square_size() / 2, -square_size() / 2);
}
/**
* \brief Size of the selector when rendered to the screen
*/
QSizeF selector_size()
{
if (display_flags & SHAPE_TRIANGLE)
return QSizeF(triangle_height(), triangle_side());
return QSizeF(square_size(), square_size());
}
/// Rotation of the selector image
qreal selector_image_angle()
{
if (display_flags & SHAPE_TRIANGLE) {
if (display_flags & ANGLE_ROTATING)
return -hue * 360 - 60;
return -150;
} else {
if (display_flags & ANGLE_ROTATING)
return -hue * 360 - 45;
else
return 180;
}
}
/// Updates the outer ring that displays the hue selector
void render_ring()
{
hue_ring = QPixmap(outer_radius() * 2, outer_radius() * 2);
hue_ring.fill(Qt::transparent);
QPainter painter(&hue_ring);
painter.setRenderHint(QPainter::Antialiasing);
painter.setCompositionMode(QPainter::CompositionMode_Source);
const int hue_stops = 24;
QConicalGradient gradient_hue(0, 0, 0);
if (gradient_hue.stops().size() < hue_stops) {
for (double a = 0; a < 1.0; a += 1.0 / (hue_stops - 1)) {
gradient_hue.setColorAt(a, rainbow_from_hue(a));
}
gradient_hue.setColorAt(1, rainbow_from_hue(0));
}
painter.translate(outer_radius(), outer_radius());
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(gradient_hue));
painter.drawEllipse(QPointF(0, 0), outer_radius(), outer_radius());
painter.setBrush(Qt::transparent); // palette().background());
painter.drawEllipse(QPointF(0, 0), inner_radius(), inner_radius());
}
void set_color(const QColor& c)
{
if (display_flags & ColorWheel::COLOR_HSV) {
hue = qMax(0.0, c.hsvHueF());
sat = c.hsvSaturationF();
val = c.valueF();
} else if (display_flags & ColorWheel::COLOR_HSL) {
hue = qMax(0.0, c.hueF());
sat = detail::color_HSL_saturationF(c);
val = detail::color_lightnessF(c);
} else if (display_flags & ColorWheel::COLOR_LCH) {
hue = qMax(0.0, c.hsvHueF());
sat = detail::color_chromaF(c);
val = detail::color_lumaF(c);
}
} }
}
}; };
ColorWheel::ColorWheel(QWidget* parent) ColorWheel::ColorWheel(QWidget* parent)
: QWidget(parent) : QWidget(parent)
, p(new Private(this)) , p(new Private(this))
{ {
setDisplayFlags(FLAGS_DEFAULT); setDisplayFlags(FLAGS_DEFAULT);
setAcceptDrops(true); setAcceptDrops(true);
} }
ColorWheel::~ColorWheel() ColorWheel::~ColorWheel()
{ {
delete p; delete p;
} }
QColor QColor ColorWheel::color() const
ColorWheel::color() const
{ {
return p->color_from(p->hue, p->sat, p->val, 1); return p->color_from(p->hue, p->sat, p->val, 1);
} }
QSize QSize ColorWheel::sizeHint() const
ColorWheel::sizeHint() const
{ {
return QSize(p->wheel_width * 5, p->wheel_width * 5); return QSize(p->wheel_width * 5, p->wheel_width * 5);
} }
qreal qreal ColorWheel::hue() const
ColorWheel::hue() const
{ {
if ((p->display_flags & COLOR_LCH) && p->sat > 0.01) if ((p->display_flags & COLOR_LCH) && p->sat > 0.01)
return color().hueF(); return color().hueF();
return p->hue; return p->hue;
} }
qreal qreal ColorWheel::saturation() const
ColorWheel::saturation() const
{ {
return color().hsvSaturationF(); return color().hsvSaturationF();
} }
qreal qreal ColorWheel::value() const
ColorWheel::value() const
{ {
return color().valueF(); return color().valueF();
} }
unsigned int unsigned int ColorWheel::wheelWidth() const
ColorWheel::wheelWidth() const
{ {
return p->wheel_width; return p->wheel_width;
} }
void void ColorWheel::setWheelWidth(unsigned int w)
ColorWheel::setWheelWidth(unsigned int w)
{ {
p->wheel_width = w; p->wheel_width = w;
p->render_inner_selector();
update();
}
void
ColorWheel::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(geometry().width() / 2, geometry().height() / 2);
// hue wheel
if (p->hue_ring.isNull())
p->render_ring();
painter.drawPixmap(-p->outer_radius(), -p->outer_radius(), p->hue_ring);
// hue selector
QColor penColor = p->bgBrightness < 0.6 ? Qt::white : Qt::black;
painter.setPen(QPen(penColor, 3));
painter.setBrush(Qt::NoBrush);
QLineF ray(0, 0, p->outer_radius(), 0);
ray.setAngle(p->hue * 360);
QPointF h1 = ray.p2();
ray.setLength(p->inner_radius());
QPointF h2 = ray.p2();
painter.drawLine(h1, h2);
// lum-sat square
if (p->inner_selector.isNull())
p->render_inner_selector(); p->render_inner_selector();
painter.rotate(p->selector_image_angle());
painter.translate(p->selector_image_offset());
QPointF selector_position;
if (p->display_flags & SHAPE_SQUARE) {
qreal side = p->square_size();
selector_position = QPointF(p->sat * side, p->val * side);
} else if (p->display_flags & SHAPE_TRIANGLE) {
qreal side = p->triangle_side();
qreal height = p->triangle_height();
qreal slice_h = side * p->val;
qreal ymin = side / 2 - slice_h / 2;
selector_position = QPointF(p->val * height, ymin + p->sat * slice_h);
QPolygonF triangle;
triangle.append(QPointF(0, side / 2));
triangle.append(QPointF(height, 0));
triangle.append(QPointF(height, side));
QPainterPath clip;
clip.addPolygon(triangle);
painter.setClipPath(clip);
}
painter.drawImage(QRectF(QPointF(0, 0), p->selector_size()),
p->inner_selector);
painter.setClipping(false);
// lum-sat selector
// we define the color of the selecto based on the background color of the
// widget in order to improve the contrast
qreal colorBrightness = color_widgets::detail::color_lumaF(color());
if (p->bgBrightness < 0.6) // dark theme
{
bool isWhite = (colorBrightness < 0.7);
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
} else // light theme
{
bool isWhite = (colorBrightness < 0.4 && p->val < 0.3);
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
}
painter.setBrush(Qt::NoBrush);
painter.drawEllipse(selector_position, selector_radius, selector_radius);
}
void
ColorWheel::mouseMoveEvent(QMouseEvent* ev)
{
if (p->mouse_status == DragCircle) {
p->hue = p->line_to_point(ev->pos()).angle() / 360.0;
p->render_inner_selector();
emit colorSelected(color());
emit colorChanged(color());
update(); update();
} else if (p->mouse_status == DragSquare) { }
QLineF glob_mouse_ln = p->line_to_point(ev->pos());
QLineF center_mouse_ln(QPointF(0, 0),
glob_mouse_ln.p2() - glob_mouse_ln.p1());
center_mouse_ln.setAngle(center_mouse_ln.angle() + void ColorWheel::paintEvent(QPaintEvent*)
p->selector_image_angle()); {
center_mouse_ln.setP2(center_mouse_ln.p2() - p->selector_image_offset()); QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(geometry().width() / 2, geometry().height() / 2);
// hue wheel
if (p->hue_ring.isNull())
p->render_ring();
painter.drawPixmap(-p->outer_radius(), -p->outer_radius(), p->hue_ring);
// hue selector
QColor penColor = p->bgBrightness < 0.6 ? Qt::white : Qt::black;
painter.setPen(QPen(penColor, 3));
painter.setBrush(Qt::NoBrush);
QLineF ray(0, 0, p->outer_radius(), 0);
ray.setAngle(p->hue * 360);
QPointF h1 = ray.p2();
ray.setLength(p->inner_radius());
QPointF h2 = ray.p2();
painter.drawLine(h1, h2);
// lum-sat square
if (p->inner_selector.isNull())
p->render_inner_selector();
painter.rotate(p->selector_image_angle());
painter.translate(p->selector_image_offset());
QPointF selector_position;
if (p->display_flags & SHAPE_SQUARE) { if (p->display_flags & SHAPE_SQUARE) {
p->sat = qBound(0.0, center_mouse_ln.x2() / p->square_size(), 1.0); qreal side = p->square_size();
p->val = qBound(0.0, center_mouse_ln.y2() / p->square_size(), 1.0); selector_position = QPointF(p->sat * side, p->val * side);
} else if (p->display_flags & SHAPE_TRIANGLE) { } else if (p->display_flags & SHAPE_TRIANGLE) {
QPointF pt = center_mouse_ln.p2(); qreal side = p->triangle_side();
qreal height = p->triangle_height();
qreal slice_h = side * p->val;
qreal ymin = side / 2 - slice_h / 2;
qreal side = p->triangle_side(); selector_position = QPointF(p->val * height, ymin + p->sat * slice_h);
p->val = qBound(0.0, pt.x() / p->triangle_height(), 1.0); QPolygonF triangle;
qreal slice_h = side * p->val; triangle.append(QPointF(0, side / 2));
triangle.append(QPointF(height, 0));
qreal ycenter = side / 2; triangle.append(QPointF(height, side));
qreal ymin = ycenter - slice_h / 2; QPainterPath clip;
clip.addPolygon(triangle);
if (slice_h > 0) painter.setClipPath(clip);
p->sat = qBound(0.0, (pt.y() - ymin) / slice_h, 1.0);
} }
emit colorSelected(color()); painter.drawImage(QRectF(QPointF(0, 0), p->selector_size()),
emit colorChanged(color()); p->inner_selector);
update(); painter.setClipping(false);
}
// lum-sat selector
// we define the color of the selecto based on the background color of the
// widget in order to improve the contrast
qreal colorBrightness = color_widgets::detail::color_lumaF(color());
if (p->bgBrightness < 0.6) // dark theme
{
bool isWhite = (colorBrightness < 0.7);
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
} else // light theme
{
bool isWhite = (colorBrightness < 0.4 && p->val < 0.3);
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
}
painter.setBrush(Qt::NoBrush);
painter.drawEllipse(selector_position, selector_radius, selector_radius);
} }
void void ColorWheel::mouseMoveEvent(QMouseEvent* ev)
ColorWheel::mousePressEvent(QMouseEvent* ev)
{ {
if (ev->buttons() & Qt::LeftButton) { if (p->mouse_status == DragCircle) {
setFocus(); p->hue = p->line_to_point(ev->pos()).angle() / 360.0;
QLineF ray = p->line_to_point(ev->pos()); p->render_inner_selector();
if (ray.length() <= p->inner_radius())
p->mouse_status = DragSquare;
else if (ray.length() <= p->outer_radius())
p->mouse_status = DragCircle;
// Update the color emit colorSelected(color());
emit colorChanged(color());
update();
} else if (p->mouse_status == DragSquare) {
QLineF glob_mouse_ln = p->line_to_point(ev->pos());
QLineF center_mouse_ln(QPointF(0, 0),
glob_mouse_ln.p2() - glob_mouse_ln.p1());
center_mouse_ln.setAngle(center_mouse_ln.angle() +
p->selector_image_angle());
center_mouse_ln.setP2(center_mouse_ln.p2() -
p->selector_image_offset());
if (p->display_flags & SHAPE_SQUARE) {
p->sat = qBound(0.0, center_mouse_ln.x2() / p->square_size(), 1.0);
p->val = qBound(0.0, center_mouse_ln.y2() / p->square_size(), 1.0);
} else if (p->display_flags & SHAPE_TRIANGLE) {
QPointF pt = center_mouse_ln.p2();
qreal side = p->triangle_side();
p->val = qBound(0.0, pt.x() / p->triangle_height(), 1.0);
qreal slice_h = side * p->val;
qreal ycenter = side / 2;
qreal ymin = ycenter - slice_h / 2;
if (slice_h > 0)
p->sat = qBound(0.0, (pt.y() - ymin) / slice_h, 1.0);
}
emit colorSelected(color());
emit colorChanged(color());
update();
}
}
void ColorWheel::mousePressEvent(QMouseEvent* ev)
{
if (ev->buttons() & Qt::LeftButton) {
setFocus();
QLineF ray = p->line_to_point(ev->pos());
if (ray.length() <= p->inner_radius())
p->mouse_status = DragSquare;
else if (ray.length() <= p->outer_radius())
p->mouse_status = DragCircle;
// Update the color
mouseMoveEvent(ev);
}
}
void ColorWheel::mouseReleaseEvent(QMouseEvent* ev)
{
mouseMoveEvent(ev); mouseMoveEvent(ev);
} p->mouse_status = Nothing;
emit mouseReleaseOnColor(color());
} }
void void ColorWheel::resizeEvent(QResizeEvent*)
ColorWheel::mouseReleaseEvent(QMouseEvent* ev)
{ {
mouseMoveEvent(ev);
p->mouse_status = Nothing;
emit mouseReleaseOnColor(color());
}
void
ColorWheel::resizeEvent(QResizeEvent*)
{
p->render_ring();
p->render_inner_selector();
}
void
ColorWheel::setColor(QColor c)
{
qreal oldh = p->hue;
p->set_color(c);
if (!qFuzzyCompare(oldh + 1, p->hue + 1))
p->render_inner_selector();
update();
emit colorChanged(c);
}
void
ColorWheel::setHue(qreal h)
{
p->hue = qBound(0.0, h, 1.0);
p->render_inner_selector();
update();
}
void
ColorWheel::setSaturation(qreal s)
{
p->sat = qBound(0.0, s, 1.0);
update();
}
void
ColorWheel::setValue(qreal v)
{
p->val = qBound(0.0, v, 1.0);
update();
}
void
ColorWheel::setDisplayFlags(DisplayFlags flags)
{
if (!(flags & COLOR_FLAGS))
flags |= default_flags & COLOR_FLAGS;
if (!(flags & ANGLE_FLAGS))
flags |= default_flags & ANGLE_FLAGS;
if (!(flags & SHAPE_FLAGS))
flags |= default_flags & SHAPE_FLAGS;
if ((flags & COLOR_FLAGS) != (p->display_flags & COLOR_FLAGS)) {
QColor old_col = color();
if (flags & ColorWheel::COLOR_HSL) {
p->hue = old_col.hueF();
p->sat = detail::color_HSL_saturationF(old_col);
p->val = detail::color_lightnessF(old_col);
p->color_from = &detail::color_from_hsl;
p->rainbow_from_hue = &detail::rainbow_hsv;
} else if (flags & ColorWheel::COLOR_LCH) {
p->hue = old_col.hueF();
p->sat = detail::color_chromaF(old_col);
p->val = detail::color_lumaF(old_col);
p->color_from = &detail::color_from_lch;
p->rainbow_from_hue = &detail::rainbow_lch;
} else {
p->hue = old_col.hsvHueF();
p->sat = old_col.hsvSaturationF();
p->val = old_col.valueF();
p->color_from = &QColor::fromHsvF;
p->rainbow_from_hue = &detail::rainbow_hsv;
}
p->render_ring(); p->render_ring();
} p->render_inner_selector();
p->display_flags = flags;
p->render_inner_selector();
update();
emit displayFlagsChanged(flags);
} }
ColorWheel::DisplayFlags void ColorWheel::setColor(QColor c)
ColorWheel::displayFlags(DisplayFlags mask) const
{ {
return p->display_flags & mask; qreal oldh = p->hue;
p->set_color(c);
if (!qFuzzyCompare(oldh + 1, p->hue + 1))
p->render_inner_selector();
update();
emit colorChanged(c);
} }
void void ColorWheel::setHue(qreal h)
ColorWheel::setDefaultDisplayFlags(DisplayFlags flags)
{ {
if (!(flags & COLOR_FLAGS)) p->hue = qBound(0.0, h, 1.0);
flags |= hard_default_flags & COLOR_FLAGS; p->render_inner_selector();
if (!(flags & ANGLE_FLAGS)) update();
flags |= hard_default_flags & ANGLE_FLAGS;
if (!(flags & SHAPE_FLAGS))
flags |= hard_default_flags & SHAPE_FLAGS;
default_flags = flags;
} }
ColorWheel::DisplayFlags void ColorWheel::setSaturation(qreal s)
ColorWheel::defaultDisplayFlags(DisplayFlags mask)
{ {
return default_flags & mask; p->sat = qBound(0.0, s, 1.0);
update();
} }
void void ColorWheel::setValue(qreal v)
ColorWheel::setDisplayFlag(DisplayFlags flag, DisplayFlags mask)
{ {
setDisplayFlags((p->display_flags & ~mask) | flag); p->val = qBound(0.0, v, 1.0);
update();
} }
void void ColorWheel::setDisplayFlags(DisplayFlags flags)
ColorWheel::dragEnterEvent(QDragEnterEvent* event)
{ {
if (event->mimeData()->hasColor() || if (!(flags & COLOR_FLAGS))
(event->mimeData()->hasText() && flags |= default_flags & COLOR_FLAGS;
QColor(event->mimeData()->text()).isValid())) if (!(flags & ANGLE_FLAGS))
event->acceptProposedAction(); flags |= default_flags & ANGLE_FLAGS;
} if (!(flags & SHAPE_FLAGS))
flags |= default_flags & SHAPE_FLAGS;
void if ((flags & COLOR_FLAGS) != (p->display_flags & COLOR_FLAGS)) {
ColorWheel::dropEvent(QDropEvent* event) QColor old_col = color();
{ if (flags & ColorWheel::COLOR_HSL) {
if (event->mimeData()->hasColor()) { p->hue = old_col.hueF();
setColor(event->mimeData()->colorData().value<QColor>()); p->sat = detail::color_HSL_saturationF(old_col);
event->accept(); p->val = detail::color_lightnessF(old_col);
} else if (event->mimeData()->hasText()) { p->color_from = &detail::color_from_hsl;
QColor col(event->mimeData()->text()); p->rainbow_from_hue = &detail::rainbow_hsv;
if (col.isValid()) { } else if (flags & ColorWheel::COLOR_LCH) {
setColor(col); p->hue = old_col.hueF();
event->accept(); p->sat = detail::color_chromaF(old_col);
p->val = detail::color_lumaF(old_col);
p->color_from = &detail::color_from_lch;
p->rainbow_from_hue = &detail::rainbow_lch;
} else {
p->hue = old_col.hsvHueF();
p->sat = old_col.hsvSaturationF();
p->val = old_col.valueF();
p->color_from = &QColor::fromHsvF;
p->rainbow_from_hue = &detail::rainbow_hsv;
}
p->render_ring();
}
p->display_flags = flags;
p->render_inner_selector();
update();
emit displayFlagsChanged(flags);
}
ColorWheel::DisplayFlags ColorWheel::displayFlags(DisplayFlags mask) const
{
return p->display_flags & mask;
}
void ColorWheel::setDefaultDisplayFlags(DisplayFlags flags)
{
if (!(flags & COLOR_FLAGS))
flags |= hard_default_flags & COLOR_FLAGS;
if (!(flags & ANGLE_FLAGS))
flags |= hard_default_flags & ANGLE_FLAGS;
if (!(flags & SHAPE_FLAGS))
flags |= hard_default_flags & SHAPE_FLAGS;
default_flags = flags;
}
ColorWheel::DisplayFlags ColorWheel::defaultDisplayFlags(DisplayFlags mask)
{
return default_flags & mask;
}
void ColorWheel::setDisplayFlag(DisplayFlags flag, DisplayFlags mask)
{
setDisplayFlags((p->display_flags & ~mask) | flag);
}
void ColorWheel::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasColor() ||
(event->mimeData()->hasText() &&
QColor(event->mimeData()->text()).isValid()))
event->acceptProposedAction();
}
void ColorWheel::dropEvent(QDropEvent* event)
{
if (event->mimeData()->hasColor()) {
setColor(event->mimeData()->colorData().value<QColor>());
event->accept();
} else if (event->mimeData()->hasText()) {
QColor col(event->mimeData()->text());
if (col.isValid()) {
setColor(col);
event->accept();
}
} }
}
} }
} // namespace color_widgets } // namespace color_widgets

View File

@@ -49,324 +49,319 @@
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication* q_ptr) SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication* q_ptr)
: q_ptr(q_ptr) : q_ptr(q_ptr)
{ {
server = nullptr; server = nullptr;
socket = nullptr; socket = nullptr;
} }
SingleApplicationPrivate::~SingleApplicationPrivate() SingleApplicationPrivate::~SingleApplicationPrivate()
{ {
if (socket != nullptr) { if (socket != nullptr) {
socket->close(); socket->close();
delete socket; delete socket;
} }
memory->lock(); memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data()); InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
if (server != nullptr) { if (server != nullptr) {
server->close(); server->close();
delete server; delete server;
inst->primary = false; inst->primary = false;
inst->primaryPid = -1; inst->primaryPid = -1;
} }
memory->unlock(); memory->unlock();
delete memory; delete memory;
} }
void void SingleApplicationPrivate::genBlockServerName(int timeout)
SingleApplicationPrivate::genBlockServerName(int timeout)
{ {
QCryptographicHash appData(QCryptographicHash::Sha256); QCryptographicHash appData(QCryptographicHash::Sha256);
appData.addData("SingleApplication", 17); appData.addData("SingleApplication", 17);
appData.addData(SingleApplication::app_t::applicationName().toUtf8()); appData.addData(SingleApplication::app_t::applicationName().toUtf8());
appData.addData(SingleApplication::app_t::organizationName().toUtf8()); appData.addData(SingleApplication::app_t::organizationName().toUtf8());
appData.addData(SingleApplication::app_t::organizationDomain().toUtf8()); appData.addData(SingleApplication::app_t::organizationDomain().toUtf8());
if (!(options & SingleApplication::Mode::ExcludeAppVersion)) { if (!(options & SingleApplication::Mode::ExcludeAppVersion)) {
appData.addData(SingleApplication::app_t::applicationVersion().toUtf8()); appData.addData(
} SingleApplication::app_t::applicationVersion().toUtf8());
}
if (!(options & SingleApplication::Mode::ExcludeAppPath)) { if (!(options & SingleApplication::Mode::ExcludeAppPath)) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
appData.addData( appData.addData(
SingleApplication::app_t::applicationFilePath().toLower().toUtf8()); SingleApplication::app_t::applicationFilePath().toLower().toUtf8());
#else #else
appData.addData(SingleApplication::app_t::applicationFilePath().toUtf8()); appData.addData(
SingleApplication::app_t::applicationFilePath().toUtf8());
#endif #endif
} }
// User level block requires a user specific data in the hash // User level block requires a user specific data in the hash
if (options & SingleApplication::Mode::User) { if (options & SingleApplication::Mode::User) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
Q_UNUSED(timeout); Q_UNUSED(timeout);
wchar_t username[UNLEN + 1]; wchar_t username[UNLEN + 1];
// Specifies size of the buffer on input // Specifies size of the buffer on input
DWORD usernameLength = UNLEN + 1; DWORD usernameLength = UNLEN + 1;
if (GetUserNameW(username, &usernameLength)) { if (GetUserNameW(username, &usernameLength)) {
appData.addData(QString::fromWCharArray(username).toUtf8()); appData.addData(QString::fromWCharArray(username).toUtf8());
} else { } else {
appData.addData( appData.addData(
QStandardPaths::standardLocations(QStandardPaths::HomeLocation) QStandardPaths::standardLocations(QStandardPaths::HomeLocation)
.join("") .join("")
.toUtf8()); .toUtf8());
}
#endif
#ifdef Q_OS_UNIX
QProcess process;
process.start(QStringLiteral("whoami"), QStringList{});
if (process.waitForFinished(timeout) &&
process.exitCode() == QProcess::NormalExit) {
appData.addData(process.readLine());
} else {
appData.addData(QDir(QStandardPaths::standardLocations(
QStandardPaths::HomeLocation)
.first())
.absolutePath()
.toUtf8());
}
#endif
} }
#endif
#ifdef Q_OS_UNIX
QProcess process;
process.start(QStringLiteral("whoami"), QStringList{});
if (process.waitForFinished(timeout) && // Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
process.exitCode() == QProcess::NormalExit) { // server naming requirements.
appData.addData(process.readLine()); blockServerName = appData.result().toBase64().replace("/", "_");
}
void SingleApplicationPrivate::startPrimary(bool resetMemory)
{
Q_Q(SingleApplication);
#ifdef Q_OS_UNIX
// Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes
crashHandler();
#endif
// Successful creation means that no main process exists
// So we start a QLocalServer to listen for connections
QLocalServer::removeServer(blockServerName);
server = new QLocalServer();
// Restrict access to the socket according to the
// SingleApplication::Mode::User flag on User level or no restrictions
if (options & SingleApplication::Mode::User) {
server->setSocketOptions(QLocalServer::UserAccessOption);
} else { } else {
appData.addData( server->setSocketOptions(QLocalServer::WorldAccessOption);
QDir(QStandardPaths::standardLocations(QStandardPaths::HomeLocation)
.first())
.absolutePath()
.toUtf8());
} }
#endif
}
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with server->listen(blockServerName);
// server naming requirements. QObject::connect(server,
blockServerName = appData.result().toBase64().replace("/", "_"); &QLocalServer::newConnection,
this,
&SingleApplicationPrivate::slotConnectionEstablished);
// Reset the number of connections
memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
if (resetMemory) {
inst->secondary = 0;
}
inst->primary = true;
inst->primaryPid = q->applicationPid();
memory->unlock();
instanceNumber = 0;
} }
void void SingleApplicationPrivate::startSecondary()
SingleApplicationPrivate::startPrimary(bool resetMemory)
{
Q_Q(SingleApplication);
#ifdef Q_OS_UNIX
// Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes
crashHandler();
#endif
// Successful creation means that no main process exists
// So we start a QLocalServer to listen for connections
QLocalServer::removeServer(blockServerName);
server = new QLocalServer();
// Restrict access to the socket according to the
// SingleApplication::Mode::User flag on User level or no restrictions
if (options & SingleApplication::Mode::User) {
server->setSocketOptions(QLocalServer::UserAccessOption);
} else {
server->setSocketOptions(QLocalServer::WorldAccessOption);
}
server->listen(blockServerName);
QObject::connect(server,
&QLocalServer::newConnection,
this,
&SingleApplicationPrivate::slotConnectionEstablished);
// Reset the number of connections
memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
if (resetMemory) {
inst->secondary = 0;
}
inst->primary = true;
inst->primaryPid = q->applicationPid();
memory->unlock();
instanceNumber = 0;
}
void
SingleApplicationPrivate::startSecondary()
{ {
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
// Handle any further termination signals to ensure the // Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes // QSharedMemory block is deleted even if the process crashes
crashHandler(); crashHandler();
#endif #endif
} }
void void SingleApplicationPrivate::connectToPrimary(int msecs,
SingleApplicationPrivate::connectToPrimary(int msecs, ConnectionType connectionType)
ConnectionType connectionType)
{ {
// Connect to the Local Server of the Primary Instance if not already // Connect to the Local Server of the Primary Instance if not already
// connected. // connected.
if (socket == nullptr) { if (socket == nullptr) {
socket = new QLocalSocket(); socket = new QLocalSocket();
} }
// If already connected - we are done; // If already connected - we are done;
if (socket->state() == QLocalSocket::ConnectedState) if (socket->state() == QLocalSocket::ConnectedState)
return; return;
// If not connect // If not connect
if (socket->state() == QLocalSocket::UnconnectedState || if (socket->state() == QLocalSocket::UnconnectedState ||
socket->state() == QLocalSocket::ClosingState) { socket->state() == QLocalSocket::ClosingState) {
socket->connectToServer(blockServerName); socket->connectToServer(blockServerName);
} }
// Wait for being connected // Wait for being connected
if (socket->state() == QLocalSocket::ConnectingState) { if (socket->state() == QLocalSocket::ConnectingState) {
socket->waitForConnected(msecs); socket->waitForConnected(msecs);
} }
// Initialisation message according to the SingleApplication protocol // Initialisation message according to the SingleApplication protocol
if (socket->state() == QLocalSocket::ConnectedState) { if (socket->state() == QLocalSocket::ConnectedState) {
// Notify the parent that a new instance had been started; // Notify the parent that a new instance had been started;
QByteArray initMsg; QByteArray initMsg;
QDataStream writeStream(&initMsg, QIODevice::WriteOnly); QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
writeStream.setVersion(QDataStream::Qt_5_2); writeStream.setVersion(QDataStream::Qt_5_2);
writeStream << blockServerName.toLatin1(); writeStream << blockServerName.toLatin1();
writeStream << static_cast<quint8>(connectionType); writeStream << static_cast<quint8>(connectionType);
writeStream << instanceNumber; writeStream << instanceNumber;
quint16 checksum = quint16 checksum = qChecksum(initMsg.constData(),
qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length())); static_cast<quint32>(initMsg.length()));
writeStream << checksum; writeStream << checksum;
socket->write(initMsg); socket->write(initMsg);
socket->flush(); socket->flush();
socket->waitForBytesWritten(msecs); socket->waitForBytesWritten(msecs);
} }
} }
qint64 qint64 SingleApplicationPrivate::primaryPid()
SingleApplicationPrivate::primaryPid()
{ {
qint64 pid; qint64 pid;
memory->lock(); memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data()); InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
pid = inst->primaryPid; pid = inst->primaryPid;
memory->unlock(); memory->unlock();
return pid; return pid;
} }
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
void void SingleApplicationPrivate::crashHandler()
SingleApplicationPrivate::crashHandler()
{ {
// Handle any further termination signals to ensure the // Handle any further termination signals to ensure the
// QSharedMemory block is deleted even if the process crashes // QSharedMemory block is deleted even if the process crashes
signal(SIGHUP, SingleApplicationPrivate::terminate); // 1 signal(SIGHUP, SingleApplicationPrivate::terminate); // 1
signal(SIGINT, SingleApplicationPrivate::terminate); // 2 signal(SIGINT, SingleApplicationPrivate::terminate); // 2
signal(SIGQUIT, SingleApplicationPrivate::terminate); // 3 signal(SIGQUIT, SingleApplicationPrivate::terminate); // 3
signal(SIGILL, SingleApplicationPrivate::terminate); // 4 signal(SIGILL, SingleApplicationPrivate::terminate); // 4
signal(SIGABRT, SingleApplicationPrivate::terminate); // 6 signal(SIGABRT, SingleApplicationPrivate::terminate); // 6
signal(SIGFPE, SingleApplicationPrivate::terminate); // 8 signal(SIGFPE, SingleApplicationPrivate::terminate); // 8
signal(SIGBUS, SingleApplicationPrivate::terminate); // 10 signal(SIGBUS, SingleApplicationPrivate::terminate); // 10
signal(SIGSEGV, SingleApplicationPrivate::terminate); // 11 signal(SIGSEGV, SingleApplicationPrivate::terminate); // 11
signal(SIGSYS, SingleApplicationPrivate::terminate); // 12 signal(SIGSYS, SingleApplicationPrivate::terminate); // 12
signal(SIGPIPE, SingleApplicationPrivate::terminate); // 13 signal(SIGPIPE, SingleApplicationPrivate::terminate); // 13
signal(SIGALRM, SingleApplicationPrivate::terminate); // 14 signal(SIGALRM, SingleApplicationPrivate::terminate); // 14
signal(SIGTERM, SingleApplicationPrivate::terminate); // 15 signal(SIGTERM, SingleApplicationPrivate::terminate); // 15
signal(SIGXCPU, SingleApplicationPrivate::terminate); // 24 signal(SIGXCPU, SingleApplicationPrivate::terminate); // 24
signal(SIGXFSZ, SingleApplicationPrivate::terminate); // 25 signal(SIGXFSZ, SingleApplicationPrivate::terminate); // 25
} }
void void SingleApplicationPrivate::terminate(int signum)
SingleApplicationPrivate::terminate(int signum)
{ {
delete ((SingleApplication*)QCoreApplication::instance())->d_ptr; delete ((SingleApplication*)QCoreApplication::instance())->d_ptr;
::exit(128 + signum); ::exit(128 + signum);
} }
#endif #endif
/** /**
* @brief Executed when a connection has been made to the LocalServer * @brief Executed when a connection has been made to the LocalServer
*/ */
void void SingleApplicationPrivate::slotConnectionEstablished()
SingleApplicationPrivate::slotConnectionEstablished()
{ {
Q_Q(SingleApplication); Q_Q(SingleApplication);
QLocalSocket* nextConnSocket = server->nextPendingConnection(); QLocalSocket* nextConnSocket = server->nextPendingConnection();
quint32 instanceId = 0; quint32 instanceId = 0;
ConnectionType connectionType = InvalidConnection; ConnectionType connectionType = InvalidConnection;
if (nextConnSocket->waitForReadyRead(100)) { if (nextConnSocket->waitForReadyRead(100)) {
// read all data from message in same order/format as written // read all data from message in same order/format as written
QByteArray msgBytes = nextConnSocket->read( QByteArray msgBytes =
nextConnSocket->bytesAvailable() - static_cast<qint64>(sizeof(quint16))); nextConnSocket->read(nextConnSocket->bytesAvailable() -
QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16)); static_cast<qint64>(sizeof(quint16)));
QDataStream readStream(msgBytes); QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16));
readStream.setVersion(QDataStream::Qt_5_2); QDataStream readStream(msgBytes);
readStream.setVersion(QDataStream::Qt_5_2);
// server name // server name
QByteArray latin1Name; QByteArray latin1Name;
readStream >> latin1Name; readStream >> latin1Name;
// connectioon type // connectioon type
quint8 connType = InvalidConnection; quint8 connType = InvalidConnection;
readStream >> connType; readStream >> connType;
connectionType = static_cast<ConnectionType>(connType); connectionType = static_cast<ConnectionType>(connType);
// instance id // instance id
readStream >> instanceId; readStream >> instanceId;
// checksum // checksum
quint16 msgChecksum = 0; quint16 msgChecksum = 0;
QDataStream checksumStream(checksumBytes); QDataStream checksumStream(checksumBytes);
checksumStream.setVersion(QDataStream::Qt_5_2); checksumStream.setVersion(QDataStream::Qt_5_2);
checksumStream >> msgChecksum; checksumStream >> msgChecksum;
const quint16 actualChecksum = const quint16 actualChecksum = qChecksum(
qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length())); msgBytes.constData(), static_cast<quint32>(msgBytes.length()));
if (readStream.status() != QDataStream::Ok || if (readStream.status() != QDataStream::Ok ||
QLatin1String(latin1Name) != blockServerName || QLatin1String(latin1Name) != blockServerName ||
msgChecksum != actualChecksum) { msgChecksum != actualChecksum) {
connectionType = InvalidConnection; connectionType = InvalidConnection;
}
} }
}
if (connectionType == InvalidConnection) { if (connectionType == InvalidConnection) {
nextConnSocket->close(); nextConnSocket->close();
delete nextConnSocket; delete nextConnSocket;
return; return;
} }
QObject::connect(nextConnSocket, QObject::connect(nextConnSocket,
&QLocalSocket::aboutToClose, &QLocalSocket::aboutToClose,
this, this,
[nextConnSocket, instanceId, this]() { [nextConnSocket, instanceId, this]() {
emit this->slotClientConnectionClosed(nextConnSocket, emit this->slotClientConnectionClosed(nextConnSocket,
instanceId); instanceId);
}); });
QObject::connect(nextConnSocket, QObject::connect(nextConnSocket,
&QLocalSocket::readyRead, &QLocalSocket::readyRead,
this, this,
[nextConnSocket, instanceId, this]() { [nextConnSocket, instanceId, this]() {
emit this->slotDataAvailable(nextConnSocket, instanceId); emit this->slotDataAvailable(nextConnSocket,
}); instanceId);
});
if (connectionType == NewInstance || if (connectionType == NewInstance ||
(connectionType == SecondaryInstance && (connectionType == SecondaryInstance &&
options & SingleApplication::Mode::SecondaryNotification)) { options & SingleApplication::Mode::SecondaryNotification)) {
emit q->instanceStarted(); emit q->instanceStarted();
} }
if (nextConnSocket->bytesAvailable() > 0) { if (nextConnSocket->bytesAvailable() > 0) {
emit this->slotDataAvailable(nextConnSocket, instanceId); emit this->slotDataAvailable(nextConnSocket, instanceId);
} }
} }
void void SingleApplicationPrivate::slotDataAvailable(QLocalSocket* dataSocket,
SingleApplicationPrivate::slotDataAvailable(QLocalSocket* dataSocket, quint32 instanceId)
quint32 instanceId)
{ {
Q_Q(SingleApplication); Q_Q(SingleApplication);
emit q->receivedMessage(instanceId, dataSocket->readAll()); emit q->receivedMessage(instanceId, dataSocket->readAll());
} }
void void SingleApplicationPrivate::slotClientConnectionClosed(
SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket* closedSocket, QLocalSocket* closedSocket,
quint32 instanceId) quint32 instanceId)
{ {
if (closedSocket->bytesAvailable() > 0) if (closedSocket->bytesAvailable() > 0)
emit slotDataAvailable(closedSocket, instanceId); emit slotDataAvailable(closedSocket, instanceId);
closedSocket->deleteLater(); closedSocket->deleteLater();
} }
/** /**
@@ -384,61 +379,62 @@ SingleApplication::SingleApplication(int& argc,
: app_t(argc, argv) : app_t(argc, argv)
, d_ptr(new SingleApplicationPrivate(this)) , d_ptr(new SingleApplicationPrivate(this))
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
// Store the current mode of the program // Store the current mode of the program
d->options = options; d->options = options;
// Generating an application ID used for identifying the shared memory // Generating an application ID used for identifying the shared memory
// block and QLocalServer // block and QLocalServer
d->genBlockServerName(timeout); d->genBlockServerName(timeout);
// Guarantee thread safe behaviour with a shared memory block. Also by // Guarantee thread safe behaviour with a shared memory block. Also by
// explicitly attaching it and then deleting it we make sure that the // explicitly attaching it and then deleting it we make sure that the
// memory is deleted even if the process had crashed on Unix. // memory is deleted even if the process had crashed on Unix.
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
d->memory = new QSharedMemory(d->blockServerName); d->memory = new QSharedMemory(d->blockServerName);
d->memory->attach(); d->memory->attach();
delete d->memory; delete d->memory;
#endif #endif
d->memory = new QSharedMemory(d->blockServerName); d->memory = new QSharedMemory(d->blockServerName);
// Create a shared memory block // Create a shared memory block
if (d->memory->create(sizeof(InstancesInfo))) { if (d->memory->create(sizeof(InstancesInfo))) {
d->startPrimary(true); d->startPrimary(true);
return;
} else {
// Attempt to attach to the memory segment
if (d->memory->attach()) {
d->memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(d->memory->data());
if (!inst->primary) {
d->startPrimary(false);
d->memory->unlock();
return; return;
} } else {
// Attempt to attach to the memory segment
if (d->memory->attach()) {
d->memory->lock();
InstancesInfo* inst =
static_cast<InstancesInfo*>(d->memory->data());
// Check if another instance can be started if (!inst->primary) {
if (allowSecondary) { d->startPrimary(false);
inst->secondary += 1; d->memory->unlock();
d->instanceNumber = inst->secondary; return;
d->startSecondary(); }
if (d->options & Mode::SecondaryNotification) {
d->connectToPrimary(timeout, // Check if another instance can be started
SingleApplicationPrivate::SecondaryInstance); if (allowSecondary) {
inst->secondary += 1;
d->instanceNumber = inst->secondary;
d->startSecondary();
if (d->options & Mode::SecondaryNotification) {
d->connectToPrimary(
timeout, SingleApplicationPrivate::SecondaryInstance);
}
d->memory->unlock();
return;
}
d->memory->unlock();
} }
d->memory->unlock();
return;
}
d->memory->unlock();
} }
}
d->connectToPrimary(timeout, SingleApplicationPrivate::NewInstance); d->connectToPrimary(timeout, SingleApplicationPrivate::NewInstance);
delete d; delete d;
::exit(EXIT_SUCCESS); ::exit(EXIT_SUCCESS);
} }
/** /**
@@ -446,52 +442,47 @@ SingleApplication::SingleApplication(int& argc,
*/ */
SingleApplication::~SingleApplication() SingleApplication::~SingleApplication()
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
delete d; delete d;
} }
bool bool SingleApplication::isPrimary()
SingleApplication::isPrimary()
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
return d->server != nullptr; return d->server != nullptr;
} }
bool bool SingleApplication::isSecondary()
SingleApplication::isSecondary()
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
return d->server == nullptr; return d->server == nullptr;
} }
quint32 quint32 SingleApplication::instanceId()
SingleApplication::instanceId()
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
return d->instanceNumber; return d->instanceNumber;
} }
qint64 qint64 SingleApplication::primaryPid()
SingleApplication::primaryPid()
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
return d->primaryPid(); return d->primaryPid();
} }
bool bool SingleApplication::sendMessage(QByteArray message, int timeout)
SingleApplication::sendMessage(QByteArray message, int timeout)
{ {
Q_D(SingleApplication); Q_D(SingleApplication);
// Nobody to connect to // Nobody to connect to
if (isPrimary()) if (isPrimary())
return false; return false;
// Make sure the socket is connected // Make sure the socket is connected
d->connectToPrimary(timeout, SingleApplicationPrivate::Reconnect); d->connectToPrimary(timeout, SingleApplicationPrivate::Reconnect);
d->socket->write(message); d->socket->write(message);
bool dataWritten = d->socket->flush(); bool dataWritten = d->socket->flush();
d->socket->waitForBytesWritten(timeout); d->socket->waitForBytesWritten(timeout);
return dataWritten; return dataWritten;
} }

View File

@@ -41,98 +41,98 @@ class SingleApplicationPrivate;
*/ */
class SingleApplication : public QAPPLICATION_CLASS class SingleApplication : public QAPPLICATION_CLASS
{ {
Q_OBJECT Q_OBJECT
typedef QAPPLICATION_CLASS app_t; typedef QAPPLICATION_CLASS app_t;
public: public:
/** /**
* @brief Mode of operation of SingleApplication. * @brief Mode of operation of SingleApplication.
* Whether the block should be user-wide or system-wide and whether the * Whether the block should be user-wide or system-wide and whether the
* primary instance should be notified when a secondary instance had been * primary instance should be notified when a secondary instance had been
* started. * started.
* @note Operating system can restrict the shared memory blocks to the same * @note Operating system can restrict the shared memory blocks to the same
* user, in which case the User/System modes will have no effect and the * user, in which case the User/System modes will have no effect and the
* block will be user wide. * block will be user wide.
* @enum * @enum
*/ */
enum Mode enum Mode
{ {
User = 1 << 0, User = 1 << 0,
System = 1 << 1, System = 1 << 1,
SecondaryNotification = 1 << 2, SecondaryNotification = 1 << 2,
ExcludeAppVersion = 1 << 3, ExcludeAppVersion = 1 << 3,
ExcludeAppPath = 1 << 4 ExcludeAppPath = 1 << 4
}; };
Q_DECLARE_FLAGS(Options, Mode) Q_DECLARE_FLAGS(Options, Mode)
/** /**
* @brief Intitializes a SingleApplication instance with argc command line * @brief Intitializes a SingleApplication instance with argc command line
* arguments in argv * arguments in argv
* @arg {int &} argc - Number of arguments in argv * @arg {int &} argc - Number of arguments in argv
* @arg {const char *[]} argv - Supplied command line arguments * @arg {const char *[]} argv - Supplied command line arguments
* @arg {bool} allowSecondary - Whether to start the instance as secondary * @arg {bool} allowSecondary - Whether to start the instance as secondary
* if there is already a primary instance. * if there is already a primary instance.
* @arg {Mode} mode - Whether for the SingleApplication block to be applied * @arg {Mode} mode - Whether for the SingleApplication block to be applied
* User wide or System wide. * User wide or System wide.
* @arg {int} timeout - Timeout to wait in miliseconds. * @arg {int} timeout - Timeout to wait in miliseconds.
* @note argc and argv may be changed as Qt removes arguments that it * @note argc and argv may be changed as Qt removes arguments that it
* recognizes * recognizes
* @note Mode::SecondaryNotification only works if set on both the primary * @note Mode::SecondaryNotification only works if set on both the primary
* instance and the secondary instance. * instance and the secondary instance.
* @note The timeout is just a hint for the maximum time of blocking * @note The timeout is just a hint for the maximum time of blocking
* operations. It does not guarantee that the SingleApplication * operations. It does not guarantee that the SingleApplication
* initialisation will be completed in given time, though is a good hint. * initialisation will be completed in given time, though is a good hint.
* Usually 4*timeout would be the worst case (fail) scenario. * Usually 4*timeout would be the worst case (fail) scenario.
* @see See the corresponding QAPPLICATION_CLASS constructor for reference * @see See the corresponding QAPPLICATION_CLASS constructor for reference
*/ */
explicit SingleApplication(int& argc, explicit SingleApplication(int& argc,
char* argv[], char* argv[],
bool allowSecondary = false, bool allowSecondary = false,
Options options = Mode::User, Options options = Mode::User,
int timeout = 100); int timeout = 100);
~SingleApplication(); ~SingleApplication();
/** /**
* @brief Returns if the instance is the primary instance * @brief Returns if the instance is the primary instance
* @returns {bool} * @returns {bool}
*/ */
bool isPrimary(); bool isPrimary();
/** /**
* @brief Returns if the instance is a secondary instance * @brief Returns if the instance is a secondary instance
* @returns {bool} * @returns {bool}
*/ */
bool isSecondary(); bool isSecondary();
/** /**
* @brief Returns a unique identifier for the current instance * @brief Returns a unique identifier for the current instance
* @returns {qint32} * @returns {qint32}
*/ */
quint32 instanceId(); quint32 instanceId();
/** /**
* @brief Returns the process ID (PID) of the primary instance * @brief Returns the process ID (PID) of the primary instance
* @returns {qint64} * @returns {qint64}
*/ */
qint64 primaryPid(); qint64 primaryPid();
/** /**
* @brief Sends a message to the primary instance. Returns true on success. * @brief Sends a message to the primary instance. Returns true on success.
* @param {int} timeout - Timeout for connecting * @param {int} timeout - Timeout for connecting
* @returns {bool} * @returns {bool}
* @note sendMessage() will return false if invoked from the primary * @note sendMessage() will return false if invoked from the primary
* instance. * instance.
*/ */
bool sendMessage(QByteArray message, int timeout = 100); bool sendMessage(QByteArray message, int timeout = 100);
Q_SIGNALS: Q_SIGNALS:
void instanceStarted(); void instanceStarted();
void receivedMessage(quint32 instanceId, QByteArray message); void receivedMessage(quint32 instanceId, QByteArray message);
private: private:
SingleApplicationPrivate* d_ptr; SingleApplicationPrivate* d_ptr;
Q_DECLARE_PRIVATE(SingleApplication) Q_DECLARE_PRIVATE(SingleApplication)
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options) Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)

View File

@@ -39,50 +39,50 @@
struct InstancesInfo struct InstancesInfo
{ {
bool primary; bool primary;
quint32 secondary; quint32 secondary;
qint64 primaryPid; qint64 primaryPid;
}; };
class SingleApplicationPrivate : public QObject class SingleApplicationPrivate : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum ConnectionType : quint8 enum ConnectionType : quint8
{ {
InvalidConnection = 0, InvalidConnection = 0,
NewInstance = 1, NewInstance = 1,
SecondaryInstance = 2, SecondaryInstance = 2,
Reconnect = 3 Reconnect = 3
}; };
Q_DECLARE_PUBLIC(SingleApplication) Q_DECLARE_PUBLIC(SingleApplication)
SingleApplicationPrivate(SingleApplication* q_ptr); SingleApplicationPrivate(SingleApplication* q_ptr);
~SingleApplicationPrivate(); ~SingleApplicationPrivate();
void genBlockServerName(int msecs); void genBlockServerName(int msecs);
void startPrimary(bool resetMemory); void startPrimary(bool resetMemory);
void startSecondary(); void startSecondary();
void connectToPrimary(int msecs, ConnectionType connectionType); void connectToPrimary(int msecs, ConnectionType connectionType);
qint64 primaryPid(); qint64 primaryPid();
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
void crashHandler(); void crashHandler();
static void terminate(int signum); static void terminate(int signum);
#endif #endif
QSharedMemory* memory; QSharedMemory* memory;
SingleApplication* q_ptr; SingleApplication* q_ptr;
QLocalSocket* socket; QLocalSocket* socket;
QLocalServer* server; QLocalServer* server;
quint32 instanceNumber; quint32 instanceNumber;
QString blockServerName; QString blockServerName;
SingleApplication::Options options; SingleApplication::Options options;
public Q_SLOTS: public Q_SLOTS:
void slotConnectionEstablished(); void slotConnectionEstablished();
void slotDataAvailable(QLocalSocket*, quint32); void slotDataAvailable(QLocalSocket*, quint32);
void slotClientConnectionClosed(QLocalSocket*, quint32); void slotClientConnectionClosed(QLocalSocket*, quint32);
}; };
#endif // SINGLEAPPLICATION_P_H #endif // SINGLEAPPLICATION_P_H

View File

@@ -25,38 +25,32 @@ CommandArgument::CommandArgument(const QString& name,
, m_description(description) , m_description(description)
{} {}
void void CommandArgument::setName(const QString& name)
CommandArgument::setName(const QString& name)
{ {
m_name = name; m_name = name;
} }
QString QString CommandArgument::name() const
CommandArgument::name() const
{ {
return m_name; return m_name;
} }
void void CommandArgument::setDescription(const QString& description)
CommandArgument::setDescription(const QString& description)
{ {
m_description = description; m_description = description;
} }
QString QString CommandArgument::description() const
CommandArgument::description() const
{ {
return m_description; return m_description;
} }
bool bool CommandArgument::isRoot() const
CommandArgument::isRoot() const
{ {
return m_name.isEmpty() && m_description.isEmpty(); return m_name.isEmpty() && m_description.isEmpty();
} }
bool bool CommandArgument::operator==(const CommandArgument& arg) const
CommandArgument::operator==(const CommandArgument& arg) const
{ {
return m_description == arg.m_description && m_name == arg.m_name; return m_description == arg.m_description && m_name == arg.m_name;
} }

View File

@@ -22,20 +22,20 @@
class CommandArgument class CommandArgument
{ {
public: public:
CommandArgument(); CommandArgument();
explicit CommandArgument(const QString& name, const QString& description); explicit CommandArgument(const QString& name, const QString& description);
void setName(const QString& name); void setName(const QString& name);
QString name() const; QString name() const;
void setDescription(const QString& description); void setDescription(const QString& description);
QString description() const; QString description() const;
bool isRoot() const; bool isRoot() const;
bool operator==(const CommandArgument& arg) const; bool operator==(const CommandArgument& arg) const;
private: private:
QString m_name; QString m_name;
QString m_description; QString m_description;
}; };

View File

@@ -34,399 +34,386 @@ auto versionOption =
auto helpOption = auto helpOption =
CommandOption({ "h", "help" }, QStringLiteral("Displays this help")); CommandOption({ "h", "help" }, QStringLiteral("Displays this help"));
QString QString optionsToString(const QList<CommandOption>& options,
optionsToString(const QList<CommandOption>& options, const QList<CommandArgument>& arguments)
const QList<CommandArgument>& arguments)
{ {
int size = 0; // track the largest size int size = 0; // track the largest size
QStringList dashedOptionList; QStringList dashedOptionList;
// save the dashed options and its size in order to print the description // save the dashed options and its size in order to print the description
// of every option at the same horizontal character position. // of every option at the same horizontal character position.
for (auto const& option : options) { for (auto const& option : options) {
QStringList dashedOptions = option.dashedNames(); QStringList dashedOptions = option.dashedNames();
QString joinedDashedOptions = dashedOptions.join(QStringLiteral(", ")); QString joinedDashedOptions = dashedOptions.join(QStringLiteral(", "));
if (!option.valueName().isEmpty()) { if (!option.valueName().isEmpty()) {
joinedDashedOptions += QStringLiteral(" <%1>").arg(option.valueName()); joinedDashedOptions +=
QStringLiteral(" <%1>").arg(option.valueName());
}
if (joinedDashedOptions.length() > size) {
size = joinedDashedOptions.length();
}
dashedOptionList << joinedDashedOptions;
} }
if (joinedDashedOptions.length() > size) { // check the length of the arguments
size = joinedDashedOptions.length(); for (auto const& arg : arguments) {
if (arg.name().length() > size)
size = arg.name().length();
} }
dashedOptionList << joinedDashedOptions; // generate the text
} QString result;
// check the length of the arguments if (!dashedOptionList.isEmpty()) {
for (auto const& arg : arguments) { result += QObject::tr("Options") + ":\n";
if (arg.name().length() > size) QString linePadding =
size = arg.name().length(); QStringLiteral(" ").repeated(size + 4).prepend("\n");
} for (int i = 0; i < options.length(); ++i) {
// generate the text result += QStringLiteral(" %1 %2\n")
QString result; .arg(dashedOptionList.at(i).leftJustified(size, ' '))
if (!dashedOptionList.isEmpty()) { .arg(options.at(i).description().replace(
result += QObject::tr("Options") + ":\n"; QLatin1String("\n"), linePadding));
QString linePadding = QStringLiteral(" ").repeated(size + 4).prepend("\n"); }
for (int i = 0; i < options.length(); ++i) { if (!arguments.isEmpty()) {
result += QStringLiteral(" %1 %2\n") result += QLatin1String("\n");
.arg(dashedOptionList.at(i).leftJustified(size, ' ')) }
.arg(options.at(i).description().replace(QLatin1String("\n"),
linePadding));
} }
if (!arguments.isEmpty()) { if (!arguments.isEmpty()) {
result += QLatin1String("\n"); result += QObject::tr("Arguments") + ":\n";
} }
} for (int i = 0; i < arguments.length(); ++i) {
if (!arguments.isEmpty()) { result += QStringLiteral(" %1 %2\n")
result += QObject::tr("Arguments") + ":\n"; .arg(arguments.at(i).name().leftJustified(size, ' '))
} .arg(arguments.at(i).description());
for (int i = 0; i < arguments.length(); ++i) { }
result += QStringLiteral(" %1 %2\n") return result;
.arg(arguments.at(i).name().leftJustified(size, ' '))
.arg(arguments.at(i).description());
}
return result;
} }
} // unnamed namespace } // unnamed namespace
bool bool CommandLineParser::processArgs(const QStringList& args,
CommandLineParser::processArgs(const QStringList& args, QStringList::const_iterator& actualIt,
QStringList::const_iterator& actualIt, Node*& actualNode)
Node*& actualNode)
{ {
QString argument = *actualIt; QString argument = *actualIt;
bool ok = true; bool ok = true;
bool isValidArg = false; bool isValidArg = false;
for (Node& n : actualNode->subNodes) { for (Node& n : actualNode->subNodes) {
if (n.argument.name() == argument) { if (n.argument.name() == argument) {
actualNode = &n; actualNode = &n;
isValidArg = true; isValidArg = true;
break; break;
}
} }
} if (isValidArg) {
if (isValidArg) { auto nextArg = actualNode->argument;
auto nextArg = actualNode->argument; m_foundArgs.append(nextArg);
m_foundArgs.append(nextArg); // check next is help
// check next is help ++actualIt;
++actualIt; ok = processIfOptionIsHelp(args, actualIt, actualNode);
ok = processIfOptionIsHelp(args, actualIt, actualNode); --actualIt;
--actualIt; } else {
} else { ok = false;
ok = false; out << QStringLiteral("'%1' is not a valid argument.").arg(argument);
out << QStringLiteral("'%1' is not a valid argument.").arg(argument); }
} return ok;
return ok;
} }
bool bool CommandLineParser::processOptions(const QStringList& args,
CommandLineParser::processOptions(const QStringList& args, QStringList::const_iterator& actualIt,
QStringList::const_iterator& actualIt, Node* const actualNode)
Node* const actualNode)
{ {
QString arg = *actualIt; QString arg = *actualIt;
bool ok = true; bool ok = true;
// track values // track values
int equalsPos = arg.indexOf(QLatin1String("=")); int equalsPos = arg.indexOf(QLatin1String("="));
QString valueStr; QString valueStr;
if (equalsPos != -1) { if (equalsPos != -1) {
valueStr = arg.mid(equalsPos + 1); // right valueStr = arg.mid(equalsPos + 1); // right
arg = arg.mid(0, equalsPos); // left arg = arg.mid(0, equalsPos); // left
}
// check format -x --xx...
bool isDoubleDashed = arg.startsWith(QLatin1String("--"));
ok = isDoubleDashed ? arg.length() > 3 : arg.length() == 2;
if (!ok) {
out << QStringLiteral("the option %1 has a wrong format.").arg(arg);
return ok;
}
arg = isDoubleDashed ? arg.remove(0, 2) : arg.remove(0, 1);
// get option
auto endIt = actualNode->options.cend();
auto optionIt = endIt;
for (auto i = actualNode->options.cbegin(); i != endIt; ++i) {
if ((*i).names().contains(arg)) {
optionIt = i;
break;
} }
} // check format -x --xx...
if (optionIt == endIt) { bool isDoubleDashed = arg.startsWith(QLatin1String("--"));
QString argName = actualNode->argument.name(); ok = isDoubleDashed ? arg.length() > 3 : arg.length() == 2;
if (argName.isEmpty()) {
argName = qApp->applicationName();
}
out << QStringLiteral("the option '%1' is not a valid option "
"for the argument '%2'.")
.arg(arg)
.arg(argName);
ok = false;
return ok;
}
// check presence of values
CommandOption option = *optionIt;
bool requiresValue = !(option.valueName().isEmpty());
if (!requiresValue && equalsPos != -1) {
out << QStringLiteral("the option '%1' contains a '=' and it doesn't "
"require a value.")
.arg(arg);
ok = false;
return ok;
} else if (requiresValue && valueStr.isEmpty()) {
// find in the next
if (actualIt + 1 != args.cend()) {
++actualIt;
} else {
out << QStringLiteral("Expected value after the option '%1'.").arg(arg);
ok = false;
return ok;
}
valueStr = *actualIt;
}
// check the value correctness
if (requiresValue) {
ok = option.checkValue(valueStr);
if (!ok) { if (!ok) {
QString err = option.errorMsg(); out << QStringLiteral("the option %1 has a wrong format.").arg(arg);
if (!err.endsWith(QLatin1String("."))) return ok;
err += QLatin1String(".");
out << err;
return ok;
} }
option.setValue(valueStr); arg = isDoubleDashed ? arg.remove(0, 2) : arg.remove(0, 1);
} // get option
m_foundOptions.append(option); auto endIt = actualNode->options.cend();
return ok; auto optionIt = endIt;
for (auto i = actualNode->options.cbegin(); i != endIt; ++i) {
if ((*i).names().contains(arg)) {
optionIt = i;
break;
}
}
if (optionIt == endIt) {
QString argName = actualNode->argument.name();
if (argName.isEmpty()) {
argName = qApp->applicationName();
}
out << QStringLiteral("the option '%1' is not a valid option "
"for the argument '%2'.")
.arg(arg)
.arg(argName);
ok = false;
return ok;
}
// check presence of values
CommandOption option = *optionIt;
bool requiresValue = !(option.valueName().isEmpty());
if (!requiresValue && equalsPos != -1) {
out << QStringLiteral("the option '%1' contains a '=' and it doesn't "
"require a value.")
.arg(arg);
ok = false;
return ok;
} else if (requiresValue && valueStr.isEmpty()) {
// find in the next
if (actualIt + 1 != args.cend()) {
++actualIt;
} else {
out << QStringLiteral("Expected value after the option '%1'.")
.arg(arg);
ok = false;
return ok;
}
valueStr = *actualIt;
}
// check the value correctness
if (requiresValue) {
ok = option.checkValue(valueStr);
if (!ok) {
QString err = option.errorMsg();
if (!err.endsWith(QLatin1String(".")))
err += QLatin1String(".");
out << err;
return ok;
}
option.setValue(valueStr);
}
m_foundOptions.append(option);
return ok;
} }
bool bool CommandLineParser::parse(const QStringList& args)
CommandLineParser::parse(const QStringList& args)
{ {
m_foundArgs.clear(); m_foundArgs.clear();
m_foundOptions.clear(); m_foundOptions.clear();
bool ok = true; bool ok = true;
Node* actualNode = &m_parseTree; Node* actualNode = &m_parseTree;
auto it = ++args.cbegin(); auto it = ++args.cbegin();
// check version option // check version option
QStringList dashedVersion = versionOption.dashedNames(); QStringList dashedVersion = versionOption.dashedNames();
if (m_withVersion && args.length() > 1 && if (m_withVersion && args.length() > 1 &&
dashedVersion.contains(args.at(1))) { dashedVersion.contains(args.at(1))) {
if (args.length() == 2) { if (args.length() == 2) {
printVersion(); printVersion();
m_foundOptions << versionOption; m_foundOptions << versionOption;
} else { } else {
out << "Invalid arguments after the version option."; out << "Invalid arguments after the version option.";
ok = false; ok = false;
}
return ok;
}
// check help option
ok = processIfOptionIsHelp(args, it, actualNode);
// process the other args
for (; it != args.cend() && ok; ++it) {
const QString& value = *it;
if (value.startsWith(QLatin1String("-"))) {
ok = processOptions(args, it, actualNode);
} else {
ok = processArgs(args, it, actualNode);
}
}
if (!ok && !m_generalErrorMessage.isEmpty()) {
out << QStringLiteral(" %1\n").arg(m_generalErrorMessage);
} }
return ok; return ok;
} }
// check help option
ok = processIfOptionIsHelp(args, it, actualNode);
// process the other args
for (; it != args.cend() && ok; ++it) {
const QString& value = *it;
if (value.startsWith(QLatin1String("-"))) {
ok = processOptions(args, it, actualNode);
CommandOption CommandLineParser::addVersionOption()
{
m_withVersion = true;
return versionOption;
}
CommandOption CommandLineParser::addHelpOption()
{
m_withHelp = true;
return helpOption;
}
bool CommandLineParser::AddArgument(const CommandArgument& arg,
const CommandArgument& parent)
{
bool res = true;
Node* n = findParent(parent);
if (n == nullptr) {
res = false;
} else { } else {
ok = processArgs(args, it, actualNode); Node child;
child.argument = arg;
n->subNodes.append(child);
} }
} return res;
if (!ok && !m_generalErrorMessage.isEmpty()) {
out << QStringLiteral(" %1\n").arg(m_generalErrorMessage);
}
return ok;
} }
CommandOption bool CommandLineParser::AddOption(const CommandOption& option,
CommandLineParser::addVersionOption() const CommandArgument& parent)
{ {
m_withVersion = true; bool res = true;
return versionOption; Node* n = findParent(parent);
} if (n == nullptr) {
res = false;
CommandOption } else {
CommandLineParser::addHelpOption() n->options.append(option);
{
m_withHelp = true;
return helpOption;
}
bool
CommandLineParser::AddArgument(const CommandArgument& arg,
const CommandArgument& parent)
{
bool res = true;
Node* n = findParent(parent);
if (n == nullptr) {
res = false;
} else {
Node child;
child.argument = arg;
n->subNodes.append(child);
}
return res;
}
bool
CommandLineParser::AddOption(const CommandOption& option,
const CommandArgument& parent)
{
bool res = true;
Node* n = findParent(parent);
if (n == nullptr) {
res = false;
} else {
n->options.append(option);
}
return res;
}
bool
CommandLineParser::AddOptions(const QList<CommandOption>& options,
const CommandArgument& parent)
{
bool res = true;
for (auto const& option : options) {
if (!AddOption(option, parent)) {
res = false;
break;
} }
} return res;
return res;
} }
void bool CommandLineParser::AddOptions(const QList<CommandOption>& options,
CommandLineParser::setGeneralErrorMessage(const QString& msg) const CommandArgument& parent)
{ {
m_generalErrorMessage = msg; bool res = true;
} for (auto const& option : options) {
if (!AddOption(option, parent)) {
void res = false;
CommandLineParser::setDescription(const QString& description) break;
{ }
m_description = description;
}
bool
CommandLineParser::isSet(const CommandArgument& arg) const
{
return m_foundArgs.contains(arg);
}
bool
CommandLineParser::isSet(const CommandOption& option) const
{
return m_foundOptions.contains(option);
}
QString
CommandLineParser::value(const CommandOption& option) const
{
QString value = option.value();
for (const CommandOption& fOption : m_foundOptions) {
if (option == fOption) {
value = fOption.value();
break;
} }
} return res;
return value;
} }
void void CommandLineParser::setGeneralErrorMessage(const QString& msg)
CommandLineParser::printVersion()
{ {
out << "Flameshot " << qApp->applicationVersion() << "\nCompiled with Qt " m_generalErrorMessage = msg;
<< static_cast<QString>(QT_VERSION_STR) << "\n";
} }
void void CommandLineParser::setDescription(const QString& description)
CommandLineParser::printHelp(QStringList args, const Node* node)
{ {
args.removeLast(); // remove the help, it's always the last m_description = description;
QString helpText; }
// add usage info bool CommandLineParser::isSet(const CommandArgument& arg) const
QString argName = node->argument.name(); {
if (argName.isEmpty()) { return m_foundArgs.contains(arg);
argName = qApp->applicationName(); }
}
QString argText =
node->subNodes.isEmpty() ? "" : "[" + QObject::tr("arguments") + "]";
helpText += QObject::tr("Usage") + ": %1 [%2-" + QObject::tr("options") +
QStringLiteral("] %3\n\n")
.arg(args.join(QStringLiteral(" ")))
.arg(argName)
.arg(argText);
// short section about default behavior bool CommandLineParser::isSet(const CommandOption& option) const
helpText += QObject::tr("Per default runs Flameshot in the background and \ {
return m_foundOptions.contains(option);
}
QString CommandLineParser::value(const CommandOption& option) const
{
QString value = option.value();
for (const CommandOption& fOption : m_foundOptions) {
if (option == fOption) {
value = fOption.value();
break;
}
}
return value;
}
void CommandLineParser::printVersion()
{
out << "Flameshot " << qApp->applicationVersion() << "\nCompiled with Qt "
<< static_cast<QString>(QT_VERSION_STR) << "\n";
}
void CommandLineParser::printHelp(QStringList args, const Node* node)
{
args.removeLast(); // remove the help, it's always the last
QString helpText;
// add usage info
QString argName = node->argument.name();
if (argName.isEmpty()) {
argName = qApp->applicationName();
}
QString argText =
node->subNodes.isEmpty() ? "" : "[" + QObject::tr("arguments") + "]";
helpText += QObject::tr("Usage") + ": %1 [%2-" + QObject::tr("options") +
QStringLiteral("] %3\n\n")
.arg(args.join(QStringLiteral(" ")))
.arg(argName)
.arg(argText);
// short section about default behavior
helpText += QObject::tr("Per default runs Flameshot in the background and \
adds a tray icon for configuration."); adds a tray icon for configuration.");
helpText += "\n\n"; helpText += "\n\n";
// add command options and subarguments // add command options and subarguments
QList<CommandArgument> subArgs; QList<CommandArgument> subArgs;
for (const Node& n : node->subNodes) for (const Node& n : node->subNodes)
subArgs.append(n.argument); subArgs.append(n.argument);
auto modifiedOptions = node->options; auto modifiedOptions = node->options;
if (m_withHelp) if (m_withHelp)
modifiedOptions << helpOption; modifiedOptions << helpOption;
if (m_withVersion && node == &m_parseTree) { if (m_withVersion && node == &m_parseTree) {
modifiedOptions << versionOption; modifiedOptions << versionOption;
}
helpText += optionsToString(modifiedOptions, subArgs);
// print it
out << helpText;
}
CommandLineParser::Node*
CommandLineParser::findParent(const CommandArgument& parent)
{
if (parent == CommandArgument()) {
return &m_parseTree;
}
// find the parent in the subNodes recursively
Node* res = nullptr;
for (auto i = m_parseTree.subNodes.begin(); i != m_parseTree.subNodes.end();
++i) {
res = recursiveParentSearch(parent, *i);
if (res != nullptr) {
break;
} }
} helpText += optionsToString(modifiedOptions, subArgs);
return res; // print it
out << helpText;
} }
CommandLineParser::Node* CommandLineParser::Node* CommandLineParser::findParent(
CommandLineParser::recursiveParentSearch(const CommandArgument& parent, const CommandArgument& parent)
Node& node) const
{ {
Node* res = nullptr; if (parent == CommandArgument()) {
if (node.argument == parent) { return &m_parseTree;
res = &node;
} else {
for (auto i = node.subNodes.begin(); i != node.subNodes.end(); ++i) {
res = recursiveParentSearch(parent, *i);
if (res != nullptr) {
break;
}
} }
} // find the parent in the subNodes recursively
return res; Node* res = nullptr;
for (auto i = m_parseTree.subNodes.begin(); i != m_parseTree.subNodes.end();
++i) {
res = recursiveParentSearch(parent, *i);
if (res != nullptr) {
break;
}
}
return res;
} }
bool CommandLineParser::Node* CommandLineParser::recursiveParentSearch(
CommandLineParser::processIfOptionIsHelp(const QStringList& args, const CommandArgument& parent,
QStringList::const_iterator& actualIt, Node& node) const
Node*& actualNode)
{ {
bool ok = true; Node* res = nullptr;
auto dashedHelpNames = helpOption.dashedNames(); if (node.argument == parent) {
if (m_withHelp && actualIt != args.cend() && res = &node;
dashedHelpNames.contains(*actualIt)) {
if (actualIt + 1 == args.cend()) {
m_foundOptions << helpOption;
printHelp(args, actualNode);
actualIt++;
} else { } else {
out << "Invalid arguments after the help option."; for (auto i = node.subNodes.begin(); i != node.subNodes.end(); ++i) {
ok = false; res = recursiveParentSearch(parent, *i);
if (res != nullptr) {
break;
}
}
} }
} return res;
return ok; }
bool CommandLineParser::processIfOptionIsHelp(
const QStringList& args,
QStringList::const_iterator& actualIt,
Node*& actualNode)
{
bool ok = true;
auto dashedHelpNames = helpOption.dashedNames();
if (m_withHelp && actualIt != args.cend() &&
dashedHelpNames.contains(*actualIt)) {
if (actualIt + 1 == args.cend()) {
m_foundOptions << helpOption;
printHelp(args, actualNode);
actualIt++;
} else {
out << "Invalid arguments after the help option.";
ok = false;
}
}
return ok;
} }

View File

@@ -24,69 +24,70 @@
class CommandLineParser class CommandLineParser
{ {
public: public:
CommandLineParser(); CommandLineParser();
bool parse(const QStringList& args); bool parse(const QStringList& args);
CommandArgument rootArgument() const { return CommandArgument(); } CommandArgument rootArgument() const { return CommandArgument(); }
CommandOption addVersionOption(); CommandOption addVersionOption();
CommandOption addHelpOption(); CommandOption addHelpOption();
bool AddArgument(const CommandArgument& arg, bool AddArgument(const CommandArgument& arg,
const CommandArgument& parent = CommandArgument());
bool AddOption(const CommandOption& option,
const CommandArgument& parent = CommandArgument()); const CommandArgument& parent = CommandArgument());
bool AddOption(const CommandOption& option, bool AddOptions(const QList<CommandOption>& options,
const CommandArgument& parent = CommandArgument()); const CommandArgument& parent = CommandArgument());
bool AddOptions(const QList<CommandOption>& options, void setGeneralErrorMessage(const QString& msg);
const CommandArgument& parent = CommandArgument()); void setDescription(const QString& description);
void setGeneralErrorMessage(const QString& msg); bool isSet(const CommandArgument& arg) const;
void setDescription(const QString& description); bool isSet(const CommandOption& option) const;
QString value(const CommandOption& option) const;
bool isSet(const CommandArgument& arg) const;
bool isSet(const CommandOption& option) const;
QString value(const CommandOption& option) const;
private: private:
bool m_withHelp = false; bool m_withHelp = false;
bool m_withVersion = false; bool m_withVersion = false;
QString m_description; QString m_description;
QString m_generalErrorMessage; QString m_generalErrorMessage;
struct Node struct Node
{
explicit Node(const CommandArgument& arg)
: argument(arg)
{}
Node() {}
bool operator==(const Node& n) const
{ {
return argument == n.argument && options == n.options && explicit Node(const CommandArgument& arg)
subNodes == n.subNodes; : argument(arg)
} {}
CommandArgument argument; Node() {}
QList<CommandOption> options; bool operator==(const Node& n) const
QList<Node> subNodes; {
}; return argument == n.argument && options == n.options &&
subNodes == n.subNodes;
}
CommandArgument argument;
QList<CommandOption> options;
QList<Node> subNodes;
};
Node m_parseTree; Node m_parseTree;
QList<CommandOption> m_foundOptions; QList<CommandOption> m_foundOptions;
QList<CommandArgument> m_foundArgs; QList<CommandArgument> m_foundArgs;
// helper functions // helper functions
void printVersion(); void printVersion();
void printHelp(QStringList args, const Node* node); void printHelp(QStringList args, const Node* node);
Node* findParent(const CommandArgument& parent); Node* findParent(const CommandArgument& parent);
Node* recursiveParentSearch(const CommandArgument& parent, Node& node) const; Node* recursiveParentSearch(const CommandArgument& parent,
bool processIfOptionIsHelp(const QStringList& args, Node& node) const;
QStringList::const_iterator& actualIt, bool processIfOptionIsHelp(const QStringList& args,
Node*& actualNode); QStringList::const_iterator& actualIt,
bool processArgs(const QStringList& args, Node*& actualNode);
QStringList::const_iterator& actualIt, bool processArgs(const QStringList& args,
Node*& actualNode); QStringList::const_iterator& actualIt,
bool processOptions(const QStringList& args, Node*& actualNode);
QStringList::const_iterator& actualIt, bool processOptions(const QStringList& args,
Node* const actualNode); QStringList::const_iterator& actualIt,
Node* const actualNode);
}; };

View File

@@ -26,7 +26,7 @@ CommandOption::CommandOption(const QString& name,
, m_valueName(valueName) , m_valueName(valueName)
, m_value(defaultValue) , m_value(defaultValue)
{ {
m_checker = [](QString const&) { return true; }; m_checker = [](QString const&) { return true; };
} }
CommandOption::CommandOption(const QStringList& names, CommandOption::CommandOption(const QStringList& names,
@@ -38,103 +38,89 @@ CommandOption::CommandOption(const QStringList& names,
, m_valueName(valueName) , m_valueName(valueName)
, m_value(defaultValue) , m_value(defaultValue)
{ {
m_checker = [](QString const&) -> bool { return true; }; m_checker = [](QString const&) -> bool { return true; };
} }
void void CommandOption::setName(const QString& name)
CommandOption::setName(const QString& name)
{ {
m_names = QStringList() << name; m_names = QStringList() << name;
} }
void void CommandOption::setNames(const QStringList& names)
CommandOption::setNames(const QStringList& names)
{ {
m_names = names; m_names = names;
} }
QStringList QStringList CommandOption::names() const
CommandOption::names() const
{ {
return m_names; return m_names;
} }
QStringList QStringList CommandOption::dashedNames() const
CommandOption::dashedNames() const
{ {
QStringList dashedNames; QStringList dashedNames;
for (const QString& name : m_names) { for (const QString& name : m_names) {
// prepend "-" to single character options, and "--" to the others // prepend "-" to single character options, and "--" to the others
QString dashedName = (name.length() == 1) QString dashedName = (name.length() == 1)
? QStringLiteral("-%1").arg(name) ? QStringLiteral("-%1").arg(name)
: QStringLiteral("--%1").arg(name); : QStringLiteral("--%1").arg(name);
dashedNames << dashedName; dashedNames << dashedName;
} }
return dashedNames; return dashedNames;
} }
void void CommandOption::setValueName(const QString& name)
CommandOption::setValueName(const QString& name)
{ {
m_valueName = name; m_valueName = name;
} }
QString QString CommandOption::valueName() const
CommandOption::valueName() const
{ {
return m_valueName; return m_valueName;
} }
void void CommandOption::setValue(const QString& value)
CommandOption::setValue(const QString& value)
{ {
if (m_valueName.isEmpty()) { if (m_valueName.isEmpty()) {
m_valueName = QLatin1String("value"); m_valueName = QLatin1String("value");
} }
m_value = value; m_value = value;
} }
QString QString CommandOption::value() const
CommandOption::value() const
{ {
return m_value; return m_value;
} }
void void CommandOption::addChecker(const function<bool(const QString&)> checker,
CommandOption::addChecker(const function<bool(const QString&)> checker, const QString& errMsg)
const QString& errMsg)
{ {
m_checker = checker; m_checker = checker;
m_errorMsg = errMsg; m_errorMsg = errMsg;
} }
bool bool CommandOption::checkValue(const QString& value) const
CommandOption::checkValue(const QString& value) const
{ {
return m_checker(value); return m_checker(value);
} }
QString QString CommandOption::description() const
CommandOption::description() const
{ {
return m_description; return m_description;
} }
void void CommandOption::setDescription(const QString& description)
CommandOption::setDescription(const QString& description)
{ {
m_description = description; m_description = description;
} }
QString QString CommandOption::errorMsg() const
CommandOption::errorMsg() const
{ {
return m_errorMsg; return m_errorMsg;
} }
bool bool CommandOption::operator==(const CommandOption& option) const
CommandOption::operator==(const CommandOption& option) const
{ {
return m_description == option.m_description && m_names == option.m_names && return m_description == option.m_description && m_names == option.m_names &&
m_valueName == option.m_valueName; m_valueName == option.m_valueName;
} }

View File

@@ -25,44 +25,44 @@ using std::function;
class CommandOption class CommandOption
{ {
public: public:
CommandOption(const QString& name, CommandOption(const QString& name,
const QString& description, const QString& description,
const QString& valueName = QString(), const QString& valueName = QString(),
const QString& defaultValue = QString()); const QString& defaultValue = QString());
CommandOption(const QStringList& names, CommandOption(const QStringList& names,
const QString& description, const QString& description,
const QString& valueName = QString(), const QString& valueName = QString(),
const QString& defaultValue = QString()); const QString& defaultValue = QString());
void setName(const QString& name); void setName(const QString& name);
void setNames(const QStringList& names); void setNames(const QStringList& names);
QStringList names() const; QStringList names() const;
QStringList dashedNames() const; QStringList dashedNames() const;
void setValueName(const QString& name); void setValueName(const QString& name);
QString valueName() const; QString valueName() const;
void setValue(const QString& value); void setValue(const QString& value);
QString value() const; QString value() const;
void addChecker(const function<bool(QString const&)> checker, void addChecker(const function<bool(QString const&)> checker,
const QString& errMsg); const QString& errMsg);
bool checkValue(const QString& value) const; bool checkValue(const QString& value) const;
QString description() const; QString description() const;
void setDescription(const QString& description); void setDescription(const QString& description);
QString errorMsg() const; QString errorMsg() const;
bool operator==(const CommandOption& option) const; bool operator==(const CommandOption& option) const;
private: private:
QStringList m_names; QStringList m_names;
QString m_description; QString m_description;
QString m_valueName; QString m_valueName;
QString m_value; QString m_value;
function<bool(QString const&)> m_checker; function<bool(QString const&)> m_checker;
QString m_errorMsg; QString m_errorMsg;
}; };

View File

@@ -24,94 +24,90 @@
ButtonListView::ButtonListView(QWidget* parent) ButtonListView::ButtonListView(QWidget* parent)
: QListWidget(parent) : QListWidget(parent)
{ {
setMouseTracking(true); setMouseTracking(true);
setFlow(QListWidget::TopToBottom); setFlow(QListWidget::TopToBottom);
initButtonList(); initButtonList();
updateComponents(); updateComponents();
connect( connect(
this, &QListWidget::itemClicked, this, &ButtonListView::reverseItemCheck); this, &QListWidget::itemClicked, this, &ButtonListView::reverseItemCheck);
} }
void void ButtonListView::initButtonList()
ButtonListView::initButtonList()
{ {
ToolFactory factory; ToolFactory factory;
auto listTypes = CaptureToolButton::getIterableButtonTypes(); auto listTypes = CaptureToolButton::getIterableButtonTypes();
for (const CaptureToolButton::ButtonType t : listTypes) { for (const CaptureToolButton::ButtonType t : listTypes) {
CaptureTool* tool = factory.CreateTool(t); CaptureTool* tool = factory.CreateTool(t);
// add element to the local map // add element to the local map
m_buttonTypeByName.insert(tool->name(), t); m_buttonTypeByName.insert(tool->name(), t);
// init the menu option // init the menu option
QListWidgetItem* m_buttonItem = new QListWidgetItem(this); QListWidgetItem* m_buttonItem = new QListWidgetItem(this);
// when the background is lighter than gray, it uses the white icons // when the background is lighter than gray, it uses the white icons
QColor bgColor = this->palette().color(QWidget::backgroundRole()); QColor bgColor = this->palette().color(QWidget::backgroundRole());
m_buttonItem->setIcon(tool->icon(bgColor, false)); m_buttonItem->setIcon(tool->icon(bgColor, false));
m_buttonItem->setFlags(Qt::ItemIsUserCheckable); m_buttonItem->setFlags(Qt::ItemIsUserCheckable);
QColor foregroundColor = this->palette().color(QWidget::foregroundRole()); QColor foregroundColor =
m_buttonItem->setForeground(foregroundColor); this->palette().color(QWidget::foregroundRole());
m_buttonItem->setForeground(foregroundColor);
m_buttonItem->setText(tool->name()); m_buttonItem->setText(tool->name());
m_buttonItem->setToolTip(tool->description()); m_buttonItem->setToolTip(tool->description());
tool->deleteLater(); tool->deleteLater();
} }
} }
void void ButtonListView::updateActiveButtons(QListWidgetItem* item)
ButtonListView::updateActiveButtons(QListWidgetItem* item) {
{ CaptureToolButton::ButtonType bType = m_buttonTypeByName[item->text()];
CaptureToolButton::ButtonType bType = m_buttonTypeByName[item->text()]; if (item->checkState() == Qt::Checked) {
if (item->checkState() == Qt::Checked) { m_listButtons.append(bType);
m_listButtons.append(bType); // TODO refactor so we don't need external sorts
// TODO refactor so we don't need external sorts using bt = CaptureToolButton::ButtonType;
using bt = CaptureToolButton::ButtonType; std::sort(m_listButtons.begin(), m_listButtons.end(), [](bt a, bt b) {
std::sort(m_listButtons.begin(), m_listButtons.end(), [](bt a, bt b) { return CaptureToolButton::getPriorityByButton(a) <
return CaptureToolButton::getPriorityByButton(a) < CaptureToolButton::getPriorityByButton(b);
CaptureToolButton::getPriorityByButton(b); });
}); } else {
} else { m_listButtons.remove(m_listButtons.indexOf(bType));
m_listButtons.remove(m_listButtons.indexOf(bType)); }
} ConfigHandler().setButtons(m_listButtons);
ConfigHandler().setButtons(m_listButtons); }
}
void ButtonListView::reverseItemCheck(QListWidgetItem* item)
void {
ButtonListView::reverseItemCheck(QListWidgetItem* item) if (item->checkState() == Qt::Checked) {
{ item->setCheckState(Qt::Unchecked);
if (item->checkState() == Qt::Checked) { } else {
item->setCheckState(Qt::Unchecked); item->setCheckState(Qt::Checked);
} else { }
item->setCheckState(Qt::Checked); updateActiveButtons(item);
} }
updateActiveButtons(item);
} void ButtonListView::selectAll()
{
void ConfigHandler().setAllTheButtons();
ButtonListView::selectAll() for (int i = 0; i < this->count(); ++i) {
{ QListWidgetItem* item = this->item(i);
ConfigHandler().setAllTheButtons(); item->setCheckState(Qt::Checked);
for (int i = 0; i < this->count(); ++i) { }
QListWidgetItem* item = this->item(i); }
item->setCheckState(Qt::Checked);
} void ButtonListView::updateComponents()
} {
m_listButtons = ConfigHandler().getButtons();
void auto listTypes = CaptureToolButton::getIterableButtonTypes();
ButtonListView::updateComponents() for (int i = 0; i < this->count(); ++i) {
{ QListWidgetItem* item = this->item(i);
m_listButtons = ConfigHandler().getButtons(); auto elem = static_cast<CaptureToolButton::ButtonType>(listTypes.at(i));
auto listTypes = CaptureToolButton::getIterableButtonTypes(); if (m_listButtons.contains(elem)) {
for (int i = 0; i < this->count(); ++i) { item->setCheckState(Qt::Checked);
QListWidgetItem* item = this->item(i); } else {
auto elem = static_cast<CaptureToolButton::ButtonType>(listTypes.at(i)); item->setCheckState(Qt::Unchecked);
if (m_listButtons.contains(elem)) { }
item->setCheckState(Qt::Checked);
} else {
item->setCheckState(Qt::Unchecked);
} }
}
} }

View File

@@ -23,21 +23,21 @@
class ButtonListView : public QListWidget class ButtonListView : public QListWidget
{ {
public: public:
explicit ButtonListView(QWidget* parent = nullptr); explicit ButtonListView(QWidget* parent = nullptr);
public slots: public slots:
void selectAll(); void selectAll();
void updateComponents(); void updateComponents();
private slots: private slots:
void reverseItemCheck(QListWidgetItem*); void reverseItemCheck(QListWidgetItem*);
protected: protected:
void initButtonList(); void initButtonList();
private: private:
QVector<CaptureToolButton::ButtonType> m_listButtons; QVector<CaptureToolButton::ButtonType> m_listButtons;
QMap<QString, CaptureToolButton::ButtonType> m_buttonTypeByName; QMap<QString, CaptureToolButton::ButtonType> m_buttonTypeByName;
void updateActiveButtons(QListWidgetItem*); void updateActiveButtons(QListWidgetItem*);
}; };

View File

@@ -24,11 +24,10 @@ ClickableLabel::ClickableLabel(QWidget* parent)
ClickableLabel::ClickableLabel(QString s, QWidget* parent) ClickableLabel::ClickableLabel(QString s, QWidget* parent)
: QLabel(parent) : QLabel(parent)
{ {
setText(s); setText(s);
} }
void void ClickableLabel::mousePressEvent(QMouseEvent*)
ClickableLabel::mousePressEvent(QMouseEvent*)
{ {
emit clicked(); emit clicked();
} }

View File

@@ -21,14 +21,14 @@
class ClickableLabel : public QLabel class ClickableLabel : public QLabel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ClickableLabel(QWidget* parent = nullptr); explicit ClickableLabel(QWidget* parent = nullptr);
ClickableLabel(QString s, QWidget* parent = nullptr); ClickableLabel(QString s, QWidget* parent = nullptr);
signals: signals:
void clicked(); void clicked();
private: private:
void mousePressEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*);
}; };

View File

@@ -36,61 +36,61 @@
ConfigWindow::ConfigWindow(QWidget* parent) ConfigWindow::ConfigWindow(QWidget* parent)
: QTabWidget(parent) : QTabWidget(parent)
{ {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
const int size = GlobalValues::buttonBaseSize() * 12; const int size = GlobalValues::buttonBaseSize() * 12;
setMinimumSize(size, size); setMinimumSize(size, size);
setWindowIcon(QIcon(":img/app/flameshot.svg")); setWindowIcon(QIcon(":img/app/flameshot.svg"));
setWindowTitle(tr("Configuration")); setWindowTitle(tr("Configuration"));
auto changedSlot = [this](QString s) { auto changedSlot = [this](QString s) {
QStringList files = m_configWatcher->files(); QStringList files = m_configWatcher->files();
if (!files.contains(s)) { if (!files.contains(s)) {
this->m_configWatcher->addPath(s); this->m_configWatcher->addPath(s);
} }
emit updateChildren(); emit updateChildren();
}; };
m_configWatcher = new QFileSystemWatcher(this); m_configWatcher = new QFileSystemWatcher(this);
m_configWatcher->addPath(ConfigHandler().configFilePath()); m_configWatcher->addPath(ConfigHandler().configFilePath());
connect(m_configWatcher, &QFileSystemWatcher::fileChanged, this, changedSlot); connect(
m_configWatcher, &QFileSystemWatcher::fileChanged, this, changedSlot);
QColor background = this->palette().window().color(); QColor background = this->palette().window().color();
bool isDark = ColorUtils::colorIsDark(background); bool isDark = ColorUtils::colorIsDark(background);
QString modifier = QString modifier =
isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath();
// visuals // visuals
m_visuals = new VisualsEditor(); m_visuals = new VisualsEditor();
addTab(m_visuals, QIcon(modifier + "graphics.svg"), tr("Interface")); addTab(m_visuals, QIcon(modifier + "graphics.svg"), tr("Interface"));
// filename // filename
m_filenameEditor = new FileNameEditor(); m_filenameEditor = new FileNameEditor();
addTab(m_filenameEditor, addTab(m_filenameEditor,
QIcon(modifier + "name_edition.svg"), QIcon(modifier + "name_edition.svg"),
tr("Filename Editor")); tr("Filename Editor"));
// general // general
m_generalConfig = new GeneneralConf(); m_generalConfig = new GeneneralConf();
addTab(m_generalConfig, QIcon(modifier + "config.svg"), tr("General")); addTab(m_generalConfig, QIcon(modifier + "config.svg"), tr("General"));
// connect update sigslots // connect update sigslots
connect(this, connect(this,
&ConfigWindow::updateChildren, &ConfigWindow::updateChildren,
m_filenameEditor, m_filenameEditor,
&FileNameEditor::updateComponents); &FileNameEditor::updateComponents);
connect(this, connect(this,
&ConfigWindow::updateChildren, &ConfigWindow::updateChildren,
m_visuals, m_visuals,
&VisualsEditor::updateComponents); &VisualsEditor::updateComponents);
connect(this, connect(this,
&ConfigWindow::updateChildren, &ConfigWindow::updateChildren,
m_generalConfig, m_generalConfig,
&GeneneralConf::updateComponents); &GeneneralConf::updateComponents);
} }
void void ConfigWindow::keyPressEvent(QKeyEvent* e)
ConfigWindow::keyPressEvent(QKeyEvent* e)
{ {
if (e->key() == Qt::Key_Escape) { if (e->key() == Qt::Key_Escape) {
close(); close();
} }
} }

View File

@@ -26,19 +26,19 @@ class VisualsEditor;
class ConfigWindow : public QTabWidget class ConfigWindow : public QTabWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigWindow(QWidget* parent = nullptr); explicit ConfigWindow(QWidget* parent = nullptr);
signals: signals:
void updateChildren(); void updateChildren();
protected: protected:
void keyPressEvent(QKeyEvent*); void keyPressEvent(QKeyEvent*);
private: private:
FileNameEditor* m_filenameEditor; FileNameEditor* m_filenameEditor;
GeneneralConf* m_generalConfig; GeneneralConf* m_generalConfig;
VisualsEditor* m_visuals; VisualsEditor* m_visuals;
QFileSystemWatcher* m_configWatcher; QFileSystemWatcher* m_configWatcher;
}; };

View File

@@ -20,38 +20,37 @@
ExtendedSlider::ExtendedSlider(QWidget* parent) ExtendedSlider::ExtendedSlider(QWidget* parent)
: QSlider(parent) : QSlider(parent)
{ {
connect( connect(this,
this, &ExtendedSlider::valueChanged, this, &ExtendedSlider::updateTooltip); &ExtendedSlider::valueChanged,
connect(this, &ExtendedSlider::sliderMoved, this, &ExtendedSlider::fireTimer); this,
m_timer.setSingleShot(true); &ExtendedSlider::updateTooltip);
connect( connect(
&m_timer, &QTimer::timeout, this, &ExtendedSlider::modificationsEnded); this, &ExtendedSlider::sliderMoved, this, &ExtendedSlider::fireTimer);
m_timer.setSingleShot(true);
connect(
&m_timer, &QTimer::timeout, this, &ExtendedSlider::modificationsEnded);
} }
int int ExtendedSlider::mappedValue(int min, int max)
ExtendedSlider::mappedValue(int min, int max)
{ {
qreal progress = qreal progress =
((value() - minimum())) / static_cast<qreal>(maximum() - minimum()); ((value() - minimum())) / static_cast<qreal>(maximum() - minimum());
return min + (max - min) * progress; return min + (max - min) * progress;
} }
void void ExtendedSlider::setMapedValue(int min, int val, int max)
ExtendedSlider::setMapedValue(int min, int val, int max)
{ {
qreal progress = ((val - min) + 1) / static_cast<qreal>(max - min); qreal progress = ((val - min) + 1) / static_cast<qreal>(max - min);
int value = minimum() + (maximum() - minimum()) * progress; int value = minimum() + (maximum() - minimum()) * progress;
setValue(value); setValue(value);
} }
void void ExtendedSlider::updateTooltip()
ExtendedSlider::updateTooltip()
{ {
setToolTip(QString::number(value()) + "%"); setToolTip(QString::number(value()) + "%");
} }
void void ExtendedSlider::fireTimer()
ExtendedSlider::fireTimer()
{ {
m_timer.start(500); m_timer.start(500);
} }

View File

@@ -22,20 +22,20 @@
class ExtendedSlider : public QSlider class ExtendedSlider : public QSlider
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ExtendedSlider(QWidget* parent = nullptr); explicit ExtendedSlider(QWidget* parent = nullptr);
int mappedValue(int min, int max); int mappedValue(int min, int max);
void setMapedValue(int min, int val, int max); void setMapedValue(int min, int val, int max);
signals: signals:
void modificationsEnded(); void modificationsEnded();
private slots: private slots:
void updateTooltip(); void updateTooltip();
void fireTimer(); void fireTimer();
private: private:
QTimer m_timer; QTimer m_timer;
}; };

View File

@@ -28,110 +28,104 @@
FileNameEditor::FileNameEditor(QWidget* parent) FileNameEditor::FileNameEditor(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
initWidgets(); initWidgets();
initLayout(); initLayout();
} }
void void FileNameEditor::initLayout()
FileNameEditor::initLayout()
{ {
m_layout = new QVBoxLayout(this); m_layout = new QVBoxLayout(this);
auto infoLabel = new QLabel(tr("Edit the name of your captures:"), this); auto infoLabel = new QLabel(tr("Edit the name of your captures:"), this);
infoLabel->setFixedHeight(20); infoLabel->setFixedHeight(20);
m_layout->addWidget(infoLabel); m_layout->addWidget(infoLabel);
m_layout->addWidget(m_helperButtons); m_layout->addWidget(m_helperButtons);
m_layout->addWidget(new QLabel(tr("Edit:"))); m_layout->addWidget(new QLabel(tr("Edit:")));
m_layout->addWidget(m_nameEditor); m_layout->addWidget(m_nameEditor);
m_layout->addWidget(new QLabel(tr("Preview:"))); m_layout->addWidget(new QLabel(tr("Preview:")));
m_layout->addWidget(m_outputLabel); m_layout->addWidget(m_outputLabel);
QHBoxLayout* horizLayout = new QHBoxLayout(); QHBoxLayout* horizLayout = new QHBoxLayout();
horizLayout->addWidget(m_saveButton); horizLayout->addWidget(m_saveButton);
horizLayout->addWidget(m_resetButton); horizLayout->addWidget(m_resetButton);
horizLayout->addWidget(m_clearButton); horizLayout->addWidget(m_clearButton);
m_layout->addLayout(horizLayout); m_layout->addLayout(horizLayout);
} }
void void FileNameEditor::initWidgets()
FileNameEditor::initWidgets()
{ {
m_nameHandler = new FileNameHandler(this); m_nameHandler = new FileNameHandler(this);
// editor // editor
m_nameEditor = new QLineEdit(this); m_nameEditor = new QLineEdit(this);
m_nameEditor->setMaxLength(FileNameHandler::MAX_CHARACTERS); m_nameEditor->setMaxLength(FileNameHandler::MAX_CHARACTERS);
// preview // preview
m_outputLabel = new QLineEdit(this); m_outputLabel = new QLineEdit(this);
m_outputLabel->setDisabled(true); m_outputLabel->setDisabled(true);
QString foreground = this->palette().windowText().color().name(); QString foreground = this->palette().windowText().color().name();
m_outputLabel->setStyleSheet(QStringLiteral("color: %1").arg(foreground)); m_outputLabel->setStyleSheet(QStringLiteral("color: %1").arg(foreground));
QPalette pal = m_outputLabel->palette(); QPalette pal = m_outputLabel->palette();
QColor color = pal.color(QPalette::Disabled, m_outputLabel->backgroundRole()); QColor color =
pal.setColor(QPalette::Active, m_outputLabel->backgroundRole(), color); pal.color(QPalette::Disabled, m_outputLabel->backgroundRole());
m_outputLabel->setPalette(pal); pal.setColor(QPalette::Active, m_outputLabel->backgroundRole(), color);
m_outputLabel->setPalette(pal);
connect(m_nameEditor, connect(m_nameEditor,
&QLineEdit::textChanged, &QLineEdit::textChanged,
this, this,
&FileNameEditor::showParsedPattern); &FileNameEditor::showParsedPattern);
updateComponents(); updateComponents();
// helper buttons // helper buttons
m_helperButtons = new StrftimeChooserWidget(this); m_helperButtons = new StrftimeChooserWidget(this);
connect(m_helperButtons, connect(m_helperButtons,
&StrftimeChooserWidget::variableEmitted, &StrftimeChooserWidget::variableEmitted,
this, this,
&FileNameEditor::addToNameEditor); &FileNameEditor::addToNameEditor);
// save // save
m_saveButton = new QPushButton(tr("Save"), this); m_saveButton = new QPushButton(tr("Save"), this);
connect( connect(
m_saveButton, &QPushButton::clicked, this, &FileNameEditor::savePattern); m_saveButton, &QPushButton::clicked, this, &FileNameEditor::savePattern);
m_saveButton->setToolTip(tr("Saves the pattern")); m_saveButton->setToolTip(tr("Saves the pattern"));
// reset // reset
m_resetButton = new QPushButton(tr("Reset"), this); m_resetButton = new QPushButton(tr("Reset"), this);
connect( connect(
m_resetButton, &QPushButton::clicked, this, &FileNameEditor::resetName); m_resetButton, &QPushButton::clicked, this, &FileNameEditor::resetName);
m_resetButton->setToolTip(tr("Restores the saved pattern")); m_resetButton->setToolTip(tr("Restores the saved pattern"));
// clear // clear
m_clearButton = new QPushButton(tr("Clear"), this); m_clearButton = new QPushButton(tr("Clear"), this);
connect(m_clearButton, &QPushButton::clicked, this, [this]() { connect(m_clearButton, &QPushButton::clicked, this, [this]() {
m_nameEditor->setText(QString()); m_nameEditor->setText(QString());
}); });
m_clearButton->setToolTip(tr("Deletes the name")); m_clearButton->setToolTip(tr("Deletes the name"));
} }
void void FileNameEditor::savePattern()
FileNameEditor::savePattern()
{ {
QString pattern = m_nameEditor->text(); QString pattern = m_nameEditor->text();
m_nameHandler->setPattern(pattern); m_nameHandler->setPattern(pattern);
} }
void void FileNameEditor::showParsedPattern(const QString& p)
FileNameEditor::showParsedPattern(const QString& p)
{ {
QString output = m_nameHandler->parseFilename(p); QString output = m_nameHandler->parseFilename(p);
m_outputLabel->setText(output); m_outputLabel->setText(output);
} }
void void FileNameEditor::resetName()
FileNameEditor::resetName()
{ {
m_nameEditor->setText(ConfigHandler().filenamePatternValue()); m_nameEditor->setText(ConfigHandler().filenamePatternValue());
} }
void void FileNameEditor::addToNameEditor(QString s)
FileNameEditor::addToNameEditor(QString s)
{ {
m_nameEditor->setText(m_nameEditor->text() + s); m_nameEditor->setText(m_nameEditor->text() + s);
m_nameEditor->setFocus(); m_nameEditor->setFocus();
} }
void void FileNameEditor::updateComponents()
FileNameEditor::updateComponents()
{ {
m_nameEditor->setText(ConfigHandler().filenamePatternValue()); m_nameEditor->setText(ConfigHandler().filenamePatternValue());
m_outputLabel->setText(m_nameHandler->parsedPattern()); m_outputLabel->setText(m_nameHandler->parsedPattern());
} }

View File

@@ -28,29 +28,29 @@ class StrftimeChooserWidget;
class FileNameEditor : public QWidget class FileNameEditor : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit FileNameEditor(QWidget* parent = nullptr); explicit FileNameEditor(QWidget* parent = nullptr);
private: private:
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
QLineEdit* m_outputLabel; QLineEdit* m_outputLabel;
QLineEdit* m_nameEditor; QLineEdit* m_nameEditor;
FileNameHandler* m_nameHandler; FileNameHandler* m_nameHandler;
StrftimeChooserWidget* m_helperButtons; StrftimeChooserWidget* m_helperButtons;
QPushButton* m_saveButton; QPushButton* m_saveButton;
QPushButton* m_resetButton; QPushButton* m_resetButton;
QPushButton* m_clearButton; QPushButton* m_clearButton;
void initLayout(); void initLayout();
void initWidgets(); void initWidgets();
public slots: public slots:
void addToNameEditor(QString s); void addToNameEditor(QString s);
void updateComponents(); void updateComponents();
private slots: private slots:
void savePattern(); void savePattern();
void showParsedPattern(const QString&); void showParsedPattern(const QString&);
void resetName(); void resetName();
}; };

View File

@@ -33,343 +33,326 @@
GeneneralConf::GeneneralConf(QWidget* parent) GeneneralConf::GeneneralConf(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
m_layout = new QVBoxLayout(this); m_layout = new QVBoxLayout(this);
m_layout->setAlignment(Qt::AlignTop); m_layout->setAlignment(Qt::AlignTop);
initShowHelp(); initShowHelp();
initShowSidePanelButton(); initShowSidePanelButton();
initShowDesktopNotification(); initShowDesktopNotification();
initShowTrayIcon(); initShowTrayIcon();
initAutostart(); initAutostart();
initCloseAfterCapture(); initCloseAfterCapture();
initCopyAndCloseAfterUpload(); initCopyAndCloseAfterUpload();
initSaveAfterCopy(); initSaveAfterCopy();
// this has to be at the end // this has to be at the end
initConfingButtons(); initConfingButtons();
updateComponents(); updateComponents();
} }
void void GeneneralConf::updateComponents()
GeneneralConf::updateComponents()
{ {
ConfigHandler config; ConfigHandler config;
m_helpMessage->setChecked(config.showHelpValue()); m_helpMessage->setChecked(config.showHelpValue());
m_sidePanelButton->setChecked(config.showSidePanelButtonValue()); m_sidePanelButton->setChecked(config.showSidePanelButtonValue());
m_sysNotifications->setChecked(config.desktopNotificationValue()); m_sysNotifications->setChecked(config.desktopNotificationValue());
m_autostart->setChecked(config.startupLaunchValue()); m_autostart->setChecked(config.startupLaunchValue());
m_closeAfterCapture->setChecked(config.closeAfterScreenshotValue()); m_closeAfterCapture->setChecked(config.closeAfterScreenshotValue());
m_copyAndCloseAfterUpload->setChecked( m_copyAndCloseAfterUpload->setChecked(
config.copyAndCloseAfterUploadEnabled()); config.copyAndCloseAfterUploadEnabled());
m_saveAfterCopy->setChecked(config.saveAfterCopyValue()); m_saveAfterCopy->setChecked(config.saveAfterCopyValue());
if (!config.saveAfterCopyPathValue().isEmpty()) { if (!config.saveAfterCopyPathValue().isEmpty()) {
m_savePath->setText(config.saveAfterCopyPathValue()); m_savePath->setText(config.saveAfterCopyPathValue());
} else { } else {
ConfigHandler().setSaveAfterCopyPath( ConfigHandler().setSaveAfterCopyPath(
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
} }
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
m_showTray->setChecked(!config.disabledTrayIconValue()); m_showTray->setChecked(!config.disabledTrayIconValue());
#endif #endif
} }
void void GeneneralConf::showHelpChanged(bool checked)
GeneneralConf::showHelpChanged(bool checked)
{ {
ConfigHandler().setShowHelp(checked); ConfigHandler().setShowHelp(checked);
} }
void void GeneneralConf::showSidePanelButtonChanged(bool checked)
GeneneralConf::showSidePanelButtonChanged(bool checked)
{ {
ConfigHandler().setShowSidePanelButton(checked); ConfigHandler().setShowSidePanelButton(checked);
} }
void void GeneneralConf::showDesktopNotificationChanged(bool checked)
GeneneralConf::showDesktopNotificationChanged(bool checked)
{ {
ConfigHandler().setDesktopNotification(checked); ConfigHandler().setDesktopNotification(checked);
} }
void void GeneneralConf::showTrayIconChanged(bool checked)
GeneneralConf::showTrayIconChanged(bool checked)
{ {
auto controller = Controller::getInstance(); auto controller = Controller::getInstance();
if (checked) { if (checked) {
controller->enableTrayIcon(); controller->enableTrayIcon();
} else { } else {
controller->disableTrayIcon(); controller->disableTrayIcon();
} }
} }
void void GeneneralConf::autostartChanged(bool checked)
GeneneralConf::autostartChanged(bool checked)
{ {
ConfigHandler().setStartupLaunch(checked); ConfigHandler().setStartupLaunch(checked);
} }
void void GeneneralConf::closeAfterCaptureChanged(bool checked)
GeneneralConf::closeAfterCaptureChanged(bool checked)
{ {
ConfigHandler().setCloseAfterScreenshot(checked); ConfigHandler().setCloseAfterScreenshot(checked);
} }
void void GeneneralConf::importConfiguration()
GeneneralConf::importConfiguration()
{ {
QString fileName = QFileDialog::getOpenFileName(this, tr("Import")); QString fileName = QFileDialog::getOpenFileName(this, tr("Import"));
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
return; return;
} }
QFile file(fileName); QFile file(fileName);
QTextCodec* codec = QTextCodec::codecForLocale(); QTextCodec* codec = QTextCodec::codecForLocale();
if (!file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
QMessageBox::about(this, tr("Error"), tr("Unable to read file.")); QMessageBox::about(this, tr("Error"), tr("Unable to read file."));
return; return;
} }
QString text = codec->toUnicode(file.readAll()); QString text = codec->toUnicode(file.readAll());
file.close(); file.close();
QFile config(ConfigHandler().configFilePath()); QFile config(ConfigHandler().configFilePath());
if (!config.open(QFile::WriteOnly)) { if (!config.open(QFile::WriteOnly)) {
QMessageBox::about(this, tr("Error"), tr("Unable to write file.")); QMessageBox::about(this, tr("Error"), tr("Unable to write file."));
return; return;
} }
config.write(codec->fromUnicode(text)); config.write(codec->fromUnicode(text));
config.close(); config.close();
} }
void void GeneneralConf::exportFileConfiguration()
GeneneralConf::exportFileConfiguration()
{ {
QString fileName = QFileDialog::getSaveFileName( QString fileName = QFileDialog::getSaveFileName(
this, tr("Save File"), QStringLiteral("flameshot.conf")); this, tr("Save File"), QStringLiteral("flameshot.conf"));
// Cancel button // Cancel button
if (fileName.isNull()) { if (fileName.isNull()) {
return; return;
} }
QFile targetFile(fileName); QFile targetFile(fileName);
if (targetFile.exists()) { if (targetFile.exists()) {
targetFile.remove(); targetFile.remove();
} }
bool ok = QFile::copy(ConfigHandler().configFilePath(), fileName); bool ok = QFile::copy(ConfigHandler().configFilePath(), fileName);
if (!ok) { if (!ok) {
QMessageBox::about(this, tr("Error"), tr("Unable to write file.")); QMessageBox::about(this, tr("Error"), tr("Unable to write file."));
} }
} }
void void GeneneralConf::resetConfiguration()
GeneneralConf::resetConfiguration()
{ {
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question( reply = QMessageBox::question(
this, this,
tr("Confirm Reset"), tr("Confirm Reset"),
tr("Are you sure you want to reset the configuration?"), tr("Are you sure you want to reset the configuration?"),
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
ConfigHandler().setDefaults(); ConfigHandler().setDefaults();
} }
} }
void void GeneneralConf::initShowHelp()
GeneneralConf::initShowHelp()
{ {
m_helpMessage = new QCheckBox(tr("Show help message"), this); m_helpMessage = new QCheckBox(tr("Show help message"), this);
ConfigHandler config; ConfigHandler config;
bool checked = config.showHelpValue(); bool checked = config.showHelpValue();
m_helpMessage->setChecked(checked); m_helpMessage->setChecked(checked);
m_helpMessage->setToolTip(tr("Show the help message at the beginning " m_helpMessage->setToolTip(tr("Show the help message at the beginning "
"in the capture mode.")); "in the capture mode."));
m_layout->addWidget(m_helpMessage); m_layout->addWidget(m_helpMessage);
connect( connect(m_helpMessage,
m_helpMessage, &QCheckBox::clicked, this, &GeneneralConf::showHelpChanged); &QCheckBox::clicked,
this,
&GeneneralConf::showHelpChanged);
} }
void void GeneneralConf::initShowSidePanelButton()
GeneneralConf::initShowSidePanelButton()
{ {
m_sidePanelButton = new QCheckBox(tr("Show the side panel button"), this); m_sidePanelButton = new QCheckBox(tr("Show the side panel button"), this);
m_sidePanelButton->setChecked(ConfigHandler().showSidePanelButtonValue()); m_sidePanelButton->setChecked(ConfigHandler().showSidePanelButtonValue());
m_sidePanelButton->setToolTip( m_sidePanelButton->setToolTip(
tr("Show the side panel toggle button in the capture mode.")); tr("Show the side panel toggle button in the capture mode."));
m_layout->addWidget(m_sidePanelButton); m_layout->addWidget(m_sidePanelButton);
connect(m_sidePanelButton, connect(m_sidePanelButton,
&QCheckBox::clicked, &QCheckBox::clicked,
this, this,
&GeneneralConf::showSidePanelButtonChanged); &GeneneralConf::showSidePanelButtonChanged);
} }
void void GeneneralConf::initShowDesktopNotification()
GeneneralConf::initShowDesktopNotification()
{ {
m_sysNotifications = new QCheckBox(tr("Show desktop notifications"), this); m_sysNotifications = new QCheckBox(tr("Show desktop notifications"), this);
ConfigHandler config; ConfigHandler config;
bool checked = config.desktopNotificationValue(); bool checked = config.desktopNotificationValue();
m_sysNotifications->setChecked(checked); m_sysNotifications->setChecked(checked);
m_sysNotifications->setToolTip(tr("Show desktop notifications")); m_sysNotifications->setToolTip(tr("Show desktop notifications"));
m_layout->addWidget(m_sysNotifications); m_layout->addWidget(m_sysNotifications);
connect(m_sysNotifications, connect(m_sysNotifications,
&QCheckBox::clicked, &QCheckBox::clicked,
this, this,
&GeneneralConf::showDesktopNotificationChanged); &GeneneralConf::showDesktopNotificationChanged);
} }
void void GeneneralConf::initShowTrayIcon()
GeneneralConf::initShowTrayIcon()
{ {
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
m_showTray = new QCheckBox(tr("Show tray icon"), this); m_showTray = new QCheckBox(tr("Show tray icon"), this);
ConfigHandler config; ConfigHandler config;
bool checked = !config.disabledTrayIconValue(); bool checked = !config.disabledTrayIconValue();
m_showTray->setChecked(checked); m_showTray->setChecked(checked);
m_showTray->setToolTip(tr("Show the systemtray icon")); m_showTray->setToolTip(tr("Show the systemtray icon"));
m_layout->addWidget(m_showTray); m_layout->addWidget(m_showTray);
connect(m_showTray, connect(m_showTray,
&QCheckBox::stateChanged, &QCheckBox::stateChanged,
this, this,
&GeneneralConf::showTrayIconChanged); &GeneneralConf::showTrayIconChanged);
#endif #endif
} }
void void GeneneralConf::initConfingButtons()
GeneneralConf::initConfingButtons()
{ {
QHBoxLayout* buttonLayout = new QHBoxLayout(); QHBoxLayout* buttonLayout = new QHBoxLayout();
m_layout->addStretch(); m_layout->addStretch();
QGroupBox* box = new QGroupBox(tr("Configuration File")); QGroupBox* box = new QGroupBox(tr("Configuration File"));
box->setFlat(true); box->setFlat(true);
box->setLayout(buttonLayout); box->setLayout(buttonLayout);
m_layout->addWidget(box); m_layout->addWidget(box);
m_exportButton = new QPushButton(tr("Export")); m_exportButton = new QPushButton(tr("Export"));
buttonLayout->addWidget(m_exportButton); buttonLayout->addWidget(m_exportButton);
connect(m_exportButton, connect(m_exportButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&GeneneralConf::exportFileConfiguration); &GeneneralConf::exportFileConfiguration);
m_importButton = new QPushButton(tr("Import")); m_importButton = new QPushButton(tr("Import"));
buttonLayout->addWidget(m_importButton); buttonLayout->addWidget(m_importButton);
connect(m_importButton, connect(m_importButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&GeneneralConf::importConfiguration); &GeneneralConf::importConfiguration);
m_resetButton = new QPushButton(tr("Reset")); m_resetButton = new QPushButton(tr("Reset"));
buttonLayout->addWidget(m_resetButton); buttonLayout->addWidget(m_resetButton);
connect(m_resetButton, connect(m_resetButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&GeneneralConf::resetConfiguration); &GeneneralConf::resetConfiguration);
} }
void void GeneneralConf::initAutostart()
GeneneralConf::initAutostart()
{ {
m_autostart = new QCheckBox(tr("Launch at startup"), this); m_autostart = new QCheckBox(tr("Launch at startup"), this);
ConfigHandler config; ConfigHandler config;
bool checked = config.startupLaunchValue(); bool checked = config.startupLaunchValue();
m_autostart->setChecked(checked); m_autostart->setChecked(checked);
m_autostart->setToolTip(tr("Launch Flameshot")); m_autostart->setToolTip(tr("Launch Flameshot"));
m_layout->addWidget(m_autostart); m_layout->addWidget(m_autostart);
connect( connect(
m_autostart, &QCheckBox::clicked, this, &GeneneralConf::autostartChanged); m_autostart, &QCheckBox::clicked, this, &GeneneralConf::autostartChanged);
} }
void void GeneneralConf::initCloseAfterCapture()
GeneneralConf::initCloseAfterCapture()
{ {
m_closeAfterCapture = new QCheckBox(tr("Close after capture"), this); m_closeAfterCapture = new QCheckBox(tr("Close after capture"), this);
ConfigHandler config; ConfigHandler config;
bool checked = config.closeAfterScreenshotValue(); bool checked = config.closeAfterScreenshotValue();
m_closeAfterCapture->setChecked(checked); m_closeAfterCapture->setChecked(checked);
m_closeAfterCapture->setToolTip(tr("Close after taking a screenshot")); m_closeAfterCapture->setToolTip(tr("Close after taking a screenshot"));
m_layout->addWidget(m_closeAfterCapture); m_layout->addWidget(m_closeAfterCapture);
connect(m_closeAfterCapture, connect(m_closeAfterCapture,
&QCheckBox::clicked, &QCheckBox::clicked,
this, this,
&GeneneralConf::closeAfterCaptureChanged); &GeneneralConf::closeAfterCaptureChanged);
} }
void void GeneneralConf::initCopyAndCloseAfterUpload()
GeneneralConf::initCopyAndCloseAfterUpload()
{ {
m_copyAndCloseAfterUpload = new QCheckBox(tr("Copy URL after upload"), this); m_copyAndCloseAfterUpload =
ConfigHandler config; new QCheckBox(tr("Copy URL after upload"), this);
m_copyAndCloseAfterUpload->setChecked( ConfigHandler config;
config.copyAndCloseAfterUploadEnabled()); m_copyAndCloseAfterUpload->setChecked(
m_copyAndCloseAfterUpload->setToolTip( config.copyAndCloseAfterUploadEnabled());
tr("Copy URL and close window after upload")); m_copyAndCloseAfterUpload->setToolTip(
m_layout->addWidget(m_copyAndCloseAfterUpload); tr("Copy URL and close window after upload"));
m_layout->addWidget(m_copyAndCloseAfterUpload);
connect(m_copyAndCloseAfterUpload, &QCheckBox::clicked, [](bool checked) { connect(m_copyAndCloseAfterUpload, &QCheckBox::clicked, [](bool checked) {
ConfigHandler().setCopyAndCloseAfterUploadEnabled(checked); ConfigHandler().setCopyAndCloseAfterUploadEnabled(checked);
}); });
} }
void void GeneneralConf::initSaveAfterCopy()
GeneneralConf::initSaveAfterCopy()
{ {
m_saveAfterCopy = new QCheckBox(tr("Save image after copy"), this); m_saveAfterCopy = new QCheckBox(tr("Save image after copy"), this);
m_saveAfterCopy->setToolTip(tr("Save image file after copying it")); m_saveAfterCopy->setToolTip(tr("Save image file after copying it"));
m_layout->addWidget(m_saveAfterCopy); m_layout->addWidget(m_saveAfterCopy);
connect(m_saveAfterCopy, connect(m_saveAfterCopy,
&QCheckBox::clicked, &QCheckBox::clicked,
this, this,
&GeneneralConf::saveAfterCopyChanged); &GeneneralConf::saveAfterCopyChanged);
QHBoxLayout* pathLayout = new QHBoxLayout(); QHBoxLayout* pathLayout = new QHBoxLayout();
m_layout->addStretch(); m_layout->addStretch();
QGroupBox* box = new QGroupBox(tr("Save Path")); QGroupBox* box = new QGroupBox(tr("Save Path"));
box->setFlat(true); box->setFlat(true);
box->setLayout(pathLayout); box->setLayout(pathLayout);
m_layout->addWidget(box); m_layout->addWidget(box);
m_savePath = new QLineEdit( m_savePath = new QLineEdit(
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), this); QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), this);
m_savePath->setDisabled(true); m_savePath->setDisabled(true);
QString foreground = this->palette().foreground().color().name(); QString foreground = this->palette().foreground().color().name();
m_savePath->setStyleSheet(QStringLiteral("color: %1").arg(foreground)); m_savePath->setStyleSheet(QStringLiteral("color: %1").arg(foreground));
pathLayout->addWidget(m_savePath); pathLayout->addWidget(m_savePath);
m_changeSaveButton = new QPushButton(tr("Change..."), this); m_changeSaveButton = new QPushButton(tr("Change..."), this);
pathLayout->addWidget(m_changeSaveButton); pathLayout->addWidget(m_changeSaveButton);
connect(m_changeSaveButton, connect(m_changeSaveButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&GeneneralConf::changeSavePath); &GeneneralConf::changeSavePath);
} }
void void GeneneralConf::saveAfterCopyChanged(bool checked)
GeneneralConf::saveAfterCopyChanged(bool checked)
{ {
ConfigHandler().setSaveAfterCopy(checked); ConfigHandler().setSaveAfterCopy(checked);
} }
void void GeneneralConf::changeSavePath()
GeneneralConf::changeSavePath()
{ {
QString path = QFileDialog::getExistingDirectory( QString path = QFileDialog::getExistingDirectory(
this, this,
tr("Choose a Folder"), tr("Choose a Folder"),
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (path.isEmpty()) { if (path.isEmpty()) {
return; return;
} }
if (!QFileInfo(path).isWritable()) { if (!QFileInfo(path).isWritable()) {
QMessageBox::about(this, tr("Error"), tr("Unable to write to directory.")); QMessageBox::about(
return; this, tr("Error"), tr("Unable to write to directory."));
} return;
m_savePath->setText(path); }
ConfigHandler().setSaveAfterCopyPath(path); m_savePath->setText(path);
ConfigHandler().setSaveAfterCopyPath(path);
} }

View File

@@ -27,49 +27,49 @@ class QLineEdit;
class GeneneralConf : public QWidget class GeneneralConf : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GeneneralConf(QWidget* parent = nullptr); explicit GeneneralConf(QWidget* parent = nullptr);
public slots: public slots:
void updateComponents(); void updateComponents();
private slots: private slots:
void showHelpChanged(bool checked); void showHelpChanged(bool checked);
void showSidePanelButtonChanged(bool checked); void showSidePanelButtonChanged(bool checked);
void showDesktopNotificationChanged(bool checked); void showDesktopNotificationChanged(bool checked);
void showTrayIconChanged(bool checked); void showTrayIconChanged(bool checked);
void autostartChanged(bool checked); void autostartChanged(bool checked);
void closeAfterCaptureChanged(bool checked); void closeAfterCaptureChanged(bool checked);
void saveAfterCopyChanged(bool checked); void saveAfterCopyChanged(bool checked);
void changeSavePath(); void changeSavePath();
void importConfiguration(); void importConfiguration();
void exportFileConfiguration(); void exportFileConfiguration();
void resetConfiguration(); void resetConfiguration();
private: private:
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
QCheckBox* m_sysNotifications; QCheckBox* m_sysNotifications;
QCheckBox* m_showTray; QCheckBox* m_showTray;
QCheckBox* m_helpMessage; QCheckBox* m_helpMessage;
QCheckBox* m_sidePanelButton; QCheckBox* m_sidePanelButton;
QCheckBox* m_autostart; QCheckBox* m_autostart;
QCheckBox* m_closeAfterCapture; QCheckBox* m_closeAfterCapture;
QCheckBox* m_copyAndCloseAfterUpload; QCheckBox* m_copyAndCloseAfterUpload;
QPushButton* m_importButton; QPushButton* m_importButton;
QPushButton* m_exportButton; QPushButton* m_exportButton;
QPushButton* m_resetButton; QPushButton* m_resetButton;
QCheckBox* m_saveAfterCopy; QCheckBox* m_saveAfterCopy;
QLineEdit* m_savePath; QLineEdit* m_savePath;
QPushButton* m_changeSaveButton; QPushButton* m_changeSaveButton;
void initShowHelp(); void initShowHelp();
void initShowSidePanelButton(); void initShowSidePanelButton();
void initShowDesktopNotification(); void initShowDesktopNotification();
void initShowTrayIcon(); void initShowTrayIcon();
void initConfingButtons(); void initConfingButtons();
void initAutostart(); void initAutostart();
void initCloseAfterCapture(); void initCloseAfterCapture();
void initCopyAndCloseAfterUpload(); void initCopyAndCloseAfterUpload();
void initSaveAfterCopy(); void initSaveAfterCopy();
}; };

View File

@@ -23,49 +23,50 @@
StrftimeChooserWidget::StrftimeChooserWidget(QWidget* parent) StrftimeChooserWidget::StrftimeChooserWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
QGridLayout* layout = new QGridLayout(this); QGridLayout* layout = new QGridLayout(this);
auto k = m_buttonData.keys(); auto k = m_buttonData.keys();
int middle = k.length() / 2; int middle = k.length() / 2;
// add the buttons in 2 columns (they need to be even) // add the buttons in 2 columns (they need to be even)
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
for (int j = 0; j < middle; j++) { for (int j = 0; j < middle; j++) {
QString key = k.last(); QString key = k.last();
k.pop_back(); k.pop_back();
QString variable = m_buttonData.value(key); QString variable = m_buttonData.value(key);
QPushButton* button = new QPushButton(this); QPushButton* button = new QPushButton(this);
button->setText(tr(key.toStdString().data())); button->setText(tr(key.toStdString().data()));
button->setToolTip(variable); button->setToolTip(variable);
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); button->setSizePolicy(QSizePolicy::Expanding,
button->setMinimumHeight(25); QSizePolicy::Expanding);
layout->addWidget(button, j, i); button->setMinimumHeight(25);
connect(button, &QPushButton::clicked, this, [variable, this]() { layout->addWidget(button, j, i);
emit variableEmitted(variable); connect(button, &QPushButton::clicked, this, [variable, this]() {
}); emit variableEmitted(variable);
});
}
} }
} setLayout(layout);
setLayout(layout);
} }
QMap<QString, QString> StrftimeChooserWidget::m_buttonData{ QMap<QString, QString> StrftimeChooserWidget::m_buttonData{
{ QT_TR_NOOP("Century (00-99)"), "%C" }, { QT_TR_NOOP("Century (00-99)"), "%C" },
{ QT_TR_NOOP("Year (00-99)"), "%y" }, { QT_TR_NOOP("Year (00-99)"), "%y" },
{ QT_TR_NOOP("Year (2000)"), "%Y" }, { QT_TR_NOOP("Year (2000)"), "%Y" },
{ QT_TR_NOOP("Month Name (jan)"), "%b" }, { QT_TR_NOOP("Month Name (jan)"), "%b" },
{ QT_TR_NOOP("Month Name (january)"), "%B" }, { QT_TR_NOOP("Month Name (january)"), "%B" },
{ QT_TR_NOOP("Month (01-12)"), "%m" }, { QT_TR_NOOP("Month (01-12)"), "%m" },
{ QT_TR_NOOP("Week Day (1-7)"), "%u" }, { QT_TR_NOOP("Week Day (1-7)"), "%u" },
{ QT_TR_NOOP("Week (01-53)"), "%V" }, { QT_TR_NOOP("Week (01-53)"), "%V" },
{ QT_TR_NOOP("Day Name (mon)"), "%a" }, { QT_TR_NOOP("Day Name (mon)"), "%a" },
{ QT_TR_NOOP("Day Name (monday)"), "%A" }, { QT_TR_NOOP("Day Name (monday)"), "%A" },
{ QT_TR_NOOP("Day (01-31)"), "%d" }, { QT_TR_NOOP("Day (01-31)"), "%d" },
{ QT_TR_NOOP("Day of Month (1-31)"), "%e" }, { QT_TR_NOOP("Day of Month (1-31)"), "%e" },
{ QT_TR_NOOP("Day (001-366)"), "%j" }, { QT_TR_NOOP("Day (001-366)"), "%j" },
{ QT_TR_NOOP("Time (%H-%M-%S)"), "%T" }, { QT_TR_NOOP("Time (%H-%M-%S)"), "%T" },
{ QT_TR_NOOP("Time (%H-%M)"), "%R" }, { QT_TR_NOOP("Time (%H-%M)"), "%R" },
{ QT_TR_NOOP("Hour (00-23)"), "%H" }, { QT_TR_NOOP("Hour (00-23)"), "%H" },
{ QT_TR_NOOP("Hour (01-12)"), "%I" }, { QT_TR_NOOP("Hour (01-12)"), "%I" },
{ QT_TR_NOOP("Minute (00-59)"), "%M" }, { QT_TR_NOOP("Minute (00-59)"), "%M" },
{ QT_TR_NOOP("Second (00-59)"), "%S" }, { QT_TR_NOOP("Second (00-59)"), "%S" },
{ QT_TR_NOOP("Full Date (%m/%d/%y)"), "%D" }, { QT_TR_NOOP("Full Date (%m/%d/%y)"), "%D" },
{ QT_TR_NOOP("Full Date (%Y-%m-%d)"), "%F" }, { QT_TR_NOOP("Full Date (%Y-%m-%d)"), "%F" },
}; };

View File

@@ -21,13 +21,13 @@
class StrftimeChooserWidget : public QWidget class StrftimeChooserWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit StrftimeChooserWidget(QWidget* parent = nullptr); explicit StrftimeChooserWidget(QWidget* parent = nullptr);
signals: signals:
void variableEmitted(const QString&); void variableEmitted(const QString&);
private: private:
static QMap<QString, QString> m_buttonData; static QMap<QString, QString> m_buttonData;
}; };

View File

@@ -29,162 +29,156 @@
UIcolorEditor::UIcolorEditor(QWidget* parent) UIcolorEditor::UIcolorEditor(QWidget* parent)
: QGroupBox(parent) : QGroupBox(parent)
{ {
setTitle(tr("UI Color Editor")); setTitle(tr("UI Color Editor"));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_hLayout = new QHBoxLayout; m_hLayout = new QHBoxLayout;
m_vLayout = new QVBoxLayout; m_vLayout = new QVBoxLayout;
const int space = QApplication::fontMetrics().lineSpacing(); const int space = QApplication::fontMetrics().lineSpacing();
m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding)); m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding));
m_vLayout->setAlignment(Qt::AlignVCenter); m_vLayout->setAlignment(Qt::AlignVCenter);
initButtons(); initButtons();
initColorWheel(); initColorWheel();
m_vLayout->addSpacing(space); m_vLayout->addSpacing(space);
m_hLayout->addLayout(m_vLayout); m_hLayout->addLayout(m_vLayout);
m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding)); m_hLayout->addItem(new QSpacerItem(space, space, QSizePolicy::Expanding));
setLayout(m_hLayout); setLayout(m_hLayout);
updateComponents(); updateComponents();
} }
void void UIcolorEditor::updateComponents()
UIcolorEditor::updateComponents()
{ {
ConfigHandler config; ConfigHandler config;
m_uiColor = config.uiMainColorValue(); m_uiColor = config.uiMainColorValue();
m_contrastColor = config.uiContrastColorValue(); m_contrastColor = config.uiContrastColorValue();
m_buttonContrast->setColor(m_contrastColor); m_buttonContrast->setColor(m_contrastColor);
m_buttonMainColor->setColor(m_uiColor); m_buttonMainColor->setColor(m_uiColor);
if (m_lastButtonPressed == m_buttonMainColor) { if (m_lastButtonPressed == m_buttonMainColor) {
m_colorWheel->setColor(m_uiColor); m_colorWheel->setColor(m_uiColor);
} else { } else {
m_colorWheel->setColor(m_contrastColor); m_colorWheel->setColor(m_contrastColor);
} }
} }
// updateUIcolor updates the appearance of the buttons // updateUIcolor updates the appearance of the buttons
void void UIcolorEditor::updateUIcolor()
UIcolorEditor::updateUIcolor()
{ {
ConfigHandler config; ConfigHandler config;
if (m_lastButtonPressed == m_buttonMainColor) { if (m_lastButtonPressed == m_buttonMainColor) {
config.setUIMainColor(m_uiColor); config.setUIMainColor(m_uiColor);
} else { } else {
config.setUIContrastColor(m_contrastColor); config.setUIContrastColor(m_contrastColor);
} }
} }
// updateLocalColor updates the local button // updateLocalColor updates the local button
void void UIcolorEditor::updateLocalColor(const QColor c)
UIcolorEditor::updateLocalColor(const QColor c)
{ {
if (m_lastButtonPressed == m_buttonMainColor) { if (m_lastButtonPressed == m_buttonMainColor) {
m_uiColor = c; m_uiColor = c;
} else { } else {
m_contrastColor = c; m_contrastColor = c;
} }
m_lastButtonPressed->setColor(c); m_lastButtonPressed->setColor(c);
} }
void void UIcolorEditor::initColorWheel()
UIcolorEditor::initColorWheel()
{ {
m_colorWheel = new color_widgets::ColorWheel(this); m_colorWheel = new color_widgets::ColorWheel(this);
connect(m_colorWheel, connect(m_colorWheel,
&color_widgets::ColorWheel::mouseReleaseOnColor, &color_widgets::ColorWheel::mouseReleaseOnColor,
this, this,
&UIcolorEditor::updateUIcolor); &UIcolorEditor::updateUIcolor);
connect(m_colorWheel, connect(m_colorWheel,
&color_widgets::ColorWheel::colorChanged, &color_widgets::ColorWheel::colorChanged,
this, this,
&UIcolorEditor::updateLocalColor); &UIcolorEditor::updateLocalColor);
const int size = GlobalValues::buttonBaseSize() * 3; const int size = GlobalValues::buttonBaseSize() * 3;
m_colorWheel->setMinimumSize(size, size); m_colorWheel->setMinimumSize(size, size);
m_colorWheel->setMaximumSize(size * 2, size * 2); m_colorWheel->setMaximumSize(size * 2, size * 2);
m_colorWheel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_colorWheel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_colorWheel->setToolTip(tr("Change the color moving the selectors and see" m_colorWheel->setToolTip(tr("Change the color moving the selectors and see"
" the changes in the preview buttons.")); " the changes in the preview buttons."));
m_hLayout->addWidget(m_colorWheel); m_hLayout->addWidget(m_colorWheel);
} }
void void UIcolorEditor::initButtons()
UIcolorEditor::initButtons()
{ {
const int extraSize = GlobalValues::buttonBaseSize() / 3; const int extraSize = GlobalValues::buttonBaseSize() / 3;
int frameSize = GlobalValues::buttonBaseSize() + extraSize; int frameSize = GlobalValues::buttonBaseSize() + extraSize;
m_vLayout->addWidget(new QLabel(tr("Select a Button to modify it"), this)); m_vLayout->addWidget(new QLabel(tr("Select a Button to modify it"), this));
QGroupBox* frame = new QGroupBox(); QGroupBox* frame = new QGroupBox();
frame->setFixedSize(frameSize, frameSize); frame->setFixedSize(frameSize, frameSize);
m_buttonMainColor = new CaptureToolButton(m_buttonIconType, frame); m_buttonMainColor = new CaptureToolButton(m_buttonIconType, frame);
m_buttonMainColor->move(m_buttonMainColor->x() + extraSize / 2, m_buttonMainColor->move(m_buttonMainColor->x() + extraSize / 2,
m_buttonMainColor->y() + extraSize / 2); m_buttonMainColor->y() + extraSize / 2);
QHBoxLayout* h1 = new QHBoxLayout(); QHBoxLayout* h1 = new QHBoxLayout();
h1->addWidget(frame); h1->addWidget(frame);
m_labelMain = new ClickableLabel(tr("Main Color"), this); m_labelMain = new ClickableLabel(tr("Main Color"), this);
h1->addWidget(m_labelMain); h1->addWidget(m_labelMain);
m_vLayout->addLayout(h1); m_vLayout->addLayout(h1);
m_buttonMainColor->setToolTip(tr("Click on this button to set the edition" m_buttonMainColor->setToolTip(tr("Click on this button to set the edition"
" mode of the main color.")); " mode of the main color."));
QGroupBox* frame2 = new QGroupBox(); QGroupBox* frame2 = new QGroupBox();
m_buttonContrast = new CaptureToolButton(m_buttonIconType, frame2); m_buttonContrast = new CaptureToolButton(m_buttonIconType, frame2);
m_buttonContrast->move(m_buttonContrast->x() + extraSize / 2, m_buttonContrast->move(m_buttonContrast->x() + extraSize / 2,
m_buttonContrast->y() + extraSize / 2); m_buttonContrast->y() + extraSize / 2);
QHBoxLayout* h2 = new QHBoxLayout(); QHBoxLayout* h2 = new QHBoxLayout();
h2->addWidget(frame2); h2->addWidget(frame2);
frame2->setFixedSize(frameSize, frameSize); frame2->setFixedSize(frameSize, frameSize);
m_labelContrast = new ClickableLabel(tr("Contrast Color"), this); m_labelContrast = new ClickableLabel(tr("Contrast Color"), this);
m_labelContrast->setStyleSheet(QStringLiteral("color : gray")); m_labelContrast->setStyleSheet(QStringLiteral("color : gray"));
h2->addWidget(m_labelContrast); h2->addWidget(m_labelContrast);
m_vLayout->addLayout(h2); m_vLayout->addLayout(h2);
m_buttonContrast->setToolTip(tr("Click on this button to set the edition" m_buttonContrast->setToolTip(tr("Click on this button to set the edition"
" mode of the contrast color.")); " mode of the contrast color."));
connect(m_buttonMainColor, connect(m_buttonMainColor,
&CaptureToolButton::pressedButton, &CaptureToolButton::pressedButton,
this, this,
&UIcolorEditor::changeLastButton); &UIcolorEditor::changeLastButton);
connect(m_buttonContrast, connect(m_buttonContrast,
&CaptureToolButton::pressedButton, &CaptureToolButton::pressedButton,
this, this,
&UIcolorEditor::changeLastButton); &UIcolorEditor::changeLastButton);
// clicking the labels changes the button too // clicking the labels changes the button too
connect(m_labelMain, &ClickableLabel::clicked, this, [this] { connect(m_labelMain, &ClickableLabel::clicked, this, [this] {
changeLastButton(m_buttonMainColor); changeLastButton(m_buttonMainColor);
}); });
connect(m_labelContrast, &ClickableLabel::clicked, this, [this] { connect(m_labelContrast, &ClickableLabel::clicked, this, [this] {
changeLastButton(m_buttonContrast); changeLastButton(m_buttonContrast);
}); });
m_lastButtonPressed = m_buttonMainColor; m_lastButtonPressed = m_buttonMainColor;
} }
// visual update for the selected button // visual update for the selected button
void void UIcolorEditor::changeLastButton(CaptureToolButton* b)
UIcolorEditor::changeLastButton(CaptureToolButton* b)
{ {
if (m_lastButtonPressed != b) { if (m_lastButtonPressed != b) {
m_lastButtonPressed = b; m_lastButtonPressed = b;
QString offStyle(QStringLiteral("QLabel { color : gray; }")); QString offStyle(QStringLiteral("QLabel { color : gray; }"));
if (b == m_buttonMainColor) { if (b == m_buttonMainColor) {
m_colorWheel->setColor(m_uiColor); m_colorWheel->setColor(m_uiColor);
m_labelContrast->setStyleSheet(offStyle); m_labelContrast->setStyleSheet(offStyle);
m_labelMain->setStyleSheet(styleSheet()); m_labelMain->setStyleSheet(styleSheet());
} else { } else {
m_colorWheel->setColor(m_contrastColor); m_colorWheel->setColor(m_contrastColor);
m_labelContrast->setStyleSheet(styleSheet()); m_labelContrast->setStyleSheet(styleSheet());
m_labelMain->setStyleSheet(offStyle); m_labelMain->setStyleSheet(offStyle);
}
b->setIcon(b->icon());
} }
b->setIcon(b->icon());
}
} }

View File

@@ -28,33 +28,33 @@ class ClickableLabel;
class UIcolorEditor : public QGroupBox class UIcolorEditor : public QGroupBox
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit UIcolorEditor(QWidget* parent = nullptr); explicit UIcolorEditor(QWidget* parent = nullptr);
public slots: public slots:
void updateComponents(); void updateComponents();
private slots: private slots:
void updateUIcolor(); void updateUIcolor();
void updateLocalColor(const QColor); void updateLocalColor(const QColor);
void changeLastButton(CaptureToolButton*); void changeLastButton(CaptureToolButton*);
private: private:
QColor m_uiColor, m_contrastColor; QColor m_uiColor, m_contrastColor;
CaptureToolButton* m_buttonMainColor; CaptureToolButton* m_buttonMainColor;
ClickableLabel* m_labelMain; ClickableLabel* m_labelMain;
CaptureToolButton* m_buttonContrast; CaptureToolButton* m_buttonContrast;
ClickableLabel* m_labelContrast; ClickableLabel* m_labelContrast;
CaptureToolButton* m_lastButtonPressed; CaptureToolButton* m_lastButtonPressed;
color_widgets::ColorWheel* m_colorWheel; color_widgets::ColorWheel* m_colorWheel;
static const CaptureToolButton::ButtonType m_buttonIconType = static const CaptureToolButton::ButtonType m_buttonIconType =
CaptureToolButton::TYPE_CIRCLE; CaptureToolButton::TYPE_CIRCLE;
QHBoxLayout* m_hLayout; QHBoxLayout* m_hLayout;
QVBoxLayout* m_vLayout; QVBoxLayout* m_vLayout;
void initColorWheel(); void initColorWheel();
void initButtons(); void initButtons();
}; };

View File

@@ -27,75 +27,71 @@
VisualsEditor::VisualsEditor(QWidget* parent) VisualsEditor::VisualsEditor(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
m_layout = new QVBoxLayout(); m_layout = new QVBoxLayout();
setLayout(m_layout); setLayout(m_layout);
initWidgets(); initWidgets();
} }
void void VisualsEditor::updateComponents()
VisualsEditor::updateComponents()
{ {
m_buttonList->updateComponents(); m_buttonList->updateComponents();
m_colorEditor->updateComponents(); m_colorEditor->updateComponents();
int opacity = ConfigHandler().contrastOpacityValue(); int opacity = ConfigHandler().contrastOpacityValue();
m_opacitySlider->setMapedValue(0, opacity, 255); m_opacitySlider->setMapedValue(0, opacity, 255);
} }
void void VisualsEditor::initOpacitySlider()
VisualsEditor::initOpacitySlider()
{ {
m_opacitySlider = new ExtendedSlider(); m_opacitySlider = new ExtendedSlider();
m_opacitySlider->setFocusPolicy(Qt::NoFocus); m_opacitySlider->setFocusPolicy(Qt::NoFocus);
m_opacitySlider->setOrientation(Qt::Horizontal); m_opacitySlider->setOrientation(Qt::Horizontal);
m_opacitySlider->setRange(0, 100); m_opacitySlider->setRange(0, 100);
connect(m_opacitySlider, connect(m_opacitySlider,
&ExtendedSlider::modificationsEnded, &ExtendedSlider::modificationsEnded,
this, this,
&VisualsEditor::saveOpacity); &VisualsEditor::saveOpacity);
QHBoxLayout* localLayout = new QHBoxLayout(); QHBoxLayout* localLayout = new QHBoxLayout();
localLayout->addWidget(new QLabel(QStringLiteral("0%"))); localLayout->addWidget(new QLabel(QStringLiteral("0%")));
localLayout->addWidget(m_opacitySlider); localLayout->addWidget(m_opacitySlider);
localLayout->addWidget(new QLabel(QStringLiteral("100%"))); localLayout->addWidget(new QLabel(QStringLiteral("100%")));
QLabel* label = new QLabel(); QLabel* label = new QLabel();
QString labelMsg = tr("Opacity of area outside selection:") + " %1%"; QString labelMsg = tr("Opacity of area outside selection:") + " %1%";
connect(m_opacitySlider, connect(m_opacitySlider,
&ExtendedSlider::valueChanged, &ExtendedSlider::valueChanged,
this, this,
[labelMsg, label](int val) { label->setText(labelMsg.arg(val)); }); [labelMsg, label](int val) { label->setText(labelMsg.arg(val)); });
m_layout->addWidget(label); m_layout->addWidget(label);
m_layout->addLayout(localLayout); m_layout->addLayout(localLayout);
int opacity = ConfigHandler().contrastOpacityValue(); int opacity = ConfigHandler().contrastOpacityValue();
m_opacitySlider->setMapedValue(0, opacity, 255); m_opacitySlider->setMapedValue(0, opacity, 255);
} }
void void VisualsEditor::saveOpacity()
VisualsEditor::saveOpacity()
{ {
int value = m_opacitySlider->mappedValue(0, 255); int value = m_opacitySlider->mappedValue(0, 255);
ConfigHandler().setContrastOpacity(value); ConfigHandler().setContrastOpacity(value);
} }
void void VisualsEditor::initWidgets()
VisualsEditor::initWidgets()
{ {
m_colorEditor = new UIcolorEditor(); m_colorEditor = new UIcolorEditor();
m_layout->addWidget(m_colorEditor); m_layout->addWidget(m_colorEditor);
initOpacitySlider(); initOpacitySlider();
auto boxButtons = new QGroupBox(); auto boxButtons = new QGroupBox();
boxButtons->setTitle(tr("Button Selection")); boxButtons->setTitle(tr("Button Selection"));
auto listLayout = new QVBoxLayout(boxButtons); auto listLayout = new QVBoxLayout(boxButtons);
m_buttonList = new ButtonListView(); m_buttonList = new ButtonListView();
m_layout->addWidget(boxButtons); m_layout->addWidget(boxButtons);
listLayout->addWidget(m_buttonList); listLayout->addWidget(m_buttonList);
QPushButton* setAllButtons = new QPushButton(tr("Select All")); QPushButton* setAllButtons = new QPushButton(tr("Select All"));
connect(setAllButtons, connect(setAllButtons,
&QPushButton::clicked, &QPushButton::clicked,
m_buttonList, m_buttonList,
&ButtonListView::selectAll); &ButtonListView::selectAll);
listLayout->addWidget(setAllButtons); listLayout->addWidget(setAllButtons);
} }

View File

@@ -26,22 +26,22 @@ class UIcolorEditor;
class VisualsEditor : public QWidget class VisualsEditor : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VisualsEditor(QWidget* parent = nullptr); explicit VisualsEditor(QWidget* parent = nullptr);
public slots: public slots:
void updateComponents(); void updateComponents();
private slots: private slots:
void saveOpacity(); void saveOpacity();
private: private:
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
ButtonListView* m_buttonList; ButtonListView* m_buttonList;
UIcolorEditor* m_colorEditor; UIcolorEditor* m_colorEditor;
ExtendedSlider* m_opacitySlider; ExtendedSlider* m_opacitySlider;
void initWidgets(); void initWidgets();
void initOpacitySlider(); void initOpacitySlider();
}; };

View File

@@ -34,72 +34,64 @@ CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode,
, m_id(0) , m_id(0)
{} {}
void void CaptureRequest::setStaticID(uint id)
CaptureRequest::setStaticID(uint id)
{ {
m_forcedID = true; m_forcedID = true;
m_id = id; m_id = id;
} }
uint uint CaptureRequest::id() const
CaptureRequest::id() const
{ {
if (m_forcedID) { if (m_forcedID) {
return m_id; return m_id;
}
uint id = 0;
QVector<uint> v;
v << qHash(m_mode) << qHash(m_delay * QDateTime::currentMSecsSinceEpoch())
<< qHash(m_path) << qHash(m_tasks) << m_data.toInt();
for (uint i : v) {
id ^= i + 0x9e3779b9 + (id << 6) + (id >> 2);
}
return id;
}
CaptureRequest::CaptureMode
CaptureRequest::captureMode() const
{
return m_mode;
}
uint
CaptureRequest::delay() const
{
return m_delay;
}
QString
CaptureRequest::path() const
{
return m_path;
}
QVariant
CaptureRequest::data() const
{
return m_data;
}
void
CaptureRequest::addTask(CaptureRequest::ExportTask task)
{
m_tasks |= task;
}
void
CaptureRequest::exportCapture(const QPixmap& p)
{
if ((m_tasks & ExportTask::FILESYSTEM_SAVE_TASK) != ExportTask::NO_TASK) {
if (m_path.isEmpty()) {
ScreenshotSaver().saveToFilesystemGUI(p);
} else {
ScreenshotSaver().saveToFilesystem(p, m_path, "");
} }
}
if ((m_tasks & ExportTask::CLIPBOARD_SAVE_TASK) != ExportTask::NO_TASK) { uint id = 0;
ScreenshotSaver().saveToClipboard(p); QVector<uint> v;
} v << qHash(m_mode) << qHash(m_delay * QDateTime::currentMSecsSinceEpoch())
<< qHash(m_path) << qHash(m_tasks) << m_data.toInt();
for (uint i : v) {
id ^= i + 0x9e3779b9 + (id << 6) + (id >> 2);
}
return id;
}
CaptureRequest::CaptureMode CaptureRequest::captureMode() const
{
return m_mode;
}
uint CaptureRequest::delay() const
{
return m_delay;
}
QString CaptureRequest::path() const
{
return m_path;
}
QVariant CaptureRequest::data() const
{
return m_data;
}
void CaptureRequest::addTask(CaptureRequest::ExportTask task)
{
m_tasks |= task;
}
void CaptureRequest::exportCapture(const QPixmap& p)
{
if ((m_tasks & ExportTask::FILESYSTEM_SAVE_TASK) != ExportTask::NO_TASK) {
if (m_path.isEmpty()) {
ScreenshotSaver().saveToFilesystemGUI(p);
} else {
ScreenshotSaver().saveToFilesystem(p, m_path, "");
}
}
if ((m_tasks & ExportTask::CLIPBOARD_SAVE_TASK) != ExportTask::NO_TASK) {
ScreenshotSaver().saveToClipboard(p);
}
} }

View File

@@ -24,65 +24,62 @@
class CaptureRequest class CaptureRequest
{ {
public: public:
enum CaptureMode enum CaptureMode
{ {
FULLSCREEN_MODE, FULLSCREEN_MODE,
GRAPHICAL_MODE, GRAPHICAL_MODE,
SCREEN_MODE, SCREEN_MODE,
}; };
enum ExportTask enum ExportTask
{ {
NO_TASK = 0, NO_TASK = 0,
CLIPBOARD_SAVE_TASK = 1, CLIPBOARD_SAVE_TASK = 1,
FILESYSTEM_SAVE_TASK = 2, FILESYSTEM_SAVE_TASK = 2,
}; };
CaptureRequest(CaptureMode mode, CaptureRequest(CaptureMode mode,
const uint delay = 0, const uint delay = 0,
const QString& path = QLatin1String(""), const QString& path = QLatin1String(""),
const QVariant& data = QVariant(), const QVariant& data = QVariant(),
ExportTask tasks = NO_TASK); ExportTask tasks = NO_TASK);
void setStaticID(uint id); void setStaticID(uint id);
uint id() const; uint id() const;
uint delay() const; uint delay() const;
QString path() const; QString path() const;
QVariant data() const; QVariant data() const;
CaptureMode captureMode() const; CaptureMode captureMode() const;
void addTask(ExportTask task); void addTask(ExportTask task);
void exportCapture(const QPixmap& p); void exportCapture(const QPixmap& p);
private: private:
CaptureMode m_mode; CaptureMode m_mode;
uint m_delay; uint m_delay;
QString m_path; QString m_path;
ExportTask m_tasks; ExportTask m_tasks;
QVariant m_data; QVariant m_data;
bool m_forcedID; bool m_forcedID;
uint m_id; uint m_id;
}; };
using eTask = CaptureRequest::ExportTask; using eTask = CaptureRequest::ExportTask;
inline eTask inline eTask operator|(const eTask& a, const eTask& b)
operator|(const eTask& a, const eTask& b)
{ {
return static_cast<eTask>(static_cast<int>(a) | static_cast<int>(b)); return static_cast<eTask>(static_cast<int>(a) | static_cast<int>(b));
} }
inline eTask inline eTask operator&(const eTask& a, const eTask& b)
operator&(const eTask& a, const eTask& b)
{ {
return static_cast<eTask>(static_cast<int>(a) & static_cast<int>(b)); return static_cast<eTask>(static_cast<int>(a) & static_cast<int>(b));
} }
inline eTask& inline eTask& operator|=(eTask& a, const eTask& b)
operator|=(eTask& a, const eTask& b)
{ {
a = static_cast<eTask>(static_cast<int>(a) | static_cast<int>(b)); a = static_cast<eTask>(static_cast<int>(a) | static_cast<int>(b));
return a; return a;
} }

View File

@@ -41,279 +41,268 @@
Controller::Controller() Controller::Controller()
: m_captureWindow(nullptr) : m_captureWindow(nullptr)
{ {
qApp->setQuitOnLastWindowClosed(false); qApp->setQuitOnLastWindowClosed(false);
// init tray icon // init tray icon
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
if (!ConfigHandler().disabledTrayIconValue()) { if (!ConfigHandler().disabledTrayIconValue()) {
enableTrayIcon(); enableTrayIcon();
} }
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
enableTrayIcon(); enableTrayIcon();
GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this); GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this);
qApp->installNativeEventFilter(nativeFilter); qApp->installNativeEventFilter(nativeFilter);
connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() { connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() {
this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE)); this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
}); });
#endif #endif
QString StyleSheet = CaptureButton::globalStyleSheet(); QString StyleSheet = CaptureButton::globalStyleSheet();
qApp->setStyleSheet(StyleSheet); qApp->setStyleSheet(StyleSheet);
} }
Controller* Controller* Controller::getInstance()
Controller::getInstance()
{ {
static Controller c; static Controller c;
return &c; return &c;
} }
void void Controller::enableExports()
Controller::enableExports()
{ {
connect( connect(
this, &Controller::captureTaken, this, &Controller::handleCaptureTaken); this, &Controller::captureTaken, this, &Controller::handleCaptureTaken);
connect( connect(
this, &Controller::captureFailed, this, &Controller::handleCaptureFailed); this, &Controller::captureFailed, this, &Controller::handleCaptureFailed);
} }
void void Controller::requestCapture(const CaptureRequest& request)
Controller::requestCapture(const CaptureRequest& request)
{ {
uint id = request.id(); uint id = request.id();
m_requestMap.insert(id, request); m_requestMap.insert(id, request);
switch (request.captureMode()) { switch (request.captureMode()) {
case CaptureRequest::FULLSCREEN_MODE: case CaptureRequest::FULLSCREEN_MODE:
doLater(request.delay(), this, [this, id]() { doLater(request.delay(), this, [this, id]() {
this->startFullscreenCapture(id); this->startFullscreenCapture(id);
}); });
break; break;
// TODO: Figure out the code path that gets here so the deprated warning can // TODO: Figure out the code path that gets here so the deprated warning
// be fixed // can be fixed
case CaptureRequest::SCREEN_MODE: { case CaptureRequest::SCREEN_MODE: {
int&& number = request.data().toInt(); int&& number = request.data().toInt();
doLater(request.delay(), this, [this, id, number]() { doLater(request.delay(), this, [this, id, number]() {
this->startScreenGrab(id, number); this->startScreenGrab(id, number);
}); });
break; break;
}
case CaptureRequest::GRAPHICAL_MODE: {
QString&& path = request.path();
doLater(request.delay(), this, [this, id, path]() {
this->startVisualCapture(id, path);
});
break;
}
default:
emit captureFailed(id);
break;
} }
case CaptureRequest::GRAPHICAL_MODE: {
QString&& path = request.path();
doLater(request.delay(), this, [this, id, path]() {
this->startVisualCapture(id, path);
});
break;
}
default:
emit captureFailed(id);
break;
}
} }
// creation of a new capture in GUI mode // creation of a new capture in GUI mode
void void Controller::startVisualCapture(const uint id,
Controller::startVisualCapture(const uint id, const QString& forcedSavePath) const QString& forcedSavePath)
{ {
if (!m_captureWindow) { if (!m_captureWindow) {
QWidget* modalWidget = nullptr; QWidget* modalWidget = nullptr;
do { do {
modalWidget = qApp->activeModalWidget(); modalWidget = qApp->activeModalWidget();
if (modalWidget) { if (modalWidget) {
modalWidget->close(); modalWidget->close();
modalWidget->deleteLater(); modalWidget->deleteLater();
} }
} while (modalWidget); } while (modalWidget);
m_captureWindow = new CaptureWidget(id, forcedSavePath); m_captureWindow = new CaptureWidget(id, forcedSavePath);
// m_captureWindow = new CaptureWidget(id, forcedSavePath, false); // debug // m_captureWindow = new CaptureWidget(id, forcedSavePath, false); //
connect(m_captureWindow, // debug
&CaptureWidget::captureFailed, connect(m_captureWindow,
this, &CaptureWidget::captureFailed,
&Controller::captureFailed); this,
connect(m_captureWindow, &Controller::captureFailed);
&CaptureWidget::captureTaken, connect(m_captureWindow,
this, &CaptureWidget::captureTaken,
&Controller::captureTaken); this,
&Controller::captureTaken);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
m_captureWindow->show(); m_captureWindow->show();
#else #else
m_captureWindow->showFullScreen(); m_captureWindow->showFullScreen();
// m_captureWindow->show(); // Debug // m_captureWindow->show(); // Debug
#endif #endif
} else { } else {
emit captureFailed(id); emit captureFailed(id);
} }
} }
void void Controller::startScreenGrab(const uint id, const int screenNumber)
Controller::startScreenGrab(const uint id, const int screenNumber)
{ {
bool ok = true; bool ok = true;
int n = screenNumber; int n = screenNumber;
if (n < 0) { if (n < 0) {
QPoint globalCursorPos = QCursor::pos(); QPoint globalCursorPos = QCursor::pos();
n = qApp->desktop()->screenNumber(globalCursorPos); n = qApp->desktop()->screenNumber(globalCursorPos);
} }
QPixmap p(ScreenGrabber().grabScreen(n, ok)); QPixmap p(ScreenGrabber().grabScreen(n, ok));
if (ok) { if (ok) {
emit captureTaken(id, p); emit captureTaken(id, p);
} else { } else {
emit captureFailed(id); emit captureFailed(id);
} }
} }
// creation of the configuration window // creation of the configuration window
void void Controller::openConfigWindow()
Controller::openConfigWindow()
{ {
if (!m_configWindow) { if (!m_configWindow) {
m_configWindow = new ConfigWindow(); m_configWindow = new ConfigWindow();
m_configWindow->show(); m_configWindow->show();
} }
} }
// creation of the window of information // creation of the window of information
void void Controller::openInfoWindow()
Controller::openInfoWindow()
{ {
if (!m_infoWindow) { if (!m_infoWindow) {
m_infoWindow = new InfoWindow(); m_infoWindow = new InfoWindow();
}
}
void
Controller::openLauncherWindow()
{
if (!m_launcherWindow) {
m_launcherWindow = new CaptureLauncher();
}
m_launcherWindow->show();
}
void
Controller::enableTrayIcon()
{
if (m_trayIcon) {
return;
}
ConfigHandler().setDisabledTrayIcon(false);
QAction* captureAction = new QAction(tr("&Take Screenshot"), this);
connect(captureAction, &QAction::triggered, this, [this]() {
// Wait 400 ms to hide the QMenu
doLater(400, this, [this]() { this->startVisualCapture(); });
});
QAction* launcherAction = new QAction(tr("&Open Launcher"), this);
connect(
launcherAction, &QAction::triggered, this, &Controller::openLauncherWindow);
QAction* configAction = new QAction(tr("&Configuration"), this);
connect(
configAction, &QAction::triggered, this, &Controller::openConfigWindow);
QAction* infoAction = new QAction(tr("&About"), this);
connect(infoAction, &QAction::triggered, this, &Controller::openInfoWindow);
QAction* quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
QMenu* trayIconMenu = new QMenu();
trayIconMenu->addAction(captureAction);
trayIconMenu->addAction(launcherAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(configAction);
trayIconMenu->addAction(infoAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
m_trayIcon = new QSystemTrayIcon();
m_trayIcon->setToolTip(QStringLiteral("Flameshot"));
m_trayIcon->setContextMenu(trayIconMenu);
QIcon trayicon =
QIcon::fromTheme("flameshot-tray", QIcon(":img/app/flameshot.png"));
m_trayIcon->setIcon(trayicon);
auto trayIconActivated = [this](QSystemTrayIcon::ActivationReason r) {
if (r == QSystemTrayIcon::Trigger) {
startVisualCapture();
} }
};
connect(m_trayIcon, &QSystemTrayIcon::activated, this, trayIconActivated);
m_trayIcon->show();
} }
void void Controller::openLauncherWindow()
Controller::disableTrayIcon() {
if (!m_launcherWindow) {
m_launcherWindow = new CaptureLauncher();
}
m_launcherWindow->show();
}
void Controller::enableTrayIcon()
{
if (m_trayIcon) {
return;
}
ConfigHandler().setDisabledTrayIcon(false);
QAction* captureAction = new QAction(tr("&Take Screenshot"), this);
connect(captureAction, &QAction::triggered, this, [this]() {
// Wait 400 ms to hide the QMenu
doLater(400, this, [this]() { this->startVisualCapture(); });
});
QAction* launcherAction = new QAction(tr("&Open Launcher"), this);
connect(launcherAction,
&QAction::triggered,
this,
&Controller::openLauncherWindow);
QAction* configAction = new QAction(tr("&Configuration"), this);
connect(
configAction, &QAction::triggered, this, &Controller::openConfigWindow);
QAction* infoAction = new QAction(tr("&About"), this);
connect(infoAction, &QAction::triggered, this, &Controller::openInfoWindow);
QAction* quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
QMenu* trayIconMenu = new QMenu();
trayIconMenu->addAction(captureAction);
trayIconMenu->addAction(launcherAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(configAction);
trayIconMenu->addAction(infoAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
m_trayIcon = new QSystemTrayIcon();
m_trayIcon->setToolTip(QStringLiteral("Flameshot"));
m_trayIcon->setContextMenu(trayIconMenu);
QIcon trayicon =
QIcon::fromTheme("flameshot-tray", QIcon(":img/app/flameshot.png"));
m_trayIcon->setIcon(trayicon);
auto trayIconActivated = [this](QSystemTrayIcon::ActivationReason r) {
if (r == QSystemTrayIcon::Trigger) {
startVisualCapture();
}
};
connect(m_trayIcon, &QSystemTrayIcon::activated, this, trayIconActivated);
m_trayIcon->show();
}
void Controller::disableTrayIcon()
{ {
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
if (m_trayIcon) { if (m_trayIcon) {
m_trayIcon->deleteLater(); m_trayIcon->deleteLater();
} }
ConfigHandler().setDisabledTrayIcon(true); ConfigHandler().setDisabledTrayIcon(true);
#endif #endif
} }
void void Controller::sendTrayNotification(const QString& text,
Controller::sendTrayNotification(const QString& text, const QString& title,
const QString& title, const int timeout)
const int timeout)
{ {
if (m_trayIcon) { if (m_trayIcon) {
m_trayIcon->showMessage(title, text, QSystemTrayIcon::Information, timeout); m_trayIcon->showMessage(
} title, text, QSystemTrayIcon::Information, timeout);
}
} }
void void Controller::updateConfigComponents()
Controller::updateConfigComponents()
{ {
if (m_configWindow) { if (m_configWindow) {
m_configWindow->updateChildren(); m_configWindow->updateChildren();
} }
} }
void void Controller::startFullscreenCapture(const uint id)
Controller::startFullscreenCapture(const uint id)
{ {
bool ok = true; bool ok = true;
QPixmap p(ScreenGrabber().grabEntireDesktop(ok)); QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
if (ok) { if (ok) {
emit captureTaken(id, p); emit captureTaken(id, p);
} else { } else {
emit captureFailed(id); emit captureFailed(id);
} }
} }
void void Controller::handleCaptureTaken(uint id, QPixmap p)
Controller::handleCaptureTaken(uint id, QPixmap p)
{ {
auto it = m_requestMap.find(id); auto it = m_requestMap.find(id);
if (it != m_requestMap.end()) { if (it != m_requestMap.end()) {
it.value().exportCapture(p); it.value().exportCapture(p);
m_requestMap.erase(it); m_requestMap.erase(it);
} }
if (ConfigHandler().closeAfterScreenshotValue()) { if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit(); QApplication::quit();
} }
} }
void void Controller::handleCaptureFailed(uint id)
Controller::handleCaptureFailed(uint id)
{ {
m_requestMap.remove(id); m_requestMap.remove(id);
if (ConfigHandler().closeAfterScreenshotValue()) { if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit(); QApplication::quit();
} }
} }
void void Controller::doLater(int msec, QObject* receiver, lambda func)
Controller::doLater(int msec, QObject* receiver, lambda func)
{ {
QTimer* timer = new QTimer(receiver); QTimer* timer = new QTimer(receiver);
QObject::connect(timer, &QTimer::timeout, receiver, [timer, func]() { QObject::connect(timer, &QTimer::timeout, receiver, [timer, func]() {
func(); func();
timer->deleteLater(); timer->deleteLater();
}); });
timer->setInterval(msec); timer->setInterval(msec);
timer->start(); timer->start();
} }

View File

@@ -34,55 +34,55 @@ using lambda = std::function<void(void)>;
class Controller : public QObject class Controller : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
static Controller* getInstance(); static Controller* getInstance();
Controller(const Controller&) = delete; Controller(const Controller&) = delete;
void operator=(const Controller&) = delete; void operator=(const Controller&) = delete;
void enableExports(); void enableExports();
signals: signals:
void captureTaken(uint id, QPixmap p); void captureTaken(uint id, QPixmap p);
void captureFailed(uint id); void captureFailed(uint id);
public slots: public slots:
void requestCapture(const CaptureRequest& request); void requestCapture(const CaptureRequest& request);
void openConfigWindow(); void openConfigWindow();
void openInfoWindow(); void openInfoWindow();
void openLauncherWindow(); void openLauncherWindow();
void enableTrayIcon(); void enableTrayIcon();
void disableTrayIcon(); void disableTrayIcon();
void sendTrayNotification( void sendTrayNotification(
const QString& text, const QString& text,
const QString& title = QStringLiteral("Flameshot Info"), const QString& title = QStringLiteral("Flameshot Info"),
const int timeout = 5000); const int timeout = 5000);
void updateConfigComponents(); void updateConfigComponents();
private slots: private slots:
void startFullscreenCapture(const uint id = 0); void startFullscreenCapture(const uint id = 0);
void startVisualCapture(const uint id = 0, void startVisualCapture(const uint id = 0,
const QString& forcedSavePath = QString()); const QString& forcedSavePath = QString());
void startScreenGrab(const uint id = 0, const int screenNumber = -1); void startScreenGrab(const uint id = 0, const int screenNumber = -1);
void handleCaptureTaken(uint id, QPixmap p); void handleCaptureTaken(uint id, QPixmap p);
void handleCaptureFailed(uint id); void handleCaptureFailed(uint id);
private: private:
Controller(); Controller();
// replace QTimer::singleShot introduced in Qt 5.4 // replace QTimer::singleShot introduced in Qt 5.4
// the actual target Qt version is 5.3 // the actual target Qt version is 5.3
void doLater(int msec, QObject* receiver, lambda func); void doLater(int msec, QObject* receiver, lambda func);
QMap<uint, CaptureRequest> m_requestMap; QMap<uint, CaptureRequest> m_requestMap;
QPointer<CaptureWidget> m_captureWindow; QPointer<CaptureWidget> m_captureWindow;
QPointer<InfoWindow> m_infoWindow; QPointer<InfoWindow> m_infoWindow;
QPointer<CaptureLauncher> m_launcherWindow; QPointer<CaptureLauncher> m_launcherWindow;
QPointer<ConfigWindow> m_configWindow; QPointer<ConfigWindow> m_configWindow;
QPointer<QSystemTrayIcon> m_trayIcon; QPointer<QSystemTrayIcon> m_trayIcon;
}; };

View File

@@ -25,102 +25,94 @@
FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent) FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent)
: QDBusAbstractAdaptor(parent) : QDBusAbstractAdaptor(parent)
{ {
auto controller = Controller::getInstance(); auto controller = Controller::getInstance();
connect(controller, connect(controller,
&Controller::captureFailed, &Controller::captureFailed,
this, this,
&FlameshotDBusAdapter::captureFailed); &FlameshotDBusAdapter::captureFailed);
connect(controller, connect(controller,
&Controller::captureTaken, &Controller::captureTaken,
this, this,
&FlameshotDBusAdapter::handleCaptureTaken); &FlameshotDBusAdapter::handleCaptureTaken);
} }
FlameshotDBusAdapter::~FlameshotDBusAdapter() {} FlameshotDBusAdapter::~FlameshotDBusAdapter() {}
void void FlameshotDBusAdapter::graphicCapture(QString path, int delay, uint id)
FlameshotDBusAdapter::graphicCapture(QString path, int delay, uint id)
{ {
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path); CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
// if (toClipboard) { // if (toClipboard) {
// req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); // req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
// } // }
req.setStaticID(id); req.setStaticID(id);
Controller::getInstance()->requestCapture(req); Controller::getInstance()->requestCapture(req);
} }
void void FlameshotDBusAdapter::fullScreen(QString path,
FlameshotDBusAdapter::fullScreen(QString path, bool toClipboard,
bool toClipboard, int delay,
int delay, uint id)
uint id)
{ {
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, path); CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, path);
if (toClipboard) { if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
} }
if (!path.isEmpty()) { if (!path.isEmpty()) {
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
} }
req.setStaticID(id); req.setStaticID(id);
Controller::getInstance()->requestCapture(req); Controller::getInstance()->requestCapture(req);
} }
void void FlameshotDBusAdapter::openLauncher()
FlameshotDBusAdapter::openLauncher()
{ {
Controller::getInstance()->openLauncherWindow(); Controller::getInstance()->openLauncherWindow();
} }
void void FlameshotDBusAdapter::captureScreen(int number,
FlameshotDBusAdapter::captureScreen(int number, QString path,
QString path, bool toClipboard,
bool toClipboard, int delay,
int delay, uint id)
uint id)
{ {
CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, path, number); CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, path, number);
if (toClipboard) { if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
} }
if (!path.isEmpty()) { if (!path.isEmpty()) {
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
} }
req.setStaticID(id); req.setStaticID(id);
Controller::getInstance()->requestCapture(req); Controller::getInstance()->requestCapture(req);
} }
void void FlameshotDBusAdapter::openConfig()
FlameshotDBusAdapter::openConfig()
{ {
Controller::getInstance()->openConfigWindow(); Controller::getInstance()->openConfigWindow();
} }
void void FlameshotDBusAdapter::trayIconEnabled(bool enabled)
FlameshotDBusAdapter::trayIconEnabled(bool enabled)
{ {
auto controller = Controller::getInstance(); auto controller = Controller::getInstance();
if (enabled) { if (enabled) {
controller->enableTrayIcon(); controller->enableTrayIcon();
} else { } else {
controller->disableTrayIcon(); controller->disableTrayIcon();
} }
} }
void void FlameshotDBusAdapter::autostartEnabled(bool enabled)
FlameshotDBusAdapter::autostartEnabled(bool enabled)
{ {
ConfigHandler().setStartupLaunch(enabled); ConfigHandler().setStartupLaunch(enabled);
auto controller = Controller::getInstance(); auto controller = Controller::getInstance();
// Autostart is not saved in a .ini file, requires manual update // Autostart is not saved in a .ini file, requires manual update
controller->updateConfigComponents(); controller->updateConfigComponents();
} }
void void FlameshotDBusAdapter::handleCaptureTaken(uint id, const QPixmap& p)
FlameshotDBusAdapter::handleCaptureTaken(uint id, const QPixmap& p)
{ {
QByteArray byteArray; QByteArray byteArray;
QBuffer buffer(&byteArray); QBuffer buffer(&byteArray);
p.save(&buffer, "PNG"); p.save(&buffer, "PNG");
emit captureTaken(id, byteArray); emit captureTaken(id, byteArray);
} }

View File

@@ -22,30 +22,33 @@
class FlameshotDBusAdapter : public QDBusAbstractAdaptor class FlameshotDBusAdapter : public QDBusAbstractAdaptor
{ {
Q_OBJECT Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.flameshot.Flameshot") Q_CLASSINFO("D-Bus Interface", "org.flameshot.Flameshot")
public: public:
explicit FlameshotDBusAdapter(QObject* parent = nullptr); explicit FlameshotDBusAdapter(QObject* parent = nullptr);
virtual ~FlameshotDBusAdapter(); virtual ~FlameshotDBusAdapter();
signals: signals:
void captureTaken(uint id, QByteArray rawImage); void captureTaken(uint id, QByteArray rawImage);
void captureFailed(uint id); void captureFailed(uint id);
public slots: public slots:
Q_NOREPLY void graphicCapture(QString path, int delay, uint id); Q_NOREPLY void graphicCapture(QString path, int delay, uint id);
Q_NOREPLY void fullScreen(QString path, bool toClipboard, int delay, uint id); Q_NOREPLY void fullScreen(QString path,
Q_NOREPLY void captureScreen(int number, bool toClipboard,
QString path, int delay,
bool toClipboard, uint id);
int delay, Q_NOREPLY void captureScreen(int number,
uint id); QString path,
Q_NOREPLY void openLauncher(); bool toClipboard,
Q_NOREPLY void openConfig(); int delay,
Q_NOREPLY void trayIconEnabled(bool enabled); uint id);
Q_NOREPLY void autostartEnabled(bool enabled); Q_NOREPLY void openLauncher();
Q_NOREPLY void openConfig();
Q_NOREPLY void trayIconEnabled(bool enabled);
Q_NOREPLY void autostartEnabled(bool enabled);
private slots: private slots:
void handleCaptureTaken(uint id, const QPixmap& p); void handleCaptureTaken(uint id, const QPixmap& p);
}; };

View File

@@ -22,30 +22,29 @@
GlobalShortcutFilter::GlobalShortcutFilter(QObject* parent) GlobalShortcutFilter::GlobalShortcutFilter(QObject* parent)
: QObject(parent) : QObject(parent)
{ {
// Forced Print Screen // Forced Print Screen
if (RegisterHotKey(NULL, 1, 0, VK_SNAPSHOT)) { if (RegisterHotKey(NULL, 1, 0, VK_SNAPSHOT)) {
// ok // ok
} }
} }
bool bool GlobalShortcutFilter::nativeEventFilter(const QByteArray& eventType,
GlobalShortcutFilter::nativeEventFilter(const QByteArray& eventType, void* message,
void* message, long* result)
long* result)
{ {
Q_UNUSED(eventType); Q_UNUSED(eventType);
Q_UNUSED(result); Q_UNUSED(result);
MSG* msg = static_cast<MSG*>(message); MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY) { if (msg->message == WM_HOTKEY) {
// const quint32 keycode = HIWORD(msg->lParam); // const quint32 keycode = HIWORD(msg->lParam);
// const quint32 modifiers = LOWORD(msg->lParam); // const quint32 modifiers = LOWORD(msg->lParam);
// TODO: this is just a temporal workwrround, proper global // TODO: this is just a temporal workwrround, proper global
// support would need custom shortcuts defined by the user. // support would need custom shortcuts defined by the user.
Controller::getInstance()->requestCapture( Controller::getInstance()->requestCapture(
CaptureRequest(CaptureRequest::GRAPHICAL_MODE)); CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
return true; return true;
} }
return false; return false;
} }

View File

@@ -24,20 +24,20 @@ class GlobalShortcutFilter
: public QObject : public QObject
, public QAbstractNativeEventFilter , public QAbstractNativeEventFilter
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GlobalShortcutFilter(QObject* parent = nullptr); explicit GlobalShortcutFilter(QObject* parent = nullptr);
bool nativeEventFilter(const QByteArray& eventType, bool nativeEventFilter(const QByteArray& eventType,
void* message, void* message,
long* result); long* result);
signals: signals:
void printPressed(); void printPressed();
private: private:
quint32 getNativeModifier(Qt::KeyboardModifiers modifiers); quint32 getNativeModifier(Qt::KeyboardModifiers modifiers);
quint32 nativeKeycode(Qt::Key key); quint32 nativeKeycode(Qt::Key key);
bool registerShortcut(quint32 nativeKey, quint32 nativeMods); bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
}; };

View File

@@ -37,431 +37,448 @@
#include <QDBusMessage> #include <QDBusMessage>
#endif #endif
int int main(int argc, char* argv[])
main(int argc, char* argv[])
{ {
// required for the button serialization // required for the button serialization
// TODO: change to QVector in v1.0 // TODO: change to QVector in v1.0
qRegisterMetaTypeStreamOperators<QList<int>>("QList<int>"); qRegisterMetaTypeStreamOperators<QList<int>>("QList<int>");
qApp->setApplicationVersion(static_cast<QString>(APP_VERSION)); qApp->setApplicationVersion(static_cast<QString>(APP_VERSION));
// no arguments, just launch Flameshot // no arguments, just launch Flameshot
if (argc == 1) { if (argc == 1) {
SingleApplication app(argc, argv); SingleApplication app(argc, argv);
QTranslator translator, qtTranslator; QTranslator translator, qtTranslator;
QStringList trPaths = PathInfo::translationsPaths(); QStringList trPaths = PathInfo::translationsPaths();
for (const QString& path : trPaths) { for (const QString& path : trPaths) {
bool match = translator.load(QLocale(), bool match = translator.load(QLocale(),
QStringLiteral("Internationalization"), QStringLiteral("Internationalization"),
QStringLiteral("_"), QStringLiteral("_"),
path); path);
if (match) { if (match) {
break; break;
} }
} }
qtTranslator.load(QLocale::system(), qtTranslator.load(
"qt", QLocale::system(),
"_", "qt",
QLibraryInfo::location(QLibraryInfo::TranslationsPath)); "_",
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&translator); app.installTranslator(&translator);
app.installTranslator(&qtTranslator); app.installTranslator(&qtTranslator);
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
app.setApplicationName(QStringLiteral("flameshot")); app.setApplicationName(QStringLiteral("flameshot"));
app.setOrganizationName(QStringLiteral("flameshot")); app.setOrganizationName(QStringLiteral("flameshot"));
auto c = Controller::getInstance(); auto c = Controller::getInstance();
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
new FlameshotDBusAdapter(c); new FlameshotDBusAdapter(c);
QDBusConnection dbus = QDBusConnection::sessionBus(); QDBusConnection dbus = QDBusConnection::sessionBus();
if (!dbus.isConnected()) { if (!dbus.isConnected()) {
SystemNotification().sendMessage( SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus")); QObject::tr("Unable to connect via DBus"));
} }
dbus.registerObject(QStringLiteral("/"), c); dbus.registerObject(QStringLiteral("/"), c);
dbus.registerService(QStringLiteral("org.flameshot.Flameshot")); dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
#endif #endif
// Exporting captures must be connected after the dbus interface // Exporting captures must be connected after the dbus interface
// or the dbus signal gets blocked until we end the exports. // or the dbus signal gets blocked until we end the exports.
c->enableExports(); c->enableExports();
return app.exec(); return app.exec();
} }
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
/*--------------| /*--------------|
* CLI parsing | * CLI parsing |
* ------------*/ * ------------*/
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
app.setApplicationName(QStringLiteral("flameshot")); app.setApplicationName(QStringLiteral("flameshot"));
app.setOrganizationName(QStringLiteral("flameshot")); app.setOrganizationName(QStringLiteral("flameshot"));
app.setApplicationVersion(qApp->applicationVersion()); app.setApplicationVersion(qApp->applicationVersion());
CommandLineParser parser; CommandLineParser parser;
// Add description // Add description
parser.setDescription( parser.setDescription(
QObject::tr("Powerful yet simple to use screenshot software.")); QObject::tr("Powerful yet simple to use screenshot software."));
parser.setGeneralErrorMessage(QObject::tr("See") + " flameshot --help."); parser.setGeneralErrorMessage(QObject::tr("See") + " flameshot --help.");
// Arguments // Arguments
CommandArgument fullArgument(QStringLiteral("full"), CommandArgument fullArgument(QStringLiteral("full"),
QObject::tr("Capture the entire desktop.")); QObject::tr("Capture the entire desktop."));
CommandArgument launcherArgument(QStringLiteral("launcher"), CommandArgument launcherArgument(QStringLiteral("launcher"),
QObject::tr("Open the capture launcher.")); QObject::tr("Open the capture launcher."));
CommandArgument guiArgument( CommandArgument guiArgument(
QStringLiteral("gui"), QObject::tr("Start a manual capture in GUI mode.")); QStringLiteral("gui"),
CommandArgument configArgument(QStringLiteral("config"), QObject::tr("Start a manual capture in GUI mode."));
QObject::tr("Configure") + " flameshot."); CommandArgument configArgument(QStringLiteral("config"),
CommandArgument screenArgument(QStringLiteral("screen"), QObject::tr("Configure") + " flameshot.");
QObject::tr("Capture a single screen.")); CommandArgument screenArgument(QStringLiteral("screen"),
QObject::tr("Capture a single screen."));
// Options // Options
CommandOption pathOption({ "p", "path" }, CommandOption pathOption(
QObject::tr("Path where the capture will be saved"), { "p", "path" },
QStringLiteral("path")); QObject::tr("Path where the capture will be saved"),
CommandOption clipboardOption( QStringLiteral("path"));
{ "c", "clipboard" }, QObject::tr("Save the capture to the clipboard")); CommandOption clipboardOption(
CommandOption delayOption({ "d", "delay" }, { "c", "clipboard" }, QObject::tr("Save the capture to the clipboard"));
QObject::tr("Delay time in milliseconds"), CommandOption delayOption({ "d", "delay" },
QStringLiteral("milliseconds")); QObject::tr("Delay time in milliseconds"),
CommandOption filenameOption({ "f", "filename" }, QStringLiteral("milliseconds"));
QObject::tr("Set the filename pattern"), CommandOption filenameOption({ "f", "filename" },
QStringLiteral("pattern")); QObject::tr("Set the filename pattern"),
CommandOption trayOption({ "t", "trayicon" }, QStringLiteral("pattern"));
QObject::tr("Enable or disable the trayicon"), CommandOption trayOption({ "t", "trayicon" },
QStringLiteral("bool")); QObject::tr("Enable or disable the trayicon"),
CommandOption autostartOption({ "a", "autostart" }, QStringLiteral("bool"));
QObject::tr("Enable or disable run at startup"), CommandOption autostartOption(
QStringLiteral("bool")); { "a", "autostart" },
CommandOption showHelpOption( QObject::tr("Enable or disable run at startup"),
{ "s", "showhelp" }, QStringLiteral("bool"));
QObject::tr("Show the help message in the capture mode"), CommandOption showHelpOption(
QStringLiteral("bool")); { "s", "showhelp" },
CommandOption mainColorOption({ "m", "maincolor" }, QObject::tr("Show the help message in the capture mode"),
QObject::tr("Define the main UI color"), QStringLiteral("bool"));
QStringLiteral("color-code")); CommandOption mainColorOption({ "m", "maincolor" },
CommandOption contrastColorOption({ "k", "contrastcolor" }, QObject::tr("Define the main UI color"),
QObject::tr("Define the contrast UI color"), QStringLiteral("color-code"));
QStringLiteral("color-code")); CommandOption contrastColorOption(
CommandOption rawImageOption({ "r", "raw" }, { "k", "contrastcolor" },
QObject::tr("Print raw PNG capture")); QObject::tr("Define the contrast UI color"),
CommandOption screenNumberOption( QStringLiteral("color-code"));
{ "n", "number" }, CommandOption rawImageOption({ "r", "raw" },
QObject::tr("Define the screen to capture") + ",\n" + QObject::tr("Print raw PNG capture"));
QObject::tr("default: screen containing the cursor"), CommandOption screenNumberOption(
QObject::tr("Screen number"), { "n", "number" },
QStringLiteral("-1")); QObject::tr("Define the screen to capture") + ",\n" +
QObject::tr("default: screen containing the cursor"),
QObject::tr("Screen number"),
QStringLiteral("-1"));
// Add checkers // Add checkers
auto colorChecker = [](const QString& colorCode) -> bool { auto colorChecker = [](const QString& colorCode) -> bool {
QColor parsedColor(colorCode); QColor parsedColor(colorCode);
return parsedColor.isValid() && parsedColor.alphaF() == 1.0; return parsedColor.isValid() && parsedColor.alphaF() == 1.0;
}; };
QString colorErr = QString colorErr =
QObject::tr("Invalid color, " QObject::tr("Invalid color, "
"this flag supports the following formats:\n" "this flag supports the following formats:\n"
"- #RGB (each of R, G, and B is a single hex digit)\n" "- #RGB (each of R, G, and B is a single hex digit)\n"
"- #RRGGBB\n- #RRRGGGBBB\n" "- #RRGGBB\n- #RRRGGGBBB\n"
"- #RRRRGGGGBBBB\n" "- #RRRRGGGGBBBB\n"
"- Named colors like 'blue' or 'red'\n" "- Named colors like 'blue' or 'red'\n"
"You may need to escape the '#' sign as in '\\#FFF'"); "You may need to escape the '#' sign as in '\\#FFF'");
const QString delayErr = const QString delayErr =
QObject::tr("Invalid delay, it must be higher than 0"); QObject::tr("Invalid delay, it must be higher than 0");
const QString numberErr = const QString numberErr =
QObject::tr("Invalid screen number, it must be non negative"); QObject::tr("Invalid screen number, it must be non negative");
auto numericChecker = [](const QString& delayValue) -> bool { auto numericChecker = [](const QString& delayValue) -> bool {
int value = delayValue.toInt(); int value = delayValue.toInt();
return value >= 0; return value >= 0;
}; };
const QString pathErr = const QString pathErr =
QObject::tr("Invalid path, it must be a real path in the system"); QObject::tr("Invalid path, it must be a real path in the system");
auto pathChecker = [pathErr](const QString& pathValue) -> bool { auto pathChecker = [pathErr](const QString& pathValue) -> bool {
bool res = QDir(pathValue).exists(); bool res = QDir(pathValue).exists();
if (!res) { if (!res) {
SystemNotification().sendMessage(QObject::tr(pathErr.toLatin1().data())); SystemNotification().sendMessage(
} QObject::tr(pathErr.toLatin1().data()));
return res; }
}; return res;
};
const QString booleanErr = const QString booleanErr =
QObject::tr("Invalid value, it must be defined as 'true' or 'false'"); QObject::tr("Invalid value, it must be defined as 'true' or 'false'");
auto booleanChecker = [](const QString& value) -> bool { auto booleanChecker = [](const QString& value) -> bool {
return value == QLatin1String("true") || value == QLatin1String("false"); return value == QLatin1String("true") ||
}; value == QLatin1String("false");
};
contrastColorOption.addChecker(colorChecker, colorErr); contrastColorOption.addChecker(colorChecker, colorErr);
mainColorOption.addChecker(colorChecker, colorErr); mainColorOption.addChecker(colorChecker, colorErr);
delayOption.addChecker(numericChecker, delayErr); delayOption.addChecker(numericChecker, delayErr);
pathOption.addChecker(pathChecker, pathErr); pathOption.addChecker(pathChecker, pathErr);
trayOption.addChecker(booleanChecker, booleanErr); trayOption.addChecker(booleanChecker, booleanErr);
autostartOption.addChecker(booleanChecker, booleanErr); autostartOption.addChecker(booleanChecker, booleanErr);
showHelpOption.addChecker(booleanChecker, booleanErr); showHelpOption.addChecker(booleanChecker, booleanErr);
screenNumberOption.addChecker(numericChecker, numberErr); screenNumberOption.addChecker(numericChecker, numberErr);
// Relationships // Relationships
parser.AddArgument(guiArgument); parser.AddArgument(guiArgument);
parser.AddArgument(screenArgument); parser.AddArgument(screenArgument);
parser.AddArgument(fullArgument); parser.AddArgument(fullArgument);
parser.AddArgument(launcherArgument); parser.AddArgument(launcherArgument);
parser.AddArgument(configArgument); parser.AddArgument(configArgument);
auto helpOption = parser.addHelpOption(); auto helpOption = parser.addHelpOption();
auto versionOption = parser.addVersionOption(); auto versionOption = parser.addVersionOption();
parser.AddOptions({ pathOption, delayOption, rawImageOption }, guiArgument); parser.AddOptions({ pathOption, delayOption, rawImageOption }, guiArgument);
parser.AddOptions({ screenNumberOption, parser.AddOptions({ screenNumberOption,
clipboardOption, clipboardOption,
pathOption, pathOption,
delayOption, delayOption,
rawImageOption }, rawImageOption },
screenArgument); screenArgument);
parser.AddOptions( parser.AddOptions(
{ pathOption, clipboardOption, delayOption, rawImageOption }, fullArgument); { pathOption, clipboardOption, delayOption, rawImageOption },
parser.AddOptions({ autostartOption, fullArgument);
filenameOption, parser.AddOptions({ autostartOption,
trayOption, filenameOption,
showHelpOption, trayOption,
mainColorOption, showHelpOption,
contrastColorOption }, mainColorOption,
configArgument); contrastColorOption },
// Parse configArgument);
if (!parser.parse(app.arguments())) { // Parse
goto finish; if (!parser.parse(app.arguments())) {
} goto finish;
// PROCESS DATA
//--------------
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
QDBusMessage m =
QDBusMessage::createMethodCall(QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("openLauncher"));
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
} else if (parser.isSet(guiArgument)) { // GUI
QString pathValue = parser.value(pathOption);
int delay = parser.value(delayOption).toInt();
bool isRaw = parser.isSet(rawImageOption);
DBusUtils dbusUtils;
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, pathValue);
uint id = req.id();
// Send message
QDBusMessage m =
QDBusMessage::createMethodCall(QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("graphicCapture"));
m << pathValue << delay << id;
QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m);
if (isRaw) {
dbusUtils.connectPrintCapture(sessionBus, id);
QTimer t;
t.setInterval(delay + 1000 * 60 * 15); // 15 minutes timeout
QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
t.start();
// wait
return app.exec();
}
} else if (parser.isSet(fullArgument)) { // FULL
QString pathValue = parser.value(pathOption);
int delay = parser.value(delayOption).toInt();
bool toClipboard = parser.isSet(clipboardOption);
bool isRaw = parser.isSet(rawImageOption);
// Not a valid command
if (!isRaw && !toClipboard && pathValue.isEmpty()) {
QTextStream out(stdout);
out << "Invalid format, set where to save the content with one of "
<< "the following flags:\n "
<< pathOption.dashedNames().join(QStringLiteral(", ")) << "\n "
<< rawImageOption.dashedNames().join(QStringLiteral(", ")) << "\n "
<< clipboardOption.dashedNames().join(QStringLiteral(", ")) << "\n\n";
parser.parse(QStringList() << argv[0] << QStringLiteral("full")
<< QStringLiteral("-h"));
goto finish;
} }
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, pathValue); // PROCESS DATA
if (toClipboard) { //--------------
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
} } else if (parser.isSet(launcherArgument)) { // LAUNCHER
if (!pathValue.isEmpty()) { QDBusMessage m = QDBusMessage::createMethodCall(
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); QStringLiteral("org.flameshot.Flameshot"),
} QStringLiteral("/"),
uint id = req.id(); QLatin1String(""),
DBusUtils dbusUtils; QStringLiteral("openLauncher"));
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
} else if (parser.isSet(guiArgument)) { // GUI
QString pathValue = parser.value(pathOption);
int delay = parser.value(delayOption).toInt();
bool isRaw = parser.isSet(rawImageOption);
DBusUtils dbusUtils;
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, pathValue);
uint id = req.id();
// Send message // Send message
QDBusMessage m = QDBusMessage m = QDBusMessage::createMethodCall(
QDBusMessage::createMethodCall(QStringLiteral("org.flameshot.Flameshot"), QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"), QStringLiteral("/"),
QLatin1String(""), QLatin1String(""),
QStringLiteral("fullScreen")); QStringLiteral("graphicCapture"));
m << pathValue << toClipboard << delay << id; m << pathValue << delay << id;
QDBusConnection sessionBus = QDBusConnection::sessionBus(); QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus); dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m); sessionBus.call(m);
if (isRaw) { if (isRaw) {
dbusUtils.connectPrintCapture(sessionBus, id); dbusUtils.connectPrintCapture(sessionBus, id);
// timeout just in case QTimer t;
QTimer t; t.setInterval(delay + 1000 * 60 * 15); // 15 minutes timeout
t.setInterval(delay + 2000); QObject::connect(
QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); &t, &QTimer::timeout, qApp, &QCoreApplication::quit);
t.start(); t.start();
// wait // wait
return app.exec(); return app.exec();
} }
} else if (parser.isSet(screenArgument)) { // SCREEN } else if (parser.isSet(fullArgument)) { // FULL
QString numberStr = parser.value(screenNumberOption); QString pathValue = parser.value(pathOption);
int number = int delay = parser.value(delayOption).toInt();
numberStr.startsWith(QLatin1String("-")) ? -1 : numberStr.toInt(); bool toClipboard = parser.isSet(clipboardOption);
QString pathValue = parser.value(pathOption); bool isRaw = parser.isSet(rawImageOption);
int delay = parser.value(delayOption).toInt(); // Not a valid command
bool toClipboard = parser.isSet(clipboardOption); if (!isRaw && !toClipboard && pathValue.isEmpty()) {
bool isRaw = parser.isSet(rawImageOption); QTextStream out(stdout);
// Not a valid command out << "Invalid format, set where to save the content with one of "
if (!isRaw && !toClipboard && pathValue.isEmpty()) { << "the following flags:\n "
QTextStream out(stdout); << pathOption.dashedNames().join(QStringLiteral(", ")) << "\n "
out << "Invalid format, set where to save the content with one of " << rawImageOption.dashedNames().join(QStringLiteral(", "))
<< "the following flags:\n " << "\n "
<< pathOption.dashedNames().join(QStringLiteral(", ")) << "\n " << clipboardOption.dashedNames().join(QStringLiteral(", "))
<< rawImageOption.dashedNames().join(QStringLiteral(", ")) << "\n " << "\n\n";
<< clipboardOption.dashedNames().join(QStringLiteral(", ")) << "\n\n"; parser.parse(QStringList() << argv[0] << QStringLiteral("full")
parser.parse(QStringList() << argv[0] << QStringLiteral("screen") << QStringLiteral("-h"));
<< QStringLiteral("-h")); goto finish;
goto finish; }
}
CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, pathValue, number); CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, pathValue);
if (toClipboard) { if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK); req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
} }
if (!pathValue.isEmpty()) { if (!pathValue.isEmpty()) {
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK); req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
} }
uint id = req.id(); uint id = req.id();
DBusUtils dbusUtils; DBusUtils dbusUtils;
// Send message // Send message
QDBusMessage m = QDBusMessage m = QDBusMessage::createMethodCall(
QDBusMessage::createMethodCall(QStringLiteral("org.flameshot.Flameshot"), QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"), QStringLiteral("/"),
QLatin1String(""), QLatin1String(""),
QStringLiteral("captureScreen")); QStringLiteral("fullScreen"));
m << number << pathValue << toClipboard << delay << id; m << pathValue << toClipboard << delay << id;
QDBusConnection sessionBus = QDBusConnection::sessionBus(); QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus); dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m); sessionBus.call(m);
if (isRaw) { if (isRaw) {
dbusUtils.connectPrintCapture(sessionBus, id); dbusUtils.connectPrintCapture(sessionBus, id);
// timeout just in case // timeout just in case
QTimer t; QTimer t;
t.setInterval(delay + 2000); t.setInterval(delay + 2000);
QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit); QObject::connect(
t.start(); &t, &QTimer::timeout, qApp, &QCoreApplication::quit);
// wait t.start();
return app.exec(); // wait
} return app.exec();
} else if (parser.isSet(configArgument)) { // CONFIG }
bool autostart = parser.isSet(autostartOption); } else if (parser.isSet(screenArgument)) { // SCREEN
bool filename = parser.isSet(filenameOption); QString numberStr = parser.value(screenNumberOption);
bool tray = parser.isSet(trayOption); int number =
bool help = parser.isSet(showHelpOption); numberStr.startsWith(QLatin1String("-")) ? -1 : numberStr.toInt();
bool mainColor = parser.isSet(mainColorOption); QString pathValue = parser.value(pathOption);
bool contrastColor = parser.isSet(contrastColorOption); int delay = parser.value(delayOption).toInt();
bool someFlagSet = (filename || tray || help || mainColor || contrastColor); bool toClipboard = parser.isSet(clipboardOption);
ConfigHandler config; bool isRaw = parser.isSet(rawImageOption);
if (autostart) { // Not a valid command
QDBusMessage m = QDBusMessage::createMethodCall( if (!isRaw && !toClipboard && pathValue.isEmpty()) {
QStringLiteral("org.flameshot.Flameshot"), QTextStream out(stdout);
QStringLiteral("/"), out << "Invalid format, set where to save the content with one of "
QLatin1String(""), << "the following flags:\n "
QStringLiteral("autostartEnabled")); << pathOption.dashedNames().join(QStringLiteral(", ")) << "\n "
if (parser.value(autostartOption) == QLatin1String("false")) { << rawImageOption.dashedNames().join(QStringLiteral(", "))
m << false; << "\n "
} else if (parser.value(autostartOption) == QLatin1String("true")) { << clipboardOption.dashedNames().join(QStringLiteral(", "))
m << true; << "\n\n";
} parser.parse(QStringList() << argv[0] << QStringLiteral("screen")
QDBusConnection sessionBus = QDBusConnection::sessionBus(); << QStringLiteral("-h"));
if (!sessionBus.isConnected()) { goto finish;
SystemNotification().sendMessage( }
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
}
if (filename) {
QString newFilename(parser.value(filenameOption));
config.setFilenamePattern(newFilename);
FileNameHandler fh;
QTextStream(stdout) << QStringLiteral("The new pattern is '%1'\n"
"Parsed pattern example: %2\n")
.arg(newFilename)
.arg(fh.parsedPattern());
}
if (tray) {
QDBusMessage m = QDBusMessage::createMethodCall(
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("trayIconEnabled"));
if (parser.value(trayOption) == QLatin1String("false")) {
m << false;
} else if (parser.value(trayOption) == QLatin1String("true")) {
m << true;
}
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
}
if (help) {
if (parser.value(showHelpOption) == QLatin1String("false")) {
config.setShowHelp(false);
} else if (parser.value(showHelpOption) == QLatin1String("true")) {
config.setShowHelp(true);
}
}
if (mainColor) {
QString colorCode = parser.value(mainColorOption);
QColor parsedColor(colorCode);
config.setUIMainColor(parsedColor);
}
if (contrastColor) {
QString colorCode = parser.value(contrastColorOption);
QColor parsedColor(colorCode);
config.setUIContrastColor(parsedColor);
}
// Open gui when no options CaptureRequest req(
if (!someFlagSet) { CaptureRequest::SCREEN_MODE, delay, pathValue, number);
QDBusMessage m = QDBusMessage::createMethodCall( if (toClipboard) {
QStringLiteral("org.flameshot.Flameshot"), req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
QStringLiteral("/"), }
QLatin1String(""), if (!pathValue.isEmpty()) {
QStringLiteral("openConfig")); req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
QDBusConnection sessionBus = QDBusConnection::sessionBus(); }
if (!sessionBus.isConnected()) { uint id = req.id();
SystemNotification().sendMessage( DBusUtils dbusUtils;
QObject::tr("Unable to connect via DBus"));
} // Send message
sessionBus.call(m); QDBusMessage m = QDBusMessage::createMethodCall(
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("captureScreen"));
m << number << pathValue << toClipboard << delay << id;
QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m);
if (isRaw) {
dbusUtils.connectPrintCapture(sessionBus, id);
// timeout just in case
QTimer t;
t.setInterval(delay + 2000);
QObject::connect(
&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
t.start();
// wait
return app.exec();
}
} else if (parser.isSet(configArgument)) { // CONFIG
bool autostart = parser.isSet(autostartOption);
bool filename = parser.isSet(filenameOption);
bool tray = parser.isSet(trayOption);
bool help = parser.isSet(showHelpOption);
bool mainColor = parser.isSet(mainColorOption);
bool contrastColor = parser.isSet(contrastColorOption);
bool someFlagSet =
(filename || tray || help || mainColor || contrastColor);
ConfigHandler config;
if (autostart) {
QDBusMessage m = QDBusMessage::createMethodCall(
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("autostartEnabled"));
if (parser.value(autostartOption) == QLatin1String("false")) {
m << false;
} else if (parser.value(autostartOption) == QLatin1String("true")) {
m << true;
}
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
}
if (filename) {
QString newFilename(parser.value(filenameOption));
config.setFilenamePattern(newFilename);
FileNameHandler fh;
QTextStream(stdout)
<< QStringLiteral("The new pattern is '%1'\n"
"Parsed pattern example: %2\n")
.arg(newFilename)
.arg(fh.parsedPattern());
}
if (tray) {
QDBusMessage m = QDBusMessage::createMethodCall(
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("trayIconEnabled"));
if (parser.value(trayOption) == QLatin1String("false")) {
m << false;
} else if (parser.value(trayOption) == QLatin1String("true")) {
m << true;
}
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
}
if (help) {
if (parser.value(showHelpOption) == QLatin1String("false")) {
config.setShowHelp(false);
} else if (parser.value(showHelpOption) == QLatin1String("true")) {
config.setShowHelp(true);
}
}
if (mainColor) {
QString colorCode = parser.value(mainColorOption);
QColor parsedColor(colorCode);
config.setUIMainColor(parsedColor);
}
if (contrastColor) {
QString colorCode = parser.value(contrastColorOption);
QColor parsedColor(colorCode);
config.setUIContrastColor(parsedColor);
}
// Open gui when no options
if (!someFlagSet) {
QDBusMessage m = QDBusMessage::createMethodCall(
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("openConfig"));
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
SystemNotification().sendMessage(
QObject::tr("Unable to connect via DBus"));
}
sessionBus.call(m);
}
} }
}
finish: finish:
#endif #endif
return 0; return 0;
} }

View File

@@ -21,74 +21,63 @@ AbstractActionTool::AbstractActionTool(QObject* parent)
: CaptureTool(parent) : CaptureTool(parent)
{} {}
bool bool AbstractActionTool::isValid() const
AbstractActionTool::isValid() const
{ {
return true; return true;
} }
bool bool AbstractActionTool::isSelectable() const
AbstractActionTool::isSelectable() const
{ {
return false; return false;
} }
bool bool AbstractActionTool::showMousePreview() const
AbstractActionTool::showMousePreview() const
{ {
return false; return false;
} }
void void AbstractActionTool::undo(QPixmap& pixmap)
AbstractActionTool::undo(QPixmap& pixmap)
{ {
Q_UNUSED(pixmap); Q_UNUSED(pixmap);
} }
void void AbstractActionTool::process(QPainter& painter,
AbstractActionTool::process(QPainter& painter, const QPixmap& pixmap,
const QPixmap& pixmap, bool recordUndo)
bool recordUndo)
{ {
Q_UNUSED(painter); Q_UNUSED(painter);
Q_UNUSED(pixmap); Q_UNUSED(pixmap);
Q_UNUSED(recordUndo); Q_UNUSED(recordUndo);
} }
void void AbstractActionTool::paintMousePreview(QPainter& painter,
AbstractActionTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
const CaptureContext& context)
{ {
Q_UNUSED(painter); Q_UNUSED(painter);
Q_UNUSED(context); Q_UNUSED(context);
} }
void void AbstractActionTool::drawEnd(const QPoint& p)
AbstractActionTool::drawEnd(const QPoint& p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
} }
void void AbstractActionTool::drawMove(const QPoint& p)
AbstractActionTool::drawMove(const QPoint& p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
} }
void void AbstractActionTool::drawStart(const CaptureContext& context)
AbstractActionTool::drawStart(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }
void void AbstractActionTool::colorChanged(const QColor& c)
AbstractActionTool::colorChanged(const QColor& c)
{ {
Q_UNUSED(c); Q_UNUSED(c);
} }
void void AbstractActionTool::thicknessChanged(const int th)
AbstractActionTool::thicknessChanged(const int th)
{ {
Q_UNUSED(th); Q_UNUSED(th);
} }

View File

@@ -21,28 +21,28 @@
class AbstractActionTool : public CaptureTool class AbstractActionTool : public CaptureTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractActionTool(QObject* parent = nullptr); explicit AbstractActionTool(QObject* parent = nullptr);
bool isValid() const override; bool isValid() const override;
bool isSelectable() const override; bool isSelectable() const override;
bool showMousePreview() const override; bool showMousePreview() const override;
void undo(QPixmap& pixmap) override; void undo(QPixmap& pixmap) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
virtual ToolType nameID() const = 0; virtual ToolType nameID() const = 0;
public slots: public slots:
void drawEnd(const QPoint& p) override; void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override; void drawMove(const QPoint& p) override;
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void colorChanged(const QColor& c) override; void colorChanged(const QColor& c) override;
void thicknessChanged(const int th) override; void thicknessChanged(const int th) override;
}; };

View File

@@ -23,83 +23,72 @@ AbstractPathTool::AbstractPathTool(QObject* parent)
, m_padding(0) , m_padding(0)
{} {}
bool bool AbstractPathTool::isValid() const
AbstractPathTool::isValid() const
{ {
return m_points.length() > 1; return m_points.length() > 1;
} }
bool bool AbstractPathTool::closeOnButtonPressed() const
AbstractPathTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
bool bool AbstractPathTool::isSelectable() const
AbstractPathTool::isSelectable() const
{ {
return true; return true;
} }
bool bool AbstractPathTool::showMousePreview() const
AbstractPathTool::showMousePreview() const
{ {
return true; return true;
} }
void void AbstractPathTool::undo(QPixmap& pixmap)
AbstractPathTool::undo(QPixmap& pixmap)
{ {
QPainter p(&pixmap); QPainter p(&pixmap);
const int val = m_thickness + m_padding; const int val = m_thickness + m_padding;
QRect area = m_backupArea + QMargins(val, val, val, val); QRect area = m_backupArea + QMargins(val, val, val, val);
p.drawPixmap(area.intersected(pixmap.rect()).topLeft(), m_pixmapBackup); p.drawPixmap(area.intersected(pixmap.rect()).topLeft(), m_pixmapBackup);
} }
void void AbstractPathTool::drawEnd(const QPoint& p)
AbstractPathTool::drawEnd(const QPoint& p)
{ {
Q_UNUSED(p); Q_UNUSED(p);
} }
void void AbstractPathTool::drawMove(const QPoint& p)
AbstractPathTool::drawMove(const QPoint& p)
{ {
addPoint(p); addPoint(p);
} }
void void AbstractPathTool::colorChanged(const QColor& c)
AbstractPathTool::colorChanged(const QColor& c)
{ {
m_color = c; m_color = c;
} }
void void AbstractPathTool::thicknessChanged(const int th)
AbstractPathTool::thicknessChanged(const int th)
{ {
m_thickness = th; m_thickness = th;
} }
void void AbstractPathTool::updateBackup(const QPixmap& pixmap)
AbstractPathTool::updateBackup(const QPixmap& pixmap)
{ {
const int val = m_thickness + m_padding; const int val = m_thickness + m_padding;
QRect area = m_backupArea.normalized() + QMargins(val, val, val, val); QRect area = m_backupArea.normalized() + QMargins(val, val, val, val);
m_pixmapBackup = pixmap.copy(area); m_pixmapBackup = pixmap.copy(area);
} }
void void AbstractPathTool::addPoint(const QPoint& point)
AbstractPathTool::addPoint(const QPoint& point)
{ {
if (m_backupArea.left() > point.x()) { if (m_backupArea.left() > point.x()) {
m_backupArea.setLeft(point.x()); m_backupArea.setLeft(point.x());
} else if (m_backupArea.right() < point.x()) { } else if (m_backupArea.right() < point.x()) {
m_backupArea.setRight(point.x()); m_backupArea.setRight(point.x());
} }
if (m_backupArea.top() > point.y()) { if (m_backupArea.top() > point.y()) {
m_backupArea.setTop(point.y()); m_backupArea.setTop(point.y());
} else if (m_backupArea.bottom() < point.y()) { } else if (m_backupArea.bottom() < point.y()) {
m_backupArea.setBottom(point.y()); m_backupArea.setBottom(point.y());
} }
m_points.append(point); m_points.append(point);
} }

View File

@@ -21,34 +21,34 @@
class AbstractPathTool : public CaptureTool class AbstractPathTool : public CaptureTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractPathTool(QObject* parent = nullptr); explicit AbstractPathTool(QObject* parent = nullptr);
bool isValid() const override; bool isValid() const override;
bool closeOnButtonPressed() const override; bool closeOnButtonPressed() const override;
bool isSelectable() const override; bool isSelectable() const override;
bool showMousePreview() const override; bool showMousePreview() const override;
void undo(QPixmap& pixmap) override; void undo(QPixmap& pixmap) override;
public slots: public slots:
void drawEnd(const QPoint& p) override; void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override; void drawMove(const QPoint& p) override;
void colorChanged(const QColor& c) override; void colorChanged(const QColor& c) override;
void thicknessChanged(const int th) override; void thicknessChanged(const int th) override;
protected: protected:
void updateBackup(const QPixmap& pixmap); void updateBackup(const QPixmap& pixmap);
void addPoint(const QPoint& point); void addPoint(const QPoint& point);
virtual ToolType nameID() const = 0; virtual ToolType nameID() const = 0;
QPixmap m_pixmapBackup; QPixmap m_pixmapBackup;
QRect m_backupArea; QRect m_backupArea;
QColor m_color; QColor m_color;
QVector<QPoint> m_points; QVector<QPoint> m_points;
int m_thickness; int m_thickness;
// use m_padding to extend the area of the backup // use m_padding to extend the area of the backup
int m_padding; int m_padding;
}; };

View File

@@ -25,10 +25,10 @@ const int DIRS_NUMBER = 4;
enum UNIT enum UNIT
{ {
HORIZ_DIR = 0, HORIZ_DIR = 0,
DIAG1_DIR = 1, DIAG1_DIR = 1,
VERT_DIR = 2, VERT_DIR = 2,
DIAG2_DIR = 3 DIAG2_DIR = 3
}; };
const double ADJ_DIAG_UNIT = 2 * ADJ_UNIT; const double ADJ_DIAG_UNIT = 2 * ADJ_UNIT;
@@ -36,8 +36,8 @@ const int DIAG_DIRS_NUMBER = 2;
enum DIAG_UNIT enum DIAG_UNIT
{ {
DIR1 = 0, DIR1 = 0,
DIR2 = 1 DIR2 = 1
}; };
} }
@@ -48,123 +48,111 @@ AbstractTwoPointTool::AbstractTwoPointTool(QObject* parent)
, m_padding(0) , m_padding(0)
{} {}
bool bool AbstractTwoPointTool::isValid() const
AbstractTwoPointTool::isValid() const
{ {
return (m_points.first != m_points.second); return (m_points.first != m_points.second);
} }
bool bool AbstractTwoPointTool::closeOnButtonPressed() const
AbstractTwoPointTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
bool bool AbstractTwoPointTool::isSelectable() const
AbstractTwoPointTool::isSelectable() const
{ {
return true; return true;
} }
bool bool AbstractTwoPointTool::showMousePreview() const
AbstractTwoPointTool::showMousePreview() const
{ {
return true; return true;
} }
void void AbstractTwoPointTool::undo(QPixmap& pixmap)
AbstractTwoPointTool::undo(QPixmap& pixmap)
{ {
QPainter p(&pixmap); QPainter p(&pixmap);
p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup); p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup);
if (this->nameID() == ToolType::CIRCLECOUNT) { if (this->nameID() == ToolType::CIRCLECOUNT) {
emit requestAction(REQ_DECREMENT_CIRCLE_COUNT); emit requestAction(REQ_DECREMENT_CIRCLE_COUNT);
}
}
void
AbstractTwoPointTool::drawEnd(const QPoint& p)
{
Q_UNUSED(p);
}
void
AbstractTwoPointTool::drawMove(const QPoint& p)
{
m_points.second = p;
}
void
AbstractTwoPointTool::drawMoveWithAdjustment(const QPoint& p)
{
m_points.second = m_points.first + adjustedVector(p - m_points.first);
}
void
AbstractTwoPointTool::colorChanged(const QColor& c)
{
m_color = c;
}
void
AbstractTwoPointTool::thicknessChanged(const int th)
{
m_thickness = th;
}
void
AbstractTwoPointTool::updateBackup(const QPixmap& pixmap)
{
m_pixmapBackup = pixmap.copy(backupRect(pixmap.rect()));
}
QRect
AbstractTwoPointTool::backupRect(const QRect& limits) const
{
QRect r = QRect(m_points.first, m_points.second).normalized();
const int val = m_thickness + m_padding;
r += QMargins(val, val, val, val);
return r.intersected(limits);
}
QPoint
AbstractTwoPointTool::adjustedVector(QPoint v) const
{
if (m_supportsOrthogonalAdj && m_supportsDiagonalAdj) {
int dir =
(static_cast<int>(round(atan2(-v.y(), v.x()) / ADJ_UNIT)) + DIRS_NUMBER) %
DIRS_NUMBER;
if (dir == UNIT::HORIZ_DIR) {
v.setY(0);
} else if (dir == UNIT::VERT_DIR) {
v.setX(0);
} else if (dir == UNIT::DIAG1_DIR) {
int newX = (v.x() - v.y()) / 2;
int newY = -newX;
v.setX(newX);
v.setY(newY);
} else {
int newX = (v.x() + v.y()) / 2;
int newY = newX;
v.setX(newX);
v.setY(newY);
} }
} else if (m_supportsDiagonalAdj) { }
int dir = (static_cast<int>(round(
(atan2(-v.y(), v.x()) - ADJ_DIAG_UNIT / 2) / ADJ_DIAG_UNIT)) + void AbstractTwoPointTool::drawEnd(const QPoint& p)
DIAG_DIRS_NUMBER) % {
DIAG_DIRS_NUMBER; Q_UNUSED(p);
if (dir == DIAG_UNIT::DIR1) { }
int newX = (v.x() - v.y()) / 2;
int newY = -newX; void AbstractTwoPointTool::drawMove(const QPoint& p)
v.setX(newX); {
v.setY(newY); m_points.second = p;
} else { }
int newX = (v.x() + v.y()) / 2;
int newY = newX; void AbstractTwoPointTool::drawMoveWithAdjustment(const QPoint& p)
v.setX(newX); {
v.setY(newY); m_points.second = m_points.first + adjustedVector(p - m_points.first);
} }
}
return v; void AbstractTwoPointTool::colorChanged(const QColor& c)
{
m_color = c;
}
void AbstractTwoPointTool::thicknessChanged(const int th)
{
m_thickness = th;
}
void AbstractTwoPointTool::updateBackup(const QPixmap& pixmap)
{
m_pixmapBackup = pixmap.copy(backupRect(pixmap.rect()));
}
QRect AbstractTwoPointTool::backupRect(const QRect& limits) const
{
QRect r = QRect(m_points.first, m_points.second).normalized();
const int val = m_thickness + m_padding;
r += QMargins(val, val, val, val);
return r.intersected(limits);
}
QPoint AbstractTwoPointTool::adjustedVector(QPoint v) const
{
if (m_supportsOrthogonalAdj && m_supportsDiagonalAdj) {
int dir = (static_cast<int>(round(atan2(-v.y(), v.x()) / ADJ_UNIT)) +
DIRS_NUMBER) %
DIRS_NUMBER;
if (dir == UNIT::HORIZ_DIR) {
v.setY(0);
} else if (dir == UNIT::VERT_DIR) {
v.setX(0);
} else if (dir == UNIT::DIAG1_DIR) {
int newX = (v.x() - v.y()) / 2;
int newY = -newX;
v.setX(newX);
v.setY(newY);
} else {
int newX = (v.x() + v.y()) / 2;
int newY = newX;
v.setX(newX);
v.setY(newY);
}
} else if (m_supportsDiagonalAdj) {
int dir =
(static_cast<int>(round((atan2(-v.y(), v.x()) - ADJ_DIAG_UNIT / 2) /
ADJ_DIAG_UNIT)) +
DIAG_DIRS_NUMBER) %
DIAG_DIRS_NUMBER;
if (dir == DIAG_UNIT::DIR1) {
int newX = (v.x() - v.y()) / 2;
int newY = -newX;
v.setX(newX);
v.setY(newY);
} else {
int newX = (v.x() + v.y()) / 2;
int newY = newX;
v.setX(newX);
v.setY(newY);
}
}
return v;
} }

View File

@@ -21,40 +21,40 @@
class AbstractTwoPointTool : public CaptureTool class AbstractTwoPointTool : public CaptureTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractTwoPointTool(QObject* parent = nullptr); explicit AbstractTwoPointTool(QObject* parent = nullptr);
bool isValid() const override; bool isValid() const override;
bool closeOnButtonPressed() const override; bool closeOnButtonPressed() const override;
bool isSelectable() const override; bool isSelectable() const override;
bool showMousePreview() const override; bool showMousePreview() const override;
void undo(QPixmap& pixmap) override; void undo(QPixmap& pixmap) override;
public slots: public slots:
void drawEnd(const QPoint& p) override; void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override; void drawMove(const QPoint& p) override;
void drawMoveWithAdjustment(const QPoint& p) override; void drawMoveWithAdjustment(const QPoint& p) override;
void colorChanged(const QColor& c) override; void colorChanged(const QColor& c) override;
void thicknessChanged(const int th) override; void thicknessChanged(const int th) override;
protected: protected:
void updateBackup(const QPixmap& pixmap); void updateBackup(const QPixmap& pixmap);
QRect backupRect(const QRect& limits) const; QRect backupRect(const QRect& limits) const;
QPixmap m_pixmapBackup; QPixmap m_pixmapBackup;
QPair<QPoint, QPoint> m_points; QPair<QPoint, QPoint> m_points;
QColor m_color; QColor m_color;
int m_thickness; int m_thickness;
// use m_padding to extend the area of the backup // use m_padding to extend the area of the backup
int m_padding; int m_padding;
bool m_supportsOrthogonalAdj = false; bool m_supportsOrthogonalAdj = false;
bool m_supportsDiagonalAdj = false; bool m_supportsDiagonalAdj = false;
virtual ToolType nameID() const = 0; virtual ToolType nameID() const = 0;
private: private:
QPoint adjustedVector(QPoint v) const; QPoint adjustedVector(QPoint v) const;
}; };

View File

@@ -24,50 +24,48 @@ namespace {
const int ArrowWidth = 10; const int ArrowWidth = 10;
const int ArrowHeight = 18; const int ArrowHeight = 18;
QPainterPath QPainterPath getArrowHead(QPoint p1, QPoint p2, const int thickness)
getArrowHead(QPoint p1, QPoint p2, const int thickness)
{ {
QLineF base(p1, p2); QLineF base(p1, p2);
// Create the vector for the position of the base of the arrowhead // Create the vector for the position of the base of the arrowhead
QLineF temp(QPoint(0, 0), p2 - p1); QLineF temp(QPoint(0, 0), p2 - p1);
int val = ArrowHeight + thickness * 4; int val = ArrowHeight + thickness * 4;
if (base.length() < val) { if (base.length() < val) {
val = (base.length() + thickness * 2); val = (base.length() + thickness * 2);
} }
temp.setLength(base.length() + thickness * 2 - val); temp.setLength(base.length() + thickness * 2 - val);
// Move across the line up to the head // Move across the line up to the head
QPointF bottonTranslation(temp.p2()); QPointF bottonTranslation(temp.p2());
// Rotate base of the arrowhead // Rotate base of the arrowhead
base.setLength(ArrowWidth + thickness * 2); base.setLength(ArrowWidth + thickness * 2);
base.setAngle(base.angle() + 90); base.setAngle(base.angle() + 90);
// Move to the correct point // Move to the correct point
QPointF temp2 = p1 - base.p2(); QPointF temp2 = p1 - base.p2();
// Center it // Center it
QPointF centerTranslation((temp2.x() / 2), (temp2.y() / 2)); QPointF centerTranslation((temp2.x() / 2), (temp2.y() / 2));
base.translate(bottonTranslation); base.translate(bottonTranslation);
base.translate(centerTranslation); base.translate(centerTranslation);
QPainterPath path; QPainterPath path;
path.moveTo(p2); path.moveTo(p2);
path.lineTo(base.p1()); path.lineTo(base.p1());
path.lineTo(base.p2()); path.lineTo(base.p2());
path.lineTo(p2); path.lineTo(p2);
return path; return path;
} }
// gets a shorter line to prevent overlap in the point of the arrow // gets a shorter line to prevent overlap in the point of the arrow
QLine QLine getShorterLine(QPoint p1, QPoint p2, const int thickness)
getShorterLine(QPoint p1, QPoint p2, const int thickness)
{ {
QLineF l(p1, p2); QLineF l(p1, p2);
int val = ArrowHeight + thickness * 4; int val = ArrowHeight + thickness * 4;
if (l.length() < val) { if (l.length() < val) {
val = (l.length() + thickness * 2); val = (l.length() + thickness * 2);
} }
l.setLength(l.length() + thickness * 2 - val); l.setLength(l.length() + thickness * 2 - val);
return l.toLine(); return l.toLine();
} }
} // unnamed namespace } // unnamed namespace
@@ -75,72 +73,66 @@ getShorterLine(QPoint p1, QPoint p2, const int thickness)
ArrowTool::ArrowTool(QObject* parent) ArrowTool::ArrowTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_padding = ArrowWidth / 2; m_padding = ArrowWidth / 2;
m_supportsOrthogonalAdj = true; m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
QIcon QIcon ArrowTool::icon(const QColor& background, bool inEditor) const
ArrowTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "arrow-bottom-left.svg"); return QIcon(iconPath(background) + "arrow-bottom-left.svg");
} }
QString QString ArrowTool::name() const
ArrowTool::name() const
{ {
return tr("Arrow"); return tr("Arrow");
} }
ToolType ToolType ArrowTool::nameID() const
ArrowTool::nameID() const
{ {
return ToolType::ARROW; return ToolType::ARROW;
} }
QString QString ArrowTool::description() const
ArrowTool::description() const
{ {
return tr("Set the Arrow as the paint tool"); return tr("Set the Arrow as the paint tool");
} }
CaptureTool* CaptureTool* ArrowTool::copy(QObject* parent)
ArrowTool::copy(QObject* parent)
{ {
return new ArrowTool(parent); return new ArrowTool(parent);
} }
void void ArrowTool::process(QPainter& painter,
ArrowTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawLine( painter.drawLine(
getShorterLine(m_points.first, m_points.second, m_thickness)); getShorterLine(m_points.first, m_points.second, m_thickness));
painter.fillPath(getArrowHead(m_points.first, m_points.second, m_thickness), painter.fillPath(getArrowHead(m_points.first, m_points.second, m_thickness),
QBrush(m_color)); QBrush(m_color));
} }
void void ArrowTool::paintMousePreview(QPainter& painter,
ArrowTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void ArrowTool::drawStart(const CaptureContext& context)
ArrowTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void ArrowTool::pressed(const CaptureContext& context)
ArrowTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -23,25 +23,25 @@
class ArrowTool : public AbstractTwoPointTool class ArrowTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ArrowTool(QObject* parent = nullptr); explicit ArrowTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -17,12 +17,11 @@
#include "capturecontext.h" #include "capturecontext.h"
QPixmap QPixmap CaptureContext::selectedScreenshotArea() const
CaptureContext::selectedScreenshotArea() const
{ {
if (selection.isNull()) { if (selection.isNull()) {
return screenshot; return screenshot;
} else { } else {
return screenshot.copy(selection); return screenshot.copy(selection);
} }
} }

View File

@@ -24,27 +24,27 @@
struct CaptureContext struct CaptureContext
{ {
// screenshot with modifications // screenshot with modifications
QPixmap screenshot; QPixmap screenshot;
// unmodified screenshot // unmodified screenshot
QPixmap origScreenshot; QPixmap origScreenshot;
// Selection area // Selection area
QRect selection; QRect selection;
// Widget dimensions // Widget dimensions
QRect widgetDimensions; QRect widgetDimensions;
// Selected tool color // Selected tool color
QColor color; QColor color;
// Path where the content has to be saved // Path where the content has to be saved
QString savePath; QString savePath;
// Ofset of the capture widget based on the system's screen (top-left) // Ofset of the capture widget based on the system's screen (top-left)
QPoint widgetOffset; QPoint widgetOffset;
// Mouse position inside the widget // Mouse position inside the widget
QPoint mousePos; QPoint mousePos;
// Value of the desired thickness // Value of the desired thickness
int thickness; int thickness;
int circleCount; int circleCount;
// Mode of the capture widget // Mode of the capture widget
bool fullscreen; bool fullscreen;
QPixmap selectedScreenshotArea() const; QPixmap selectedScreenshotArea() const;
}; };

View File

@@ -25,152 +25,152 @@
enum class ToolType enum class ToolType
{ {
ARROW, ARROW,
CIRCLE, CIRCLE,
CIRCLECOUNT, CIRCLECOUNT,
COPY, COPY,
EXIT, EXIT,
IMGUR, IMGUR,
LAUNCHER, LAUNCHER,
LINE, LINE,
MARKER, MARKER,
MOVE, MOVE,
PENCIL, PENCIL,
PIN, PIN,
PIXELATE, PIXELATE,
RECTANGLE, RECTANGLE,
REDO, REDO,
SAVE, SAVE,
SELECTION, SELECTION,
SIZEINDICATOR, SIZEINDICATOR,
TEXT, TEXT,
UNDO UNDO
}; };
class CaptureTool : public QObject class CaptureTool : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
// Request actions on the main widget // Request actions on the main widget
enum Request enum Request
{ {
// Call close() in the editor. // Call close() in the editor.
REQ_CLOSE_GUI, REQ_CLOSE_GUI,
// Call hide() in the editor. // Call hide() in the editor.
REQ_HIDE_GUI, REQ_HIDE_GUI,
// Select the whole screen. // Select the whole screen.
REQ_SELECT_ALL, REQ_SELECT_ALL,
// Disable the selection. // Disable the selection.
REQ_HIDE_SELECTION, REQ_HIDE_SELECTION,
// Undo the last active modification in the stack. // Undo the last active modification in the stack.
REQ_UNDO_MODIFICATION, REQ_UNDO_MODIFICATION,
// Redo the next modification in the stack. // Redo the next modification in the stack.
REQ_REDO_MODIFICATION, REQ_REDO_MODIFICATION,
// Remove all the modifications. // Remove all the modifications.
REQ_CLEAR_MODIFICATIONS, REQ_CLEAR_MODIFICATIONS,
// Disable the active tool. // Disable the active tool.
REQ_MOVE_MODE, REQ_MOVE_MODE,
// Open the color picker under the mouse. // Open the color picker under the mouse.
REQ_SHOW_COLOR_PICKER, REQ_SHOW_COLOR_PICKER,
// Open/Close the side-panel. // Open/Close the side-panel.
REQ_TOGGLE_SIDEBAR, REQ_TOGGLE_SIDEBAR,
// Call update() in the editor. // Call update() in the editor.
REQ_REDRAW, REQ_REDRAW,
// Append this tool to the undo/redo stack // Append this tool to the undo/redo stack
REQ_APPEND_TO_STACK, REQ_APPEND_TO_STACK,
// Notify is the screenshot has been saved. // Notify is the screenshot has been saved.
REQ_CAPTURE_DONE_OK, REQ_CAPTURE_DONE_OK,
// Instance this->widget()'s widget inside the editor under the mouse. // Instance this->widget()'s widget inside the editor under the mouse.
REQ_ADD_CHILD_WIDGET, REQ_ADD_CHILD_WIDGET,
// Instance this->widget()'s widget as a window which closes after // Instance this->widget()'s widget as a window which closes after
// closing the editor. // closing the editor.
REQ_ADD_CHILD_WINDOW, REQ_ADD_CHILD_WINDOW,
// Instance this->widget()'s widget which handles its own lifetime. // Instance this->widget()'s widget which handles its own lifetime.
REQ_ADD_EXTERNAL_WIDGETS, REQ_ADD_EXTERNAL_WIDGETS,
REQ_INCREMENT_CIRCLE_COUNT, REQ_INCREMENT_CIRCLE_COUNT,
REQ_DECREMENT_CIRCLE_COUNT, REQ_DECREMENT_CIRCLE_COUNT,
}; };
explicit CaptureTool(QObject* parent = nullptr) explicit CaptureTool(QObject* parent = nullptr)
: QObject(parent) : QObject(parent)
{} {}
// Returns false when the tool is in an inconsistent state and shouldn't // Returns false when the tool is in an inconsistent state and shouldn't
// be included in the tool undo/redo stack. // be included in the tool undo/redo stack.
virtual bool isValid() const = 0; virtual bool isValid() const = 0;
// Close the capture after the process() call if the tool was activated // Close the capture after the process() call if the tool was activated
// from a button press. // from a button press.
virtual bool closeOnButtonPressed() const = 0; virtual bool closeOnButtonPressed() const = 0;
// If the tool keeps active after the selection. // If the tool keeps active after the selection.
virtual bool isSelectable() const = 0; virtual bool isSelectable() const = 0;
// Enable mouse preview. // Enable mouse preview.
virtual bool showMousePreview() const = 0; virtual bool showMousePreview() const = 0;
// The icon of the tool. // The icon of the tool.
// inEditor is true when the icon is requested inside the editor // inEditor is true when the icon is requested inside the editor
// and false otherwise. // and false otherwise.
virtual QIcon icon(const QColor& background, bool inEditor) const = 0; virtual QIcon icon(const QColor& background, bool inEditor) const = 0;
// Name displayed for the tool, this could be translated with tr() // Name displayed for the tool, this could be translated with tr()
virtual QString name() const = 0; virtual QString name() const = 0;
// Codename for the tool, this hsouldn't change as it is used as ID // Codename for the tool, this hsouldn't change as it is used as ID
// for the tool in the internals of Flameshot // for the tool in the internals of Flameshot
virtual ToolType nameID() const = 0; virtual ToolType nameID() const = 0;
// Short description of the tool. // Short description of the tool.
virtual QString description() const = 0; virtual QString description() const = 0;
// if the type is TYPE_WIDGET the widget is loaded in the main widget. // if the type is TYPE_WIDGET the widget is loaded in the main widget.
// If the type is TYPE_EXTERNAL_WIDGET it is created outside as an // If the type is TYPE_EXTERNAL_WIDGET it is created outside as an
// individual widget. // individual widget.
virtual QWidget* widget() { return nullptr; } virtual QWidget* widget() { return nullptr; }
// When the tool is selected this method is called and the widget is added // When the tool is selected this method is called and the widget is added
// to the configuration panel inside the main widget. // to the configuration panel inside the main widget.
virtual QWidget* configurationWidget() { return nullptr; } virtual QWidget* configurationWidget() { return nullptr; }
// Permanent configuration used in the configuration outside of the // Permanent configuration used in the configuration outside of the
// capture. // capture.
virtual QWidget* permanentConfigurationWidget() { return nullptr; } virtual QWidget* permanentConfigurationWidget() { return nullptr; }
// Return a copy of the tool // Return a copy of the tool
virtual CaptureTool* copy(QObject* parent = nullptr) = 0; virtual CaptureTool* copy(QObject* parent = nullptr) = 0;
// revert changes // revert changes
virtual void undo(QPixmap& pixmap) = 0; virtual void undo(QPixmap& pixmap) = 0;
// Called every time the tool has to draw // Called every time the tool has to draw
// recordUndo indicates when the tool should save the information // recordUndo indicates when the tool should save the information
// for the undo(), if the value is false calling undo() after // for the undo(), if the value is false calling undo() after
// that process should not modify revert the changes. // that process should not modify revert the changes.
virtual void process(QPainter& painter, virtual void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) = 0; bool recordUndo = false) = 0;
// When the tool is selected, this is called when the mouse moves // When the tool is selected, this is called when the mouse moves
virtual void paintMousePreview(QPainter& painter, virtual void paintMousePreview(QPainter& painter,
const CaptureContext& context) = 0; const CaptureContext& context) = 0;
signals: signals:
void requestAction(Request r); void requestAction(Request r);
protected: protected:
QString iconPath(const QColor& c) const QString iconPath(const QColor& c) const
{ {
return ColorUtils::colorIsDark(c) ? PathInfo::whiteIconPath() return ColorUtils::colorIsDark(c) ? PathInfo::whiteIconPath()
: PathInfo::blackIconPath(); : PathInfo::blackIconPath();
} }
public slots: public slots:
// On mouse release. // On mouse release.
virtual void drawEnd(const QPoint& p) = 0; virtual void drawEnd(const QPoint& p) = 0;
// Mouse pressed and moving, called once a pixel. // Mouse pressed and moving, called once a pixel.
virtual void drawMove(const QPoint& p) = 0; virtual void drawMove(const QPoint& p) = 0;
// Called when drawMove is needed with an adjustment; // Called when drawMove is needed with an adjustment;
// should be overridden in case an adjustment is applicable. // should be overridden in case an adjustment is applicable.
virtual void drawMoveWithAdjustment(const QPoint& p) { drawMove(p); } virtual void drawMoveWithAdjustment(const QPoint& p) { drawMove(p); }
// Called when the tool is activated. // Called when the tool is activated.
virtual void drawStart(const CaptureContext& context) = 0; virtual void drawStart(const CaptureContext& context) = 0;
// Called right after pressign the button which activates the tool. // Called right after pressign the button which activates the tool.
virtual void pressed(const CaptureContext& context) = 0; virtual void pressed(const CaptureContext& context) = 0;
// Called when the color is changed in the editor. // Called when the color is changed in the editor.
virtual void colorChanged(const QColor& c) = 0; virtual void colorChanged(const QColor& c) = 0;
// Called when the thickness of the tool is updated in the editor. // Called when the thickness of the tool is updated in the editor.
virtual void thicknessChanged(const int th) = 0; virtual void thicknessChanged(const int th) = 0;
}; };

View File

@@ -25,67 +25,61 @@ namespace {
CircleTool::CircleTool(QObject* parent) CircleTool::CircleTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
QIcon QIcon CircleTool::icon(const QColor& background, bool inEditor) const
CircleTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "circle-outline.svg"); return QIcon(iconPath(background) + "circle-outline.svg");
} }
QString QString CircleTool::name() const
CircleTool::name() const
{ {
return tr("Circle"); return tr("Circle");
} }
ToolType ToolType CircleTool::nameID() const
CircleTool::nameID() const
{ {
return ToolType::CIRCLE; return ToolType::CIRCLE;
} }
QString QString CircleTool::description() const
CircleTool::description() const
{ {
return tr("Set the Circle as the paint tool"); return tr("Set the Circle as the paint tool");
} }
CaptureTool* CaptureTool* CircleTool::copy(QObject* parent)
CircleTool::copy(QObject* parent)
{ {
return new CircleTool(parent); return new CircleTool(parent);
} }
void void CircleTool::process(QPainter& painter,
CircleTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawEllipse(QRect(m_points.first, m_points.second)); painter.drawEllipse(QRect(m_points.first, m_points.second));
} }
void void CircleTool::paintMousePreview(QPainter& painter,
CircleTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void CircleTool::drawStart(const CaptureContext& context)
CircleTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void CircleTool::pressed(const CaptureContext& context)
CircleTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,25 +21,25 @@
class CircleTool : public AbstractTwoPointTool class CircleTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CircleTool(QObject* parent = nullptr); explicit CircleTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -24,120 +24,111 @@ namespace {
CircleCountTool::CircleCountTool(QObject* parent) CircleCountTool::CircleCountTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_count = 0; m_count = 0;
} }
QIcon QIcon CircleCountTool::icon(const QColor& background, bool inEditor) const
CircleCountTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "circlecount-outline.svg"); return QIcon(iconPath(background) + "circlecount-outline.svg");
} }
QString QString CircleCountTool::name() const
CircleCountTool::name() const
{ {
return tr("Circle Counter"); return tr("Circle Counter");
} }
ToolType ToolType CircleCountTool::nameID() const
CircleCountTool::nameID() const
{ {
return ToolType::CIRCLECOUNT; return ToolType::CIRCLECOUNT;
} }
QString QString CircleCountTool::description() const
CircleCountTool::description() const
{ {
return tr("Add an autoincrementing counter bubble"); return tr("Add an autoincrementing counter bubble");
} }
CaptureTool* CaptureTool* CircleCountTool::copy(QObject* parent)
CircleCountTool::copy(QObject* parent)
{ {
return new CircleCountTool(parent); return new CircleCountTool(parent);
} }
void void CircleCountTool::process(QPainter& painter,
CircleCountTool::process(QPainter& painter, const QPixmap& pixmap,
const QPixmap& pixmap, bool recordUndo)
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
}
painter.setBrush(m_color);
int bubble_size = m_thickness;
// Decrease by 1px so the border is properly ereased when doing undo
painter.drawEllipse(m_points.first, bubble_size - 1, bubble_size - 1);
QRect textRect = QRect(m_points.first.x() - bubble_size / 2,
m_points.first.y() - bubble_size / 2,
bubble_size,
bubble_size);
auto orig_font = painter.font();
auto new_font = orig_font;
auto fontSize = bubble_size;
new_font.setPixelSize(fontSize);
painter.setFont(new_font);
QRect bRect =
painter.boundingRect(textRect, Qt::AlignCenter, QString::number(m_count));
while (bRect.width() > textRect.width()) {
fontSize--;
if (fontSize == 0) {
break;
} }
painter.setBrush(m_color);
int bubble_size = m_thickness;
// Decrease by 1px so the border is properly ereased when doing undo
painter.drawEllipse(m_points.first, bubble_size - 1, bubble_size - 1);
QRect textRect = QRect(m_points.first.x() - bubble_size / 2,
m_points.first.y() - bubble_size / 2,
bubble_size,
bubble_size);
auto orig_font = painter.font();
auto new_font = orig_font;
auto fontSize = bubble_size;
new_font.setPixelSize(fontSize); new_font.setPixelSize(fontSize);
painter.setFont(new_font); painter.setFont(new_font);
bRect = QRect bRect =
painter.boundingRect(textRect, Qt::AlignCenter, QString::number(m_count)); painter.boundingRect(textRect, Qt::AlignCenter, QString::number(m_count));
}
// Lightness value ranges from 0-255, we split at 75 as this looks best while (bRect.width() > textRect.width()) {
if (m_color.lightness() <= 75) { fontSize--;
painter.setPen(Qt::white); if (fontSize == 0) {
} else { break;
painter.setPen(Qt::black); }
} new_font.setPixelSize(fontSize);
painter.setFont(new_font);
painter.drawText(textRect, Qt::AlignCenter, QString::number(m_count)); bRect = painter.boundingRect(
painter.setFont(orig_font); textRect, Qt::AlignCenter, QString::number(m_count));
}
// Lightness value ranges from 0-255, we split at 75 as this looks best
if (m_color.lightness() <= 75) {
painter.setPen(Qt::white);
} else {
painter.setPen(Qt::black);
}
painter.drawText(textRect, Qt::AlignCenter, QString::number(m_count));
painter.setFont(orig_font);
} }
void void CircleCountTool::paintMousePreview(QPainter& painter,
CircleCountTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
const CaptureContext& context)
{ {
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) { if (m_thickness < 15) {
m_thickness = 15; m_thickness = 15;
} }
// Thickness for pen is *2 to range from radius to diameter to match the // Thickness for pen is *2 to range from radius to diameter to match the
// ellipse draw function // ellipse draw function
painter.setPen( painter.setPen(
QPen(context.color, m_thickness * 2, Qt::SolidLine, Qt::RoundCap)); QPen(context.color, m_thickness * 2, Qt::SolidLine, Qt::RoundCap));
painter.drawLine(context.mousePos, painter.drawLine(context.mousePos,
{ context.mousePos.x() + 1, context.mousePos.y() + 1 }); { context.mousePos.x() + 1, context.mousePos.y() + 1 });
} }
void void CircleCountTool::drawStart(const CaptureContext& context)
CircleCountTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) { if (m_thickness < 15) {
m_thickness = 15; m_thickness = 15;
} }
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_count = context.circleCount; m_count = context.circleCount;
emit requestAction(REQ_INCREMENT_CIRCLE_COUNT); emit requestAction(REQ_INCREMENT_CIRCLE_COUNT);
} }
void void CircleCountTool::pressed(const CaptureContext& context)
CircleCountTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,27 +21,27 @@
class CircleCountTool : public AbstractTwoPointTool class CircleCountTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CircleCountTool(QObject* parent = nullptr); explicit CircleCountTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
private: private:
unsigned int m_count; unsigned int m_count;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -23,45 +23,38 @@ CopyTool::CopyTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool CopyTool::closeOnButtonPressed() const
CopyTool::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon CopyTool::icon(const QColor& background, bool inEditor) const
CopyTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "content-copy.svg"); return QIcon(iconPath(background) + "content-copy.svg");
} }
QString QString CopyTool::name() const
CopyTool::name() const
{ {
return tr("Copy"); return tr("Copy");
} }
ToolType ToolType CopyTool::nameID() const
CopyTool::nameID() const
{ {
return ToolType::COPY; return ToolType::COPY;
} }
QString QString CopyTool::description() const
CopyTool::description() const
{ {
return tr("Copy the selection into the clipboard"); return tr("Copy the selection into the clipboard");
} }
CaptureTool* CaptureTool* CopyTool::copy(QObject* parent)
CopyTool::copy(QObject* parent)
{ {
return new CopyTool(parent); return new CopyTool(parent);
} }
void void CopyTool::pressed(const CaptureContext& context)
CopyTool::pressed(const CaptureContext& context)
{ {
emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_CAPTURE_DONE_OK);
ScreenshotSaver().saveToClipboard(context.selectedScreenshotArea()); ScreenshotSaver().saveToClipboard(context.selectedScreenshotArea());
} }

View File

@@ -21,21 +21,21 @@
class CopyTool : public AbstractActionTool class CopyTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CopyTool(QObject* parent = nullptr); explicit CopyTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -22,45 +22,38 @@ ExitTool::ExitTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool ExitTool::closeOnButtonPressed() const
ExitTool::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon ExitTool::icon(const QColor& background, bool inEditor) const
ExitTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "close.svg"); return QIcon(iconPath(background) + "close.svg");
} }
QString QString ExitTool::name() const
ExitTool::name() const
{ {
return tr("Exit"); return tr("Exit");
} }
ToolType ToolType ExitTool::nameID() const
ExitTool::nameID() const
{ {
return ToolType::EXIT; return ToolType::EXIT;
} }
QString QString ExitTool::description() const
ExitTool::description() const
{ {
return tr("Leave the capture screen"); return tr("Leave the capture screen");
} }
CaptureTool* CaptureTool* ExitTool::copy(QObject* parent)
ExitTool::copy(QObject* parent)
{ {
return new ExitTool(parent); return new ExitTool(parent);
} }
void void ExitTool::pressed(const CaptureContext& context)
ExitTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
emit requestAction(REQ_CLOSE_GUI); emit requestAction(REQ_CLOSE_GUI);
} }

View File

@@ -21,21 +21,21 @@
class ExitTool : public AbstractActionTool class ExitTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ExitTool(QObject* parent = nullptr); explicit ExitTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -45,165 +45,158 @@ ImgurUploader::ImgurUploader(const QPixmap& capture, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_pixmap(capture) , m_pixmap(capture)
{ {
setWindowTitle(tr("Upload to Imgur")); setWindowTitle(tr("Upload to Imgur"));
setWindowIcon(QIcon(":img/app/flameshot.svg")); setWindowIcon(QIcon(":img/app/flameshot.svg"));
m_spinner = new LoadSpinner(this); m_spinner = new LoadSpinner(this);
m_spinner->setColor(ConfigHandler().uiMainColorValue()); m_spinner->setColor(ConfigHandler().uiMainColorValue());
m_spinner->start(); m_spinner->start();
m_infoLabel = new QLabel(tr("Uploading Image")); m_infoLabel = new QLabel(tr("Uploading Image"));
m_vLayout = new QVBoxLayout(); m_vLayout = new QVBoxLayout();
setLayout(m_vLayout); setLayout(m_vLayout);
m_vLayout->addWidget(m_spinner, 0, Qt::AlignHCenter); m_vLayout->addWidget(m_spinner, 0, Qt::AlignHCenter);
m_vLayout->addWidget(m_infoLabel); m_vLayout->addWidget(m_infoLabel);
m_NetworkAM = new QNetworkAccessManager(this); m_NetworkAM = new QNetworkAccessManager(this);
connect(m_NetworkAM, connect(m_NetworkAM,
&QNetworkAccessManager::finished, &QNetworkAccessManager::finished,
this, this,
&ImgurUploader::handleReply); &ImgurUploader::handleReply);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
upload(); upload();
// QTimer::singleShot(2000, this, &ImgurUploader::onUploadOk); // testing // QTimer::singleShot(2000, this, &ImgurUploader::onUploadOk); // testing
} }
void void ImgurUploader::handleReply(QNetworkReply* reply)
ImgurUploader::handleReply(QNetworkReply* reply)
{ {
m_spinner->deleteLater(); m_spinner->deleteLater();
if (reply->error() == QNetworkReply::NoError) { if (reply->error() == QNetworkReply::NoError) {
QJsonDocument response = QJsonDocument::fromJson(reply->readAll()); QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
QJsonObject json = response.object(); QJsonObject json = response.object();
QJsonObject data = json[QStringLiteral("data")].toObject(); QJsonObject data = json[QStringLiteral("data")].toObject();
m_imageURL.setUrl(data[QStringLiteral("link")].toString()); m_imageURL.setUrl(data[QStringLiteral("link")].toString());
m_deleteImageURL.setUrl( m_deleteImageURL.setUrl(
QStringLiteral("https://imgur.com/delete/%1") QStringLiteral("https://imgur.com/delete/%1")
.arg(data[QStringLiteral("deletehash")].toString())); .arg(data[QStringLiteral("deletehash")].toString()));
if (ConfigHandler().copyAndCloseAfterUploadEnabled()) { if (ConfigHandler().copyAndCloseAfterUploadEnabled()) {
QApplication::clipboard()->setText(m_imageURL.toString()); QApplication::clipboard()->setText(m_imageURL.toString());
SystemNotification().sendMessage(QObject::tr("URL copied to clipboard.")); SystemNotification().sendMessage(
close(); QObject::tr("URL copied to clipboard."));
close();
} else {
onUploadOk();
}
} else { } else {
onUploadOk(); m_infoLabel->setText(reply->errorString());
} }
} else { new QShortcut(Qt::Key_Escape, this, SLOT(close()));
m_infoLabel->setText(reply->errorString());
}
new QShortcut(Qt::Key_Escape, this, SLOT(close()));
} }
void void ImgurUploader::startDrag()
ImgurUploader::startDrag()
{ {
QMimeData* mimeData = new QMimeData; QMimeData* mimeData = new QMimeData;
mimeData->setUrls(QList<QUrl>{ m_imageURL }); mimeData->setUrls(QList<QUrl>{ m_imageURL });
mimeData->setImageData(m_pixmap); mimeData->setImageData(m_pixmap);
QDrag* dragHandler = new QDrag(this); QDrag* dragHandler = new QDrag(this);
dragHandler->setMimeData(mimeData); dragHandler->setMimeData(mimeData);
dragHandler->setPixmap(m_pixmap.scaled( dragHandler->setPixmap(m_pixmap.scaled(
256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); 256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
dragHandler->exec(); dragHandler->exec();
} }
void void ImgurUploader::upload()
ImgurUploader::upload()
{ {
QByteArray byteArray; QByteArray byteArray;
QBuffer buffer(&byteArray); QBuffer buffer(&byteArray);
m_pixmap.save(&buffer, "PNG"); m_pixmap.save(&buffer, "PNG");
QUrlQuery urlQuery; QUrlQuery urlQuery;
urlQuery.addQueryItem(QStringLiteral("title"), urlQuery.addQueryItem(QStringLiteral("title"),
QStringLiteral("flameshot_screenshot")); QStringLiteral("flameshot_screenshot"));
QString description = FileNameHandler().parsedPattern(); QString description = FileNameHandler().parsedPattern();
urlQuery.addQueryItem(QStringLiteral("description"), description); urlQuery.addQueryItem(QStringLiteral("description"), description);
QUrl url(QStringLiteral("https://api.imgur.com/3/image")); QUrl url(QStringLiteral("https://api.imgur.com/3/image"));
url.setQuery(urlQuery); url.setQuery(urlQuery);
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/application/x-www-form-urlencoded"); "application/application/x-www-form-urlencoded");
request.setRawHeader( request.setRawHeader(
"Authorization", "Authorization",
QStringLiteral("Client-ID %1").arg(IMGUR_CLIENT_ID).toUtf8()); QStringLiteral("Client-ID %1").arg(IMGUR_CLIENT_ID).toUtf8());
m_NetworkAM->post(request, byteArray); m_NetworkAM->post(request, byteArray);
} }
void void ImgurUploader::onUploadOk()
ImgurUploader::onUploadOk()
{ {
m_infoLabel->deleteLater(); m_infoLabel->deleteLater();
m_notification = new NotificationWidget(); m_notification = new NotificationWidget();
m_vLayout->addWidget(m_notification); m_vLayout->addWidget(m_notification);
ImageLabel* imageLabel = new ImageLabel(); ImageLabel* imageLabel = new ImageLabel();
imageLabel->setScreenshot(m_pixmap); imageLabel->setScreenshot(m_pixmap);
imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect( connect(
imageLabel, &ImageLabel::dragInitiated, this, &ImgurUploader::startDrag); imageLabel, &ImageLabel::dragInitiated, this, &ImgurUploader::startDrag);
m_vLayout->addWidget(imageLabel); m_vLayout->addWidget(imageLabel);
m_hLayout = new QHBoxLayout(); m_hLayout = new QHBoxLayout();
m_vLayout->addLayout(m_hLayout); m_vLayout->addLayout(m_hLayout);
m_copyUrlButton = new QPushButton(tr("Copy URL")); m_copyUrlButton = new QPushButton(tr("Copy URL"));
m_openUrlButton = new QPushButton(tr("Open URL")); m_openUrlButton = new QPushButton(tr("Open URL"));
m_openDeleteUrlButton = new QPushButton(tr("Delete image")); m_openDeleteUrlButton = new QPushButton(tr("Delete image"));
m_toClipboardButton = new QPushButton(tr("Image to Clipboard.")); m_toClipboardButton = new QPushButton(tr("Image to Clipboard."));
m_hLayout->addWidget(m_copyUrlButton); m_hLayout->addWidget(m_copyUrlButton);
m_hLayout->addWidget(m_openUrlButton); m_hLayout->addWidget(m_openUrlButton);
m_hLayout->addWidget(m_openDeleteUrlButton); m_hLayout->addWidget(m_openDeleteUrlButton);
m_hLayout->addWidget(m_toClipboardButton); m_hLayout->addWidget(m_toClipboardButton);
connect( connect(
m_copyUrlButton, &QPushButton::clicked, this, &ImgurUploader::copyURL); m_copyUrlButton, &QPushButton::clicked, this, &ImgurUploader::copyURL);
connect( connect(
m_openUrlButton, &QPushButton::clicked, this, &ImgurUploader::openURL); m_openUrlButton, &QPushButton::clicked, this, &ImgurUploader::openURL);
connect(m_openDeleteUrlButton, connect(m_openDeleteUrlButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&ImgurUploader::openDeleteURL); &ImgurUploader::openDeleteURL);
connect(m_toClipboardButton, connect(m_toClipboardButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&ImgurUploader::copyImage); &ImgurUploader::copyImage);
} }
void void ImgurUploader::openURL()
ImgurUploader::openURL()
{ {
bool successful = QDesktopServices::openUrl(m_imageURL); bool successful = QDesktopServices::openUrl(m_imageURL);
if (!successful) { if (!successful) {
m_notification->showMessage(tr("Unable to open the URL.")); m_notification->showMessage(tr("Unable to open the URL."));
} }
} }
void void ImgurUploader::copyURL()
ImgurUploader::copyURL()
{ {
QApplication::clipboard()->setText(m_imageURL.toString()); QApplication::clipboard()->setText(m_imageURL.toString());
m_notification->showMessage(tr("URL copied to clipboard.")); m_notification->showMessage(tr("URL copied to clipboard."));
} }
void void ImgurUploader::openDeleteURL()
ImgurUploader::openDeleteURL()
{ {
bool successful = QDesktopServices::openUrl(m_deleteImageURL); bool successful = QDesktopServices::openUrl(m_deleteImageURL);
if (!successful) { if (!successful) {
m_notification->showMessage(tr("Unable to open the URL.")); m_notification->showMessage(tr("Unable to open the URL."));
} }
} }
void void ImgurUploader::copyImage()
ImgurUploader::copyImage()
{ {
QApplication::clipboard()->setPixmap(m_pixmap); QApplication::clipboard()->setPixmap(m_pixmap);
m_notification->showMessage(tr("Screenshot copied to clipboard.")); m_notification->showMessage(tr("Screenshot copied to clipboard."));
} }

View File

@@ -32,37 +32,37 @@ class NotificationWidget;
class ImgurUploader : public QWidget class ImgurUploader : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ImgurUploader(const QPixmap& capture, QWidget* parent = nullptr); explicit ImgurUploader(const QPixmap& capture, QWidget* parent = nullptr);
private slots: private slots:
void handleReply(QNetworkReply* reply); void handleReply(QNetworkReply* reply);
void startDrag(); void startDrag();
void openURL(); void openURL();
void copyURL(); void copyURL();
void openDeleteURL(); void openDeleteURL();
void copyImage(); void copyImage();
private: private:
QPixmap m_pixmap; QPixmap m_pixmap;
QNetworkAccessManager* m_NetworkAM; QNetworkAccessManager* m_NetworkAM;
QVBoxLayout* m_vLayout; QVBoxLayout* m_vLayout;
QHBoxLayout* m_hLayout; QHBoxLayout* m_hLayout;
// loading // loading
QLabel* m_infoLabel; QLabel* m_infoLabel;
LoadSpinner* m_spinner; LoadSpinner* m_spinner;
// uploaded // uploaded
QPushButton* m_openUrlButton; QPushButton* m_openUrlButton;
QPushButton* m_openDeleteUrlButton; QPushButton* m_openDeleteUrlButton;
QPushButton* m_copyUrlButton; QPushButton* m_copyUrlButton;
QPushButton* m_toClipboardButton; QPushButton* m_toClipboardButton;
QUrl m_imageURL; QUrl m_imageURL;
QUrl m_deleteImageURL; QUrl m_deleteImageURL;
NotificationWidget* m_notification; NotificationWidget* m_notification;
void upload(); void upload();
void onUploadOk(); void onUploadOk();
}; };

View File

@@ -23,52 +23,44 @@ ImgurUploaderTool::ImgurUploaderTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool ImgurUploaderTool::closeOnButtonPressed() const
ImgurUploaderTool::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon ImgurUploaderTool::icon(const QColor& background, bool inEditor) const
ImgurUploaderTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "cloud-upload.svg"); return QIcon(iconPath(background) + "cloud-upload.svg");
} }
QString QString ImgurUploaderTool::name() const
ImgurUploaderTool::name() const
{ {
return tr("Image Uploader"); return tr("Image Uploader");
} }
ToolType ToolType ImgurUploaderTool::nameID() const
ImgurUploaderTool::nameID() const
{ {
return ToolType::IMGUR; return ToolType::IMGUR;
} }
QString QString ImgurUploaderTool::description() const
ImgurUploaderTool::description() const
{ {
return tr("Upload the selection to Imgur"); return tr("Upload the selection to Imgur");
} }
QWidget* QWidget* ImgurUploaderTool::widget()
ImgurUploaderTool::widget()
{ {
return new ImgurUploader(capture); return new ImgurUploader(capture);
} }
CaptureTool* CaptureTool* ImgurUploaderTool::copy(QObject* parent)
ImgurUploaderTool::copy(QObject* parent)
{ {
return new ImgurUploaderTool(parent); return new ImgurUploaderTool(parent);
} }
void void ImgurUploaderTool::pressed(const CaptureContext& context)
ImgurUploaderTool::pressed(const CaptureContext& context)
{ {
capture = context.selectedScreenshotArea(); capture = context.selectedScreenshotArea();
emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
} }

View File

@@ -21,26 +21,26 @@
class ImgurUploaderTool : public AbstractActionTool class ImgurUploaderTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ImgurUploaderTool(QObject* parent = nullptr); explicit ImgurUploaderTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
QWidget* widget() override; QWidget* widget() override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
private: private:
QPixmap capture; QPixmap capture;
}; };

View File

@@ -22,52 +22,44 @@ AppLauncher::AppLauncher(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool AppLauncher::closeOnButtonPressed() const
AppLauncher::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon AppLauncher::icon(const QColor& background, bool inEditor) const
AppLauncher::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "open_with.svg"); return QIcon(iconPath(background) + "open_with.svg");
} }
QString QString AppLauncher::name() const
AppLauncher::name() const
{ {
return tr("App Launcher"); return tr("App Launcher");
} }
ToolType ToolType AppLauncher::nameID() const
AppLauncher::nameID() const
{ {
return ToolType::LAUNCHER; return ToolType::LAUNCHER;
} }
QString QString AppLauncher::description() const
AppLauncher::description() const
{ {
return tr("Choose an app to open the capture"); return tr("Choose an app to open the capture");
} }
QWidget* QWidget* AppLauncher::widget()
AppLauncher::widget()
{ {
return new AppLauncherWidget(capture); return new AppLauncherWidget(capture);
} }
CaptureTool* CaptureTool* AppLauncher::copy(QObject* parent)
AppLauncher::copy(QObject* parent)
{ {
return new AppLauncher(parent); return new AppLauncher(parent);
} }
void void AppLauncher::pressed(const CaptureContext& context)
AppLauncher::pressed(const CaptureContext& context)
{ {
capture = context.selectedScreenshotArea(); capture = context.selectedScreenshotArea();
emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
} }

View File

@@ -21,26 +21,26 @@
class AppLauncher : public AbstractActionTool class AppLauncher : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AppLauncher(QObject* parent = nullptr); explicit AppLauncher(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
QWidget* widget() override; QWidget* widget() override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
private: private:
QPixmap capture; QPixmap capture;
}; };

View File

@@ -51,218 +51,213 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_pixmap(p) , m_pixmap(p)
{ {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(QIcon(":img/app/flameshot.svg")); setWindowIcon(QIcon(":img/app/flameshot.svg"));
setWindowTitle(tr("Open With")); setWindowTitle(tr("Open With"));
m_keepOpen = ConfigHandler().keepOpenAppLauncherValue(); m_keepOpen = ConfigHandler().keepOpenAppLauncherValue();
QString dirLocal = QDir::homePath() + "/.local/share/applications/"; QString dirLocal = QDir::homePath() + "/.local/share/applications/";
QDir appsDirLocal(dirLocal); QDir appsDirLocal(dirLocal);
m_parser.processDirectory(appsDirLocal); m_parser.processDirectory(appsDirLocal);
QString dir = QStringLiteral("/usr/share/applications/"); QString dir = QStringLiteral("/usr/share/applications/");
QDir appsDir(dir); QDir appsDir(dir);
m_parser.processDirectory(appsDir); m_parser.processDirectory(appsDir);
initAppMap(); initAppMap();
initListWidget(); initListWidget();
m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this); m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this);
m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this); m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this);
m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue()); m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue());
connect(m_keepOpenCheckbox, connect(m_keepOpenCheckbox,
&QCheckBox::clicked, &QCheckBox::clicked,
this, this,
&AppLauncherWidget::checkboxClicked); &AppLauncherWidget::checkboxClicked);
// search items // search items
m_lineEdit = new QLineEdit; m_lineEdit = new QLineEdit;
connect(m_lineEdit, connect(m_lineEdit,
&QLineEdit::textChanged, &QLineEdit::textChanged,
this, this,
&AppLauncherWidget::searchChanged); &AppLauncherWidget::searchChanged);
m_filterList = new QListWidget; m_filterList = new QListWidget;
m_filterList->hide();
configureListView(m_filterList);
connect(
m_filterList, &QListWidget::clicked, this, &AppLauncherWidget::launch);
m_layout = new QVBoxLayout(this);
m_layout->addWidget(m_filterList);
m_layout->addWidget(m_tabWidget);
m_layout->addWidget(m_lineEdit);
m_layout->addWidget(m_keepOpenCheckbox);
m_layout->addWidget(m_terminalCheckbox);
m_lineEdit->setFocus();
}
void
AppLauncherWidget::launch(const QModelIndex& index)
{
if (!QFileInfo(m_tempFile).isReadable()) {
m_tempFile =
FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png";
bool ok = m_pixmap.save(m_tempFile);
if (!ok) {
QMessageBox::about(
this, tr("Error"), tr("Unable to write in") + QDir::tempPath());
return;
}
}
QString command = index.data(Qt::UserRole)
.toString()
.replace(QRegExp("(\\%.)"), '"' + m_tempFile + '"');
QString app_name = index.data(Qt::UserRole).toString().split(" ").at(0);
bool inTerminal =
index.data(Qt::UserRole + 1).toBool() || m_terminalCheckbox->isChecked();
if (inTerminal) {
bool ok = TerminalLauncher::launchDetached(command);
if (!ok) {
QMessageBox::about(
this, tr("Error"), tr("Unable to launch in terminal."));
}
} else {
QProcess::startDetached(app_name, { m_tempFile });
}
if (!m_keepOpen) {
close();
}
}
void
AppLauncherWidget::checkboxClicked(const bool enabled)
{
m_keepOpen = enabled;
ConfigHandler().setKeepOpenAppLauncher(enabled);
m_keepOpenCheckbox->setChecked(enabled);
}
void
AppLauncherWidget::searchChanged(const QString& text)
{
if (text.isEmpty()) {
m_filterList->hide(); m_filterList->hide();
m_tabWidget->show(); configureListView(m_filterList);
} else { connect(
m_tabWidget->hide(); m_filterList, &QListWidget::clicked, this, &AppLauncherWidget::launch);
m_filterList->show();
m_filterList->clear(); m_layout = new QVBoxLayout(this);
QRegExp regexp(text, Qt::CaseInsensitive, QRegExp::Wildcard); m_layout->addWidget(m_filterList);
QVector<DesktopAppData> apps; m_layout->addWidget(m_tabWidget);
m_layout->addWidget(m_lineEdit);
m_layout->addWidget(m_keepOpenCheckbox);
m_layout->addWidget(m_terminalCheckbox);
m_lineEdit->setFocus();
}
void AppLauncherWidget::launch(const QModelIndex& index)
{
if (!QFileInfo(m_tempFile).isReadable()) {
m_tempFile =
FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png";
bool ok = m_pixmap.save(m_tempFile);
if (!ok) {
QMessageBox::about(
this, tr("Error"), tr("Unable to write in") + QDir::tempPath());
return;
}
}
QString command = index.data(Qt::UserRole)
.toString()
.replace(QRegExp("(\\%.)"), '"' + m_tempFile + '"');
QString app_name = index.data(Qt::UserRole).toString().split(" ").at(0);
bool inTerminal =
index.data(Qt::UserRole + 1).toBool() || m_terminalCheckbox->isChecked();
if (inTerminal) {
bool ok = TerminalLauncher::launchDetached(command);
if (!ok) {
QMessageBox::about(
this, tr("Error"), tr("Unable to launch in terminal."));
}
} else {
QProcess::startDetached(app_name, { m_tempFile });
}
if (!m_keepOpen) {
close();
}
}
void AppLauncherWidget::checkboxClicked(const bool enabled)
{
m_keepOpen = enabled;
ConfigHandler().setKeepOpenAppLauncher(enabled);
m_keepOpenCheckbox->setChecked(enabled);
}
void AppLauncherWidget::searchChanged(const QString& text)
{
if (text.isEmpty()) {
m_filterList->hide();
m_tabWidget->show();
} else {
m_tabWidget->hide();
m_filterList->show();
m_filterList->clear();
QRegExp regexp(text, Qt::CaseInsensitive, QRegExp::Wildcard);
QVector<DesktopAppData> apps;
for (auto const& i : catIconNames.toStdMap()) {
const QString& cat = i.first;
if (!m_appsMap.contains(cat)) {
continue;
}
const QVector<DesktopAppData>& appList = m_appsMap[cat];
for (const DesktopAppData& app : appList) {
if (!apps.contains(app) && (app.name.contains(regexp) ||
app.description.contains(regexp))) {
apps.append(app);
}
}
}
addAppsToListWidget(m_filterList, apps);
}
}
void AppLauncherWidget::initListWidget()
{
m_tabWidget = new QTabWidget;
const int size = GlobalValues::buttonBaseSize();
m_tabWidget->setIconSize(QSize(size, size));
for (auto const& i : catIconNames.toStdMap()) { for (auto const& i : catIconNames.toStdMap()) {
const QString& cat = i.first; const QString& cat = i.first;
if (!m_appsMap.contains(cat)) { const QString& iconName = i.second;
continue;
} if (!m_appsMap.contains(cat)) {
const QVector<DesktopAppData>& appList = m_appsMap[cat]; continue;
for (const DesktopAppData& app : appList) { }
if (!apps.contains(app) &&
(app.name.contains(regexp) || app.description.contains(regexp))) { QListWidget* itemsWidget = new QListWidget();
apps.append(app); configureListView(itemsWidget);
const QVector<DesktopAppData>& appList = m_appsMap[cat];
addAppsToListWidget(itemsWidget, appList);
m_tabWidget->addTab(
itemsWidget, QIcon::fromTheme(iconName), QLatin1String(""));
m_tabWidget->setTabToolTip(m_tabWidget->count(), cat);
if (cat == QLatin1String("Graphics")) {
m_tabWidget->setCurrentIndex(m_tabWidget->count() - 1);
} }
}
} }
addAppsToListWidget(m_filterList, apps);
}
} }
void void AppLauncherWidget::initAppMap()
AppLauncherWidget::initListWidget()
{ {
m_tabWidget = new QTabWidget; QStringList categories({ "AudioVideo",
const int size = GlobalValues::buttonBaseSize(); "Audio",
m_tabWidget->setIconSize(QSize(size, size)); "Video",
"Development",
"Graphics",
"Network",
"Office",
"Science",
"Settings",
"System",
"Utility" });
for (auto const& i : catIconNames.toStdMap()) { m_appsMap = m_parser.getAppsByCategory(categories);
const QString& cat = i.first;
const QString& iconName = i.second;
if (!m_appsMap.contains(cat)) { // Unify multimedia.
continue; QVector<DesktopAppData> multimediaList;
QStringList multimediaNames;
multimediaNames << QStringLiteral("AudioVideo") << QStringLiteral("Audio")
<< QStringLiteral("Video");
for (const QString& name : multimediaNames) {
if (!m_appsMap.contains(name)) {
continue;
}
for (auto i : m_appsMap[name]) {
if (!multimediaList.contains(i)) {
multimediaList.append(i);
}
}
m_appsMap.remove(name);
} }
m_appsMap.insert(QStringLiteral("Multimedia"), multimediaList);
QListWidget* itemsWidget = new QListWidget();
configureListView(itemsWidget);
const QVector<DesktopAppData>& appList = m_appsMap[cat];
addAppsToListWidget(itemsWidget, appList);
m_tabWidget->addTab(
itemsWidget, QIcon::fromTheme(iconName), QLatin1String(""));
m_tabWidget->setTabToolTip(m_tabWidget->count(), cat);
if (cat == QLatin1String("Graphics")) {
m_tabWidget->setCurrentIndex(m_tabWidget->count() - 1);
}
}
} }
void void AppLauncherWidget::configureListView(QListWidget* widget)
AppLauncherWidget::initAppMap()
{ {
QStringList categories({ "AudioVideo", widget->setItemDelegate(new LauncherItemDelegate());
"Audio", widget->setViewMode(QListWidget::IconMode);
"Video", widget->setResizeMode(QListView::Adjust);
"Development", widget->setSpacing(4);
"Graphics", widget->setFlow(QListView::LeftToRight);
"Network", widget->setDragEnabled(false);
"Office", widget->setMinimumWidth(GlobalValues::buttonBaseSize() * 11);
"Science", connect(widget, &QListWidget::clicked, this, &AppLauncherWidget::launch);
"Settings",
"System",
"Utility" });
m_appsMap = m_parser.getAppsByCategory(categories);
// Unify multimedia.
QVector<DesktopAppData> multimediaList;
QStringList multimediaNames;
multimediaNames << QStringLiteral("AudioVideo") << QStringLiteral("Audio")
<< QStringLiteral("Video");
for (const QString& name : multimediaNames) {
if (!m_appsMap.contains(name)) {
continue;
}
for (auto i : m_appsMap[name]) {
if (!multimediaList.contains(i)) {
multimediaList.append(i);
}
}
m_appsMap.remove(name);
}
m_appsMap.insert(QStringLiteral("Multimedia"), multimediaList);
} }
void void AppLauncherWidget::addAppsToListWidget(
AppLauncherWidget::configureListView(QListWidget* widget) QListWidget* widget,
const QVector<DesktopAppData>& appList)
{ {
widget->setItemDelegate(new LauncherItemDelegate()); for (const DesktopAppData& app : appList) {
widget->setViewMode(QListWidget::IconMode); QListWidgetItem* buttonItem = new QListWidgetItem(widget);
widget->setResizeMode(QListView::Adjust); buttonItem->setData(Qt::DecorationRole, app.icon);
widget->setSpacing(4); buttonItem->setData(Qt::DisplayRole, app.name);
widget->setFlow(QListView::LeftToRight); buttonItem->setData(Qt::UserRole, app.exec);
widget->setDragEnabled(false); buttonItem->setData(Qt::UserRole + 1, app.showInTerminal);
widget->setMinimumWidth(GlobalValues::buttonBaseSize() * 11); QColor foregroundColor =
connect(widget, &QListWidget::clicked, this, &AppLauncherWidget::launch); this->palette().color(QWidget::foregroundRole());
} buttonItem->setForeground(foregroundColor);
void buttonItem->setIcon(app.icon);
AppLauncherWidget::addAppsToListWidget(QListWidget* widget, buttonItem->setText(app.name);
const QVector<DesktopAppData>& appList) buttonItem->setToolTip(app.description);
{ }
for (const DesktopAppData& app : appList) {
QListWidgetItem* buttonItem = new QListWidgetItem(widget);
buttonItem->setData(Qt::DecorationRole, app.icon);
buttonItem->setData(Qt::DisplayRole, app.name);
buttonItem->setData(Qt::UserRole, app.exec);
buttonItem->setData(Qt::UserRole + 1, app.showInTerminal);
QColor foregroundColor = this->palette().color(QWidget::foregroundRole());
buttonItem->setForeground(foregroundColor);
buttonItem->setIcon(app.icon);
buttonItem->setText(app.name);
buttonItem->setToolTip(app.description);
}
} }

View File

@@ -29,31 +29,31 @@ class QListWidget;
class AppLauncherWidget : public QWidget class AppLauncherWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AppLauncherWidget(const QPixmap& p, QWidget* parent = nullptr); explicit AppLauncherWidget(const QPixmap& p, QWidget* parent = nullptr);
private slots: private slots:
void launch(const QModelIndex& index); void launch(const QModelIndex& index);
void checkboxClicked(const bool enabled); void checkboxClicked(const bool enabled);
void searchChanged(const QString& text); void searchChanged(const QString& text);
private: private:
void initListWidget(); void initListWidget();
void initAppMap(); void initAppMap();
void configureListView(QListWidget* widget); void configureListView(QListWidget* widget);
void addAppsToListWidget(QListWidget* widget, void addAppsToListWidget(QListWidget* widget,
const QVector<DesktopAppData>& appList); const QVector<DesktopAppData>& appList);
DesktopFileParser m_parser; DesktopFileParser m_parser;
QPixmap m_pixmap; QPixmap m_pixmap;
QString m_tempFile; QString m_tempFile;
bool m_keepOpen; bool m_keepOpen;
QMap<QString, QVector<DesktopAppData>> m_appsMap; QMap<QString, QVector<DesktopAppData>> m_appsMap;
QCheckBox* m_keepOpenCheckbox; QCheckBox* m_keepOpenCheckbox;
QCheckBox* m_terminalCheckbox; QCheckBox* m_terminalCheckbox;
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
QLineEdit* m_lineEdit; QLineEdit* m_lineEdit;
QListWidget* m_filterList; QListWidget* m_filterList;
QTabWidget* m_tabWidget; QTabWidget* m_tabWidget;
}; };

View File

@@ -23,45 +23,44 @@ LauncherItemDelegate::LauncherItemDelegate(QObject* parent)
: QStyledItemDelegate(parent) : QStyledItemDelegate(parent)
{} {}
void void LauncherItemDelegate::paint(QPainter* painter,
LauncherItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
const QStyleOptionViewItem& option, const QModelIndex& index) const
const QModelIndex& index) const
{ {
const QRect& rect = option.rect; const QRect& rect = option.rect;
if (option.state & (QStyle::State_Selected | QStyle::State_MouseOver)) { if (option.state & (QStyle::State_Selected | QStyle::State_MouseOver)) {
painter->save(); painter->save();
painter->setPen(Qt::transparent); painter->setPen(Qt::transparent);
painter->setBrush(QPalette().highlight()); painter->setBrush(QPalette().highlight());
painter->drawRect(rect.x(), rect.y(), rect.width() - 1, rect.height() - 1); painter->drawRect(
painter->restore(); rect.x(), rect.y(), rect.width() - 1, rect.height() - 1);
} painter->restore();
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>(); }
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
const int iconSide = GlobalValues::buttonBaseSize() * 1.3; const int iconSide = GlobalValues::buttonBaseSize() * 1.3;
const int halfIcon = iconSide / 2; const int halfIcon = iconSide / 2;
const int halfWidth = rect.width() / 2; const int halfWidth = rect.width() / 2;
const int halfHeight = rect.height() / 2; const int halfHeight = rect.height() / 2;
QSize size(iconSide, iconSide); QSize size(iconSide, iconSide);
QPixmap pixIcon = icon.pixmap(size).scaled(size, Qt::KeepAspectRatio); QPixmap pixIcon = icon.pixmap(size).scaled(size, Qt::KeepAspectRatio);
painter->drawPixmap(rect.x() + (halfWidth - halfIcon), painter->drawPixmap(rect.x() + (halfWidth - halfIcon),
rect.y() + (halfHeight / 2 - halfIcon), rect.y() + (halfHeight / 2 - halfIcon),
iconSide, iconSide,
iconSide, iconSide,
pixIcon); pixIcon);
const QRect textRect( const QRect textRect(
rect.x(), rect.y() + halfHeight, rect.width(), halfHeight); rect.x(), rect.y() + halfHeight, rect.width(), halfHeight);
painter->drawText(textRect, painter->drawText(textRect,
Qt::TextWordWrap | Qt::AlignHCenter, Qt::TextWordWrap | Qt::AlignHCenter,
index.data(Qt::DisplayRole).toString()); index.data(Qt::DisplayRole).toString());
} }
QSize QSize LauncherItemDelegate::sizeHint(const QStyleOptionViewItem& option,
LauncherItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
const QModelIndex& index) const
{ {
Q_UNUSED(option); Q_UNUSED(option);
Q_UNUSED(index); Q_UNUSED(index);
const int size = GlobalValues::buttonBaseSize(); const int size = GlobalValues::buttonBaseSize();
return QSize(size * 3.2, size * 3.7); return QSize(size * 3.2, size * 3.7);
} }

View File

@@ -22,14 +22,14 @@
class LauncherItemDelegate : public QStyledItemDelegate class LauncherItemDelegate : public QStyledItemDelegate
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LauncherItemDelegate(QObject* parent = nullptr); explicit LauncherItemDelegate(QObject* parent = nullptr);
void paint(QPainter* painter, void paint(QPainter* painter,
const QStyleOptionViewItem& option, const QStyleOptionViewItem& option,
const QModelIndex& index) const; const QModelIndex& index) const;
QSize sizeHint(const QStyleOptionViewItem& option, QSize sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const; const QModelIndex& index) const;
}; };

View File

@@ -33,28 +33,28 @@
#include "src/tools/launcher/applauncherwidget.h" #include "src/tools/launcher/applauncherwidget.h"
#endif #endif
void void showOpenWithMenu(const QPixmap& capture)
showOpenWithMenu(const QPixmap& capture)
{ {
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
QString tempFile = QString tempFile =
FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png"; FileNameHandler().generateAbsolutePath(QDir::tempPath()) + ".png";
bool ok = capture.save(tempFile); bool ok = capture.save(tempFile);
if (!ok) { if (!ok) {
QMessageBox::about(nullptr, QMessageBox::about(nullptr,
QObject::tr("Error"), QObject::tr("Error"),
QObject::tr("Unable to write in") + QDir::tempPath()); QObject::tr("Unable to write in") +
return; QDir::tempPath());
} return;
}
OPENASINFO info; OPENASINFO info;
auto wStringFile = tempFile.replace("/", "\\").toStdWString(); auto wStringFile = tempFile.replace("/", "\\").toStdWString();
info.pcszFile = wStringFile.c_str(); info.pcszFile = wStringFile.c_str();
info.pcszClass = nullptr; info.pcszClass = nullptr;
info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC; info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
SHOpenWithDialog(nullptr, &info); SHOpenWithDialog(nullptr, &info);
#else #else
auto w = new AppLauncherWidget(capture); auto w = new AppLauncherWidget(capture);
w->show(); w->show();
#endif #endif
} }

View File

@@ -19,5 +19,4 @@
#include <QPixmap> #include <QPixmap>
void void showOpenWithMenu(const QPixmap& capture);
showOpenWithMenu(const QPixmap& capture);

View File

@@ -23,18 +23,18 @@
namespace { namespace {
static const TerminalApp terminalApps[] = { static const TerminalApp terminalApps[] = {
{ "x-terminal-emulator", "-e" }, { "x-terminal-emulator", "-e" },
{ "xfce4-terminal", "-x" }, { "xfce4-terminal", "-x" },
{ "konsole", "-e" }, { "konsole", "-e" },
{ "gnome-terminal", "--" }, { "gnome-terminal", "--" },
{ "terminator", "-e" }, { "terminator", "-e" },
{ "terminology", "-e" }, { "terminology", "-e" },
{ "tilix", "-e" }, { "tilix", "-e" },
{ "xterm", "-e" }, { "xterm", "-e" },
{ "aterm", "-e" }, { "aterm", "-e" },
{ "Eterm", "-e" }, { "Eterm", "-e" },
{ "rxvt", "-e" }, { "rxvt", "-e" },
{ "urxvt", "-e" }, { "urxvt", "-e" },
}; };
} }
@@ -42,24 +42,22 @@ TerminalLauncher::TerminalLauncher(QObject* parent)
: QObject(parent) : QObject(parent)
{} {}
TerminalApp TerminalApp TerminalLauncher::getPreferedTerminal()
TerminalLauncher::getPreferedTerminal()
{ {
TerminalApp res; TerminalApp res;
for (const TerminalApp& app : terminalApps) { for (const TerminalApp& app : terminalApps) {
QString path = QStandardPaths::findExecutable(app.name); QString path = QStandardPaths::findExecutable(app.name);
if (!path.isEmpty()) { if (!path.isEmpty()) {
res = app; res = app;
break; break;
}
} }
} return res;
return res;
} }
bool bool TerminalLauncher::launchDetached(const QString& command)
TerminalLauncher::launchDetached(const QString& command)
{ {
TerminalApp app = getPreferedTerminal(); TerminalApp app = getPreferedTerminal();
QString s = app.name + " " + app.arg + " " + command; QString s = app.name + " " + app.arg + " " + command;
return QProcess::startDetached(app.name, { app.arg, command }); return QProcess::startDetached(app.name, { app.arg, command });
} }

View File

@@ -21,18 +21,18 @@
struct TerminalApp struct TerminalApp
{ {
QString name; QString name;
QString arg; QString arg;
}; };
class TerminalLauncher : public QObject class TerminalLauncher : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TerminalLauncher(QObject* parent = nullptr); explicit TerminalLauncher(QObject* parent = nullptr);
static bool launchDetached(const QString& command); static bool launchDetached(const QString& command);
private: private:
static TerminalApp getPreferedTerminal(); static TerminalApp getPreferedTerminal();
}; };

View File

@@ -27,68 +27,62 @@ namespace {
LineTool::LineTool(QObject* parent) LineTool::LineTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_supportsOrthogonalAdj = true; m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
QIcon QIcon LineTool::icon(const QColor& background, bool inEditor) const
LineTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "line.svg"); return QIcon(iconPath(background) + "line.svg");
} }
QString QString LineTool::name() const
LineTool::name() const
{ {
return tr("Line"); return tr("Line");
} }
ToolType ToolType LineTool::nameID() const
LineTool::nameID() const
{ {
return ToolType::LINE; return ToolType::LINE;
} }
QString QString LineTool::description() const
LineTool::description() const
{ {
return tr("Set the Line as the paint tool"); return tr("Set the Line as the paint tool");
} }
CaptureTool* CaptureTool* LineTool::copy(QObject* parent)
LineTool::copy(QObject* parent)
{ {
return new LineTool(parent); return new LineTool(parent);
} }
void void LineTool::process(QPainter& painter,
LineTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawLine(m_points.first, m_points.second); painter.drawLine(m_points.first, m_points.second);
} }
void void LineTool::paintMousePreview(QPainter& painter,
LineTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void LineTool::drawStart(const CaptureContext& context)
LineTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void LineTool::pressed(const CaptureContext& context)
LineTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,25 +21,25 @@
class LineTool : public AbstractTwoPointTool class LineTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LineTool(QObject* parent = nullptr); explicit LineTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -27,78 +27,71 @@ namespace {
MarkerTool::MarkerTool(QObject* parent) MarkerTool::MarkerTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_supportsOrthogonalAdj = true; m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
QIcon QIcon MarkerTool::icon(const QColor& background, bool inEditor) const
MarkerTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "marker.svg"); return QIcon(iconPath(background) + "marker.svg");
} }
QString QString MarkerTool::name() const
MarkerTool::name() const
{ {
return tr("Marker"); return tr("Marker");
} }
ToolType ToolType MarkerTool::nameID() const
MarkerTool::nameID() const
{ {
return ToolType::MARKER; return ToolType::MARKER;
} }
QString QString MarkerTool::description() const
MarkerTool::description() const
{ {
return tr("Set the Marker as the paint tool"); return tr("Set the Marker as the paint tool");
} }
CaptureTool* CaptureTool* MarkerTool::copy(QObject* parent)
MarkerTool::copy(QObject* parent)
{ {
return new MarkerTool(parent); return new MarkerTool(parent);
} }
void void MarkerTool::process(QPainter& painter,
MarkerTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setCompositionMode(QPainter::CompositionMode_Multiply); painter.setCompositionMode(QPainter::CompositionMode_Multiply);
painter.setOpacity(0.35); painter.setOpacity(0.35);
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawLine(m_points.first, m_points.second); painter.drawLine(m_points.first, m_points.second);
} }
void void MarkerTool::paintMousePreview(QPainter& painter,
MarkerTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
painter.setCompositionMode(QPainter::CompositionMode_Multiply); painter.setCompositionMode(QPainter::CompositionMode_Multiply);
painter.setOpacity(0.35); painter.setOpacity(0.35);
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void MarkerTool::drawStart(const CaptureContext& context)
MarkerTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void MarkerTool::pressed(const CaptureContext& context)
MarkerTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }
void void MarkerTool::thicknessChanged(const int th)
MarkerTool::thicknessChanged(const int th)
{ {
m_thickness = th + PADDING_VALUE; m_thickness = th + PADDING_VALUE;
} }

View File

@@ -21,26 +21,26 @@
class MarkerTool : public AbstractTwoPointTool class MarkerTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MarkerTool(QObject* parent = nullptr); explicit MarkerTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
void thicknessChanged(const int th) override; void thicknessChanged(const int th) override;
}; };

View File

@@ -22,45 +22,38 @@ MoveTool::MoveTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool MoveTool::closeOnButtonPressed() const
MoveTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
QIcon QIcon MoveTool::icon(const QColor& background, bool inEditor) const
MoveTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "cursor-move.svg"); return QIcon(iconPath(background) + "cursor-move.svg");
} }
QString QString MoveTool::name() const
MoveTool::name() const
{ {
return tr("Move"); return tr("Move");
} }
ToolType ToolType MoveTool::nameID() const
MoveTool::nameID() const
{ {
return ToolType::MOVE; return ToolType::MOVE;
} }
QString QString MoveTool::description() const
MoveTool::description() const
{ {
return tr("Move the selection area"); return tr("Move the selection area");
} }
CaptureTool* CaptureTool* MoveTool::copy(QObject* parent)
MoveTool::copy(QObject* parent)
{ {
return new MoveTool(parent); return new MoveTool(parent);
} }
void void MoveTool::pressed(const CaptureContext& context)
MoveTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
emit requestAction(REQ_MOVE_MODE); emit requestAction(REQ_MOVE_MODE);
} }

View File

@@ -21,19 +21,19 @@
class MoveTool : public AbstractActionTool class MoveTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MoveTool(QObject* parent = nullptr); explicit MoveTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
ToolType nameID() const override; ToolType nameID() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -22,65 +22,59 @@ PencilTool::PencilTool(QObject* parent)
: AbstractPathTool(parent) : AbstractPathTool(parent)
{} {}
QIcon QIcon PencilTool::icon(const QColor& background, bool inEditor) const
PencilTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "pencil.svg"); return QIcon(iconPath(background) + "pencil.svg");
} }
QString QString PencilTool::name() const
PencilTool::name() const
{ {
return tr("Pencil"); return tr("Pencil");
} }
ToolType ToolType PencilTool::nameID() const
PencilTool::nameID() const
{ {
return ToolType::PENCIL; return ToolType::PENCIL;
} }
QString QString PencilTool::description() const
PencilTool::description() const
{ {
return tr("Set the Pencil as the paint tool"); return tr("Set the Pencil as the paint tool");
} }
CaptureTool* CaptureTool* PencilTool::copy(QObject* parent)
PencilTool::copy(QObject* parent)
{ {
return new PencilTool(parent); return new PencilTool(parent);
} }
void void PencilTool::process(QPainter& painter,
PencilTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawPolyline(m_points.data(), m_points.size()); painter.drawPolyline(m_points.data(), m_points.size());
} }
void void PencilTool::paintMousePreview(QPainter& painter,
PencilTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, context.thickness + 2)); painter.setPen(QPen(context.color, context.thickness + 2));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void PencilTool::drawStart(const CaptureContext& context)
PencilTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + 2; m_thickness = context.thickness + 2;
m_points.append(context.mousePos); m_points.append(context.mousePos);
m_backupArea.setTopLeft(context.mousePos); m_backupArea.setTopLeft(context.mousePos);
m_backupArea.setBottomRight(context.mousePos); m_backupArea.setBottomRight(context.mousePos);
} }
void void PencilTool::pressed(const CaptureContext& context)
PencilTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,26 +21,26 @@
class PencilTool : public AbstractPathTool class PencilTool : public AbstractPathTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PencilTool(QObject* parent = nullptr); explicit PencilTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -22,58 +22,50 @@ PinTool::PinTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool PinTool::closeOnButtonPressed() const
PinTool::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon PinTool::icon(const QColor& background, bool inEditor) const
PinTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "pin.svg"); return QIcon(iconPath(background) + "pin.svg");
} }
QString QString PinTool::name() const
PinTool::name() const
{ {
return tr("Pin Tool"); return tr("Pin Tool");
} }
ToolType ToolType PinTool::nameID() const
PinTool::nameID() const
{ {
return ToolType::PIN; return ToolType::PIN;
} }
QString QString PinTool::description() const
PinTool::description() const
{ {
return tr("Pin image on the desktop"); return tr("Pin image on the desktop");
} }
QWidget* QWidget* PinTool::widget()
PinTool::widget()
{ {
PinWidget* w = new PinWidget(m_pixmap); PinWidget* w = new PinWidget(m_pixmap);
const int&& m = w->margin(); const int&& m = w->margin();
QRect adjusted_pos = m_geometry + QMargins(m, m, m, m); QRect adjusted_pos = m_geometry + QMargins(m, m, m, m);
w->setGeometry(adjusted_pos); w->setGeometry(adjusted_pos);
return w; return w;
} }
CaptureTool* CaptureTool* PinTool::copy(QObject* parent)
PinTool::copy(QObject* parent)
{ {
return new PinTool(parent); return new PinTool(parent);
} }
void void PinTool::pressed(const CaptureContext& context)
PinTool::pressed(const CaptureContext& context)
{ {
emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_CAPTURE_DONE_OK);
m_geometry = context.selection; m_geometry = context.selection;
m_geometry.setTopLeft(m_geometry.topLeft() + context.widgetOffset); m_geometry.setTopLeft(m_geometry.topLeft() + context.widgetOffset);
m_pixmap = context.selectedScreenshotArea(); m_pixmap = context.selectedScreenshotArea();
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS); emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
} }

View File

@@ -21,27 +21,27 @@
class PinTool : public AbstractActionTool class PinTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PinTool(QObject* parent = nullptr); explicit PinTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
QWidget* widget() override; QWidget* widget() override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
private: private:
QRect m_geometry; QRect m_geometry;
QPixmap m_pixmap; QPixmap m_pixmap;
}; };

View File

@@ -27,93 +27,85 @@ PinWidget::PinWidget(const QPixmap& pixmap, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_pixmap(pixmap) , m_pixmap(pixmap)
{ {
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
// set the bottom widget background transparent // set the bottom widget background transparent
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
ConfigHandler conf; ConfigHandler conf;
m_baseColor = conf.uiMainColorValue(); m_baseColor = conf.uiMainColorValue();
m_hoverColor = conf.uiContrastColorValue(); m_hoverColor = conf.uiContrastColorValue();
m_layout = new QVBoxLayout(this); m_layout = new QVBoxLayout(this);
const int margin = this->margin(); const int margin = this->margin();
m_layout->setContentsMargins(margin, margin, margin, margin); m_layout->setContentsMargins(margin, margin, margin, margin);
m_shadowEffect = new QGraphicsDropShadowEffect(this); m_shadowEffect = new QGraphicsDropShadowEffect(this);
m_shadowEffect->setColor(m_baseColor); m_shadowEffect->setColor(m_baseColor);
m_shadowEffect->setBlurRadius(2 * margin); m_shadowEffect->setBlurRadius(2 * margin);
m_shadowEffect->setOffset(0, 0); m_shadowEffect->setOffset(0, 0);
setGraphicsEffect(m_shadowEffect); setGraphicsEffect(m_shadowEffect);
m_label = new QLabel(); m_label = new QLabel();
m_label->setPixmap(m_pixmap); m_label->setPixmap(m_pixmap);
m_layout->addWidget(m_label); m_layout->addWidget(m_label);
new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(close()));
new QShortcut(Qt::Key_Escape, this, SLOT(close())); new QShortcut(Qt::Key_Escape, this, SLOT(close()));
} }
int int PinWidget::margin() const
PinWidget::margin() const
{ {
return 7; return 7;
} }
void void PinWidget::wheelEvent(QWheelEvent* e)
PinWidget::wheelEvent(QWheelEvent* e)
{ {
int val = e->angleDelta().y() > 0 ? 15 : -15; int val = e->angleDelta().y() > 0 ? 15 : -15;
int newWidth = qBound(50, m_label->width() + val, maximumWidth()); int newWidth = qBound(50, m_label->width() + val, maximumWidth());
int newHeight = qBound(50, m_label->height() + val, maximumHeight()); int newHeight = qBound(50, m_label->height() + val, maximumHeight());
QSize size(newWidth, newHeight); QSize size(newWidth, newHeight);
setScaledPixmap(size); setScaledPixmap(size);
adjustSize(); adjustSize();
e->accept(); e->accept();
} }
void void PinWidget::enterEvent(QEvent*)
PinWidget::enterEvent(QEvent*)
{ {
m_shadowEffect->setColor(m_hoverColor); m_shadowEffect->setColor(m_hoverColor);
} }
void void PinWidget::leaveEvent(QEvent*)
PinWidget::leaveEvent(QEvent*)
{ {
m_shadowEffect->setColor(m_baseColor); m_shadowEffect->setColor(m_baseColor);
} }
void void PinWidget::mouseDoubleClickEvent(QMouseEvent*)
PinWidget::mouseDoubleClickEvent(QMouseEvent*)
{ {
close(); close();
} }
void void PinWidget::mousePressEvent(QMouseEvent* e)
PinWidget::mousePressEvent(QMouseEvent* e)
{ {
m_dragStart = e->globalPos(); m_dragStart = e->globalPos();
m_offsetX = e->localPos().x() / width(); m_offsetX = e->localPos().x() / width();
m_offsetY = e->localPos().y() / height(); m_offsetY = e->localPos().y() / height();
} }
void void PinWidget::mouseMoveEvent(QMouseEvent* e)
PinWidget::mouseMoveEvent(QMouseEvent* e)
{ {
const QPoint delta = e->globalPos() - m_dragStart; const QPoint delta = e->globalPos() - m_dragStart;
int offsetW = width() * m_offsetX; int offsetW = width() * m_offsetX;
int offsetH = height() * m_offsetY; int offsetH = height() * m_offsetY;
move(m_dragStart.x() + delta.x() - offsetW, move(m_dragStart.x() + delta.x() - offsetW,
m_dragStart.y() + delta.y() - offsetH); m_dragStart.y() + delta.y() - offsetH);
} }
void void PinWidget::setScaledPixmap(const QSize& size)
PinWidget::setScaledPixmap(const QSize& size)
{ {
const qreal scale = qApp->devicePixelRatio(); const qreal scale = qApp->devicePixelRatio();
QPixmap scaledPixmap = m_pixmap.scaled( QPixmap scaledPixmap = m_pixmap.scaled(
size * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation); size * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation);
scaledPixmap.setDevicePixelRatio(scale); scaledPixmap.setDevicePixelRatio(scale);
m_label->setPixmap(scaledPixmap); m_label->setPixmap(scaledPixmap);
} }

View File

@@ -25,28 +25,28 @@ class QLabel;
class PinWidget : public QWidget class PinWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PinWidget(const QPixmap& pixmap, QWidget* parent = nullptr); explicit PinWidget(const QPixmap& pixmap, QWidget* parent = nullptr);
int margin() const; int margin() const;
protected: protected:
void wheelEvent(QWheelEvent* e); void wheelEvent(QWheelEvent* e);
void mouseDoubleClickEvent(QMouseEvent*); void mouseDoubleClickEvent(QMouseEvent*);
void mousePressEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*);
void enterEvent(QEvent*); void enterEvent(QEvent*);
void leaveEvent(QEvent*); void leaveEvent(QEvent*);
private: private:
void setScaledPixmap(const QSize& size); void setScaledPixmap(const QSize& size);
QPixmap m_pixmap; QPixmap m_pixmap;
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
QLabel* m_label; QLabel* m_label;
QPoint m_dragStart; QPoint m_dragStart;
qreal m_offsetX, m_offsetY; qreal m_offsetX, m_offsetY;
QGraphicsDropShadowEffect* m_shadowEffect; QGraphicsDropShadowEffect* m_shadowEffect;
QColor m_baseColor, m_hoverColor; QColor m_baseColor, m_hoverColor;
}; };

View File

@@ -28,95 +28,88 @@ PixelateTool::PixelateTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{} {}
QIcon QIcon PixelateTool::icon(const QColor& background, bool inEditor) const
PixelateTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "pixelate.svg"); return QIcon(iconPath(background) + "pixelate.svg");
} }
QString QString PixelateTool::name() const
PixelateTool::name() const
{ {
return tr("Pixelate"); return tr("Pixelate");
} }
ToolType ToolType PixelateTool::nameID() const
PixelateTool::nameID() const
{ {
return ToolType::PIXELATE; return ToolType::PIXELATE;
} }
QString QString PixelateTool::description() const
PixelateTool::description() const
{ {
return tr("Set Pixelate as the paint tool"); return tr("Set Pixelate as the paint tool");
} }
CaptureTool* CaptureTool* PixelateTool::copy(QObject* parent)
PixelateTool::copy(QObject* parent)
{ {
return new PixelateTool(parent); return new PixelateTool(parent);
} }
void void PixelateTool::process(QPainter& painter,
PixelateTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
QPoint& p0 = m_points.first; QPoint& p0 = m_points.first;
QPoint& p1 = m_points.second; QPoint& p1 = m_points.second;
QRect selection = QRect(p0, p1).normalized(); QRect selection = QRect(p0, p1).normalized();
// If thickness is less than 1, use old blur process // If thickness is less than 1, use old blur process
if (m_thickness <= 1) { if (m_thickness <= 1) {
auto pixelRatio = pixmap.devicePixelRatio(); auto pixelRatio = pixmap.devicePixelRatio();
QRect selectionScaled = QRect selectionScaled =
QRect(p0 * pixelRatio, p1 * pixelRatio).normalized(); QRect(p0 * pixelRatio, p1 * pixelRatio).normalized();
QGraphicsBlurEffect* blur = new QGraphicsBlurEffect; QGraphicsBlurEffect* blur = new QGraphicsBlurEffect;
blur->setBlurRadius(10); blur->setBlurRadius(10);
QGraphicsPixmapItem* item = QGraphicsPixmapItem* item =
new QGraphicsPixmapItem(pixmap.copy(selectionScaled)); new QGraphicsPixmapItem(pixmap.copy(selectionScaled));
item->setGraphicsEffect(blur); item->setGraphicsEffect(blur);
QGraphicsScene scene; QGraphicsScene scene;
scene.addItem(item); scene.addItem(item);
scene.render(&painter, selection, QRectF()); scene.render(&painter, selection, QRectF());
blur->setBlurRadius(12); blur->setBlurRadius(12);
scene.render(&painter, selection, QRectF()); scene.render(&painter, selection, QRectF());
} else { } else {
int width = selection.width() * (0.5 / qMax(1, m_thickness)); int width = selection.width() * (0.5 / qMax(1, m_thickness));
QPixmap t = pixmap.copy(selection); QPixmap t = pixmap.copy(selection);
t = t.scaledToWidth(qMax(width, 10), Qt::SmoothTransformation); t = t.scaledToWidth(qMax(width, 10), Qt::SmoothTransformation);
t = t.scaledToWidth(selection.width()); t = t.scaledToWidth(selection.width());
painter.drawImage(selection, t.toImage()); painter.drawImage(selection, t.toImage());
} }
} }
void void PixelateTool::paintMousePreview(QPainter& painter,
PixelateTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
Q_UNUSED(painter); Q_UNUSED(painter);
} }
void void PixelateTool::drawStart(const CaptureContext& context)
PixelateTool::drawStart(const CaptureContext& context)
{ {
m_thickness = context.thickness; m_thickness = context.thickness;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void PixelateTool::pressed(const CaptureContext& context)
PixelateTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,25 +21,25 @@
class PixelateTool : public AbstractTwoPointTool class PixelateTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PixelateTool(QObject* parent = nullptr); explicit PixelateTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -25,71 +25,62 @@ namespace {
RectangleTool::RectangleTool(QObject* parent) RectangleTool::RectangleTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
QIcon QIcon RectangleTool::icon(const QColor& background, bool inEditor) const
RectangleTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "square.svg"); return QIcon(iconPath(background) + "square.svg");
} }
QString QString RectangleTool::name() const
RectangleTool::name() const
{ {
return tr("Rectangle"); return tr("Rectangle");
} }
ToolType ToolType RectangleTool::nameID() const
RectangleTool::nameID() const
{ {
return ToolType::RECTANGLE; return ToolType::RECTANGLE;
} }
QString QString RectangleTool::description() const
RectangleTool::description() const
{ {
return tr("Set the Rectangle as the paint tool"); return tr("Set the Rectangle as the paint tool");
} }
CaptureTool* CaptureTool* RectangleTool::copy(QObject* parent)
RectangleTool::copy(QObject* parent)
{ {
return new RectangleTool(parent); return new RectangleTool(parent);
} }
void void RectangleTool::process(QPainter& painter,
RectangleTool::process(QPainter& painter, const QPixmap& pixmap,
const QPixmap& pixmap, bool recordUndo)
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.setBrush(QBrush(m_color)); painter.setBrush(QBrush(m_color));
painter.drawRect(QRect(m_points.first, m_points.second)); painter.drawRect(QRect(m_points.first, m_points.second));
} }
void void RectangleTool::paintMousePreview(QPainter& painter,
RectangleTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void RectangleTool::drawStart(const CaptureContext& context)
RectangleTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void RectangleTool::pressed(const CaptureContext& context)
RectangleTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,25 +21,25 @@
class RectangleTool : public AbstractTwoPointTool class RectangleTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit RectangleTool(QObject* parent = nullptr); explicit RectangleTool(QObject* parent = nullptr);
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -22,45 +22,38 @@ RedoTool::RedoTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool RedoTool::closeOnButtonPressed() const
RedoTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
QIcon QIcon RedoTool::icon(const QColor& background, bool inEditor) const
RedoTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "redo-variant.svg"); return QIcon(iconPath(background) + "redo-variant.svg");
} }
QString QString RedoTool::name() const
RedoTool::name() const
{ {
return tr("Redo"); return tr("Redo");
} }
ToolType ToolType RedoTool::nameID() const
RedoTool::nameID() const
{ {
return ToolType::REDO; return ToolType::REDO;
} }
QString QString RedoTool::description() const
RedoTool::description() const
{ {
return tr("Redo the next modification"); return tr("Redo the next modification");
} }
CaptureTool* CaptureTool* RedoTool::copy(QObject* parent)
RedoTool::copy(QObject* parent)
{ {
return new RedoTool(parent); return new RedoTool(parent);
} }
void void RedoTool::pressed(const CaptureContext& context)
RedoTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
emit requestAction(REQ_REDO_MODIFICATION); emit requestAction(REQ_REDO_MODIFICATION);
} }

View File

@@ -21,21 +21,21 @@
class RedoTool : public AbstractActionTool class RedoTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit RedoTool(QObject* parent = nullptr); explicit RedoTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -23,57 +23,50 @@ SaveTool::SaveTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool SaveTool::closeOnButtonPressed() const
SaveTool::closeOnButtonPressed() const
{ {
return true; return true;
} }
QIcon QIcon SaveTool::icon(const QColor& background, bool inEditor) const
SaveTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "content-save.svg"); return QIcon(iconPath(background) + "content-save.svg");
} }
QString QString SaveTool::name() const
SaveTool::name() const
{ {
return tr("Save"); return tr("Save");
} }
ToolType ToolType SaveTool::nameID() const
SaveTool::nameID() const
{ {
return ToolType::SAVE; return ToolType::SAVE;
} }
QString QString SaveTool::description() const
SaveTool::description() const
{ {
return tr("Save the capture"); return tr("Save the capture");
} }
CaptureTool* CaptureTool* SaveTool::copy(QObject* parent)
SaveTool::copy(QObject* parent)
{ {
return new SaveTool(parent); return new SaveTool(parent);
} }
void void SaveTool::pressed(const CaptureContext& context)
SaveTool::pressed(const CaptureContext& context)
{ {
if (context.savePath.isEmpty()) { if (context.savePath.isEmpty()) {
emit requestAction(REQ_HIDE_GUI); emit requestAction(REQ_HIDE_GUI);
bool ok = bool ok = ScreenshotSaver().saveToFilesystemGUI(
ScreenshotSaver().saveToFilesystemGUI(context.selectedScreenshotArea()); context.selectedScreenshotArea());
if (ok) { if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK); emit requestAction(REQ_CAPTURE_DONE_OK);
}
} else {
bool ok = ScreenshotSaver().saveToFilesystem(
context.selectedScreenshotArea(), context.savePath, "");
if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK);
}
} }
} else {
bool ok = ScreenshotSaver().saveToFilesystem(
context.selectedScreenshotArea(), context.savePath, "");
if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK);
}
}
} }

View File

@@ -21,21 +21,21 @@
class SaveTool : public AbstractActionTool class SaveTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SaveTool(QObject* parent = nullptr); explicit SaveTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -25,76 +25,66 @@ namespace {
SelectionTool::SelectionTool(QObject* parent) SelectionTool::SelectionTool(QObject* parent)
: AbstractTwoPointTool(parent) : AbstractTwoPointTool(parent)
{ {
m_supportsDiagonalAdj = true; m_supportsDiagonalAdj = true;
} }
bool bool SelectionTool::closeOnButtonPressed() const
SelectionTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
QIcon QIcon SelectionTool::icon(const QColor& background, bool inEditor) const
SelectionTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "square-outline.svg"); return QIcon(iconPath(background) + "square-outline.svg");
} }
QString QString SelectionTool::name() const
SelectionTool::name() const
{ {
return tr("Rectangular Selection"); return tr("Rectangular Selection");
} }
ToolType ToolType SelectionTool::nameID() const
SelectionTool::nameID() const
{ {
return ToolType::SELECTION; return ToolType::SELECTION;
} }
QString QString SelectionTool::description() const
SelectionTool::description() const
{ {
return tr("Set Selection as the paint tool"); return tr("Set Selection as the paint tool");
} }
CaptureTool* CaptureTool* SelectionTool::copy(QObject* parent)
SelectionTool::copy(QObject* parent)
{ {
return new SelectionTool(parent); return new SelectionTool(parent);
} }
void void SelectionTool::process(QPainter& painter,
SelectionTool::process(QPainter& painter, const QPixmap& pixmap,
const QPixmap& pixmap, bool recordUndo)
bool recordUndo)
{ {
if (recordUndo) { if (recordUndo) {
updateBackup(pixmap); updateBackup(pixmap);
} }
painter.setPen(QPen(m_color, m_thickness)); painter.setPen(QPen(m_color, m_thickness));
painter.drawRect(QRect(m_points.first, m_points.second)); painter.drawRect(QRect(m_points.first, m_points.second));
} }
void void SelectionTool::paintMousePreview(QPainter& painter,
SelectionTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
const CaptureContext& context)
{ {
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness)); painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos); painter.drawLine(context.mousePos, context.mousePos);
} }
void void SelectionTool::drawStart(const CaptureContext& context)
SelectionTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE; m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos; m_points.first = context.mousePos;
m_points.second = context.mousePos; m_points.second = context.mousePos;
} }
void void SelectionTool::pressed(const CaptureContext& context)
SelectionTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,27 +21,27 @@
class SelectionTool : public AbstractTwoPointTool class SelectionTool : public AbstractTwoPointTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SelectionTool(QObject* parent = nullptr); explicit SelectionTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
void process(QPainter& painter, void process(QPainter& painter,
const QPixmap& pixmap, const QPixmap& pixmap,
bool recordUndo = false) override; bool recordUndo = false) override;
void paintMousePreview(QPainter& painter, void paintMousePreview(QPainter& painter,
const CaptureContext& context) override; const CaptureContext& context) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void drawStart(const CaptureContext& context) override; void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -22,44 +22,37 @@ SizeIndicatorTool::SizeIndicatorTool(QObject* parent)
: AbstractActionTool(parent) : AbstractActionTool(parent)
{} {}
bool bool SizeIndicatorTool::closeOnButtonPressed() const
SizeIndicatorTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
QIcon QIcon SizeIndicatorTool::icon(const QColor& background, bool inEditor) const
SizeIndicatorTool::icon(const QColor& background, bool inEditor) const
{ {
return inEditor ? QIcon() return inEditor ? QIcon()
: QIcon(iconPath(background) + "size_indicator.svg"); : QIcon(iconPath(background) + "size_indicator.svg");
} }
QString QString SizeIndicatorTool::name() const
SizeIndicatorTool::name() const
{ {
return tr("Selection Size Indicator"); return tr("Selection Size Indicator");
} }
ToolType ToolType SizeIndicatorTool::nameID() const
SizeIndicatorTool::nameID() const
{ {
return ToolType::SIZEINDICATOR; return ToolType::SIZEINDICATOR;
} }
QString QString SizeIndicatorTool::description() const
SizeIndicatorTool::description() const
{ {
return tr("Show the dimensions of the selection (X Y)"); return tr("Show the dimensions of the selection (X Y)");
} }
CaptureTool* CaptureTool* SizeIndicatorTool::copy(QObject* parent)
SizeIndicatorTool::copy(QObject* parent)
{ {
return new SizeIndicatorTool(parent); return new SizeIndicatorTool(parent);
} }
void void SizeIndicatorTool::pressed(const CaptureContext& context)
SizeIndicatorTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }

View File

@@ -21,21 +21,21 @@
class SizeIndicatorTool : public AbstractActionTool class SizeIndicatorTool : public AbstractActionTool
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SizeIndicatorTool(QObject* parent = nullptr); explicit SizeIndicatorTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const; bool closeOnButtonPressed() const;
QIcon icon(const QColor& background, bool inEditor) const override; QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override; QString name() const override;
QString description() const override; QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override; CaptureTool* copy(QObject* parent = nullptr) override;
protected: protected:
ToolType nameID() const override; ToolType nameID() const override;
public slots: public slots:
void pressed(const CaptureContext& context) override; void pressed(const CaptureContext& context) override;
}; };

View File

@@ -27,98 +27,93 @@
TextConfig::TextConfig(QWidget* parent) TextConfig::TextConfig(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
m_layout = new QVBoxLayout(this); m_layout = new QVBoxLayout(this);
QFontDatabase fontDB; QFontDatabase fontDB;
QComboBox* fontsCB = new QComboBox(); QComboBox* fontsCB = new QComboBox();
connect(fontsCB, connect(fontsCB,
&QComboBox::currentTextChanged, &QComboBox::currentTextChanged,
this, this,
&TextConfig::fontFamilyChanged); &TextConfig::fontFamilyChanged);
fontsCB->addItems(fontDB.families()); fontsCB->addItems(fontDB.families());
// TODO save family in config // TODO save family in config
int index = fontsCB->findText(font().family()); int index = fontsCB->findText(font().family());
fontsCB->setCurrentIndex(index); fontsCB->setCurrentIndex(index);
QString iconPrefix = ColorUtils::colorIsDark(palette().windowText().color()) QString iconPrefix = ColorUtils::colorIsDark(palette().windowText().color())
? PathInfo::blackIconPath() ? PathInfo::blackIconPath()
: PathInfo::whiteIconPath(); : PathInfo::whiteIconPath();
m_strikeOutButton = new QPushButton( m_strikeOutButton = new QPushButton(
QIcon(iconPrefix + "format_strikethrough.svg"), QLatin1String("")); QIcon(iconPrefix + "format_strikethrough.svg"), QLatin1String(""));
m_strikeOutButton->setCheckable(true); m_strikeOutButton->setCheckable(true);
connect(m_strikeOutButton, connect(m_strikeOutButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&TextConfig::fontStrikeOutChanged); &TextConfig::fontStrikeOutChanged);
m_strikeOutButton->setToolTip(tr("StrikeOut")); m_strikeOutButton->setToolTip(tr("StrikeOut"));
m_underlineButton = new QPushButton( m_underlineButton = new QPushButton(
QIcon(iconPrefix + "format_underlined.svg"), QLatin1String("")); QIcon(iconPrefix + "format_underlined.svg"), QLatin1String(""));
m_underlineButton->setCheckable(true); m_underlineButton->setCheckable(true);
connect(m_underlineButton, connect(m_underlineButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&TextConfig::fontUnderlineChanged); &TextConfig::fontUnderlineChanged);
m_underlineButton->setToolTip(tr("Underline")); m_underlineButton->setToolTip(tr("Underline"));
m_weightButton = m_weightButton =
new QPushButton(QIcon(iconPrefix + "format_bold.svg"), QLatin1String("")); new QPushButton(QIcon(iconPrefix + "format_bold.svg"), QLatin1String(""));
m_weightButton->setCheckable(true); m_weightButton->setCheckable(true);
connect(m_weightButton, connect(m_weightButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&TextConfig::weightButtonPressed); &TextConfig::weightButtonPressed);
m_weightButton->setToolTip(tr("Bold")); m_weightButton->setToolTip(tr("Bold"));
m_italicButton = m_italicButton = new QPushButton(QIcon(iconPrefix + "format_italic.svg"),
new QPushButton(QIcon(iconPrefix + "format_italic.svg"), QLatin1String("")); QLatin1String(""));
m_italicButton->setCheckable(true); m_italicButton->setCheckable(true);
connect(m_italicButton, connect(m_italicButton,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&TextConfig::fontItalicChanged); &TextConfig::fontItalicChanged);
m_italicButton->setToolTip(tr("Italic")); m_italicButton->setToolTip(tr("Italic"));
QHBoxLayout* modifiersLayout = new QHBoxLayout(); QHBoxLayout* modifiersLayout = new QHBoxLayout();
m_layout->addWidget(fontsCB); m_layout->addWidget(fontsCB);
modifiersLayout->addWidget(m_strikeOutButton); modifiersLayout->addWidget(m_strikeOutButton);
modifiersLayout->addWidget(m_underlineButton); modifiersLayout->addWidget(m_underlineButton);
modifiersLayout->addWidget(m_weightButton); modifiersLayout->addWidget(m_weightButton);
modifiersLayout->addWidget(m_italicButton); modifiersLayout->addWidget(m_italicButton);
m_layout->addLayout(modifiersLayout); m_layout->addLayout(modifiersLayout);
} }
void void TextConfig::setUnderline(const bool u)
TextConfig::setUnderline(const bool u)
{ {
m_underlineButton->setChecked(u); m_underlineButton->setChecked(u);
} }
void void TextConfig::setStrikeOut(const bool s)
TextConfig::setStrikeOut(const bool s)
{ {
m_strikeOutButton->setChecked(s); m_strikeOutButton->setChecked(s);
} }
void void TextConfig::setWeight(const int w)
TextConfig::setWeight(const int w)
{ {
m_weightButton->setChecked(static_cast<QFont::Weight>(w) == QFont::Bold); m_weightButton->setChecked(static_cast<QFont::Weight>(w) == QFont::Bold);
} }
void void TextConfig::setItalic(const bool i)
TextConfig::setItalic(const bool i)
{ {
m_italicButton->setChecked(i); m_italicButton->setChecked(i);
} }
void void TextConfig::weightButtonPressed(const bool w)
TextConfig::weightButtonPressed(const bool w)
{ {
if (w) { if (w) {
emit fontWeightChanged(QFont::Bold); emit fontWeightChanged(QFont::Bold);
} else { } else {
emit fontWeightChanged(QFont::Normal); emit fontWeightChanged(QFont::Normal);
} }
} }

View File

@@ -24,31 +24,31 @@ class QPushButton;
class TextConfig : public QWidget class TextConfig : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TextConfig(QWidget* parent = nullptr); explicit TextConfig(QWidget* parent = nullptr);
void setUnderline(const bool u); void setUnderline(const bool u);
void setStrikeOut(const bool s); void setStrikeOut(const bool s);
void setWeight(const int w); void setWeight(const int w);
void setItalic(const bool i); void setItalic(const bool i);
signals: signals:
void fontFamilyChanged(const QString& f); void fontFamilyChanged(const QString& f);
void fontUnderlineChanged(const bool underlined); void fontUnderlineChanged(const bool underlined);
void fontStrikeOutChanged(const bool dashed); void fontStrikeOutChanged(const bool dashed);
void fontWeightChanged(const QFont::Weight w); void fontWeightChanged(const QFont::Weight w);
void fontItalicChanged(const bool italic); void fontItalicChanged(const bool italic);
public slots: public slots:
private slots: private slots:
void weightButtonPressed(const bool w); void weightButtonPressed(const bool w);
private: private:
QVBoxLayout* m_layout; QVBoxLayout* m_layout;
QPushButton* m_strikeOutButton; QPushButton* m_strikeOutButton;
QPushButton* m_underlineButton; QPushButton* m_underlineButton;
QPushButton* m_weightButton; QPushButton* m_weightButton;
QPushButton* m_italicButton; QPushButton* m_italicButton;
}; };

View File

@@ -26,246 +26,227 @@ TextTool::TextTool(QObject* parent)
, m_size(1) , m_size(1)
{} {}
bool bool TextTool::isValid() const
TextTool::isValid() const
{ {
return !m_text.isEmpty(); return !m_text.isEmpty();
} }
bool bool TextTool::closeOnButtonPressed() const
TextTool::closeOnButtonPressed() const
{ {
return false; return false;
} }
bool bool TextTool::isSelectable() const
TextTool::isSelectable() const
{ {
return true; return true;
} }
bool bool TextTool::showMousePreview() const
TextTool::showMousePreview() const
{ {
return false; return false;
} }
QIcon QIcon TextTool::icon(const QColor& background, bool inEditor) const
TextTool::icon(const QColor& background, bool inEditor) const
{ {
Q_UNUSED(inEditor); Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "text.svg"); return QIcon(iconPath(background) + "text.svg");
} }
QString QString TextTool::name() const
TextTool::name() const
{ {
return tr("Text"); return tr("Text");
} }
ToolType ToolType TextTool::nameID() const
TextTool::nameID() const
{ {
return ToolType::TEXT; return ToolType::TEXT;
} }
QString QString TextTool::description() const
TextTool::description() const
{ {
return tr("Add text to your capture"); return tr("Add text to your capture");
} }
QWidget* QWidget* TextTool::widget()
TextTool::widget()
{ {
TextWidget* w = new TextWidget(); TextWidget* w = new TextWidget();
w->setTextColor(m_color); w->setTextColor(m_color);
m_font.setPointSize(m_size + BASE_POINT_SIZE); m_font.setPointSize(m_size + BASE_POINT_SIZE);
w->setFont(m_font); w->setFont(m_font);
connect(w, &TextWidget::textUpdated, this, &TextTool::updateText); connect(w, &TextWidget::textUpdated, this, &TextTool::updateText);
m_widget = w; m_widget = w;
return w; return w;
} }
QWidget* QWidget* TextTool::configurationWidget()
TextTool::configurationWidget()
{ {
m_confW = new TextConfig(); m_confW = new TextConfig();
connect( connect(
m_confW, &TextConfig::fontFamilyChanged, this, &TextTool::updateFamily); m_confW, &TextConfig::fontFamilyChanged, this, &TextTool::updateFamily);
connect( connect(m_confW,
m_confW, &TextConfig::fontItalicChanged, this, &TextTool::updateFontItalic); &TextConfig::fontItalicChanged,
connect(m_confW, this,
&TextConfig::fontStrikeOutChanged, &TextTool::updateFontItalic);
this, connect(m_confW,
&TextTool::updateFontStrikeOut); &TextConfig::fontStrikeOutChanged,
connect(m_confW, this,
&TextConfig::fontUnderlineChanged, &TextTool::updateFontStrikeOut);
this, connect(m_confW,
&TextTool::updateFontUnderline); &TextConfig::fontUnderlineChanged,
connect( this,
m_confW, &TextConfig::fontWeightChanged, this, &TextTool::updateFontWeight); &TextTool::updateFontUnderline);
m_confW->setItalic(m_font.italic()); connect(m_confW,
m_confW->setUnderline(m_font.underline()); &TextConfig::fontWeightChanged,
m_confW->setStrikeOut(m_font.strikeOut()); this,
m_confW->setWeight(m_font.weight()); &TextTool::updateFontWeight);
return m_confW; m_confW->setItalic(m_font.italic());
m_confW->setUnderline(m_font.underline());
m_confW->setStrikeOut(m_font.strikeOut());
m_confW->setWeight(m_font.weight());
return m_confW;
} }
CaptureTool* CaptureTool* TextTool::copy(QObject* parent)
TextTool::copy(QObject* parent)
{ {
TextTool* tt = new TextTool(parent); TextTool* tt = new TextTool(parent);
connect(m_confW, &TextConfig::fontFamilyChanged, tt, &TextTool::updateFamily); connect(
connect( m_confW, &TextConfig::fontFamilyChanged, tt, &TextTool::updateFamily);
m_confW, &TextConfig::fontItalicChanged, tt, &TextTool::updateFontItalic); connect(
connect(m_confW, m_confW, &TextConfig::fontItalicChanged, tt, &TextTool::updateFontItalic);
&TextConfig::fontStrikeOutChanged, connect(m_confW,
tt, &TextConfig::fontStrikeOutChanged,
&TextTool::updateFontStrikeOut); tt,
connect(m_confW, &TextTool::updateFontStrikeOut);
&TextConfig::fontUnderlineChanged, connect(m_confW,
tt, &TextConfig::fontUnderlineChanged,
&TextTool::updateFontUnderline); tt,
connect( &TextTool::updateFontUnderline);
m_confW, &TextConfig::fontWeightChanged, tt, &TextTool::updateFontWeight); connect(
tt->m_font = m_font; m_confW, &TextConfig::fontWeightChanged, tt, &TextTool::updateFontWeight);
return tt; tt->m_font = m_font;
return tt;
} }
void void TextTool::undo(QPixmap& pixmap)
TextTool::undo(QPixmap& pixmap)
{ {
QPainter p(&pixmap); QPainter p(&pixmap);
p.drawPixmap(m_backupArea.topLeft(), m_pixmapBackup); p.drawPixmap(m_backupArea.topLeft(), m_pixmapBackup);
} }
void void TextTool::process(QPainter& painter,
TextTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo) const QPixmap& pixmap,
bool recordUndo)
{ {
if (m_text.isEmpty()) { if (m_text.isEmpty()) {
return; return;
} }
QFontMetrics fm(m_font); QFontMetrics fm(m_font);
QSize size(fm.boundingRect(QRect(), 0, m_text).size()); QSize size(fm.boundingRect(QRect(), 0, m_text).size());
m_backupArea.setSize(size); m_backupArea.setSize(size);
if (recordUndo) { if (recordUndo) {
m_pixmapBackup = pixmap.copy(m_backupArea + QMargins(0, 0, 5, 5)); m_pixmapBackup = pixmap.copy(m_backupArea + QMargins(0, 0, 5, 5));
} }
// draw text // draw text
painter.setFont(m_font); painter.setFont(m_font);
painter.setPen(m_color); painter.setPen(m_color);
painter.drawText(m_backupArea + QMargins(-5, -5, 5, 5), m_text); painter.drawText(m_backupArea + QMargins(-5, -5, 5, 5), m_text);
} }
void void TextTool::paintMousePreview(QPainter& painter,
TextTool::paintMousePreview(QPainter& painter, const CaptureContext& context) const CaptureContext& context)
{ {
Q_UNUSED(painter); Q_UNUSED(painter);
Q_UNUSED(context); Q_UNUSED(context);
} }
void void TextTool::drawEnd(const QPoint& p)
TextTool::drawEnd(const QPoint& p)
{ {
m_backupArea.moveTo(p); m_backupArea.moveTo(p);
} }
void void TextTool::drawMove(const QPoint& p)
TextTool::drawMove(const QPoint& p)
{ {
m_widget->move(p); m_widget->move(p);
} }
void void TextTool::drawStart(const CaptureContext& context)
TextTool::drawStart(const CaptureContext& context)
{ {
m_color = context.color; m_color = context.color;
m_size = context.thickness; m_size = context.thickness;
emit requestAction(REQ_ADD_CHILD_WIDGET); emit requestAction(REQ_ADD_CHILD_WIDGET);
} }
void void TextTool::pressed(const CaptureContext& context)
TextTool::pressed(const CaptureContext& context)
{ {
Q_UNUSED(context); Q_UNUSED(context);
} }
void void TextTool::colorChanged(const QColor& c)
TextTool::colorChanged(const QColor& c)
{ {
m_color = c; m_color = c;
if (m_widget) { if (m_widget) {
m_widget->setTextColor(c); m_widget->setTextColor(c);
} }
} }
void void TextTool::thicknessChanged(const int th)
TextTool::thicknessChanged(const int th)
{ {
m_size = th; m_size = th;
m_font.setPointSize(m_size + BASE_POINT_SIZE); m_font.setPointSize(m_size + BASE_POINT_SIZE);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }
void void TextTool::updateText(const QString& s)
TextTool::updateText(const QString& s)
{ {
m_text = s; m_text = s;
} }
void void TextTool::setFont(const QFont& f)
TextTool::setFont(const QFont& f)
{ {
m_font = f; m_font = f;
if (m_widget) { if (m_widget) {
m_widget->setFont(f); m_widget->setFont(f);
} }
} }
void void TextTool::updateFamily(const QString& s)
TextTool::updateFamily(const QString& s)
{ {
m_font.setFamily(s); m_font.setFamily(s);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }
void void TextTool::updateFontUnderline(const bool underlined)
TextTool::updateFontUnderline(const bool underlined)
{ {
m_font.setUnderline(underlined); m_font.setUnderline(underlined);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }
void void TextTool::updateFontStrikeOut(const bool s)
TextTool::updateFontStrikeOut(const bool s)
{ {
m_font.setStrikeOut(s); m_font.setStrikeOut(s);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }
void void TextTool::updateFontWeight(const QFont::Weight w)
TextTool::updateFontWeight(const QFont::Weight w)
{ {
m_font.setWeight(w); m_font.setWeight(w);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }
void void TextTool::updateFontItalic(const bool italic)
TextTool::updateFontItalic(const bool italic)
{ {
m_font.setItalic(italic); m_font.setItalic(italic);
if (m_widget) { if (m_widget) {
m_widget->setFont(m_font); m_widget->setFont(m_font);
} }
} }

Some files were not shown because too many files have changed in this diff Show More