kdeui Library API Documentation

kedittoolbar.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, USA.
00017 */
00018 #include <kedittoolbar.h>
00019 
00020 #include <qdom.h>
00021 
00022 #include <qlayout.h>
00023 #include <kaction.h>
00024 
00025 #include <qheader.h>
00026 #include <qcombobox.h>
00027 #include <qtoolbutton.h>
00028 #include <qlabel.h>
00029 #include <qvaluelist.h>
00030 #include <qapplication.h>
00031 
00032 #include <kstandarddirs.h>
00033 #include <klocale.h>
00034 #include <kicontheme.h>
00035 #include <kiconloader.h>
00036 #include <kinstance.h>
00037 #include <kxmlguifactory.h>
00038 #include <kseparator.h>
00039 #include <kconfig.h>
00040 #include <klistview.h>
00041 
00042 #include <qtextstream.h>
00043 #include <qfile.h>
00044 #include <kdebug.h>
00045 
00046 static void dump_xml(const QDomDocument& doc)
00047 {
00048     QString str;
00049     QTextStream ts(&str, IO_WriteOnly);
00050     ts << doc;
00051     kdDebug() << str << endl;
00052 }
00053 
00054 typedef QValueList<QDomElement> ToolbarList;
00055 
00056 namespace
00057 {
00058 class XmlData
00059 {
00060 public:
00061   enum XmlType { Shell = 0, Part, Local, Merged };
00062   XmlData()
00063   {
00064     m_isModified = false;
00065   }
00066 
00067   QString      m_xmlFile;
00068   QDomDocument m_document;
00069   XmlType      m_type;
00070   bool         m_isModified;
00071 
00072   ToolbarList  m_barList;
00073 };
00074 
00075 typedef QValueList<XmlData> XmlDataList;
00076 
00077 class ToolbarItem : public QListViewItem
00078 {
00079 public:
00080   ToolbarItem(KListView *parent, const QString& tag, const QString& name, const QString& statusText)
00081     : QListViewItem(parent),
00082       m_tag(tag),
00083       m_name(name),
00084       m_statusText(statusText)
00085   {
00086   }
00087 
00088   ToolbarItem(KListView *parent, QListViewItem *item, const QString &tag, const QString& name, const QString& statusText)
00089     : QListViewItem(parent, item),
00090       m_tag(tag),
00091       m_name(name),
00092       m_statusText(statusText)
00093   {
00094   }
00095 
00096   QString internalTag() const { return m_tag; }
00097   QString internalName() const { return m_name; }
00098   QString statusText() const { return m_statusText; }
00099 private:
00100   QString m_tag;
00101   QString m_name;
00102   QString m_statusText;
00103 };
00104 } // namespace
00105 
00106 class KEditToolbarWidgetPrivate
00107 {
00108 public:
00116   KEditToolbarWidgetPrivate(KInstance *instance, KActionCollection* collection)
00117       : m_collection( collection )
00118   {
00119     m_instance = instance;
00120     m_isPart   = false;
00121     m_helpArea = 0L;
00122   }
00123   ~KEditToolbarWidgetPrivate()
00124   {
00125   }
00126 
00127   QString xmlFile(const QString& xml_file)
00128   {
00129     return xml_file.isNull() ? QString(m_instance->instanceName()) + "ui.rc" :
00130                                xml_file;
00131   }
00132 
00136   QString loadXMLFile(const QString& _xml_file)
00137   {
00138     QString raw_xml;
00139     QString xml_file = xmlFile(_xml_file);
00140     //kdDebug() << "loadXMLFile xml_file=" << xml_file << endl;
00141 
00142     if ( xml_file[0] == '/' )
00143       raw_xml = KXMLGUIFactory::readConfigFile(xml_file);
00144     else
00145       raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_instance);
00146 
00147     return raw_xml;
00148   }
00149 
00153   ToolbarList findToolbars(QDomElement elem)
00154   {
00155     static const QString &tagToolbar = KGlobal::staticQString( "ToolBar" );
00156     static const QString &attrNoEdit = KGlobal::staticQString( "noEdit" );
00157     ToolbarList list;
00158 
00159     for( ; !elem.isNull(); elem = elem.nextSibling().toElement() )
00160     {
00161       if (elem.tagName() == tagToolbar && elem.attribute( attrNoEdit ) != "true" )
00162         list.append(elem);
00163 
00164       QDomElement child = elem.firstChild().toElement();
00165       list += findToolbars(child);
00166     }
00167 
00168     return list;
00169   }
00170 
00171   QValueList<KAction*> m_actionList;
00172   KActionCollection* m_collection;
00173   KInstance         *m_instance;
00174 
00175   XmlData     m_currentXmlData;
00176   QDomElement m_currentToolbarElem;
00177 
00178   QString            m_xmlFile;
00179   QString            m_globalFile;
00180   QString            m_rcFile;
00181   QDomDocument       m_localDoc;
00182   bool               m_isPart;
00183 
00184   ToolbarList        m_barList;
00185 
00186   XmlDataList m_xmlFiles;
00187 
00188   QLabel * m_helpArea;
00189 
00190 };
00191 
00192 class KEditToolbarPrivate {
00193 public:
00194     bool m_accept;
00195 };
00196 
00197 KEditToolbar::KEditToolbar(KActionCollection *collection, const QString& file,
00198                            bool global, QWidget* parent, const char* name)
00199   : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00200     m_widget(new KEditToolbarWidget(collection, file, global, this))
00201 {
00202     init();
00203 }
00204 
00205 KEditToolbar::KEditToolbar(const QString& defaultToolbar, KActionCollection *collection,
00206                            const QString& file, bool global,
00207                            QWidget* parent, const char* name)
00208   : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00209     m_widget(new KEditToolbarWidget(defaultToolbar, collection, file, global, this))
00210 {
00211     init();
00212 }
00213 
00214 KEditToolbar::KEditToolbar(KXMLGUIFactory* factory, QWidget* parent, const char* name)
00215     : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00216       m_widget(new KEditToolbarWidget(factory, this))
00217 {
00218     init();
00219 }
00220 
00221 KEditToolbar::KEditToolbar(const QString& defaultToolbar,KXMLGUIFactory* factory,
00222                            QWidget* parent, const char* name)
00223     : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name),
00224       m_widget(new KEditToolbarWidget(defaultToolbar, factory, this))
00225 {
00226     init();
00227 }
00228 
00229 void KEditToolbar::init()
00230 {
00231     d = new KEditToolbarPrivate();
00232     d->m_accept = false;
00233 
00234     setMainWidget(m_widget);
00235 
00236     connect(m_widget, SIGNAL(enableOk(bool)), SLOT(acceptOK(bool)));
00237     connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool)));
00238     enableButtonApply(false);
00239 
00240     setMinimumSize(sizeHint());
00241 }
00242 
00243 KEditToolbar::~KEditToolbar()
00244 {
00245     delete d;
00246 }
00247 
00248 void KEditToolbar::acceptOK(bool b)
00249 {
00250     enableButtonOK(b);
00251     d->m_accept = b;
00252 }
00253 
00254 void KEditToolbar::slotOk()
00255 {
00256   if (!d->m_accept) {
00257       reject();
00258       return;
00259   }
00260 
00261   if (!m_widget->save())
00262   {
00263     // some error box here is needed
00264   }
00265   else
00266   {
00267     emit newToolbarConfig();
00268     accept();
00269   }
00270 }
00271 
00272 void KEditToolbar::slotApply()
00273 {
00274     (void)m_widget->save();
00275     enableButtonApply(false);
00276     emit newToolbarConfig();
00277 }
00278 
00279 KEditToolbarWidget::KEditToolbarWidget(KActionCollection *collection,
00280                                        const QString& file,
00281                                        bool global, QWidget *parent)
00282   : QWidget(parent),
00283     d(new KEditToolbarWidgetPrivate(instance(), collection))
00284 {
00285   initNonKPart(collection, file, global);
00286   // now load in our toolbar combo box
00287   loadToolbarCombo();
00288   adjustSize();
00289   setMinimumSize(sizeHint());
00290 }
00291 
00292 KEditToolbarWidget::KEditToolbarWidget(const QString& defaultToolbar,
00293                                        KActionCollection *collection,
00294                                        const QString& file, bool global,
00295                                        QWidget *parent)
00296   : QWidget(parent),
00297     d(new KEditToolbarWidgetPrivate(instance(), collection))
00298 {
00299   initNonKPart(collection, file, global);
00300   // now load in our toolbar combo box
00301   loadToolbarCombo(defaultToolbar);
00302   adjustSize();
00303   setMinimumSize(sizeHint());
00304 }
00305 
00306 KEditToolbarWidget::KEditToolbarWidget( KXMLGUIFactory* factory,
00307                                         QWidget *parent)
00308   : QWidget(parent),
00309     d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
00310 {
00311   initKPart(factory);
00312   // now load in our toolbar combo box
00313   loadToolbarCombo();
00314   adjustSize();
00315   setMinimumSize(sizeHint());
00316 }
00317 
00318 KEditToolbarWidget::KEditToolbarWidget( const QString& defaultToolbar,
00319                                         KXMLGUIFactory* factory,
00320                                         QWidget *parent)
00321   : QWidget(parent),
00322     d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
00323 {
00324   initKPart(factory);
00325   // now load in our toolbar combo box
00326   loadToolbarCombo(defaultToolbar);
00327   adjustSize();
00328   setMinimumSize(sizeHint());
00329 }
00330 
00331 KEditToolbarWidget::~KEditToolbarWidget()
00332 {
00333     delete d;
00334 }
00335 
00336 void KEditToolbarWidget::initNonKPart(KActionCollection *collection,
00337                                       const QString& file, bool global)
00338 {
00339   // let's not forget the stuff that's not xml specific
00340   //d->m_collection = *collection;
00341   d->m_actionList = collection->actions();
00342 
00343   // handle the merging
00344   if (global)
00345     setXMLFile(locate("config", "ui/ui_standards.rc"));
00346   QString localXML = d->loadXMLFile(file);
00347   setXML(localXML, true);
00348 
00349   // reusable vars
00350   QDomElement elem;
00351 
00352   // first, get all of the necessary info for our local xml
00353   XmlData local;
00354   local.m_xmlFile = d->xmlFile(file);
00355   local.m_type    = XmlData::Local;
00356   local.m_document.setContent(localXML);
00357   elem = local.m_document.documentElement().toElement();
00358   KXMLGUIFactory::removeDOMComments( elem );
00359   local.m_barList = d->findToolbars(elem);
00360   d->m_xmlFiles.append(local);
00361 
00362   // then, the merged one
00363   XmlData merge;
00364   merge.m_xmlFile  = QString::null;
00365   merge.m_type     = XmlData::Merged;
00366   merge.m_document = domDocument();
00367   elem = merge.m_document.documentElement().toElement();
00368   merge.m_barList  = d->findToolbars(elem);
00369   d->m_xmlFiles.append(merge);
00370 
00371   // okay, that done, we concern ourselves with the GUI aspects
00372   setupLayout();
00373 }
00374 
00375 void KEditToolbarWidget::initKPart(KXMLGUIFactory* factory)
00376 {
00377   // reusable vars
00378   QDomElement elem;
00379 
00380   setFactory( factory );
00381   actionCollection()->setWidget( this );
00382 
00383   // add all of the client data
00384   QPtrList<KXMLGUIClient> clients(factory->clients());
00385   QPtrListIterator<KXMLGUIClient> it( clients );
00386   for( ; it.current(); ++it)
00387   {
00388     KXMLGUIClient *client = it.current();
00389 
00390     if (client->xmlFile().isNull())
00391       continue;
00392 
00393     XmlData data;
00394     data.m_xmlFile = client->localXMLFile();
00395     if ( it.atFirst() )
00396       data.m_type = XmlData::Shell;
00397     else
00398       data.m_type = XmlData::Part;
00399     data.m_document.setContent( KXMLGUIFactory::readConfigFile( client->xmlFile(), client->instance() ) );
00400     elem = data.m_document.documentElement().toElement();
00401     KXMLGUIFactory::removeDOMComments( elem );
00402     data.m_barList = d->findToolbars(elem);
00403     d->m_xmlFiles.append(data);
00404 
00405     d->m_actionList += client->actionCollection()->actions();
00406   }
00407 
00408   // okay, that done, we concern ourselves with the GUI aspects
00409   setupLayout();
00410 }
00411 
00412 bool KEditToolbarWidget::save()
00413 {
00414   //kdDebug() << "KEditToolbarWidget::save" << endl;
00415   XmlDataList::Iterator it = d->m_xmlFiles.begin();
00416   for ( ; it != d->m_xmlFiles.end(); ++it)
00417   {
00418     // let's not save non-modified files
00419     if ( (*it).m_isModified == false )
00420       continue;
00421 
00422     // let's also skip (non-existent) merged files
00423     if ( (*it).m_type == XmlData::Merged )
00424       continue;
00425 
00426     dump_xml((*it).m_document);
00427 
00428     // if we got this far, we might as well just save it
00429     KXMLGUIFactory::saveConfigFile((*it).m_document, (*it).m_xmlFile);
00430   }
00431 
00432   if ( !factory() )
00433     return true;
00434 
00435   QPtrList<KXMLGUIClient> clients(factory()->clients());
00436   //kdDebug() << "factory: " << clients.count() << " clients" << endl;
00437 
00438   // remove the elements starting from the last going to the first
00439   KXMLGUIClient *client = clients.last();
00440   while ( client )
00441   {
00442     //kdDebug() << "factory->removeClient " << client << endl;
00443     factory()->removeClient( client );
00444     client = clients.prev();
00445   }
00446 
00447   client = clients.first();
00448   KXMLGUIClient *firstClient = client;
00449 
00450   // now, rebuild the gui from the first to the last
00451   //kdDebug() << "rebuildling the gui" << endl;
00452   for (; client; client = clients.next() )
00453   {
00454     QString file( client->xmlFile() ); // before setting ui_standards!
00455     if ( !file.isEmpty() )
00456     {
00457         // passing an empty stream forces the clients to reread the XML
00458         client->setXMLGUIBuildDocument( QDomDocument() );
00459 
00460         // for the shell, merge in ui_standards.rc
00461         if ( client == firstClient ) // same assumption as in the ctor: first==shell
00462             client->setXMLFile(locate("config", "ui/ui_standards.rc"));
00463 
00464         // and this forces it to use the *new* XML file
00465         client->setXMLFile( file, client == firstClient /* merge if shell */ );
00466     }
00467 
00468     //kdDebug() << "factory->addClient " << client << endl;
00469     // finally, do all the real work
00470     factory()->addClient( client );
00471   }
00472 
00473   return true;
00474 }
00475 
00476 void KEditToolbarWidget::setupLayout()
00477 {
00478   // the toolbar name combo
00479   QLabel *toolbar_label = new QLabel(i18n("&Toolbar:"), this);
00480   m_toolbarCombo = new QComboBox(this);
00481   m_toolbarCombo->setEnabled(false);
00482   toolbar_label->setBuddy(m_toolbarCombo);
00483   connect(m_toolbarCombo, SIGNAL(activated(const QString&)),
00484           this,           SLOT(slotToolbarSelected(const QString&)));
00485 
00486 //  QPushButton *new_toolbar = new QPushButton(i18n("&New"), this);
00487 //  new_toolbar->setPixmap(BarIcon("filenew", KIcon::SizeSmall));
00488 //  new_toolbar->setEnabled(false); // disabled until implemented
00489 //  QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this);
00490 //  del_toolbar->setPixmap(BarIcon("editdelete", KIcon::SizeSmall));
00491 //  del_toolbar->setEnabled(false); // disabled until implemented
00492 
00493   // our list of inactive actions
00494   QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), this);
00495   m_inactiveList = new KListView(this);
00496   m_inactiveList->setAllColumnsShowFocus(true);
00497   m_inactiveList->setMinimumSize(180, 250);
00498   m_inactiveList->header()->hide();
00499   m_inactiveList->addColumn("");
00500   int column2 = m_inactiveList->addColumn("");
00501   m_inactiveList->setSorting( column2 );
00502   inactive_label->setBuddy(m_inactiveList);
00503   connect(m_inactiveList, SIGNAL(selectionChanged(QListViewItem *)),
00504           this,           SLOT(slotInactiveSelected(QListViewItem *)));
00505 
00506   // our list of active actions
00507   QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), this);
00508   m_activeList = new KListView(this);
00509   m_activeList->setAllColumnsShowFocus(true);
00510   m_activeList->setMinimumWidth(m_inactiveList->minimumWidth());
00511   m_activeList->header()->hide();
00512   m_activeList->addColumn("");
00513   m_activeList->addColumn("");
00514   m_activeList->setSorting (-1);
00515   active_label->setBuddy(m_activeList);
00516 
00517   connect(m_activeList, SIGNAL(selectionChanged(QListViewItem *)),
00518           this,         SLOT(slotActiveSelected(QListViewItem *)));
00519 
00520   QIconSet iconSet;
00521 
00522   m_upAction     = new QToolButton(this);
00523   iconSet = SmallIconSet( "up" );
00524   m_upAction->setIconSet( iconSet );
00525   m_upAction->setEnabled(false);
00526   m_upAction->setAutoRepeat(true);
00527   connect(m_upAction, SIGNAL(clicked()), SLOT(slotUpButton()));
00528 
00529   m_insertAction = new QToolButton(this);
00530   iconSet = QApplication::reverseLayout() ? SmallIconSet( "back" ) : SmallIconSet( "forward" );
00531   m_insertAction->setIconSet( iconSet );
00532   m_insertAction->setEnabled(false);
00533   connect(m_insertAction, SIGNAL(clicked()), SLOT(slotInsertButton()));
00534 
00535   m_removeAction = new QToolButton(this);
00536   iconSet = QApplication::reverseLayout() ? SmallIconSet( "forward" ) : SmallIconSet( "back" );
00537   m_removeAction->setIconSet( iconSet );
00538   m_removeAction->setEnabled(false);
00539   connect(m_removeAction, SIGNAL(clicked()), SLOT(slotRemoveButton()));
00540 
00541   m_downAction   = new QToolButton(this);
00542   iconSet = SmallIconSet( "down" );
00543   m_downAction->setIconSet( iconSet );
00544   m_downAction->setEnabled(false);
00545   m_downAction->setAutoRepeat(true);
00546   connect(m_downAction, SIGNAL(clicked()), SLOT(slotDownButton()));
00547 
00548   d->m_helpArea = new QLabel(this);
00549   d->m_helpArea->setAlignment( Qt::WordBreak );
00550 
00551   // now start with our layouts
00552   QVBoxLayout *top_layout = new QVBoxLayout(this, 0, KDialog::spacingHint());
00553 
00554   QVBoxLayout *name_layout = new QVBoxLayout(KDialog::spacingHint());
00555   QHBoxLayout *list_layout = new QHBoxLayout(KDialog::spacingHint());
00556 
00557   QVBoxLayout *inactive_layout = new QVBoxLayout(KDialog::spacingHint());
00558   QVBoxLayout *active_layout = new QVBoxLayout(KDialog::spacingHint());
00559 
00560   QGridLayout *button_layout = new QGridLayout(5, 3, 0);
00561 
00562   name_layout->addWidget(toolbar_label);
00563   name_layout->addWidget(m_toolbarCombo);
00564 //  name_layout->addWidget(new_toolbar);
00565 //  name_layout->addWidget(del_toolbar);
00566 
00567   button_layout->setRowStretch( 0, 10 );
00568   button_layout->addWidget(m_upAction, 1, 1);
00569   button_layout->addWidget(m_removeAction, 2, 0);
00570   button_layout->addWidget(m_insertAction, 2, 2);
00571   button_layout->addWidget(m_downAction, 3, 1);
00572   button_layout->setRowStretch( 4, 10 );
00573 
00574   inactive_layout->addWidget(inactive_label);
00575   inactive_layout->addWidget(m_inactiveList, 1);
00576 
00577   active_layout->addWidget(active_label);
00578   active_layout->addWidget(m_activeList, 1);
00579 
00580   list_layout->addLayout(inactive_layout);
00581   list_layout->addLayout(button_layout);
00582   list_layout->addLayout(active_layout);
00583 
00584   top_layout->addLayout(name_layout);
00585   top_layout->addWidget(new KSeparator(this));
00586   top_layout->addLayout(list_layout,10);
00587   top_layout->addWidget(d->m_helpArea);
00588   top_layout->addWidget(new KSeparator(this));
00589 }
00590 
00591 void KEditToolbarWidget::loadToolbarCombo(const QString& defaultToolbar)
00592 {
00593   static const QString &attrName = KGlobal::staticQString( "name" );
00594   static const QString &tagText = KGlobal::staticQString( "text" );
00595   static const QString &tagText2 = KGlobal::staticQString( "Text" );
00596 
00597   // just in case, we clear our combo
00598   m_toolbarCombo->clear();
00599 
00600   int defaultToolbarId = 0;
00601   int count = 0;
00602   // load in all of the toolbar names into this combo box
00603   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
00604   for ( ; xit != d->m_xmlFiles.end(); ++xit)
00605   {
00606     // skip the local one in favor of the merged
00607     if ( (*xit).m_type == XmlData::Local )
00608       continue;
00609 
00610     // each xml file may have any number of toolbars
00611     ToolbarList::Iterator it = (*xit).m_barList.begin();
00612     for ( ; it != (*xit).m_barList.end(); ++it)
00613     {
00614       QString name;
00615       QCString txt( (*it).namedItem( tagText ).toElement().text().utf8() );
00616       if ( txt.isEmpty() )
00617           txt = (*it).namedItem( tagText2 ).toElement().text().utf8();
00618       if ( txt.isEmpty() )
00619           name = (*it).attribute( attrName );
00620       else
00621           name = i18n( txt );
00622 
00623       // the name of the toolbar might depend on whether or not
00624       // it is in kparts
00625       if ( ( (*xit).m_type == XmlData::Shell ) ||
00626            ( (*xit).m_type == XmlData::Part ) )
00627       {
00628         QString doc_name((*xit).m_document.documentElement().attribute( attrName ));
00629         name += " <" + doc_name + ">";
00630       }
00631 
00632       m_toolbarCombo->setEnabled( true );
00633       m_toolbarCombo->insertItem( name );
00634       if (name == defaultToolbar)
00635           defaultToolbarId = count;
00636       count++;
00637     }
00638   }
00639 
00640   // we want to the specified item selected and its actions loaded
00641   m_toolbarCombo->setCurrentItem(defaultToolbarId);
00642   slotToolbarSelected(m_toolbarCombo->currentText());
00643 }
00644 
00645 void KEditToolbarWidget::loadActionList(QDomElement& elem)
00646 {
00647   static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
00648   static const QString &tagMerge     = KGlobal::staticQString( "Merge" );
00649   static const QString &tagActionList= KGlobal::staticQString( "ActionList" );
00650   static const QString &attrName     = KGlobal::staticQString( "name" );
00651 
00652   int     sep_num = 0;
00653   QString sep_name("separator_%1");
00654 
00655   // clear our lists
00656   m_inactiveList->clear();
00657   m_activeList->clear();
00658   m_insertAction->setEnabled(false);
00659   m_removeAction->setEnabled(false);
00660   m_upAction->setEnabled(false);
00661   m_downAction->setEnabled(false);
00662 
00663   // store the names of our active actions
00664   QMap<QString, bool> active_list;
00665 
00666   // see if our current action is in this toolbar
00667   QDomElement it = elem.lastChild().toElement();
00668   for( ; !it.isNull(); it = it.previousSibling().toElement() )
00669   {
00670     if (it.tagName() == tagSeparator)
00671     {
00672       ToolbarItem *act = new ToolbarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString::null);
00673       act->setText(1, "-----");
00674       it.setAttribute( attrName, act->internalName() );
00675       continue;
00676     }
00677 
00678     if (it.tagName() == tagMerge)
00679     {
00680       // Merge can be named or not - use the name if there is one
00681       QString name = it.attribute( attrName );
00682       ToolbarItem *act = new ToolbarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component."));
00683       if ( name.isEmpty() )
00684           act->setText(1, i18n("<Merge>"));
00685       else
00686           act->setText(1, i18n("<Merge %1>").arg(name));
00687       continue;
00688     }
00689 
00690     if (it.tagName() == tagActionList)
00691     {
00692       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.") );
00693       act->setText(1, i18n("ActionList: %1").arg(it.attribute(attrName)));
00694       continue;
00695     }
00696 
00697     // iterate through all of our actions
00698     for (unsigned int i = 0;  i < d->m_actionList.count(); i++)
00699     {
00700       KAction *action = d->m_actionList[i];
00701 
00702       // do we have a match?
00703       if (it.attribute( attrName ) == action->name())
00704       {
00705         // we have a match!
00706         ToolbarItem *act = new ToolbarItem(m_activeList, it.tagName(), action->name(), action->toolTip());
00707         act->setText(1, action->plainText());
00708         if (action->hasIcon())
00709           if (!action->icon().isEmpty())
00710             act->setPixmap(0, BarIcon(action->icon(), 16));
00711           else // Has iconset
00712             act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
00713 
00714         active_list.insert(action->name(), true);
00715         break;
00716       }
00717     }
00718   }
00719 
00720   // go through the rest of the collection
00721   for (int i = d->m_actionList.count() - 1; i > -1; --i)
00722   {
00723     KAction *action = d->m_actionList[i];
00724 
00725     // skip our active ones
00726     if (active_list.contains(action->name()))
00727       continue;
00728 
00729     ToolbarItem *act = new ToolbarItem(m_inactiveList, tagActionList, action->name(), action->toolTip());
00730     act->setText(1, action->plainText());
00731     if (action->hasIcon())
00732       if (!action->icon().isEmpty())
00733         act->setPixmap(0, BarIcon(action->icon(), 16));
00734       else // Has iconset
00735         act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
00736   }
00737 
00738   // finally, add a default separator to the inactive list
00739   ToolbarItem *act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null);
00740   act->setText(1, "-----");
00741 }
00742 
00743 KActionCollection *KEditToolbarWidget::actionCollection() const
00744 {
00745   return d->m_collection;
00746 }
00747 
00748 void KEditToolbarWidget::slotToolbarSelected(const QString& _text)
00749 {
00750   static const QString &attrName = KGlobal::staticQString( "name" );
00751   static const QString &tagText = KGlobal::staticQString( "text" );
00752   static const QString &tagText2 = KGlobal::staticQString( "Text" );
00753 
00754   // iterate through everything
00755   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
00756   for ( ; xit != d->m_xmlFiles.end(); ++xit)
00757   {
00758     // each xml file may have any number of toolbars
00759     ToolbarList::Iterator it = (*xit).m_barList.begin();
00760     for ( ; it != (*xit).m_barList.end(); ++it)
00761     {
00762       QString name;
00763       QCString txt( (*it).namedItem( tagText ).toElement().text().utf8() );
00764       if ( txt.isEmpty() )
00765           txt = (*it).namedItem( tagText2 ).toElement().text().utf8();
00766       if ( txt.isEmpty() )
00767           name = (*it).attribute( attrName );
00768       else
00769           name = i18n( txt );
00770 
00771       // the name of the toolbar might depend on whether or not
00772       // it is in kparts
00773       if ( ( (*xit).m_type == XmlData::Shell ) ||
00774            ( (*xit).m_type == XmlData::Part ) )
00775       {
00776         QString doc_name((*xit).m_document.documentElement().attribute( attrName ));
00777         name += " <" + doc_name + ">";
00778       }
00779 
00780       // is this our toolbar?
00781       if ( name == _text )
00782       {
00783         // save our current settings
00784         d->m_currentXmlData     = (*xit);
00785         d->m_currentToolbarElem = (*it);
00786 
00787         // load in our values
00788         loadActionList(d->m_currentToolbarElem);
00789 
00790         if ((*xit).m_type == XmlData::Part || (*xit).m_type == XmlData::Shell)
00791           setDOMDocument( (*xit).m_document );
00792         return;
00793       }
00794     }
00795   }
00796 }
00797 
00798 void KEditToolbarWidget::slotInactiveSelected(QListViewItem *item)
00799 {
00800   if (item)
00801   {
00802     m_insertAction->setEnabled(true);
00803     QString statusText = static_cast<ToolbarItem *>(item)->statusText();
00804     d->m_helpArea->setText( statusText );
00805   }
00806   else
00807   {
00808     m_insertAction->setEnabled(false);
00809     d->m_helpArea->setText( QString::null );
00810   }
00811 }
00812 
00813 void KEditToolbarWidget::slotActiveSelected(QListViewItem *item)
00814 {
00815   if (item)
00816   {
00817     m_removeAction->setEnabled(true);
00818 
00819     if (item->itemAbove())
00820       m_upAction->setEnabled(true);
00821     else
00822       m_upAction->setEnabled(false);
00823 
00824     if (item->itemBelow())
00825       m_downAction->setEnabled(true);
00826     else
00827       m_downAction->setEnabled(false);
00828     QString statusText = static_cast<ToolbarItem *>(item)->statusText();
00829     d->m_helpArea->setText( statusText );
00830   }
00831   else
00832   {
00833     m_removeAction->setEnabled(false);
00834     m_upAction->setEnabled(false);
00835     m_downAction->setEnabled(false);
00836     d->m_helpArea->setText( QString::null );
00837   }
00838 }
00839 
00840 void KEditToolbarWidget::slotInsertButton()
00841 {
00842   static const QString &tagAction    = KGlobal::staticQString( "Action" );
00843   static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
00844   static const QString &attrName     = KGlobal::staticQString( "name" );
00845 
00846   // we're modified, so let this change
00847   emit enableOk(true);
00848 
00849   ToolbarItem *item = (ToolbarItem*)m_inactiveList->currentItem();
00850 
00851   QDomElement new_item;
00852   // let's handle the separator specially
00853   if (item->text(1) == "-----")
00854     new_item = domDocument().createElement(tagSeparator);
00855   else
00856     new_item = domDocument().createElement(tagAction);
00857   new_item.setAttribute(attrName, item->internalName());
00858 
00859   if (m_activeList->currentItem())
00860   {
00861     // we have a selected item in the active list.. so let's try
00862     // our best to add our new item right after the selected one
00863     ToolbarItem *act_item = (ToolbarItem*)m_activeList->currentItem();
00864     QDomElement elem = d->m_currentToolbarElem.firstChild().toElement();
00865     for( ; !elem.isNull(); elem = elem.nextSibling().toElement())
00866     {
00867       if ((elem.attribute(attrName) == act_item->internalName()) &&
00868           (elem.tagName() == act_item->internalTag()))
00869       {
00870         d->m_currentToolbarElem.insertAfter(new_item, elem);
00871         break;
00872       }
00873     }
00874   }
00875   else
00876   {
00877     // just stick it at the end of this
00878     d->m_currentToolbarElem.appendChild(new_item);
00879   }
00880 
00881   // and set this container as a noMerge
00882   d->m_currentToolbarElem.setAttribute(QString::fromLatin1("noMerge"), "1");
00883 
00884   // update the local doc
00885   updateLocal(d->m_currentToolbarElem);
00886 
00887   slotToolbarSelected( m_toolbarCombo->currentText() );
00888 }
00889 
00890 void KEditToolbarWidget::slotRemoveButton()
00891 {
00892   static const QString &attrName    = KGlobal::staticQString( "name" );
00893   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
00894 
00895   // we're modified, so let this change
00896   emit enableOk(true);
00897 
00898   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
00899   // now iterate through to find the child to nuke
00900   QDomElement elem = d->m_currentToolbarElem.firstChild().toElement();
00901   for( ; !elem.isNull(); elem = elem.nextSibling().toElement())
00902   {
00903     if ((elem.attribute(attrName) == item->internalName()) &&
00904         (elem.tagName() == item->internalTag()))
00905     {
00906       // nuke myself!
00907       d->m_currentToolbarElem.removeChild(elem);
00908 
00909       // and set this container as a noMerge
00910       d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
00911 
00912       // update the local doc
00913       updateLocal(d->m_currentToolbarElem);
00914       break;
00915     }
00916   }
00917   slotToolbarSelected( m_toolbarCombo->currentText() );
00918 }
00919 
00920 void KEditToolbarWidget::slotUpButton()
00921 {
00922   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
00923 
00924   // make sure we're not the top item already
00925   if (!item->itemAbove())
00926     return;
00927 
00928   static const QString &attrName    = KGlobal::staticQString( "name" );
00929   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
00930 
00931   // we're modified, so let this change
00932   emit enableOk(true);
00933 
00934   // now iterate through to find where we are
00935   QDomElement elem = d->m_currentToolbarElem.firstChild().toElement();
00936   for( ; !elem.isNull(); elem = elem.nextSibling().toElement())
00937   {
00938     if ((elem.attribute(attrName) == item->internalName()) &&
00939         (elem.tagName() == item->internalTag()))
00940     {
00941       // cool, i found me.  now clone myself
00942       ToolbarItem *clone = new ToolbarItem(m_activeList,
00943                                            item->itemAbove()->itemAbove(),
00944                                            item->internalTag(),
00945                                            item->internalName(),
00946                                            item->statusText());
00947       clone->setText(1, item->text(1));
00948 
00949       // only set new pixmap if exists
00950       if( item->pixmap(0) )
00951         clone->setPixmap(0, *item->pixmap(0));
00952 
00953       // remove the old me
00954       m_activeList->takeItem(item);
00955       delete item;
00956 
00957       // select my clone
00958       m_activeList->setSelected(clone, true);
00959 
00960       // make clone visible
00961       m_activeList->ensureItemVisible(clone);
00962 
00963       // and do the real move in the DOM
00964       QDomNode prev = elem.previousSibling();
00965       while ( prev.toElement().tagName() == QString( "WeakSeparator" ) )
00966         prev = prev.previousSibling();
00967       d->m_currentToolbarElem.insertBefore(elem, prev);
00968 
00969       // and set this container as a noMerge
00970       d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
00971 
00972       // update the local doc
00973       updateLocal(d->m_currentToolbarElem);
00974 
00975       break;
00976     }
00977   }
00978 }
00979 
00980 void KEditToolbarWidget::slotDownButton()
00981 {
00982   ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
00983 
00984   // make sure we're not the bottom item already
00985   if (!item->itemBelow())
00986     return;
00987 
00988   static const QString &attrName    = KGlobal::staticQString( "name" );
00989   static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
00990 
00991   // we're modified, so let this change
00992   emit enableOk(true);
00993 
00994   // now iterate through to find where we are
00995   QDomElement elem = d->m_currentToolbarElem.firstChild().toElement();
00996   for( ; !elem.isNull(); elem = elem.nextSibling().toElement())
00997   {
00998     if ((elem.attribute(attrName) == item->internalName()) &&
00999         (elem.tagName() == item->internalTag()))
01000     {
01001       // cool, i found me.  now clone myself
01002       ToolbarItem *clone = new ToolbarItem(m_activeList,
01003                                            item->itemBelow(),
01004                                            item->internalTag(),
01005                                            item->internalName(),
01006                                            item->statusText());
01007       clone->setText(1, item->text(1));
01008 
01009       // only set new pixmap if exists
01010       if( item->pixmap(0) )
01011         clone->setPixmap(0, *item->pixmap(0));
01012 
01013       // remove the old me
01014       m_activeList->takeItem(item);
01015       delete item;
01016 
01017       // select my clone
01018       m_activeList->setSelected(clone, true);
01019 
01020       // make clone visible
01021       m_activeList->ensureItemVisible(clone);
01022 
01023       // and do the real move in the DOM
01024       QDomNode next = elem.nextSibling();
01025       while ( next.toElement().tagName() == QString( "WeakSeparator" ) )
01026         next = next.nextSibling();
01027       d->m_currentToolbarElem.insertAfter(elem, next);
01028 
01029       // and set this container as a noMerge
01030       d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
01031 
01032       // update the local doc
01033       updateLocal(d->m_currentToolbarElem);
01034 
01035       break;
01036     }
01037   }
01038 }
01039 
01040 void KEditToolbarWidget::updateLocal(QDomElement& elem)
01041 {
01042   static const QString &attrName = KGlobal::staticQString( "name" );
01043 
01044   XmlDataList::Iterator xit = d->m_xmlFiles.begin();
01045   for ( ; xit != d->m_xmlFiles.end(); ++xit)
01046   {
01047     if ( (*xit).m_type == XmlData::Merged )
01048       continue;
01049 
01050     if ( (*xit).m_type == XmlData::Shell ||
01051          (*xit).m_type == XmlData::Part )
01052     {
01053       if ( d->m_currentXmlData.m_xmlFile == (*xit).m_xmlFile )
01054       {
01055         (*xit).m_isModified = true;
01056         return;
01057       }
01058 
01059       continue;
01060     }
01061 
01062     (*xit).m_isModified = true;
01063 
01064     ToolbarList::Iterator it = (*xit).m_barList.begin();
01065     for ( ; it != (*xit).m_barList.end(); ++it)
01066     {
01067       QString name( (*it).attribute( attrName ) );
01068       QString tag( (*it).tagName() );
01069       if ( (tag != elem.tagName()) || (name != elem.attribute(attrName)) )
01070         continue;
01071 
01072       QDomElement toolbar = (*xit).m_document.documentElement().toElement();
01073       toolbar.replaceChild(elem, (*it));
01074       return;
01075     }
01076 
01077     // just append it
01078     QDomElement toolbar = (*xit).m_document.documentElement().toElement();
01079     toolbar.appendChild(elem);
01080   }
01081 }
01082 
01083 void KEditToolbar::virtual_hook( int id, void* data )
01084 { KDialogBase::virtual_hook( id, data ); }
01085 
01086 void KEditToolbarWidget::virtual_hook( int id, void* data )
01087 { KXMLGUIClient::virtual_hook( id, data ); }
01088 
01089 #include "kedittoolbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 22 14:23:26 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003