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