diff options
Diffstat (limited to 'kdevdesigner/designer/menubareditor.cpp')
-rw-r--r-- | kdevdesigner/designer/menubareditor.cpp | 1129 |
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; +} |