/* This file is part of the KDE libraries Copyright (C) 2000 Kurt Granroth Copyright (C) 2006 Hamish Rodda Copyright 2007 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kaction.h" #include "kactioncollection.h" static const char * const separatorstring = I18N_NOOP("--- separator ---"); #define SEPARATORSTRING i18n(separatorstring) static const char* const s_XmlTypeToString[] = { "Shell", "Part", "Local", "Merged" }; typedef QList ToolBarList; namespace KDEPrivate { /** * Return a list of toolbar elements given a toplevel element */ static ToolBarList findToolBars(const QDomElement& start) { static const QString tagToolBar = QString::fromLatin1( "ToolBar" ); static const QString tagMenuBar = QString::fromLatin1( "MenuBar" ); static const QString attrNoEdit = QString::fromLatin1( "noEdit" ); ToolBarList list; for( QDomElement elem = start; !elem.isNull(); elem = elem.nextSiblingElement() ) { if (elem.tagName() == tagToolBar) { if ( elem.attribute( attrNoEdit ) != "true" ) list.append(elem); } else { if (elem.tagName() != tagMenuBar) // there are no toolbars inside the menubar :) list += findToolBars(elem.firstChildElement()); // recursive } } return list; } class XmlData { public: enum XmlType { Shell = 0, Part, Local, Merged }; explicit XmlData( XmlType xmlType, const QString& xmlFile, KActionCollection* collection ) : m_isModified(false), m_xmlFile(xmlFile), m_type(xmlType), m_actionCollection(collection) { } void dump() const { kDebug() << "XmlData" << this << "type" << s_XmlTypeToString[m_type] << "xmlFile:" << m_xmlFile; foreach (const QDomElement& element, m_barList) { kDebug() << " ToolBar:" << toolBarText( element ); } if ( m_actionCollection ) kDebug() << " " << m_actionCollection->actions().count() << "actions in the collection."; else kDebug() << " no action collection."; } QString xmlFile() const { return m_xmlFile; } XmlType type() const { return m_type; } KActionCollection* actionCollection() const { return m_actionCollection; } void setDomDocument(const QDomDocument& domDoc) { m_document = domDoc.cloneNode().toDocument(); m_barList = findToolBars(m_document.documentElement()); } // Return reference, for e.g. actionPropertiesElement() to modify the document QDomDocument& domDocument() { return m_document; } const QDomDocument& domDocument() const { return m_document; } /** * Return the text (user-visible name) of a given toolbar */ QString toolBarText( const QDomElement& it ) const; bool m_isModified; ToolBarList& barList() { return m_barList; } const ToolBarList& barList() const { return m_barList; } private: ToolBarList m_barList; QString m_xmlFile; QDomDocument m_document; XmlType m_type; KActionCollection* m_actionCollection; }; QString XmlData::toolBarText( const QDomElement& it ) const { static const QString tagText = QString::fromLatin1( "text" ); static const QString tagText2 = QString::fromLatin1( "Text" ); static const QString attrName = QString::fromLatin1( "name" ); QString name; QByteArray txt( it.namedItem( tagText ).toElement().text().toUtf8() ); if ( txt.isEmpty() ) txt = it.namedItem( tagText2 ).toElement().text().toUtf8(); if ( txt.isEmpty() ) name = it.attribute( attrName ); else name = i18n( txt ); // the name of the toolbar might depend on whether or not // it is in kparts if ( ( m_type == XmlData::Shell ) || ( m_type == XmlData::Part ) ) { QString doc_name(m_document.documentElement().attribute( attrName )); name += " <" + doc_name + '>'; } return name; } typedef QList XmlDataList; class ToolBarItem : public QListWidgetItem { public: ToolBarItem(QListWidget *parent, const QString& tag = QString(), const QString& name = QString(), const QString& statusText = QString()) : QListWidgetItem(parent), m_internalTag(tag), m_internalName(name), m_statusText(statusText), m_isSeparator(false), m_isTextAlongsideIconHidden(false) { // Drop between items, not onto items setFlags((flags() | Qt::ItemIsDragEnabled) & ~Qt::ItemIsDropEnabled); } void setInternalTag(const QString &tag) { m_internalTag = tag; } void setInternalName(const QString &name) { m_internalName = name; } void setStatusText(const QString &text) { m_statusText = text; } void setSeparator(bool sep) { m_isSeparator = sep; } void setTextAlongsideIconHidden(bool hidden) { m_isTextAlongsideIconHidden = hidden; } QString internalTag() const { return m_internalTag; } QString internalName() const { return m_internalName; } QString statusText() const { return m_statusText; } bool isSeparator() const { return m_isSeparator; } bool isTextAlongsideIconHidden() const { return m_isTextAlongsideIconHidden; } int index() const { return listWidget()->row(const_cast(this)); } private: QString m_internalTag; QString m_internalName; QString m_statusText; bool m_isSeparator; bool m_isTextAlongsideIconHidden; }; static QDataStream & operator<< ( QDataStream & s, const ToolBarItem & item ) { s << item.internalTag(); s << item.internalName(); s << item.statusText(); s << item.isSeparator(); s << item.isTextAlongsideIconHidden(); return s; } static QDataStream & operator>> ( QDataStream & s, ToolBarItem & item ) { QString internalTag; s >> internalTag; item.setInternalTag(internalTag); QString internalName; s >> internalName; item.setInternalName(internalName); QString statusText; s >> statusText; item.setStatusText(statusText); bool sep; s >> sep; item.setSeparator(sep); bool hidden; s >> hidden; item.setTextAlongsideIconHidden(hidden); return s; } //// ToolBarListWidget::ToolBarListWidget(QWidget *parent) : QListWidget(parent), m_activeList(true) { setDragDropMode(QAbstractItemView::DragDrop); // no internal moves } QMimeData* ToolBarListWidget::mimeData(const QList items) const { if (items.isEmpty()) return 0; QMimeData* mimedata = new QMimeData(); QByteArray data; { QDataStream stream(&data, QIODevice::WriteOnly); // we only support single selection ToolBarItem* item = static_cast(items.first()); stream << *item; } mimedata->setData("application/x-kde-action-list", data); mimedata->setData("application/x-kde-source-treewidget", m_activeList ? "active" : "inactive"); return mimedata; } bool ToolBarListWidget::dropMimeData(int index, const QMimeData * mimeData, Qt::DropAction action) { Q_UNUSED(action) const QByteArray data = mimeData->data("application/x-kde-action-list"); if (data.isEmpty()) return false; QDataStream stream(data); const bool sourceIsActiveList = mimeData->data("application/x-kde-source-treewidget") == "active"; ToolBarItem* item = new ToolBarItem(this); // needs parent, use this temporarily stream >> *item; emit dropped(this, index, item, sourceIsActiveList); return true; } ToolBarItem* ToolBarListWidget::currentItem() const { return static_cast(QListWidget::currentItem()); } IconTextEditDialog::IconTextEditDialog(QWidget *parent) : KDialog(parent) { setCaption(i18n("Change Text")); setButtons(Ok | Cancel); setDefaultButton(Ok); setModal(true); QWidget *mainWidget = new QWidget(this); QGridLayout *layout = new QGridLayout(mainWidget); layout->setMargin(0); m_lineEdit = new KLineEdit(mainWidget); m_lineEdit->setClearButtonShown(true); QLabel *label = new QLabel(i18n("Icon te&xt:"), this); label->setBuddy(m_lineEdit); layout->addWidget(label, 0, 0); layout->addWidget(m_lineEdit, 0, 1); m_cbHidden = new QCheckBox(i18n("&Hide text when toolbar shows text alongside icons"), mainWidget); layout->addWidget(m_cbHidden, 1, 1); connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(slotTextChanged(QString))); m_lineEdit->setFocus(); setMainWidget(mainWidget); setFixedHeight(sizeHint().height()); } void IconTextEditDialog::setIconText(const QString &text) { m_lineEdit->setText(text); } QString IconTextEditDialog::iconText() const { return m_lineEdit->text().trimmed(); } void IconTextEditDialog::setTextAlongsideIconHidden(bool hidden) { m_cbHidden->setChecked(hidden); } bool IconTextEditDialog::textAlongsideIconHidden() const { return m_cbHidden->isChecked(); } void IconTextEditDialog::slotTextChanged(const QString &text) { // Do not allow empty icon text enableButton(Ok, !text.trimmed().isEmpty()); } class KEditToolBarWidgetPrivate { public: /** * * @param collection In the old-style constructor, this is the collection passed * to the KEditToolBar constructor. * In the xmlguifactory-based constructor, we let KXMLGUIClient create a dummy one, * but it probably isn't used. */ KEditToolBarWidgetPrivate(KEditToolBarWidget* widget, const KComponentData &cData, KActionCollection* collection) : m_collection( collection ), m_widget(widget), m_factory(NULL), m_loadedOnce( false ) { m_componentData = cData; m_isPart = false; m_helpArea = 0L; m_kdialogProcess = 0; // We want items with an icon to align with items without icon // So we use an empty QPixmap for that const int iconSize = widget->style()->pixelMetric(QStyle::PM_SmallIconSize); m_emptyIcon = QPixmap(iconSize, iconSize); m_emptyIcon.fill(Qt::transparent); } ~KEditToolBarWidgetPrivate() { } // private slots void slotToolBarSelected(int index); void slotInactiveSelectionChanged(); void slotActiveSelectionChanged(); void slotInsertButton(); void slotRemoveButton(); void slotUpButton(); void slotDownButton(); void selectActiveItem(const QString&); void slotChangeIcon(); void slotChangeIconText(); void slotProcessExited(); void slotDropped(ToolBarListWidget* list, int index, ToolBarItem* item, bool sourceIsActiveList); void setupLayout(); void initOldStyle( const QString& file, bool global, const QString& defaultToolbar ); void initFromFactory( KXMLGUIFactory* factory, const QString& defaultToolbar ); void loadToolBarCombo( const QString& defaultToolbar ); void loadActions(const QDomElement& elem); QString xmlFile(const QString& xml_file) const { return xml_file.isEmpty() ? QString(m_componentData.componentName()) + "ui.rc" : xml_file; } /** * Load in the specified XML file and dump the raw xml */ QString loadXMLFile(const QString& _xml_file) { QString raw_xml; QString xml_file = xmlFile(_xml_file); //kDebug() << "loadXMLFile xml_file=" << xml_file; if ( !QDir::isRelativePath(xml_file) ) raw_xml = KXMLGUIFactory::readConfigFile(xml_file); else raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_componentData); return raw_xml; } /** * Look for a given item in the current toolbar */ QDomElement findElementForToolBarItem( const ToolBarItem* item ) const { static const QString attrName = QString::fromLatin1( "name" ); // kDebug() << "looking for name=" << item->internalName() << "and tag=" << item->internalTag(); for(QDomNode n = m_currentToolBarElem.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement elem = n.toElement(); if ((elem.attribute(attrName) == item->internalName()) && (elem.tagName() == item->internalTag())) return elem; } // kDebug() << "no item found in the DOM with name=" << item->internalName() << "and tag=" << item->internalTag(); return QDomElement(); } void insertActive(ToolBarItem *item, ToolBarItem *before, bool prepend = false); void removeActive(ToolBarItem *item); void moveActive(ToolBarItem *item, ToolBarItem *before); void updateLocal(QDomElement& elem); #ifndef NDEBUG void dump() const { XmlDataList::const_iterator xit = m_xmlFiles.begin(); for ( ; xit != m_xmlFiles.end(); ++xit ) { (*xit).dump(); } } #endif KComboBox *m_toolbarCombo; QToolButton *m_upAction; QToolButton *m_removeAction; QToolButton *m_insertAction; QToolButton *m_downAction; //QValueList m_actionList; KActionCollection* m_collection; KEditToolBarWidget* m_widget; KXMLGUIFactory* m_factory; KComponentData m_componentData; QPixmap m_emptyIcon; XmlData* m_currentXmlData; QDomElement m_currentToolBarElem; QString m_xmlFile; QString m_globalFile; QString m_rcFile; QDomDocument m_localDoc; ToolBarList m_barList; ToolBarListWidget *m_inactiveList; ToolBarListWidget *m_activeList; XmlDataList m_xmlFiles; QLabel *m_comboLabel; KSeparator *m_comboSeparator; QLabel * m_helpArea; KPushButton* m_changeIcon; KPushButton* m_changeIconText; QProcess* m_kdialogProcess; bool m_isPart : 1; bool m_hasKDialog : 1; bool m_loadedOnce : 1; }; } using namespace KDEPrivate; class KEditToolBarPrivate { public: KEditToolBarPrivate(KEditToolBar *q): q(q), m_accept(false), m_global(false), m_collection(0), m_factory(0), m_widget(0) {} void init(); void _k_slotOk(); void _k_slotApply(); void _k_acceptOK(bool); void _k_slotDefault(); KEditToolBar *q; bool m_accept; // Save parameters for recreating widget after resetting toolbar bool m_global; KActionCollection* m_collection; QString m_file; QString m_defaultToolBar; KXMLGUIFactory* m_factory; KEditToolBarWidget *m_widget; }; K_GLOBAL_STATIC(QString, s_defaultToolBarName) KEditToolBar::KEditToolBar( KActionCollection *collection, QWidget* parent ) : KDialog(parent), d(new KEditToolBarPrivate(this)) { d->m_widget = new KEditToolBarWidget( collection, this); d->init(); d->m_collection = collection; } KEditToolBar::KEditToolBar( KXMLGUIFactory* factory, QWidget* parent ) : KDialog(parent), d(new KEditToolBarPrivate(this)) { d->m_widget = new KEditToolBarWidget( this); d->init(); d->m_factory = factory; } void KEditToolBarPrivate::init() { m_accept = false; m_factory = 0; q->setDefaultToolBar( QString() ); q->setCaption(i18n("Configure Toolbars")); q->setButtons(KDialog::Default|KDialog::Ok|KDialog::Apply|KDialog::Cancel); q->setDefaultButton(KDialog::Ok); q->setModal(false); q->setMainWidget(m_widget); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_acceptOK(bool))); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool))); q->enableButtonApply(false); q->connect(q, SIGNAL(okClicked()), SLOT(_k_slotOk())); q->connect(q, SIGNAL(applyClicked()), SLOT(_k_slotApply())); q->connect(q, SIGNAL(defaultClicked()), SLOT(_k_slotDefault())); q->setMinimumSize(q->sizeHint()); } void KEditToolBar::setResourceFile( const QString& file, bool global ) { d->m_file = file; d->m_global = global; d->m_widget->load( d->m_file, d->m_global, d->m_defaultToolBar ); } KEditToolBar::~KEditToolBar() { delete d; s_defaultToolBarName->clear(); } void KEditToolBar::setDefaultToolBar( const QString& toolBarName ) { if ( toolBarName.isEmpty() ) { d->m_defaultToolBar = *s_defaultToolBarName; } else { d->m_defaultToolBar = toolBarName; } } void KEditToolBarPrivate::_k_acceptOK(bool b) { q->enableButtonOk(b); m_accept = b; } void KEditToolBarPrivate::_k_slotDefault() { 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 ) return; KEditToolBarWidget * oldWidget = m_widget; m_widget = 0; m_accept = false; if ( m_factory ) { foreach (KXMLGUIClient* client, m_factory->clients()) { const QString file = client->localXMLFile(); if (file.isEmpty()) continue; kDebug() << "Deleting local xml file" << file; // << "for client" << client << typeid(*client).name(); if ( QFile::exists( file ) ) if ( !QFile::remove( file ) ) kWarning() << "Could not delete" << file; } // Reload the xml files in all clients, now that the local files are gone oldWidget->rebuildKXMLGUIClients(); m_widget = new KEditToolBarWidget( q ); m_widget->load( m_factory, m_defaultToolBar ); } else { int slash = m_file.lastIndexOf('/')+1; if (slash) m_file = m_file.mid(slash); QString xml_file = KStandardDirs::locateLocal("data", KGlobal::mainComponent().componentName() + '/' + m_file); if ( QFile::exists( xml_file ) ) if ( !QFile::remove( xml_file ) ) kWarning() << "Could not delete " << xml_file; m_widget = new KEditToolBarWidget( m_collection, q ); q->setResourceFile( m_file, m_global ); } // Copy the geometry to minimize UI flicker m_widget->setGeometry( oldWidget->geometry() ); q->setMainWidget(m_widget); delete oldWidget; q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_acceptOK(bool))); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool))); q->enableButtonApply(false); emit q->newToolBarConfig(); } void KEditToolBarPrivate::_k_slotOk() { if (!m_accept) { q->reject(); return; } if (!m_widget->save()) { // some error box here is needed } else { // Do not emit the "newToolBarConfig" signal again here if the "Apply" // button was already pressed and no further changes were made. if (q->isButtonEnabled(KDialog::Apply)) { emit q->newToolBarConfig(); } q->accept(); } } void KEditToolBarPrivate::_k_slotApply() { (void)m_widget->save(); q->enableButtonApply(false); emit q->newToolBarConfig(); } void KEditToolBar::setGlobalDefaultToolBar(const char *toolbarName) { *s_defaultToolBarName = QString::fromLatin1(toolbarName); } KEditToolBarWidget::KEditToolBarWidget( KActionCollection *collection, QWidget *parent ) : QWidget(parent), d(new KEditToolBarWidgetPrivate(this, componentData(), collection)) { d->setupLayout(); } KEditToolBarWidget::KEditToolBarWidget( QWidget *parent ) : QWidget(parent), d(new KEditToolBarWidgetPrivate(this, componentData(), KXMLGUIClient::actionCollection() /*create new one*/)) { d->setupLayout(); } KEditToolBarWidget::~KEditToolBarWidget() { delete d; } void KEditToolBarWidget::load( const QString& file, bool global, const QString& defaultToolBar ) { d->initOldStyle( file, global, defaultToolBar ); } void KEditToolBarWidget::load( KXMLGUIFactory* factory, const QString& defaultToolBar ) { d->initFromFactory( factory, defaultToolBar ); } void KEditToolBarWidgetPrivate::initOldStyle( const QString& resourceFile, bool global, const QString& defaultToolBar ) { //TODO: make sure we can call this multiple times? if ( m_loadedOnce ) { return; } m_loadedOnce = true; //d->m_actionList = collection->actions(); // handle the merging if (global) m_widget->loadStandardsXmlFile(); // ui_standards.rc const QString localXML = loadXMLFile( resourceFile ); m_widget->setXML(localXML, global ? true /*merge*/ : false); // first, get all of the necessary info for our local xml XmlData local(XmlData::Local, xmlFile(resourceFile), m_collection); QDomDocument domDoc; domDoc.setContent(localXML); local.setDomDocument(domDoc); m_xmlFiles.append(local); // then, the merged one (ui_standards + local xml) XmlData merge(XmlData::Merged, QString(), m_collection); merge.setDomDocument(m_widget->domDocument()); m_xmlFiles.append(merge); #ifndef NDEBUG dump(); #endif // now load in our toolbar combo box loadToolBarCombo( defaultToolBar ); m_widget->adjustSize(); m_widget->setMinimumSize( m_widget->sizeHint() ); } void KEditToolBarWidgetPrivate::initFromFactory(KXMLGUIFactory* factory, const QString& defaultToolBar) { //TODO: make sure we can call this multiple times? if ( m_loadedOnce ) { return; } m_loadedOnce = true; m_factory = factory; // add all of the client data bool first = true; foreach (KXMLGUIClient* client, factory->clients()) { if (client->xmlFile().isEmpty()) continue; XmlData::XmlType type = XmlData::Part; if ( first ) { type = XmlData::Shell; first = false; Q_ASSERT(!client->localXMLFile().isEmpty()); // where would we save changes?? } XmlData data(type, client->localXMLFile(), client->actionCollection()); QDomDocument domDoc = client->domDocument(); data.setDomDocument(domDoc); m_xmlFiles.append(data); //d->m_actionList += client->actionCollection()->actions(); } #ifndef NDEBUG //d->dump(); #endif // now load in our toolbar combo box loadToolBarCombo( defaultToolBar ); m_widget->adjustSize(); m_widget->setMinimumSize( m_widget->sizeHint() ); m_widget->actionCollection()->addAssociatedWidget( m_widget ); foreach (QAction* action, m_widget->actionCollection()->actions()) action->setShortcutContext(Qt::WidgetWithChildrenShortcut); } bool KEditToolBarWidget::save() { //kDebug() << "KEditToolBarWidget::save"; XmlDataList::Iterator it = d->m_xmlFiles.begin(); for ( ; it != d->m_xmlFiles.end(); ++it) { // let's not save non-modified files if ( !((*it).m_isModified) ) continue; // let's also skip (non-existent) merged files if ( (*it).type() == XmlData::Merged ) continue; // Add noMerge="1" to all the menus since we are saving the merged data QDomNodeList menuNodes = (*it).domDocument().elementsByTagName( "Menu" ); for (int i = 0; i < menuNodes.length(); ++i) { QDomNode menuNode = menuNodes.item(i); QDomElement menuElement = menuNode.toElement(); if (menuElement.isNull()) continue; menuElement.setAttribute( "noMerge", "1" ); } kDebug() << (*it).domDocument().toString(); kDebug() << "Saving " << (*it).xmlFile(); // if we got this far, we might as well just save it KXMLGUIFactory::saveConfigFile((*it).domDocument(), (*it).xmlFile()); } if (!d->m_factory) return true; rebuildKXMLGUIClients(); return true; } void KEditToolBarWidget::rebuildKXMLGUIClients() { if (!d->m_factory) return; const QList clients = d->m_factory->clients(); // kDebug() << "factory: " << clients.count() << " clients"; // remove the elements starting from the last going to the first if (!clients.count()) return; QListIterator clientIterator = clients; clientIterator.toBack(); while (clientIterator.hasPrevious()) { KXMLGUIClient* client = clientIterator.previous(); // kDebug() << "factory->removeClient " << client; d->m_factory->removeClient(client); } KXMLGUIClient *firstClient = clients.first(); // now, rebuild the gui from the first to the last // kDebug() << "rebuilding the gui"; foreach (KXMLGUIClient* client, clients) { //kDebug() << "updating client " << client << " " << client->componentData().componentName() << " xmlFile=" << client->xmlFile(); QString file( client->xmlFile() ); // before setting ui_standards! if ( !file.isEmpty() ) { // passing an empty stream forces the clients to reread the XML client->setXMLGUIBuildDocument( QDomDocument() ); // for the shell, merge in ui_standards.rc if ( client == firstClient ) // same assumption as in the ctor: first==shell client->loadStandardsXmlFile(); // and this forces it to use the *new* XML file client->setXMLFile( file, client == firstClient /* merge if shell */ ); // [we can't use reloadXML, it doesn't load ui_standards.rc] } } // Now we can add the clients to the factory // We don't do it in the loop above because adding a part automatically // adds its plugins, so we must make sure the plugins were updated first. foreach(KXMLGUIClient* client, clients) { d->m_factory->addClient(client); } } void KEditToolBarWidgetPrivate::setupLayout() { // the toolbar name combo m_comboLabel = new QLabel(i18n("&Toolbar:"), m_widget); m_toolbarCombo = new KComboBox(m_widget); m_comboLabel->setBuddy(m_toolbarCombo); m_comboSeparator = new KSeparator(m_widget); QObject::connect(m_toolbarCombo, SIGNAL(activated(int)), m_widget, SLOT(slotToolBarSelected(int))); // QPushButton *new_toolbar = new QPushButton(i18n("&New"), this); // new_toolbar->setPixmap(BarIcon("document-new", KIconLoader::SizeSmall)); // new_toolbar->setEnabled(false); // disabled until implemented // QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this); // del_toolbar->setPixmap(BarIcon("edit-delete", KIconLoader::SizeSmall)); // del_toolbar->setEnabled(false); // disabled until implemented // our list of inactive actions QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), m_widget); m_inactiveList = new ToolBarListWidget(m_widget); m_inactiveList->setDragEnabled(true); m_inactiveList->setActiveList(false); m_inactiveList->setMinimumSize(180, 250); m_inactiveList->setDropIndicatorShown(false); // #165663 inactive_label->setBuddy(m_inactiveList); QObject::connect(m_inactiveList, SIGNAL(itemSelectionChanged()), m_widget, SLOT(slotInactiveSelectionChanged())); QObject::connect(m_inactiveList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), m_widget, SLOT(slotInsertButton())); QObject::connect(m_inactiveList, SIGNAL(dropped(ToolBarListWidget*,int,ToolBarItem*,bool)), m_widget, SLOT(slotDropped(ToolBarListWidget*,int,ToolBarItem*,bool))); KListWidgetSearchLine *inactiveListSearchLine = new KListWidgetSearchLine(m_widget, m_inactiveList); inactiveListSearchLine->setClickMessage(i18n("Filter")); // our list of active actions QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), m_widget); m_activeList = new ToolBarListWidget(m_widget); m_activeList->setDragEnabled(true); m_activeList->setActiveList(true); // With Qt-4.1 only setting MiniumWidth results in a 0-width icon column ... m_activeList->setMinimumSize(m_inactiveList->minimumWidth(), 100); active_label->setBuddy(m_activeList); QObject::connect(m_activeList, SIGNAL(itemSelectionChanged()), m_widget, SLOT(slotActiveSelectionChanged())); QObject::connect(m_activeList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), m_widget, SLOT(slotRemoveButton())); QObject::connect(m_activeList, SIGNAL(dropped(ToolBarListWidget*,int,ToolBarItem*,bool)), m_widget, SLOT(slotDropped(ToolBarListWidget*,int,ToolBarItem*,bool))); KListWidgetSearchLine *activeListSearchLine = new KListWidgetSearchLine(m_widget, m_activeList); activeListSearchLine->setClickMessage(i18n("Filter")); // "change icon" button m_changeIcon = new KPushButton(i18n( "Change &Icon..." ), m_widget); m_changeIcon->setIcon(KIcon("preferences-desktop-icons")); QString kdialogExe = KStandardDirs::findExe(QLatin1String("kdialog")); m_hasKDialog = !kdialogExe.isEmpty(); m_changeIcon->setEnabled(m_hasKDialog && m_activeList->currentItem()); QObject::connect( m_changeIcon, SIGNAL(clicked()), m_widget, SLOT(slotChangeIcon()) ); // "change icon text" button m_changeIconText = new KPushButton(i18n( "Change Te&xt..." ), m_widget); m_changeIconText->setIcon(KIcon("edit-rename")); m_changeIconText->setEnabled(m_activeList->currentItem() != 0); QObject::connect( m_changeIconText, SIGNAL(clicked()), m_widget, SLOT(slotChangeIconText()) ); // The buttons in the middle m_upAction = new QToolButton(m_widget); m_upAction->setIcon( KIcon("go-up") ); m_upAction->setEnabled(false); m_upAction->setAutoRepeat(true); QObject::connect(m_upAction, SIGNAL(clicked()), m_widget, SLOT(slotUpButton())); m_insertAction = new QToolButton(m_widget); m_insertAction->setIcon( KIcon(QApplication::isRightToLeft() ? "go-previous" : "go-next") ); m_insertAction->setEnabled(false); QObject::connect(m_insertAction, SIGNAL(clicked()), m_widget, SLOT(slotInsertButton())); m_removeAction = new QToolButton(m_widget); m_removeAction->setIcon( KIcon(QApplication::isRightToLeft() ? "go-next" : "go-previous") ); m_removeAction->setEnabled(false); QObject::connect(m_removeAction, SIGNAL(clicked()), m_widget, SLOT(slotRemoveButton())); m_downAction = new QToolButton(m_widget); m_downAction->setIcon( KIcon("go-down") ); m_downAction->setEnabled(false); m_downAction->setAutoRepeat(true); QObject::connect(m_downAction, SIGNAL(clicked()), m_widget, SLOT(slotDownButton())); m_helpArea = new QLabel(m_widget); m_helpArea->setWordWrap(true); // now start with our layouts QVBoxLayout *top_layout = new QVBoxLayout(m_widget); top_layout->setMargin(0); QVBoxLayout *name_layout = new QVBoxLayout(); QHBoxLayout *list_layout = new QHBoxLayout(); QVBoxLayout *inactive_layout = new QVBoxLayout(); QVBoxLayout *active_layout = new QVBoxLayout(); QHBoxLayout *changeIcon_layout = new QHBoxLayout(); QGridLayout *button_layout = new QGridLayout(); name_layout->addWidget(m_comboLabel); name_layout->addWidget(m_toolbarCombo); // name_layout->addWidget(new_toolbar); // name_layout->addWidget(del_toolbar); button_layout->setSpacing( 0 ); button_layout->setRowStretch( 0, 10 ); button_layout->addWidget(m_upAction, 1, 1); button_layout->addWidget(m_removeAction, 2, 0); button_layout->addWidget(m_insertAction, 2, 2); button_layout->addWidget(m_downAction, 3, 1); button_layout->setRowStretch( 4, 10 ); inactive_layout->addWidget(inactive_label); inactive_layout->addWidget(inactiveListSearchLine); inactive_layout->addWidget(m_inactiveList, 1); active_layout->addWidget(active_label); active_layout->addWidget(activeListSearchLine); active_layout->addWidget(m_activeList, 1); active_layout->addLayout(changeIcon_layout); changeIcon_layout->addWidget(m_changeIcon); changeIcon_layout->addStretch( 1 ); changeIcon_layout->addWidget(m_changeIconText); list_layout->addLayout(inactive_layout); list_layout->addLayout(button_layout); list_layout->addLayout(active_layout); top_layout->addLayout(name_layout); top_layout->addWidget(m_comboSeparator); top_layout->addLayout(list_layout,10); top_layout->addWidget(m_helpArea); top_layout->addWidget(new KSeparator(m_widget)); } void KEditToolBarWidgetPrivate::loadToolBarCombo( const QString& defaultToolBar ) { const QLatin1String attrName( "name" ); // just in case, we clear our combo m_toolbarCombo->clear(); int defaultToolBarId = -1; int count = 0; // load in all of the toolbar names into this combo box XmlDataList::const_iterator xit = m_xmlFiles.constBegin(); for ( ; xit != m_xmlFiles.constEnd(); ++xit) { // skip the merged one in favor of the local one, // so that we can change icons // This also makes the app-defined named for "mainToolBar" appear rather than the ui_standards-defined name. if ( (*xit).type() == XmlData::Merged ) continue; // each xml file may have any number of toolbars ToolBarList::const_iterator it = (*xit).barList().begin(); for ( ; it != (*xit).barList().constEnd(); ++it) { const QString text = (*xit).toolBarText( *it ); m_toolbarCombo->addItem( text ); const QString name = (*it).attribute(attrName); if (defaultToolBarId == -1 && name == defaultToolBar) defaultToolBarId = count; count++; } } const bool showCombo = (count > 1); m_comboLabel->setVisible(showCombo); m_comboSeparator->setVisible(showCombo); m_toolbarCombo->setVisible(showCombo); if (defaultToolBarId == -1) defaultToolBarId = 0; // we want to the specified item selected and its actions loaded m_toolbarCombo->setCurrentIndex(defaultToolBarId); slotToolBarSelected(m_toolbarCombo->currentIndex()); } void KEditToolBarWidgetPrivate::loadActions(const QDomElement& elem) { const QLatin1String tagSeparator( "Separator" ); const QLatin1String tagMerge( "Merge" ); const QLatin1String tagActionList( "ActionList" ); const QLatin1String tagAction( "Action" ); const QLatin1String attrName( "name" ); int sep_num = 0; QString sep_name("separator_%1"); // clear our lists m_inactiveList->clear(); m_activeList->clear(); m_insertAction->setEnabled(false); m_removeAction->setEnabled(false); m_upAction->setEnabled(false); m_downAction->setEnabled(false); // We'll use this action collection KActionCollection* actionCollection = m_currentXmlData->actionCollection(); // store the names of our active actions QSet active_list; // Filtering message requested by translators (scripting). KLocalizedString nameFilter = ki18nc("@item:intable Action name in toolbar editor", "%1"); // see if our current action is in this toolbar QDomNode n = elem.firstChild(); for( ; !n.isNull(); n = n.nextSibling() ) { QDomElement it = n.toElement(); if (it.isNull()) continue; if (it.tagName() == tagSeparator) { ToolBarItem *act = new ToolBarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString()); act->setSeparator(true); act->setText(SEPARATORSTRING); it.setAttribute( attrName, act->internalName() ); continue; } if (it.tagName() == tagMerge) { // Merge can be named or not - use the name if there is one QString name = it.attribute( attrName ); ToolBarItem *act = new ToolBarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component.")); if ( name.isEmpty() ) act->setText(i18n("")); else act->setText(i18n("", name)); continue; } if (it.tagName() == tagActionList) { 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.") ); act->setText(i18n("ActionList: %1", it.attribute(attrName))); continue; } // iterate through this client's actions // This used to iterate through _all_ actions, but we don't support // putting any action into any client... foreach (QAction* action, actionCollection->actions()) { // do we have a match? if (it.attribute( attrName ) == action->objectName()) { // we have a match! ToolBarItem *act = new ToolBarItem(m_activeList, it.tagName(), action->objectName(), action->toolTip()); act->setText(nameFilter.subs(KGlobal::locale()->removeAcceleratorMarker(action->iconText())).toString()); act->setIcon(!action->icon().isNull() ? action->icon() : m_emptyIcon); act->setTextAlongsideIconHidden(action->priority() < QAction::NormalPriority); active_list.insert(action->objectName()); break; } } } // go through the rest of the collection foreach (QAction* action, actionCollection->actions()) { // skip our active ones if (active_list.contains(action->objectName())) continue; ToolBarItem *act = new ToolBarItem(m_inactiveList, tagAction, action->objectName(), action->toolTip()); act->setText(nameFilter.subs(KGlobal::locale()->removeAcceleratorMarker(action->text())).toString()); act->setIcon(!action->icon().isNull() ? action->icon() : m_emptyIcon); } m_inactiveList->sortItems(Qt::AscendingOrder); // finally, add default separators to the inactive list ToolBarItem *act = new ToolBarItem(0L, tagSeparator, sep_name.arg(sep_num++), QString()); act->setSeparator(true); act->setText(SEPARATORSTRING); m_inactiveList->insertItem(0, act); } KActionCollection *KEditToolBarWidget::actionCollection() const { return d->m_collection; } void KEditToolBarWidgetPrivate::slotToolBarSelected(int index) { const QLatin1String attrName( "name" ); // We need to find the XmlData and toolbar element for this index // To do that, we do the same iteration as the one which filled in the combobox. int toolbarNumber = 0; XmlDataList::iterator xit = m_xmlFiles.begin(); for ( ; xit != m_xmlFiles.end(); ++xit) { // skip the merged one in favor of the local one, // so that we can change icons if ( (*xit).type() == XmlData::Merged ) continue; // each xml file may have any number of toolbars ToolBarList::Iterator it = (*xit).barList().begin(); for ( ; it != (*xit).barList().end(); ++it) { // is this our toolbar? if (toolbarNumber == index) { // save our current settings m_currentXmlData = & (*xit); m_currentToolBarElem = *it; kDebug() << "found toolbar" << m_currentXmlData->toolBarText(*it) << "m_currentXmlData set to"; m_currentXmlData->dump(); // If this is a Merged xmldata, clicking the "change icon" button would assert... Q_ASSERT( m_currentXmlData->type() != XmlData::Merged ); // load in our values loadActions(m_currentToolBarElem); if ((*xit).type() == XmlData::Part || (*xit).type() == XmlData::Shell) m_widget->setDOMDocument( (*xit).domDocument() ); return; } ++toolbarNumber; } } } void KEditToolBarWidgetPrivate::slotInactiveSelectionChanged() { if (m_inactiveList->selectedItems().count()) { m_insertAction->setEnabled(true); QString statusText = static_cast(m_inactiveList->selectedItems().first())->statusText(); m_helpArea->setText( i18nc("@label Action tooltip in toolbar editor, below the action list", "%1", statusText) ); } else { m_insertAction->setEnabled(false); m_helpArea->setText( QString() ); } } void KEditToolBarWidgetPrivate::slotActiveSelectionChanged() { ToolBarItem* toolitem = 0; if (!m_activeList->selectedItems().isEmpty()) toolitem = static_cast(m_activeList->selectedItems().first()); m_removeAction->setEnabled( toolitem ); m_changeIcon->setEnabled( toolitem && m_hasKDialog && toolitem->internalTag() == "Action" ); m_changeIconText->setEnabled( toolitem && toolitem->internalTag() == "Action" ); if (toolitem) { m_upAction->setEnabled(toolitem->index() != 0); m_downAction->setEnabled(toolitem->index() != toolitem->listWidget()->count() - 1); QString statusText = toolitem->statusText(); m_helpArea->setText( i18nc("@label Action tooltip in toolbar editor, below the action list", "%1", statusText) ); } else { m_upAction->setEnabled(false); m_downAction->setEnabled(false); m_helpArea->setText( QString() ); } } void KEditToolBarWidgetPrivate::slotInsertButton() { QString internalName = static_cast(m_inactiveList->currentItem())->internalName(); insertActive(m_inactiveList->currentItem(), m_activeList->currentItem(), false); // we're modified, so let this change emit m_widget->enableOk(true); slotToolBarSelected( m_toolbarCombo->currentIndex() ); selectActiveItem( internalName ); } void KEditToolBarWidgetPrivate::selectActiveItem(const QString& internalName) { int activeItemCount = m_activeList->count(); for(int i = 0; i < activeItemCount; i++) { ToolBarItem * item = static_cast(m_activeList->item(i)); if (item->internalName()==internalName) { m_activeList->setCurrentItem(item); break; } } } void KEditToolBarWidgetPrivate::slotRemoveButton() { removeActive( m_activeList->currentItem() ); slotToolBarSelected( m_toolbarCombo->currentIndex() ); } void KEditToolBarWidgetPrivate::insertActive(ToolBarItem *item, ToolBarItem *before, bool prepend) { if (!item) return; static const QString tagAction = QString::fromLatin1( "Action" ); static const QString tagSeparator = QString::fromLatin1( "Separator" ); static const QString attrName = QString::fromLatin1( "name" ); static const QString attrNoMerge = QString::fromLatin1( "noMerge" ); QDomElement new_item; // let's handle the separator specially if (item->isSeparator()) new_item = m_widget->domDocument().createElement(tagSeparator); else new_item = m_widget->domDocument().createElement(tagAction); new_item.setAttribute(attrName, item->internalName()); Q_ASSERT(!m_currentToolBarElem.isNull()); if (before) { // we have the item in the active list which is before the new // item.. so let's try our best to add our new item right after it QDomElement elem = findElementForToolBarItem( before ); Q_ASSERT( !elem.isNull() ); m_currentToolBarElem.insertAfter(new_item, elem); } else { // simply put it at the beginning or the end of the list. if (prepend) m_currentToolBarElem.insertBefore(new_item, m_currentToolBarElem.firstChild()); else m_currentToolBarElem.appendChild(new_item); } // and set this container as a noMerge m_currentToolBarElem.setAttribute( attrNoMerge, "1"); // update the local doc updateLocal(m_currentToolBarElem); } void KEditToolBarWidgetPrivate::removeActive(ToolBarItem *item) { if (!item) return; static const QString attrNoMerge = QString::fromLatin1( "noMerge" ); // we're modified, so let this change emit m_widget->enableOk(true); // now iterate through to find the child to nuke QDomElement elem = findElementForToolBarItem( item ); if ( !elem.isNull() ) { // nuke myself! m_currentToolBarElem.removeChild(elem); // and set this container as a noMerge m_currentToolBarElem.setAttribute( attrNoMerge, "1"); // update the local doc updateLocal(m_currentToolBarElem); } } void KEditToolBarWidgetPrivate::slotUpButton() { ToolBarItem *item = m_activeList->currentItem(); if (!item) { Q_ASSERT(false); return; } int row = item->listWidget()->row(item) - 1; // make sure we're not the top item already if (row < 0) { Q_ASSERT(false); return; } // we're modified, so let this change emit m_widget->enableOk(true); moveActive( item, static_cast(item->listWidget()->item(row - 1)) ); } void KEditToolBarWidgetPrivate::moveActive( ToolBarItem* item, ToolBarItem* before ) { QDomElement e = findElementForToolBarItem( item ); if ( e.isNull() ) return; // remove item m_activeList->takeItem(m_activeList->row(item)); // put it where it's supposed to go m_activeList->insertItem(m_activeList->row(before) + 1, item); // make it selected again m_activeList->setCurrentItem(item); // and do the real move in the DOM if ( !before ) m_currentToolBarElem.insertBefore(e, m_currentToolBarElem.firstChild() ); else m_currentToolBarElem.insertAfter(e, findElementForToolBarItem( (ToolBarItem*)before )); // and set this container as a noMerge static const QString attrNoMerge = QString::fromLatin1( "noMerge" ); m_currentToolBarElem.setAttribute( attrNoMerge, "1"); // update the local doc updateLocal(m_currentToolBarElem); } void KEditToolBarWidgetPrivate::slotDownButton() { ToolBarItem *item = m_activeList->currentItem(); if (!item) { Q_ASSERT(false); return; } // make sure we're not the bottom item already int newRow = item->listWidget()->row(item) + 1; if (newRow >= item->listWidget()->count()) { Q_ASSERT(false); return; } // we're modified, so let this change emit m_widget->enableOk(true); moveActive( item, static_cast(item->listWidget()->item(newRow)) ); } void KEditToolBarWidgetPrivate::updateLocal(QDomElement& elem) { static const QString attrName = QString::fromLatin1( "name" ); XmlDataList::Iterator xit = m_xmlFiles.begin(); for ( ; xit != m_xmlFiles.end(); ++xit) { if ( (*xit).type() == XmlData::Merged ) continue; if ( (*xit).type() == XmlData::Shell || (*xit).type() == XmlData::Part ) { if ( m_currentXmlData->xmlFile() == (*xit).xmlFile() ) { (*xit).m_isModified = true; return; } continue; } (*xit).m_isModified = true; ToolBarList::Iterator it = (*xit).barList().begin(); for ( ; it != (*xit).barList().end(); ++it) { QString name( (*it).attribute( attrName ) ); QString tag( (*it).tagName() ); if ( (tag != elem.tagName()) || (name != elem.attribute(attrName)) ) continue; QDomElement toolbar = (*xit).domDocument().documentElement().toElement(); toolbar.replaceChild(elem, (*it)); return; } // just append it QDomElement toolbar = (*xit).domDocument().documentElement().toElement(); Q_ASSERT(!toolbar.isNull()); toolbar.appendChild(elem); } } void KEditToolBarWidgetPrivate::slotChangeIcon() { // We can't use KIconDialog here, since it's in libkio // ##### KDE4: reconsider this, e.g. move KEditToolBar to libkio //if the process is already running (e.g. when somebody clicked the change button twice (see #127149)) - do nothing... //otherwise m_kdialogProcess will be overwritten and set to zero in slotProcessExited()...crash! if ( m_kdialogProcess && m_kdialogProcess->state() == QProcess::Running ) return; m_currentXmlData->dump(); Q_ASSERT( m_currentXmlData->type() != XmlData::Merged ); m_kdialogProcess = new QProcess(); QString kdialogExe = KStandardDirs::findExe(QLatin1String("kdialog")); QStringList kdialogArgs; kdialogArgs << "--caption"; kdialogArgs << i18n( "Change Icon" ); kdialogArgs << "--embed"; kdialogArgs << QString::number( (quintptr)m_widget->window()->winId() ); kdialogArgs << "--geticon"; kdialogArgs << "Toolbar"; kdialogArgs << "Actions"; m_kdialogProcess->setReadChannel(QProcess::StandardOutput); m_kdialogProcess->start(kdialogExe, kdialogArgs, QIODevice::ReadOnly | QIODevice::Text); if ( !m_kdialogProcess->waitForStarted() ) { kError() << "Can't run " << kdialogExe; delete m_kdialogProcess; m_kdialogProcess = 0; return; } m_activeList->setEnabled( false ); // don't change the current item m_toolbarCombo->setEnabled( false ); // don't change the current toolbar QObject::connect( m_kdialogProcess, SIGNAL(finished(int,QProcess::ExitStatus)), m_widget, SLOT(slotProcessExited()) ); } void KEditToolBarWidgetPrivate::slotChangeIconText() { m_currentXmlData->dump(); ToolBarItem *item = m_activeList->currentItem(); if(item){ QString iconText = item->text(); bool hidden = item->isTextAlongsideIconHidden(); IconTextEditDialog dialog(m_widget); dialog.setIconText(iconText); dialog.setTextAlongsideIconHidden(hidden); bool ok = dialog.exec() == KDialog::Accepted; iconText = dialog.iconText(); hidden = dialog.textAlongsideIconHidden(); bool hiddenChanged = hidden != item->isTextAlongsideIconHidden(); bool iconTextChanged = iconText != item->text(); if (!ok || (!hiddenChanged && !iconTextChanged)) return; item->setText(iconText); item->setTextAlongsideIconHidden(hidden); Q_ASSERT( m_currentXmlData->type() != XmlData::Merged ); m_currentXmlData->m_isModified = true; // Get hold of ActionProperties tag QDomElement elem = KXMLGUIFactory::actionPropertiesElement( m_currentXmlData->domDocument() ); // Find or create an element for this action QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, item->internalName(), true /*create*/ ); Q_ASSERT( !act_elem.isNull() ); if (iconTextChanged) act_elem.setAttribute( "iconText", iconText ); if (hiddenChanged) act_elem.setAttribute( "priority", hidden ? QAction::LowPriority : QAction::NormalPriority ); // we're modified, so let this change emit m_widget->enableOk(true); } } void KEditToolBarWidgetPrivate::slotProcessExited() { m_activeList->setEnabled( true ); m_toolbarCombo->setEnabled( true ); QString icon; if (!m_kdialogProcess) { kError() << "Something is wrong here! m_kdialogProcess is zero!"; return; } icon = QString::fromLocal8Bit( m_kdialogProcess->readLine() ); icon = icon.left( icon.indexOf( '\n' ) ); kDebug() << "icon=" << icon; if ( m_kdialogProcess->exitStatus() != QProcess::NormalExit || icon.isEmpty() ) { delete m_kdialogProcess; m_kdialogProcess = 0; return; } ToolBarItem *item = m_activeList->currentItem(); kDebug() << item; if(item){ item->setIcon(KIcon(icon)); Q_ASSERT( m_currentXmlData->type() != XmlData::Merged ); m_currentXmlData->m_isModified = true; // Get hold of ActionProperties tag QDomElement elem = KXMLGUIFactory::actionPropertiesElement( m_currentXmlData->domDocument() ); // Find or create an element for this action QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, item->internalName(), true /*create*/ ); Q_ASSERT( !act_elem.isNull() ); act_elem.setAttribute( "icon", icon ); // we're modified, so let this change emit m_widget->enableOk(true); } delete m_kdialogProcess; m_kdialogProcess = 0; } void KEditToolBarWidgetPrivate::slotDropped(ToolBarListWidget* list, int index, ToolBarItem* item, bool sourceIsActiveList) { //kDebug() << "slotDropped list=" << (list==m_activeList?"activeList":"inactiveList") // << "index=" << index << "sourceIsActiveList=" << sourceIsActiveList; if (list == m_activeList) { ToolBarItem* after = index > 0 ? static_cast(list->item(index-1)) : 0; //kDebug() << "after" << after->text() << after->internalTag(); if (sourceIsActiveList) { // has been dragged within the active list (moved). moveActive(item, after); } else { // dragged from the inactive list to the active list insertActive(item, after, true); } } else if (list == m_inactiveList) { // has been dragged to the inactive list -> remove from the active list. removeActive(item); } delete item; // not needed anymore. must be deleted before slotToolBarSelected clears the lists // we're modified, so let this change emit m_widget->enableOk(true); slotToolBarSelected( m_toolbarCombo->currentIndex() ); } void KEditToolBar::showEvent( QShowEvent * event ) { if (!event->spontaneous()) { // The dialog has been shown, enable toolbar editing if ( d->m_factory ) { // call the xmlgui-factory version d->m_widget->load( d->m_factory, d->m_defaultToolBar ); } else { // call the action collection version d->m_widget->load( d->m_file, d->m_global, d->m_defaultToolBar ); } KToolBar::setToolBarsEditable(true); } KDialog::showEvent(event); } void KEditToolBar::hideEvent(QHideEvent* event) { // The dialog has been hidden, disable toolbar editing KToolBar::setToolBarsEditable(false); KDialog::hideEvent(event); } #include "moc_kedittoolbar.cpp" #include "moc_kedittoolbar_p.cpp"