File indexing completed on 2023-09-24 06:04:30
0001 /** 0002 * SPDX-FileCopyrightText: (C) 2005 Sébastien Laoût <slaout@linux62.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "tagsedit.h" 0008 0009 #include <QAction> 0010 #include <QApplication> 0011 #include <QCheckBox> 0012 #include <QDialogButtonBox> 0013 #include <QFontComboBox> 0014 #include <QGridLayout> 0015 #include <QGroupBox> 0016 #include <QHBoxLayout> 0017 #include <QHeaderView> //For m_tags->header() 0018 #include <QLabel> 0019 #include <QLineEdit> 0020 #include <QLocale> 0021 #include <QPushButton> 0022 #include <QVBoxLayout> 0023 #include <QtCore/QEvent> 0024 #include <QtCore/QList> 0025 #include <QtCore/QTimer> 0026 #include <QtGui/QKeyEvent> 0027 #include <QtGui/QMouseEvent> 0028 #include <QtGui/QPainter> 0029 0030 #include <KConfigGroup> 0031 #include <KIconButton> 0032 #include <KIconLoader> 0033 #include <KLocalizedString> 0034 #include <KMessageBox> 0035 #include <KSeparator> 0036 #include <KShortcutWidget> 0037 0038 #include "bnpview.h" 0039 #include "global.h" 0040 #include "kcolorcombo2.h" 0041 #include "tag.h" 0042 #include "variouswidgets.h" //For FontSizeCombo 0043 0044 /** class StateCopy: */ 0045 0046 StateCopy::StateCopy(State *old /* = 0*/) 0047 { 0048 oldState = old; 0049 newState = new State(); 0050 if (oldState) 0051 oldState->copyTo(newState); 0052 } 0053 0054 StateCopy::~StateCopy() 0055 { 0056 delete newState; 0057 } 0058 0059 void StateCopy::copyBack() 0060 { 0061 } 0062 0063 /** class TagCopy: */ 0064 0065 TagCopy::TagCopy(Tag *old /* = 0*/) 0066 { 0067 oldTag = old; 0068 newTag = new Tag(); 0069 if (oldTag) 0070 oldTag->copyTo(newTag); 0071 0072 if (old) 0073 for (State::List::iterator it = old->states().begin(); it != old->states().end(); ++it) 0074 stateCopies.append(new StateCopy(*it)); 0075 else 0076 stateCopies.append(new StateCopy()); 0077 } 0078 0079 TagCopy::~TagCopy() 0080 { 0081 delete newTag; 0082 } 0083 0084 void TagCopy::copyBack() 0085 { 0086 } 0087 0088 bool TagCopy::isMultiState() 0089 { 0090 return (stateCopies.count() > 1); 0091 } 0092 0093 /** class TagListViewItem: */ 0094 0095 TagListViewItem::TagListViewItem(QTreeWidget *parent, TagCopy *tagCopy) 0096 : QTreeWidgetItem(parent) 0097 , m_tagCopy(tagCopy) 0098 , m_stateCopy(nullptr) 0099 { 0100 setText(0, tagCopy->newTag->name()); 0101 } 0102 0103 TagListViewItem::TagListViewItem(QTreeWidgetItem *parent, TagCopy *tagCopy) 0104 : QTreeWidgetItem(parent) 0105 , m_tagCopy(tagCopy) 0106 , m_stateCopy(nullptr) 0107 { 0108 setText(0, tagCopy->newTag->name()); 0109 } 0110 0111 TagListViewItem::TagListViewItem(QTreeWidget *parent, QTreeWidgetItem *after, TagCopy *tagCopy) 0112 : QTreeWidgetItem(parent, after) 0113 , m_tagCopy(tagCopy) 0114 , m_stateCopy(nullptr) 0115 { 0116 setText(0, tagCopy->newTag->name()); 0117 } 0118 0119 TagListViewItem::TagListViewItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, TagCopy *tagCopy) 0120 : QTreeWidgetItem(parent, after) 0121 , m_tagCopy(tagCopy) 0122 , m_stateCopy(nullptr) 0123 { 0124 setText(0, tagCopy->newTag->name()); 0125 } 0126 0127 /* */ 0128 0129 TagListViewItem::TagListViewItem(QTreeWidget *parent, StateCopy *stateCopy) 0130 : QTreeWidgetItem(parent) 0131 , m_tagCopy(nullptr) 0132 , m_stateCopy(stateCopy) 0133 { 0134 setText(0, stateCopy->newState->name()); 0135 } 0136 0137 TagListViewItem::TagListViewItem(QTreeWidgetItem *parent, StateCopy *stateCopy) 0138 : QTreeWidgetItem(parent) 0139 , m_tagCopy(nullptr) 0140 , m_stateCopy(stateCopy) 0141 { 0142 setText(0, stateCopy->newState->name()); 0143 } 0144 0145 TagListViewItem::TagListViewItem(QTreeWidget *parent, QTreeWidgetItem *after, StateCopy *stateCopy) 0146 : QTreeWidgetItem(parent, after) 0147 , m_tagCopy(nullptr) 0148 , m_stateCopy(stateCopy) 0149 { 0150 setText(0, stateCopy->newState->name()); 0151 } 0152 0153 TagListViewItem::TagListViewItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, StateCopy *stateCopy) 0154 : QTreeWidgetItem(parent, after) 0155 , m_tagCopy(nullptr) 0156 , m_stateCopy(stateCopy) 0157 { 0158 setText(0, stateCopy->newState->name()); 0159 } 0160 0161 /* */ 0162 0163 TagListViewItem::~TagListViewItem() 0164 { 0165 } 0166 0167 TagListViewItem *TagListViewItem::lastChild() 0168 { 0169 if (childCount() <= 0) 0170 return nullptr; 0171 return (TagListViewItem *)child(childCount() - 1); 0172 } 0173 0174 bool TagListViewItem::isEmblemObligatory() 0175 { 0176 return m_stateCopy != nullptr; // It's a state of a multi-state 0177 } 0178 0179 TagListViewItem *TagListViewItem::prevSibling() 0180 { 0181 TagListViewItem *item = this; 0182 int idx = 0; 0183 if (!parent()) { 0184 idx = treeWidget()->indexOfTopLevelItem(item); 0185 if (idx <= 0) 0186 return nullptr; 0187 return (TagListViewItem *)treeWidget()->topLevelItem(idx - 1); 0188 } else { 0189 idx = parent()->indexOfChild(item); 0190 if (idx <= 0) 0191 return nullptr; 0192 return (TagListViewItem *)parent()->child(idx - 1); 0193 } 0194 } 0195 0196 TagListViewItem *TagListViewItem::nextSibling() 0197 { 0198 TagListViewItem *item = this; 0199 int idx = 0; 0200 if (!parent()) { 0201 idx = treeWidget()->indexOfTopLevelItem(item); 0202 if (idx >= treeWidget()->topLevelItemCount()) 0203 return nullptr; 0204 return (TagListViewItem *)treeWidget()->topLevelItem(idx + 1); 0205 } else { 0206 idx = parent()->indexOfChild(item); 0207 if (idx >= parent()->childCount()) 0208 return nullptr; 0209 return (TagListViewItem *)parent()->child(idx + 1); 0210 } 0211 } 0212 0213 TagListViewItem *TagListViewItem::parent() const 0214 { 0215 return (TagListViewItem *)QTreeWidgetItem::parent(); 0216 } 0217 0218 // TODO: TagListViewItem:: 0219 int TAG_ICON_SIZE = 16; 0220 int TAG_MARGIN = 1; 0221 0222 int TagListViewItem::width(const QFontMetrics & /* fontMetrics */, const QTreeWidget * /*listView*/, int /* column */) const 0223 { 0224 return treeWidget()->width(); 0225 } 0226 0227 void TagListViewItem::setup() 0228 { 0229 QString text = (m_tagCopy ? m_tagCopy->newTag->name() : m_stateCopy->newState->name()); 0230 State *state = (m_tagCopy ? m_tagCopy->stateCopies[0]->newState : m_stateCopy->newState); 0231 0232 QFont font = state->font(treeWidget()->font()); 0233 0234 setText(0, text); 0235 0236 QBrush brush; 0237 0238 bool withIcon = m_stateCopy || (m_tagCopy && !m_tagCopy->isMultiState()); 0239 brush.setColor(isSelected() ? qApp->palette().color(QPalette::Highlight) 0240 : (withIcon && state->backgroundColor().isValid() ? state->backgroundColor() : treeWidget()->viewport()->palette().color(treeWidget()->viewport()->backgroundRole()))); 0241 setBackground(1, brush); 0242 } 0243 0244 /** class TagListView: */ 0245 0246 TagListView::TagListView(QWidget *parent) 0247 : QTreeWidget(parent) 0248 { 0249 setItemDelegate(new TagListDelegate); 0250 } 0251 0252 TagListView::~TagListView() 0253 { 0254 } 0255 0256 void TagListView::keyPressEvent(QKeyEvent *event) 0257 { 0258 if (event->key() == Qt::Key_Delete) 0259 Q_EMIT deletePressed(); 0260 else if (event->key() != Qt::Key_Left || (currentItem() && currentItem()->parent())) 0261 // Do not allow to open/close first-level items 0262 QTreeWidget::keyPressEvent(event); 0263 } 0264 0265 void TagListView::mouseDoubleClickEvent(QMouseEvent *event) 0266 { 0267 // Ignore this event! Do not open/close first-level items! 0268 0269 // But trigger edit (change focus to name) when double-click an item: 0270 if (itemAt(event->pos()) != nullptr) 0271 Q_EMIT doubleClickedItem(); 0272 } 0273 0274 void TagListView::mousePressEvent(QMouseEvent *event) 0275 { 0276 // When clicking on an empty space, QListView would unselect the current item! We forbid that! 0277 if (itemAt(event->pos()) != nullptr) 0278 QTreeWidget::mousePressEvent(event); 0279 } 0280 0281 void TagListView::mouseReleaseEvent(QMouseEvent *event) 0282 { 0283 // When clicking on an empty space, QListView would unselect the current item! We forbid that! 0284 if (itemAt(event->pos()) != nullptr) 0285 QTreeWidget::mouseReleaseEvent(event); 0286 } 0287 0288 TagListViewItem *TagListView::currentItem() const 0289 { 0290 return (TagListViewItem *)QTreeWidget::currentItem(); 0291 } 0292 0293 TagListViewItem *TagListView::firstChild() const 0294 { 0295 if (topLevelItemCount() <= 0) 0296 return nullptr; 0297 return (TagListViewItem *)topLevelItem(0); 0298 } 0299 0300 TagListViewItem *TagListView::lastItem() const 0301 { 0302 if (topLevelItemCount() <= 0) 0303 return nullptr; 0304 return (TagListViewItem *)topLevelItem(topLevelItemCount() - 1); 0305 } 0306 0307 /** class TagsEditDialog: */ 0308 0309 TagsEditDialog::TagsEditDialog(QWidget *parent, State *stateToEdit, bool addNewTag) 0310 : QDialog(parent) 0311 , m_loading(false) 0312 { 0313 // QDialog options 0314 setWindowTitle(i18n("Customize Tags")); 0315 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0316 QWidget *mainWidget = new QWidget(this); 0317 QVBoxLayout *mainLayout = new QVBoxLayout; 0318 setLayout(mainLayout); 0319 mainLayout->addWidget(mainWidget); 0320 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0321 okButton->setDefault(true); 0322 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0323 connect(buttonBox, &QDialogButtonBox::accepted, this, &TagsEditDialog::accept); 0324 connect(buttonBox, &QDialogButtonBox::rejected, this, &TagsEditDialog::reject); 0325 mainLayout->addWidget(buttonBox); 0326 okButton->setDefault(true); 0327 setObjectName("CustomizeTags"); 0328 0329 QHBoxLayout *layout = new QHBoxLayout(mainWidget); 0330 0331 /* Left part: */ 0332 0333 QPushButton *newTag = new QPushButton(i18n("Ne&w Tag"), mainWidget); 0334 QPushButton *newState = new QPushButton(i18n("New St&ate"), mainWidget); 0335 0336 connect(newTag, &QPushButton::clicked, this, &TagsEditDialog::newTag); 0337 connect(newState, &QPushButton::clicked, this, &TagsEditDialog::newState); 0338 0339 m_tags = new TagListView(mainWidget); 0340 m_tags->header()->hide(); 0341 m_tags->setRootIsDecorated(false); 0342 // m_tags->addColumn(QString()); 0343 // m_tags->setSorting(-1); // Sort column -1, so disabled sorting 0344 // m_tags->setResizeMode(QTreeWidget::LastColumn); 0345 0346 m_tags->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0347 0348 m_moveUp = new QPushButton(mainWidget); 0349 KGuiItem::assign(m_moveUp, KGuiItem(QString(), "arrow-up")); 0350 m_moveDown = new QPushButton(mainWidget); 0351 KGuiItem::assign(m_moveDown, KGuiItem(QString(), "arrow-down")); 0352 m_deleteTag = new QPushButton(mainWidget); 0353 KGuiItem::assign(m_deleteTag, KGuiItem(QString(), "edit-delete")); 0354 0355 m_moveUp->setToolTip(i18n("Move Up (Ctrl+Shift+Up)")); 0356 m_moveDown->setToolTip(i18n("Move Down (Ctrl+Shift+Down)")); 0357 m_deleteTag->setToolTip(i18n("Delete")); 0358 0359 connect(m_moveUp, &QPushButton::clicked, this, &TagsEditDialog::moveUp); 0360 connect(m_moveDown, &QPushButton::clicked, this, &TagsEditDialog::moveDown); 0361 connect(m_deleteTag, &QPushButton::clicked, this, &TagsEditDialog::deleteTag); 0362 0363 QHBoxLayout *topLeftLayout = new QHBoxLayout; 0364 topLeftLayout->addWidget(m_moveUp); 0365 topLeftLayout->addWidget(m_moveDown); 0366 topLeftLayout->addWidget(m_deleteTag); 0367 0368 QVBoxLayout *leftLayout = new QVBoxLayout; 0369 leftLayout->addWidget(newTag); 0370 leftLayout->addWidget(newState); 0371 leftLayout->addWidget(m_tags); 0372 leftLayout->addLayout(topLeftLayout); 0373 0374 layout->addLayout(leftLayout); 0375 0376 /* Right part: */ 0377 0378 QWidget *rightWidget = new QWidget(mainWidget); 0379 0380 m_tagBox = new QGroupBox(i18n("Tag"), rightWidget); 0381 m_tagBoxLayout = new QHBoxLayout; 0382 m_tagBox->setLayout(m_tagBoxLayout); 0383 0384 QWidget *tagWidget = new QWidget; 0385 m_tagBoxLayout->addWidget(tagWidget); 0386 0387 m_tagName = new QLineEdit(tagWidget); 0388 QLabel *tagNameLabel = new QLabel(i18n("&Name:"), tagWidget); 0389 tagNameLabel->setBuddy(m_tagName); 0390 0391 m_shortcut = new KShortcutWidget(tagWidget); 0392 m_removeShortcut = new QPushButton(i18nc("Remove tag shortcut", "&Remove"), tagWidget); 0393 QLabel *shortcutLabel = new QLabel(i18n("S&hortcut:"), tagWidget); 0394 shortcutLabel->setBuddy(m_shortcut); 0395 //connect(m_shortcut, &KShortcutWidget::shortcutChanged, this, &TagsEditDialog::capturedShortcut); 0396 connect(m_removeShortcut, &QPushButton::clicked, this, &TagsEditDialog::removeShortcut); 0397 0398 m_inherit = new QCheckBox(i18n("&Inherited by new sibling notes"), tagWidget); 0399 0400 m_allowCrossRefernce = new QCheckBox(i18n("Allow Cross Reference Links"), tagWidget); 0401 0402 HelpLabel *allowCrossReferenceHelp = new HelpLabel(i18n("What does this do?"), 0403 "<p>" + i18n("This option will enable you to type a cross reference link directly into a text note. Cross Reference links can have the following syntax:") + "</p>" + "<p>" + 0404 i18n("From the top of the tree (Absolute path):") + "<br />" + i18n("[[/top level item/child|optional title]]") + "<p>" + "<p>" + i18n("Relative to the current basket:") + 0405 "<br />" + i18n("[[../sibling|optional title]]") + "<br />" + i18n("[[child|optional title]]") + "<br />" + i18n("[[./child|optional title]]") + "<p>"+ 0406 "<p>" +i18n("Baskets matching is cAse inSEnsItive.") + "</p>", 0407 tagWidget); 0408 0409 QGridLayout *tagGrid = new QGridLayout(tagWidget); 0410 tagGrid->addWidget(tagNameLabel, 0, 0); 0411 tagGrid->addWidget(m_tagName, 0, 1, 1, 3); 0412 tagGrid->addWidget(shortcutLabel, 1, 0); 0413 tagGrid->addWidget(m_shortcut, 1, 1); 0414 tagGrid->addWidget(m_removeShortcut, 1, 2); 0415 tagGrid->addWidget(m_inherit, 2, 0, 1, 4); 0416 tagGrid->addWidget(m_allowCrossRefernce, 3, 0); 0417 tagGrid->addWidget(allowCrossReferenceHelp, 3, 1); 0418 tagGrid->setColumnStretch(/*col=*/3, /*stretch=*/255); 0419 0420 m_stateBox = new QGroupBox(i18n("State"), rightWidget); 0421 m_stateBoxLayout = new QHBoxLayout; 0422 m_stateBox->setLayout(m_stateBoxLayout); 0423 0424 QWidget *stateWidget = new QWidget; 0425 m_stateBoxLayout->addWidget(stateWidget); 0426 0427 m_stateName = new QLineEdit(stateWidget); 0428 m_stateNameLabel = new QLabel(i18n("Na&me:"), stateWidget); 0429 m_stateNameLabel->setBuddy(m_stateName); 0430 0431 QWidget *emblemWidget = new QWidget(stateWidget); 0432 m_emblem = new KIconButton(emblemWidget); 0433 m_emblem->setIconType(KIconLoader::NoGroup, KIconLoader::Action); 0434 m_emblem->setIconSize(16); 0435 m_emblem->setIcon("edit-delete"); 0436 m_removeEmblem = new QPushButton(i18nc("Remove tag emblem", "Remo&ve"), emblemWidget); 0437 QLabel *emblemLabel = new QLabel(i18n("&Emblem:"), stateWidget); 0438 emblemLabel->setBuddy(m_emblem); 0439 connect(m_removeEmblem, &QPushButton::clicked, this, &TagsEditDialog::removeEmblem); // m_emblem.resetIcon() is not a slot! 0440 0441 // Make the icon button and the remove button the same height: 0442 int height = qMax(m_emblem->sizeHint().width(), m_emblem->sizeHint().height()); 0443 height = qMax(height, m_removeEmblem->sizeHint().height()); 0444 m_emblem->setFixedSize(height, height); // Make it square 0445 m_removeEmblem->setFixedHeight(height); 0446 m_emblem->resetIcon(); 0447 0448 QHBoxLayout *emblemLayout = new QHBoxLayout(emblemWidget); 0449 emblemLayout->addWidget(m_emblem); 0450 emblemLayout->addWidget(m_removeEmblem); 0451 emblemLayout->addStretch(); 0452 0453 m_backgroundColor = new KColorCombo2(QColor(), palette().color(QPalette::Base), stateWidget); 0454 QLabel *backgroundColorLabel = new QLabel(i18n("&Background:"), stateWidget); 0455 backgroundColorLabel->setBuddy(m_backgroundColor); 0456 0457 QHBoxLayout *backgroundColorLayout = new QHBoxLayout(nullptr); 0458 backgroundColorLayout->addWidget(m_backgroundColor); 0459 backgroundColorLayout->addStretch(); 0460 0461 QIcon boldIconSet = QIcon::fromTheme("format-text-bold"); 0462 m_bold = new QPushButton(boldIconSet, QString(), stateWidget); 0463 m_bold->setCheckable(true); 0464 int size = qMax(m_bold->sizeHint().width(), m_bold->sizeHint().height()); 0465 m_bold->setFixedSize(size, size); // Make it square! 0466 m_bold->setToolTip(i18n("Bold")); 0467 0468 QIcon underlineIconSet = QIcon::fromTheme("format-text-underline"); 0469 m_underline = new QPushButton(underlineIconSet, QString(), stateWidget); 0470 m_underline->setCheckable(true); 0471 m_underline->setFixedSize(size, size); // Make it square! 0472 m_underline->setToolTip(i18n("Underline")); 0473 0474 QIcon italicIconSet = QIcon::fromTheme("format-text-italic"); 0475 m_italic = new QPushButton(italicIconSet, QString(), stateWidget); 0476 m_italic->setCheckable(true); 0477 m_italic->setFixedSize(size, size); // Make it square! 0478 m_italic->setToolTip(i18n("Italic")); 0479 0480 QIcon strikeIconSet = QIcon::fromTheme("format-text-strikethrough"); 0481 m_strike = new QPushButton(strikeIconSet, QString(), stateWidget); 0482 m_strike->setCheckable(true); 0483 m_strike->setFixedSize(size, size); // Make it square! 0484 m_strike->setToolTip(i18n("Strike Through")); 0485 0486 QLabel *textLabel = new QLabel(i18n("&Text:"), stateWidget); 0487 textLabel->setBuddy(m_bold); 0488 0489 QHBoxLayout *textLayout = new QHBoxLayout; 0490 textLayout->addWidget(m_bold); 0491 textLayout->addWidget(m_underline); 0492 textLayout->addWidget(m_italic); 0493 textLayout->addWidget(m_strike); 0494 textLayout->addStretch(); 0495 0496 m_textColor = new KColorCombo2(QColor(), palette().color(QPalette::Text), stateWidget); 0497 QLabel *textColorLabel = new QLabel(i18n("Co&lor:"), stateWidget); 0498 textColorLabel->setBuddy(m_textColor); 0499 0500 m_font = new QFontComboBox(stateWidget); 0501 m_font->addItem(i18n("(Default)"), 0); 0502 QLabel *fontLabel = new QLabel(i18n("&Font:"), stateWidget); 0503 fontLabel->setBuddy(m_font); 0504 0505 m_fontSize = new FontSizeCombo(/*rw=*/true, /*withDefault=*/true, stateWidget); 0506 QLabel *fontSizeLabel = new QLabel(i18n("&Size:"), stateWidget); 0507 fontSizeLabel->setBuddy(m_fontSize); 0508 0509 m_textEquivalent = new QLineEdit(stateWidget); 0510 QLabel *textEquivalentLabel = new QLabel(i18n("Te&xt equivalent:"), stateWidget); 0511 textEquivalentLabel->setBuddy(m_textEquivalent); 0512 QFont font = m_textEquivalent->font(); 0513 font.setFamily("monospace"); 0514 m_textEquivalent->setFont(font); 0515 0516 HelpLabel *textEquivalentHelp = new HelpLabel(i18n("What is this for?"), 0517 "<p>" + i18n("When you copy and paste or drag and drop notes to a text editor, this text will be inserted as a textual equivalent of the tag.") + "</p>" + 0518 // "<p>" + i18n("If filled, this property lets you paste this tag or this state as textual equivalent.") + "<br>" + 0519 i18n("For instance, a list of notes with the <b>To Do</b> and <b>Done</b> tags are exported as lines preceded by <b>[ ]</b> or <b>[x]</b>, " 0520 "representing an empty checkbox and a checked box.") + 0521 "</p>" + "<p align='center'><img src=\":images/tag_export_help.png\"></p>", 0522 stateWidget); 0523 QHBoxLayout *textEquivalentHelpLayout = new QHBoxLayout; 0524 textEquivalentHelpLayout->addWidget(textEquivalentHelp); 0525 textEquivalentHelpLayout->addStretch(255); 0526 0527 m_onEveryLines = new QCheckBox(i18n("On ever&y line"), stateWidget); 0528 0529 HelpLabel *onEveryLinesHelp = new HelpLabel(i18n("What does this mean?"), 0530 "<p>" + i18n("When a note has several lines, you can choose to export the tag or the state on the first line or on every line of the note.") + "</p>" + 0531 "<p align='center'><img src=\":images/tag_export_on_every_lines_help.png\"></p>" + "<p>" + 0532 i18n("In the example above, the tag of the top note is only exported on the first line, while the tag of the bottom note is exported on every line of the note."), 0533 stateWidget); 0534 QHBoxLayout *onEveryLinesHelpLayout = new QHBoxLayout; 0535 onEveryLinesHelpLayout->addWidget(onEveryLinesHelp); 0536 onEveryLinesHelpLayout->addStretch(255); 0537 0538 QGridLayout *textEquivalentGrid = new QGridLayout; 0539 textEquivalentGrid->addWidget(textEquivalentLabel, 0, 0); 0540 textEquivalentGrid->addWidget(m_textEquivalent, 0, 1); 0541 textEquivalentGrid->addLayout(textEquivalentHelpLayout, 0, 2); 0542 textEquivalentGrid->addWidget(m_onEveryLines, 1, 1); 0543 textEquivalentGrid->addLayout(onEveryLinesHelpLayout, 1, 2); 0544 textEquivalentGrid->setColumnStretch(/*col=*/3, /*stretch=*/255); 0545 0546 KSeparator *separator = new KSeparator(Qt::Horizontal, stateWidget); 0547 0548 QGridLayout *stateGrid = new QGridLayout(stateWidget); 0549 stateGrid->addWidget(m_stateNameLabel, 0, 0); 0550 stateGrid->addWidget(m_stateName, 0, 1, 1, 6); 0551 stateGrid->addWidget(emblemLabel, 1, 0); 0552 stateGrid->addWidget(emblemWidget, 1, 1, 1, 6); 0553 stateGrid->addWidget(backgroundColorLabel, 1, 5); 0554 stateGrid->addLayout(backgroundColorLayout, 1, 6, 1, 1); 0555 stateGrid->addWidget(textLabel, 2, 0); 0556 stateGrid->addLayout(textLayout, 2, 1, 1, 4); 0557 stateGrid->addWidget(textColorLabel, 2, 5); 0558 stateGrid->addWidget(m_textColor, 2, 6); 0559 stateGrid->addWidget(fontLabel, 3, 0); 0560 stateGrid->addWidget(m_font, 3, 1, 1, 4); 0561 stateGrid->addWidget(fontSizeLabel, 3, 5); 0562 stateGrid->addWidget(m_fontSize, 3, 6); 0563 stateGrid->addWidget(separator, 4, 0, 1, 7); 0564 stateGrid->addLayout(textEquivalentGrid, 5, 0, 1, 7); 0565 0566 QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget); 0567 rightLayout->addWidget(m_tagBox); 0568 rightLayout->addWidget(m_stateBox); 0569 rightLayout->addStretch(); 0570 0571 layout->addWidget(rightWidget); 0572 rightWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); 0573 0574 // Equalize the width of the first column of the two grids: 0575 int maxWidth = tagNameLabel->sizeHint().width(); 0576 maxWidth = qMax(maxWidth, shortcutLabel->sizeHint().width()); 0577 maxWidth = qMax(maxWidth, m_stateNameLabel->sizeHint().width()); 0578 maxWidth = qMax(maxWidth, emblemLabel->sizeHint().width()); 0579 maxWidth = qMax(maxWidth, textLabel->sizeHint().width()); 0580 maxWidth = qMax(maxWidth, fontLabel->sizeHint().width()); 0581 maxWidth = qMax(maxWidth, backgroundColorLabel->sizeHint().width()); 0582 maxWidth = qMax(maxWidth, textEquivalentLabel->sizeHint().width()); 0583 0584 tagNameLabel->setFixedWidth(maxWidth); 0585 m_stateNameLabel->setFixedWidth(maxWidth); 0586 textEquivalentLabel->setFixedWidth(maxWidth); 0587 0588 // Load Tags: 0589 for (Tag::List::iterator tagIt = Tag::all.begin(); tagIt != Tag::all.end(); ++tagIt) 0590 m_tagCopies.append(new TagCopy(*tagIt)); 0591 0592 TagListViewItem *lastInsertedItem = nullptr; 0593 TagListViewItem *lastInsertedSubItem; 0594 TagListViewItem *item; 0595 TagListViewItem *subItem; 0596 for (TagCopy::List::iterator tagCopyIt = m_tagCopies.begin(); tagCopyIt != m_tagCopies.end(); ++tagCopyIt) { 0597 // New List View Item: 0598 if (lastInsertedItem) 0599 item = new TagListViewItem(m_tags, lastInsertedItem, *tagCopyIt); 0600 else 0601 item = new TagListViewItem(m_tags, *tagCopyIt); 0602 item->setExpanded(true); 0603 lastInsertedItem = item; 0604 // Load 0605 if ((*tagCopyIt)->isMultiState()) { 0606 lastInsertedSubItem = nullptr; 0607 StateCopy::List stateCopies = item->tagCopy()->stateCopies; 0608 for (StateCopy::List::iterator stateCopyIt = stateCopies.begin(); stateCopyIt != stateCopies.end(); ++stateCopyIt) { 0609 if (lastInsertedSubItem) 0610 subItem = new TagListViewItem(item, lastInsertedSubItem, *stateCopyIt); 0611 else 0612 subItem = new TagListViewItem(item, *stateCopyIt); 0613 lastInsertedSubItem = subItem; 0614 } 0615 } 0616 } 0617 0618 // Connect Signals: 0619 connect(m_tagName, &QLineEdit::textChanged, this, &TagsEditDialog::modified); 0620 connect(m_shortcut, &KShortcutWidget::shortcutChanged, this, &TagsEditDialog::modified); 0621 connect(m_inherit, &QCheckBox::stateChanged, this, &TagsEditDialog::modified); 0622 connect(m_allowCrossRefernce, &QCheckBox::clicked, this, &TagsEditDialog::modified); 0623 connect(m_stateName, &QLineEdit::textChanged, this, &TagsEditDialog::modified); 0624 connect(m_emblem, &KIconButton::iconChanged, this, &TagsEditDialog::modified); 0625 connect(m_backgroundColor, &KColorCombo2::colorChanged, this, &TagsEditDialog::modified); 0626 connect(m_bold, &QPushButton::toggled, this, &TagsEditDialog::modified); 0627 connect(m_underline, &QPushButton::toggled, this, &TagsEditDialog::modified); 0628 connect(m_italic, &QPushButton::toggled, this, &TagsEditDialog::modified); 0629 connect(m_strike, &QPushButton::toggled, this, &TagsEditDialog::modified); 0630 connect(m_textColor, &KColorCombo2::colorChanged, this, &TagsEditDialog::modified); 0631 connect(m_font, &QFontComboBox::editTextChanged, this, &TagsEditDialog::modified); 0632 connect(m_fontSize, &FontSizeCombo::editTextChanged, this, &TagsEditDialog::modified); 0633 connect(m_textEquivalent, &QLineEdit::textChanged, this, &TagsEditDialog::modified); 0634 connect(m_onEveryLines, &QCheckBox::stateChanged, this, &TagsEditDialog::modified); 0635 0636 connect(m_tags, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))); 0637 connect(m_tags, SIGNAL(deletePressed()), this, SLOT(deleteTag())); 0638 connect(m_tags, SIGNAL(doubleClickedItem()), this, SLOT(renameIt())); 0639 0640 QTreeWidgetItem *firstItem = m_tags->firstChild(); 0641 if (stateToEdit != nullptr) { 0642 TagListViewItem *item = itemForState(stateToEdit); 0643 if (item) 0644 firstItem = item; 0645 } 0646 // Select the first tag unless the first tag is a multi-state tag. 0647 // In this case, select the first state, as it let customize the state AND the associated tag. 0648 if (firstItem) { 0649 if (firstItem->childCount() > 0) 0650 firstItem = firstItem->child(0); 0651 firstItem->setSelected(true); 0652 m_tags->setCurrentItem(firstItem); 0653 currentItemChanged(firstItem); 0654 if (stateToEdit == nullptr) 0655 m_tags->scrollToItem(firstItem); 0656 m_tags->setFocus(); 0657 } else { 0658 m_moveUp->setEnabled(false); 0659 m_moveDown->setEnabled(false); 0660 m_deleteTag->setEnabled(false); 0661 m_tagBox->setEnabled(false); 0662 m_stateBox->setEnabled(false); 0663 } 0664 // TODO: Disabled both boxes if no tag!!! 0665 0666 // Some keyboard shortcuts: // Ctrl+arrows instead of Alt+arrows (same as Go menu in the main window) because Alt+Down is for combo boxes 0667 QAction *selectAbove = new QAction(this); 0668 selectAbove->setShortcut(Qt::CTRL + Qt::Key_Up); 0669 connect(selectAbove, &QAction::triggered, this, &TagsEditDialog::selectUp); 0670 0671 QAction *selectBelow = new QAction(this); 0672 selectBelow->setShortcut(Qt::CTRL + Qt::Key_Down); 0673 connect(selectBelow, &QAction::triggered, this, &TagsEditDialog::selectDown); 0674 0675 QAction *selectLeft = new QAction(this); 0676 selectLeft->setShortcut(Qt::CTRL + Qt::Key_Left); 0677 connect(selectLeft, &QAction::triggered, this, &TagsEditDialog::selectLeft); 0678 0679 QAction *selectRight = new QAction(this); 0680 selectRight->setShortcut(Qt::CTRL + Qt::Key_Right); 0681 connect(selectRight, &QAction::triggered, this, &TagsEditDialog::selectRight); 0682 0683 QAction *moveAbove = new QAction(this); 0684 moveAbove->setShortcut(Qt::CTRL + Qt::Key_Up); 0685 connect(moveAbove, &QAction::triggered, this, &TagsEditDialog::moveUp); 0686 0687 QAction *moveBelow = new QAction(this); 0688 moveBelow->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Down); 0689 connect(moveBelow, &QAction::triggered, this, &TagsEditDialog::moveDown); 0690 0691 QAction *rename = new QAction(this); 0692 rename->setShortcut(Qt::Key_F2); 0693 connect(rename, &QAction::triggered, this, &TagsEditDialog::renameIt); 0694 0695 m_tags->setMinimumSize(m_tags->sizeHint().width() * 2, m_tagBox->sizeHint().height() + m_stateBox->sizeHint().height()); 0696 0697 if (addNewTag) 0698 QTimer::singleShot(0, this, SLOT(newTag())); 0699 else 0700 // Once the window initial size is computed and the window show, allow the user to resize it down: 0701 QTimer::singleShot(0, this, SLOT(resetTreeSizeHint())); 0702 } 0703 0704 TagsEditDialog::~TagsEditDialog() 0705 { 0706 } 0707 0708 void TagsEditDialog::resetTreeSizeHint() 0709 { 0710 m_tags->setMinimumSize(m_tags->sizeHint()); 0711 } 0712 0713 TagListViewItem *TagsEditDialog::itemForState(State *state) 0714 { 0715 // Browse all tags: 0716 QTreeWidgetItemIterator it(m_tags); 0717 while (*it) { 0718 QTreeWidgetItem *item = *it; 0719 0720 // Return if we found the tag item: 0721 TagListViewItem *tagItem = (TagListViewItem *)item; 0722 if (tagItem->tagCopy() && tagItem->tagCopy()->oldTag && tagItem->tagCopy()->stateCopies[0]->oldState == state) 0723 return tagItem; 0724 0725 // Browser all sub-states: 0726 QTreeWidgetItemIterator it2(item); 0727 while (*it2) { 0728 QTreeWidgetItem *subItem = *it2; 0729 0730 // Return if we found the state item: 0731 TagListViewItem *stateItem = (TagListViewItem *)subItem; 0732 if (stateItem->stateCopy() && stateItem->stateCopy()->oldState && stateItem->stateCopy()->oldState == state) 0733 return stateItem; 0734 0735 ++it2; 0736 } 0737 0738 ++it; 0739 } 0740 return nullptr; 0741 } 0742 0743 void TagsEditDialog::newTag() 0744 { 0745 // Add to the "model": 0746 TagCopy *newTagCopy = new TagCopy(); 0747 newTagCopy->stateCopies[0]->newState->setId("tag_state_" + QString::number(Tag::getNextStateUid())); // TODO: Check if it's really unique 0748 m_tagCopies.append(newTagCopy); 0749 m_addedStates.append(newTagCopy->stateCopies[0]->newState); 0750 0751 // Add to the "view": 0752 TagListViewItem *item; 0753 if (m_tags->firstChild()) { 0754 // QListView::lastItem is the last item in the tree. If we the last item is a state item, the new tag gets appended to the begin of the list. 0755 TagListViewItem *last = m_tags->lastItem(); 0756 if (last->parent()) 0757 last = last->parent(); 0758 item = new TagListViewItem(m_tags, last, newTagCopy); 0759 } else 0760 item = new TagListViewItem(m_tags, newTagCopy); 0761 0762 m_deleteTag->setEnabled(true); 0763 m_tagBox->setEnabled(true); 0764 0765 // Add to the "controller": 0766 m_tags->setCurrentItem(item); 0767 currentItemChanged(item); 0768 item->setSelected(true); 0769 m_tagName->setFocus(); 0770 } 0771 0772 void TagsEditDialog::newState() 0773 { 0774 TagListViewItem *tagItem = m_tags->currentItem(); 0775 if (tagItem->parent()) 0776 tagItem = ((TagListViewItem *)(tagItem->parent())); 0777 tagItem->setExpanded(true); // Show sub-states if we're adding them for the first time! 0778 0779 State *firstState = tagItem->tagCopy()->stateCopies[0]->newState; 0780 0781 // Add the first state to the "view". From now on, it's a multi-state tag: 0782 if (tagItem->childCount() <= 0) { 0783 firstState->setName(tagItem->tagCopy()->newTag->name()); 0784 // Force emblem to exists for multi-state tags: 0785 if (firstState->emblem().isEmpty()) 0786 firstState->setEmblem("empty"); 0787 new TagListViewItem(tagItem, tagItem->tagCopy()->stateCopies[0]); 0788 } 0789 0790 // Add to the "model": 0791 StateCopy *newStateCopy = new StateCopy(); 0792 firstState->copyTo(newStateCopy->newState); 0793 newStateCopy->newState->setId("tag_state_" + QString::number(Tag::getNextStateUid())); // TODO: Check if it's really unique 0794 newStateCopy->newState->setName(QString()); // We copied it too but it's likely the name will not be the same 0795 tagItem->tagCopy()->stateCopies.append(newStateCopy); 0796 m_addedStates.append(newStateCopy->newState); 0797 0798 // Add to the "view": 0799 TagListViewItem *item = new TagListViewItem(tagItem, tagItem->lastChild(), newStateCopy); 0800 0801 // Add to the "controller": 0802 m_tags->setCurrentItem(item); 0803 currentItemChanged(item); 0804 m_stateName->setFocus(); 0805 } 0806 0807 void TagsEditDialog::moveUp() 0808 { 0809 if (!m_moveUp->isEnabled()) // Trggered by keyboard shortcut 0810 return; 0811 0812 TagListViewItem *tagItem = m_tags->currentItem(); 0813 0814 // Move in the list view: 0815 int idx = 0; 0816 QList<QTreeWidgetItem *> children; 0817 if (tagItem->parent()) { 0818 TagListViewItem *parentItem = tagItem->parent(); 0819 idx = parentItem->indexOfChild(tagItem); 0820 if (idx > 0) { 0821 tagItem = (TagListViewItem *)parentItem->takeChild(idx); 0822 children = tagItem->takeChildren(); 0823 parentItem->insertChild(idx - 1, tagItem); 0824 tagItem->insertChildren(0, children); 0825 tagItem->setExpanded(true); 0826 } 0827 } else { 0828 idx = m_tags->indexOfTopLevelItem(tagItem); 0829 if (idx > 0) { 0830 tagItem = (TagListViewItem *)m_tags->takeTopLevelItem(idx); 0831 children = tagItem->takeChildren(); 0832 m_tags->insertTopLevelItem(idx - 1, tagItem); 0833 tagItem->insertChildren(0, children); 0834 tagItem->setExpanded(true); 0835 } 0836 } 0837 0838 m_tags->setCurrentItem(tagItem); 0839 0840 // Move in the value list: 0841 if (tagItem->tagCopy()) { 0842 int pos = m_tagCopies.indexOf(tagItem->tagCopy()); 0843 m_tagCopies.removeAll(tagItem->tagCopy()); 0844 int i = 0; 0845 for (TagCopy::List::iterator it = m_tagCopies.begin(); it != m_tagCopies.end(); ++it, ++i) 0846 if (i == pos - 1) { 0847 m_tagCopies.insert(it, tagItem->tagCopy()); 0848 break; 0849 } 0850 } else { 0851 StateCopy::List &stateCopies = ((TagListViewItem *)(tagItem->parent()))->tagCopy()->stateCopies; 0852 int pos = stateCopies.indexOf(tagItem->stateCopy()); 0853 stateCopies.removeAll(tagItem->stateCopy()); 0854 int i = 0; 0855 for (StateCopy::List::iterator it = stateCopies.begin(); it != stateCopies.end(); ++it, ++i) 0856 if (i == pos - 1) { 0857 stateCopies.insert(it, tagItem->stateCopy()); 0858 break; 0859 } 0860 } 0861 0862 ensureCurrentItemVisible(); 0863 0864 m_moveDown->setEnabled(tagItem->nextSibling() != nullptr); 0865 m_moveUp->setEnabled(tagItem->prevSibling() != nullptr); 0866 } 0867 0868 void TagsEditDialog::moveDown() 0869 { 0870 if (!m_moveDown->isEnabled()) // Trggered by keyboard shortcut 0871 return; 0872 0873 TagListViewItem *tagItem = m_tags->currentItem(); 0874 0875 // Move in the list view: 0876 int idx = 0; 0877 QList<QTreeWidgetItem *> children; 0878 if (tagItem->parent()) { 0879 TagListViewItem *parentItem = tagItem->parent(); 0880 idx = parentItem->indexOfChild(tagItem); 0881 if (idx < parentItem->childCount() - 1) { 0882 children = tagItem->takeChildren(); 0883 tagItem = (TagListViewItem *)parentItem->takeChild(idx); 0884 parentItem->insertChild(idx + 1, tagItem); 0885 tagItem->insertChildren(0, children); 0886 tagItem->setExpanded(true); 0887 } 0888 } else { 0889 idx = m_tags->indexOfTopLevelItem(tagItem); 0890 if (idx < m_tags->topLevelItemCount() - 1) { 0891 children = tagItem->takeChildren(); 0892 tagItem = (TagListViewItem *)m_tags->takeTopLevelItem(idx); 0893 m_tags->insertTopLevelItem(idx + 1, tagItem); 0894 tagItem->insertChildren(0, children); 0895 tagItem->setExpanded(true); 0896 } 0897 } 0898 0899 m_tags->setCurrentItem(tagItem); 0900 0901 // Move in the value list: 0902 if (tagItem->tagCopy()) { 0903 uint pos = m_tagCopies.indexOf(tagItem->tagCopy()); 0904 m_tagCopies.removeAll(tagItem->tagCopy()); 0905 if (pos == (uint)m_tagCopies.count() - 1) // Insert at end: iterator does not go there 0906 m_tagCopies.append(tagItem->tagCopy()); 0907 else { 0908 uint i = 0; 0909 for (TagCopy::List::iterator it = m_tagCopies.begin(); it != m_tagCopies.end(); ++it, ++i) 0910 if (i == pos + 1) { 0911 m_tagCopies.insert(it, tagItem->tagCopy()); 0912 break; 0913 } 0914 } 0915 } else { 0916 StateCopy::List &stateCopies = ((TagListViewItem *)(tagItem->parent()))->tagCopy()->stateCopies; 0917 uint pos = stateCopies.indexOf(tagItem->stateCopy()); 0918 stateCopies.removeAll(tagItem->stateCopy()); 0919 if (pos == (uint)stateCopies.count() - 1) // Insert at end: iterator does not go there 0920 stateCopies.append(tagItem->stateCopy()); 0921 else { 0922 uint i = 0; 0923 for (StateCopy::List::iterator it = stateCopies.begin(); it != stateCopies.end(); ++it, ++i) 0924 if (i == pos + 1) { 0925 stateCopies.insert(it, tagItem->stateCopy()); 0926 break; 0927 } 0928 } 0929 } 0930 0931 ensureCurrentItemVisible(); 0932 0933 m_moveDown->setEnabled(tagItem->nextSibling() != nullptr); 0934 m_moveUp->setEnabled(tagItem->prevSibling() != nullptr); 0935 } 0936 0937 void TagsEditDialog::selectUp() 0938 { 0939 QKeyEvent *keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::KeyboardModifiers(), nullptr); 0940 QApplication::postEvent(m_tags, keyEvent); 0941 } 0942 0943 void TagsEditDialog::selectDown() 0944 { 0945 QKeyEvent *keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::KeyboardModifiers(), nullptr); 0946 QApplication::postEvent(m_tags, keyEvent); 0947 } 0948 0949 void TagsEditDialog::selectLeft() 0950 { 0951 QKeyEvent *keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::KeyboardModifiers(), nullptr); 0952 QApplication::postEvent(m_tags, keyEvent); 0953 } 0954 0955 void TagsEditDialog::selectRight() 0956 { 0957 QKeyEvent *keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::KeyboardModifiers(), nullptr); 0958 QApplication::postEvent(m_tags, keyEvent); 0959 } 0960 0961 void TagsEditDialog::deleteTag() 0962 { 0963 if (!m_deleteTag->isEnabled()) 0964 return; 0965 0966 TagListViewItem *item = m_tags->currentItem(); 0967 0968 int result = KMessageBox::Continue; 0969 if (item->tagCopy() && item->tagCopy()->oldTag) 0970 result = KMessageBox::warningContinueCancel(this, i18n("Deleting the tag will remove it from every note it is currently assigned to."), i18n("Confirm Delete Tag"), KGuiItem(i18n("Delete Tag"), "edit-delete")); 0971 else if (item->stateCopy() && item->stateCopy()->oldState) 0972 result = KMessageBox::warningContinueCancel(this, i18n("Deleting the state will remove the tag from every note the state is currently assigned to."), i18n("Confirm Delete State"), KGuiItem(i18n("Delete State"), "edit-delete")); 0973 if (result != KMessageBox::Continue) 0974 return; 0975 0976 if (item->tagCopy()) { 0977 StateCopy::List stateCopies = item->tagCopy()->stateCopies; 0978 for (StateCopy::List::iterator stateCopyIt = stateCopies.begin(); stateCopyIt != stateCopies.end(); ++stateCopyIt) { 0979 StateCopy *stateCopy = *stateCopyIt; 0980 if (stateCopy->oldState) { 0981 m_deletedStates.append(stateCopy->oldState); 0982 m_addedStates.removeAll(stateCopy->oldState); 0983 } 0984 m_addedStates.removeAll(stateCopy->newState); 0985 } 0986 m_tagCopies.removeAll(item->tagCopy()); 0987 // Remove the new tag, to avoid keyboard-shortcut clashes: 0988 delete item->tagCopy()->newTag; 0989 } else { 0990 TagListViewItem *parentItem = item->parent(); 0991 // Remove the state: 0992 parentItem->tagCopy()->stateCopies.removeAll(item->stateCopy()); 0993 if (item->stateCopy()->oldState) { 0994 m_deletedStates.append(item->stateCopy()->oldState); 0995 m_addedStates.removeAll(item->stateCopy()->oldState); 0996 } 0997 m_addedStates.removeAll(item->stateCopy()->newState); 0998 delete item; 0999 item = nullptr; 1000 // Transform to single-state tag if needed: 1001 if (parentItem->childCount() == 1) { 1002 delete parentItem->child(0); 1003 m_tags->setCurrentItem(parentItem); 1004 } 1005 } 1006 1007 delete item; 1008 if (m_tags->currentItem()) 1009 m_tags->currentItem()->setSelected(true); 1010 1011 if (!m_tags->firstChild()) { 1012 m_deleteTag->setEnabled(false); 1013 m_tagBox->setEnabled(false); 1014 m_stateBox->setEnabled(false); 1015 } 1016 } 1017 1018 void TagsEditDialog::renameIt() 1019 { 1020 if (m_tags->currentItem()->tagCopy()) 1021 m_tagName->setFocus(); 1022 else 1023 m_stateName->setFocus(); 1024 } 1025 1026 void TagsEditDialog::capturedShortcut(const QKeySequence &shortcut) 1027 { 1028 Q_UNUSED(shortcut); 1029 // TODO: Validate it! 1030 // m_shortcut->setShortcut(shortcut); 1031 } 1032 1033 void TagsEditDialog::removeShortcut() 1034 { 1035 // m_shortcut->setShortcut(QKeySequence()); 1036 modified(); 1037 } 1038 1039 void TagsEditDialog::removeEmblem() 1040 { 1041 m_emblem->resetIcon(); 1042 modified(); 1043 } 1044 1045 void TagsEditDialog::modified() 1046 { 1047 if (m_loading) 1048 return; 1049 1050 TagListViewItem *tagItem = m_tags->currentItem(); 1051 if (tagItem == nullptr) 1052 return; 1053 1054 if (tagItem->tagCopy()) { 1055 if (tagItem->tagCopy()->isMultiState()) { 1056 saveTagTo(tagItem->tagCopy()->newTag); 1057 } else { 1058 saveTagTo(tagItem->tagCopy()->newTag); 1059 saveStateTo(tagItem->tagCopy()->stateCopies[0]->newState); 1060 } 1061 } else if (tagItem->stateCopy()) { 1062 saveTagTo(((TagListViewItem *)(tagItem->parent()))->tagCopy()->newTag); 1063 saveStateTo(tagItem->stateCopy()->newState); 1064 } 1065 1066 m_tags->currentItem()->setup(); 1067 if (m_tags->currentItem()->parent()) 1068 m_tags->currentItem()->parent()->setup(); 1069 1070 m_removeShortcut->setEnabled(!m_shortcut->shortcut().isEmpty()); 1071 m_removeEmblem->setEnabled(!m_emblem->icon().isEmpty() && !m_tags->currentItem()->isEmblemObligatory()); 1072 m_onEveryLines->setEnabled(!m_textEquivalent->text().isEmpty()); 1073 } 1074 1075 void TagsEditDialog::currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *nextItem) 1076 { 1077 Q_UNUSED(nextItem); 1078 if (item == nullptr) 1079 return; 1080 1081 m_loading = true; 1082 1083 TagListViewItem *tagItem = (TagListViewItem *)item; 1084 if (tagItem->tagCopy()) { 1085 if (tagItem->tagCopy()->isMultiState()) { 1086 loadTagFrom(tagItem->tagCopy()->newTag); 1087 loadBlankState(); 1088 m_stateBox->setEnabled(false); 1089 m_stateBox->setTitle(i18n("State")); 1090 m_stateNameLabel->setEnabled(true); 1091 m_stateName->setEnabled(true); 1092 } else { 1093 loadTagFrom(tagItem->tagCopy()->newTag); // TODO: No duplicate 1094 loadStateFrom(tagItem->tagCopy()->stateCopies[0]->newState); 1095 m_stateBox->setEnabled(true); 1096 m_stateBox->setTitle(i18n("Appearance")); 1097 m_stateName->setText(QString()); 1098 m_stateNameLabel->setEnabled(false); 1099 m_stateName->setEnabled(false); 1100 } 1101 } else if (tagItem->stateCopy()) { 1102 loadTagFrom(((TagListViewItem *)(tagItem->parent()))->tagCopy()->newTag); 1103 loadStateFrom(tagItem->stateCopy()->newState); 1104 m_stateBox->setEnabled(true); 1105 m_stateBox->setTitle(i18n("State")); 1106 m_stateNameLabel->setEnabled(true); 1107 m_stateName->setEnabled(true); 1108 } 1109 1110 ensureCurrentItemVisible(); 1111 1112 m_loading = false; 1113 } 1114 1115 void TagsEditDialog::ensureCurrentItemVisible() 1116 { 1117 TagListViewItem *tagItem = m_tags->currentItem(); 1118 1119 // Ensure the tag and the states (if available) to be visible, but if there is a looooot of states, 1120 // ensure the tag is still visible, even if the last states are not... 1121 m_tags->scrollToItem(tagItem); 1122 1123 int idx = 0; 1124 1125 if (tagItem->parent()) { 1126 idx = ((QTreeWidgetItem *)tagItem->parent())->indexOfChild(tagItem); 1127 m_moveDown->setEnabled(idx < ((QTreeWidgetItem *)tagItem->parent())->childCount()); 1128 } else { 1129 idx = m_tags->indexOfTopLevelItem(tagItem); 1130 m_moveDown->setEnabled(idx < m_tags->topLevelItemCount()); 1131 } 1132 1133 m_moveUp->setEnabled(idx > 0); 1134 } 1135 1136 void TagsEditDialog::loadBlankState() 1137 { 1138 QFont defaultFont; 1139 m_stateName->setText(QString()); 1140 m_emblem->resetIcon(); 1141 m_removeEmblem->setEnabled(false); 1142 m_backgroundColor->setColor(QColor()); 1143 m_bold->setChecked(false); 1144 m_underline->setChecked(false); 1145 m_italic->setChecked(false); 1146 m_strike->setChecked(false); 1147 m_textColor->setColor(QColor()); 1148 // m_font->setCurrentIndex(0); 1149 m_font->setCurrentFont(defaultFont.family()); 1150 m_fontSize->setCurrentIndex(0); 1151 m_textEquivalent->setText(QString()); 1152 m_onEveryLines->setChecked(false); 1153 m_allowCrossRefernce->setChecked(false); 1154 } 1155 1156 void TagsEditDialog::loadStateFrom(State *state) 1157 { 1158 m_stateName->setText(state->name()); 1159 if (state->emblem().isEmpty()) 1160 m_emblem->resetIcon(); 1161 else 1162 m_emblem->setIcon(state->emblem()); 1163 m_removeEmblem->setEnabled(!state->emblem().isEmpty() && !m_tags->currentItem()->isEmblemObligatory()); 1164 m_backgroundColor->setColor(state->backgroundColor()); 1165 m_bold->setChecked(state->bold()); 1166 m_underline->setChecked(state->underline()); 1167 m_italic->setChecked(state->italic()); 1168 m_strike->setChecked(state->strikeOut()); 1169 m_textColor->setColor(state->textColor()); 1170 m_textEquivalent->setText(state->textEquivalent()); 1171 m_onEveryLines->setChecked(state->onAllTextLines()); 1172 m_allowCrossRefernce->setChecked(state->allowCrossReferences()); 1173 1174 QFont defaultFont; 1175 if (state->fontName().isEmpty()) 1176 m_font->setCurrentFont(defaultFont.family()); 1177 else 1178 m_font->setCurrentFont(state->fontName()); 1179 1180 if (state->fontSize() == -1) 1181 m_fontSize->setCurrentIndex(0); 1182 else 1183 m_fontSize->setItemText(m_fontSize->currentIndex(), QString::number(state->fontSize())); 1184 } 1185 1186 void TagsEditDialog::loadTagFrom(Tag *tag) 1187 { 1188 m_tagName->setText(tag->name()); 1189 QList<QKeySequence> shortcuts {tag->shortcut()}; 1190 m_shortcut->setShortcut(shortcuts); 1191 m_removeShortcut->setEnabled(!tag->shortcut().isEmpty()); 1192 m_inherit->setChecked(tag->inheritedBySiblings()); 1193 } 1194 1195 void TagsEditDialog::saveStateTo(State *state) 1196 { 1197 state->setName(m_stateName->text()); 1198 state->setEmblem(m_emblem->icon()); 1199 state->setBackgroundColor(m_backgroundColor->color()); 1200 state->setBold(m_bold->isChecked()); 1201 state->setUnderline(m_underline->isChecked()); 1202 state->setItalic(m_italic->isChecked()); 1203 state->setStrikeOut(m_strike->isChecked()); 1204 state->setTextColor(m_textColor->color()); 1205 state->setTextEquivalent(m_textEquivalent->text()); 1206 state->setOnAllTextLines(m_onEveryLines->isChecked()); 1207 state->setAllowCrossReferences(m_allowCrossRefernce->isChecked()); 1208 1209 if (m_font->currentIndex() == 0) 1210 state->setFontName(QString()); 1211 else 1212 state->setFontName(m_font->currentFont().family()); 1213 1214 bool conversionOk; 1215 int fontSize = m_fontSize->currentText().toInt(&conversionOk); 1216 if (conversionOk) 1217 state->setFontSize(fontSize); 1218 else 1219 state->setFontSize(-1); 1220 } 1221 1222 void TagsEditDialog::saveTagTo(Tag *tag) 1223 { 1224 tag->setName(m_tagName->text()); 1225 1226 QKeySequence shortcut; 1227 if (m_shortcut->shortcut().count() > 0) 1228 shortcut = m_shortcut->shortcut()[0]; 1229 tag->setShortcut(shortcut); 1230 1231 tag->setInheritedBySiblings(m_inherit->isChecked()); 1232 } 1233 1234 void TagsEditDialog::reject() 1235 { 1236 // All copies of tag have a shortcut, that is stored as a QAction. 1237 // So, shortcuts are duplicated, and if the user press one tag keyboard-shortcut in the main window, there is a conflict. 1238 // We then should delete every copies: 1239 for (TagCopy::List::iterator tagCopyIt = m_tagCopies.begin(); tagCopyIt != m_tagCopies.end(); ++tagCopyIt) { 1240 delete (*tagCopyIt)->newTag; 1241 } 1242 1243 QDialog::reject(); 1244 } 1245 1246 void TagsEditDialog::accept() 1247 { 1248 Tag::all.clear(); 1249 for (TagCopy::List::iterator tagCopyIt = m_tagCopies.begin(); tagCopyIt != m_tagCopies.end(); ++tagCopyIt) { 1250 TagCopy *tagCopy = *tagCopyIt; 1251 // Copy changes to the tag and append in the list of tags:: 1252 if (tagCopy->oldTag) { 1253 tagCopy->newTag->copyTo(tagCopy->oldTag); 1254 delete tagCopy->newTag; 1255 } 1256 Tag *tag = (tagCopy->oldTag ? tagCopy->oldTag : tagCopy->newTag); 1257 Tag::all.append(tag); 1258 // And change all states: 1259 State::List &states = tag->states(); 1260 StateCopy::List &stateCopies = tagCopy->stateCopies; 1261 states.clear(); 1262 for (StateCopy::List::iterator stateCopyIt = stateCopies.begin(); stateCopyIt != stateCopies.end(); ++stateCopyIt) { 1263 StateCopy *stateCopy = *stateCopyIt; 1264 // Copy changes to the state and append in the list of tags: 1265 if (stateCopy->oldState) 1266 stateCopy->newState->copyTo(stateCopy->oldState); 1267 State *state = (stateCopy->oldState ? stateCopy->oldState : stateCopy->newState); 1268 states.append(state); 1269 state->setParentTag(tag); 1270 } 1271 } 1272 Tag::saveTags(); 1273 Tag::updateCaches(); 1274 1275 // Notify removed states and tags, and then remove them: 1276 if (!m_deletedStates.isEmpty()) 1277 Global::bnpView->removedStates(m_deletedStates); 1278 1279 // Update every note (change colors, size because of font change or added/removed emblems...): 1280 Global::bnpView->relayoutAllBaskets(); 1281 Global::bnpView->recomputeAllStyles(); 1282 1283 QDialog::accept(); 1284 } 1285 1286 void TagListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 1287 { 1288 // TagListViewItem* thisItem = qvariant_cast<TagListViewItem*>(index.data()); 1289 // qDebug() << "Pointer is: " << thisItem << endl; 1290 QItemDelegate::paint(painter, option, index); 1291 } 1292 1293 #include "moc_tagsedit.cpp"