KDEUI
kxmlguibuilder.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> 00003 David Faure <faure@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 as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kxmlguibuilder.h" 00022 00023 #include "kapplication.h" 00024 #include "kauthorized.h" 00025 #include "kxmlguiclient.h" 00026 #include "kmenubar.h" 00027 #include "kmenu.h" 00028 #include "ktoolbar.h" 00029 #include "kstatusbar.h" 00030 #include "kmainwindow.h" 00031 #include "kxmlguiwindow.h" 00032 #include "kaction.h" 00033 #include "kglobalsettings.h" 00034 #include <klocale.h> 00035 #include <kiconloader.h> 00036 #include <kdebug.h> 00037 #include <QtXml/QDomElement> 00038 #include <QtCore/QObject> 00039 #include <QtCore/QMutableStringListIterator> 00040 #include "kmenumenuhandler_p.h" 00041 #include <kcomponentdata.h> 00042 00043 using namespace KDEPrivate; 00044 00045 class KXMLGUIBuilderPrivate 00046 { 00047 public: 00048 KXMLGUIBuilderPrivate() : m_client(0L) {} 00049 ~KXMLGUIBuilderPrivate() { } 00050 00051 QWidget *m_widget; 00052 00053 QString tagMainWindow; 00054 QString tagMenuBar; 00055 QString tagMenu; 00056 QString tagToolBar; 00057 QString tagStatusBar; 00058 00059 QString tagSeparator; 00060 QString tagTearOffHandle; 00061 QString tagMenuTitle; 00062 00063 QString attrName; 00064 QString attrLineSeparator; 00065 00066 QString attrText1; 00067 QString attrText2; 00068 QString attrContext; 00069 00070 QString attrIcon; 00071 00072 KComponentData m_componentData; 00073 KXMLGUIClient *m_client; 00074 00075 KMenuMenuHandler *m_menumenuhandler; 00076 }; 00077 00078 00079 KXMLGUIBuilder::KXMLGUIBuilder( QWidget *widget ) 00080 : d( new KXMLGUIBuilderPrivate ) 00081 { 00082 d->m_widget = widget; 00083 00084 d->tagMainWindow = QLatin1String( "mainwindow" ); 00085 d->tagMenuBar = QLatin1String( "menubar" ); 00086 d->tagMenu = QLatin1String( "menu" ); 00087 d->tagToolBar = QLatin1String( "toolbar" ); 00088 d->tagStatusBar = QLatin1String( "statusbar" ); 00089 00090 d->tagSeparator = QLatin1String( "separator" ); 00091 d->tagTearOffHandle = QLatin1String( "tearoffhandle" ); 00092 d->tagMenuTitle = QLatin1String( "title" ); 00093 00094 d->attrName = QLatin1String( "name" ); 00095 d->attrLineSeparator = QLatin1String( "lineseparator" ); 00096 00097 d->attrText1 = QLatin1String( "text" ); 00098 d->attrText2 = QLatin1String( "Text" ); 00099 d->attrContext = QLatin1String( "context" ); 00100 00101 d->attrIcon = QLatin1String( "icon" ); 00102 00103 d->m_menumenuhandler=new KMenuMenuHandler(this); 00104 } 00105 00106 KXMLGUIBuilder::~KXMLGUIBuilder() 00107 { 00108 delete d->m_menumenuhandler; 00109 delete d; 00110 } 00111 00112 QWidget *KXMLGUIBuilder::widget() 00113 { 00114 return d->m_widget; 00115 } 00116 00117 QStringList KXMLGUIBuilder::containerTags() const 00118 { 00119 QStringList res; 00120 res << d->tagMenu << d->tagToolBar << d->tagMainWindow << d->tagMenuBar << d->tagStatusBar; 00121 00122 return res; 00123 } 00124 00125 QWidget *KXMLGUIBuilder::createContainer( QWidget *parent, int index, const QDomElement &element, QAction*& containerAction ) 00126 { 00127 containerAction = 0; 00128 00129 if (element.attribute("deleted").toLower() == "true") { 00130 return 0; 00131 } 00132 00133 const QString tagName = element.tagName().toLower(); 00134 if ( tagName == d->tagMainWindow ) { 00135 KMainWindow *mainwindow = qobject_cast<KMainWindow*>( d->m_widget ); // could be 0 00136 return mainwindow; 00137 } 00138 00139 if ( tagName == d->tagMenuBar ) { 00140 KMainWindow *mainWin = qobject_cast<KMainWindow*>( d->m_widget ); 00141 KMenuBar *bar = 0; 00142 if (mainWin) 00143 bar = mainWin->menuBar(); 00144 if (!bar) 00145 bar = new KMenuBar( d->m_widget ); 00146 bar->show(); 00147 return bar; 00148 } 00149 00150 if ( tagName == d->tagMenu ) { 00151 // Look up to see if we are inside a mainwindow. If yes, then 00152 // use it as parent widget (to get kaction to plug itself into the 00153 // mainwindow). Don't use a popupmenu as parent widget, otherwise 00154 // the popup won't be hidden if it is used as a standalone menu as well. 00155 // And we don't want to set the parent for a standalone popupmenu, 00156 // otherwise its shortcuts appear. 00157 // 00158 // Note: menus with a parent of 0, coming from child clients, can be 00159 // leaked if the child client is deleted without a proper removeClient call, though. 00160 QWidget* p = parent; 00161 while ( p && !qobject_cast<QMainWindow*>( p ) ) 00162 p = p->parentWidget(); 00163 00164 QByteArray name = element.attribute( d->attrName ).toUtf8(); 00165 00166 if (!KAuthorized::authorizeKAction(name)) 00167 return 0; 00168 00169 KMenu *popup = new KMenu(p); 00170 popup->setObjectName(name); 00171 00172 d->m_menumenuhandler->insertKMenu(popup); 00173 00174 QString i18nText; 00175 QDomElement textElem = element.namedItem( d->attrText1 ).toElement(); 00176 if ( textElem.isNull() ) // try with capital T 00177 textElem = element.namedItem( d->attrText2 ).toElement(); 00178 const QByteArray text = textElem.text().toUtf8(); 00179 const QByteArray context = textElem.attribute(d->attrContext).toUtf8(); 00180 00181 if ( text.isEmpty() ) // still no luck 00182 i18nText = i18n( "No text" ); 00183 else if ( context.isEmpty() ) 00184 i18nText = i18n( text ); 00185 else 00186 i18nText = i18nc( context, text ); 00187 00188 const QString icon = element.attribute( d->attrIcon ); 00189 KIcon pix; 00190 if (!icon.isEmpty()) { 00191 pix = KIcon( icon ); 00192 } 00193 00194 if ( parent ) { 00195 QAction* act = popup->menuAction(); 00196 if ( !icon.isEmpty() ) 00197 act->setIcon(pix); 00198 act->setText(i18nText); 00199 if (index == -1 || index >= parent->actions().count()) 00200 parent->addAction(act); 00201 else 00202 parent->insertAction(parent->actions().value(index), act); 00203 containerAction = act; 00204 containerAction->setObjectName( name ); 00205 } 00206 00207 return popup; 00208 } 00209 00210 if ( tagName == d->tagToolBar ) { 00211 QByteArray name = element.attribute( d->attrName ).toUtf8(); 00212 00213 KToolBar *bar = static_cast<KToolBar*>(d->m_widget->findChild<KToolBar*>( name )); 00214 if( !bar ) 00215 { 00216 bar = new KToolBar(name, d->m_widget, false); 00217 } 00218 00219 if ( qobject_cast<KMainWindow*>( d->m_widget ) ) 00220 { 00221 if ( d->m_client && !d->m_client->xmlFile().isEmpty() ) 00222 bar->setXMLGUIClient( d->m_client ); 00223 } 00224 00225 bar->loadState( element ); 00226 00227 return bar; 00228 } 00229 00230 if ( tagName == d->tagStatusBar ) { 00231 KMainWindow *mainWin = qobject_cast<KMainWindow *>(d->m_widget); 00232 if ( mainWin ) { 00233 mainWin->statusBar()->show(); 00234 return mainWin->statusBar(); 00235 } 00236 KStatusBar *bar = new KStatusBar( d->m_widget ); 00237 return bar; 00238 } 00239 00240 return 0L; 00241 } 00242 00243 void KXMLGUIBuilder::removeContainer( QWidget *container, QWidget *parent, QDomElement &element, QAction* containerAction ) 00244 { 00245 // Warning parent can be 0L 00246 00247 if ( qobject_cast<QMenu*>( container ) ) 00248 { 00249 if ( parent ) { 00250 parent->removeAction( containerAction ); 00251 } 00252 00253 delete container; 00254 } 00255 else if ( qobject_cast<KToolBar*>( container ) ) 00256 { 00257 KToolBar *tb = static_cast<KToolBar *>( container ); 00258 00259 tb->saveState( element ); 00260 delete tb; 00261 } 00262 else if ( qobject_cast<KMenuBar*>( container ) ) 00263 { 00264 KMenuBar *mb = static_cast<KMenuBar *>( container ); 00265 mb->hide(); 00266 // Don't delete menubar - it can be reused by createContainer. 00267 // If you decide that you do need to delete the menubar, make 00268 // sure that QMainWindow::d->mb does not point to a deleted 00269 // menubar object. 00270 } 00271 else if ( qobject_cast<KStatusBar*>( container ) ) 00272 { 00273 if ( qobject_cast<KMainWindow*>( d->m_widget ) ) 00274 container->hide(); 00275 else 00276 delete static_cast<KStatusBar *>(container); 00277 } 00278 else 00279 kWarning() << "Unhandled container to remove : " << container->metaObject()->className(); 00280 } 00281 00282 QStringList KXMLGUIBuilder::customTags() const 00283 { 00284 QStringList res; 00285 res << d->tagSeparator << d->tagTearOffHandle << d->tagMenuTitle; 00286 return res; 00287 } 00288 00289 QAction* KXMLGUIBuilder::createCustomElement( QWidget *parent, int index, const QDomElement &element ) 00290 { 00291 QAction* before = 0L; 00292 if (index > 0 && index < parent->actions().count()) 00293 before = parent->actions().at(index); 00294 00295 const QString tagName = element.tagName().toLower(); 00296 if (tagName == d->tagSeparator) 00297 { 00298 if ( QMenu *menu = qobject_cast<QMenu*>( parent ) ) 00299 { 00300 // QMenu already cares for leading/trailing/repeated separators 00301 // no need to check anything 00302 return menu->insertSeparator( before ); 00303 } 00304 else if ( QMenuBar* bar = qobject_cast<QMenuBar*>( parent ) ) 00305 { 00306 QAction* separatorAction = new QAction(bar); 00307 separatorAction->setSeparator(true); 00308 bar->insertAction( before, separatorAction ); 00309 return separatorAction; 00310 } 00311 else if ( KToolBar *bar = qobject_cast<KToolBar*>( parent ) ) 00312 { 00313 /* FIXME KAction port - any need to provide a replacement for lineSeparator/normal separator? 00314 bool isLineSep = true; 00315 00316 QDomNamedNodeMap attributes = element.attributes(); 00317 unsigned int i = 0; 00318 for (; i < attributes.length(); i++ ) 00319 { 00320 QDomAttr attr = attributes.item( i ).toAttr(); 00321 00322 if ( attr.name().toLower() == d->attrLineSeparator && 00323 attr.value().toLower() == QLatin1String("false") ) 00324 { 00325 isLineSep = false; 00326 break; 00327 } 00328 } 00329 00330 if ( isLineSep ) 00331 return bar->insertSeparator( index ? bar->actions()[index - 1] : 0L ); 00332 else*/ 00333 00334 return bar->insertSeparator( before ); 00335 } 00336 } 00337 else if (tagName == d->tagTearOffHandle) 00338 { 00339 static_cast<QMenu *>(parent)->setTearOffEnabled(true); 00340 } 00341 else if (tagName == d->tagMenuTitle) 00342 { 00343 if ( KMenu* m = qobject_cast<KMenu*>( parent ) ) 00344 { 00345 QString i18nText; 00346 QByteArray text = element.text().toUtf8(); 00347 00348 if ( text.isEmpty() ) 00349 i18nText = i18n( "No text" ); 00350 else 00351 i18nText = i18n( text ); 00352 00353 QString icon = element.attribute( d->attrIcon ); 00354 KIcon pix; 00355 00356 if ( !icon.isEmpty() ) 00357 { 00358 pix = KIcon( icon ); 00359 } 00360 00361 if ( !icon.isEmpty() ) { 00362 return m->addTitle( pix, i18nText, before ); 00363 } else { 00364 return m->addTitle( i18nText, before ); 00365 } 00366 } 00367 } 00368 00369 QAction* blank = new QAction(parent); 00370 blank->setVisible(false); 00371 parent->insertAction(before, blank); 00372 return blank; 00373 } 00374 00375 void KXMLGUIBuilder::removeCustomElement( QWidget *parent, QAction* action ) 00376 { 00377 parent->removeAction(action); 00378 } 00379 00380 KXMLGUIClient *KXMLGUIBuilder::builderClient() const 00381 { 00382 return d->m_client; 00383 } 00384 00385 void KXMLGUIBuilder::setBuilderClient( KXMLGUIClient *client ) 00386 { 00387 d->m_client = client; 00388 if ( client ) 00389 setBuilderComponentData( client->componentData() ); 00390 } 00391 00392 KComponentData KXMLGUIBuilder::builderComponentData() const 00393 { 00394 return d->m_componentData; 00395 } 00396 00397 void KXMLGUIBuilder::setBuilderComponentData(const KComponentData &componentData) 00398 { 00399 d->m_componentData = componentData; 00400 } 00401 00402 void KXMLGUIBuilder::finalizeGUI( KXMLGUIClient * ) 00403 { 00404 KXmlGuiWindow* window = qobject_cast<KXmlGuiWindow*>(d->m_widget); 00405 if (!window) 00406 return; 00407 #if 0 00408 KToolBar *toolbar = 0; 00409 QListIterator<KToolBar> it( ( (KMainWindow*)d->m_widget )->toolBarIterator() ); 00410 while ( ( toolbar = it.current() ) ) { 00411 kDebug(260) << "KXMLGUIBuilder::finalizeGUI toolbar=" << (void*)toolbar; 00412 ++it; 00413 toolbar->positionYourself(); 00414 } 00415 #else 00416 window->finalizeGUI( false ); 00417 #endif 00418 } 00419 00420 void KXMLGUIBuilder::virtual_hook( int, void* ) 00421 { /*BASE::virtual_hook( id, data );*/ } 00422
KDE 4.6 API Reference