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
BasedOnStyle: Mozilla
IndentWidth: 4
AccessModifierOffset: -4
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None

View File

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

View File

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

View File

@@ -34,9 +34,9 @@ namespace color_widgets {
enum MouseStatus
{
Nothing,
DragCircle,
DragSquare
Nothing,
DragCircle,
DragSquare
};
static const ColorWheel::DisplayFlags hard_default_flags =
@@ -48,517 +48,499 @@ static const double selector_radius = 6;
class ColorWheel::Private
{
private:
ColorWheel* const w;
ColorWheel* const w;
public:
qreal hue, sat, val;
qreal bgBrightness;
unsigned int wheel_width;
MouseStatus mouse_status;
QPixmap hue_ring;
QImage inner_selector;
DisplayFlags display_flags;
QColor (*color_from)(qreal, qreal, qreal, qreal);
QColor (*rainbow_from_hue)(qreal);
int max_size = 128;
qreal hue, sat, val;
qreal bgBrightness;
unsigned int wheel_width;
MouseStatus mouse_status;
QPixmap hue_ring;
QImage inner_selector;
DisplayFlags display_flags;
QColor (*color_from)(qreal, qreal, qreal, qreal);
QColor (*rainbow_from_hue)(qreal);
int max_size = 128;
explicit Private(ColorWheel* widget)
: w(widget)
, hue(0)
, sat(0)
, val(0)
, wheel_width(20)
, mouse_status(Nothing)
, display_flags(FLAGS_DEFAULT)
, color_from(&QColor::fromHsvF)
, rainbow_from_hue(&detail::rainbow_hsv)
{
QColor bgColor = widget->palette().window().color();
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));
explicit Private(ColorWheel* widget)
: w(widget)
, hue(0)
, sat(0)
, val(0)
, wheel_width(20)
, mouse_status(Nothing)
, display_flags(FLAGS_DEFAULT)
, color_from(&QColor::fromHsvF)
, rainbow_from_hue(&detail::rainbow_hsv)
{
QColor bgColor = widget->palette().window().color();
bgBrightness = color_widgets::detail::color_lumaF(bgColor);
}
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);
/// 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());
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)
: QWidget(parent)
, p(new Private(this))
{
setDisplayFlags(FLAGS_DEFAULT);
setAcceptDrops(true);
setDisplayFlags(FLAGS_DEFAULT);
setAcceptDrops(true);
}
ColorWheel::~ColorWheel()
{
delete p;
delete p;
}
QColor
ColorWheel::color() const
QColor 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
ColorWheel::sizeHint() const
QSize ColorWheel::sizeHint() const
{
return QSize(p->wheel_width * 5, p->wheel_width * 5);
return QSize(p->wheel_width * 5, p->wheel_width * 5);
}
qreal
ColorWheel::hue() const
qreal ColorWheel::hue() const
{
if ((p->display_flags & COLOR_LCH) && p->sat > 0.01)
return color().hueF();
return p->hue;
if ((p->display_flags & COLOR_LCH) && p->sat > 0.01)
return color().hueF();
return p->hue;
}
qreal
ColorWheel::saturation() const
qreal ColorWheel::saturation() const
{
return color().hsvSaturationF();
return color().hsvSaturationF();
}
qreal
ColorWheel::value() const
qreal ColorWheel::value() const
{
return color().valueF();
return color().valueF();
}
unsigned int
ColorWheel::wheelWidth() const
unsigned int ColorWheel::wheelWidth() const
{
return p->wheel_width;
return p->wheel_width;
}
void
ColorWheel::setWheelWidth(unsigned int w)
void ColorWheel::setWheelWidth(unsigned int 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->wheel_width = w;
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();
} 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());
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();
painter.rotate(p->selector_image_angle());
painter.translate(p->selector_image_offset());
QPointF selector_position;
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);
qreal side = p->square_size();
selector_position = QPointF(p->sat * side, p->val * side);
} 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();
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);
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);
}
emit colorSelected(color());
emit colorChanged(color());
update();
}
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::mousePressEvent(QMouseEvent* ev)
void ColorWheel::mouseMoveEvent(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;
if (p->mouse_status == DragCircle) {
p->hue = p->line_to_point(ev->pos()).angle() / 360.0;
p->render_inner_selector();
// 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);
}
p->mouse_status = Nothing;
emit mouseReleaseOnColor(color());
}
void
ColorWheel::mouseReleaseEvent(QMouseEvent* ev)
void ColorWheel::resizeEvent(QResizeEvent*)
{
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->display_flags = flags;
p->render_inner_selector();
update();
emit displayFlagsChanged(flags);
p->render_inner_selector();
}
ColorWheel::DisplayFlags
ColorWheel::displayFlags(DisplayFlags mask) const
void ColorWheel::setColor(QColor c)
{
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
ColorWheel::setDefaultDisplayFlags(DisplayFlags flags)
void ColorWheel::setHue(qreal h)
{
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;
p->hue = qBound(0.0, h, 1.0);
p->render_inner_selector();
update();
}
ColorWheel::DisplayFlags
ColorWheel::defaultDisplayFlags(DisplayFlags mask)
void ColorWheel::setSaturation(qreal s)
{
return default_flags & mask;
p->sat = qBound(0.0, s, 1.0);
update();
}
void
ColorWheel::setDisplayFlag(DisplayFlags flag, DisplayFlags mask)
void ColorWheel::setValue(qreal v)
{
setDisplayFlags((p->display_flags & ~mask) | flag);
p->val = qBound(0.0, v, 1.0);
update();
}
void
ColorWheel::dragEnterEvent(QDragEnterEvent* event)
void ColorWheel::setDisplayFlags(DisplayFlags flags)
{
if (event->mimeData()->hasColor() ||
(event->mimeData()->hasText() &&
QColor(event->mimeData()->text()).isValid()))
event->acceptProposedAction();
}
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;
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();
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->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

View File

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

View File

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

View File

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

View File

@@ -25,38 +25,32 @@ CommandArgument::CommandArgument(const QString& name,
, m_description(description)
{}
void
CommandArgument::setName(const QString& name)
void CommandArgument::setName(const QString& name)
{
m_name = name;
m_name = name;
}
QString
CommandArgument::name() const
QString CommandArgument::name() const
{
return m_name;
return m_name;
}
void
CommandArgument::setDescription(const QString& description)
void CommandArgument::setDescription(const QString& description)
{
m_description = description;
m_description = description;
}
QString
CommandArgument::description() const
QString CommandArgument::description() const
{
return m_description;
return m_description;
}
bool
CommandArgument::isRoot() const
bool CommandArgument::isRoot() const
{
return m_name.isEmpty() && m_description.isEmpty();
return m_name.isEmpty() && m_description.isEmpty();
}
bool
CommandArgument::operator==(const CommandArgument& arg) const
bool 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
{
public:
CommandArgument();
explicit CommandArgument(const QString& name, const QString& description);
CommandArgument();
explicit CommandArgument(const QString& name, const QString& description);
void setName(const QString& name);
QString name() const;
void setName(const QString& name);
QString name() const;
void setDescription(const QString& description);
QString description() const;
void setDescription(const QString& description);
QString description() const;
bool isRoot() const;
bool isRoot() const;
bool operator==(const CommandArgument& arg) const;
bool operator==(const CommandArgument& arg) const;
private:
QString m_name;
QString m_description;
QString m_name;
QString m_description;
};

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,21 +23,21 @@
class ButtonListView : public QListWidget
{
public:
explicit ButtonListView(QWidget* parent = nullptr);
explicit ButtonListView(QWidget* parent = nullptr);
public slots:
void selectAll();
void updateComponents();
void selectAll();
void updateComponents();
private slots:
void reverseItemCheck(QListWidgetItem*);
void reverseItemCheck(QListWidgetItem*);
protected:
void initButtonList();
void initButtonList();
private:
QVector<CaptureToolButton::ButtonType> m_listButtons;
QMap<QString, CaptureToolButton::ButtonType> m_buttonTypeByName;
QVector<CaptureToolButton::ButtonType> m_listButtons;
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)
: QLabel(parent)
{
setText(s);
setText(s);
}
void
ClickableLabel::mousePressEvent(QMouseEvent*)
void ClickableLabel::mousePressEvent(QMouseEvent*)
{
emit clicked();
emit clicked();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,72 +34,64 @@ CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode,
, m_id(0)
{}
void
CaptureRequest::setStaticID(uint id)
void CaptureRequest::setStaticID(uint id)
{
m_forcedID = true;
m_id = id;
m_forcedID = true;
m_id = id;
}
uint
CaptureRequest::id() const
uint CaptureRequest::id() const
{
if (m_forcedID) {
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_forcedID) {
return m_id;
}
}
if ((m_tasks & ExportTask::CLIPBOARD_SAVE_TASK) != ExportTask::NO_TASK) {
ScreenshotSaver().saveToClipboard(p);
}
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) {
ScreenshotSaver().saveToClipboard(p);
}
}

View File

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

View File

@@ -41,279 +41,268 @@
Controller::Controller()
: 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 (!ConfigHandler().disabledTrayIconValue()) {
enableTrayIcon();
}
if (!ConfigHandler().disabledTrayIconValue()) {
enableTrayIcon();
}
#elif defined(Q_OS_WIN)
enableTrayIcon();
enableTrayIcon();
GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this);
qApp->installNativeEventFilter(nativeFilter);
connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() {
this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
});
GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this);
qApp->installNativeEventFilter(nativeFilter);
connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() {
this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
});
#endif
QString StyleSheet = CaptureButton::globalStyleSheet();
qApp->setStyleSheet(StyleSheet);
QString StyleSheet = CaptureButton::globalStyleSheet();
qApp->setStyleSheet(StyleSheet);
}
Controller*
Controller::getInstance()
Controller* Controller::getInstance()
{
static Controller c;
return &c;
static Controller c;
return &c;
}
void
Controller::enableExports()
void Controller::enableExports()
{
connect(
this, &Controller::captureTaken, this, &Controller::handleCaptureTaken);
connect(
this, &Controller::captureFailed, this, &Controller::handleCaptureFailed);
connect(
this, &Controller::captureTaken, this, &Controller::handleCaptureTaken);
connect(
this, &Controller::captureFailed, this, &Controller::handleCaptureFailed);
}
void
Controller::requestCapture(const CaptureRequest& request)
void Controller::requestCapture(const CaptureRequest& request)
{
uint id = request.id();
m_requestMap.insert(id, request);
uint id = request.id();
m_requestMap.insert(id, request);
switch (request.captureMode()) {
case CaptureRequest::FULLSCREEN_MODE:
doLater(request.delay(), this, [this, id]() {
this->startFullscreenCapture(id);
});
break;
// TODO: Figure out the code path that gets here so the deprated warning can
// be fixed
case CaptureRequest::SCREEN_MODE: {
int&& number = request.data().toInt();
doLater(request.delay(), this, [this, id, number]() {
this->startScreenGrab(id, number);
});
break;
switch (request.captureMode()) {
case CaptureRequest::FULLSCREEN_MODE:
doLater(request.delay(), this, [this, id]() {
this->startFullscreenCapture(id);
});
break;
// TODO: Figure out the code path that gets here so the deprated warning
// can be fixed
case CaptureRequest::SCREEN_MODE: {
int&& number = request.data().toInt();
doLater(request.delay(), this, [this, id, number]() {
this->startScreenGrab(id, number);
});
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
void
Controller::startVisualCapture(const uint id, const QString& forcedSavePath)
void Controller::startVisualCapture(const uint id,
const QString& forcedSavePath)
{
if (!m_captureWindow) {
QWidget* modalWidget = nullptr;
do {
modalWidget = qApp->activeModalWidget();
if (modalWidget) {
modalWidget->close();
modalWidget->deleteLater();
}
} while (modalWidget);
if (!m_captureWindow) {
QWidget* modalWidget = nullptr;
do {
modalWidget = qApp->activeModalWidget();
if (modalWidget) {
modalWidget->close();
modalWidget->deleteLater();
}
} while (modalWidget);
m_captureWindow = new CaptureWidget(id, forcedSavePath);
// m_captureWindow = new CaptureWidget(id, forcedSavePath, false); // debug
connect(m_captureWindow,
&CaptureWidget::captureFailed,
this,
&Controller::captureFailed);
connect(m_captureWindow,
&CaptureWidget::captureTaken,
this,
&Controller::captureTaken);
m_captureWindow = new CaptureWidget(id, forcedSavePath);
// m_captureWindow = new CaptureWidget(id, forcedSavePath, false); //
// debug
connect(m_captureWindow,
&CaptureWidget::captureFailed,
this,
&Controller::captureFailed);
connect(m_captureWindow,
&CaptureWidget::captureTaken,
this,
&Controller::captureTaken);
#ifdef Q_OS_WIN
m_captureWindow->show();
m_captureWindow->show();
#else
m_captureWindow->showFullScreen();
// m_captureWindow->show(); // Debug
m_captureWindow->showFullScreen();
// m_captureWindow->show(); // Debug
#endif
} else {
emit captureFailed(id);
}
} else {
emit captureFailed(id);
}
}
void
Controller::startScreenGrab(const uint id, const int screenNumber)
void Controller::startScreenGrab(const uint id, const int screenNumber)
{
bool ok = true;
int n = screenNumber;
bool ok = true;
int n = screenNumber;
if (n < 0) {
QPoint globalCursorPos = QCursor::pos();
n = qApp->desktop()->screenNumber(globalCursorPos);
}
QPixmap p(ScreenGrabber().grabScreen(n, ok));
if (ok) {
emit captureTaken(id, p);
} else {
emit captureFailed(id);
}
if (n < 0) {
QPoint globalCursorPos = QCursor::pos();
n = qApp->desktop()->screenNumber(globalCursorPos);
}
QPixmap p(ScreenGrabber().grabScreen(n, ok));
if (ok) {
emit captureTaken(id, p);
} else {
emit captureFailed(id);
}
}
// creation of the configuration window
void
Controller::openConfigWindow()
void Controller::openConfigWindow()
{
if (!m_configWindow) {
m_configWindow = new ConfigWindow();
m_configWindow->show();
}
if (!m_configWindow) {
m_configWindow = new ConfigWindow();
m_configWindow->show();
}
}
// creation of the window of information
void
Controller::openInfoWindow()
void Controller::openInfoWindow()
{
if (!m_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();
if (!m_infoWindow) {
m_infoWindow = new InfoWindow();
}
};
connect(m_trayIcon, &QSystemTrayIcon::activated, this, trayIconActivated);
m_trayIcon->show();
}
void
Controller::disableTrayIcon()
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 Controller::disableTrayIcon()
{
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
if (m_trayIcon) {
m_trayIcon->deleteLater();
}
ConfigHandler().setDisabledTrayIcon(true);
if (m_trayIcon) {
m_trayIcon->deleteLater();
}
ConfigHandler().setDisabledTrayIcon(true);
#endif
}
void
Controller::sendTrayNotification(const QString& text,
const QString& title,
const int timeout)
void Controller::sendTrayNotification(const QString& text,
const QString& title,
const int timeout)
{
if (m_trayIcon) {
m_trayIcon->showMessage(title, text, QSystemTrayIcon::Information, timeout);
}
if (m_trayIcon) {
m_trayIcon->showMessage(
title, text, QSystemTrayIcon::Information, timeout);
}
}
void
Controller::updateConfigComponents()
void Controller::updateConfigComponents()
{
if (m_configWindow) {
m_configWindow->updateChildren();
}
if (m_configWindow) {
m_configWindow->updateChildren();
}
}
void
Controller::startFullscreenCapture(const uint id)
void Controller::startFullscreenCapture(const uint id)
{
bool ok = true;
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
if (ok) {
emit captureTaken(id, p);
} else {
emit captureFailed(id);
}
bool ok = true;
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
if (ok) {
emit captureTaken(id, p);
} else {
emit captureFailed(id);
}
}
void
Controller::handleCaptureTaken(uint id, QPixmap p)
void Controller::handleCaptureTaken(uint id, QPixmap p)
{
auto it = m_requestMap.find(id);
if (it != m_requestMap.end()) {
it.value().exportCapture(p);
m_requestMap.erase(it);
}
if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit();
}
auto it = m_requestMap.find(id);
if (it != m_requestMap.end()) {
it.value().exportCapture(p);
m_requestMap.erase(it);
}
if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit();
}
}
void
Controller::handleCaptureFailed(uint id)
void Controller::handleCaptureFailed(uint id)
{
m_requestMap.remove(id);
m_requestMap.remove(id);
if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit();
}
if (ConfigHandler().closeAfterScreenshotValue()) {
QApplication::quit();
}
}
void
Controller::doLater(int msec, QObject* receiver, lambda func)
void Controller::doLater(int msec, QObject* receiver, lambda func)
{
QTimer* timer = new QTimer(receiver);
QObject::connect(timer, &QTimer::timeout, receiver, [timer, func]() {
func();
timer->deleteLater();
});
timer->setInterval(msec);
timer->start();
QTimer* timer = new QTimer(receiver);
QObject::connect(timer, &QTimer::timeout, receiver, [timer, func]() {
func();
timer->deleteLater();
});
timer->setInterval(msec);
timer->start();
}

View File

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

View File

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

View File

@@ -22,30 +22,33 @@
class FlameshotDBusAdapter : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.flameshot.Flameshot")
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.flameshot.Flameshot")
public:
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
virtual ~FlameshotDBusAdapter();
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
virtual ~FlameshotDBusAdapter();
signals:
void captureTaken(uint id, QByteArray rawImage);
void captureFailed(uint id);
void captureTaken(uint id, QByteArray rawImage);
void captureFailed(uint id);
public slots:
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 captureScreen(int number,
QString path,
bool toClipboard,
int delay,
uint id);
Q_NOREPLY void openLauncher();
Q_NOREPLY void openConfig();
Q_NOREPLY void trayIconEnabled(bool enabled);
Q_NOREPLY void autostartEnabled(bool enabled);
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 captureScreen(int number,
QString path,
bool toClipboard,
int delay,
uint id);
Q_NOREPLY void openLauncher();
Q_NOREPLY void openConfig();
Q_NOREPLY void trayIconEnabled(bool enabled);
Q_NOREPLY void autostartEnabled(bool enabled);
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)
: QObject(parent)
{
// Forced Print Screen
if (RegisterHotKey(NULL, 1, 0, VK_SNAPSHOT)) {
// ok
}
// Forced Print Screen
if (RegisterHotKey(NULL, 1, 0, VK_SNAPSHOT)) {
// ok
}
}
bool
GlobalShortcutFilter::nativeEventFilter(const QByteArray& eventType,
void* message,
long* result)
bool GlobalShortcutFilter::nativeEventFilter(const QByteArray& eventType,
void* message,
long* result)
{
Q_UNUSED(eventType);
Q_UNUSED(result);
Q_UNUSED(eventType);
Q_UNUSED(result);
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY) {
// const quint32 keycode = HIWORD(msg->lParam);
// const quint32 modifiers = LOWORD(msg->lParam);
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY) {
// const quint32 keycode = HIWORD(msg->lParam);
// const quint32 modifiers = LOWORD(msg->lParam);
// TODO: this is just a temporal workwrround, proper global
// support would need custom shortcuts defined by the user.
Controller::getInstance()->requestCapture(
CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
return true;
}
return false;
// TODO: this is just a temporal workwrround, proper global
// support would need custom shortcuts defined by the user.
Controller::getInstance()->requestCapture(
CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
return true;
}
return false;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,10 +25,10 @@ const int DIRS_NUMBER = 4;
enum UNIT
{
HORIZ_DIR = 0,
DIAG1_DIR = 1,
VERT_DIR = 2,
DIAG2_DIR = 3
HORIZ_DIR = 0,
DIAG1_DIR = 1,
VERT_DIR = 2,
DIAG2_DIR = 3
};
const double ADJ_DIAG_UNIT = 2 * ADJ_UNIT;
@@ -36,8 +36,8 @@ const int DIAG_DIRS_NUMBER = 2;
enum DIAG_UNIT
{
DIR1 = 0,
DIR2 = 1
DIR1 = 0,
DIR2 = 1
};
}
@@ -48,123 +48,111 @@ AbstractTwoPointTool::AbstractTwoPointTool(QObject* parent)
, m_padding(0)
{}
bool
AbstractTwoPointTool::isValid() const
bool AbstractTwoPointTool::isValid() const
{
return (m_points.first != m_points.second);
return (m_points.first != m_points.second);
}
bool
AbstractTwoPointTool::closeOnButtonPressed() const
bool AbstractTwoPointTool::closeOnButtonPressed() const
{
return false;
return false;
}
bool
AbstractTwoPointTool::isSelectable() const
bool AbstractTwoPointTool::isSelectable() const
{
return true;
return true;
}
bool
AbstractTwoPointTool::showMousePreview() const
bool AbstractTwoPointTool::showMousePreview() const
{
return true;
return true;
}
void
AbstractTwoPointTool::undo(QPixmap& pixmap)
void AbstractTwoPointTool::undo(QPixmap& pixmap)
{
QPainter p(&pixmap);
p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup);
if (this->nameID() == ToolType::CIRCLECOUNT) {
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);
QPainter p(&pixmap);
p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup);
if (this->nameID() == ToolType::CIRCLECOUNT) {
emit requestAction(REQ_DECREMENT_CIRCLE_COUNT);
}
} 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;
}
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)) +
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
{
Q_OBJECT
Q_OBJECT
public:
explicit AbstractTwoPointTool(QObject* parent = nullptr);
explicit AbstractTwoPointTool(QObject* parent = nullptr);
bool isValid() const override;
bool closeOnButtonPressed() const override;
bool isSelectable() const override;
bool showMousePreview() const override;
bool isValid() const override;
bool closeOnButtonPressed() const override;
bool isSelectable() const override;
bool showMousePreview() const override;
void undo(QPixmap& pixmap) override;
void undo(QPixmap& pixmap) override;
public slots:
void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override;
void drawMoveWithAdjustment(const QPoint& p) override;
void colorChanged(const QColor& c) override;
void thicknessChanged(const int th) override;
void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override;
void drawMoveWithAdjustment(const QPoint& p) override;
void colorChanged(const QColor& c) override;
void thicknessChanged(const int th) override;
protected:
void updateBackup(const QPixmap& pixmap);
QRect backupRect(const QRect& limits) const;
void updateBackup(const QPixmap& pixmap);
QRect backupRect(const QRect& limits) const;
QPixmap m_pixmapBackup;
QPair<QPoint, QPoint> m_points;
QColor m_color;
int m_thickness;
// use m_padding to extend the area of the backup
int m_padding;
QPixmap m_pixmapBackup;
QPair<QPoint, QPoint> m_points;
QColor m_color;
int m_thickness;
// use m_padding to extend the area of the backup
int m_padding;
bool m_supportsOrthogonalAdj = false;
bool m_supportsDiagonalAdj = false;
bool m_supportsOrthogonalAdj = false;
bool m_supportsDiagonalAdj = false;
virtual ToolType nameID() const = 0;
virtual ToolType nameID() const = 0;
private:
QPoint adjustedVector(QPoint v) const;
QPoint adjustedVector(QPoint v) const;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,120 +24,111 @@ namespace {
CircleCountTool::CircleCountTool(QObject* parent)
: AbstractTwoPointTool(parent)
{
m_count = 0;
m_count = 0;
}
QIcon
CircleCountTool::icon(const QColor& background, bool inEditor) const
QIcon CircleCountTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "circlecount-outline.svg");
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "circlecount-outline.svg");
}
QString
CircleCountTool::name() const
QString CircleCountTool::name() const
{
return tr("Circle Counter");
return tr("Circle Counter");
}
ToolType
CircleCountTool::nameID() const
ToolType CircleCountTool::nameID() const
{
return ToolType::CIRCLECOUNT;
return ToolType::CIRCLECOUNT;
}
QString
CircleCountTool::description() const
QString CircleCountTool::description() const
{
return tr("Add an autoincrementing counter bubble");
return tr("Add an autoincrementing counter bubble");
}
CaptureTool*
CircleCountTool::copy(QObject* parent)
CaptureTool* CircleCountTool::copy(QObject* parent)
{
return new CircleCountTool(parent);
return new CircleCountTool(parent);
}
void
CircleCountTool::process(QPainter& painter,
const QPixmap& pixmap,
bool recordUndo)
void CircleCountTool::process(QPainter& painter,
const QPixmap& pixmap,
bool recordUndo)
{
if (recordUndo) {
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;
if (recordUndo) {
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);
bRect =
QRect bRect =
painter.boundingRect(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);
}
while (bRect.width() > textRect.width()) {
fontSize--;
if (fontSize == 0) {
break;
}
new_font.setPixelSize(fontSize);
painter.setFont(new_font);
painter.drawText(textRect, Qt::AlignCenter, QString::number(m_count));
painter.setFont(orig_font);
bRect = painter.boundingRect(
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
CircleCountTool::paintMousePreview(QPainter& painter,
const CaptureContext& context)
void CircleCountTool::paintMousePreview(QPainter& painter,
const CaptureContext& context)
{
m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) {
m_thickness = 15;
}
m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) {
m_thickness = 15;
}
// Thickness for pen is *2 to range from radius to diameter to match the
// ellipse draw function
painter.setPen(
QPen(context.color, m_thickness * 2, Qt::SolidLine, Qt::RoundCap));
painter.drawLine(context.mousePos,
{ context.mousePos.x() + 1, context.mousePos.y() + 1 });
// Thickness for pen is *2 to range from radius to diameter to match the
// ellipse draw function
painter.setPen(
QPen(context.color, m_thickness * 2, Qt::SolidLine, Qt::RoundCap));
painter.drawLine(context.mousePos,
{ context.mousePos.x() + 1, context.mousePos.y() + 1 });
}
void
CircleCountTool::drawStart(const CaptureContext& context)
void CircleCountTool::drawStart(const CaptureContext& context)
{
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) {
m_thickness = 15;
}
m_points.first = context.mousePos;
m_count = context.circleCount;
emit requestAction(REQ_INCREMENT_CIRCLE_COUNT);
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;
if (m_thickness < 15) {
m_thickness = 15;
}
m_points.first = context.mousePos;
m_count = context.circleCount;
emit requestAction(REQ_INCREMENT_CIRCLE_COUNT);
}
void
CircleCountTool::pressed(const CaptureContext& context)
void CircleCountTool::pressed(const CaptureContext& context)
{
Q_UNUSED(context);
Q_UNUSED(context);
}

