Skip to content

Commit 0f2932b

Browse files
nyalldawsonmhugent
authored andcommittedSep 12, 2013
[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
1 parent 033440f commit 0f2932b

File tree

5 files changed

+242
-68
lines changed

5 files changed

+242
-68
lines changed
 

‎src/app/composer/qgscomposer.cpp

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,38 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
203203
composerMenu->addAction( mActionQuit );
204204
QObject::connect( mActionQuit, SIGNAL( triggered() ), this, SLOT( close() ) );
205205

206+
//cut/copy/paste actions. Note these are not included in the ui file
207+
//as ui files have no support for QKeySequence shortcuts
208+
mActionCut = new QAction( tr( "Cu&t" ), this );
209+
mActionCut->setShortcuts( QKeySequence::Cut );
210+
mActionCut->setStatusTip( tr( "Cut" ) );
211+
QObject::connect( mActionCut, SIGNAL( triggered() ), this, SLOT( actionCutTriggered() ) );
212+
mActionCopy = new QAction( tr( "&Copy" ), this );
213+
mActionCopy->setShortcuts( QKeySequence::Copy );
214+
mActionCopy->setStatusTip( tr( "Copy" ) );
215+
QObject::connect( mActionCopy, SIGNAL( triggered() ), this, SLOT( actionCopyTriggered() ) );
216+
mActionPaste = new QAction( tr( "&Paste" ), this );
217+
mActionPaste->setShortcuts( QKeySequence::Paste );
218+
mActionPaste->setStatusTip( tr( "Paste" ) );
219+
QObject::connect( mActionPaste, SIGNAL( triggered() ), this, SLOT( actionPasteTriggered() ) );
220+
221+
QMenu *editMenu = menuBar()->addMenu( tr( "Edit" ) );
222+
editMenu->addAction( mActionUndo );
223+
editMenu->addAction( mActionRedo );
224+
editMenu->addSeparator();
225+
226+
//Backspace should also trigger delete selection
227+
QShortcut* backSpace = new QShortcut( QKeySequence( "Backspace" ), this );
228+
connect( backSpace, SIGNAL( activated() ), mActionDeleteSelection, SLOT( trigger() ) );
229+
editMenu->addAction( mActionDeleteSelection );
230+
editMenu->addSeparator();
231+
232+
editMenu->addAction( mActionCut );
233+
editMenu->addAction( mActionCopy );
234+
editMenu->addAction( mActionPaste );
235+
//TODO : "Ctrl+Shift+V" is one way to paste in place, but on some platforms you can use Shift+Ins and F18
236+
editMenu->addAction( mActionPasteInPlace );
237+
206238
QMenu *viewMenu = menuBar()->addMenu( tr( "View" ) );
207239
viewMenu->addAction( mActionZoomIn );
208240
viewMenu->addAction( mActionZoomOut );
@@ -225,22 +257,20 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
225257
mToolbarMenu->addAction( mItemToolbar->toggleViewAction() );
226258

227259
QMenu *layoutMenu = menuBar()->addMenu( tr( "Layout" ) );
228-
layoutMenu->addAction( mActionUndo );
229-
layoutMenu->addAction( mActionRedo );
230-
layoutMenu->addSeparator();
231260
layoutMenu->addAction( mActionAddNewMap );
232261
layoutMenu->addAction( mActionAddNewLabel );
233262
layoutMenu->addAction( mActionAddNewScalebar );
234263
layoutMenu->addAction( mActionAddNewLegend );
235264
layoutMenu->addAction( mActionAddImage );
236-
layoutMenu->addAction( mActionSelectMoveItem );
237-
layoutMenu->addAction( mActionMoveItemContent );
238-
239265
layoutMenu->addAction( mActionAddArrow );
240266
layoutMenu->addAction( mActionAddTable );
241267
layoutMenu->addSeparator();
268+
layoutMenu->addAction( mActionSelectMoveItem );
269+
layoutMenu->addAction( mActionMoveItemContent );
270+
layoutMenu->addSeparator();
242271
layoutMenu->addAction( mActionGroupItems );
243272
layoutMenu->addAction( mActionUngroupItems );
273+
layoutMenu->addSeparator();
244274
layoutMenu->addAction( mActionRaiseItems );
245275
layoutMenu->addAction( mActionLowerItems );
246276
layoutMenu->addAction( mActionMoveItemsToTop );
@@ -1669,6 +1699,58 @@ void QgsComposer::on_mActionUnlockAll_triggered()
16691699
}
16701700
}
16711701

