Skip to content
Permalink
Browse files

[FEATURE] New edit menu for composer

Change cut/copy/paste functions to actions and add to edit menu
Move undo/redo/delete to edit menu
Rearrange layout menu to logical order
  • Loading branch information
nyalldawson authored and mhugent committed Sep 12, 2013
1 parent 033440f commit 0f2932b9cc35d8577fe83d1cee16de939bf307a5
@@ -203,6 +203,38 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
composerMenu->addAction( mActionQuit );
QObject::connect( mActionQuit, SIGNAL( triggered() ), this, SLOT( close() ) );

//cut/copy/paste actions. Note these are not included in the ui file
//as ui files have no support for QKeySequence shortcuts
mActionCut = new QAction( tr( "Cu&t" ), this );
mActionCut->setShortcuts( QKeySequence::Cut );
mActionCut->setStatusTip( tr( "Cut" ) );
QObject::connect( mActionCut, SIGNAL( triggered() ), this, SLOT( actionCutTriggered() ) );
mActionCopy = new QAction( tr( "&Copy" ), this );
mActionCopy->setShortcuts( QKeySequence::Copy );
mActionCopy->setStatusTip( tr( "Copy" ) );
QObject::connect( mActionCopy, SIGNAL( triggered() ), this, SLOT( actionCopyTriggered() ) );
mActionPaste = new QAction( tr( "&Paste" ), this );
mActionPaste->setShortcuts( QKeySequence::Paste );
mActionPaste->setStatusTip( tr( "Paste" ) );
QObject::connect( mActionPaste, SIGNAL( triggered() ), this, SLOT( actionPasteTriggered() ) );

QMenu *editMenu = menuBar()->addMenu( tr( "Edit" ) );
editMenu->addAction( mActionUndo );
editMenu->addAction( mActionRedo );
editMenu->addSeparator();

//Backspace should also trigger delete selection
QShortcut* backSpace = new QShortcut( QKeySequence( "Backspace" ), this );
connect( backSpace, SIGNAL( activated() ), mActionDeleteSelection, SLOT( trigger() ) );
editMenu->addAction( mActionDeleteSelection );
editMenu->addSeparator();

editMenu->addAction( mActionCut );
editMenu->addAction( mActionCopy );
editMenu->addAction( mActionPaste );
//TODO : "Ctrl+Shift+V" is one way to paste in place, but on some platforms you can use Shift+Ins and F18
editMenu->addAction( mActionPasteInPlace );

QMenu *viewMenu = menuBar()->addMenu( tr( "View" ) );
viewMenu->addAction( mActionZoomIn );
viewMenu->addAction( mActionZoomOut );
@@ -225,22 +257,20 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
mToolbarMenu->addAction( mItemToolbar->toggleViewAction() );

QMenu *layoutMenu = menuBar()->addMenu( tr( "Layout" ) );
layoutMenu->addAction( mActionUndo );
layoutMenu->addAction( mActionRedo );
layoutMenu->addSeparator();
layoutMenu->addAction( mActionAddNewMap );
layoutMenu->addAction( mActionAddNewLabel );
layoutMenu->addAction( mActionAddNewScalebar );
layoutMenu->addAction( mActionAddNewLegend );
layoutMenu->addAction( mActionAddImage );
layoutMenu->addAction( mActionSelectMoveItem );
layoutMenu->addAction( mActionMoveItemContent );

layoutMenu->addAction( mActionAddArrow );
layoutMenu->addAction( mActionAddTable );
layoutMenu->addSeparator();
layoutMenu->addAction( mActionSelectMoveItem );
layoutMenu->addAction( mActionMoveItemContent );
layoutMenu->addSeparator();
layoutMenu->addAction( mActionGroupItems );
layoutMenu->addAction( mActionUngroupItems );
layoutMenu->addSeparator();
layoutMenu->addAction( mActionRaiseItems );
layoutMenu->addAction( mActionLowerItems );
layoutMenu->addAction( mActionMoveItemsToTop );
@@ -1669,6 +1699,58 @@ void QgsComposer::on_mActionUnlockAll_triggered()
}
}

void QgsComposer::actionCutTriggered()
{
if ( mView )
{
mView->copyItems( QgsComposerView::ClipboardModeCut );
}
}

void QgsComposer::actionCopyTriggered()
{
if ( mView )
{
mView->copyItems( QgsComposerView::ClipboardModeCopy );
}
}