View File

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

View File

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

View File

@@ -21,21 +21,21 @@
class CopyTool : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override;
QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override;
CaptureTool* copy(QObject* parent = nullptr) override;
protected:
ToolType nameID() const override;
ToolType nameID() const override;
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)
{}
bool
ExitTool::closeOnButtonPressed() const
bool ExitTool::closeOnButtonPressed() const
{
return true;
return true;
}
QIcon
ExitTool::icon(const QColor& background, bool inEditor) const
QIcon ExitTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "close.svg");
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "close.svg");
}
QString
ExitTool::name() const
QString ExitTool::name() const
{
return tr("Exit");
return tr("Exit");
}
ToolType
ExitTool::nameID() const
ToolType ExitTool::nameID() const
{
return ToolType::EXIT;
return ToolType::EXIT;
}
QString
ExitTool::description() const
QString ExitTool::description() const
{
return tr("Leave the capture screen");
return tr("Leave the capture screen");
}
CaptureTool*
ExitTool::copy(QObject* parent)
CaptureTool* ExitTool::copy(QObject* parent)
{
return new ExitTool(parent);
return new ExitTool(parent);
}
void
ExitTool::pressed(const CaptureContext& context)
void ExitTool::pressed(const CaptureContext& context)
{
Q_UNUSED(context);
emit requestAction(REQ_CLOSE_GUI);
Q_UNUSED(context);
emit requestAction(REQ_CLOSE_GUI);
}

