kdeui Library API Documentation

kedittoolbar.cpp

00001 // -*- mode: c++; c-basic-offset: 2 -*-
00002 /* This file is part of the KDE libraries
00003    Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 #include <kedittoolbar.h>
00020 
00021 #include <qdom.h>
00022 
00023 #include <qlayout.h>
00024 #include <kaction.h>
00025 
00026 #include <qheader.h>
00027 #include <qcombobox.h>
00028 #include <qdragobject.h>
00029 #include <qtoolbutton.h>
00030 #include <qlabel.h>
00031 #include <qvaluelist.h>
00032 #include <qapplication.h>
00033 
00034 #include <kstandarddirs.h>
00035 #include <klocale.h>
00036 #include <kicontheme.h>
00037 #include <kiconloader.h>
00038 #include <kinstance.h>
00039 #include <kxmlguifactory.h>
00040 #include <kseparator.h>
00041 #include <kconfig.h>
00042 #include <klistview.h>
00043 
00044 #include <qtextstream.h>
00045 #include <qfile.h>
00046 #include <kdebug.h>
00047 #include "kpushbutton.h"
00048 #include <kprocio.h>
00049 
00050 #define LINESEPARATORSTRING I18N_NOOP("--- line separator ---")
00051 #define SEPARATORSTRING I18N_NOOP("--- separator ---")
00052 
00053 static void dump_xml(const QDomDocument& doc)
00054 {
00055     QString str;
00056     QTextStream ts(&str, IO_WriteOnly);
00057     ts << doc;
00058     kdDebug() << str << endl;
00059 }
00060 
00061 typedef QValueList<QDomElement> ToolbarList;
00062 
00063 namespace
00064 {
00065 class XmlData
00066 {
00067 public:
00068   enum XmlType { Shell = 0, Part, Local, Merged };
00069   XmlData()
00070   {
00071     m_isModified = false;
00072     m_actionCollection = 0;
00073   }
00074 
00075   QString      m_xmlFile;
00076   QDomDocument m_document;
00077   XmlType      m_type;
00078   bool         m_isModified;
00079   KActionCollection* m_actionCollection;
00080 
00081   ToolbarList  m_barList;
00082 };
00083 
00084 typedef QValueList<XmlData> XmlDataList;
00085 
00086 class ToolbarItem : public QListViewItem
00087 {
00088 public:
00089   ToolbarItem(KListView *parent, const QString& tag = QString::null, const QString& name = QString::null, const QString& statusText = QString::null)
00090     : QListViewItem(parent),
00091       m_tag(tag),
00092       m_name(name),
00093       m_statusText(statusText)
00094   {
00095   }
00096 
00097   ToolbarItem(KListView *parent, QListViewItem *item, const QString &tag = QString::null, const QString& name = QString::null, const QString& statusText = QString::null)
00098     : QListViewItem(parent, item),
00099       m_tag(tag),
00100       m_name(name),
00101       m_statusText(statusText)
00102   {
00103   }
00104 
00105   virtual QString key(int column, bool) const
00106   {
00107     QString s = text( column );
00108     if ( s == i18n(LINESEPARATORSTRING) )
00109       return "0";
00110     if ( s == i18n(SEPARATORSTRING) )
00111       return "1";
00112     return "2" + s;
00113   }
00114 
00115   void setInternalTag(const QString &tag) { m_tag = tag; }
00116   void setInternalName(const QString &name) { m_name = name; }
00117   void setStatusText(const QString &text) { m_statusText = text; }
00118   QString internalTag() const { return m_tag; }
00119   QString internalName() const { return m_name; }
00120   QString statusText() const { return m_statusText; }
00121 private:
00122   QString m_tag;
00123   QString m_name;
00124   QString m_statusText;
00125 };
00126 
00127 #define TOOLBARITEMMIMETYPE "data/x-kde.toolbar.item"
00128 class ToolbarItemDrag : public QStoredDrag
00129 {
00130 public:
00131   ToolbarItemDrag(ToolbarItem *toolbarItem,
00132                     QWidget *dragSource = 0, const char *name = 0)
00133     : QStoredDrag( TOOLBARITEMMIMETYPE, dragSource, name )
00134   {
00135     if (toolbarItem) {
00136       QByteArray data;
00137       QDataStream out(data, IO_WriteOnly);
00138       out << toolbarItem->internalTag();
00139       out << toolbarItem->internalName();
00140       out << toolbarItem->statusText();
00141       out << toolbarItem->text(1); // separators need this.
00142       setEncodedData(data);
00143     }
00144   }
00145 
00146   static bool canDecode(QMimeSource* e)
00147   {
00148     return e->provides(TOOLBARITEMMIMETYPE);
00149   }
00150 
00151   static bool decode( const QMimeSource* e, ToolbarItem& item )
00152   {
00153     if (!e)
00154       return false;
00155 
00156     QByteArray data = e->encodedData(TOOLBARITEMMIMETYPE);
00157     if ( data.isEmpty() )
00158       return false;
00159 
00160     QString internalTag, internalName, statusText, text;
00161     QDataStream in(data, IO_ReadOnly);
00162     in >> internalTag;
00163     in >> internalName;
00164     in >> statusText;
00165     in >> text;
00166 
00167     item.setInternalTag( internalTag );
00168     item.setInternalName( internalName );
00169     item.setStatusText( statusText );
00170     item.setText(1, text);
00171 
00172     return true;
00173   }
00174 };
00175 
00176 class ToolbarListView : public KListView
00177 {
00178 public:
00179   ToolbarListView(QWidget *parent=0, const char *name=0)
00180     : KListView(parent, name)
00181   {
00182   }
00183 protected:
00184   virtual QDragObject *dragObject()
00185   {
00186     ToolbarItem *item = dynamic_cast<ToolbarItem*>(selectedItem());
00187     if ( item != 0 ) {
00188       ToolbarItemDrag *obj = new ToolbarItemDrag(item,
00189                                  this, "ToolbarAction drag item");
00190       const QPixmap *pm = item->pixmap(0);
00191       if( pm )
00192         obj->setPixmap( *pm );
00193       return obj;
00194     }
00195     return 0;
00196   }
00197 
00198   virtual bool acceptDrag(QDropEvent *event) const
00199   {
00200     return ToolbarItemDrag::canDecode( event );
00201   }
00202 };
00203 } // namespace
00204 
00205 class KEditToolbarWidgetPrivate
00206 {
00207 public:
00215   KEditToolbarWidgetPrivate(KInstance *instance, KActionCollection* collection)
00216       : m_collection( collection )
00217   {
00218     m_instance = instance;
00219     m_isPart   = false;
00220     m_helpArea = 0L;
00221     m_kdialogProcess = 0;
00222   }
00223   ~KEditToolbarWidgetPrivate()
00224   {
00225   }
00226 
00227   QString xmlFile(const QString& xml_file)
00228   {
00229     return xml_file.isNull() ? QString(m_instance->instanceName()) + "ui.rc" :
00230                                xml_file;
00231   }
00232 
00236   QString loadXMLFile(const QString& _xml_file)
00237   {
00238     QString raw_xml;
00239     QString xml_file = xmlFile(_xml_file);
00240     //kdDebug() << "loadXMLFile xml_file=" << xml_file << endl;
00241 
00242     if ( xml_file[0] == '/' )
00243       raw_xml = KXMLGUIFactory::readConfigFile(xml_file);
00244     else
00245       raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_instance);
00246 
00247     return raw_xml;
00248   }
00249 
00253   ToolbarList findToolbars(QDomNode n)
00254   {
00255     static const QString &tagToolbar = KGlobal::staticQString( "ToolBar" );
00256     static const QString &attrNoEdit = KGlobal::staticQString( "noEdit" );
00257     ToolbarList list;
00258 
00259     for( ; !n.isNull(); n = n.nextSibling() )
00260     {
00261       QDomElement elem = n.toElement();
00262       if (elem.isNull())
00263         continue;
00264 
00265       if (elem.tagName() == tagToolbar && elem.attribute( attrNoEdit ) != "true" )
00266         list.append(elem);
00267 
00268       list += findToolbars(elem.firstChild());
00269     }
00270 
00271     return list;
00272   }
00273 
00277   QString toolbarName( const XmlData& xmlData, const QDomElement& it ) const
00278   {
00279       static const QString &tagText = KGlobal::staticQString( "text" );
00280       static const QString &tagText2 = KGlobal::staticQString( "Text" );
00281       static const QString &attrName = KGlobal::staticQString( "name" );
00282 
00283       QString name;
00284       QCString txt( it.namedItem( tagText ).toElement().text().utf8() );
00285       if ( txt.isEmpty() )
00286           txt = it.namedItem( tagText2 ).toElement().text().utf8();
00287       if ( txt.isEmpty() )
00288           name = it.attribute( attrName );
00289       else
00290           name = i18n( txt );
00291 
00292       // the name of the toolbar might depend on whether or not
00293       // it is in kparts
00294       if ( ( xmlData.m_type == XmlData::Shell ) ||
00295            ( xmlData.m_type == XmlData::Part ) )
00296       {
00297         QString doc_name(xmlData.m_document.documentElement().attribute( attrName ));
00298         name += " <" + doc_name + ">";
00299       }
00300       return name;
00301   }
00305   QDomElement findElementForToolbarItem( const ToolbarItem* item ) const
00306   {
00307     static const QString &attrName    = KGlobal::staticQString( "name" );
00308     for(QDomNode n = m_currentToolbarElem.firstChild(); !n.isNull(); n = n.nextSibling())
00309     {
00310       QDomElement elem = n.toElement();
00311       if ((elem.attribute(attrName) == item->internalName()) &&
00312           (elem.tagName() == item->internalTag()))
00313         return elem;
00314     }
00315     return QDomElement();
00316   }
00317 
00318 #ifndef NDEBUG
00319   void dump()
00320   {
00321     static const char* s_XmlTypeToString[] = { "Shell", "Part", "Local", "Merged" };
00322     XmlDataList::Iterator xit = m_xmlFiles.begin();
00323     for ( ; xit != m_xmlFiles.end(); ++xit )
00324     {
00325         kdDebug(240) << "XmlData type " << s_XmlTypeToString[(*xit).m_type] << " xmlFile: " << (*xit).m_xmlFile << endl;
00326         for( QValueList<QDomElement>::Iterator it = (*xit).m_barList.begin();
00327              it != (*xit).m_barList.end(); ++it ) {
00328             kdDebug(240) << "    Toolbar: " << toolbarName( *xit, *it ) << endl;
00329         }
00330         if ( (*xit).m_actionCollection )
00331             kdDebug(240) << "    " << (*xit).m_actionCollection->count() << " actions in the collection." << endl;
00332         else
00333             kdDebug(240) << "    no action collection." << endl;
00334     }
00335   }
00336 #endif
00337 
00338   //QValueList<KAction*> m_actionList;
00339   KActionCollection* m_collection;
00340   KInstance         *m_instance;
00341 
00342   XmlData     m_currentXmlData;
00343   QDomElement m_currentToolbarElem;
00344 
00345   QString            m_xmlFile;
00346   QString            m_globalFile;
00347   QString            m_rcFile;
00348   QDomDocument       m_localDoc;
00349   bool               m_isPart;
00350 
00351   ToolbarList        m_barList;
00352 
00353   XmlDataList m_xmlFiles;
00354 
00355   QLabel     *m_comboLabel;
00356   KSeparator *m_comboSeparator;
00357   QLabel * m_helpArea;
00358   KPushButton* m_changeIcon;
00359   KProcIO* m_kdialogProcess;
00360   bool m_hasKDialog;
00361 };
00362 
00363 class KEditToolbarPrivate {
00364 public:
00365     bool m_accept;
00366 };
00367 
00368 const char *KEditToolbar::s_defaultToolbar = 0L;
00369 
00370 KEditToolbar::KEditToolbar(KActionCollection *collection, const QString& file,
00371                            bool global, QWidget* parent, const char* name)
00372   : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00373     m_widget(new KEditToolbarWidget(QString::fromLatin1(s_defaultToolbar), collection, file, global, this))
00374 {
00375     init();
00376 }
00377 
00378 KEditToolbar::KEditToolbar(const QString& defaultToolbar, KActionCollection *collection,
00379                            const QString& file, bool global,
00380                            QWidget* parent, const char* name)
00381   : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00382     m_widget(new KEditToolbarWidget(defaultToolbar, collection, file, global, this))
00383 {
00384     init();
00385 }
00386 
00387 KEditToolbar::KEditToolbar(KXMLGUIFactory* factory, QWidget* parent, const char* name)
00388     : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00389       m_widget(new KEditToolbarWidget(QString::fromLatin1(s_defaultToolbar), factory, this))
00390 {
00391     init();
00392 }
00393 
00394 KEditToolbar::KEditToolbar(const QString& defaultToolbar,KXMLGUIFactory* factory,
00395                            QWidget* parent, const char* name)
00396     : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00397       m_widget(new KEditToolbarWidget(defaultToolbar, factory, this))
00398 {
00399     init();
00400 }
00401 
00402 void KEditToolbar::init()
00403 {
00404     d = new KEditToolbarPrivate();
00405     d->m_accept = false;
00406 
00407     setMainWidget(m_widget);
00408 
00409     connect(m_widget, SIGNAL(enableOk(bool)), SLOT(acceptOK(bool)));
00410     connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool)));
00411     enableButtonApply(false);
00412 
00413     setMinimumSize(sizeHint());
00414     s_defaultToolbar = 0L;
00415 }
00416 
00417 KEditToolbar::~KEditToolbar()
00418 {
00419     delete d;
00420 }
00421 
00422 void KEditToolbar::acceptOK(bool b)
00423 {
00424     enableButtonOK(b);
00425     d->m_accept = b;
00426 }
00427 
00428 void KEditToolbar::slotOk()
00429 {
00430   if (!d->m_accept) {
00431       reject();
00432       return;
00433   }
00434 
00435   if (!m_widget->save())
00436   {
00437     // some error box here is needed
00438   }
00439   else
00440   {
00441     emit newToolbarConfig();
00442     accept();
00443   }
00444 }
00445 
00446 void KEditToolbar::slotApply()
00447 {
00448     (void)m_widget->save();
00449     enableButtonApply(false);
00450     emit newToolbarConfig();
00451 }
00452 
00453 void KEditToolbar::setDefaultToolbar(const char *toolbarName)
00454 {
00455     s_defaultToolbar = toolbarName;
00456 }
00457 
00458 KEditToolbarWidget::KEditToolbarWidget(KActionCollection *collection,
00459                                        const QString& file,
00460                                        bool global, QWidget *parent)
00461   : QWidget(parent),
00462     d(new KEditToolbarWidgetPrivate(instance(), collection))
00463 {
00464   initNonKPart(collection, file, global);
00465   // now load in our toolbar combo box
00466   loadToolbarCombo();
00467   adjustSize();
00468   setMinimumSize(sizeHint());
00469 }
00470 
00471 KEditToolbarWidget::KEditToolbarWidget(const QString& defaultToolbar,
00472                                        KActionCollection *collection,
00473                                        const QString& file, bool global,
00474                                        QWidget *parent)
00475   : QWidget(parent),
00476     d(new KEditToolbarWidgetPrivate(instance(), collection))
00477 {
00478   initNonKPart(collection, file, global);
00479   // now load in our toolbar combo box
00480   loadToolbarCombo(defaultToolbar);
00481   adjustSize();
00482   setMinimumSize(sizeHint());
00483 }
00484 
00485 KEditToolbarWidget::KEditToolbarWidget( KXMLGUIFactory* factory,
00486                                         QWidget *parent)
00487   : QWidget(parent),
00488     d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
00489 {
00490   initKPart(factory);
00491   // now load in our toolbar combo box
00492   loadToolbarCombo();
00493   adjustSize();
00494   setMinimumSize(sizeHint());
00495 }
00496 
00497 KEditToolbarWidget::KEditToolbarWidget( const QString& defaultToolbar,
00498                                         KXMLGUIFactory* factory,
00499                                         QWidget *parent)
00500   : QWidget(parent),
00501     d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
00502 {
00503   initKPart(factory);
00504   // now load in our toolbar combo box
00505   loadToolbarCombo(defaultToolbar);
00506   adjustSize();
00507   setMinimumSize(sizeHint());
00508 }
00509 
00510 KEditToolbarWidget::~KEditToolbarWidget()
00511 {
00512     delete d;
00513 }
00514 
00515 void KEditToolbarWidget::initNonKPart(KActionCollection *collection,
00516                                       const QString& file, bool global)
00517 {
00518   //d->m_actionList = collection->actions();
00519 
00520   // handle the merging
00521   if (global)
00522     setXMLFile(locate("config", "ui/ui_standards.rc"));
00523   QString localXML = d->loadXMLFile(file);
00524   setXML(localXML, true);
00525 
00526   // reusable vars
00527   QDomElement elem;
00528 
00529   // first, get all of the necessary info for our local xml
00530   XmlData local;
00531   local.m_xmlFile = d->xmlFile(file);
00532   local.m_type    = XmlData::Local;
00533   local.m_document.setContent(localXML);
00534   elem = local.m_document.documentElement().toElement();
00535   local.m_barList = d->findToolbars(elem);
00536   local.m_actionCollection = collection;
00537   d->m_xmlFiles.append(local);
00538 
00539   // then, the merged one (ui_standards + local xml)
00540   XmlData merge;
00541   merge.m_xmlFile  = QString::null;
00542   merge.m_type     = XmlData::Merged;
00543   merge.m_document = domDocument();
00544   elem = merge.m_document.documentElement().toElement();
00545   merge.m_barList  = d->findToolbars(elem);
00546   merge.m_actionCollection = collection;
00547   d->m_xmlFiles.append(merge);
00548 
00549 #ifndef NDEBUG
00550   //d->dump();
00551 #endif
00552 
00553   // okay, that done, we concern ourselves with the GUI aspects
00554   setupLayout();
00555 }
00556 
00557 void KEditToolbarWidget::initKPart(KXMLGUIFactory* factory)
00558 {
00559   // reusable vars
00560   QDomElement elem;
00561 
00562   setFactory( factory );
00563   actionCollection()->setWidget( this );
00564 
00565   // add all of the client data
00566   QPtrList<KXMLGUIClient> clients(factory->clients());
00567   QPtrListIterator<KXMLGUIClient> it( clients );
00568   for( ; it.current(); ++it)
00569   {
00570     KXMLGUIClient *client = it.current();
00571 
00572     if (client->xmlFile().isNull())
00573       continue;
00574 
00575     XmlData data;
00576     data.m_xmlFile = client->localXMLFile();
00577     if ( it.atFirst() )
00578       data.m_type = XmlData::Shell;
00579     else
00580       data.m_type = XmlData::Part;
00581     data.m_document.setContent( KXMLGUIFactory::readConfigFile( client->xmlFile(), client->instance() ) );
00582     elem = data.m_document.documentElement().toElement();
00583     data.m_barList = d->findToolbars(elem);
00584     data.m_actionCollection = client->actionCollection();
00585     d->m_xmlFiles.append(data);
00586 
00587     //d->m_actionList += client->actionCollection()->actions();
00588   }
00589 
00590 #ifndef NDEBUG
00591   //d->dump();
00592 #endif
00593 
00594   // okay, that done, we concern ourselves with the GUI aspects
00595   setupLayout();
00596 }
00597 
00598 bool KEditToolbarWidget::save()
00599 {
00600   //kdDebug(240) << "KEditToolbarWidget::save" << endl;
00601   XmlDataList::Iterator it = d->m_xmlFiles.begin();
00602   for ( ; it != d->m_xmlFiles.end(); ++it)
00603   {
00604     // let's not save non-modified files
00605     if ( (*it).m_isModified == false )
00606       continue;
00607 
00608     // let's also skip (non-existent) merged files
00609     if ( (*it).m_type == XmlData::Merged )
00610       continue;
00611 
00612     dump_xml((*it).m_document);
00613 
00614     // if we got this far, we might as well just save it
00615     KXMLGUIFactory::saveConfigFile((*it).m_document, (*it).m_xmlFile);
00616   }
00617 
00618   if ( !factory() )
00619     return true;
00620 
00621   QPtrList<KXMLGUIClient> clients(factory()->clients());
00622   //kdDebug(240) << "factory: " << clients.count() << " clients" << endl;
00623 
00624   // remove the elements starting from the last going to the first
00625   KXMLGUIClient *client = clients.last();
00626   while ( client )
00627   {
00628     //kdDebug(240) << "factory->removeClient " << client << endl;
00629     factory()->removeClient( client );
00630     client = clients.prev();
00631   }
00632 
00633   KXMLGUIClient *firstClient = clients.first();
00634 
00635   // now, rebuild the gui from the first to the last
00636   //kdDebug(240) << "rebuilding the gui" << endl;
00637   QPtrListIterator<KXMLGUIClient> cit( clients );
00638   for( ; cit.current(); ++cit)
00639   {
00640     KXMLGUIClient* client = cit.current();
00641     //kdDebug(240) << "updating client " << client << " " << client->instance()->instanceName() << "  xmlFile=" << client->xmlFile() << endl;
00642     QString file( client->xmlFile() ); // before setting ui_standards!
00643     if ( !file.isEmpty() )
00644     {
00645         // passing an empty stream forces the clients to reread the XML
00646         client->setXMLGUIBuildDocument( QDomDocument() );
00647 
00648         // for the shell, merge in ui_standards.rc
00649         if ( client == firstClient ) // same assumption as in the ctor: first==shell
00650             client->setXMLFile(locate("config", "ui/ui_standards.rc"));
00651 
00652         // and this forces it to use the *new* XML file
00653         client->setXMLFile( file, client == firstClient /* merge if shell */ );
00654     }
00655   }
00656 
00657   // Now we can add the clients to the factory
00658   // We don't do it in the loop above because adding a part automatically
00659   // adds its plugins, so we must make sure the plugins were updated first.
00660   cit.toFirst();
00661   for( ; cit.current(); ++cit)
00662     factory()->addClient( cit.current() );
00663 
00664   return true;
00665 }
00666 
00667 void KEditToolbarWidget::setupLayout()
00668 {
00669   // the toolbar name combo
00670   d->m_comboLabel = new QLabel(i18n("&Toolbar:"), this);
00671   m_toolbarCombo = new QComboBox(this);
00672   m_toolbarCombo->setEnabled(false);
00673   d->m_comboLabel->setBuddy(m_toolbarCombo);
00674   d->m_comboSeparator = new KSeparator(this);
00675   connect(m_toolbarCombo, SIGNAL(activated(const QString&)),
00676           this,           SLOT(slotToolbarSelected(const QString&)));
00677 
00678 //  QPushButton *new_toolbar = new QPushButton(i18n("&New"), this);
00679 //  new_toolbar->setPixmap(BarIcon("filenew", KIcon::SizeSmall));
00680 //  new_toolbar->setEnabled(false); // disabled until implemented
00681 //  QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this);
00682 //  del_toolbar->setPixmap(BarIcon("editdelete", KIcon::SizeSmall));
00683 //  del_toolbar->setEnabled(false); // disabled until implemented
00684 
00685   // our list of inactive actions
00686   QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), this);
00687   m_inactiveList = new ToolbarListView(this);
00688   m_inactiveList->setDragEnabled(true);
00689   m_inactiveList->setAcceptDrops(true);
00690   m_inactiveList->setDropVisualizer(false);
00691   m_inactiveList->setAllColumnsShowFocus(true);
00692   m_inactiveList->setMinimumSize(180, 250);
00693   m_inactiveList->header()->hide();
00694   m_inactiveList->addColumn(""); // icon
00695   int column2 = m_inactiveList->addColumn(""); // text
00696   m_inactiveList->setSorting( column2 );
00697   inactive_label->setBuddy(m_inactiveList);
00698   connect(m_inactiveList, SIGNAL(selectionChanged(QListViewItem *)),
00699           this,           SLOT(slotInactiveSelected(QListViewItem *)));
00700   connect(m_inactiveList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int  )),
00701           this,           SLOT(slotInsertButton()));
00702 
00703   // our list of active actions
00704   QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), this);
00705   m_activeList = new ToolbarListView(this);
00706   m_activeList->setDragEnabled(true);
00707   m_activeList->setAcceptDrops(true);
00708   m_activeList->setDropVisualizer(true);
00709   m_activeList->setAllColumnsShowFocus(true);
00710   m_activeList->setMinimumWidth(m_inactiveList->minimumWidth());
00711   m_activeList->header()->hide();
00712   m_activeList->addColumn(""); // icon
00713   m_activeList->addColumn(""); // text
00714   m_activeList->setSorting(-1);
00715   active_label->setBuddy(m_activeList);
00716 
00717   connect(m_inactiveList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)),
00718           this,              SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*)));
00719   connect(m_activeList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)),
00720           this,            SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*)));
00721   connect(m_activeList, SIGNAL(selectionChanged(QListViewItem *)),
00722           this,         SLOT(slotActiveSelected(QListViewItem *)));
00723   connect(m_activeList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int  )),
00724           this,           SLOT(slotRemoveButton()));
00725 
00726   // "change icon" button
00727   d->m_changeIcon = new KPushButton( i18n( "Change &Icon..." ), this );
00728   QString kdialogExe = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
00729   d->m_hasKDialog = !kdialogExe.isEmpty();
00730   d->m_changeIcon->setEnabled( d->m_hasKDialog );
00731 
00732   connect( d->m_changeIcon, SIGNAL( clicked() ),
00733            this, SLOT( slotChangeIcon() ) );
00734 
00735   // The buttons in the middle
00736   QIconSet iconSet;
00737 
00738   m_upAction     = new QToolButton(this);
00739   iconSet = SmallIconSet( "up" );
00740   m_upAction->setIconSet( iconSet );
00741   m_upAction->setEnabled(false);
00742   m_upAction->setAutoRepeat(true);
00743   connect(m_upAction, SIGNAL(clicked()), SLOT(slotUpButton()));
00744 
00745   m_insertAction = new QToolButton(this);
00746   iconSet = QApplication::reverseLayout() ? SmallIconSet( "back" ) : SmallIconSet( "forward" );
00747   m_insertAction->setIconSet( iconSet );
00748   m_insertAction->setEnabled(false);
00749   connect(m_insertAction, SIGNAL(clicked()), SLOT(slotInsertButton()));
00750 
00751   m_removeAction = new QToolButton(this);
00752   iconSet = QApplication::reverseLayout() ? SmallIconSet( "forward" ) : SmallIconSet( "back" );
00753   m_removeAction->setIconSet( iconSet );
00754   m_removeAction->setEnabled(false);
00755   connect(m_removeAction, SIGNAL(clicked()), SLOT(slotRemoveButton()));
00756 
00757   m_downAction   = new QToolButton(this);
00758   iconSet = SmallIconSet( "down" );
00759   m_downAction->setIconSet( iconSet );
00760   m_downAction->setEnabled(false);
00761   m_downAction->setAutoRepeat(true);
00762   connect(m_downAction, SIGNAL(clicked()), SLOT(slotDownButton()));
00763 
00764   d->m_helpArea = new QLabel(this);
00765   d->m_helpArea->setAlignment( Qt::WordBreak );
00766 
00767   // now start with our layouts
00768   QVBoxLayout *top_layout = new QVBoxLayout(this, 0, KDialog::spacingHint());
00769 
00770   QVBoxLayout *name_layout = new QVBoxLayout(KDialog::spacingHint());
00771   QHBoxLayout *list_layout = new QHBoxLayout(KDialog::spacingHint());
00772 
00773   QVBoxLayout *inactive_layout = new QVBoxLayout(KDialog::spacingHint());
00774   QVBoxLayout *active_layout = new QVBoxLayout(KDialog::spacingHint());
00775   QHBoxLayout *changeIcon_layout = new QHBoxLayout(KDialog::spacingHint());
00776 
00777   QGridLayout *button_layout = new QGridLayout(5, 3, 0);
00778 
00779   name_layout->addWidget(d->m_comboLabel);
00780   name_layout->addWidget(m_toolbarCombo);
00781 //  name_layout->addWidget(new_toolbar);
00782 //  name_layout->addWidget(del_toolbar);
00783 
00784   button_layout->setRowStretch( 0, 10 );
00785   button_layout->addWidget(m_upAction, 1, 1);
00786   button_layout->addWidget(m_removeAction, 2, 0);
00787   button_layout->addWidget(m_insertAction, 2, 2);
00788   button_layout->addWidget(m_downAction, 3, 1);
00789   button_layout->setRowStretch( 4, 10 );
00790 
00791   inactive_layout->addWidget(inactive_label);
00792   inactive_layout->addWidget(m_inactiveList, 1);
00793 
00794   active_layout->addWidget(active_label);
00795   active_layout->addWidget(m_activeList, 1);
00796   active_layout->addLayout(changeIcon_layout);
00797 
00798   changeIcon_layout->addStretch( 1 );
00799   changeIcon_layout->addWidget( d->m_changeIcon );
00800   changeIcon_layout->addStretch( 1 );
00801 
00802   list_layout->addLayout(inactive_layout);
00803   list_layout->addLayout(button_layout);
00804   list_layout->addLayout(active_layout);
00805 
00806   top_layout->addLayout(name_layout);
00807   top_layout->addWidget(d->m_comboSeparator);
00808   top_layout->addLayout(list_layout,10);
00809   top_layout->addWidget(d->m_helpArea);
00810   top_layout->addWidget(new KSeparator(this));
00811 }
00812 
00813 void KEditToolbarWidget::loadToolbarCombo(const QString& defaultToolbar)
00814 {
00815   static const QString &attrName = KGlobal::staticQString( "name" );
00816   // just in case, we clear our combo
00817   m_toolbarCombo->clear();
00818 
00819   int defaultToolbarId = -1;
00820   int count = 0;
00821   // load in all of the toolbar names into this combo box
00822   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
00823   for ( ; xit != d->m_xmlFiles.end(); ++xit)
00824   {
00825     // skip the local one in favor of the merged
00826     if ( (*xit).m_type == XmlData::Local )
00827       continue;
00828 
00829     // each xml file may have any number of toolbars
00830     ToolbarList::Iterator it = (*xit).m_barList.begin();
00831     for ( ; it != (*xit).m_barList.end(); ++it)
00832     {
00833       QString name = d->toolbarName( *xit, *it );
00834       m_toolbarCombo->setEnabled( true );
00835       m_toolbarCombo->insertItem( name );
00836       if (defaultToolbarId == -1 && (name == defaultToolbar || defaultToolbar == (*it).attribute( attrName )))
00837           defaultToolbarId = count;
00838       count++;
00839     }
00840   }
00841   bool showCombo = (count > 1);
00842   d->m_comboLabel->setShown(showCombo);
00843   d->m_comboSeparator->setShown(showCombo);
00844   m_toolbarCombo->setShown(showCombo);
00845   if (defaultToolbarId == -1)
00846       defaultToolbarId = 0;
00847   // we want to the specified item selected and its actions loaded
00848   m_toolbarCombo->setCurrentItem(defaultToolbarId);
00849   slotToolbarSelected(m_toolbarCombo->currentText());
00850 }
00851 
00852 void KEditToolbarWidget::loadActionList(QDomElement& elem)
00853 {
00854   static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
00855   static const QString &tagMerge     = KGlobal::staticQString( "Merge" );
00856   static const QString &tagActionList= KGlobal::staticQString( "ActionList" );
00857   static const QString &attrName     = KGlobal::staticQString( "name" );
00858   static const QString &attrLineSeparator = KGlobal::staticQString( "lineSeparator" );
00859 
00860   int     sep_num = 0;
00861   QString sep_name("separator_%1");
00862 
00863   // clear our lists
00864   m_inactiveList->clear();
00865   m_activeList->clear();
00866   m_insertAction->setEnabled(false);
00867   m_removeAction->setEnabled(false);
00868   m_upAction->setEnabled(false);
00869   m_downAction->setEnabled(false);
00870 
00871   // We'll use this action collection
00872   KActionCollection* actionCollection = d->m_currentXmlData.m_actionCollection;
00873 
00874   // store the names of our active actions
00875   QMap<QString, bool> active_list;
00876 
00877   // see if our current action is in this toolbar
00878   QDomNode n = elem.lastChild();
00879   for( ; !n.isNull(); n = n.previousSibling() )
00880   {
00881     QDomElement it = n.toElement();
00882     if (it.isNull()) continue;
00883     if (it.tagName() == tagSeparator)
00884     {
00885       ToolbarItem *act = new ToolbarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString::null);
00886       bool isLineSep = ( it.attribute(attrLineSeparator, "true").lower() == QString::fromLatin1("true") );
00887       if(isLineSep)
00888         act->setText(1, i18n(LINESEPARATORSTRING));
00889       else
00890         act->setText(1, i18n(SEPARATORSTRING));
00891       it.setAttribute( attrName, act->internalName() );
00892       continue;
00893     }
00894 
00895     if (it.tagName() == tagMerge)
00896     {
00897       // Merge can be named or not - use the name if there is one
00898       QString name = it.attribute( attrName );
00899       ToolbarItem *act = new ToolbarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component."));
00900       if ( name.isEmpty() )
00901           act->setText(1, i18n("<Merge>"));
00902       else
00903           act->setText(1, i18n("<Merge %1>").arg(name));
00904       continue;
00905     }
00906 
00907     if (it.tagName() == tagActionList)
00908     {
00909       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 won't be able to re-add it.") );
00910       act->setText(1, i18n("ActionList: %1").arg(it.attribute(attrName)));
00911       continue;
00912     }
00913 
00914     // iterate through this client's actions
00915     // This used to iterate through _all_ actions, but we don't support
00916     // putting any action into any client...
00917     for (unsigned int i = 0;  i < actionCollection->count(); i++)
00918     {
00919       KAction *action = actionCollection->action( i );
00920 
00921       // do we have a match?
00922       if (it.attribute( attrName ) == action->name())
00923       {
00924         // we have a match!
00925         ToolbarItem *act = new ToolbarItem(m_activeList, it.tagName(), action->name(), action->toolTip());
00926         act->setText(1, action->plainText());
00927         if (action->hasIcon())
00928           if (!action->icon().isEmpty())
00929             act->setPixmap(0, BarIcon(action->icon(), 16));
00930           else // Has iconset
00931             act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
00932 
00933         active_list.insert(action->name(), true);
00934         break;
00935       }
00936     }
00937   }
00938 
00939   // go through the rest of the collection
00940   for (int i = actionCollection->count() - 1; i > -1; --i)
00941   {
00942     KAction *action = actionCollection->action( i );
00943 
00944     // skip our active ones
00945     if (active_list.contains(action->name()))
00946       continue;
00947 
00948     ToolbarItem *act = new ToolbarItem(m_inactiveList, tagActionList, action->name(), action->toolTip());
00949     act->setText(1, action->plainText());
00950     if (action->hasIcon())
00951       if (!action->icon().isEmpty())
00952         act->setPixmap(0, BarIcon(action->icon(), 16));
00953       else // Has iconset
00954         act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
00955   }
00956 
00957   // finally, add default separators to the inactive list
00958   ToolbarItem *act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null);
00959   act->setText(1, i18n(LINESEPARATORSTRING));
00960   act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null);
00961   act->setText(1, i18n(SEPARATORSTRING));
00962 }
00963 
00964 KActionCollection *KEditToolbarWidget::actionCollection() const
00965 {
00966   return d->m_collection;
00967 }
00968 
00969 void KEditToolbarWidget::slotToolbarSelected(const QString& _text)
00970 {
00971   // iterate through everything
00972   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
00973   for ( ; xit != d->m_xmlFiles.end(); ++xit)
00974   {
00975     // each xml file may have any number of toolbars
00976     ToolbarList::Iterator it = (*xit).m_barList.begin();
00977     for ( ; it != (*xit).m_barList.end(); ++it)
00978     {
00979       QString name = d->toolbarName( *xit, *it );
00980       // is this our toolbar?
00981       if ( name == _text )
00982       {
00983         // save our current settings
00984         d->m_currentXmlData     = (*xit);
00985         d->m_currentToolbarElem = (*it);
00986 
00987         // load in our values
00988         loadActionList(d->m_currentToolbarElem);
00989 
00990         if ((*xit).m_type == XmlData::Part || (*xit).m_type == XmlData::Shell)
00991           setDOMDocument( (*xit).m_document );
00992         return;
00993       }
00994     }
00995   }
00996 }
00997 
00998 void KEditToolbarWidget::slotInactiveSelected(QListViewItem *item)
00999 {
01000   ToolbarItem* toolitem = static_cast<ToolbarItem *>(item);
01001   if (item)
01002   {
01003     m_insertAction->setEnabled(true);
01004     QString statusText = toolitem->statusText();
01005     d->m_helpArea->setText( statusText );
01006   }
01007   else
01008   {
01009     m_insertAction->setEnabled(false);
01010     d->m_helpArea->setText( QString::null );
01011   }
01012 }
01013 
01014 void KEditToolbarWidget::slotActiveSelected(QListViewItem *item)
01015 {
01016   ToolbarItem* toolitem = static_cast<ToolbarItem *>(item);
01017   m_removeAction->setEnabled( item != 0 );
01018 
01019   static const QString &tagAction = KGlobal::staticQString( "Action" );
01020   d->m_changeIcon->setEnabled( item != 0 &&
01021                                d->m_hasKDialog &&
01022                                toolitem->internalTag() == tagAction );
01023 
01024   if (item)
01025   {
01026     if (item->itemAbove())
01027       m_upAction->setEnabled(true);
01028     else
01029       m_upAction->setEnabled(false);
01030 
01031     if (item->itemBelow())
01032       m_downAction->setEnabled(true);
01033     else
01034       m_downAction->setEnabled(false);
01035     QString statusText = toolitem->statusText();
01036     d->m_helpArea->setText( statusText );
01037   }
01038   else
01039   {
01040     m_upAction->setEnabled(false);
01041     m_downAction->setEnabled(false);
01042     d->m_helpArea->setText( QString::null );
01043   }
01044 }
01045 
01046 void KEditToolbarWidget::slotDropped(KListView *list, QDropEvent *e, QListViewItem *after)
01047 {
01048   ToolbarItem *item = new ToolbarItem(m_inactiveList); // needs parent, use inactiveList temporarily
01049   if(!ToolbarItemDrag::decode(e, *item)) {
01050     delete item;
01051     return;
01052   }
01053 
01054   if (list == m_activeList) {
01055     if (e->source() == m_activeList) {
01056       // has been dragged within the active list (moved) -> remove the old item.
01057       removeActive(item);
01058     }
01059 
01060     insertActive(item, after, true);
01061   } else if (list == m_inactiveList) {
01062     // has been dragged to the inactive list -> remove from the active list.
01063     removeActive(item);
01064   }
01065 
01066   delete item; item = 0; // not neded anymore
01067 
01068   // we're modified, so let this change
01069   emit enableOk(true);
01070 
01071   slotToolbarSelected( m_toolbarCombo->currentText() );
01072 }
01073 
01074 void KEditToolbarWidget::slotInsertButton()
01075 {
01076   ToolbarItem *item = (ToolbarItem*)m_inactiveList->currentItem();
01077   insertActive(item, m_activeList->currentItem(), false);
01078 
01079   // we're modified, so let this change
01080   emit enableOk(true);
01081 
01082   slotToolbarSelected( m_toolbarCombo->currentText() );
01083 }
01084 
01085 void KEditToolbarWidget::slotRemoveButton()
01086 {
01087   removeActive( dynamic_cast<ToolbarItem*>(m_activeList->currentItem()) );
01088 
01089   // we're modified, so let this change
01090   emit enableOk(true);
01091 
01092   slotToolbarSelected( m_toolbarCombo->currentText() );
01093 }
01094 
01095 void KEditToolbarWidget::insertActive(ToolbarItem *item, QListViewItem *before, bool prepend)
01096 {
01097   if (!item)
01098     return;
01099 
01100   static const QString &tagAction    = KGlobal::staticQString( "Action" );
01101   static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
01102   static const QString &attrName     = KGlobal::staticQString( "name" );
01103   static const QString &attrLineSeparator = KGlobal::staticQString( "lineSeparator" );
01104   static const QString &attrNoMerge  = KGlobal::staticQString( "noMerge" );
01105 
01106   QDomElement new_item;
01107   // let's handle the separator specially
01108   if (item->text(1) == i18n(LINESEPARATORSTRING)) {
01109     new_item = domDocument().createElement(tagSeparator);
01110   } else if (item->text(1) == i18n(SEPARATORSTRING)) {
01111     new_item = domDocument().createElement(tagSeparator);
01112     new_item.setAttribute(attrLineSeparator, "false");
01113   } else
01114     new_item = domDocument().createElement(tagAction);
01115   new_item.setAttribute(attrName, item->internalName());
01116 
01117   if (before)
01118   {
01119     // we have the item in the active list which is before the new
01120     // item.. so let's try our best to add our new item right after it
01121     ToolbarItem *act_item = (ToolbarItem*)before;
01122     QDomElement elem = d->findElementForToolbarItem( act_item );
01123     Q_ASSERT( !elem.isNull() );
01124     d->m_currentToolbarElem.insertAfter(new_item, elem);
01125   }
01126   else
01127   {
01128     // simply put it at the beginning or the end of the list.
01129     if (prepend)
01130       d->m_currentToolbarElem.insertBefore(new_item, d->m_currentToolbarElem.firstChild());
01131     else
01132       d->m_currentToolbarElem.appendChild(new_item);
01133   }
01134 
01135   // and set this container as a noMerge
01136   d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
01137 
01138   // update the local doc
01139   updateLocal(d->m_currentToolbarElem);
01140 }
01141 
01142 void KEditToolbarWidget::removeActive(ToolbarItem *item)
01143 {
01144   if (!item)
01145     return;
01146 
01147   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
01148 
01149   // we're modified, so let this change
01150   emit enableOk(true);
01151 
01152   // now iterate through to find the child to nuke
01153   QDomElement elem = d->findElementForToolbarItem( item );
01154   if ( !elem.isNull() )
01155   {
01156     // nuke myself!
01157     d->m_currentToolbarElem.removeChild(elem);
01158 
01159     // and set this container as a noMerge
01160     d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
01161 
01162     // update the local doc
01163     updateLocal(d->m_currentToolbarElem);
01164   }
01165 }
01166 
01167 void KEditToolbarWidget::slotUpButton()
01168 {
01169   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
01170 
01171   // make sure we're not the top item already
01172   if (!item->itemAbove())
01173     return;
01174 
01175   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
01176 
01177   // we're modified, so let this change
01178   emit enableOk(true);
01179 
01180   // now iterate through to find where we are
01181   QDomElement elem = d->findElementForToolbarItem( item );
01182   if ( !elem.isNull() )
01183   {
01184     // cool, i found me.  now clone myself
01185     ToolbarItem *clone = new ToolbarItem(m_activeList,
01186                                          item->itemAbove()->itemAbove(),
01187                                          item->internalTag(),
01188                                          item->internalName(),
01189                                          item->statusText());
01190     clone->setText(1, item->text(1));
01191 
01192     // only set new pixmap if exists
01193     if( item->pixmap(0) )
01194       clone->setPixmap(0, *item->pixmap(0));
01195 
01196     // remove the old me
01197     m_activeList->takeItem(item);
01198     delete item;
01199 
01200     // select my clone
01201     m_activeList->setSelected(clone, true);
01202 
01203     // make clone visible
01204     m_activeList->ensureItemVisible(clone);
01205 
01206     // and do the real move in the DOM
01207     QDomNode prev = elem.previousSibling();
01208     while ( prev.toElement().tagName() == QString( "WeakSeparator" ) )
01209         prev = prev.previousSibling();
01210     d->m_currentToolbarElem.insertBefore(elem, prev);
01211 
01212     // and set this container as a noMerge
01213     d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
01214 
01215     // update the local doc
01216     updateLocal(d->m_currentToolbarElem);
01217   }
01218 }
01219 
01220 void KEditToolbarWidget::slotDownButton()
01221 {
01222   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
01223 
01224   // make sure we're not the bottom item already
01225   if (!item->itemBelow())
01226     return;
01227 
01228   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
01229 
01230   // we're modified, so let this change
01231   emit enableOk(true);
01232 
01233   // now iterate through to find where we are
01234   QDomElement elem = d->findElementForToolbarItem( item );
01235   if ( !elem.isNull() )
01236   {
01237     // cool, i found me.  now clone myself
01238     ToolbarItem *clone = new ToolbarItem(m_activeList,
01239                                          item->itemBelow(),
01240                                          item->internalTag(),
01241                                          item->internalName(),
01242                                          item->statusText());
01243     clone->setText(1, item->text(1));
01244 
01245     // only set new pixmap if exists
01246     if( item->pixmap(0) )
01247       clone->setPixmap(0, *item->pixmap(0));
01248 
01249     // remove the old me
01250     m_activeList->takeItem(item);
01251     delete item;
01252 
01253     // select my clone
01254     m_activeList->setSelected(clone, true);
01255 
01256     // make clone visible
01257     m_activeList->ensureItemVisible(clone);
01258 
01259     // and do the real move in the DOM
01260     QDomNode next = elem.nextSibling();
01261     while ( next.toElement().tagName() == QString( "WeakSeparator" ) )
01262       next = next.nextSibling();
01263     d->m_currentToolbarElem.insertAfter(elem, next);
01264 
01265     // and set this container as a noMerge
01266     d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
01267 
01268     // update the local doc
01269     updateLocal(d->m_currentToolbarElem);
01270   }
01271 }
01272 
01273 void KEditToolbarWidget::updateLocal(QDomElement& elem)
01274 {
01275   static const QString &attrName = KGlobal::staticQString( "name" );
01276 
01277   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
01278   for ( ; xit != d->m_xmlFiles.end(); ++xit)
01279   {
01280     if ( (*xit).m_type == XmlData::Merged )
01281       continue;
01282 
01283     if ( (*xit).m_type == XmlData::Shell ||
01284          (*xit).m_type == XmlData::Part )
01285     {
01286       if ( d->m_currentXmlData.m_xmlFile == (*xit).m_xmlFile )
01287       {
01288         (*xit).m_isModified = true;
01289         return;
01290       }
01291 
01292       continue;
01293     }
01294 
01295     (*xit).m_isModified = true;
01296 
01297     ToolbarList::Iterator it = (*xit).m_barList.begin();
01298     for ( ; it != (*xit).m_barList.end(); ++it)
01299     {
01300       QString name( (*it).attribute( attrName ) );
01301       QString tag( (*it).tagName() );
01302       if ( (tag != elem.tagName()) || (name != elem.attribute(attrName)) )
01303         continue;
01304 
01305       QDomElement toolbar = (*xit).m_document.documentElement().toElement();
01306       toolbar.replaceChild(elem, (*it));
01307       return;
01308     }
01309 
01310     // just append it
01311     QDomElement toolbar = (*xit).m_document.documentElement().toElement();
01312     toolbar.appendChild(elem);
01313   }
01314 }
01315 
01316 void KEditToolbarWidget::slotChangeIcon()
01317 {
01318   // We can't use KIconChooser here, since it's in libkio
01319   // ##### KDE4: reconsider this, e.g. move KEditToolbar to libkio
01320   d->m_kdialogProcess = new KProcIO;
01321   QString kdialogExe = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
01322   (*d->m_kdialogProcess) << kdialogExe;
01323   (*d->m_kdialogProcess) << "--embed";
01324   (*d->m_kdialogProcess) << QString::number( topLevelWidget()->winId() );
01325   (*d->m_kdialogProcess) << "--geticon";
01326   (*d->m_kdialogProcess) << "Toolbar";
01327   (*d->m_kdialogProcess) << "Actions";
01328   if ( !d->m_kdialogProcess->start( KProcess::NotifyOnExit ) ) {
01329     kdError(240) << "Can't run " << kdialogExe << endl;
01330     delete d->m_kdialogProcess;
01331     d->m_kdialogProcess = 0;
01332     return;
01333   }
01334 
01335   m_activeList->setEnabled( false ); // don't change the current item
01336   m_toolbarCombo->setEnabled( false ); // don't change the current toolbar
01337 
01338   connect( d->m_kdialogProcess, SIGNAL( processExited( KProcess* ) ),
01339            this, SLOT( slotProcessExited( KProcess* ) ) );
01340 }
01341 
01342 void KEditToolbarWidget::slotProcessExited( KProcess* )
01343 {
01344   m_activeList->setEnabled( true );
01345   m_toolbarCombo->setEnabled( true );
01346 
01347   QString icon;
01348   if ( !d->m_kdialogProcess->normalExit() ||
01349        d->m_kdialogProcess->exitStatus() != 0 ||
01350        d->m_kdialogProcess->readln(icon, true) <= 0 ) {
01351     delete d->m_kdialogProcess;
01352     d->m_kdialogProcess = 0;
01353     return;
01354   }
01355 
01356   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
01357   if(item){
01358     item->setPixmap(0, BarIcon(icon, 16));
01359 
01360     d->m_currentXmlData.m_isModified = true;
01361 
01362     // Get hold of ActionProperties tag
01363     QDomElement elem = KXMLGUIFactory::actionPropertiesElement( d->m_currentXmlData.m_document );
01364     // Find or create an element for this action
01365     QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, item->internalName(), true /*create*/ );
01366     Q_ASSERT( !act_elem.isNull() );
01367     act_elem.setAttribute( "icon", icon );
01368 
01369     // we're modified, so let this change
01370     emit enableOk(true);
01371   }
01372   
01373   delete d->m_kdialogProcess;
01374   d->m_kdialogProcess = 0;
01375 }
01376 
01377 void KEditToolbar::virtual_hook( int id, void* data )
01378 { KDialogBase::virtual_hook( id, data ); }
01379 
01380 void KEditToolbarWidget::virtual_hook( int id, void* data )
01381 { KXMLGUIClient::virtual_hook( id, data ); }
01382 
01383 #include "kedittoolbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jul 22 10:16:44 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003