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 = QString::null, const QString& name = QString::null , const QString& statusText = QString::null) 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 = QString::null, const QString& name = QString::null, const QString& statusText = QString::null) 00089 : QListViewItem(parent, item), 00090 m_tag(tag), 00091 m_name(name), 00092 m_statusText(statusText) 00093 { 00094 } 00095 00096 void setInternalTag(const QString &tag) { m_tag = tag; } 00097 void setInternalName(const QString &name) { m_name = name; } 00098 void setStatusText(const QString &text) { m_statusText = text; } 00099 00100 QString internalTag() const { return m_tag; } 00101 QString internalName() const { return m_name; } 00102 QString statusText() const { return m_statusText; } 00103 private: 00104 QString m_tag; 00105 QString m_name; 00106 QString m_statusText; 00107 }; 00108 #define TOOLBARITEMMIMETYPE "data/x-kde.toolbar.item" 00109 class ToolbarItemDrag : public QStoredDrag 00110 { 00111 public: 00112 ToolbarItemDrag(ToolbarItem *toolbarItem, 00113 QWidget *dragSource = 0, const char *name = 0) 00114 : QStoredDrag( TOOLBARITEMMIMETYPE, dragSource, name ) 00115 { 00116 if (toolbarItem) { 00117 QByteArray data; 00118 QDataStream out(data, IO_WriteOnly); 00119 out << toolbarItem->internalTag(); 00120 out << toolbarItem->internalName(); 00121 out << toolbarItem->statusText(); 00122 out << toolbarItem->text(1); // separators need this. 00123 setEncodedData(data); 00124 } 00125 } 00126 00127 static bool canDecode(QMimeSource* e) 00128 { 00129 return e->provides(TOOLBARITEMMIMETYPE); 00130 } 00131 00132 static bool decode( const QMimeSource* e, ToolbarItem& item ) 00133 { 00134 if (!e) 00135 return false; 00136 00137 QByteArray data = e->encodedData(TOOLBARITEMMIMETYPE); 00138 if ( data.isEmpty() ) 00139 return false; 00140 00141 QString internalTag, internalName, statusText, text; 00142 QDataStream in(data, IO_ReadOnly); 00143 in >> internalTag; 00144 in >> internalName; 00145 in >> statusText; 00146 in >> text; 00147 00148 item.setInternalTag( internalTag ); 00149 item.setInternalName( internalName ); 00150 item.setStatusText( statusText ); 00151 item.setText(1, text); 00152 00153 return true; 00154 } 00155 }; 00156 00157 class ToolbarListView : public KListView 00158 { 00159 public: 00160 ToolbarListView(QWidget *parent=0, const char *name=0) 00161 : KListView(parent, name) 00162 { 00163 } 00164 protected: 00165 virtual QDragObject *dragObject() 00166 { 00167 ToolbarItem *item = dynamic_cast<ToolbarItem*>(selectedItem()); 00168 if ( item != 0 ) { 00169 ToolbarItemDrag *obj = new ToolbarItemDrag(item, 00170 this, "ToolbarAction drag item"); 00171 const QPixmap *pm = item->pixmap(0); 00172 if( pm ) 00173 obj->setPixmap( *pm ); 00174 return obj; 00175 } 00176 return 0; 00177 } 00178 00179 virtual bool acceptDrag(QDropEvent *event) const 00180 { 00181 return ToolbarItemDrag::canDecode( event ); 00182 } 00183 }; 00184 } // namespace 00185 00186 class KEditToolbarWidgetPrivate 00187 { 00188 public: 00196 KEditToolbarWidgetPrivate(KInstance *instance, KActionCollection* collection) 00197 : m_collection( collection ) 00198 { 00199 m_instance = instance; 00200 m_isPart = false; 00201 m_helpArea = 0L; 00202 } 00203 ~KEditToolbarWidgetPrivate() 00204 { 00205 } 00206 00207 QString xmlFile(const QString& xml_file) 00208 { 00209 return xml_file.isNull() ? QString(m_instance->instanceName()) + "ui.rc" : 00210 xml_file; 00211 } 00212 00216 QString loadXMLFile(const QString& _xml_file) 00217 { 00218 QString raw_xml; 00219 QString xml_file = xmlFile(_xml_file); 00220 //kdDebug() << "loadXMLFile xml_file=" << xml_file << endl; 00221 00222 if ( xml_file[0] == '/' ) 00223 raw_xml = KXMLGUIFactory::readConfigFile(xml_file); 00224 else 00225 raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_instance); 00226 00227 return raw_xml; 00228 } 00229 00233 ToolbarList findToolbars(QDomElement elem) 00234 { 00235 static const QString &tagToolbar = KGlobal::staticQString( "ToolBar" ); 00236 static const QString &attrNoEdit = KGlobal::staticQString( "noEdit" ); 00237 ToolbarList list; 00238 00239 for( ; !elem.isNull(); elem = elem.nextSibling().toElement() ) 00240 { 00241 if (elem.tagName() == tagToolbar && elem.attribute( attrNoEdit ) != "true" ) 00242 list.append(elem); 00243 00244 QDomElement child = elem.firstChild().toElement(); 00245 list += findToolbars(child); 00246 } 00247 00248 return list; 00249 } 00253 QDomElement findElementForToolbarItem( const ToolbarItem* item ) const 00254 { 00255 static const QString &attrName = KGlobal::staticQString( "name" ); 00256 for(QDomNode n = m_currentToolbarElem.firstChild(); !n.isNull(); n = n.nextSibling()) 00257 { 00258 QDomElement elem = n.toElement(); 00259 if ((elem.attribute(attrName) == item->internalName()) && 00260 (elem.tagName() == item->internalTag())) 00261 return elem; 00262 } 00263 return QDomElement(); 00264 } 00265 00266 QValueList<KAction*> m_actionList; 00267 KActionCollection* m_collection; 00268 KInstance *m_instance; 00269 00270 XmlData m_currentXmlData; 00271 QDomElement m_currentToolbarElem; 00272 00273 QString m_xmlFile; 00274 QString m_globalFile; 00275 QString m_rcFile; 00276 QDomDocument m_localDoc; 00277 bool m_isPart; 00278 00279 ToolbarList m_barList; 00280 00281 XmlDataList m_xmlFiles; 00282 00283 QLabel * m_helpArea; 00284 00285 }; 00286 00287 class KEditToolbarPrivate { 00288 public: 00289 bool m_accept; 00290 }; 00291 00292 KEditToolbar::KEditToolbar(KActionCollection *collection, const QString& file, 00293 bool global, QWidget* parent, const char* name) 00294 : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name), 00295 m_widget(new KEditToolbarWidget(collection, file, global, this)) 00296 { 00297 init(); 00298 } 00299 00300 KEditToolbar::KEditToolbar(const QString& defaultToolbar, KActionCollection *collection, 00301 const QString& file, bool global, 00302 QWidget* parent, const char* name) 00303 : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name), 00304 m_widget(new KEditToolbarWidget(defaultToolbar, collection, file, global, this)) 00305 { 00306 init(); 00307 } 00308 00309 KEditToolbar::KEditToolbar(KXMLGUIFactory* factory, QWidget* parent, const char* name) 00310 : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name), 00311 m_widget(new KEditToolbarWidget(factory, this)) 00312 { 00313 init(); 00314 } 00315 00316 KEditToolbar::KEditToolbar(const QString& defaultToolbar,KXMLGUIFactory* factory, 00317 QWidget* parent, const char* name) 00318 : KDialogBase(Swallow, i18n("Configure Toolbars"), Ok|Apply|Cancel, Ok, parent, name), 00319 m_widget(new KEditToolbarWidget(defaultToolbar, factory, this)) 00320 { 00321 init(); 00322 } 00323 00324 void KEditToolbar::init() 00325 { 00326 d = new KEditToolbarPrivate(); 00327 d->m_accept = false; 00328 00329 setMainWidget(m_widget); 00330 00331 connect(m_widget, SIGNAL(enableOk(bool)), SLOT(acceptOK(bool))); 00332 connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool))); 00333 enableButtonApply(false); 00334 00335 setMinimumSize(sizeHint()); 00336 } 00337 00338 KEditToolbar::~KEditToolbar() 00339 { 00340 delete d; 00341 } 00342 00343 void KEditToolbar::acceptOK(bool b) 00344 { 00345 enableButtonOK(b); 00346 d->m_accept = b; 00347 } 00348 00349 void KEditToolbar::slotOk() 00350 { 00351 if (!d->m_accept) { 00352 reject(); 00353 return; 00354 } 00355 00356 if (!m_widget->save()) 00357 { 00358 // some error box here is needed 00359 } 00360 else 00361 { 00362 emit newToolbarConfig(); 00363 accept(); 00364 } 00365 } 00366 00367 void KEditToolbar::slotApply() 00368 { 00369 (void)m_widget->save(); 00370 enableButtonApply(false); 00371 emit newToolbarConfig(); 00372 } 00373 00374 KEditToolbarWidget::KEditToolbarWidget(KActionCollection *collection, 00375 const QString& file, 00376 bool global, QWidget *parent) 00377 : QWidget(parent), 00378 d(new KEditToolbarWidgetPrivate(instance(), collection)) 00379 { 00380 initNonKPart(collection, file, global); 00381 // now load in our toolbar combo box 00382 loadToolbarCombo(); 00383 adjustSize(); 00384 setMinimumSize(sizeHint()); 00385 } 00386 00387 KEditToolbarWidget::KEditToolbarWidget(const QString& defaultToolbar, 00388 KActionCollection *collection, 00389 const QString& file, bool global, 00390 QWidget *parent) 00391 : QWidget(parent), 00392 d(new KEditToolbarWidgetPrivate(instance(), collection)) 00393 { 00394 initNonKPart(collection, file, global); 00395 // now load in our toolbar combo box 00396 loadToolbarCombo(defaultToolbar); 00397 adjustSize(); 00398 setMinimumSize(sizeHint()); 00399 } 00400 00401 KEditToolbarWidget::KEditToolbarWidget( KXMLGUIFactory* factory, 00402 QWidget *parent) 00403 : QWidget(parent), 00404 d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/)) 00405 { 00406 initKPart(factory); 00407 // now load in our toolbar combo box 00408 loadToolbarCombo(); 00409 adjustSize(); 00410 setMinimumSize(sizeHint()); 00411 } 00412 00413 KEditToolbarWidget::KEditToolbarWidget( const QString& defaultToolbar, 00414 KXMLGUIFactory* factory, 00415 QWidget *parent) 00416 : QWidget(parent), 00417 d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/)) 00418 { 00419 initKPart(factory); 00420 // now load in our toolbar combo box 00421 loadToolbarCombo(defaultToolbar); 00422 adjustSize(); 00423 setMinimumSize(sizeHint()); 00424 } 00425 00426 KEditToolbarWidget::~KEditToolbarWidget() 00427 { 00428 delete d; 00429 } 00430 00431 void KEditToolbarWidget::initNonKPart(KActionCollection *collection, 00432 const QString& file, bool global) 00433 { 00434 // let's not forget the stuff that's not xml specific 00435 //d->m_collection = *collection; 00436 d->m_actionList = collection->actions(); 00437 00438 // handle the merging 00439 if (global) 00440 setXMLFile(locate("config", "ui/ui_standards.rc")); 00441 QString localXML = d->loadXMLFile(file); 00442 setXML(localXML, true); 00443 00444 // reusable vars 00445 QDomElement elem; 00446 00447 // first, get all of the necessary info for our local xml 00448 XmlData local; 00449 local.m_xmlFile = d->xmlFile(file); 00450 local.m_type = XmlData::Local; 00451 local.m_document.setContent(localXML); 00452 elem = local.m_document.documentElement().toElement(); 00453 KXMLGUIFactory::removeDOMComments( elem ); 00454 local.m_barList = d->findToolbars(elem); 00455 d->m_xmlFiles.append(local); 00456 00457 // then, the merged one 00458 XmlData merge; 00459 merge.m_xmlFile = QString::null; 00460 merge.m_type = XmlData::Merged; 00461 merge.m_document = domDocument(); 00462 elem = merge.m_document.documentElement().toElement(); 00463 merge.m_barList = d->findToolbars(elem); 00464 d->m_xmlFiles.append(merge); 00465 00466 // okay, that done, we concern ourselves with the GUI aspects 00467 setupLayout(); 00468 } 00469 00470 void KEditToolbarWidget::initKPart(KXMLGUIFactory* factory) 00471 { 00472 // reusable vars 00473 QDomElement elem; 00474 00475 setFactory( factory ); 00476 actionCollection()->setWidget( this ); 00477 00478 // add all of the client data 00479 QPtrList<KXMLGUIClient> clients(factory->clients()); 00480 QPtrListIterator<KXMLGUIClient> it( clients ); 00481 for( ; it.current(); ++it) 00482 { 00483 KXMLGUIClient *client = it.current(); 00484 00485 if (client->xmlFile().isNull()) 00486 continue; 00487 00488 XmlData data; 00489 data.m_xmlFile = client->localXMLFile(); 00490 if ( it.atFirst() ) 00491 data.m_type = XmlData::Shell; 00492 else 00493 data.m_type = XmlData::Part; 00494 data.m_document.setContent( KXMLGUIFactory::readConfigFile( client->xmlFile(), client->instance() ) ); 00495 elem = data.m_document.documentElement().toElement(); 00496 KXMLGUIFactory::removeDOMComments( elem ); 00497 data.m_barList = d->findToolbars(elem); 00498 d->m_xmlFiles.append(data); 00499 00500 d->m_actionList += client->actionCollection()->actions(); 00501 } 00502 00503 // okay, that done, we concern ourselves with the GUI aspects 00504 setupLayout(); 00505 } 00506 00507 bool KEditToolbarWidget::save() 00508 { 00509 //kdDebug() << "KEditToolbarWidget::save" << endl; 00510 XmlDataList::Iterator it = d->m_xmlFiles.begin(); 00511 for ( ; it != d->m_xmlFiles.end(); ++it) 00512 { 00513 // let's not save non-modified files 00514 if ( (*it).m_isModified == false ) 00515 continue; 00516 00517 // let's also skip (non-existent) merged files 00518 if ( (*it).m_type == XmlData::Merged ) 00519 continue; 00520 00521 dump_xml((*it).m_document); 00522 00523 // if we got this far, we might as well just save it 00524 KXMLGUIFactory::saveConfigFile((*it).m_document, (*it).m_xmlFile); 00525 } 00526 00527 if ( !factory() ) 00528 return true; 00529 00530 QPtrList<KXMLGUIClient> clients(factory()->clients()); 00531 //kdDebug() << "factory: " << clients.count() << " clients" << endl; 00532 00533 // remove the elements starting from the last going to the first 00534 KXMLGUIClient *client = clients.last(); 00535 while ( client ) 00536 { 00537 //kdDebug() << "factory->removeClient " << client << endl; 00538 factory()->removeClient( client ); 00539 client = clients.prev(); 00540 } 00541 00542 client = clients.first(); 00543 KXMLGUIClient *firstClient = client; 00544 00545 // now, rebuild the gui from the first to the last 00546 //kdDebug() << "rebuildling the gui" << endl; 00547 for (; client; client = clients.next() ) 00548 { 00549 QString file( client->xmlFile() ); // before setting ui_standards! 00550 if ( !file.isEmpty() ) 00551 { 00552 // passing an empty stream forces the clients to reread the XML 00553 client->setXMLGUIBuildDocument( QDomDocument() ); 00554 00555 // for the shell, merge in ui_standards.rc 00556 if ( client == firstClient ) // same assumption as in the ctor: first==shell 00557 client->setXMLFile(locate("config", "ui/ui_standards.rc")); 00558 00559 // and this forces it to use the *new* XML file 00560 client->setXMLFile( file, client == firstClient /* merge if shell */ ); 00561 } 00562 00563 //kdDebug() << "factory->addClient " << client << endl; 00564 // finally, do all the real work 00565 factory()->addClient( client ); 00566 } 00567 00568 return true; 00569 } 00570 00571 void KEditToolbarWidget::setupLayout() 00572 { 00573 // the toolbar name combo 00574 QLabel *toolbar_label = new QLabel(i18n("&Toolbar:"), this); 00575 m_toolbarCombo = new QComboBox(this); 00576 m_toolbarCombo->setEnabled(false); 00577 toolbar_label->setBuddy(m_toolbarCombo); 00578 connect(m_toolbarCombo, SIGNAL(activated(const QString&)), 00579 this, SLOT(slotToolbarSelected(const QString&))); 00580 00581 // QPushButton *new_toolbar = new QPushButton(i18n("&New"), this); 00582 // new_toolbar->setPixmap(BarIcon("filenew", KIcon::SizeSmall)); 00583 // new_toolbar->setEnabled(false); // disabled until implemented 00584 // QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this); 00585 // del_toolbar->setPixmap(BarIcon("editdelete", KIcon::SizeSmall)); 00586 // del_toolbar->setEnabled(false); // disabled until implemented 00587 00588 // our list of inactive actions 00589 QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), this); 00590 m_inactiveList = new ToolbarListView(this); 00591 m_inactiveList->setDragEnabled(true); 00592 m_inactiveList->setAcceptDrops(true); 00593 m_inactiveList->setDropVisualizer(false); 00594 00595 m_inactiveList->setAllColumnsShowFocus(true); 00596 m_inactiveList->setMinimumSize(180, 250); 00597 m_inactiveList->header()->hide(); 00598 m_inactiveList->addColumn(""); 00599 int column2 = m_inactiveList->addColumn(""); 00600 m_inactiveList->setSorting( column2 ); 00601 inactive_label->setBuddy(m_inactiveList); 00602 connect(m_inactiveList, SIGNAL(selectionChanged(QListViewItem *)), 00603 this, SLOT(slotInactiveSelected(QListViewItem *))); 00604 connect(m_inactiveList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )), 00605 this, SLOT(slotInsertButton())); 00606 00607 // our list of active actions 00608 QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), this); 00609 m_activeList = new ToolbarListView(this); 00610 m_activeList->setDragEnabled(true); 00611 m_activeList->setAcceptDrops(true); 00612 m_activeList->setDropVisualizer(true); 00613 m_activeList->setAllColumnsShowFocus(true); 00614 m_activeList->setMinimumWidth(m_inactiveList->minimumWidth()); 00615 m_activeList->header()->hide(); 00616 m_activeList->addColumn(""); 00617 m_activeList->addColumn(""); 00618 m_activeList->setSorting (-1); 00619 active_label->setBuddy(m_activeList); 00620 connect(m_inactiveList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)), 00621 this, SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*))); 00622 connect(m_activeList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)), 00623 this, SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*))); 00624 00625 connect(m_activeList, SIGNAL(selectionChanged(QListViewItem *)), 00626 this, SLOT(slotActiveSelected(QListViewItem *))); 00627 connect(m_activeList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )), 00628 this, SLOT(slotRemoveButton())); 00629 00630 00631 QIconSet iconSet; 00632 00633 m_upAction = new QToolButton(this); 00634 iconSet = SmallIconSet( "up" ); 00635 m_upAction->setIconSet( iconSet ); 00636 m_upAction->setEnabled(false); 00637 m_upAction->setAutoRepeat(true); 00638 connect(m_upAction, SIGNAL(clicked()), SLOT(slotUpButton())); 00639 00640 m_insertAction = new QToolButton(this); 00641 iconSet = QApplication::reverseLayout() ? SmallIconSet( "back" ) : SmallIconSet( "forward" ); 00642 m_insertAction->setIconSet( iconSet ); 00643 m_insertAction->setEnabled(false); 00644 connect(m_insertAction, SIGNAL(clicked()), SLOT(slotInsertButton())); 00645 00646 m_removeAction = new QToolButton(this); 00647 iconSet = QApplication::reverseLayout() ? SmallIconSet( "forward" ) : SmallIconSet( "back" ); 00648 m_removeAction->setIconSet( iconSet ); 00649 m_removeAction->setEnabled(false); 00650 connect(m_removeAction, SIGNAL(clicked()), SLOT(slotRemoveButton())); 00651 00652 m_downAction = new QToolButton(this); 00653 iconSet = SmallIconSet( "down" ); 00654 m_downAction->setIconSet( iconSet ); 00655 m_downAction->setEnabled(false); 00656 m_downAction->setAutoRepeat(true); 00657 connect(m_downAction, SIGNAL(clicked()), SLOT(slotDownButton())); 00658 00659 d->m_helpArea = new QLabel(this); 00660 d->m_helpArea->setAlignment( Qt::WordBreak ); 00661 00662 // now start with our layouts 00663 QVBoxLayout *top_layout = new QVBoxLayout(this, 0, KDialog::spacingHint()); 00664 00665 QVBoxLayout *name_layout = new QVBoxLayout(KDialog::spacingHint()); 00666 QHBoxLayout *list_layout = new QHBoxLayout(KDialog::spacingHint()); 00667 00668 QVBoxLayout *inactive_layout = new QVBoxLayout(KDialog::spacingHint()); 00669 QVBoxLayout *active_layout = new QVBoxLayout(KDialog::spacingHint()); 00670 00671 QGridLayout *button_layout = new QGridLayout(5, 3, 0); 00672 00673 name_layout->addWidget(toolbar_label); 00674 name_layout->addWidget(m_toolbarCombo); 00675 // name_layout->addWidget(new_toolbar); 00676 // name_layout->addWidget(del_toolbar); 00677 00678 button_layout->setRowStretch( 0, 10 ); 00679 button_layout->addWidget(m_upAction, 1, 1); 00680 button_layout->addWidget(m_removeAction, 2, 0); 00681 button_layout->addWidget(m_insertAction, 2, 2); 00682 button_layout->addWidget(m_downAction, 3, 1); 00683 button_layout->setRowStretch( 4, 10 ); 00684 00685 inactive_layout->addWidget(inactive_label); 00686 inactive_layout->addWidget(m_inactiveList, 1); 00687 00688 active_layout->addWidget(active_label); 00689 active_layout->addWidget(m_activeList, 1); 00690 00691 list_layout->addLayout(inactive_layout); 00692 list_layout->addLayout(button_layout); 00693 list_layout->addLayout(active_layout); 00694 00695 top_layout->addLayout(name_layout); 00696 top_layout->addWidget(new KSeparator(this)); 00697 top_layout->addLayout(list_layout,10); 00698 top_layout->addWidget(d->m_helpArea); 00699 top_layout->addWidget(new KSeparator(this)); 00700 } 00701 00702 void KEditToolbarWidget::loadToolbarCombo(const QString& defaultToolbar) 00703 { 00704 static const QString &attrName = KGlobal::staticQString( "name" ); 00705 static const QString &tagText = KGlobal::staticQString( "text" ); 00706 static const QString &tagText2 = KGlobal::staticQString( "Text" ); 00707 00708 // just in case, we clear our combo 00709 m_toolbarCombo->clear(); 00710 00711 int defaultToolbarId = 0; 00712 int count = 0; 00713 // load in all of the toolbar names into this combo box 00714 XmlDataList::Iterator xit = d->m_xmlFiles.begin(); 00715 for ( ; xit != d->m_xmlFiles.end(); ++xit) 00716 { 00717 // skip the local one in favor of the merged 00718 if ( (*xit).m_type == XmlData::Local ) 00719 continue; 00720 00721 // each xml file may have any number of toolbars 00722 ToolbarList::Iterator it = (*xit).m_barList.begin(); 00723 for ( ; it != (*xit).m_barList.end(); ++it) 00724 { 00725 QString name; 00726 QCString txt( (*it).namedItem( tagText ).toElement().text().utf8() ); 00727 if ( txt.isEmpty() ) 00728 txt = (*it).namedItem( tagText2 ).toElement().text().utf8(); 00729 if ( txt.isEmpty() ) 00730 name = (*it).attribute( attrName ); 00731 else 00732 name = i18n( txt ); 00733 00734 // the name of the toolbar might depend on whether or not 00735 // it is in kparts 00736 if ( ( (*xit).m_type == XmlData::Shell ) || 00737 ( (*xit).m_type == XmlData::Part ) ) 00738 { 00739 QString doc_name((*xit).m_document.documentElement().attribute( attrName )); 00740 name += " <" + doc_name + ">"; 00741 } 00742 00743 m_toolbarCombo->setEnabled( true ); 00744 m_toolbarCombo->insertItem( name ); 00745 if (name == defaultToolbar) 00746 defaultToolbarId = count; 00747 count++; 00748 } 00749 } 00750 00751 // we want to the specified item selected and its actions loaded 00752 m_toolbarCombo->setCurrentItem(defaultToolbarId); 00753 slotToolbarSelected(m_toolbarCombo->currentText()); 00754 } 00755 00756 void KEditToolbarWidget::loadActionList(QDomElement& elem) 00757 { 00758 static const QString &tagSeparator = KGlobal::staticQString( "Separator" ); 00759 static const QString &tagMerge = KGlobal::staticQString( "Merge" ); 00760 static const QString &tagActionList= KGlobal::staticQString( "ActionList" ); 00761 static const QString &attrName = KGlobal::staticQString( "name" ); 00762 00763 int sep_num = 0; 00764 QString sep_name("separator_%1"); 00765 00766 // clear our lists 00767 m_inactiveList->clear(); 00768 m_activeList->clear(); 00769 m_insertAction->setEnabled(false); 00770 m_removeAction->setEnabled(false); 00771 m_upAction->setEnabled(false); 00772 m_downAction->setEnabled(false); 00773 00774 // store the names of our active actions 00775 QMap<QString, bool> active_list; 00776 00777 // see if our current action is in this toolbar 00778 QDomElement it = elem.lastChild().toElement(); 00779 for( ; !it.isNull(); it = it.previousSibling().toElement() ) 00780 { 00781 if (it.tagName() == tagSeparator) 00782 { 00783 ToolbarItem *act = new ToolbarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString::null); 00784 act->setText(1, "-----"); 00785 it.setAttribute( attrName, act->internalName() ); 00786 continue; 00787 } 00788 00789 if (it.tagName() == tagMerge) 00790 { 00791 // Merge can be named or not - use the name if there is one 00792 QString name = it.attribute( attrName ); 00793 ToolbarItem *act = new ToolbarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component.")); 00794 if ( name.isEmpty() ) 00795 act->setText(1, i18n("<Merge>")); 00796 else 00797 act->setText(1, i18n("<Merge %1>").arg(name)); 00798 continue; 00799 } 00800 00801 if (it.tagName() == tagActionList) 00802 { 00803 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.") ); 00804 act->setText(1, i18n("ActionList: %1").arg(it.attribute(attrName))); 00805 continue; 00806 } 00807 00808 // iterate through all of our actions 00809 for (unsigned int i = 0; i < d->m_actionList.count(); i++) 00810 { 00811 KAction *action = d->m_actionList[i]; 00812 00813 // do we have a match? 00814 if (it.attribute( attrName ) == action->name()) 00815 { 00816 // we have a match! 00817 ToolbarItem *act = new ToolbarItem(m_activeList, it.tagName(), action->name(), action->toolTip()); 00818 act->setText(1, action->plainText()); 00819 if (action->hasIcon()) 00820 if (!action->icon().isEmpty()) 00821 act->setPixmap(0, BarIcon(action->icon(), 16)); 00822 else // Has iconset 00823 act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap()); 00824 00825 active_list.insert(action->name(), true); 00826 break; 00827 } 00828 } 00829 } 00830 00831 // go through the rest of the collection 00832 for (int i = d->m_actionList.count() - 1; i > -1; --i) 00833 { 00834 KAction *action = d->m_actionList[i]; 00835 00836 // skip our active ones 00837 if (active_list.contains(action->name())) 00838 continue; 00839 00840 ToolbarItem *act = new ToolbarItem(m_inactiveList, tagActionList, action->name(), action->toolTip()); 00841 act->setText(1, action->plainText()); 00842 if (action->hasIcon()) 00843 if (!action->icon().isEmpty()) 00844 act->setPixmap(0, BarIcon(action->icon(), 16)); 00845 else // Has iconset 00846 act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap()); 00847 } 00848 00849 // finally, add a default separator to the inactive list 00850 ToolbarItem *act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null); 00851 act->setText(1, "-----"); 00852 } 00853 00854 KActionCollection *KEditToolbarWidget::actionCollection() const 00855 { 00856 return d->m_collection; 00857 } 00858 00859 void KEditToolbarWidget::slotToolbarSelected(const QString& _text) 00860 { 00861 static const QString &attrName = KGlobal::staticQString( "name" ); 00862 static const QString &tagText = KGlobal::staticQString( "text" ); 00863 static const QString &tagText2 = KGlobal::staticQString( "Text" ); 00864 00865 // iterate through everything 00866 XmlDataList::Iterator xit = d->m_xmlFiles.begin(); 00867 for ( ; xit != d->m_xmlFiles.end(); ++xit) 00868 { 00869 // each xml file may have any number of toolbars 00870 ToolbarList::Iterator it = (*xit).m_barList.begin(); 00871 for ( ; it != (*xit).m_barList.end(); ++it) 00872 { 00873 QString name; 00874 QCString txt( (*it).namedItem( tagText ).toElement().text().utf8() ); 00875 if ( txt.isEmpty() ) 00876 txt = (*it).namedItem( tagText2 ).toElement().text().utf8(); 00877 if ( txt.isEmpty() ) 00878 name = (*it).attribute( attrName ); 00879 else 00880 name = i18n( txt ); 00881 00882 // the name of the toolbar might depend on whether or not 00883 // it is in kparts 00884 if ( ( (*xit).m_type == XmlData::Shell ) || 00885 ( (*xit).m_type == XmlData::Part ) ) 00886 { 00887 QString doc_name((*xit).m_document.documentElement().attribute( attrName )); 00888 name += " <" + doc_name + ">"; 00889 } 00890 00891 // is this our toolbar? 00892 if ( name == _text ) 00893 { 00894 // save our current settings 00895 d->m_currentXmlData = (*xit); 00896 d->m_currentToolbarElem = (*it); 00897 00898 // load in our values 00899 loadActionList(d->m_currentToolbarElem); 00900 00901 if ((*xit).m_type == XmlData::Part || (*xit).m_type == XmlData::Shell) 00902 setDOMDocument( (*xit).m_document ); 00903 return; 00904 } 00905 } 00906 } 00907 } 00908 00909 00910 00911 void KEditToolbarWidget::slotInactiveSelected(QListViewItem *item) 00912 { 00913 if (item) 00914 { 00915 m_insertAction->setEnabled(true); 00916 QString statusText = static_cast<ToolbarItem *>(item)->statusText(); 00917 d->m_helpArea->setText( statusText ); 00918 } 00919 else 00920 { 00921 m_insertAction->setEnabled(false); 00922 d->m_helpArea->setText( QString::null ); 00923 } 00924 } 00925 00926 void KEditToolbarWidget::slotActiveSelected(QListViewItem *item) 00927 { 00928 if (item) 00929 { 00930 m_removeAction->setEnabled(true); 00931 00932 if (item->itemAbove()) 00933 m_upAction->setEnabled(true); 00934 else 00935 m_upAction->setEnabled(false); 00936 00937 if (item->itemBelow()) 00938 m_downAction->setEnabled(true); 00939 else 00940 m_downAction->setEnabled(false); 00941 QString statusText = static_cast<ToolbarItem *>(item)->statusText(); 00942 d->m_helpArea->setText( statusText ); 00943 } 00944 else 00945 { 00946 m_removeAction->setEnabled(false); 00947 m_upAction->setEnabled(false); 00948 m_downAction->setEnabled(false); 00949 d->m_helpArea->setText( QString::null ); 00950 } 00951 } 00952 00953 void KEditToolbarWidget::slotDropped(KListView *list, QDropEvent *e, QListViewItem *after) 00954 { 00955 ToolbarItem *item = new ToolbarItem(m_inactiveList); // needs parent, use inactiveList temporarily 00956 if(!ToolbarItemDrag::decode(e, *item)) { 00957 delete item; 00958 return; 00959 } 00960 00961 if (list == m_activeList) { 00962 if (e->source() == m_activeList) { 00963 // has been dragged within the active list (moved) -> remove the old item. 00964 removeActive(item); 00965 } 00966 00967 insertActive(item, after, true); 00968 } else if (list == m_inactiveList) { 00969 // has been dragged to the inactive list -> remove from the active list. 00970 removeActive(item); 00971 } 00972 00973 delete item; item = 0; // not neded anymore 00974 00975 // we're modified, so let this change 00976 emit enableOk(true); 00977 00978 slotToolbarSelected( m_toolbarCombo->currentText() ); 00979 } 00980 00981 void KEditToolbarWidget::slotInsertButton() 00982 { 00983 ToolbarItem *item = (ToolbarItem*)m_inactiveList->currentItem(); 00984 insertActive(item, m_activeList->currentItem(), false); 00985 00986 // we're modified, so let this change 00987 emit enableOk(true); 00988 00989 slotToolbarSelected( m_toolbarCombo->currentText() ); 00990 } 00991 00992 00993 void KEditToolbarWidget::slotRemoveButton() 00994 { 00995 removeActive( dynamic_cast<ToolbarItem*>(m_activeList->currentItem()) ); 00996 00997 // we're modified, so let this change 00998 emit enableOk(true); 00999 01000 slotToolbarSelected( m_toolbarCombo->currentText() ); 01001 } 01002 01003 void KEditToolbarWidget::insertActive(ToolbarItem *item, QListViewItem *before, bool prepend) 01004 { 01005 if (!item) 01006 return; 01007 01008 static const QString &tagAction = KGlobal::staticQString( "Action" ); 01009 static const QString &tagSeparator = KGlobal::staticQString( "Separator" ); 01010 static const QString &attrName = KGlobal::staticQString( "name" ); 01011 static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); 01012 01013 QDomElement new_item; 01014 new_item = domDocument().createElement(tagAction); 01015 new_item.setAttribute(attrName, item->internalName()); 01016 01017 if (before) 01018 { 01019 // we have the item in the active list which is before the new 01020 // item.. so let's try our best to add our new item right after it 01021 ToolbarItem *act_item = (ToolbarItem*)before; 01022 QDomElement elem = d->findElementForToolbarItem( act_item ); 01023 Q_ASSERT( !elem.isNull() ); 01024 d->m_currentToolbarElem.insertAfter(new_item, elem); 01025 } 01026 else 01027 { 01028 // simply put it at the beginning or the end of the list. 01029 if (prepend) 01030 d->m_currentToolbarElem.insertBefore(new_item, d->m_currentToolbarElem.firstChild()); 01031 else 01032 d->m_currentToolbarElem.appendChild(new_item); 01033 } 01034 01035 // and set this container as a noMerge 01036 d->m_currentToolbarElem.setAttribute( attrNoMerge, "1"); 01037 01038 // update the local doc 01039 updateLocal(d->m_currentToolbarElem); 01040 } 01041 01042 void KEditToolbarWidget::removeActive(ToolbarItem *item) 01043 { 01044 if (!item) 01045 return; 01046 01047 static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); 01048 01049 // we're modified, so let this change 01050 emit enableOk(true); 01051 01052 // now iterate through to find the child to nuke 01053 QDomElement elem = d->findElementForToolbarItem( item ); 01054 if ( !elem.isNull() ) 01055 { 01056 // nuke myself! 01057 d->m_currentToolbarElem.removeChild(elem); 01058 01059 // and set this container as a noMerge 01060 d->m_currentToolbarElem.setAttribute( attrNoMerge, "1"); 01061 01062 // update the local doc 01063 updateLocal(d->m_currentToolbarElem); 01064 } 01065 } 01066 01067 01068 void KEditToolbarWidget::slotUpButton() 01069 { 01070 ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem(); 01071 01072 // make sure we're not the top item already 01073 if (!item->itemAbove()) 01074 return; 01075 01076 static const QString &attrName = KGlobal::staticQString( "name" ); 01077 static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); 01078 01079 // we're modified, so let this change 01080 emit enableOk(true); 01081 01082 // now iterate through to find where we are 01083 QDomElement elem = d->m_currentToolbarElem.firstChild().toElement(); 01084 for( ; !elem.isNull(); elem = elem.nextSibling().toElement()) 01085 { 01086 if ((elem.attribute(attrName) == item->internalName()) && 01087 (elem.tagName() == item->internalTag())) 01088 { 01089 // cool, i found me. now clone myself 01090 ToolbarItem *clone = new ToolbarItem(m_activeList, 01091 item->itemAbove()->itemAbove(), 01092 item->internalTag(), 01093 item->internalName(), 01094 item->statusText()); 01095 clone->setText(1, item->text(1)); 01096 01097 // only set new pixmap if exists 01098 if( item->pixmap(0) ) 01099 clone->setPixmap(0, *item->pixmap(0)); 01100 01101 // remove the old me 01102 m_activeList->takeItem(item); 01103 delete item; 01104 01105 // select my clone 01106 m_activeList->setSelected(clone, true); 01107 01108 // make clone visible 01109 m_activeList->ensureItemVisible(clone); 01110 01111 // and do the real move in the DOM 01112 QDomNode prev = elem.previousSibling(); 01113 while ( prev.toElement().tagName() == QString( "WeakSeparator" ) ) 01114 prev = prev.previousSibling(); 01115 d->m_currentToolbarElem.insertBefore(elem, prev); 01116 01117 // and set this container as a noMerge 01118 d->m_currentToolbarElem.setAttribute( attrNoMerge, "1"); 01119 01120 // update the local doc 01121 updateLocal(d->m_currentToolbarElem); 01122 01123 break; 01124 } 01125 } 01126 } 01127 01128 void KEditToolbarWidget::slotDownButton() 01129 { 01130 ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem(); 01131 01132 // make sure we're not the bottom item already 01133 if (!item->itemBelow()) 01134 return; 01135 01136 static const QString &attrName = KGlobal::staticQString( "name" ); 01137 static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" ); 01138 01139 // we're modified, so let this change 01140 emit enableOk(true); 01141 01142 // now iterate through to find where we are 01143 QDomElement elem = d->m_currentToolbarElem.firstChild().toElement(); 01144 for( ; !elem.isNull(); elem = elem.nextSibling().toElement()) 01145 { 01146 if ((elem.attribute(attrName) == item->internalName()) && 01147 (elem.tagName() == item->internalTag())) 01148 { 01149 // cool, i found me. now clone myself 01150 ToolbarItem *clone = new ToolbarItem(m_activeList, 01151 item->itemBelow(), 01152 item->internalTag(), 01153 item->internalName(), 01154 item->statusText()); 01155 clone->setText(1, item->text(1)); 01156 01157 // only set new pixmap if exists 01158 if( item->pixmap(0) ) 01159 clone->setPixmap(0, *item->pixmap(0)); 01160 01161 // remove the old me 01162 m_activeList->takeItem(item); 01163 delete item; 01164 01165 // select my clone 01166 m_activeList->setSelected(clone, true); 01167 01168 // make clone visible 01169 m_activeList->ensureItemVisible(clone); 01170 01171 // and do the real move in the DOM 01172 QDomNode next = elem.nextSibling(); 01173 while ( next.toElement().tagName() == QString( "WeakSeparator" ) ) 01174 next = next.nextSibling(); 01175 d->m_currentToolbarElem.insertAfter(elem, next); 01176 01177 // and set this container as a noMerge 01178 d->m_currentToolbarElem.setAttribute( attrNoMerge, "1"); 01179 01180 // update the local doc 01181 updateLocal(d->m_currentToolbarElem); 01182 01183 break; 01184 } 01185 } 01186 } 01187 01188 void KEditToolbarWidget::updateLocal(QDomElement& elem) 01189 { 01190 static const QString &attrName = KGlobal::staticQString( "name" ); 01191 01192 XmlDataList::Iterator xit = d->m_xmlFiles.begin(); 01193 for ( ; xit != d->m_xmlFiles.end(); ++xit) 01194 { 01195 if ( (*xit).m_type == XmlData::Merged ) 01196 continue; 01197 01198 if ( (*xit).m_type == XmlData::Shell || 01199 (*xit).m_type == XmlData::Part ) 01200 { 01201 if ( d->m_currentXmlData.m_xmlFile == (*xit).m_xmlFile ) 01202 { 01203 (*xit).m_isModified = true; 01204 return; 01205 } 01206 01207 continue; 01208 } 01209 01210 (*xit).m_isModified = true; 01211 01212 ToolbarList::Iterator it = (*xit).m_barList.begin(); 01213 for ( ; it != (*xit).m_barList.end(); ++it) 01214 { 01215 QString name( (*it).attribute( attrName ) ); 01216 QString tag( (*it).tagName() ); 01217 if ( (tag != elem.tagName()) || (name != elem.attribute(attrName)) ) 01218 continue; 01219 01220 QDomElement toolbar = (*xit).m_document.documentElement().toElement(); 01221 toolbar.replaceChild(elem, (*it)); 01222 return; 01223 } 01224 01225 // just append it 01226 QDomElement toolbar = (*xit).m_document.documentElement().toElement(); 01227 toolbar.appendChild(elem); 01228 } 01229 } 01230 01231 void KEditToolbar::virtual_hook( int id, void* data ) 01232 { KDialogBase::virtual_hook( id, data ); } 01233 01234 void KEditToolbarWidget::virtual_hook( int id, void* data ) 01235 { KXMLGUIClient::virtual_hook( id, data ); } 01236 01237 #include "kedittoolbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:14:25 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003