View File

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

View File

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

View File

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

View File

@@ -21,26 +21,26 @@
class ImgurUploaderTool : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() 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:
ToolType nameID() const override;
ToolType nameID() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
private:
QPixmap capture;
QPixmap capture;
};

View File

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

View File

@@ -21,26 +21,26 @@
class AppLauncher : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() 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:
ToolType nameID() const override;
ToolType nameID() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
private:
QPixmap capture;
QPixmap capture;
};

View File

@@ -51,218 +51,213 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
: QWidget(parent)
, m_pixmap(p)
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(QIcon(":img/app/flameshot.svg"));
setWindowTitle(tr("Open With"));
setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(QIcon(":img/app/flameshot.svg"));
setWindowTitle(tr("Open With"));
m_keepOpen = ConfigHandler().keepOpenAppLauncherValue();
m_keepOpen = ConfigHandler().keepOpenAppLauncherValue();
QString dirLocal = QDir::homePath() + "/.local/share/applications/";
QDir appsDirLocal(dirLocal);
m_parser.processDirectory(appsDirLocal);
QString dirLocal = QDir::homePath() + "/.local/share/applications/";
QDir appsDirLocal(dirLocal);
m_parser.processDirectory(appsDirLocal);
QString dir = QStringLiteral("/usr/share/applications/");
QDir appsDir(dir);
m_parser.processDirectory(appsDir);
QString dir = QStringLiteral("/usr/share/applications/");
QDir appsDir(dir);
m_parser.processDirectory(appsDir);
initAppMap();
initListWidget();
initAppMap();
initListWidget();
m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this);
m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this);
m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue());
connect(m_keepOpenCheckbox,
&QCheckBox::clicked,
this,
&AppLauncherWidget::checkboxClicked);
m_terminalCheckbox = new QCheckBox(tr("Launch in terminal"), this);
m_keepOpenCheckbox = new QCheckBox(tr("Keep open after selection"), this);
m_keepOpenCheckbox->setChecked(ConfigHandler().keepOpenAppLauncherValue());
connect(m_keepOpenCheckbox,
&QCheckBox::clicked,
this,
&AppLauncherWidget::checkboxClicked);
// search items
m_lineEdit = new QLineEdit;
connect(m_lineEdit,
&QLineEdit::textChanged,
this,
&AppLauncherWidget::searchChanged);
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()) {
// search items
m_lineEdit = new QLineEdit;
connect(m_lineEdit,
&QLineEdit::textChanged,
this,
&AppLauncherWidget::searchChanged);
m_filterList = new QListWidget;
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;
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_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()) {
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);
const QString& cat = i.first;
const QString& iconName = i.second;
if (!m_appsMap.contains(cat)) {
continue;
}
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);
}
}
}
addAppsToListWidget(m_filterList, apps);
}
}
void
AppLauncherWidget::initListWidget()
void AppLauncherWidget::initAppMap()
{
m_tabWidget = new QTabWidget;
const int size = GlobalValues::buttonBaseSize();
m_tabWidget->setIconSize(QSize(size, size));
QStringList categories({ "AudioVideo",
"Audio",
"Video",
"Development",
"Graphics",
"Network",
"Office",
"Science",
"Settings",
"System",
"Utility" });
for (auto const& i : catIconNames.toStdMap()) {
const QString& cat = i.first;
const QString& iconName = i.second;
m_appsMap = m_parser.getAppsByCategory(categories);
if (!m_appsMap.contains(cat)) {
continue;
// 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);
}
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);
}
}
m_appsMap.insert(QStringLiteral("Multimedia"), multimediaList);
}
void
AppLauncherWidget::initAppMap()
void AppLauncherWidget::configureListView(QListWidget* widget)
{
QStringList categories({ "AudioVideo",
"Audio",
"Video",
"Development",
"Graphics",
"Network",
"Office",
"Science",
"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);
widget->setItemDelegate(new LauncherItemDelegate());
widget->setViewMode(QListWidget::IconMode);
widget->setResizeMode(QListView::Adjust);
widget->setSpacing(4);
widget->setFlow(QListView::LeftToRight);
widget->setDragEnabled(false);
widget->setMinimumWidth(GlobalValues::buttonBaseSize() * 11);
connect(widget, &QListWidget::clicked, this, &AppLauncherWidget::launch);
}
void
AppLauncherWidget::configureListView(QListWidget* widget)
void AppLauncherWidget::addAppsToListWidget(
QListWidget* widget,
const QVector<DesktopAppData>& appList)
{
widget->setItemDelegate(new LauncherItemDelegate());
widget->setViewMode(QListWidget::IconMode);
widget->setResizeMode(QListView::Adjust);
widget->setSpacing(4);
widget->setFlow(QListView::LeftToRight);
widget->setDragEnabled(false);
widget->setMinimumWidth(GlobalValues::buttonBaseSize() * 11);
connect(widget, &QListWidget::clicked, this, &AppLauncherWidget::launch);
}
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);
void
AppLauncherWidget::addAppsToListWidget(QListWidget* widget,
const QVector<DesktopAppData>& appList)
{
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);
}
buttonItem->setIcon(app.icon);
buttonItem->setText(app.name);
buttonItem->setToolTip(app.description);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,19 +21,19 @@
class MoveTool : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
ToolType nameID() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override;
ToolType nameID() const override;
QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override;
CaptureTool* copy(QObject* parent = nullptr) override;
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)
{}
QIcon
PencilTool::icon(const QColor& background, bool inEditor) const
QIcon PencilTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "pencil.svg");
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "pencil.svg");
}
QString
PencilTool::name() const
QString PencilTool::name() const
{
return tr("Pencil");
return tr("Pencil");
}
ToolType
PencilTool::nameID() const
ToolType PencilTool::nameID() const
{
return ToolType::PENCIL;
return ToolType::PENCIL;
}
QString
PencilTool::description() const
QString PencilTool::description() const
{
return tr("Set the Pencil as the paint tool");
return tr("Set the Pencil as the paint tool");
}
CaptureTool*
PencilTool::copy(QObject* parent)
CaptureTool* PencilTool::copy(QObject* parent)
{
return new PencilTool(parent);
return new PencilTool(parent);
}
void
PencilTool::process(QPainter& painter, const QPixmap& pixmap, bool recordUndo)
void PencilTool::process(QPainter& painter,
const QPixmap& pixmap,
bool recordUndo)
{
if (recordUndo) {
updateBackup(pixmap);
}
painter.setPen(QPen(m_color, m_thickness));
painter.drawPolyline(m_points.data(), m_points.size());
if (recordUndo) {
updateBackup(pixmap);
}
painter.setPen(QPen(m_color, m_thickness));
painter.drawPolyline(m_points.data(), m_points.size());
}
void
PencilTool::paintMousePreview(QPainter& painter, const CaptureContext& context)
void PencilTool::paintMousePreview(QPainter& painter,
const CaptureContext& context)
{
painter.setPen(QPen(context.color, context.thickness + 2));
painter.drawLine(context.mousePos, context.mousePos);
painter.setPen(QPen(context.color, context.thickness + 2));
painter.drawLine(context.mousePos, context.mousePos);
}
void
PencilTool::drawStart(const CaptureContext& context)
void PencilTool::drawStart(const CaptureContext& context)
{
m_color = context.color;
m_thickness = context.thickness + 2;
m_points.append(context.mousePos);
m_backupArea.setTopLeft(context.mousePos);
m_backupArea.setBottomRight(context.mousePos);
m_color = context.color;
m_thickness = context.thickness + 2;
m_points.append(context.mousePos);
m_backupArea.setTopLeft(context.mousePos);
m_backupArea.setBottomRight(context.mousePos);
}
void
PencilTool::pressed(const CaptureContext& context)
void PencilTool::pressed(const CaptureContext& context)
{
Q_UNUSED(context);
Q_UNUSED(context);
}

