void FilterBar::repopulateTagsCombo() { static const int ICON_SIZE = 16; m_tagsBox->clear(); m_tagsMap.clear(); m_statesMap.clear(); m_tagsBox->insertItem("", 0); m_tagsBox->insertItem(i18n("(Not tagged)"), 1); m_tagsBox->insertItem(i18n("(Tagged)"), 2); int index = 3; Tag *tag; State *state; QString icon; QString text; QPixmap emblem; for (Tag::List::iterator it = Tag::all.begin(); it != Tag::all.end(); ++it) { tag = *it; state = tag->states().first(); // Insert the tag in the combo-box: if (tag->countStates() > 1) { text = tag->name(); icon = ""; } else { text = state->name(); icon = state->emblem(); } emblem = KIconLoader::global()->loadIcon( icon, KIconLoader::Desktop, ICON_SIZE, KIconLoader::DefaultState, QStringList(), 0L, /*canReturnNull=*/true ); m_tagsBox->insertItem(emblem, text, index); // Update the mapping: m_tagsMap.insert(index, tag); ++index; // Insert sub-states, if needed: if (tag->countStates() > 1) { for (State::List::iterator it2 = tag->states().begin(); it2 != tag->states().end(); ++it2) { state = *it2; // Insert the state: text = state->name(); icon = state->emblem(); emblem = KIconLoader::global()->loadIcon( icon, KIconLoader::Desktop, ICON_SIZE, KIconLoader::DefaultState, QStringList(), 0L, /*canReturnNull=*/true ); // Indent the emblem to show the hierarchy relation: if (!emblem.isNull()) emblem = Tools::indentPixmap(emblem, /*depth=*/1, /*deltaX=*/2 * ICON_SIZE / 3); m_tagsBox->insertItem(emblem, text, index); // Update the mapping: m_statesMap.insert(index, state); ++index; } } } }
Tag* Tag::tagSimilarTo(Tag *tagToTest) { // Tags are considered similar if they have the same name, the same number of states, in the same order, and the same look. // Keyboard shortcut, text equivalent and onEveryLines are user settings, and thus not considered during the comparision. // Default tags (To Do, Important, Idea...) do not take into account the name of the tag and states during the comparision. // Default tags are equal only if they have the same number of states, in the same order, and the same look. // This is because default tag names are translated differently in every countries, but they are essentialy the same! // User tags begins with "tag_state_" followed by a number. Default tags are the other ones. // Browse all tags: for (List::iterator it = all.begin(); it != all.end(); ++it) { Tag *tag = *it; bool same = true; bool sameName; bool defaultTag = true; // We test only name and look. Shorcut and whenever it is inherited by sibling new notes are user settings only! sameName = tag->name() == tagToTest->name(); if (tag->countStates() != tagToTest->countStates()) continue; // Tag is different! // We found a tag with same name, check if every states/look are same too: State::List::iterator itTest = tagToTest->states().begin(); for (State::List::iterator it2 = (*it)->states().begin(); it2 != (*it)->states().end(); ++it2, ++itTest) { State *state = *it2; State *stateToTest = *itTest; if (state->id().startsWith("tag_state_") || stateToTest->id().startsWith("tag_state_")) { defaultTag = false; } if (state->name() != stateToTest->name()) { sameName = false; } if (state->emblem() != stateToTest->emblem()) { same = false; break; } if (state->bold() != stateToTest->bold()) { same = false; break; } if (state->italic() != stateToTest->italic()) { same = false; break; } if (state->underline() != stateToTest->underline()) { same = false; break; } if (state->strikeOut() != stateToTest->strikeOut()) { same = false; break; } if (state->textColor() != stateToTest->textColor()) { same = false; break; } if (state->fontName() != stateToTest->fontName()) { same = false; break; } if (state->fontSize() != stateToTest->fontSize()) { same = false; break; } if (state->backgroundColor() != stateToTest->backgroundColor()) { same = false; break; } // Text equivalent (as well as onAllTextLines) is also a user setting! } // We found an existing tag that is "exactly" the same: if (same && (sameName || defaultTag)) return tag; } // Not found: return 0; }
QMap<QString, QString> Tag::loadTags(const QString &path/* = QString()*//*, bool merge = false*/) { QMap<QString, QString> mergedStates; bool merge = !path.isEmpty(); QString fullPath = (merge ? path : Global::savesFolder() + "tags.xml"); QString doctype = "basketTags"; QDir dir; if (!dir.exists(fullPath)) { if (merge) return mergedStates; DEBUG_WIN << "Tags file does not exist: Creating it..."; createDefaultTagsSet(fullPath); } QDomDocument *document = XMLWork::openFile(doctype, fullPath); if (!document) { DEBUG_WIN << "<font color=red>FAILED to read the tags file</font>"; return mergedStates; } QDomElement docElem = document->documentElement(); if (!merge) nextStateUid = docElem.attribute("nextStateUid", QString::number(nextStateUid)).toLong(); QDomNode node = docElem.firstChild(); while (!node.isNull()) { QDomElement element = node.toElement(); if ( (!element.isNull()) && element.tagName() == "tag" ) { Tag *tag = new Tag(); // Load properties: QString name = XMLWork::getElementText(element, "name"); QString shortcut = XMLWork::getElementText(element, "shortcut"); QString inherited = XMLWork::getElementText(element, "inherited", "false"); tag->setName(name); tag->setShortcut(KShortcut(shortcut)); tag->setInheritedBySiblings(XMLWork::trueOrFalse(inherited)); // Load states: QDomNode subNode = element.firstChild(); while (!subNode.isNull()) { QDomElement subElement = subNode.toElement(); if ( (!subElement.isNull()) && subElement.tagName() == "state" ) { State *state = new State(subElement.attribute("id"), tag); state->setName( XMLWork::getElementText(subElement, "name") ); state->setEmblem( XMLWork::getElementText(subElement, "emblem") ); QDomElement textElement = XMLWork::getElement(subElement, "text"); state->setBold( XMLWork::trueOrFalse(textElement.attribute("bold", "false")) ); state->setItalic( XMLWork::trueOrFalse(textElement.attribute("italic", "false")) ); state->setUnderline( XMLWork::trueOrFalse(textElement.attribute("underline", "false")) ); state->setStrikeOut( XMLWork::trueOrFalse(textElement.attribute("strikeOut", "false")) ); QString textColor = textElement.attribute("color", ""); state->setTextColor(textColor.isEmpty() ? QColor() : QColor(textColor)); QDomElement fontElement = XMLWork::getElement(subElement, "font"); state->setFontName(fontElement.attribute("name", "")); QString fontSize = fontElement.attribute("size", ""); state->setFontSize(fontSize.isEmpty() ? -1 : fontSize.toInt()); QString backgroundColor = XMLWork::getElementText(subElement, "backgroundColor", ""); state->setBackgroundColor(backgroundColor.isEmpty() ? QColor() : QColor(backgroundColor)); QDomElement textEquivalentElement = XMLWork::getElement(subElement, "textEquivalent"); state->setTextEquivalent( textEquivalentElement.attribute("string", "") ); state->setOnAllTextLines( XMLWork::trueOrFalse(textEquivalentElement.attribute("onAllTextLines", "false")) ); tag->appendState(state); } subNode = subNode.nextSibling(); } // If the Tag is Valid: if (tag->countStates() > 0) { // Rename Things if Needed: State *firstState = tag->states().first(); if (tag->countStates() == 1 && firstState->name().isEmpty()) firstState->setName(tag->name()); if (tag->name().isEmpty()) tag->setName(firstState->name()); // Add or Merge the Tag: if (!merge) { all.append(tag); } else { Tag *similarTag = tagSimilarTo(tag); // Tag does not exists, add it: if (similarTag == 0) { // We are merging the new states, so we should choose new and unique (on that computer) ids for those states: for (State::List::iterator it = tag->states().begin(); it != tag->states().end(); ++it) { State *state = *it; QString uid = state->id(); QString newUid = "tag_state_" + QString::number(getNextStateUid()); state->setId(newUid); mergedStates[uid] = newUid; } // TODO: if shortcut is already assigned to a previous note, do not import it, keep the user settings! all.append(tag); // Tag already exists, rename to theire ids: } else { State::List::iterator it2 = similarTag->states().begin(); for (State::List::iterator it = tag->states().begin(); it != tag->states().end(); ++it, ++it2) { State *state = *it; State *similarState = *it2; QString uid = state->id(); QString newUid = similarState->id(); if (uid != newUid) mergedStates[uid] = newUid; } delete tag; // Already exists, not to be merged. Delete the shortcut and all. } } } } node = node.nextSibling(); } return mergedStates; }