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