View File

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

View File

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

View File

@@ -21,27 +21,27 @@
class PinTool : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() 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:
ToolType nameID() const override;
ToolType nameID() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
private:
QRect m_geometry;
QPixmap m_pixmap;
QRect m_geometry;
QPixmap m_pixmap;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,21 +21,21 @@
class RedoTool : public AbstractActionTool
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override;
QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override;
CaptureTool* copy(QObject* parent = nullptr) override;
protected:
ToolType nameID() const override;
ToolType nameID() const override;
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)
{}
bool
SaveTool::closeOnButtonPressed() const
bool SaveTool::closeOnButtonPressed() const
{
return true;
return true;
}
QIcon
SaveTool::icon(const QColor& background, bool inEditor) const
QIcon SaveTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "content-save.svg");
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "content-save.svg");
}
QString
SaveTool::name() const
QString SaveTool::name() const
{
return tr("Save");
return tr("Save");
}
ToolType
SaveTool::nameID() const
ToolType SaveTool::nameID() const
{
return ToolType::SAVE;
return ToolType::SAVE;
}
QString
SaveTool::description() const
QString SaveTool::description() const
{
return tr("Save the capture");
return tr("Save the capture");
}
CaptureTool*
SaveTool::copy(QObject* parent)
CaptureTool* SaveTool::copy(QObject* parent)
{
return new SaveTool(parent);
return new SaveTool(parent);
}
void
SaveTool::pressed(const CaptureContext& context)
void SaveTool::pressed(const CaptureContext& context)
{
if (context.savePath.isEmpty()) {
emit requestAction(REQ_HIDE_GUI);
bool ok =
ScreenshotSaver().saveToFilesystemGUI(context.selectedScreenshotArea());
if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK);
if (context.savePath.isEmpty()) {
emit requestAction(REQ_HIDE_GUI);
bool ok = ScreenshotSaver().saveToFilesystemGUI(
context.selectedScreenshotArea());
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);
}
}
} 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
{
Q_OBJECT
Q_OBJECT
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;
QString name() const override;
QString description() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override;
QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override;
CaptureTool* copy(QObject* parent = nullptr) override;
protected:
ToolType nameID() const override;
ToolType nameID() const override;
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)
: AbstractTwoPointTool(parent)
{
m_supportsDiagonalAdj = true;
m_supportsDiagonalAdj = true;
}
bool
SelectionTool::closeOnButtonPressed() const
bool SelectionTool::closeOnButtonPressed() const
{
return false;
return false;
}
QIcon
SelectionTool::icon(const QColor& background, bool inEditor) const
QIcon SelectionTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "square-outline.svg");
Q_UNUSED(inEditor);
return QIcon(iconPath(background) + "square-outline.svg");
}
QString
SelectionTool::name() const
QString SelectionTool::name() const
{
return tr("Rectangular Selection");
return tr("Rectangular Selection");
}
ToolType
SelectionTool::nameID() const
ToolType SelectionTool::nameID() const
{
return ToolType::SELECTION;
return ToolType::SELECTION;
}
QString
SelectionTool::description() const
QString SelectionTool::description() const
{
return tr("Set Selection as the paint tool");
return tr("Set Selection as the paint tool");
}
CaptureTool*
SelectionTool::copy(QObject* parent)
CaptureTool* SelectionTool::copy(QObject* parent)
{
return new SelectionTool(parent);
return new SelectionTool(parent);
}
void
SelectionTool::process(QPainter& painter,
const QPixmap& pixmap,
bool recordUndo)
void SelectionTool::process(QPainter& painter,
const QPixmap& pixmap,
bool recordUndo)
{
if (recordUndo) {
updateBackup(pixmap);
}
painter.setPen(QPen(m_color, m_thickness));
painter.drawRect(QRect(m_points.first, m_points.second));
if (recordUndo) {
updateBackup(pixmap);
}
painter.setPen(QPen(m_color, m_thickness));
painter.drawRect(QRect(m_points.first, m_points.second));
}
void
SelectionTool::paintMousePreview(QPainter& painter,
const CaptureContext& context)
void SelectionTool::paintMousePreview(QPainter& painter,
const CaptureContext& context)
{
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos);
painter.setPen(QPen(context.color, PADDING_VALUE + context.thickness));
painter.drawLine(context.mousePos, context.mousePos);
}
void
SelectionTool::drawStart(const CaptureContext& context)
void SelectionTool::drawStart(const CaptureContext& context)
{
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos;
m_points.second = context.mousePos;
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;
m_points.first = context.mousePos;
m_points.second = context.mousePos;
}
void
SelectionTool::pressed(const CaptureContext& context)
void SelectionTool::pressed(const CaptureContext& context)
{
Q_UNUSED(context);
Q_UNUSED(context);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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