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