1702+
void QgsComposer::actionCutTriggered()
1703+
{
1704+
if ( mView )
1705+
{
1706+
mView->copyItems( QgsComposerView::ClipboardModeCut );
1707+
}
1708+
}
1709+
1710+
void QgsComposer::actionCopyTriggered()
1711+
{
1712+
if ( mView )
1713+
{
1714+
mView->copyItems( QgsComposerView::ClipboardModeCopy );
1715+
}
1716+
}
1717+
1718+
void QgsComposer::actionPasteTriggered()
1719+
{
1720+
if ( mView )
1721+
{
1722+
QPointF pt = mView->mapToScene( mView->mapFromGlobal( QCursor::pos() ) );
1723+
//TODO - use a better way of determining whether paste was triggered by keystroke
1724+
//or menu item
1725+
if (( pt.x() < 0 ) || ( pt.y() < 0 ) )
1726+
{
1727+
//action likely triggered by menu, paste items in center of screen
1728+
mView->pasteItems( QgsComposerView::PasteModeCenter );
1729+
}
1730+
else
1731+
{
1732+
//action likely triggered by keystroke, paste items at cursor position
1733+
mView->pasteItems( QgsComposerView::PasteModeCursor );
1734+
}
1735+
}
1736+
}
1737+
1738+
void QgsComposer::on_mActionPasteInPlace_triggered()
1739+
{
1740+
if ( mView )
1741+
{
1742+
mView->pasteItems( QgsComposerView::PasteModeInPlace );
1743+
}
1744+
}
1745+
1746+
void QgsComposer::on_mActionDeleteSelection_triggered()
1747+
{
1748+
if ( mView )
1749+
{
1750+
mView->deleteSelectedItems();
1751+
}
1752+
}
1753+
16721754
void QgsComposer::on_mActionRaiseItems_triggered()
16731755
{
16741756
if ( mComposition )

‎src/app/composer/qgscomposer.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,21 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
207207
//! Group selected items
208208
void on_mActionGroupItems_triggered();
209209

210+
//! Cut item(s)
211+
void actionCutTriggered();
212+
213+
//! Copy item(s)
214+
void actionCopyTriggered();
215+
216+
//! Paste item(s)
217+
void actionPasteTriggered();
218+
219+
//! Paste in place item(s)
220+
void on_mActionPasteInPlace_triggered();
221+
222+
//! Delete selected item(s)
223+
void on_mActionDeleteSelection_triggered();
224+
210225
//! Ungroup selected item group
211226
void on_mActionUngroupItems_triggered();
212227

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

391+
//! Copy/cut/paste actions
392+
QAction *mActionCut;
393+
QAction *mActionCopy;
394+
QAction *mActionPaste;
395+
376396
//! Page & Printer Setup
377397
QPrinter mPrinter;
378398

‎src/gui/qgscomposerview.cpp

Lines changed: 90 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,8 @@ void QgsComposerView::mouseDoubleClickEvent( QMouseEvent* e )
487487
e->ignore();
488488
}
489489

