summaryrefslogtreecommitdiffstats
path: root/kdevdesigner/designer/menubareditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdevdesigner/designer/menubareditor.cpp')
-rw-r--r--kdevdesigner/designer/menubareditor.cpp1129
1 files changed, 1129 insertions, 0 deletions
diff --git a/kdevdesigner/designer/menubareditor.cpp b/kdevdesigner/designer/menubareditor.cpp
new file mode 100644
index 00000000..33cf923e
--- /dev/null
+++ b/kdevdesigner/designer/menubareditor.cpp
@@ -0,0 +1,1129 @@
+/**********************************************************************
+** Copyright (C) 2003 Trolltech AS. All rights reserved.
+**
+** This file is part of Qt Designer.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email [email protected] for
+** information about Qt Commercial License Agreements.
+**
+** Contact [email protected] if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qaction.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qdragobject.h>
+#include <qlineedit.h>
+#include <qmainwindow.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include "command.h"
+#include "formwindow.h"
+#include "menubareditor.h"
+#include "popupmenueditor.h"
+
+#include <klocale.h>
+
+extern void find_accel( const QString &txt, QMap<QChar, QWidgetList > &accels, QWidget *w );
+
+// Drag Object Declaration -------------------------------------------
+
+class MenuBarEditorItemPtrDrag : public QStoredDrag
+{
+public:
+ MenuBarEditorItemPtrDrag( MenuBarEditorItem * item,
+ QWidget * parent = 0,
+ const char * name = 0 );
+ ~MenuBarEditorItemPtrDrag() {};
+ static bool canDecode( QDragMoveEvent * e );
+ static bool decode( QDropEvent * e, MenuBarEditorItem ** i );
+};
+
+// Drag Object Implementation ---------------------------------------
+
+MenuBarEditorItemPtrDrag::MenuBarEditorItemPtrDrag( MenuBarEditorItem * item,
+ QWidget * parent,
+ const char * name )
+ : QStoredDrag( "qt/menubareditoritemptr", parent, name )
+{
+ QByteArray data( sizeof( Q_LONG ) );
+ QDataStream stream( data, IO_WriteOnly );
+ stream << ( Q_LONG ) item;
+ setEncodedData( data );
+}
+
+bool MenuBarEditorItemPtrDrag::canDecode( QDragMoveEvent * e )
+{
+ return e->provides( "qt/menubareditoritemptr" );
+}
+
+bool MenuBarEditorItemPtrDrag::decode( QDropEvent * e, MenuBarEditorItem ** i )
+{
+ QByteArray data = e->encodedData( "qt/menubareditoritemptr" );
+ QDataStream stream( data, IO_ReadOnly );
+
+ if ( !data.size() )
+ return FALSE;
+
+ Q_LONG p = 0;
+ stream >> p;
+ *i = ( MenuBarEditorItem *) p;
+
+ return TRUE;
+}
+
+// MenuBarEditorItem ---------------------------------------------------
+
+MenuBarEditorItem::MenuBarEditorItem( MenuBarEditor * bar, QObject * parent, const char * name )
+ : QObject( parent, name ),
+ menuBar( bar ),
+ popupMenu( 0 ),
+ visible( TRUE ),
+ separator( FALSE ),
+ removable( FALSE )
+{ }
+
+MenuBarEditorItem::MenuBarEditorItem( PopupMenuEditor * menu, MenuBarEditor * bar,
+ QObject * parent, const char * name )
+ : QObject( parent, name ),
+ menuBar( bar ),
+ popupMenu( menu ),
+ visible( TRUE ),
+ separator( FALSE ),
+ removable( TRUE )
+{
+ text = menu->name();
+}
+
+MenuBarEditorItem::MenuBarEditorItem( QActionGroup * actionGroup, MenuBarEditor * bar,
+ QObject * parent, const char * name )
+ : QObject( parent, name ),
+ menuBar( bar ),
+ popupMenu( 0 ),
+ visible( TRUE ),
+ separator( FALSE ),
+ removable( TRUE )
+{
+ text = actionGroup->menuText();
+ popupMenu = new PopupMenuEditor( menuBar->formWindow(), menuBar );
+ popupMenu->insert( actionGroup );
+}
+
+MenuBarEditorItem::MenuBarEditorItem( MenuBarEditorItem * item, QObject * parent, const char * name )
+ : QObject( parent, name ),
+ menuBar( item->menuBar ),
+ popupMenu( 0 ),
+ text( item->text ),
+ visible( item->visible ),
+ separator( item->separator ),
+ removable( item->removable )
+{
+ popupMenu = new PopupMenuEditor( menuBar->formWindow(), item->popupMenu, menuBar );
+}
+
+// MenuBarEditor --------------------------------------------------------
+
+int MenuBarEditor::clipboardOperation = 0;
+MenuBarEditorItem * MenuBarEditor::clipboardItem = 0;
+
+MenuBarEditor::MenuBarEditor( FormWindow * fw, QWidget * parent, const char * name )
+ : QMenuBar( parent, name ),
+ formWnd( fw ),
+ draggedItem( 0 ),
+ currentIndex( 0 ),
+ itemHeight( 0 ),
+ separatorWidth( 32 ),
+ hideWhenEmpty( TRUE ),
+ hasSeparator( FALSE )
+{
+ setAcceptDrops( TRUE );
+ setFocusPolicy( StrongFocus );
+
+ addItem.setMenuText( i18n("new menu") );
+ addSeparator.setMenuText( i18n("new separator") );
+
+ lineEdit = new QLineEdit( this, "menubar lineedit" );
+ lineEdit->hide();
+ lineEdit->setFrameStyle(QFrame::Plain | QFrame::NoFrame);
+ lineEdit->polish();
+ lineEdit->setBackgroundMode(PaletteButton);
+ lineEdit->setBackgroundOrigin(ParentOrigin);
+ lineEdit->installEventFilter( this );
+
+ dropLine = new QWidget( this, "menubar dropline", Qt::WStyle_NoBorder | WStyle_StaysOnTop );
+ dropLine->setBackgroundColor( Qt::red );
+ dropLine->hide();
+
+ setMinimumHeight( fontMetrics().height() + 2 * borderSize() );
+}
+
+MenuBarEditor::~MenuBarEditor()
+{
+ itemList.setAutoDelete( TRUE );
+}
+
+FormWindow * MenuBarEditor::formWindow()
+{
+ return formWnd;
+}
+
+MenuBarEditorItem * MenuBarEditor::createItem( int index, bool addToCmdStack )
+{
+ MenuBarEditorItem * i =
+ new MenuBarEditorItem( new PopupMenuEditor( formWnd, ( QWidget * ) parent() ), this );
+ if ( addToCmdStack ) {
+ AddMenuCommand * cmd = new AddMenuCommand( i18n( "Add Menu" ), formWnd, this, i, index );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ } else {
+ AddMenuCommand cmd( i18n( "Add Menu" ), formWnd, this, i, index );
+ cmd.execute();
+ }
+ return i;
+}
+
+void MenuBarEditor::insertItem( MenuBarEditorItem * item, int index )
+{
+ item->menu()->parentMenu = this;
+
+ if ( index != -1 )
+ itemList.insert( index, item );
+ else
+ itemList.append( item );
+
+ if ( hideWhenEmpty && itemList.count() == 1 )
+ show(); // calls resizeInternals();
+ else
+ resizeInternals();
+
+ if ( isVisible() )
+ update();
+}
+
+void MenuBarEditor::insertItem( QString text, PopupMenuEditor * menu, int index )
+{
+ MenuBarEditorItem * item = new MenuBarEditorItem( menu, this );
+ if ( !text.isNull() )
+ item->setMenuText( text );
+ insertItem( item, index );
+}
+
+void MenuBarEditor::insertItem( QString text, QActionGroup * group, int index )
+{
+ MenuBarEditorItem * item = new MenuBarEditorItem( group, this );
+ if ( !text.isNull() )
+ item->setMenuText( text );
+ insertItem( item, index );
+}
+
+
+void MenuBarEditor::insertSeparator( int index )
+{
+ if ( hasSeparator )
+ return;
+
+ MenuBarEditorItem * i = createItem( index );
+ i->setSeparator( TRUE );
+ i->setMenuText( i18n( "separator" ) );
+ hasSeparator = TRUE;
+}
+
+void MenuBarEditor::removeItemAt( int index )
+{
+ removeItem( item( index ) );
+}
+
+void MenuBarEditor::removeItem( MenuBarEditorItem * item )
+{
+ if ( item &&
+ item->isRemovable() &&
+ itemList.removeRef( item ) ) {
+
+ if ( item->isSeparator() )
+ hasSeparator = FALSE;
+
+ if ( hideWhenEmpty && itemList.count() == 0 )
+ hide();
+ else
+ resizeInternals();
+
+ int n = count() + 1;
+ if ( currentIndex >= n )
+ currentIndex = n;
+
+ if ( isVisible() )
+ update();
+ }
+}
+
+int MenuBarEditor::findItem( MenuBarEditorItem * item )
+{
+ return itemList.findRef( item );
+}
+
+int MenuBarEditor::findItem( PopupMenuEditor * menu )
+{
+ MenuBarEditorItem * i = itemList.first();
+
+ while ( i ) {
+ if ( i->menu() == menu )
+ return itemList.at();
+ i = itemList.next();
+ }
+
+ return -1;
+}
+
+int MenuBarEditor::findItem( QPoint & pos )
+{
+ int x = borderSize();
+ int dx = 0;
+ int y = 0;
+ int w = width();
+ QSize s;
+ QRect r;
+
+ MenuBarEditorItem * i = itemList.first();
+
+ while ( i ) {
+
+ if ( i->isVisible() ) {
+
+ s = itemSize( i );
+ dx = s.width();
+
+ if ( x + dx > w && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+
+ r = QRect( x, y, s.width(), s.height() );
+
+ if ( r.contains( pos ) )
+ return itemList.at();
+
+ addItemSizeToCoords( i, x, y, w );
+ }
+
+ i = itemList.next();
+ }
+
+ // check add item
+ s = itemSize( &addItem );
+ dx = s.width();
+
+ if ( x + dx > w && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+
+ r = QRect( x, y, s.width(), s.height() );
+
+ if ( r.contains( pos ) )
+ return itemList.count();
+
+ return itemList.count() + 1;
+}
+
+MenuBarEditorItem * MenuBarEditor::item( int index )
+{
+ if ( index == -1 )
+ return itemList.at( currentIndex );
+
+ int c = itemList.count();
+ if ( index == c )
+ return &addItem;
+ else if ( index > c )
+ return &addSeparator;
+
+ return itemList.at( index );
+}
+
+int MenuBarEditor::count()
+{
+ return itemList.count();
+}
+
+int MenuBarEditor::current()
+{
+ return currentIndex;
+}
+
+void MenuBarEditor::cut( int index )
+{
+ if ( clipboardItem && clipboardOperation == Cut )
+ delete clipboardItem;
+
+ clipboardOperation = Cut;
+ clipboardItem = itemList.at( index );
+
+ if ( clipboardItem == &addItem || clipboardItem == &addSeparator ) {
+ clipboardOperation = None;
+ clipboardItem = 0;
+ return; // do nothing
+ }
+
+ RemoveMenuCommand * cmd = new RemoveMenuCommand( i18n( "Cut Menu" ), formWnd, this, index );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+}
+
+void MenuBarEditor::copy( int index )
+{
+ if ( clipboardItem && clipboardOperation == Cut )
+ delete clipboardItem;
+
+ clipboardOperation = Copy;
+ clipboardItem = itemList.at( index );
+
+ if ( clipboardItem == &addItem || clipboardItem == &addSeparator ) {
+ clipboardOperation = None;
+ clipboardItem = 0;
+ }
+}
+
+void MenuBarEditor::paste( int index )
+{
+ if ( clipboardItem && clipboardOperation ) {
+ MenuBarEditorItem * i = new MenuBarEditorItem( clipboardItem );
+ AddMenuCommand * cmd = new AddMenuCommand( i18n( "Paste Menu" ), formWnd, this, i, index );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ }
+}
+
+void MenuBarEditor::exchange( int a, int b )
+{
+ MenuBarEditorItem * ia = itemList.at( a );
+ MenuBarEditorItem * ib = itemList.at( b );
+ if ( !ia || !ib ||
+ ia == &addItem || ia == &addSeparator ||
+ ib == &addItem || ib == &addSeparator )
+ return; // do nothing
+ itemList.replace( b, ia );
+ itemList.replace( a, ib );
+}
+
+void MenuBarEditor::showLineEdit( int index )
+{
+ if ( index == -1 )
+ index = currentIndex;
+
+ MenuBarEditorItem * i = 0;
+
+ if ( (uint) index >= itemList.count() )
+ i = &addItem;
+ else
+ i = itemList.at( index );
+
+ if ( i && i->isSeparator() )
+ return;
+
+ // open edit field for item name
+ lineEdit->setText( i->menuText() );
+ lineEdit->selectAll();
+ QPoint pos = itemPos( index );
+ lineEdit->move( pos.x() + borderSize(), pos.y() - ( borderSize() / 2 ) );
+ lineEdit->resize( itemSize( i ) );
+ lineEdit->show();
+ lineEdit->setFocus();
+}
+
+void MenuBarEditor::showItem( int index )
+{
+ if ( index == -1 )
+ index = currentIndex;
+
+ if ( (uint)index < itemList.count() ) {
+ MenuBarEditorItem * i = itemList.at( index );
+ if ( i->isSeparator() || draggedItem )
+ return;
+ PopupMenuEditor * m = i->menu();
+ QPoint pos = itemPos( index );
+ m->move( pos.x(), pos.y() + itemHeight - 1 );
+ m->raise();
+ m->show();
+ setFocus();
+ }
+}
+
+void MenuBarEditor::hideItem( int index )
+{
+ if ( index == -1 )
+ index = currentIndex;
+
+ if ( (uint)index < itemList.count() ) {
+ PopupMenuEditor * m = itemList.at( index )->menu();
+ m->hideSubMenu();
+ m->hide();
+ }
+}
+
+void MenuBarEditor::focusItem( int index )
+{
+ if ( index == -1 )
+ index = currentIndex;
+
+ if ( (uint)index < itemList.count() ) {
+ PopupMenuEditor * m = itemList.at( index )->menu();
+ m->setFocus();
+ m->update();
+ update();
+ }
+}
+
+void MenuBarEditor::deleteItem( int index )
+{
+ if ( index == -1 )
+ index = currentIndex;
+
+ if ( (uint)index < itemList.count() ) {
+ RemoveMenuCommand * cmd = new RemoveMenuCommand( i18n( "Delete Menu" ),
+ formWnd,
+ this,
+ currentIndex );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ }
+}
+
+QSize MenuBarEditor::sizeHint() const
+{
+ return QSize( parentWidget()->width(), heightForWidth( parentWidget()->width() ) );
+}
+
+int MenuBarEditor::heightForWidth( int max_width ) const
+{
+ MenuBarEditor * that = ( MenuBarEditor * ) this;
+ int x = borderSize();
+ int y = 0;
+
+ QPainter p( this );
+ that->itemHeight = that->itemSize( &(that->addItem) ).height();
+
+ MenuBarEditorItem * i = that->itemList.first();
+ while ( i ) {
+ if ( i->isVisible() )
+ that->addItemSizeToCoords( i, x, y, max_width );
+ i = that->itemList.next();
+ }
+
+ that->addItemSizeToCoords( &(that->addItem), x, y, max_width );
+ that->addItemSizeToCoords( &(that->addSeparator), x, y, max_width );
+
+ return y + itemHeight;
+}
+
+void MenuBarEditor::show()
+{
+ QWidget::show();
+ resizeInternals();
+
+ QResizeEvent e( parentWidget()->size(), parentWidget()->size() );
+ QApplication::sendEvent( parentWidget(), &e );
+}
+
+void MenuBarEditor::checkAccels( QMap<QChar, QWidgetList > &accels )
+{
+ QString t;
+ MenuBarEditorItem * i = itemList.first();
+ while ( i ) {
+ t = i->menuText();
+ find_accel( t, accels, this );
+ // do not check the accelerators in the popup menus
+ i = itemList.next();
+ }
+}
+
+// public slots
+
+void MenuBarEditor::cut()
+{
+ cut( currentIndex );
+}
+
+void MenuBarEditor::copy()
+{
+ copy( currentIndex );
+}
+
+void MenuBarEditor::paste()
+{
+ paste( currentIndex );
+}
+
+// protected
+
+bool MenuBarEditor::eventFilter( QObject * o, QEvent * e )
+{
+ if ( o == lineEdit && e->type() == QEvent::FocusOut ) {
+ leaveEditMode();
+ lineEdit->hide();
+ update();
+ } else if ( e->type() == QEvent::LayoutHint ) {
+ resize( sizeHint() );
+ }
+ return QMenuBar::eventFilter( o, e );
+}
+
+void MenuBarEditor::paintEvent( QPaintEvent * )
+{
+ QPainter p( this );
+ QRect r = rect();
+ style().drawPrimitive( QStyle::PE_PanelMenuBar, &p,
+ r, colorGroup() );
+ drawItems( p );
+}
+
+void MenuBarEditor::mousePressEvent( QMouseEvent * e )
+{
+ mousePressPos = e->pos();
+ hideItem();
+ lineEdit->hide();
+ currentIndex = findItem( mousePressPos );
+ showItem();
+ update();
+ e->accept();
+}
+
+void MenuBarEditor::mouseDoubleClickEvent( QMouseEvent * e )
+{
+ mousePressPos = e->pos();
+ currentIndex = findItem( mousePressPos );
+ lineEdit->hide();
+ if ( currentIndex > (int)itemList.count() ) {
+ insertSeparator();
+ update();
+ } else {
+ showLineEdit();
+ }
+}
+
+void MenuBarEditor::mouseMoveEvent( QMouseEvent * e )
+{
+ if ( e->state() & Qt::LeftButton ) {
+ if ( ( e->pos() - mousePressPos ).manhattanLength() > 3 ) {
+ bool itemCreated = FALSE;
+ bool isSeparator = FALSE;
+ draggedItem = item( findItem( mousePressPos ) );
+ if ( draggedItem == &addItem ) {
+ draggedItem = createItem();
+ itemCreated = TRUE;
+ } else if ( draggedItem == &addSeparator ) {
+ if (hasSeparator) // we can only have one separator
+ return;
+ draggedItem = createItem();
+ draggedItem->setSeparator( TRUE );
+ draggedItem->setMenuText( "separator" );
+ isSeparator = TRUE;
+ itemCreated = TRUE;
+ } else {
+ isSeparator = draggedItem->isSeparator();
+ }
+
+ MenuBarEditorItemPtrDrag * d =
+ new MenuBarEditorItemPtrDrag( draggedItem, this );
+ d->setPixmap( createTextPixmap( draggedItem->menuText() ) );
+ hideItem();
+ draggedItem->setVisible( FALSE );
+ update();
+
+ // If the item is dropped in the same list,
+ // we will have two instances of the same pointer
+ // in the list.
+ itemList.find( draggedItem );
+ QLNode * node = itemList.currentNode();
+ dropConfirmed = FALSE;
+ d->dragCopy(); // dragevents and stuff happens
+ if ( draggedItem ) { // item was not dropped
+ if ( itemCreated ) {
+ removeItem( draggedItem );
+ } else {
+ hideItem();
+ draggedItem->setVisible( TRUE );
+ draggedItem = 0;
+ showItem();
+ }
+ } else if ( dropConfirmed ) { // item was dropped
+ dropConfirmed = FALSE;
+ hideItem();
+ itemList.takeNode( node )->setVisible( TRUE );
+ hasSeparator = isSeparator || hasSeparator;
+ showItem();
+ } else {
+ hasSeparator = isSeparator || hasSeparator;
+ }
+ update();
+ }
+ }
+}
+
+void MenuBarEditor::dragEnterEvent( QDragEnterEvent * e )
+{
+ if ( MenuBarEditorItemPtrDrag::canDecode( e ) ) {
+ e->accept();
+ dropLine->show();
+ }
+}
+
+void MenuBarEditor::dragLeaveEvent( QDragLeaveEvent * )
+{
+ dropLine->hide();
+}
+
+void MenuBarEditor::dragMoveEvent( QDragMoveEvent * e )
+{
+
+ QPoint pos = e->pos();
+ dropLine->move( snapToItem( pos ) );
+
+ int idx = findItem( pos );
+ if ( currentIndex != idx ) {
+ hideItem();
+ currentIndex = idx;
+ showItem();
+ }
+}
+
+void MenuBarEditor::dropEvent( QDropEvent * e )
+{
+ MenuBarEditorItem * i = 0;
+
+ if ( MenuBarEditorItemPtrDrag::decode( e, &i ) ) {
+ draggedItem = 0;
+ hideItem();
+ dropInPlace( i, e->pos() );
+ e->accept();
+ }
+
+ dropLine->hide();
+}
+
+void MenuBarEditor::keyPressEvent( QKeyEvent * e )
+{
+ if ( lineEdit->isHidden() ) { // In navigation mode
+ switch ( e->key() ) {
+
+ case Qt::Key_Delete:
+ hideItem();
+ deleteItem();
+ showItem();
+ break;
+
+ case Qt::Key_Left:
+ e->accept();
+ navigateLeft( e->state() & Qt::ControlButton );
+ return;
+
+ case Qt::Key_Right:
+ e->accept();
+ navigateRight( e->state() & Qt::ControlButton );
+ return; // no update
+
+ case Qt::Key_Down:
+ e->accept();
+ focusItem();
+ return; // no update
+
+ case Qt::Key_PageUp:
+ currentIndex = 0;
+ break;
+
+ case Qt::Key_PageDown:
+ currentIndex = itemList.count();
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F2:
+ e->accept();
+ enterEditMode();
+ return; // no update
+
+ case Qt::Key_Up:
+ case Qt::Key_Alt:
+ case Qt::Key_Shift:
+ case Qt::Key_Control:
+ case Qt::Key_Escape:
+ e->ignore();
+ setFocus(); // FIXME: this is because some other widget get the focus when CTRL is pressed
+ return; // no update
+
+ case Qt::Key_C:
+ if ( e->state() & Qt::ControlButton && currentIndex < (int)itemList.count() ) {
+ copy( currentIndex );
+ break;
+ }
+
+ case Qt::Key_X:
+ if ( e->state() & Qt::ControlButton && currentIndex < (int)itemList.count() ) {
+ hideItem();
+ cut( currentIndex );
+ showItem();
+ break;
+ }
+
+ case Qt::Key_V:
+ if ( e->state() & Qt::ControlButton ) {
+ hideItem();
+ paste( currentIndex < (int)itemList.count() ? currentIndex + 1: itemList.count() );
+ showItem();
+ break;
+ }
+
+ default:
+ if ( e->ascii() >= 32 || e->ascii() == 0 ) {
+ showLineEdit();
+ QApplication::sendEvent( lineEdit, e );
+ e->accept();
+ } else {
+ e->ignore();
+ }
+ return;
+ }
+ } else { // In edit mode
+
+ switch ( e->key() ) {
+ case Qt::Key_Control:
+ e->ignore();
+ return;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ leaveEditMode();
+ case Qt::Key_Escape:
+ lineEdit->hide();
+ setFocus();
+ break;
+ }
+ }
+ e->accept();
+ update();
+}
+
+void MenuBarEditor::focusOutEvent( QFocusEvent * e )
+{
+ QWidget * fw = qApp->focusWidget();
+ if ( e->lostFocus() && !::qt_cast<PopupMenuEditor*>(fw) )
+ hideItem();
+ update();
+}
+
+void MenuBarEditor::resizeInternals()
+{
+ dropLine->resize( 2, itemHeight );
+ updateGeometry();
+}
+
+void MenuBarEditor::drawItems( QPainter & p )
+{
+ QPoint pos( borderSize(), 0 );
+ uint c = 0;
+
+ p.setPen( colorGroup().buttonText() );
+
+ MenuBarEditorItem * i = itemList.first();
+ while ( i ) {
+ if ( i->isVisible() )
+ drawItem( p, i, c++, pos ); // updates x y
+ i = itemList.next();
+ }
+
+ p.setPen( darkBlue );
+ drawItem( p, &addItem, c++, pos );
+ if ( !hasSeparator )
+ drawItem( p, &addSeparator, c, pos );
+}
+
+void MenuBarEditor::drawItem( QPainter & p,
+ MenuBarEditorItem * i,
+ int idx,
+ QPoint & pos )
+{
+ int w = itemSize( i ).width();
+
+ // If the item passes the right border, and it is not the first item on the line
+ if ( pos.x() + w > width() && pos.x() > borderSize() ) { // wrap
+ pos.ry() += itemHeight;
+ pos.setX( borderSize() );
+ }
+
+ if ( i->isSeparator() ) {
+ drawSeparator( p, pos );
+ } else {
+ int flags = QPainter::AlignLeft | QPainter::AlignVCenter |
+ Qt::ShowPrefix | Qt::SingleLine;
+ p.drawText( pos.x() + borderSize(), pos.y(), w - borderSize(), itemHeight,
+ flags, i->menuText() );
+ }
+
+ if ( hasFocus() && idx == currentIndex && !draggedItem )
+ p.drawWinFocusRect( pos.x(), pos.y() + 1, w, itemHeight - 2 );
+
+ pos.rx() += w;
+}
+
+void MenuBarEditor::drawSeparator( QPainter & p, QPoint & pos )
+{
+ p.save();
+ p.setPen( darkBlue );
+
+ int left = pos.x();
+ int top = pos.y() + 2;
+ int right = left + separatorWidth - 1;
+ int bottom = pos.y() + itemHeight - 4;
+
+ p.drawLine( left, top, left, bottom );
+ p.drawLine( right, top, right, bottom );
+
+ p.fillRect( left, pos.y() + borderSize() * 2,
+ separatorWidth - 1, itemHeight - borderSize() * 4,
+ QBrush( darkBlue, Qt::Dense5Pattern ) );
+
+ p.restore();
+}
+
+QSize MenuBarEditor::itemSize( MenuBarEditorItem * i )
+{
+ if ( i->isSeparator() )
+ return QSize( separatorWidth, itemHeight );
+ QRect r = fontMetrics().boundingRect( i->menuText().remove( "&") );
+ return QSize( r.width() + borderSize() * 2, r.height() + borderSize() * 4 );
+}
+
+void MenuBarEditor::addItemSizeToCoords( MenuBarEditorItem * i, int & x, int & y, int w )
+{
+ int dx = itemSize( i ).width();
+ if ( x + dx > w && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+ x += dx;
+}
+
+QPoint MenuBarEditor::itemPos( int index )
+{
+ int x = borderSize();
+ int y = 0;
+ int w = width();
+ int dx = 0;
+ int c = 0;
+
+ MenuBarEditorItem * i = itemList.first();
+
+ while ( i ) {
+ if ( i->isVisible() ) {
+ dx = itemSize( i ).width();
+ if ( x + dx > w && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+ if ( c == index )
+ return QPoint( x, y );
+ x += dx;
+ c++;
+ }
+ i = itemList.next();
+ }
+ dx = itemSize( &addItem ).width();
+ if ( x + dx > width() && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+
+ return QPoint( x, y );
+}
+
+QPoint MenuBarEditor::snapToItem( const QPoint & pos )
+{
+ int x = borderSize();
+ int y = 0;
+ int dx = 0;
+
+ MenuBarEditorItem * n = itemList.first();
+
+ while ( n ) {
+ if ( n->isVisible() ) {
+ dx = itemSize( n ).width();
+ if ( x + dx > width() && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+ if ( pos.y() > y &&
+ pos.y() < y + itemHeight &&
+ pos.x() < x + dx / 2 ) {
+ return QPoint( x, y );
+ }
+ x += dx;
+ }
+ n = itemList.next();
+ }
+
+ return QPoint( x, y );
+}
+
+void MenuBarEditor::dropInPlace( MenuBarEditorItem * i, const QPoint & pos )
+{
+ int x = borderSize();
+ int y = 0;
+ int dx = 0;
+ int idx = 0;
+
+ MenuBarEditorItem * n = itemList.first();
+
+ while ( n ) {
+ if ( n->isVisible() ) {
+ dx = itemSize( n ).width();
+ if ( x + dx > width() && x > borderSize() ) {
+ y += itemHeight;
+ x = borderSize();
+ }
+ if ( pos.y() > y &&
+ pos.y() < y + itemHeight &&
+ pos.x() < x + dx / 2 )
+ break;
+ x += dx;
+ }
+ n = itemList.next();
+ idx++;
+ }
+
+ hideItem();
+ Command * cmd = 0;
+ int iidx = itemList.findRef( i );
+ if ( iidx != -1 ) { // internal dnd
+ cmd = new MoveMenuCommand( i18n( "Item Dragged" ), formWnd, this, iidx, idx );
+ item( iidx )->setVisible( TRUE );
+ } else {
+ cmd = new AddMenuCommand( i18n( "Add Menu" ), formWnd, this, i, idx );
+ dropConfirmed = TRUE; // let mouseMoveEvent set the item visible
+ }
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ currentIndex = ( iidx >= 0 && iidx < idx ) ? idx - 1 : idx;
+ showItem();
+}
+
+
+void MenuBarEditor::safeDec()
+{
+ do {
+ currentIndex--;
+ } while ( currentIndex > 0 && !( item( currentIndex )->isVisible() ) );
+}
+
+void MenuBarEditor::safeInc()
+{
+ int max = (int)itemList.count();
+ if ( !hasSeparator )
+ max += 1;
+ if ( currentIndex < max ) {
+ do {
+ currentIndex++;
+ // skip invisible items
+ } while ( currentIndex < max && !( item( currentIndex )->isVisible() ) );
+ }
+}
+
+void MenuBarEditor::navigateLeft( bool ctrl )
+{
+ // FIXME: handle invisible items
+ if ( currentIndex > 0 ) {
+ hideItem();
+ if ( ctrl ) {
+ ExchangeMenuCommand * cmd = new ExchangeMenuCommand( i18n( "Move Menu Left" ),
+ formWnd,
+ this,
+ currentIndex,
+ currentIndex - 1 );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ safeDec();
+ } else {
+ safeDec();
+ }
+ showItem();
+ }
+ update();
+}
+
+void MenuBarEditor::navigateRight( bool ctrl )
+{
+// FIXME: handle invisible items
+ hideItem();
+ if ( ctrl ) {
+ if ( currentIndex < ( (int)itemList.count() - 1 ) ) {
+ ExchangeMenuCommand * cmd = new ExchangeMenuCommand( i18n( "Move Menu Right" ),
+ formWnd,
+ this,
+ currentIndex,
+ currentIndex + 1 );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ safeInc();
+ }
+ } else {
+ safeInc();
+ }
+ showItem();
+ update();
+}
+
+void MenuBarEditor::enterEditMode()
+{
+ if ( currentIndex > (int)itemList.count() ) {
+ insertSeparator();
+ } else {
+ showLineEdit();
+ }
+}
+
+void MenuBarEditor::leaveEditMode()
+{
+ MenuBarEditorItem * i = 0;
+ if ( currentIndex >= (int)itemList.count() ) {
+ i = createItem();
+ // do not put rename on cmd stack
+ RenameMenuCommand rename( i18n( "Rename Menu" ), formWnd, this, lineEdit->text(), i );
+ rename.execute();
+ } else {
+ i = itemList.at( currentIndex );
+ RenameMenuCommand * cmd =
+ new RenameMenuCommand( i18n( "Rename Menu" ), formWnd, this, lineEdit->text(), i );
+ formWnd->commandHistory()->addCommand( cmd );
+ cmd->execute();
+ }
+ showItem();
+}
+
+QPixmap MenuBarEditor::createTextPixmap( const QString &text )
+{
+ QSize sz( fontMetrics().boundingRect( text ).size() );
+ QPixmap pix( sz.width() + 20, sz.height() * 2 );
+ pix.fill( white );
+ QPainter p( &pix, this );
+ p.drawText( 2, 0, pix.width(), pix.height(), 0, text );
+ p.end();
+ QBitmap bm( pix.size() );
+ bm.fill( color0 );
+ p.begin( &bm );
+ p.setPen( color1 );
+ p.drawText( 2, 0, pix.width(), pix.height(), 0, text );
+ p.end();
+ pix.setMask( bm );
+ return pix;
+}