File indexing completed on 2024-04-21 05:48:24
0001 /** 0002 * SPDX-FileCopyrightText: (C) 2003 Sébastien Laoût <slaout@linux62.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "noteedit.h" 0008 0009 #include <QAction> 0010 #include <QApplication> 0011 #include <QColorDialog> 0012 #include <QDialogButtonBox> 0013 #include <QFontComboBox> 0014 #include <QGraphicsProxyWidget> 0015 #include <QGridLayout> 0016 #include <QHBoxLayout> 0017 #include <QLabel> 0018 #include <QLineEdit> 0019 #include <QLocale> 0020 #include <QPushButton> 0021 #include <QScrollBar> 0022 #include <QVBoxLayout> 0023 #include <QWidgetAction> 0024 #include <QtGui/QKeyEvent> 0025 #include <QtGui/QTextCharFormat> 0026 0027 #include <KActionCollection> 0028 #include <KColorCombo> 0029 #include <KConfig> 0030 #include <KConfigGroup> 0031 #include <KDesktopFile> 0032 #include <KIconButton> 0033 #include <KLineEdit> 0034 #include <KLocalizedString> 0035 #include <KMessageBox> 0036 #include <KService> 0037 #include <KToggleAction> 0038 #include <KToolBar> 0039 #include <KUrlRequester> 0040 0041 #include "basketlistview.h" 0042 #include "basketscene.h" 0043 #include "focusedwidgets.h" 0044 #include "icon_names.h" 0045 #include "note.h" 0046 #include "notecontent.h" 0047 #include "notefactory.h" 0048 #include "settings.h" 0049 #include "tools.h" 0050 #include "variouswidgets.h" 0051 0052 /** class NoteEditor: */ 0053 0054 NoteEditor::NoteEditor(NoteContent *noteContent) 0055 { 0056 m_isEmpty = false; 0057 m_canceled = false; 0058 m_widget = nullptr; 0059 m_textEdit = nullptr; 0060 m_lineEdit = nullptr; 0061 m_noteContent = noteContent; 0062 } 0063 0064 NoteEditor::~NoteEditor() 0065 { 0066 delete m_widget; 0067 } 0068 0069 Note *NoteEditor::note() 0070 { 0071 return m_noteContent->note(); 0072 } 0073 0074 void NoteEditor::setCursorTo(const QPointF &pos) 0075 { 0076 // clicked comes from the QMouseEvent, which is in item's coordinate system. 0077 if (m_textEdit) { 0078 QPointF currentPos = note()->mapFromScene(pos); 0079 QPointF deltaPos = m_textEdit->pos() - note()->pos(); 0080 m_textEdit->setTextCursor(m_textEdit->cursorForPosition((currentPos - deltaPos).toPoint())); 0081 } 0082 } 0083 0084 void NoteEditor::startSelection(const QPointF &pos) 0085 { 0086 if (m_textEdit) { 0087 QPointF currentPos = note()->mapFromScene(pos); 0088 QPointF deltaPos = m_textEdit->pos() - note()->pos(); 0089 m_textEdit->setTextCursor(m_textEdit->cursorForPosition((currentPos - deltaPos).toPoint())); 0090 } 0091 } 0092 0093 void NoteEditor::updateSelection(const QPointF &pos) 0094 { 0095 if (m_textEdit) { 0096 QPointF currentPos = note()->mapFromScene(pos); 0097 QPointF deltaPos = m_textEdit->pos() - note()->pos(); 0098 0099 QTextCursor cursor = m_textEdit->cursorForPosition((currentPos - deltaPos).toPoint()); 0100 QTextCursor currentCursor = m_textEdit->textCursor(); 0101 // select the text 0102 currentCursor.setPosition(cursor.position(), QTextCursor::KeepAnchor); 0103 // update the cursor 0104 m_textEdit->setTextCursor(currentCursor); 0105 } 0106 } 0107 0108 void NoteEditor::endSelection(const QPointF & /*pos*/) 0109 { 0110 // For TextEdit inside GraphicsScene selectionChanged() is only generated for the first selected char - 0111 // thus we need to call it manually after selection is finished 0112 if (FocusedTextEdit *textEdit = dynamic_cast<FocusedTextEdit *>(m_textEdit)) 0113 textEdit->onSelectionChanged(); 0114 } 0115 0116 void NoteEditor::paste(const QPointF &pos, QClipboard::Mode mode) 0117 { 0118 if (FocusedTextEdit *textEdit = dynamic_cast<FocusedTextEdit *>(m_textEdit)) { 0119 setCursorTo(pos); 0120 textEdit->paste(mode); 0121 } 0122 } 0123 0124 void NoteEditor::connectActions(BasketScene *scene) 0125 { 0126 if (m_textEdit) { 0127 connect(m_textEdit, SIGNAL(textChanged()), scene, SLOT(selectionChangedInEditor())); 0128 connect(m_textEdit, SIGNAL(textChanged()), scene, SLOT(contentChangedInEditor())); 0129 connect(m_textEdit, &KTextEdit::textChanged, scene, &BasketScene::placeEditorAndEnsureVisible); 0130 connect(m_textEdit, SIGNAL(selectionChanged()), scene, SLOT(selectionChangedInEditor())); 0131 0132 } else if (m_lineEdit) { 0133 connect(m_lineEdit, SIGNAL(textChanged(const QString &)), scene, SLOT(selectionChangedInEditor())); 0134 connect(m_lineEdit, SIGNAL(textChanged(const QString &)), scene, SLOT(contentChangedInEditor())); 0135 connect(m_lineEdit, SIGNAL(selectionChanged()), scene, SLOT(selectionChangedInEditor())); 0136 } 0137 } 0138 0139 NoteEditor *NoteEditor::editNoteContent(NoteContent *noteContent, QWidget *parent) 0140 { 0141 TextContent *textContent = dynamic_cast<TextContent *>(noteContent); 0142 if (textContent) 0143 return new TextEditor(textContent, parent); 0144 0145 HtmlContent *htmlContent = dynamic_cast<HtmlContent *>(noteContent); 0146 if (htmlContent) 0147 return new HtmlEditor(htmlContent, parent); 0148 0149 ImageContent *imageContent = dynamic_cast<ImageContent *>(noteContent); 0150 if (imageContent) 0151 return new ImageEditor(imageContent, parent); 0152 0153 AnimationContent *animationContent = dynamic_cast<AnimationContent *>(noteContent); 0154 if (animationContent) 0155 return new AnimationEditor(animationContent, parent); 0156 0157 FileContent *fileContent = dynamic_cast<FileContent *>(noteContent); // Same for SoundContent 0158 if (fileContent) 0159 return new FileEditor(fileContent, parent); 0160 0161 LinkContent *linkContent = dynamic_cast<LinkContent *>(noteContent); 0162 if (linkContent) 0163 return new LinkEditor(linkContent, parent); 0164 0165 CrossReferenceContent *crossReferenceContent = dynamic_cast<CrossReferenceContent *>(noteContent); 0166 if (crossReferenceContent) 0167 return new CrossReferenceEditor(crossReferenceContent, parent); 0168 0169 LauncherContent *launcherContent = dynamic_cast<LauncherContent *>(noteContent); 0170 if (launcherContent) 0171 return new LauncherEditor(launcherContent, parent); 0172 0173 ColorContent *colorContent = dynamic_cast<ColorContent *>(noteContent); 0174 if (colorContent) 0175 return new ColorEditor(colorContent, parent); 0176 0177 UnknownContent *unknownContent = dynamic_cast<UnknownContent *>(noteContent); 0178 if (unknownContent) 0179 return new UnknownEditor(unknownContent, parent); 0180 0181 return nullptr; 0182 } 0183 0184 void NoteEditor::setInlineEditor(QWidget *inlineEditor) 0185 { 0186 if (!m_widget) { 0187 m_widget = new QGraphicsProxyWidget(); 0188 } 0189 m_widget->setWidget(inlineEditor); 0190 m_widget->setZValue(500); 0191 // m_widget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); 0192 m_widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0193 0194 m_textEdit = nullptr; 0195 m_lineEdit = nullptr; 0196 KTextEdit *textEdit = dynamic_cast<KTextEdit *>(inlineEditor); 0197 if (textEdit) { 0198 m_textEdit = textEdit; 0199 } else { 0200 QLineEdit *lineEdit = dynamic_cast<QLineEdit *>(inlineEditor); 0201 if (lineEdit) { 0202 m_lineEdit = lineEdit; 0203 } 0204 } 0205 } 0206 0207 /** class TextEditor: */ 0208 0209 TextEditor::TextEditor(TextContent *textContent, QWidget *parent) 0210 : NoteEditor(textContent) 0211 , m_textContent(textContent) 0212 { 0213 FocusedTextEdit *textEdit = new FocusedTextEdit(/*disableUpdatesOnKeyPress=*/true, parent); 0214 textEdit->setLineWidth(0); 0215 textEdit->setMidLineWidth(0); 0216 textEdit->setFrameStyle(QFrame::Box); 0217 QPalette palette; 0218 palette.setColor(textEdit->backgroundRole(), note()->backgroundColor()); 0219 palette.setColor(textEdit->foregroundRole(), note()->textColor()); 0220 textEdit->setPalette(palette); 0221 0222 textEdit->setFont(note()->font()); 0223 textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0224 0225 if (Settings::spellCheckTextNotes()) 0226 textEdit->setCheckSpellingEnabled(true); 0227 textEdit->setPlainText(m_textContent->text()); 0228 0229 // Not sure if the following comment is still true 0230 // FIXME: Sometimes, the cursor flicker at ends before being positioned where clicked (because qApp->processEvents() I think) 0231 textEdit->moveCursor(QTextCursor::End); 0232 textEdit->verticalScrollBar()->setCursor(Qt::ArrowCursor); 0233 setInlineEditor(textEdit); 0234 connect(textEdit, &FocusedTextEdit::escapePressed, this, &TextEditor::askValidation); 0235 connect(textEdit, &FocusedTextEdit::mouseEntered, this, &TextEditor::mouseEnteredEditorWidget); 0236 0237 connect(textEdit, &FocusedTextEdit::cursorPositionChanged, textContent->note()->basket(), &BasketScene::editorCursorPositionChanged); 0238 // In case it is a very big note, the top is displayed and Enter is pressed: the cursor is on bottom, we should enure it visible: 0239 QTimer::singleShot(0, textContent->note()->basket(), SLOT(editorCursorPositionChanged())); 0240 } 0241 0242 TextEditor::~TextEditor() 0243 { 0244 delete graphicsWidget()->widget(); // TODO: delete that in validate(), so we can remove one method 0245 } 0246 0247 void TextEditor::autoSave(bool toFileToo) 0248 { 0249 bool autoSpellCheck = true; 0250 if (toFileToo) { 0251 if (Settings::spellCheckTextNotes() != textEdit()->checkSpellingEnabled()) { 0252 Settings::setSpellCheckTextNotes(textEdit()->checkSpellingEnabled()); 0253 Settings::saveConfig(); 0254 } 0255 0256 autoSpellCheck = textEdit()->checkSpellingEnabled(); 0257 textEdit()->setCheckSpellingEnabled(false); 0258 } 0259 0260 m_textContent->setText(textEdit()->toPlainText()); 0261 0262 if (toFileToo) { 0263 m_textContent->saveToFile(); 0264 m_textContent->setEdited(); 0265 textEdit()->setCheckSpellingEnabled(autoSpellCheck); 0266 } 0267 } 0268 0269 void TextEditor::validate() 0270 { 0271 if (Settings::spellCheckTextNotes() != textEdit()->checkSpellingEnabled()) { 0272 Settings::setSpellCheckTextNotes(textEdit()->checkSpellingEnabled()); 0273 Settings::saveConfig(); 0274 } 0275 0276 textEdit()->setCheckSpellingEnabled(false); 0277 if (textEdit()->document()->isEmpty()) 0278 setEmpty(); 0279 m_textContent->setText(textEdit()->toPlainText()); 0280 m_textContent->saveToFile(); 0281 m_textContent->setEdited(); 0282 0283 note()->setWidth(0); 0284 } 0285 0286 /** class HtmlEditor: */ 0287 0288 HtmlEditor::HtmlEditor(HtmlContent *htmlContent, QWidget *parent) 0289 : NoteEditor(htmlContent) 0290 , m_htmlContent(htmlContent) 0291 { 0292 FocusedTextEdit *textEdit = new FocusedTextEdit(/*disableUpdatesOnKeyPress=*/true, parent); 0293 textEdit->setLineWidth(0); 0294 textEdit->setMidLineWidth(0); 0295 textEdit->setFrameStyle(QFrame::Box); 0296 textEdit->setAutoFormatting(Settings::autoBullet() ? QTextEdit::AutoAll : QTextEdit::AutoNone); 0297 0298 QPalette palette; 0299 palette.setColor(textEdit->backgroundRole(), note()->backgroundColor()); 0300 palette.setColor(textEdit->foregroundRole(), note()->textColor()); 0301 textEdit->setPalette(palette); 0302 0303 textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0304 textEdit->setHtml(Tools::detectCrossReferences(m_htmlContent->html(), /*userLink=*/true)); 0305 textEdit->moveCursor(QTextCursor::End); 0306 textEdit->verticalScrollBar()->setCursor(Qt::ArrowCursor); 0307 setInlineEditor(textEdit); 0308 0309 connect(textEdit, &FocusedTextEdit::mouseEntered, this, &HtmlEditor::mouseEnteredEditorWidget); 0310 connect(textEdit, &FocusedTextEdit::escapePressed, this, &HtmlEditor::askValidation); 0311 0312 connect(InlineEditors::instance()->richTextFont, &QFontComboBox::currentFontChanged, this, &HtmlEditor::onFontSelectionChanged); 0313 connect(InlineEditors::instance()->richTextFontSize, &FontSizeCombo::sizeChanged, textEdit, &FocusedTextEdit::setFontPointSize); 0314 connect(InlineEditors::instance()->richTextColor, &KColorCombo::activated, textEdit, &FocusedTextEdit::setTextColor); 0315 0316 connect(InlineEditors::instance()->focusWidgetFilter, &FocusWidgetFilter::escapePressed, textEdit, [&textEdit]() { textEdit->setFocus(); }); 0317 connect(InlineEditors::instance()->focusWidgetFilter, &FocusWidgetFilter::returnPressed, textEdit, [&textEdit]() { textEdit->setFocus(); }); 0318 connect(InlineEditors::instance()->richTextFont, SIGNAL(activated(int)), textEdit, SLOT(setFocus())); 0319 0320 connect(InlineEditors::instance()->richTextFontSize, SIGNAL(activated(int)), textEdit, SLOT(setFocus())); 0321 0322 connect(textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged())); 0323 connect(textEdit, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this, SLOT(charFormatChanged(const QTextCharFormat &))); 0324 // connect( textEdit, SIGNAL(currentVerticalAlignmentChanged(VerticalAlignment)), this, SLOT(slotVerticalAlignmentChanged()) ); 0325 0326 connect(InlineEditors::instance()->richTextBold, SIGNAL(triggered(bool)), this, SLOT(setBold(bool))); 0327 connect(InlineEditors::instance()->richTextItalic, SIGNAL(triggered(bool)), textEdit, SLOT(setFontItalic(bool))); 0328 connect(InlineEditors::instance()->richTextUnderline, SIGNAL(triggered(bool)), textEdit, SLOT(setFontUnderline(bool))); 0329 connect(InlineEditors::instance()->richTextLeft, SIGNAL(triggered()), this, SLOT(setLeft())); 0330 connect(InlineEditors::instance()->richTextCenter, SIGNAL(triggered()), this, SLOT(setCentered())); 0331 connect(InlineEditors::instance()->richTextRight, SIGNAL(triggered()), this, SLOT(setRight())); 0332 connect(InlineEditors::instance()->richTextJustified, SIGNAL(triggered()), this, SLOT(setBlock())); 0333 0334 // InlineEditors::instance()->richTextToolBar()->show(); 0335 cursorPositionChanged(); 0336 charFormatChanged(textEdit->currentCharFormat()); 0337 // QTimer::singleShot( 0, this, SLOT(cursorPositionChanged()) ); 0338 InlineEditors::instance()->enableRichTextToolBar(); 0339 0340 connect(InlineEditors::instance()->richTextUndo, SIGNAL(triggered()), textEdit, SLOT(undo())); 0341 connect(InlineEditors::instance()->richTextRedo, SIGNAL(triggered()), textEdit, SLOT(redo())); 0342 connect(textEdit, SIGNAL(undoAvailable(bool)), InlineEditors::instance()->richTextUndo, SLOT(setEnabled(bool))); 0343 connect(textEdit, SIGNAL(redoAvailable(bool)), InlineEditors::instance()->richTextRedo, SLOT(setEnabled(bool))); 0344 connect(textEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged())); 0345 InlineEditors::instance()->richTextUndo->setEnabled(false); 0346 InlineEditors::instance()->richTextRedo->setEnabled(false); 0347 0348 connect(textEdit, SIGNAL(cursorPositionChanged()), htmlContent->note()->basket(), SLOT(editorCursorPositionChanged())); 0349 // In case it is a very big note, the top is displayed and Enter is pressed: the cursor is on bottom, we should enure it visible: 0350 QTimer::singleShot(0, htmlContent->note()->basket(), SLOT(editorCursorPositionChanged())); 0351 } 0352 0353 void HtmlEditor::cursorPositionChanged() 0354 { 0355 InlineEditors::instance()->richTextFont->setCurrentFont(textEdit()->currentFont().family()); 0356 if (InlineEditors::instance()->richTextColor->color() != textEdit()->textColor()) 0357 InlineEditors::instance()->richTextColor->setColor(textEdit()->textColor()); 0358 InlineEditors::instance()->richTextBold->setChecked((textEdit()->fontWeight() >= QFont::Bold)); 0359 InlineEditors::instance()->richTextItalic->setChecked(textEdit()->fontItalic()); 0360 InlineEditors::instance()->richTextUnderline->setChecked(textEdit()->fontUnderline()); 0361 0362 switch (textEdit()->alignment()) { 0363 default: 0364 case 1 /*Qt::AlignLeft*/: 0365 InlineEditors::instance()->richTextLeft->setChecked(true); 0366 break; 0367 case 2 /*Qt::AlignRight*/: 0368 InlineEditors::instance()->richTextRight->setChecked(true); 0369 break; 0370 case 4 /*Qt::AlignHCenter*/: 0371 InlineEditors::instance()->richTextCenter->setChecked(true); 0372 break; 0373 case 8 /*Qt::AlignJustify*/: 0374 InlineEditors::instance()->richTextJustified->setChecked(true); 0375 break; 0376 } 0377 } 0378 0379 void HtmlEditor::editTextChanged() 0380 { 0381 // The following is a workaround for an apparent Qt bug. 0382 // When I start typing in a textEdit, the undo&redo actions are not enabled until I click 0383 // or move the cursor - probably, the signal undoAvailable() is not emitted. 0384 // So, I had to intervene and do that manually. 0385 InlineEditors::instance()->richTextUndo->setEnabled(textEdit()->document()->isUndoAvailable()); 0386 InlineEditors::instance()->richTextRedo->setEnabled(textEdit()->document()->isRedoAvailable()); 0387 } 0388 0389 void HtmlEditor::charFormatChanged(const QTextCharFormat &format) 0390 { 0391 InlineEditors::instance()->richTextFontSize->setFontSize(format.font().pointSize()); 0392 } 0393 0394 /*void HtmlEditor::slotVerticalAlignmentChanged(QTextEdit::VerticalAlignment align) 0395 { 0396 QTextEdit::VerticalAlignment align = textEdit() 0397 switch (align) { 0398 case KTextEdit::AlignSuperScript: 0399 InlineEditors::instance()->richTextSuper->setChecked(true); 0400 InlineEditors::instance()->richTextSub->setChecked(false); 0401 break; 0402 case KTextEdit::AlignSubScript: 0403 InlineEditors::instance()->richTextSuper->setChecked(false); 0404 InlineEditors::instance()->richTextSub->setChecked(true); 0405 break; 0406 default: 0407 InlineEditors::instance()->richTextSuper->setChecked(false); 0408 InlineEditors::instance()->richTextSub->setChecked(false); 0409 } 0410 0411 NoteHtmlEditor::buttonToggled(int id) : 0412 case 106: 0413 if (isChecked && m_toolbar->isButtonOn(107)) 0414 m_toolbar->setButton(107, false); 0415 m_text->setVerticalAlignment(isChecked ? KTextEdit::AlignSuperScript : KTextEdit::AlignNormal); 0416 break; 0417 case 107: 0418 if (isChecked && m_toolbar->isButtonOn(106)) 0419 m_toolbar->setButton(106, false); 0420 m_text->setVerticalAlignment(isChecked ? KTextEdit::AlignSubScript : KTextEdit::AlignNormal); 0421 break; 0422 }*/ 0423 0424 void HtmlEditor::setLeft() 0425 { 0426 textEdit()->setAlignment(Qt::AlignLeft); 0427 } 0428 void HtmlEditor::setRight() 0429 { 0430 textEdit()->setAlignment(Qt::AlignRight); 0431 } 0432 void HtmlEditor::setCentered() 0433 { 0434 textEdit()->setAlignment(Qt::AlignHCenter); 0435 } 0436 void HtmlEditor::setBlock() 0437 { 0438 textEdit()->setAlignment(Qt::AlignJustify); 0439 } 0440 0441 void HtmlEditor::onFontSelectionChanged(const QFont &font) 0442 { 0443 // Change font family only 0444 textEdit()->setFontFamily(font.family()); 0445 InlineEditors::instance()->richTextFont->clearFocus(); 0446 // textEdit()->setFocus(); 0447 } 0448 0449 void HtmlEditor::setBold(bool isChecked) 0450 { 0451 qWarning() << "setBold " << isChecked; 0452 textEdit()->setFontWeight(isChecked ? QFont::Bold : QFont::Normal); 0453 } 0454 0455 HtmlEditor::~HtmlEditor() 0456 { 0457 // delete graphicsWidget()->widget(); 0458 } 0459 0460 void HtmlEditor::autoSave(bool toFileToo) 0461 { 0462 m_htmlContent->setHtml(Tools::textDocumentToMinimalHTML(textEdit()->document())); 0463 if (toFileToo) { 0464 m_htmlContent->saveToFile(); 0465 m_htmlContent->setEdited(); 0466 } 0467 } 0468 0469 void HtmlEditor::validate() 0470 { 0471 if (Tools::htmlToText(textEdit()->toHtml()).isEmpty()) 0472 setEmpty(); 0473 if (Settings::detectTextTags()) 0474 detectTags(); 0475 QString convert = Tools::textDocumentToMinimalHTML(textEdit()->document()); 0476 QString textEquivalent = Tools::htmlToText(convert); 0477 0478 if (note()->allowCrossReferences()) 0479 convert = Tools::detectCrossReferences(convert, /*userLink=*/true); 0480 0481 m_htmlContent->setHtml(convert); 0482 m_htmlContent->saveToFile(); 0483 m_htmlContent->setEdited(); 0484 0485 disconnect(); 0486 graphicsWidget()->disconnect(); 0487 if (InlineEditors::instance()) { 0488 InlineEditors::instance()->disableRichTextToolBar(); 0489 // if (InlineEditors::instance()->richTextToolBar()) 0490 // InlineEditors::instance()->richTextToolBar()->hide(); 0491 } 0492 0493 if (graphicsWidget()) { 0494 note()->setZValue(1); 0495 delete graphicsWidget()->widget(); 0496 setInlineEditor(nullptr); 0497 } 0498 } 0499 0500 void HtmlEditor::detectTags() 0501 { 0502 QTextDocument * doc = textEdit()->document(); 0503 const QTextBlock& block = doc->firstBlock(); 0504 if (!block.isValid() || block.begin() == block.end()) return; 0505 0506 const QTextFragment& fragment = block.begin().fragment(); 0507 if (!fragment.isValid() || fragment.length() == 0) return; 0508 //Process unstyled text only 0509 const QTextCharFormat& charFmt = fragment.charFormat(); 0510 if (charFmt.propertyCount() > 0) return; 0511 0512 QString newText = fragment.text(); 0513 int prefixLength; 0514 QTextCursor cursor(block); 0515 const QList<State*>& states = Tools::detectTags(fragment.text(), prefixLength); 0516 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, prefixLength); 0517 cursor.removeSelectedText(); 0518 0519 for (State* state: states) 0520 { 0521 note()->addState(state, true); 0522 } 0523 } 0524 /** class ImageEditor: */ 0525 0526 ImageEditor::ImageEditor(ImageContent *imageContent, QWidget *parent) 0527 : NoteEditor(imageContent) 0528 { 0529 int choice = KMessageBox::questionYesNoCancel(parent, 0530 i18n("Images can not be edited here at the moment (the next version of BasKet Note Pads will include an image editor).\n" 0531 "Do you want to open it with an application that understand it?"), 0532 i18n("Edit Image Note"), 0533 KStandardGuiItem::open(), 0534 KGuiItem(i18n("Load From &File..."), IconNames::DOCUMENT_IMPORT), 0535 KStandardGuiItem::cancel()); 0536 0537 switch (choice) { 0538 case (KMessageBox::Yes): 0539 note()->basket()->noteOpen(note()); 0540 break; 0541 case (KMessageBox::No): // Load from file 0542 cancel(); 0543 Global::bnpView->insertWizard(3); // 3 maps to m_actLoadFile 0544 break; 0545 case (KMessageBox::Cancel): 0546 cancel(); 0547 break; 0548 } 0549 } 0550 0551 /** class AnimationEditor: */ 0552 0553 AnimationEditor::AnimationEditor(AnimationContent *animationContent, QWidget *parent) 0554 : NoteEditor(animationContent) 0555 { 0556 int choice = KMessageBox::questionYesNo(parent, 0557 i18n("This animated image can not be edited here.\n" 0558 "Do you want to open it with an application that understands it?"), 0559 i18n("Edit Animation Note"), 0560 KStandardGuiItem::open(), 0561 KStandardGuiItem::cancel()); 0562 0563 if (choice == KMessageBox::Yes) 0564 note()->basket()->noteOpen(note()); 0565 } 0566 0567 /** class FileEditor: */ 0568 0569 FileEditor::FileEditor(FileContent *fileContent, QWidget *parent) 0570 : NoteEditor(fileContent) 0571 , m_fileContent(fileContent) 0572 { 0573 QLineEdit *lineEdit = new QLineEdit(parent); 0574 FocusWidgetFilter *filter = new FocusWidgetFilter(lineEdit); 0575 0576 QPalette palette; 0577 palette.setColor(lineEdit->backgroundRole(), note()->backgroundColor()); 0578 palette.setColor(lineEdit->foregroundRole(), note()->textColor()); 0579 lineEdit->setPalette(palette); 0580 0581 lineEdit->setFont(note()->font()); 0582 lineEdit->setText(m_fileContent->fileName()); 0583 lineEdit->selectAll(); 0584 setInlineEditor(lineEdit); 0585 connect(filter, SIGNAL(returnPressed()), this, SIGNAL(askValidation())); 0586 connect(filter, SIGNAL(escapePressed()), this, SIGNAL(askValidation())); 0587 connect(filter, SIGNAL(mouseEntered()), this, SIGNAL(mouseEnteredEditorWidget())); 0588 } 0589 0590 FileEditor::~FileEditor() 0591 { 0592 delete graphicsWidget()->widget(); 0593 } 0594 0595 void FileEditor::autoSave(bool toFileToo) 0596 { 0597 // FIXME: How to detect cancel? 0598 if (toFileToo && !lineEdit()->text().isEmpty() && m_fileContent->trySetFileName(lineEdit()->text())) { 0599 m_fileContent->setFileName(lineEdit()->text()); 0600 m_fileContent->setEdited(); 0601 } 0602 } 0603 0604 void FileEditor::validate() 0605 { 0606 autoSave(/*toFileToo=*/true); 0607 } 0608 0609 /** class LinkEditor: */ 0610 0611 LinkEditor::LinkEditor(LinkContent *linkContent, QWidget *parent) 0612 : NoteEditor(linkContent) 0613 { 0614 QPointer<LinkEditDialog> dialog = new LinkEditDialog(linkContent, parent); 0615 if (dialog->exec() == QDialog::Rejected) 0616 cancel(); 0617 if (linkContent->url().isEmpty() && linkContent->title().isEmpty()) 0618 setEmpty(); 0619 } 0620 0621 /** class CrossReferenceEditor: */ 0622 0623 CrossReferenceEditor::CrossReferenceEditor(CrossReferenceContent *crossReferenceContent, QWidget *parent) 0624 : NoteEditor(crossReferenceContent) 0625 { 0626 QPointer<CrossReferenceEditDialog> dialog = new CrossReferenceEditDialog(crossReferenceContent, parent); 0627 if (dialog->exec() == QDialog::Rejected) 0628 cancel(); 0629 if (crossReferenceContent->url().isEmpty() && crossReferenceContent->title().isEmpty()) 0630 setEmpty(); 0631 } 0632 0633 /** class LauncherEditor: */ 0634 0635 LauncherEditor::LauncherEditor(LauncherContent *launcherContent, QWidget *parent) 0636 : NoteEditor(launcherContent) 0637 { 0638 QPointer<LauncherEditDialog> dialog = new LauncherEditDialog(launcherContent, parent); 0639 if (dialog->exec() == QDialog::Rejected) 0640 cancel(); 0641 if (launcherContent->name().isEmpty() && launcherContent->exec().isEmpty()) 0642 setEmpty(); 0643 } 0644 0645 /** class ColorEditor: */ 0646 0647 ColorEditor::ColorEditor(ColorContent *colorContent, QWidget *parent) 0648 : NoteEditor(colorContent) 0649 { 0650 QPointer<QColorDialog> dialog = new QColorDialog(parent); 0651 dialog->setCurrentColor(colorContent->color()); 0652 dialog->setWindowTitle(i18n("Edit Color Note")); 0653 // dialog->setButtons(QDialog::Ok | QDialog::Cancel); 0654 if (dialog->exec() == QDialog::Accepted) { 0655 if (dialog->currentColor() != colorContent->color()) { 0656 colorContent->setColor(dialog->currentColor()); 0657 colorContent->setEdited(); 0658 } 0659 } else 0660 cancel(); 0661 0662 /* This code don't allow to set a caption to the dialog: 0663 QColor color = colorContent()->color(); 0664 color = QColorDialog::getColor(parent)==QDialog::Accepted&&color!=m_color); 0665 if ( color.isValid() ) { 0666 colorContent()->setColor(color); 0667 setEdited(); 0668 }*/ 0669 } 0670 0671 /** class UnknownEditor: */ 0672 0673 UnknownEditor::UnknownEditor(UnknownContent *unknownContent, QWidget *parent) 0674 : NoteEditor(unknownContent) 0675 { 0676 KMessageBox::information(parent, 0677 i18n("The type of this note is unknown and can not be edited here.\n" 0678 "You however can drag or copy the note into an application that understands it."), 0679 i18n("Edit Unknown Note")); 0680 } 0681 0682 /*********************************************************************/ 0683 0684 /** class LinkEditDialog: */ 0685 0686 LinkEditDialog::LinkEditDialog(LinkContent *contentNote, QWidget *parent /*, QKeyEvent *ke*/) 0687 : QDialog(parent) 0688 , m_noteContent(contentNote) 0689 { 0690 // QDialog options 0691 setWindowTitle(i18n("Edit Link Note")); 0692 0693 QWidget *mainWidget = new QWidget(this); 0694 QVBoxLayout *mainLayout = new QVBoxLayout; 0695 setLayout(mainLayout); 0696 mainLayout->addWidget(mainWidget); 0697 0698 setObjectName("EditLink"); 0699 setModal(true); 0700 0701 QWidget *page = new QWidget(this); 0702 mainLayout->addWidget(page); 0703 // QGridLayout *layout = new QGridLayout(page, /*nRows=*/4, /*nCols=*/2, /*margin=*/0, spacingHint()); 0704 QGridLayout *layout = new QGridLayout(page); 0705 mainLayout->addLayout(layout); 0706 0707 QWidget *wid1 = new QWidget(page); 0708 mainLayout->addWidget(wid1); 0709 QHBoxLayout *titleLay = new QHBoxLayout(wid1); 0710 m_title = new QLineEdit(m_noteContent->title(), wid1); 0711 m_autoTitle = new QPushButton(i18n("Auto"), wid1); 0712 m_autoTitle->setCheckable(true); 0713 m_autoTitle->setChecked(m_noteContent->autoTitle()); 0714 titleLay->addWidget(m_title); 0715 titleLay->addWidget(m_autoTitle); 0716 0717 QWidget *wid = new QWidget(page); 0718 mainLayout->addWidget(wid); 0719 QHBoxLayout *hLay = new QHBoxLayout(wid); 0720 m_icon = new KIconButton(wid); 0721 QLabel *label3 = new QLabel(page); 0722 mainLayout->addWidget(label3); 0723 label3->setText(i18n("&Icon:")); 0724 label3->setBuddy(m_icon); 0725 0726 if (m_noteContent->url().isEmpty()) { 0727 m_url = new KUrlRequester(QUrl(QString()), wid); 0728 m_url->setMode(KFile::File | KFile::ExistingOnly); 0729 } else { 0730 m_url = new KUrlRequester(m_noteContent->url().toDisplayString(), wid); 0731 m_url->setMode(KFile::File | KFile::ExistingOnly); 0732 } 0733 0734 if (m_noteContent->title().isEmpty()) { 0735 m_title->setText(QString()); 0736 } else { 0737 m_title->setText(m_noteContent->title()); 0738 } 0739 0740 QUrl filteredURL = NoteFactory::filteredURL(QUrl::fromUserInput(m_url->lineEdit()->text())); // KURIFilter::self()->filteredURI(KUrl(m_url->lineEdit()->text())); 0741 m_icon->setIconType(KIconLoader::NoGroup, KIconLoader::MimeType); 0742 m_icon->setIconSize(LinkLook::lookForURL(filteredURL)->iconSize()); 0743 m_autoIcon = new QPushButton(i18n("Auto"), wid); // Create before to know size here: 0744 /* Icon button: */ 0745 m_icon->setIcon(m_noteContent->icon()); 0746 int minSize = m_autoIcon->sizeHint().height(); 0747 // Make the icon button at least the same height than the other buttons for a better alignment (nicer to the eyes): 0748 if (m_icon->sizeHint().height() < minSize) 0749 m_icon->setFixedSize(minSize, minSize); 0750 else 0751 m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square 0752 /* Auto button: */ 0753 m_autoIcon->setCheckable(true); 0754 m_autoIcon->setChecked(m_noteContent->autoIcon()); 0755 hLay->addWidget(m_icon); 0756 hLay->addWidget(m_autoIcon); 0757 hLay->addStretch(); 0758 0759 m_url->lineEdit()->setMinimumWidth(m_url->lineEdit()->fontMetrics().maxWidth() * 20); 0760 m_title->setMinimumWidth(m_title->fontMetrics().maxWidth() * 20); 0761 0762 // m_url->setShowLocalProtocol(true); 0763 QLabel *label1 = new QLabel(page); 0764 mainLayout->addWidget(label1); 0765 label1->setText(i18n("Ta&rget:")); 0766 label1->setBuddy(m_url); 0767 0768 QLabel *label2 = new QLabel(page); 0769 mainLayout->addWidget(label2); 0770 label2->setText(i18n("&Title:")); 0771 label2->setBuddy(m_title); 0772 0773 layout->addWidget(label1, 0, 0, Qt::AlignVCenter); 0774 layout->addWidget(label2, 1, 0, Qt::AlignVCenter); 0775 layout->addWidget(label3, 2, 0, Qt::AlignVCenter); 0776 layout->addWidget(m_url, 0, 1, Qt::AlignVCenter); 0777 layout->addWidget(wid1, 1, 1, Qt::AlignVCenter); 0778 layout->addWidget(wid, 2, 1, Qt::AlignVCenter); 0779 0780 m_isAutoModified = false; 0781 connect(m_url, &KUrlRequester::textChanged, this, &LinkEditDialog::urlChanged); 0782 connect(m_title, &QLineEdit::textChanged, this, &LinkEditDialog::doNotAutoTitle); 0783 connect(m_icon, &KIconButton::iconChanged, this, &LinkEditDialog::doNotAutoIcon); 0784 connect(m_autoTitle, &QPushButton::clicked, this, [this](bool) { guessTitle(); }); 0785 connect(m_autoIcon, &QPushButton::clicked, this, [this](bool) { guessIcon(); }); 0786 0787 QWidget *stretchWidget = new QWidget(page); 0788 mainLayout->addWidget(stretchWidget); 0789 QSizePolicy policy(QSizePolicy::Fixed, QSizePolicy::Expanding); 0790 policy.setHorizontalStretch(1); 0791 policy.setVerticalStretch(255); 0792 stretchWidget->setSizePolicy(policy); // Make it fill ALL vertical space 0793 layout->addWidget(stretchWidget, 3, 1, Qt::AlignVCenter); 0794 0795 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0796 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0797 okButton->setDefault(true); 0798 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0799 connect(okButton, SIGNAL(clicked()), SLOT(slotOk())); 0800 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 0801 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0802 mainLayout->addWidget(buttonBox); 0803 0804 // urlChanged(QString()); 0805 0806 // if (ke) 0807 // qApp->postEvent(m_url->lineEdit(), ke); 0808 } 0809 0810 LinkEditDialog::~LinkEditDialog() 0811 { 0812 } 0813 0814 void LinkEditDialog::ensurePolished() 0815 { 0816 QDialog::ensurePolished(); 0817 if (m_url->lineEdit()->text().isEmpty()) { 0818 m_url->setFocus(); 0819 m_url->lineEdit()->end(false); 0820 } else { 0821 m_title->setFocus(); 0822 m_title->end(false); 0823 } 0824 } 0825 0826 void LinkEditDialog::urlChanged(const QString &) 0827 { 0828 m_isAutoModified = true; 0829 // guessTitle(); 0830 // guessIcon(); 0831 // Optimization (filter only once): 0832 QUrl filteredURL = NoteFactory::filteredURL(m_url->url()); // KURIFilter::self()->filteredURI(KUrl(m_url->url())); 0833 if (m_autoIcon->isChecked()) 0834 m_icon->setIcon(NoteFactory::iconForURL(filteredURL)); 0835 if (m_autoTitle->isChecked()) { 0836 m_title->setText(NoteFactory::titleForURL(filteredURL)); 0837 m_autoTitle->setChecked(true); // Because the setText() will disable it! 0838 } 0839 } 0840 0841 void LinkEditDialog::doNotAutoTitle(const QString &) 0842 { 0843 if (m_isAutoModified) 0844 m_isAutoModified = false; 0845 else 0846 m_autoTitle->setChecked(false); 0847 } 0848 0849 void LinkEditDialog::doNotAutoIcon(QString) 0850 { 0851 m_autoIcon->setChecked(false); 0852 } 0853 0854 void LinkEditDialog::guessIcon() 0855 { 0856 if (m_autoIcon->isChecked()) { 0857 QUrl filteredURL = NoteFactory::filteredURL(m_url->url()); // KURIFilter::self()->filteredURI(KUrl(m_url->url())); 0858 m_icon->setIcon(NoteFactory::iconForURL(filteredURL)); 0859 } 0860 } 0861 0862 void LinkEditDialog::guessTitle() 0863 { 0864 if (m_autoTitle->isChecked()) { 0865 QUrl filteredURL = NoteFactory::filteredURL(m_url->url()); // KURIFilter::self()->filteredURI(KUrl(m_url->url())); 0866 m_title->setText(NoteFactory::titleForURL(filteredURL)); 0867 m_autoTitle->setChecked(true); // Because the setText() will disable it! 0868 } 0869 } 0870 0871 void LinkEditDialog::slotOk() 0872 { 0873 QUrl filteredURL = NoteFactory::filteredURL(m_url->url()); // KURIFilter::self()->filteredURI(KUrl(m_url->url())); 0874 m_noteContent->setLink(filteredURL, m_title->text(), m_icon->icon(), m_autoTitle->isChecked(), m_autoIcon->isChecked()); 0875 m_noteContent->setEdited(); 0876 0877 /* Change icon size if link look have changed */ 0878 LinkLook *linkLook = LinkLook::lookForURL(filteredURL); 0879 QString icon = m_icon->icon(); // When we change size, icon isn't changed and keep it's old size 0880 m_icon->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); // Reset size policy 0881 m_icon->setIconSize(linkLook->iconSize()); // So I store it's name and reload it after size change ! 0882 m_icon->setIcon(icon); 0883 int minSize = m_autoIcon->sizeHint().height(); 0884 // Make the icon button at least the same height than the other buttons for a better alignment (nicer to the eyes): 0885 if (m_icon->sizeHint().height() < minSize) 0886 m_icon->setFixedSize(minSize, minSize); 0887 else 0888 m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square 0889 } 0890 0891 /** class CrossReferenceEditDialog: */ 0892 0893 CrossReferenceEditDialog::CrossReferenceEditDialog(CrossReferenceContent *contentNote, QWidget *parent /*, QKeyEvent *ke*/) 0894 : QDialog(parent) 0895 , m_noteContent(contentNote) 0896 { 0897 QVBoxLayout *mainLayout = new QVBoxLayout; 0898 setLayout(mainLayout); 0899 0900 // QDialog options 0901 setWindowTitle(i18n("Edit Cross Reference")); 0902 0903 QWidget *page = new QWidget(this); 0904 mainLayout->addWidget(page); 0905 QWidget *wid = new QWidget(page); 0906 mainLayout->addWidget(wid); 0907 0908 QGridLayout *layout = new QGridLayout(page); 0909 mainLayout->addLayout(layout); 0910 0911 m_targetBasket = new KComboBox(wid); 0912 this->generateBasketList(m_targetBasket); 0913 0914 if (m_noteContent->url().isEmpty()) { 0915 BasketListViewItem *item = Global::bnpView->topLevelItem(0); 0916 m_noteContent->setCrossReference(QUrl::fromUserInput(item->data(0, Qt::UserRole).toString()), m_targetBasket->currentText(), "edit-copy"); 0917 this->urlChanged(0); 0918 } else { 0919 QString url = m_noteContent->url().url(); 0920 // cannot use findData because I'm using a StringList and I don't have the second 0921 // piece of data to make find work. 0922 for (int i = 0; i < m_targetBasket->count(); ++i) { 0923 if (url == m_targetBasket->itemData(i, Qt::UserRole).toStringList().first()) { 0924 m_targetBasket->setCurrentIndex(i); 0925 break; 0926 } 0927 } 0928 } 0929 0930 QLabel *label1 = new QLabel(page); 0931 mainLayout->addWidget(label1); 0932 label1->setText(i18n("Ta&rget:")); 0933 label1->setBuddy(m_targetBasket); 0934 0935 layout->addWidget(label1, 0, 0, Qt::AlignVCenter); 0936 layout->addWidget(m_targetBasket, 0, 1, Qt::AlignVCenter); 0937 0938 connect(m_targetBasket, SIGNAL(activated(int)), this, SLOT(urlChanged(int))); 0939 0940 QWidget *stretchWidget = new QWidget(page); 0941 mainLayout->addWidget(stretchWidget); 0942 QSizePolicy policy(QSizePolicy::Fixed, QSizePolicy::Expanding); 0943 policy.setHorizontalStretch(1); 0944 policy.setVerticalStretch(255); 0945 stretchWidget->setSizePolicy(policy); // Make it fill ALL vertical space 0946 layout->addWidget(stretchWidget, 3, 1, Qt::AlignVCenter); 0947 0948 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0949 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0950 okButton->setDefault(true); 0951 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0952 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 0953 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0954 mainLayout->addWidget(buttonBox); 0955 setObjectName("EditCrossReference"); 0956 setModal(true); 0957 connect(okButton, SIGNAL(clicked()), SLOT(slotOk())); 0958 } 0959 0960 CrossReferenceEditDialog::~CrossReferenceEditDialog() 0961 { 0962 } 0963 0964 void CrossReferenceEditDialog::urlChanged(const int index) 0965 { 0966 if (m_targetBasket) 0967 m_noteContent->setCrossReference( 0968 QUrl::fromUserInput(m_targetBasket->itemData(index, Qt::UserRole).toStringList().first()), m_targetBasket->currentText().trimmed(), m_targetBasket->itemData(index, Qt::UserRole).toStringList().last()); 0969 } 0970 0971 void CrossReferenceEditDialog::slotOk() 0972 { 0973 m_noteContent->setEdited(); 0974 } 0975 0976 void CrossReferenceEditDialog::generateBasketList(KComboBox *targetList, BasketListViewItem *item, int indent) 0977 { 0978 if (!item) { // include ALL top level items and their children. 0979 for (int i = 0; i < Global::bnpView->topLevelItemCount(); ++i) 0980 this->generateBasketList(targetList, Global::bnpView->topLevelItem(i)); 0981 } else { 0982 BasketScene *bv = item->basket(); 0983 0984 // TODO: add some fancy deco stuff to make it look like a tree list. 0985 QString pad; 0986 QString text = item->text(0); // user text 0987 0988 text.prepend(pad.fill(' ', indent * 2)); 0989 0990 // create the link text 0991 QString link = "basket://"; 0992 link.append(bv->folderName().toLower()); // unique ref. 0993 QStringList data; 0994 data.append(link); 0995 data.append(bv->icon()); 0996 0997 targetList->addItem(item->icon(0), text, QVariant(data)); 0998 0999 int subBasketCount = item->childCount(); 1000 if (subBasketCount > 0) { 1001 indent++; 1002 for (int i = 0; i < subBasketCount; ++i) { 1003 this->generateBasketList(targetList, (BasketListViewItem *)item->child(i), indent); 1004 } 1005 } 1006 } 1007 } 1008 1009 /** class LauncherEditDialog: */ 1010 1011 LauncherEditDialog::LauncherEditDialog(LauncherContent *contentNote, QWidget *parent) 1012 : QDialog(parent) 1013 , m_noteContent(contentNote) 1014 { 1015 QVBoxLayout *mainLayout = new QVBoxLayout; 1016 setLayout(mainLayout); 1017 1018 // QDialog options 1019 setWindowTitle(i18n("Edit Launcher Note")); 1020 1021 setObjectName("EditLauncher"); 1022 setModal(true); 1023 1024 QWidget *page = new QWidget(this); 1025 mainLayout->addWidget(page); 1026 1027 // QGridLayout *layout = new QGridLayout(page, /*nRows=*/4, /*nCols=*/2, /*margin=*/0, spacingHint()); 1028 QGridLayout *layout = new QGridLayout(page); 1029 mainLayout->addLayout(layout); 1030 1031 KService service(contentNote->fullPath()); 1032 1033 m_command = new RunCommandRequester(service.exec(), i18n("Choose a command to run:"), page); 1034 mainLayout->addWidget(m_command); 1035 m_name = new QLineEdit(service.name(), page); 1036 mainLayout->addWidget(m_name); 1037 1038 QWidget *wid = new QWidget(page); 1039 mainLayout->addWidget(wid); 1040 QHBoxLayout *hLay = new QHBoxLayout(wid); 1041 m_icon = new KIconButton(wid); 1042 1043 QLabel *label = new QLabel(page); 1044 mainLayout->addWidget(label); 1045 label->setText(i18n("&Icon:")); 1046 label->setBuddy(m_icon); 1047 1048 m_icon->setIconType(KIconLoader::NoGroup, KIconLoader::Application); 1049 m_icon->setIconSize(LinkLook::launcherLook->iconSize()); 1050 QPushButton *guessButton = new QPushButton(i18n("&Guess"), wid); 1051 /* Icon button: */ 1052 m_icon->setIcon(service.icon()); 1053 int minSize = guessButton->sizeHint().height(); 1054 // Make the icon button at least the same height than the other buttons for a better alignment (nicer to the eyes): 1055 if (m_icon->sizeHint().height() < minSize) 1056 m_icon->setFixedSize(minSize, minSize); 1057 else 1058 m_icon->setFixedSize(m_icon->sizeHint().height(), m_icon->sizeHint().height()); // Make it square 1059 /* Guess button: */ 1060 hLay->addWidget(m_icon); 1061 hLay->addWidget(guessButton); 1062 hLay->addStretch(); 1063 1064 m_command->lineEdit()->setMinimumWidth(m_command->lineEdit()->fontMetrics().maxWidth() * 20); 1065 1066 QLabel *label1 = new QLabel(page); 1067 mainLayout->addWidget(label1); 1068 label1->setText(i18n("Comman&d:")); 1069 label1->setBuddy(m_command->lineEdit()); 1070 1071 QLabel *label2 = new QLabel(page); 1072 mainLayout->addWidget(label2); 1073 label2->setText(i18n("&Name:")); 1074 label2->setBuddy(m_name); 1075 1076 layout->addWidget(label1, 0, 0, Qt::AlignVCenter); 1077 layout->addWidget(label2, 1, 0, Qt::AlignVCenter); 1078 layout->addWidget(label, 2, 0, Qt::AlignVCenter); 1079 layout->addWidget(m_command, 0, 1, Qt::AlignVCenter); 1080 layout->addWidget(m_name, 1, 1, Qt::AlignVCenter); 1081 layout->addWidget(wid, 2, 1, Qt::AlignVCenter); 1082 1083 QWidget *stretchWidget = new QWidget(page); 1084 mainLayout->addWidget(stretchWidget); 1085 1086 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 1087 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 1088 okButton->setDefault(true); 1089 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 1090 connect(okButton, SIGNAL(clicked()), SLOT(slotOk())); 1091 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 1092 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 1093 mainLayout->addWidget(buttonBox); 1094 1095 QSizePolicy policy(QSizePolicy::Fixed, QSizePolicy::Expanding); 1096 policy.setHorizontalStretch(1); 1097 policy.setVerticalStretch(255); 1098 stretchWidget->setSizePolicy(policy); // Make it fill ALL vertical space 1099 1100 layout->addWidget(stretchWidget, 3, 1, Qt::AlignVCenter); 1101 1102 connect(guessButton, SIGNAL(clicked()), this, SLOT(guessIcon())); 1103 } 1104 1105 LauncherEditDialog::~LauncherEditDialog() 1106 { 1107 } 1108 1109 void LauncherEditDialog::ensurePolished() 1110 { 1111 QDialog::ensurePolished(); 1112 if (m_command->runCommand().isEmpty()) { 1113 m_command->lineEdit()->setFocus(); 1114 m_command->lineEdit()->end(false); 1115 } else { 1116 m_name->setFocus(); 1117 m_name->end(false); 1118 } 1119 } 1120 1121 void LauncherEditDialog::slotOk() 1122 { 1123 // TODO: Remember if a string has been modified AND IS DIFFERENT FROM THE 1124 // ORIGINAL! 1125 1126 KDesktopFile dtFile(m_noteContent->fullPath()); 1127 KConfigGroup grp = dtFile.desktopGroup(); 1128 grp.writeEntry("Exec", m_command->runCommand()); 1129 grp.writeEntry("Name", m_name->text()); 1130 grp.writeEntry("Icon", m_icon->icon()); 1131 1132 // Just for faster feedback: conf object will save to disk (and then 1133 // m_note->loadContent() called) 1134 m_noteContent->setLauncher(m_name->text(), m_icon->icon(), m_command->runCommand()); 1135 m_noteContent->setEdited(); 1136 } 1137 1138 void LauncherEditDialog::guessIcon() 1139 { 1140 m_icon->setIcon(NoteFactory::iconForCommand(m_command->runCommand())); 1141 } 1142 1143 /** class InlineEditors: */ 1144 1145 InlineEditors::InlineEditors() 1146 { 1147 } 1148 1149 InlineEditors::~InlineEditors() 1150 { 1151 } 1152 1153 InlineEditors *InlineEditors::instance() 1154 { 1155 static InlineEditors *instance = nullptr; 1156 if (!instance) 1157 instance = new InlineEditors(); 1158 return instance; 1159 } 1160 1161 void InlineEditors::initToolBars(KActionCollection *ac) 1162 { 1163 QFont defaultFont; 1164 QColor textColor = (Global::bnpView && Global::bnpView->currentBasket() ? Global::bnpView->currentBasket()->textColor() : palette().color(QPalette::Text)); 1165 1166 // NOTE: currently it is NULL since initToolBars is called early. Could use different way to get MainWindow pointer from main 1167 KMainWindow *parent = Global::activeMainWindow(); 1168 1169 // Init the RichTextEditor Toolbar: 1170 richTextFont = new QFontComboBox(Global::activeMainWindow()); 1171 focusWidgetFilter = new FocusWidgetFilter(richTextFont); 1172 richTextFont->setFixedWidth(richTextFont->sizeHint().width() * 2 / 3); 1173 richTextFont->setCurrentFont(defaultFont.family()); 1174 1175 QWidgetAction *action = new QWidgetAction(parent); 1176 ac->addAction("richtext_font", action); 1177 action->setDefaultWidget(richTextFont); 1178 action->setText(i18n("Font")); 1179 ac->setDefaultShortcut(action, Qt::Key_F6); 1180 1181 richTextFontSize = new FontSizeCombo(/*rw=*/true, Global::activeMainWindow()); 1182 richTextFontSize->setFontSize(defaultFont.pointSize()); 1183 action = new QWidgetAction(parent); 1184 ac->addAction("richtext_font_size", action); 1185 action->setDefaultWidget(richTextFontSize); 1186 action->setText(i18n("Font Size")); 1187 ac->setDefaultShortcut(action, Qt::Key_F7); 1188 1189 richTextColor = new KColorCombo(Global::activeMainWindow()); 1190 richTextColor->installEventFilter(focusWidgetFilter); 1191 richTextColor->setFixedWidth(richTextColor->sizeHint().height() * 2); 1192 richTextColor->setColor(textColor); 1193 action = new QWidgetAction(parent); 1194 ac->addAction("richtext_color", action); 1195 action->setDefaultWidget(richTextColor); 1196 action->setText(i18n("Color")); 1197 1198 KToggleAction *ta = nullptr; 1199 ta = new KToggleAction(ac); 1200 ac->addAction("richtext_bold", ta); 1201 ta->setText(i18n("Bold")); 1202 ta->setIcon(QIcon::fromTheme("format-text-bold")); 1203 ac->setDefaultShortcut(ta, QKeySequence("Ctrl+B")); 1204 richTextBold = ta; 1205 1206 ta = new KToggleAction(ac); 1207 ac->addAction("richtext_italic", ta); 1208 ta->setText(i18n("Italic")); 1209 ta->setIcon(QIcon::fromTheme("format-text-italic")); 1210 ac->setDefaultShortcut(ta, QKeySequence("Ctrl+I")); 1211 richTextItalic = ta; 1212 1213 ta = new KToggleAction(ac); 1214 ac->addAction("richtext_underline", ta); 1215 ta->setText(i18n("Underline")); 1216 ta->setIcon(QIcon::fromTheme("format-text-underline")); 1217 ac->setDefaultShortcut(ta, QKeySequence("Ctrl+U")); 1218 richTextUnderline = ta; 1219 1220 #if 0 1221 ta = new KToggleAction(ac); 1222 ac->addAction("richtext_super", ta); 1223 ta->setText(i18n("Superscript")); 1224 ta->setIcon(QIcon::fromTheme("text_super")); 1225 richTextSuper = ta; 1226 1227 ta = new KToggleAction(ac); 1228 ac->addAction("richtext_sub", ta); 1229 ta->setText(i18n("Subscript")); 1230 ta->setIcon(QIcon::fromTheme("text_sub")); 1231 richTextSub = ta; 1232 #endif 1233 1234 ta = new KToggleAction(ac); 1235 ac->addAction("richtext_left", ta); 1236 ta->setText(i18n("Align Left")); 1237 ta->setIcon(QIcon::fromTheme("format-justify-left")); 1238 richTextLeft = ta; 1239 1240 ta = new KToggleAction(ac); 1241 ac->addAction("richtext_center", ta); 1242 ta->setText(i18n("Centered")); 1243 ta->setIcon(QIcon::fromTheme("format-justify-center")); 1244 richTextCenter = ta; 1245 1246 ta = new KToggleAction(ac); 1247 ac->addAction("richtext_right", ta); 1248 ta->setText(i18n("Align Right")); 1249 ta->setIcon(QIcon::fromTheme("format-justify-right")); 1250 richTextRight = ta; 1251 1252 ta = new KToggleAction(ac); 1253 ac->addAction("richtext_block", ta); 1254 ta->setText(i18n("Justified")); 1255 ta->setIcon(QIcon::fromTheme("format-justify-fill")); 1256 richTextJustified = ta; 1257 1258 QActionGroup *alignmentGroup = new QActionGroup(this); 1259 alignmentGroup->addAction(richTextLeft); 1260 alignmentGroup->addAction(richTextCenter); 1261 alignmentGroup->addAction(richTextRight); 1262 alignmentGroup->addAction(richTextJustified); 1263 1264 ta = new KToggleAction(ac); 1265 ac->addAction("richtext_undo", ta); 1266 ta->setText(i18n("Undo")); 1267 ta->setIcon(QIcon::fromTheme("edit-undo")); 1268 richTextUndo = ta; 1269 1270 ta = new KToggleAction(ac); 1271 ac->addAction("richtext_redo", ta); 1272 ta->setText(i18n("Redo")); 1273 ta->setIcon(QIcon::fromTheme("edit-redo")); 1274 richTextRedo = ta; 1275 1276 disableRichTextToolBar(); 1277 } 1278 1279 KToolBar *InlineEditors::richTextToolBar() 1280 { 1281 if (Global::activeMainWindow()) { 1282 Global::activeMainWindow()->toolBar(); // Make sure we create the main toolbar FIRST, so it will be on top of the edit toolbar! 1283 return Global::activeMainWindow()->toolBar("richTextEditToolBar"); 1284 } else 1285 return nullptr; 1286 } 1287 1288 void InlineEditors::enableRichTextToolBar() 1289 { 1290 richTextFont->setEnabled(true); 1291 richTextFontSize->setEnabled(true); 1292 richTextColor->setEnabled(true); 1293 richTextBold->setEnabled(true); 1294 richTextItalic->setEnabled(true); 1295 richTextUnderline->setEnabled(true); 1296 richTextLeft->setEnabled(true); 1297 richTextCenter->setEnabled(true); 1298 richTextRight->setEnabled(true); 1299 richTextJustified->setEnabled(true); 1300 richTextUndo->setEnabled(true); 1301 richTextRedo->setEnabled(true); 1302 } 1303 1304 void InlineEditors::disableRichTextToolBar() 1305 { 1306 disconnect(richTextFont); 1307 disconnect(richTextFontSize); 1308 disconnect(richTextColor); 1309 disconnect(richTextBold); 1310 disconnect(richTextItalic); 1311 disconnect(richTextUnderline); 1312 disconnect(richTextLeft); 1313 disconnect(richTextCenter); 1314 disconnect(richTextRight); 1315 disconnect(richTextJustified); 1316 disconnect(richTextUndo); 1317 disconnect(richTextRedo); 1318 1319 richTextFont->setEnabled(false); 1320 richTextFontSize->setEnabled(false); 1321 richTextColor->setEnabled(false); 1322 richTextBold->setEnabled(false); 1323 richTextItalic->setEnabled(false); 1324 richTextUnderline->setEnabled(false); 1325 richTextLeft->setEnabled(false); 1326 richTextCenter->setEnabled(false); 1327 richTextRight->setEnabled(false); 1328 richTextJustified->setEnabled(false); 1329 richTextUndo->setEnabled(false); 1330 richTextRedo->setEnabled(false); 1331 1332 // Return to a "proper" state: 1333 QFont defaultFont; 1334 QColor textColor = (Global::bnpView && Global::bnpView->currentBasket() ? Global::bnpView->currentBasket()->textColor() : palette().color(QPalette::Text)); 1335 richTextFont->setCurrentFont(defaultFont.family()); 1336 richTextFontSize->setFontSize(defaultFont.pointSize()); 1337 richTextColor->setColor(textColor); 1338 richTextBold->setChecked(false); 1339 richTextItalic->setChecked(false); 1340 richTextUnderline->setChecked(false); 1341 richTextLeft->setChecked(false); 1342 richTextCenter->setChecked(false); 1343 richTextRight->setChecked(false); 1344 richTextJustified->setChecked(false); 1345 } 1346 1347 QPalette InlineEditors::palette() const 1348 { 1349 return qApp->palette(); 1350 } 1351 1352 #include "moc_noteedit.cpp"