490-
void QgsComposerView::keyPressEvent( QKeyEvent * e )
490+
void QgsComposerView::copyItems( ClipboardMode mode )
491491
{
492-
//TODO : those should be actions (so we could also display menu items and/or toolbar items)
493-
494492
if ( !composition() )
495493
{
496494
return;
@@ -499,93 +497,123 @@ void QgsComposerView::keyPressEvent( QKeyEvent * e )
499497
QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
500498
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();
501499

502-
// increment used for cursor key item movement
503-
double increment = 1.0;
504-
if ( e->modifiers() & Qt::ShiftModifier )
500+
QDomDocument doc;
501+
QDomElement documentElement = doc.createElement( "ComposerItemClipboard" );
502+
for ( ; itemIt != composerItemList.end(); ++itemIt )
505503
{
506-
//holding shift while pressing cursor keys results in a big step
507-
increment = 10.0;
508-
}
509-
510-
if ( e->matches( QKeySequence::Copy ) || e->matches( QKeySequence::Cut ) )
511-
{
512-
QDomDocument doc;
513-
QDomElement documentElement = doc.createElement( "ComposerItemClipboard" );
514-
for ( ; itemIt != composerItemList.end(); ++itemIt )
504+
// copy each item in a group
505+
QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
506+
if ( itemGroup && composition() )
515507
{
516-
// copy each item in a group
517-
QgsComposerItemGroup* itemGroup = dynamic_cast<QgsComposerItemGroup*>( *itemIt );
518-
if ( itemGroup && composition() )
519-
{
520-
QSet<QgsComposerItem*> groupedItems = itemGroup->items();
521-
QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
522-
for ( ; it != groupedItems.end(); ++it )
523-
{
524-
( *it )->writeXML( documentElement, doc );
525-
}
526-
}
527-
( *itemIt )->writeXML( documentElement, doc );
528-
if ( e->matches( QKeySequence::Cut ) )
508+
QSet<QgsComposerItem*> groupedItems = itemGroup->items();
509+
QSet<QgsComposerItem*>::iterator it = groupedItems.begin();
510+
for ( ; it != groupedItems.end(); ++it )
529511
{
530-
composition()->removeComposerItem( *itemIt );
512+
( *it )->writeXML( documentElement, doc );
531513
}
532514
}
533-
doc.appendChild( documentElement );
515+
( *itemIt )->writeXML( documentElement, doc );
516+
if ( mode == ClipboardModeCut )
517+
{
518+
composition()->removeComposerItem( *itemIt );
519+
}
520+
}
521+
doc.appendChild( documentElement );
534522

535-
//if it's a copy, we have to remove the UUIDs since we don't want any duplicate UUID
536-
if ( e->matches( QKeySequence::Copy ) )
523+
//if it's a copy, we have to remove the UUIDs since we don't want any duplicate UUID
524+
if ( mode == ClipboardModeCopy )
525+
{
526+
// remove all uuid attributes
527+
QDomNodeList composerItemsNodes = doc.elementsByTagName( "ComposerItem" );
528+
for ( int i = 0; i < composerItemsNodes.count(); ++i )
537529
{
538-
// remove all uuid attributes
539-
QDomNodeList composerItemsNodes = doc.elementsByTagName( "ComposerItem" );
540-
for ( int i = 0; i < composerItemsNodes.count(); ++i )
530+
QDomNode composerItemNode = composerItemsNodes.at( i );
531+
if ( composerItemNode.isElement() )
541532
{
542-
QDomNode composerItemNode = composerItemsNodes.at( i );
543-
if ( composerItemNode.isElement() )
544-
{
545-
composerItemNode.toElement().removeAttribute( "uuid" );
546-
}
533+
composerItemNode.toElement().removeAttribute( "uuid" );
547534
}
548535
}
536+
}
537+
538+
QMimeData *mimeData = new QMimeData;
539+
mimeData->setData( "text/xml", doc.toByteArray() );
540+
QClipboard *clipboard = QApplication::clipboard();
541+
clipboard->setMimeData( mimeData );
542+
}
549543

550-
QMimeData *mimeData = new QMimeData;
551-
mimeData->setData( "text/xml", doc.toByteArray() );
552-
QClipboard *clipboard = QApplication::clipboard();
553-
clipboard->setMimeData( mimeData );
544+
void QgsComposerView::pasteItems( PasteMode mode )
545+
{
546+
if ( !composition() )
547+
{
548+
return;
554549
}
555550

556-
//TODO : "Ctrl+Shift+V" is one way to paste, but on some platefoms you can use Shift+Ins and F18
557-
if ( e->matches( QKeySequence::Paste ) || ( e->key() == Qt::Key_V && e->modifiers() & Qt::ControlModifier && e->modifiers() & Qt::ShiftModifier ) )
551+
QDomDocument doc;
552+
QClipboard *clipboard = QApplication::clipboard();
553+
if ( doc.setContent( clipboard->mimeData()->data( "text/xml" ) ) )
558554
{
559-
QDomDocument doc;
560-
QClipboard *clipboard = QApplication::clipboard();
561-
if ( doc.setContent( clipboard->mimeData()->data( "text/xml" ) ) )
555+
QDomElement docElem = doc.documentElement();
556+
if ( docElem.tagName() == "ComposerItemClipboard" )
562557
{
563-
QDomElement docElem = doc.documentElement();
564-
if ( docElem.tagName() == "ComposerItemClipboard" )
558+
if ( composition() )
565559
{
566-
if ( composition() )
560+
QPointF pt;
561+
if ( mode == PasteModeCursor )
567562
{
568-
QPointF pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
569-
bool pasteInPlace = ( e->modifiers() & Qt::ShiftModifier );
570-
composition()->addItemsFromXML( docElem, doc, 0, true, &pt, pasteInPlace );
563+
// place items at cursor position
564+
pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
571565
}
566+
else
567+
{
568+
// place items in center of viewport
569+
pt = mapToScene( viewport()->rect().center() );
570+
}
571+
bool pasteInPlace = ( mode == PasteModeInPlace );
572+
composition()->addItemsFromXML( docElem, doc, 0, true, &pt, pasteInPlace );
572573
}
573574
}
574575
}
576+
}
577+
578+
void QgsComposerView::deleteSelectedItems()
579+
{
580+
if ( !composition() )
581+
{
582+
return;
583+
}
584+
585+
QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
586+
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();
575587

576588
//delete selected items
577-
if ( e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace )
589+
for ( ; itemIt != composerItemList.end(); ++itemIt )
578590
{
579-
for ( ; itemIt != composerItemList.end(); ++itemIt )
591+
if ( composition() )
580592
{
581-
if ( composition() )
582-
{
583-
composition()->removeComposerItem( *itemIt );
584-
}
593+
composition()->removeComposerItem( *itemIt );
585594
}
586595
}
596+
}
597+
598+
void QgsComposerView::keyPressEvent( QKeyEvent * e )
599+
{
600+
if ( !composition() )
601+
{
602+
return;
603+
}
604+
605+
QList<QgsComposerItem*> composerItemList = composition()->selectedComposerItems();
606+
QList<QgsComposerItem*>::iterator itemIt = composerItemList.begin();
607+
608+
// increment used for cursor key item movement
609+
double increment = 1.0;
610+
if ( e->modifiers() & Qt::ShiftModifier )
611+
{
612+
//holding shift while pressing cursor keys results in a big step
613+
increment = 10.0;
614+
}
587615

588-
else if ( e->key() == Qt::Key_Left )
616+
if ( e->key() == Qt::Key_Left )
589617
{
590618
for ( ; itemIt != composerItemList.end(); ++itemIt )
591619
{

‎src/gui/qgscomposerview.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ class GUI_EXPORT QgsComposerView: public QGraphicsView
6868
MoveItemContent //move content of item (e.g. content of map)
6969
};
7070

71+
enum ClipboardMode
72+
{
73+
ClipboardModeCut,
74+
ClipboardModeCopy
75+
};
76+
77+
enum PasteMode
78+
{
79+
PasteModeCursor,
80+
PasteModeCenter,
81+
PasteModeInPlace
82+
};
83+
7184
QgsComposerView( QWidget* parent = 0, const char* name = 0, Qt::WFlags f = 0 );
7285

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

98+
/**Cuts or copies the selected items*/
99+
void copyItems( ClipboardMode mode );
100+
101+
/**Pastes items from clipboard*/
102+
void pasteItems( PasteMode mode );
103+
104+
/**Deletes selected items*/
105+
void deleteSelectedItems();
106+
85107
QgsComposerView::Tool currentTool() const {return mCurrentTool;}
86108
void setCurrentTool( QgsComposerView::Tool t ) {mCurrentTool = t;}
87109

0 commit comments

Comments
 (0)