void QgsComposer::actionPasteTriggered()
{
if ( mView )
{
QPointF pt = mView->mapToScene( mView->mapFromGlobal( QCursor::pos() ) );
//TODO - use a better way of determining whether paste was triggered by keystroke
//or menu item
if (( pt.x() < 0 ) || ( pt.y() < 0 ) )
{
//action likely triggered by menu, paste items in center of screen
mView->pasteItems( QgsComposerView::PasteModeCenter );
}
else
{
//action likely triggered by keystroke, paste items at cursor position
mView->pasteItems( QgsComposerView::PasteModeCursor );
}
}
}

void QgsComposer::on_mActionPasteInPlace_triggered()
{
if ( mView )
{
mView->pasteItems( QgsComposerView::PasteModeInPlace );
}
}

void QgsComposer::on_mActionDeleteSelection_triggered()
{
if ( mView )
{
mView->deleteSelectedItems();
}
}

void QgsComposer::on_mActionRaiseItems_triggered()
{
if ( mComposition )
@@ -207,6 +207,21 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! Group selected items
void on_mActionGroupItems_triggered();

//! Cut item(s)
void actionCutTriggered();

//! Copy item(s)
void actionCopyTriggered();

//! Paste item(s)
void actionPasteTriggered();

//! Paste in place item(s)
void on_mActionPasteInPlace_triggered();

//! Delete selected item(s)
void on_mActionDeleteSelection_triggered();

//! Ungroup selected item group
void on_mActionUngroupItems_triggered();

@@ -373,6 +388,11 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! Window menu action to select this window
QAction *mWindowAction;

//! Copy/cut/paste actions
QAction *mActionCut;
QAction *mActionCopy;
QAction *mActionPaste;

//! Page & Printer Setup
QPrinter mPrinter;

@@ -487,10 +487,8 @@ void QgsComposerView::mouseDoubleClickEvent( QMouseEvent* e )
e->ignore();
}

