File indexing completed on 2025-01-19 03:51:07
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-02-14 0007 * Description : a tool to insert a text over an image. 0008 * 0009 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "inserttexttool.h" 0017 0018 // Qt includes 0019 0020 #include <QBrush> 0021 #include <QButtonGroup> 0022 #include <QCheckBox> 0023 #include <QFont> 0024 #include <QFrame> 0025 #include <QGridLayout> 0026 #include <QGroupBox> 0027 #include <QLabel> 0028 #include <QPainter> 0029 #include <QPen> 0030 #include <QPixmap> 0031 #include <QTimer> 0032 #include <QToolButton> 0033 #include <QVBoxLayout> 0034 #include <QIcon> 0035 #include <QComboBox> 0036 #include <QApplication> 0037 0038 // KDE includes 0039 0040 #include <klocalizedstring.h> 0041 #include <ksharedconfig.h> 0042 #include <kconfiggroup.h> 0043 0044 // Local includes 0045 0046 #include "dlayoutbox.h" 0047 #include "dimg.h" 0048 #include "editortoolsettings.h" 0049 #include "imageiface.h" 0050 #include "inserttextwidget.h" 0051 #include "dfontproperties.h" 0052 #include "dcolorselector.h" 0053 #include "dnuminput.h" 0054 #include "dtextedit.h" 0055 0056 namespace DigikamEditorInsertTextToolPlugin 0057 { 0058 0059 class Q_DECL_HIDDEN InsertTextTool::Private 0060 { 0061 public: 0062 0063 explicit Private() 0064 : alignTextMode (0), 0065 defaultSizeFont (0), 0066 borderText (nullptr), 0067 transparentText (nullptr), 0068 alignButtonGroup (nullptr), 0069 textRotation (nullptr), 0070 textOpacity (nullptr), 0071 fontColorButton (nullptr), 0072 fontChooserWidget (nullptr), 0073 textEdit (nullptr), 0074 previewWidget (nullptr), 0075 gboxSettings (nullptr) 0076 { 0077 } 0078 0079 static const QString configGroupName; 0080 static const QString configTextRotationEntry; 0081 static const QString configFontColorEntry; 0082 static const QString configTextOpacity; 0083 static const QString configTextStringEntry; 0084 static const QString configFontPropertiesEntry; 0085 static const QString configTextAlignmentEntry; 0086 static const QString configBorderTextEntry; 0087 static const QString configTransparentTextEntry; 0088 static const QString configPositionHintEntry; 0089 0090 int alignTextMode; 0091 int defaultSizeFont; 0092 0093 QCheckBox* borderText; 0094 QCheckBox* transparentText; 0095 0096 QButtonGroup* alignButtonGroup; 0097 QFont textFont; 0098 0099 QComboBox* textRotation; 0100 DIntNumInput* textOpacity; 0101 DColorSelector* fontColorButton; 0102 DFontProperties* fontChooserWidget; 0103 DTextEdit* textEdit; 0104 0105 InsertTextWidget* previewWidget; 0106 EditorToolSettings* gboxSettings; 0107 }; 0108 0109 const QString InsertTextTool::Private::configGroupName(QLatin1String("inserttext Tool")); 0110 const QString InsertTextTool::Private::configTextRotationEntry(QLatin1String("Text Rotation")); 0111 const QString InsertTextTool::Private::configFontColorEntry(QLatin1String("Font Color")); 0112 const QString InsertTextTool::Private::configTextOpacity(QLatin1String("Text Opacity")); 0113 const QString InsertTextTool::Private::configTextStringEntry(QLatin1String("Enter your text here.")); 0114 const QString InsertTextTool::Private::configFontPropertiesEntry(QLatin1String("Font Properties")); 0115 const QString InsertTextTool::Private::configTextAlignmentEntry(QLatin1String("Text Alignment")); 0116 const QString InsertTextTool::Private::configBorderTextEntry(QLatin1String("Border Text")); 0117 const QString InsertTextTool::Private::configTransparentTextEntry(QLatin1String("Transparent Text")); 0118 const QString InsertTextTool::Private::configPositionHintEntry(QLatin1String("Position Hint")); 0119 0120 // -------------------------------------------------------- 0121 0122 InsertTextTool::InsertTextTool(QObject* const parent) 0123 : EditorTool(parent), 0124 d (new Private) 0125 { 0126 setObjectName(QLatin1String("inserttext")); 0127 0128 // ------------------------------------------------------------- 0129 0130 QFrame* const frame = new QFrame(nullptr); 0131 frame->setFrameStyle(QFrame::Panel|QFrame::Sunken); 0132 0133 QVBoxLayout* const l = new QVBoxLayout(frame); 0134 d->previewWidget = new InsertTextWidget(480, 320, frame); 0135 l->addWidget(d->previewWidget); 0136 d->previewWidget->setWhatsThis(i18n("This previews the text inserted in the image. " 0137 "You can use the mouse to move the text to the right location.")); 0138 setToolView(frame); 0139 0140 // ------------------------------------------------------------- 0141 0142 d->gboxSettings = new EditorToolSettings(nullptr); 0143 d->textEdit = new DTextEdit(); 0144 d->textEdit->setWordWrapMode(QTextOption::NoWrap); 0145 d->textEdit->setWhatsThis(i18n("Here, enter the text you want to insert in your image.")); 0146 0147 // ------------------------------------------------------------- 0148 0149 d->fontChooserWidget = new DFontProperties(nullptr, DFontProperties::NoDisplayFlags); 0150 d->fontChooserWidget->setSampleBoxVisible(false); 0151 d->fontChooserWidget->setWhatsThis(i18n("Here you can choose the font to be used.")); 0152 0153 // ------------------------------------------------------------- 0154 0155 QWidget* const alignBox = new QWidget(); 0156 QHBoxLayout* const hlay = new QHBoxLayout(alignBox); 0157 d->alignButtonGroup = new QButtonGroup(alignBox); 0158 d->alignButtonGroup->setExclusive(true); 0159 0160 QToolButton* const alignLeft = new QToolButton(alignBox); 0161 d->alignButtonGroup->addButton(alignLeft, InsertTextWidget::ALIGN_LEFT); 0162 alignLeft->setIcon(QIcon::fromTheme(QLatin1String("format-justify-left"))); 0163 alignLeft->setCheckable(true); 0164 alignLeft->setToolTip(i18n("Align text to the left")); 0165 0166 QToolButton* const alignRight = new QToolButton(alignBox); 0167 d->alignButtonGroup->addButton(alignRight, InsertTextWidget::ALIGN_RIGHT); 0168 alignRight->setIcon(QIcon::fromTheme(QLatin1String("format-justify-right"))); 0169 alignRight->setCheckable(true); 0170 alignRight->setToolTip(i18n("Align text to the right")); 0171 0172 QToolButton* const alignCenter = new QToolButton(alignBox); 0173 d->alignButtonGroup->addButton(alignCenter, InsertTextWidget::ALIGN_CENTER); 0174 alignCenter->setIcon(QIcon::fromTheme(QLatin1String("format-justify-center"))); 0175 alignCenter->setCheckable(true); 0176 alignCenter->setToolTip(i18n("Align text to center")); 0177 0178 QToolButton* alignBlock = new QToolButton(alignBox); 0179 d->alignButtonGroup->addButton(alignBlock, InsertTextWidget::ALIGN_BLOCK); 0180 alignBlock->setIcon(QIcon::fromTheme(QLatin1String("format-justify-fill"))); 0181 alignBlock->setCheckable(true); 0182 alignBlock->setToolTip(i18n("Align text to a block")); 0183 0184 hlay->setContentsMargins(QMargins()); 0185 hlay->setSpacing(0); 0186 hlay->addStretch(); 0187 hlay->addWidget(alignLeft); 0188 hlay->addWidget(alignRight); 0189 hlay->addWidget(alignCenter); 0190 hlay->addWidget(alignBlock); 0191 hlay->addStretch(); 0192 0193 // ------------------------------------------------------------- 0194 0195 QLabel* const label1 = new QLabel(i18n("Rotation:")); 0196 d->textRotation = new QComboBox(); 0197 d->textRotation->addItem(i18nc("no rotation", "None")); 0198 d->textRotation->addItem(i18n("90 Degrees")); 0199 d->textRotation->addItem(i18n("180 Degrees")); 0200 d->textRotation->addItem(i18n("270 Degrees")); 0201 d->textRotation->setWhatsThis(i18n("Select the text rotation to use here.")); 0202 0203 // ------------------------------------------------------------- 0204 0205 QLabel* const label2 = new QLabel(i18nc("font color", "Color:")); 0206 d->fontColorButton = new DColorSelector(); 0207 d->fontColorButton->setColor(Qt::black); 0208 d->fontColorButton->setWhatsThis(i18n("Set here the font color to use.")); 0209 0210 // ------------------------------------------------------------- 0211 0212 QLabel* const label3 = new QLabel(i18nc("text opacity", "Opacity:")); 0213 d->textOpacity = new DIntNumInput(); 0214 d->textOpacity->setRange(0, 100, 1); 0215 d->textOpacity->setDefaultValue(100); 0216 d->textOpacity->setSuffix(QLatin1String("%")); 0217 d->textOpacity->setWhatsThis(i18n("Select the text opacity to use here.")); 0218 0219 // ------------------------------------------------------------- 0220 0221 d->borderText = new QCheckBox(i18n("Add border")); 0222 d->borderText->setToolTip(i18n("Add a solid border around text using current text color")); 0223 0224 d->transparentText = new QCheckBox(i18n("Semi-transparent")); 0225 d->transparentText->setToolTip(i18n("Use semi-transparent text background under image")); 0226 0227 // ------------------------------------------------------------- 0228 0229 const int spacing = d->gboxSettings->spacingHint(); 0230 0231 QGridLayout* const mainLayout = new QGridLayout(); 0232 mainLayout->addWidget(d->textEdit, 0, 0, 3, -1); 0233 mainLayout->addWidget(d->fontChooserWidget, 3, 0, 1, -1); 0234 mainLayout->addWidget(alignBox, 4, 0, 1, -1); 0235 mainLayout->addWidget(label1, 5, 0, 1, 1); 0236 mainLayout->addWidget(d->textRotation, 5, 1, 1, 1); 0237 mainLayout->addWidget(label2, 6, 0, 1, 1); 0238 mainLayout->addWidget(d->fontColorButton, 6, 1, 1, 1); 0239 mainLayout->addWidget(label3, 7, 0, 1, 1); 0240 mainLayout->addWidget(d->textOpacity, 7, 1, 1, 1); 0241 mainLayout->addWidget(d->borderText, 8, 0, 1, -1); 0242 mainLayout->addWidget(d->transparentText, 9, 0, 1, -1); 0243 mainLayout->setRowStretch(10, 10); 0244 mainLayout->setColumnStretch(1, 5); 0245 mainLayout->setColumnStretch(2, 10); 0246 mainLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0247 mainLayout->setSpacing(spacing); 0248 d->gboxSettings->plainPage()->setLayout(mainLayout); 0249 0250 // ------------------------------------------------------------- 0251 0252 setToolSettings(d->gboxSettings); 0253 0254 // ------------------------------------------------------------- 0255 0256 connect(d->fontChooserWidget, SIGNAL(fontSelected(QFont)), 0257 this, SLOT(slotFontPropertiesChanged(QFont))); 0258 0259 connect(d->fontColorButton, SIGNAL(signalColorSelected(QColor)), 0260 this, SLOT(slotUpdatePreview())); 0261 0262 connect(d->textOpacity, SIGNAL(valueChanged(int)), 0263 this, SLOT(slotUpdatePreview())); 0264 0265 connect(d->textEdit, SIGNAL(textChanged()), 0266 this, SLOT(slotUpdatePreview())); 0267 0268 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) 0269 0270 connect(d->alignButtonGroup, SIGNAL(idReleased(int)), 0271 this, SLOT(slotAlignModeChanged(int))); 0272 0273 #else 0274 0275 connect(d->alignButtonGroup, SIGNAL(buttonReleased(int)), 0276 this, SLOT(slotAlignModeChanged(int))); 0277 0278 #endif 0279 0280 connect(d->borderText, SIGNAL(toggled(bool)), 0281 this, SLOT(slotUpdatePreview())); 0282 0283 connect(d->transparentText, SIGNAL(toggled(bool)), 0284 this, SLOT(slotUpdatePreview())); 0285 0286 connect(d->textRotation, SIGNAL(activated(int)), 0287 this, SLOT(slotUpdatePreview())); 0288 0289 connect(this, SIGNAL(signalUpdatePreview()), 0290 this, SLOT(slotUpdatePreview())); 0291 0292 // ------------------------------------------------------------- 0293 0294 slotUpdatePreview(); 0295 } 0296 0297 InsertTextTool::~InsertTextTool() 0298 { 0299 delete d; 0300 } 0301 0302 void InsertTextTool::readSettings() 0303 { 0304 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0305 KConfigGroup group = config->group(d->configGroupName); 0306 QColor black(0, 0, 0); 0307 QFont defaultFont; 0308 0309 int orgW = d->previewWidget->imageIface()->originalSize().width(); 0310 int orgH = d->previewWidget->imageIface()->originalSize().height(); 0311 0312 if ( orgW > orgH ) 0313 { 0314 d->defaultSizeFont = (int)(orgH / 8.0); 0315 } 0316 else 0317 { 0318 d->defaultSizeFont = (int)(orgW / 8.0); 0319 } 0320 0321 defaultFont.setPointSize(d->defaultSizeFont); 0322 0323 d->textRotation->setCurrentIndex(group.readEntry(d->configTextRotationEntry, 0)); 0324 d->fontColorButton->setColor(group.readEntry(d->configFontColorEntry, black)); 0325 d->textOpacity->setValue(group.readEntry(d->configTextOpacity, 100)); 0326 d->textEdit->setText(group.readEntry(d->configTextStringEntry, i18n("Enter your text here."))); 0327 d->textFont = group.readEntry(d->configFontPropertiesEntry, defaultFont); 0328 d->fontChooserWidget->setFont(d->textFont); 0329 d->alignTextMode = group.readEntry(d->configTextAlignmentEntry, (int) InsertTextWidget::ALIGN_LEFT); 0330 d->borderText->setChecked(group.readEntry(d->configBorderTextEntry, false)); 0331 d->transparentText->setChecked(group.readEntry(d->configTransparentTextEntry, false)); 0332 d->previewWidget->setPositionHint(group.readEntry(d->configPositionHintEntry, QRect())); 0333 0334 d->alignButtonGroup->button(d->alignTextMode)->setChecked(true); 0335 slotAlignModeChanged(d->alignTextMode); 0336 } 0337 0338 void InsertTextTool::writeSettings() 0339 { 0340 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0341 KConfigGroup group = config->group(d->configGroupName); 0342 0343 group.writeEntry(d->configTextRotationEntry, d->textRotation->currentIndex()); 0344 group.writeEntry(d->configFontColorEntry, d->fontColorButton->color()); 0345 group.writeEntry(d->configTextOpacity, d->textOpacity->value()); 0346 group.writeEntry(d->configTextStringEntry, d->textEdit->toPlainText()); 0347 group.writeEntry(d->configFontPropertiesEntry, d->textFont); 0348 group.writeEntry(d->configTextAlignmentEntry, d->alignTextMode); 0349 group.writeEntry(d->configBorderTextEntry, d->borderText->isChecked()); 0350 group.writeEntry(d->configTransparentTextEntry, d->transparentText->isChecked()); 0351 group.writeEntry(d->configPositionHintEntry, d->previewWidget->getPositionHint()); 0352 0353 config->sync(); 0354 } 0355 0356 void InsertTextTool::slotResetSettings() 0357 { 0358 d->fontColorButton->blockSignals(true); 0359 d->alignButtonGroup->blockSignals(true); 0360 d->fontChooserWidget->blockSignals(true); 0361 0362 d->textRotation->setCurrentIndex(0); // No rotation. 0363 d->fontColorButton->setColor(Qt::black); 0364 d->textOpacity->slotReset(); 0365 QFont defaultFont; 0366 d->textFont = defaultFont; // Reset to default KDE font. 0367 d->textFont.setPointSize(d->defaultSizeFont); 0368 d->fontChooserWidget->setFont(d->textFont); 0369 d->borderText->setChecked(false); 0370 d->transparentText->setChecked(false); 0371 d->previewWidget->resetEdit(); 0372 d->alignButtonGroup->button(InsertTextWidget::ALIGN_LEFT)->setChecked(true); 0373 0374 d->fontChooserWidget->blockSignals(false); 0375 d->fontColorButton->blockSignals(false); 0376 d->alignButtonGroup->blockSignals(false); 0377 slotAlignModeChanged(InsertTextWidget::ALIGN_LEFT); 0378 } 0379 0380 void InsertTextTool::slotAlignModeChanged(int mode) 0381 { 0382 d->alignTextMode = mode; 0383 d->textEdit->selectAll(); 0384 0385 switch (d->alignTextMode) 0386 { 0387 case InsertTextWidget::ALIGN_LEFT: 0388 d->textEdit->setAlignment(Qt::AlignLeft); 0389 break; 0390 0391 case InsertTextWidget::ALIGN_RIGHT: 0392 d->textEdit->setAlignment(Qt::AlignRight); 0393 break; 0394 0395 case InsertTextWidget::ALIGN_CENTER: 0396 d->textEdit->setAlignment(Qt::AlignHCenter); 0397 break; 0398 0399 case InsertTextWidget::ALIGN_BLOCK: 0400 d->textEdit->setAlignment(Qt::AlignJustify); 0401 break; 0402 } 0403 0404 d->textEdit->textCursor().clearSelection(); 0405 Q_EMIT signalUpdatePreview(); 0406 } 0407 0408 void InsertTextTool::slotFontPropertiesChanged(const QFont& font) 0409 { 0410 d->textFont = font; 0411 Q_EMIT signalUpdatePreview(); 0412 } 0413 0414 void InsertTextTool::setBackgroundColor(const QColor& bg) 0415 { 0416 d->previewWidget->setBackgroundColor(bg); 0417 } 0418 0419 void InsertTextTool::slotUpdatePreview() 0420 { 0421 d->previewWidget->setText(d->textEdit->toPlainText(), d->textFont, d->fontColorButton->color(), 0422 d->textOpacity->value(), d->alignTextMode, 0423 d->borderText->isChecked(), d->transparentText->isChecked(), 0424 d->textRotation->currentIndex()); 0425 } 0426 0427 void InsertTextTool::finalRendering() 0428 { 0429 qApp->setOverrideCursor( Qt::WaitCursor ); 0430 0431 ImageIface iface; 0432 DImg dest = d->previewWidget->makeInsertText(); 0433 0434 FilterAction action(QLatin1String("digikam:insertTextTool"), 2); 0435 action.setDisplayableName(i18n("Insert Text Tool")); 0436 0437 action.addParameter(QLatin1String("text"), d->textEdit->toPlainText()); 0438 action.addParameter(QLatin1String("textRotationIndex"), d->textRotation->currentIndex()); 0439 action.addParameter(QLatin1String("textFont"), d->textFont.toString()); 0440 action.addParameter(QLatin1String("colorR"), d->fontColorButton->color().red()); 0441 action.addParameter(QLatin1String("colorG"), d->fontColorButton->color().green()); 0442 action.addParameter(QLatin1String("colorB"), d->fontColorButton->color().blue()); 0443 action.addParameter(QLatin1String("colorA"), d->fontColorButton->color().alpha()); 0444 action.addParameter(QLatin1String("textOpacity"), d->textOpacity->value()); 0445 action.addParameter(QLatin1String("borderText"), d->borderText->isChecked()); 0446 action.addParameter(QLatin1String("transparentText"), d->transparentText->isChecked()); 0447 0448 iface.setOriginal(i18n("Insert Text"), action, dest); 0449 0450 qApp->restoreOverrideCursor(); 0451 } 0452 0453 } // namespace DigikamEditorInsertTextToolPlugin 0454 0455 #include "moc_inserttexttool.cpp"