12#include "config-xmlgui.h"
16#include <QDialogButtonBox>
17#include <QDomDocument>
24#include <QApplication>
29#include <QStandardPaths>
34#include <klistwidgetsearchline.h>
35#include <klocalizedstring.h>
36#include <kmessagebox.h>
37#include <kseparator.h>
49static const char separatorstring[] = QT_TRANSLATE_NOOP(
"KEditToolBar",
"--- separator ---");
51#define SEPARATORSTRING i18n(separatorstring)
67 for (QDomElement elem = start; !elem.isNull(); elem = elem.nextSiblingElement()) {
68 if (elem.tagName() == QStringLiteral(
"ToolBar")) {
69 if (elem.attribute(QStringLiteral(
"noEdit")) != QLatin1String(
"true")) {
73 if (elem.tagName() != QStringLiteral(
"MenuBar")) {
102 qDebug() <<
"XmlData" <<
this <<
"xmlFile:" <<
m_xmlFile;
103 foreach (
const QDomElement &element,
m_barList) {
110 qDebug() <<
" no action collection.";
174 const QLatin1String attrName(
"name");
177 QByteArray txt(it.namedItem(QStringLiteral(
"text")).toElement().text().toUtf8());
179 txt = it.namedItem(QStringLiteral(
"text")).toElement().text().toUtf8();
182 name = it.attribute(attrName);
184 QByteArray domain = it.namedItem(QStringLiteral(
"text")).toElement().attribute(QStringLiteral(
"translationDomain")).toUtf8();
185 if (domain.isEmpty()) {
186 domain = it.ownerDocument().documentElement().attribute(QStringLiteral(
"translationDomain")).toUtf8();
187 if (domain.isEmpty()) {
188 domain = KLocalizedString::applicationDomain();
191 name = i18nd(domain.constData(), txt.constData());
198 QString doc_name(
m_document.documentElement().attribute(attrName));
199 name += QStringLiteral(
" <") + doc_name + QLatin1Char(
'>');
207 ToolBarItem(QListWidget *parent,
const QString &tag = QString(),
const QString &name = QString(),
const QString &
statusText = QString())
208 : QListWidgetItem(parent),
216 setFlags((flags() | Qt::ItemIsDragEnabled) & ~Qt::ItemIsDropEnabled);
262 return listWidget()->row(
const_cast<ToolBarItem *
>(
this));
287 QString internalName;
305 : QListWidget(parent),
308 setDragDropMode(QAbstractItemView::DragDrop);
311#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
317 if (items.isEmpty()) {
320 QMimeData *mimedata =
new QMimeData();
324 QDataStream stream(&data, QIODevice::WriteOnly);
330 mimedata->setData(QStringLiteral(
"application/x-kde-action-list"), data);
331 mimedata->setData(QStringLiteral(
"application/x-kde-source-treewidget"), m_activeList ?
"active" :
"inactive");
339 const QByteArray data =
mimeData->data(QStringLiteral(
"application/x-kde-action-list"));
340 if (data.isEmpty()) {
343 QDataStream stream(data);
344 const bool sourceIsActiveList =
mimeData->data(QStringLiteral(
"application/x-kde-source-treewidget")) ==
"active";
347 Q_EMIT
dropped(
this, index, item, sourceIsActiveList);
353 return static_cast<ToolBarItem *
>(QListWidget::currentItem());
359 setWindowTitle(i18n(
"Change Text"));
362 QVBoxLayout *layout =
new QVBoxLayout(
this);
364 QGridLayout *grid =
new QGridLayout;
365 grid->setContentsMargins(0, 0, 0, 0);
369 QLabel *label =
new QLabel(i18n(
"Icon te&xt:"),
this);
371 grid->addWidget(label, 0, 0);
374 m_cbHidden =
new QCheckBox(i18n(
"&Hide text when toolbar shows text alongside icons"),
this);
377 layout->addLayout(grid);
380 m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
381 connect(
m_buttonBox, SIGNAL(accepted()),
this, SLOT(accept()));
382 connect(
m_buttonBox, SIGNAL(rejected()),
this, SLOT(reject()));
388 setFixedHeight(sizeHint().height());
414 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.trimmed().isEmpty());
438 const int iconSize = widget->style()->pixelMetric(QStyle::PM_SmallIconSize);
465 void initOldStyle(
const QString &file,
bool global,
const QString &defaultToolbar);
470 QString
xmlFile(
const QString &xml_file)
const
472 return xml_file.isEmpty() ?
m_componentName + QStringLiteral(
"ui.xmlgui") : xml_file;
481 QString xml_file =
xmlFile(_xml_file);
484 if (!QDir::isRelativePath(xml_file)) {
500 QDomElement elem = n.toElement();
501 if ((elem.attribute(QStringLiteral(
"name")) == item->
internalName()) &&
507 return QDomElement();
605 d->m_factory = factory;
615 q->setWindowTitle(i18n(
"Configure Toolbars"));
623 m_buttonBox->setStandardButtons(QDialogButtonBox::RestoreDefaults
624 | QDialogButtonBox::Ok
625 | QDialogButtonBox::Apply
626 | QDialogButtonBox::Cancel);
627 KGuiItem::assign(
m_buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
628 KGuiItem::assign(
m_buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply());
629 KGuiItem::assign(
m_buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
630 KGuiItem::assign(
m_buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults());
632 q->connect(
m_buttonBox, SIGNAL(rejected()), SLOT(reject()));
639 q->setMinimumSize(
q->sizeHint());
652 s_defaultToolBarName()->clear();
657 if (toolBarName.isEmpty()) {
666 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(b);
672 m_buttonBox->button(QDialogButtonBox::Apply)->setEnabled(b);
677 if (KMessageBox::warningContinueCancel(
q, i18n(
"Do you really want to reset all toolbars of this application to their default? The changes will be applied immediately."), i18n(
"Reset Toolbars"), KGuiItem(i18n(
"Reset"))) != KMessageBox::Continue) {
688 if (file.isEmpty()) {
693 if (QFile::exists(file))
694 if (!QFile::remove(file)) {
695 qWarning() <<
"Could not delete" << file;
705 int slash =
m_file.lastIndexOf(QLatin1Char(
'/')) + 1;
709 const QString xml_file = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
710 QStringLiteral(
"/kxmlgui5/") + QCoreApplication::instance()->applicationName() + QLatin1Char(
'/') +
m_file;
712 if (QFile::exists(xml_file))
713 if (!QFile::remove(xml_file)) {
714 qWarning() <<
"Could not delete " << xml_file;
722 m_widget->setGeometry(oldWidget->geometry());
740 case QDialogButtonBox::Ok:
743 case QDialogButtonBox::Apply:
746 case QDialogButtonBox::RestoreDefaults:
763 if (
m_buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
781 *s_defaultToolBarName() = QString::fromLatin1(toolbarName);
816 const QString &defaultToolBar)
818 qDebug() <<
"initOldStyle";
831 const QString localXML =
loadXMLFile(resourceFile);
837 domDoc.setContent(localXML);
857 const QString &defaultToolBar)
859 qDebug() <<
"initFromFactory";
872 if (client->
xmlFile().isEmpty()) {
902 action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
912 if (!((*it).m_isModified)) {
922 QDomNodeList menuNodes = (*it).domDocument().elementsByTagName(QStringLiteral(
"Menu"));
923 for (
int i = 0; i < menuNodes.length(); ++i) {
924 QDomNode menuNode = menuNodes.item(i);
925 QDomElement menuElement = menuNode.toElement();
926 if (menuElement.isNull()) {
929 menuElement.setAttribute(QStringLiteral(
"noMerge"), QLatin1String(
"1"));
956 if (!clients.count()) {
960 QListIterator<KisKXMLGUIClient *> clientIterator = clients;
961 clientIterator.toBack();
962 while (clientIterator.hasPrevious()) {
974 QString file(client->
xmlFile());
975 if (!file.isEmpty()) {
980 if (client == firstClient) {
985 client->
setXMLFile(file, client == firstClient );
1017 QLabel *inactive_label =
new QLabel(i18n(
"A&vailable actions:"),
m_widget);
1026 QObject::connect(
m_inactiveList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
1034 QObject::connect(scroller, &QScroller::stateChanged,
m_widget, [&](QScroller::State state) {
1041 inactiveListSearchLine->setPlaceholderText(i18nc(
"Filter as in showing only matching items",
"Filter"));
1044 QLabel *active_label =
new QLabel(i18n(
"Curr&ent actions:"),
m_widget);
1052 QObject::connect(
m_activeList, SIGNAL(itemSelectionChanged()),
1054 QObject::connect(
m_activeList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
1061 QObject::connect(scroller, &QScroller::stateChanged,
m_widget, [&](QScroller::State state) {
1076 KListWidgetSearchLine *activeListSearchLine =
new KListWidgetSearchLine(
m_widget,
m_activeList);
1077 activeListSearchLine->setPlaceholderText(i18n(
"Filter"));
1107 QVBoxLayout *top_layout =
new QVBoxLayout(
m_widget);
1108 top_layout->setContentsMargins(0, 0, 0, 0);
1110 QVBoxLayout *name_layout =
new QVBoxLayout();
1111 QHBoxLayout *list_layout =
new QHBoxLayout();
1113 QVBoxLayout *inactive_layout =
new QVBoxLayout();
1114 QVBoxLayout *active_layout =
new QVBoxLayout();
1116 QGridLayout *button_layout =
new QGridLayout();
1123 button_layout->setSpacing(0);
1124 button_layout->setRowStretch(0, 10);
1129 button_layout->setRowStretch(4, 10);
1131 inactive_layout->addWidget(inactive_label);
1132 inactive_layout->addWidget(inactiveListSearchLine);
1135 active_layout->addWidget(active_label);
1136 active_layout->addWidget(activeListSearchLine);
1140 list_layout->addLayout(inactive_layout);
1141 list_layout->addLayout(button_layout);
1142 list_layout->addLayout(active_layout);
1144 top_layout->addLayout(name_layout);
1146 top_layout->addLayout(list_layout, 10);
1148 top_layout->addWidget(
new KSeparator(
m_widget));
1153 const QLatin1String attrName(
"name");
1157 int defaultToolBarId = -1;
1161 for (; xit !=
m_xmlFiles.constEnd(); ++xit) {
1170 ToolBarList::const_iterator it = (*xit).barList().begin();
1171 for (; it != (*xit).barList().constEnd(); ++it) {
1172 const QString text = (*xit).toolBarText(*it);
1174 const QString name = (*it).attribute(attrName);
1175 if (defaultToolBarId == -1 && name == defaultToolBar) {
1176 defaultToolBarId = count;
1181 const bool showCombo = (count > 1);
1185 if (defaultToolBarId == -1) {
1186 defaultToolBarId = 0;
1195 const QLatin1String tagSeparator(
"Separator");
1196 const QLatin1String tagMerge(
"Merge");
1197 const QLatin1String tagActionList(
"ActionList");
1198 const QLatin1String tagAction(
"Action");
1199 const QLatin1String attrName(
"name");
1202 QString sep_name(QStringLiteral(
"separator_%1"));
1216 QSet<QString> active_list;
1219 KLocalizedString nameFilter = ki18nc(
"@item:intable Action name in toolbar editor",
"%1");
1222 QDomNode n = elem.firstChild();
1223 for (; !n.isNull(); n = n.nextSibling()) {
1224 QDomElement it = n.toElement();
1228 if (it.tagName() == tagSeparator) {
1236 if (it.tagName() == tagMerge) {
1238 QString name = it.attribute(attrName);
1240 if (name.isEmpty()) {
1241 act->setText(i18n(
"<Merge>"));
1243 act->setText(i18n(
"<Merge %1>", name));
1248 if (it.tagName() == tagActionList) {
1249 ToolBarItem *act =
new ToolBarItem(
m_activeList, tagActionList, it.attribute(attrName), i18n(
"This is a dynamic list of actions. You can move it, but if you remove it you will not be able to re-add it."));
1250 act->setText(i18n(
"ActionList: %1", it.attribute(attrName)));
1257 foreach (QAction *action, actionCollection->
actions()) {
1259 if (it.attribute(attrName) == action->objectName()) {
1262 act->setText(nameFilter.subs(KLocalizedString::removeAcceleratorMarker(action->iconText())).toString());
1263 act->setIcon(!action->icon().isNull() ? action->icon() :
m_emptyIcon);
1266 active_list.insert(action->objectName());
1273 foreach (QAction *action, actionCollection->
actions()) {
1275 if (active_list.contains(action->objectName())) {
1280 act->setText(nameFilter.subs(KLocalizedString::removeAcceleratorMarker(action->text())).toString());
1281 act->setIcon(!action->icon().isNull() ? action->icon() :
m_emptyIcon);
1303 int toolbarNumber = 0;
1314 ToolBarList::Iterator it = (*xit).barList().begin();
1315 for (; it != (*xit).barList().end(); ++it) {
1318 if (toolbarNumber == index) {
1349 m_helpArea->setText(i18nc(
"@label Action tooltip in toolbar editor, below the action list",
"%1", statusText));
1368 m_downAction->setEnabled(toolitem->
index() != toolitem->listWidget()->count() - 1);
1371 m_helpArea->setText(i18nc(
"@label Action tooltip in toolbar editor, below the action list",
"%1", statusText));
1395 for (
int i = 0; i < activeItemCount; i++) {
1417 QDomElement new_item;
1425 new_item.setAttribute(QStringLiteral(
"name"), item->
internalName());
1433 Q_ASSERT(!elem.isNull());
1462 if (!elem.isNull()) {
1479 int row = item->listWidget()->row(item) - 1;
1526 int newRow = item->listWidget()->row(item) + 1;
1543 static bool iconsLoaded {
false};
1548 QFileInfoList entryList = QDir(
":/").entryInfoList(QDir::Files);
1549 entryList += QDir(
":/pics/").entryInfoList(QDir::Files);
1550 const QStringList suffixes {
"png",
"svg",
"svgz"};
1552 foreach (
const QFileInfo info, entryList) {
1553 if (suffixes.contains(info.suffix())) {
1554 QString basename = info.baseName();
1555 int i = basename.indexOf(
'_', 5);
1556 basename = basename.mid(i + 1);
1567 dialog.setWindowTitle(i18n(
"Choose Icon"));
1568 dialog.resize(480, 500);
1570 QVBoxLayout *layout =
new QVBoxLayout(&dialog);
1573 QLineEdit *filterEdit =
new QLineEdit(&dialog);
1574 filterEdit->setPlaceholderText(i18n(
"Filter icons..."));
1575 layout->addWidget(filterEdit);
1578 QListWidget *list =
new QListWidget(&dialog);
1579 list->setViewMode(QListView::ListMode);
1580 list->setIconSize(QSize(22, 22));
1581 list->setResizeMode(QListWidget::Adjust);
1582 list->setSelectionMode(QAbstractItemView::SingleSelection);
1585 QObject::connect(scroller, &QScroller::stateChanged,
m_widget, [&](QScroller::State state) {
1591 for (
const QString &iconName : loadedIcons) {
1592 QListWidgetItem *item =
new QListWidgetItem(
1597 item->setData(Qt::UserRole, iconName);
1599 layout->addWidget(list);
1602 QDialogButtonBox *backButton =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog);
1603 layout->addWidget(backButton);
1605 QObject::connect(backButton, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
1606 QObject::connect(backButton, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
1609 QObject::connect(filterEdit, &QLineEdit::textChanged, &dialog, [&list](
const QString &text) {
1610 for (
int i = 0; i < list->count(); ++i) {
1611 QListWidgetItem *item = list->item(i);
1612 bool match = item->text().contains(text, Qt::CaseInsensitive);
1613 item->setHidden(!match);
1618 QString currentIconName = elem.attribute(QStringLiteral(
"icon"));
1619 for (
int i = 0; i < list->count(); ++i) {
1620 if (list->item(i)->data(Qt::UserRole).toString() == currentIconName) {
1621 list->setCurrentItem(list->item(i));
1627 if (dialog.exec() == QDialog::Accepted && list->currentItem()) {
1628 QString chosenIconName = list->currentItem()->data(Qt::UserRole).toString();
1635 QDomElement root = doc.documentElement();
1636 QDomElement overridesElem = root.namedItem(QStringLiteral(
"ActionIconOverrides")).toElement();
1637 if (overridesElem.isNull()) {
1638 overridesElem = doc.createElement(QStringLiteral(
"ActionIconOverrides"));
1639 root.appendChild(overridesElem);
1644 QDomElement overrideAction;
1645 for (QDomNode child = overridesElem.firstChild(); !child.isNull(); child = child.nextSibling()) {
1646 QDomElement childElement = child.toElement();
1647 if (childElement.attribute(QStringLiteral(
"name")) == actionName) {
1648 overrideAction = childElement;
1652 if (overrideAction.isNull()) {
1653 overrideAction = doc.createElement(QStringLiteral(
"Action"));
1654 overrideAction.setAttribute(QStringLiteral(
"name"), actionName);
1655 overridesElem.appendChild(overrideAction);
1659 overrideAction.setAttribute(QStringLiteral(
"icon"), chosenIconName);
1682 (*xit).m_isModified =
true;
1689 (*xit).m_isModified =
true;
1690 const QLatin1String attrName(
"name");
1691 ToolBarList::Iterator it = (*xit).barList().begin();
1692 for (; it != (*xit).barList().end(); ++it) {
1693 QString name((*it).attribute(attrName));
1694 QString tag((*it).tagName());
1695 if ((tag != elem.tagName()) || (name != elem.attribute(attrName))) {
1699 QDomElement toolbar = (*xit).domDocument().documentElement().toElement();
1700 toolbar.replaceChild(elem, (*it));
1705 QDomElement toolbar = (*xit).domDocument().documentElement().toElement();
1706 Q_ASSERT(!toolbar.isNull());
1707 toolbar.appendChild(elem);
1719 if (sourceIsActiveList) {
1741 if (!event->spontaneous()) {
1745 d->m_widget->load(d->m_factory, d->m_defaultToolBar);
1748 d->m_widget->load(d->m_file, d->m_global, d->m_defaultToolBar);
1753 QDialog::showEvent(event);
1761 QDialog::hideEvent(event);
1764#include "moc_kedittoolbar.cpp"
1765#include "moc_kedittoolbar_p.cpp"
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
int iconSize(qreal width, qreal height)
IconTextEditDialog(QWidget *parent=0)
void setIconText(const QString &text)
QDialogButtonBox * m_buttonBox
void setTextAlongsideIconHidden(bool hidden)
void slotTextChanged(const QString &text)
bool textAlongsideIconHidden() const
QString toolBarText(const QDomElement &it) const
KisKActionCollection * actionCollection() const
XmlData(XmlType xmlType, const QString &xmlFile, KisKActionCollection *collection)
void setDomDocument(const QDomDocument &domDoc)
const ToolBarList & barList() const
KisKActionCollection * m_actionCollection
QDomDocument & domDocument()
const QDomDocument & domDocument() const
A container for a set of QAction objects.
QList< QAction * > actions() const
void addAssociatedWidget(QWidget *widget)
void setXMLGUIBuildDocument(const QDomDocument &doc)
void setDOMDocument(const QDomDocument &document, bool merge=false)
virtual QString xmlFile() const
virtual QDomDocument domDocument() const
void loadStandardsXmlFile()
virtual QString localXMLFile() const
KisKXMLGUIFactory * factory() const
void setXMLFile(const QString &file, bool merge=false, bool setXMLDoc=true)
friend class KDEPrivate::KisKEditToolBarWidget
void setXML(const QString &document, bool merge=false)
virtual KisKActionCollection * actionCollection() const
static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName=QString())
static QString readConfigFile(const QString &filename, const QString &componentName=QString())
void removeClient(KisKXMLGUIClient *client)
void addClient(KisKXMLGUIClient *client)
QList< KisKXMLGUIClient * > clients() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
QString button(const QWheelEvent &ev)
static ToolBarList findToolBars(const QDomElement &start)
static QDataStream & operator>>(QDataStream &s, ToolBarItem &item)
static QDataStream & operator<<(QDataStream &s, const ToolBarItem &item)
QIcon loadIcon(const QString &name)
QStringList allUniqueLoadedIconNames()