void QgsComposerView::keyPressEvent( QKeyEvent * e )
void QgsComposerView::copyItems( ClipboardMode mode )
{
//TODO : those should be actions (so we could also display menu items and/or toolbar items)

if ( !composition() )
{
return;
@@ -499,93 +497,123 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();

// increment used for cursor key item movement
double increment = 1.0;
if ( e->modifiers() & Qt::ShiftModifier )
QDomDocument doc;
QDomElement documentElement = doc.createElement( "ComposerItemClipboard" );
for ( ; itemIt != composerItemList.end(); ++itemIt )
{
//holding shift while pressing cursor keys results in a big step
increment = 10.0;
}

if ( e->matches( QKeySequence::Copy ) || e->matches( QKeySequence::Cut ) )
{
QDomDocument doc;
QDomElement documentElement = doc.createElement( "ComposerItemClipboard" );
for ( ; itemIt != composerItemList.end(); ++itemIt )
// copy each item in a group
QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
if ( itemGroup && composition() )
{
// copy each item in a group
QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
if ( itemGroup && composition() )
{
QSet<QgsComposerItem*> groupedItems = itemGroup->items();
QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
for ( ; it != groupedItems.end(); ++it )
{
( *it )->writeXML( documentElement, doc );
}
}
( *itemIt )->writeXML( documentElement, doc );
if ( e->matches( QKeySequence::Cut ) )
QSet<QgsComposerItem*> groupedItems = itemGroup->items();
QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
for ( ; it != groupedItems.end(); ++it )
{
composition()->removeComposerItem( *itemIt );
( *it )->writeXML( documentElement, doc );
}
}
doc.appendChild( documentElement );
( *itemIt )->writeXML( documentElement, doc );
if ( mode == ClipboardModeCut )
{
composition()->removeComposerItem( *itemIt );
}
}
doc.appendChild( documentElement );

//if it's a copy, we have to remove the UUIDs since we don't want any duplicate UUID
if ( e->matches( QKeySequence::Copy ) )
//if it's a copy, we have to remove the UUIDs since we don't want any duplicate UUID
if ( mode == ClipboardModeCopy )
{
// remove all uuid attributes
QDomNodeList composerItemsNodes = doc.elementsByTagName( "ComposerItem" );
for ( int i = 0; i < composerItemsNodes.count(); ++i )
{
// remove all uuid attributes
QDomNodeList composerItemsNodes = doc.elementsByTagName( "ComposerItem" );
for ( int i = 0; i < composerItemsNodes.count(); ++i )
QDomNode composerItemNode = composerItemsNodes.at( i );
if ( composerItemNode.isElement() )
{
QDomNode composerItemNode = composerItemsNodes.at( i );
if ( composerItemNode.isElement() )
{
composerItemNode.toElement().removeAttribute( "uuid" );
}
composerItemNode.toElement().removeAttribute( "uuid" );
}
}
}

QMimeData *mimeData = new QMimeData;
mimeData->setData( "text/xml", doc.toByteArray() );
QClipboard *clipboard = QApplication::clipboard();
clipboard->setMimeData( mimeData );
}

QMimeData *mimeData = new QMimeData;
mimeData->setData( "text/xml", doc.toByteArray() );
QClipboard *clipboard = QApplication::clipboard();
clipboard->setMimeData( mimeData );
void QgsComposerView::pasteItems( PasteMode mode )
{
if ( !composition() )
{
return;
}

//TODO : "Ctrl+Shift+V" is one way to paste, but on some platefoms you can use Shift+Ins and F18
if ( e->matches( QKeySequence::Paste ) || ( e->key() == Qt::Key_V && e->modifiers() & Qt::ControlModifier && e->modifiers() & Qt::ShiftModifier ) )
QDomDocument doc;
QClipboard *clipboard = QApplication::clipboard();
if ( doc.setContent( clipboard->mimeData()->data( "text/xml" ) ) )
{
QDomDocument doc;
QClipboard *clipboard = QApplication::clipboard();
if ( doc.setContent( clipboard->mimeData()->data( "text/xml" ) ) )
QDomElement docElem = doc.documentElement();
if ( docElem.tagName() == "ComposerItemClipboard" )
{
QDomElement docElem = doc.documentElement();
if ( docElem.tagName() == "ComposerItemClipboard" )
if ( composition() )
{
if ( composition() )
QPointF pt;
if ( mode == PasteModeCursor )
{
QPointF pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
bool pasteInPlace = ( e->modifiers() & Qt::ShiftModifier );
composition()->addItemsFromXML( docElem, doc, 0, true, &pt, pasteInPlace );
// place items at cursor position
pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
}
else
{
// place items in center of viewport
pt = mapToScene( viewport()->rect().center() );
}
bool pasteInPlace = ( mode == PasteModeInPlace );
composition()->addItemsFromXML( docElem, doc, 0, true, &pt, pasteInPlace );
}
}
}
}

void QgsComposerView::deleteSelectedItems()
{
if ( !composition() )
{
return;
}

QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();

//delete selected items
if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace )
for ( ; itemIt != composerItemList.end(); ++itemIt )
{
for ( ; itemIt != composerItemList.end(); ++itemIt )
if ( composition() )
{
if ( composition() )
{
composition()->removeComposerItem( *itemIt );
}
composition()->removeComposerItem( *itemIt );
}
}
}

void QgsComposerView::keyPressEvent( QKeyEvent * e )
{
if ( !composition() )
{
return;
}

QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();

// increment used for cursor key item movement
double increment = 1.0;
if ( e->modifiers() & Qt::ShiftModifier )
{
//holding shift while pressing cursor keys results in a big step
increment = 10.0;
}

else if ( e->key() == Qt::Key_Left )
if ( e->key() == Qt::Key_Left )
{
for ( ; itemIt != composerItemList.end(); ++itemIt )
{
@@ -68,6 +68,19 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
MoveItemContent //move content of item (e.g. content of map)
};

enum ClipboardMode
{
ClipboardModeCut,
ClipboardModeCopy
};

enum PasteMode
{
PasteModeCursor,
PasteModeCenter,
PasteModeInPlace
};

QgsComposerView( QWidget* parent = 0, const char* name = 0, Qt::WFlags f = 0 );

/**Add an item group containing the selected items*/
@@ -82,6 +95,15 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
/**Unlock all items*/
void unlockAllItems();

/**Cuts or copies the selected items*/
void copyItems( ClipboardMode mode );

/**Pastes items from clipboard*/
void pasteItems( PasteMode mode );

/**Deletes selected items*/
void deleteSelectedItems();

QgsComposerView::Tool currentTool() const {return mCurrentTool;}
void setCurrentTool( QgsComposerView::Tool t ) {mCurrentTool = t;}

0 comments on commit 0f2932b

Please sign in to comment.
You can’t perform that action at this time.