File indexing completed on 2025-02-02 04:26:09

0001 /* SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>
0002  * SPDX-FileCopyrightText: 2022 Noah Davis <noahadvs@gmail.com>
0003  * SPDX-License-Identifier: LGPL-2.0-or-later
0004  */
0005 
0006 #include "AnnotationTool.h"
0007 #include "settings.h"
0008 
0009 using enum AnnotationTool::Tool;
0010 using enum AnnotationTool::Option;
0011 
0012 // clang-format off
0013 
0014 // Default value macros
0015 
0016 #define DEFAULT_STROKE_WIDTH(ToolName) case ToolName##Tool: { return Settings::default##ToolName##StrokeWidthValue(); }
0017 
0018 #define DEFAULT_STROKE_COLOR(ToolName) case ToolName##Tool: { return Settings::default##ToolName##StrokeColorValue(); }
0019 
0020 #define DEFAULT_FILL_COLOR(ToolName) case ToolName##Tool: { return Settings::default##ToolName##FillColorValue(); }
0021 
0022 #define DEFAULT_FONT(ToolName) case ToolName##Tool: { return Settings::default##ToolName##FontValue(); }
0023 
0024 #define DEFAULT_FONT_COLOR(ToolName) case ToolName##Tool: { return Settings::default##ToolName##FontColorValue(); }
0025 
0026 #define DEFAULT_SHADOW(ToolName) case ToolName##Tool: { return Settings::default##ToolName##ShadowValue(); }
0027 
0028 // No getter macros because there's no way to lowercase the ToolName arg
0029 
0030 // Setter macros
0031 
0032 #define SET_STROKE_WIDTH(ToolName) case ToolName##Tool: { Settings::set##ToolName##StrokeWidth(width); } break;
0033 
0034 #define SET_STROKE_COLOR(ToolName) case ToolName##Tool: { Settings::set##ToolName##StrokeColor(color); } break;
0035 
0036 #define SET_FILL_COLOR(ToolName) case ToolName##Tool: { Settings::set##ToolName##FillColor(color); } break;
0037 
0038 #define SET_FONT(ToolName) case ToolName##Tool: { Settings::set##ToolName##Font(font); } break;
0039 
0040 #define SET_FONT_COLOR(ToolName) case ToolName##Tool: { Settings::set##ToolName##FontColor(color); } break;
0041 
0042 #define SET_SHADOW(ToolName) case ToolName##Tool: { Settings::set##ToolName##Shadow(shadow); } break;
0043 
0044 // clang-format on
0045 
0046 AnnotationTool::AnnotationTool(QObject *parent)
0047     : QObject(parent)
0048 {
0049 }
0050 
0051 AnnotationTool::~AnnotationTool()
0052 {
0053 }
0054 
0055 AnnotationTool::Tool AnnotationTool::type() const
0056 {
0057     return m_type;
0058 }
0059 
0060 void AnnotationTool::setType(AnnotationTool::Tool type)
0061 {
0062     if (m_type == type) {
0063         return;
0064     }
0065 
0066     auto oldType = m_type;
0067     m_type = type;
0068     Q_EMIT typeChanged();
0069 
0070     auto newOptions = optionsForType(type);
0071     if (m_options != newOptions) {
0072         m_options = newOptions;
0073         Q_EMIT optionsChanged();
0074     }
0075 
0076     const auto &oldStrokeWidth = strokeWidthForType(oldType);
0077     const auto &newStrokeWidth = strokeWidthForType(type);
0078     if (oldStrokeWidth != newStrokeWidth) {
0079         Q_EMIT strokeWidthChanged(newStrokeWidth);
0080     }
0081 
0082     const auto &oldStrokeColor = strokeColorForType(oldType);
0083     const auto &newStrokeColor = strokeColorForType(type);
0084     if (oldStrokeColor != newStrokeColor) {
0085         Q_EMIT strokeColorChanged(newStrokeColor);
0086     }
0087 
0088     const auto &oldFillColor = fillColorForType(oldType);
0089     const auto &newFillColor = fillColorForType(type);
0090     if (oldFillColor != newFillColor) {
0091         Q_EMIT fillColorChanged(newFillColor);
0092     }
0093 
0094     const auto &oldFont = fontForType(oldType);
0095     const auto &newFont = fontForType(type);
0096     if (oldFont != newFont) {
0097         Q_EMIT fontChanged(newFont);
0098     }
0099 
0100     const auto &oldFontColor = fontColorForType(oldType);
0101     const auto &newFontColor = fontColorForType(type);
0102     if (oldFontColor != newFontColor) {
0103         Q_EMIT fontColorChanged(newFontColor);
0104     }
0105 
0106     const auto &oldShadow = typeHasShadow(oldType);
0107     const auto &newShadow = typeHasShadow(type);
0108     if (oldShadow != newShadow) {
0109         Q_EMIT shadowChanged(newShadow);
0110     }
0111 }
0112 
0113 void AnnotationTool::resetType()
0114 {
0115     setType(AnnotationTool::NoTool);
0116 }
0117 
0118 bool AnnotationTool::isCreationTool() const
0119 {
0120     return m_type != NoTool && m_type != SelectTool;
0121 }
0122 
0123 AnnotationTool::Options AnnotationTool::options() const
0124 {
0125     return m_options;
0126 }
0127 
0128 constexpr AnnotationTool::Options AnnotationTool::optionsForType(AnnotationTool::Tool type)
0129 {
0130     switch (type) {
0131     case HighlighterTool:
0132         return StrokeOption;
0133     case FreehandTool:
0134     case LineTool:
0135     case ArrowTool:
0136         return {StrokeOption, ShadowOption};
0137     case RectangleTool:
0138     case EllipseTool:
0139         return {StrokeOption, ShadowOption, FillOption};
0140     case TextTool:
0141         return {FontOption, TextOption, ShadowOption};
0142     case NumberTool:
0143         return {FillOption, ShadowOption, FontOption, NumberOption};
0144     default:
0145         return NoOptions;
0146     }
0147 }
0148 
0149 int AnnotationTool::strokeWidth() const
0150 {
0151     return strokeWidthForType(m_type);
0152 }
0153 
0154 constexpr int AnnotationTool::defaultStrokeWidthForType(AnnotationTool::Tool type)
0155 {
0156     switch (type) {
0157         DEFAULT_STROKE_WIDTH(Freehand)
0158         DEFAULT_STROKE_WIDTH(Highlighter)
0159         DEFAULT_STROKE_WIDTH(Line)
0160         DEFAULT_STROKE_WIDTH(Arrow)
0161         DEFAULT_STROKE_WIDTH(Rectangle)
0162         DEFAULT_STROKE_WIDTH(Ellipse)
0163     default:
0164         return 0;
0165     }
0166 }
0167 
0168 int AnnotationTool::strokeWidthForType(AnnotationTool::Tool type) const
0169 {
0170     switch (type) {
0171     case FreehandTool:
0172         return Settings::freehandStrokeWidth();
0173     case HighlighterTool:
0174         return Settings::highlighterStrokeWidth();
0175     case LineTool:
0176         return Settings::lineStrokeWidth();
0177     case ArrowTool:
0178         return Settings::arrowStrokeWidth();
0179     case RectangleTool:
0180         return Settings::rectangleStrokeWidth();
0181     case EllipseTool:
0182         return Settings::ellipseStrokeWidth();
0183     default:
0184         return 0;
0185     }
0186 }
0187 
0188 void AnnotationTool::setStrokeWidth(int width)
0189 {
0190     if (!m_options.testFlag(Option::StrokeOption) || strokeWidth() == width) {
0191         return;
0192     }
0193 
0194     setStrokeWidthForType(width, m_type);
0195     Q_EMIT strokeWidthChanged(width);
0196 }
0197 
0198 void AnnotationTool::setStrokeWidthForType(int width, AnnotationTool::Tool type)
0199 {
0200     switch (type) {
0201         SET_STROKE_WIDTH(Freehand)
0202         SET_STROKE_WIDTH(Highlighter)
0203         SET_STROKE_WIDTH(Line)
0204         SET_STROKE_WIDTH(Arrow)
0205         SET_STROKE_WIDTH(Rectangle)
0206         SET_STROKE_WIDTH(Ellipse)
0207     default:
0208         break;
0209     }
0210 }
0211 
0212 void AnnotationTool::resetStrokeWidth()
0213 {
0214     setStrokeWidth(defaultStrokeWidthForType(m_type));
0215 }
0216 
0217 QColor AnnotationTool::strokeColor() const
0218 {
0219     return strokeColorForType(m_type);
0220 }
0221 
0222 constexpr QColor AnnotationTool::defaultStrokeColorForType(AnnotationTool::Tool type)
0223 {
0224     switch (type) {
0225         DEFAULT_STROKE_COLOR(Freehand)
0226         DEFAULT_STROKE_COLOR(Highlighter)
0227         DEFAULT_STROKE_COLOR(Line)
0228         DEFAULT_STROKE_COLOR(Arrow)
0229         DEFAULT_STROKE_COLOR(Rectangle)
0230         DEFAULT_STROKE_COLOR(Ellipse)
0231     default:
0232         return Qt::transparent;
0233     }
0234 }
0235 
0236 QColor AnnotationTool::strokeColorForType(AnnotationTool::Tool type) const
0237 {
0238     switch (type) {
0239     case FreehandTool:
0240         return Settings::freehandStrokeColor();
0241     case HighlighterTool:
0242         return Settings::highlighterStrokeColor();
0243     case LineTool:
0244         return Settings::lineStrokeColor();
0245     case ArrowTool:
0246         return Settings::arrowStrokeColor();
0247     case RectangleTool:
0248         return Settings::rectangleStrokeColor();
0249     case EllipseTool:
0250         return Settings::ellipseStrokeColor();
0251     default:
0252         return Qt::transparent;
0253     }
0254 }
0255 
0256 void AnnotationTool::setStrokeColor(const QColor &color)
0257 {
0258     if (!m_options.testFlag(Option::StrokeOption) || strokeColor() == color) {
0259         return;
0260     }
0261 
0262     setStrokeColorForType(color, m_type);
0263     Q_EMIT strokeColorChanged(color);
0264 }
0265 
0266 void AnnotationTool::setStrokeColorForType(const QColor &color, AnnotationTool::Tool type)
0267 {
0268     switch (type) {
0269         SET_STROKE_COLOR(Freehand)
0270         SET_STROKE_COLOR(Highlighter)
0271         SET_STROKE_COLOR(Line)
0272         SET_STROKE_COLOR(Arrow)
0273         SET_STROKE_COLOR(Rectangle)
0274         SET_STROKE_COLOR(Ellipse)
0275     default:
0276         break;
0277     }
0278 }
0279 
0280 void AnnotationTool::resetStrokeColor()
0281 {
0282     setStrokeColor(defaultStrokeColorForType(m_type));
0283 }
0284 
0285 QColor AnnotationTool::fillColor() const
0286 {
0287     return fillColorForType(m_type);
0288 }
0289 
0290 constexpr QColor AnnotationTool::defaultFillColorForType(AnnotationTool::Tool type)
0291 {
0292     switch (type) {
0293         DEFAULT_FILL_COLOR(Rectangle)
0294         DEFAULT_FILL_COLOR(Ellipse)
0295         DEFAULT_FILL_COLOR(Number)
0296     default:
0297         return Qt::transparent;
0298     }
0299 }
0300 
0301 QColor AnnotationTool::fillColorForType(AnnotationTool::Tool type) const
0302 {
0303     switch (type) {
0304     case RectangleTool:
0305         return Settings::rectangleFillColor();
0306     case EllipseTool:
0307         return Settings::ellipseFillColor();
0308     case NumberTool:
0309         return Settings::numberFillColor();
0310     default:
0311         return Qt::transparent;
0312     }
0313 }
0314 
0315 void AnnotationTool::setFillColor(const QColor &color)
0316 {
0317     if (!m_options.testFlag(Option::FillOption) || fillColor() == color) {
0318         return;
0319     }
0320 
0321     setFillColorForType(color, m_type);
0322     Q_EMIT fillColorChanged(color);
0323 }
0324 
0325 void AnnotationTool::setFillColorForType(const QColor &color, AnnotationTool::Tool type)
0326 {
0327     switch (type) {
0328         SET_FILL_COLOR(Rectangle)
0329         SET_FILL_COLOR(Ellipse)
0330         SET_FILL_COLOR(Number)
0331     default:
0332         break;
0333     }
0334 }
0335 
0336 void AnnotationTool::resetFillColor()
0337 {
0338     setFillColor(defaultFillColorForType(m_type));
0339 }
0340 
0341 QFont AnnotationTool::font() const
0342 {
0343     return fontForType(m_type);
0344 }
0345 
0346 QFont AnnotationTool::fontForType(AnnotationTool::Tool type) const
0347 {
0348     switch (type) {
0349     case TextTool:
0350         return Settings::textFont();
0351     case NumberTool:
0352         return Settings::numberFont();
0353     default:
0354         return {};
0355     }
0356 }
0357 
0358 void AnnotationTool::setFont(const QFont &font)
0359 {
0360     if (!m_options.testFlag(Option::FontOption) || this->font() == font) {
0361         return;
0362     }
0363 
0364     setFontForType(font, m_type);
0365     Q_EMIT fontChanged(font);
0366 }
0367 
0368 void AnnotationTool::setFontForType(const QFont &font, AnnotationTool::Tool type)
0369 {
0370     switch (type) {
0371         SET_FONT(Text)
0372         SET_FONT(Number)
0373     default:
0374         break;
0375     }
0376 }
0377 
0378 void AnnotationTool::resetFont()
0379 {
0380     setFont({});
0381 }
0382 
0383 QColor AnnotationTool::fontColor() const
0384 {
0385     return fontColorForType(m_type);
0386 }
0387 
0388 constexpr QColor AnnotationTool::defaultFontColorForType(AnnotationTool::Tool type)
0389 {
0390     switch (type) {
0391         DEFAULT_FONT_COLOR(Text)
0392         DEFAULT_FONT_COLOR(Number)
0393     default:
0394         return Qt::transparent;
0395     }
0396 }
0397 
0398 QColor AnnotationTool::fontColorForType(AnnotationTool::Tool type) const
0399 {
0400     switch (type) {
0401     case TextTool:
0402         return Settings::textFontColor();
0403     case NumberTool:
0404         return Settings::numberFontColor();
0405     default:
0406         return Qt::transparent;
0407     }
0408 }
0409 
0410 void AnnotationTool::setFontColor(const QColor &color)
0411 {
0412     if (!m_options.testFlag(Option::FontOption) || fontColor() == color) {
0413         return;
0414     }
0415 
0416     setFontColorForType(color, m_type);
0417     Q_EMIT fontColorChanged(color);
0418 }
0419 
0420 void AnnotationTool::setFontColorForType(const QColor &color, AnnotationTool::Tool type)
0421 {
0422     switch (type) {
0423         SET_FONT_COLOR(Text)
0424         SET_FONT_COLOR(Number)
0425     default:
0426         break;
0427     }
0428 }
0429 
0430 void AnnotationTool::resetFontColor()
0431 {
0432     setFontColor(defaultFontColorForType(m_type));
0433 }
0434 
0435 int AnnotationTool::number() const
0436 {
0437     return m_number;
0438 }
0439 
0440 void AnnotationTool::setNumber(int number)
0441 {
0442     if (m_number == number) {
0443         return;
0444     }
0445 
0446     m_number = number;
0447     Q_EMIT numberChanged(number);
0448 }
0449 
0450 void AnnotationTool::resetNumber()
0451 {
0452     setNumber(1);
0453 }
0454 
0455 bool AnnotationTool::typeHasShadow(AnnotationTool::Tool type) const
0456 {
0457     switch (type) {
0458     case FreehandTool:
0459         return Settings::freehandShadow();
0460     case LineTool:
0461         return Settings::lineShadow();
0462     case ArrowTool:
0463         return Settings::arrowShadow();
0464     case RectangleTool:
0465         return Settings::rectangleShadow();
0466     case EllipseTool:
0467         return Settings::ellipseShadow();
0468     case TextTool:
0469         return Settings::textShadow();
0470     case NumberTool:
0471         return Settings::numberShadow();
0472     default:
0473         return false;
0474     }
0475 }
0476 
0477 bool AnnotationTool::hasShadow() const
0478 {
0479     return typeHasShadow(m_type);
0480 }
0481 
0482 void AnnotationTool::setTypeHasShadow(AnnotationTool::Tool type, bool shadow)
0483 {
0484     switch (type) {
0485         SET_SHADOW(Freehand)
0486         SET_SHADOW(Line)
0487         SET_SHADOW(Arrow)
0488         SET_SHADOW(Rectangle)
0489         SET_SHADOW(Ellipse)
0490         SET_SHADOW(Text)
0491         SET_SHADOW(Number)
0492     default:
0493         break;
0494     }
0495 }
0496 
0497 void AnnotationTool::setShadow(bool shadow)
0498 {
0499     if (!m_options.testFlag(Option::ShadowOption) || hasShadow() == shadow) {
0500         return;
0501     }
0502 
0503     setTypeHasShadow(m_type, shadow);
0504     Q_EMIT shadowChanged(shadow);
0505 }
0506 
0507 void AnnotationTool::resetShadow()
0508 {
0509     setShadow(true);
0510 }
0511 
0512 #include <moc_AnnotationTool.cpp>