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