mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Port duplicate layout functionality
This commit is contained in:
parent
a64a675830
commit
3a0b751698
@ -109,6 +109,14 @@ class QgsLayoutManager : QObject
|
||||
:rtype: QgsComposition
|
||||
%End
|
||||
|
||||
QgsLayout *duplicateLayout( const QgsLayout *layout, const QString &newName );
|
||||
%Docstring
|
||||
Duplicates an existing ``layout`` from the manager. The new
|
||||
layout will automatically be stored in the manager.
|
||||
Returns new the layout if duplication was successful.
|
||||
:rtype: QgsLayout
|
||||
%End
|
||||
|
||||
QString generateUniqueTitle() const;
|
||||
%Docstring
|
||||
Generates a unique title for a new composition, which does not
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "qgslayoutmodel.h"
|
||||
#include "qgslayoutitemslistview.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsbusyindicatordialog.h"
|
||||
#include <QShortcut>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
@ -311,6 +312,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
|
||||
|
||||
connect( mActionSaveAsTemplate, &QAction::triggered, this, &QgsLayoutDesignerDialog::saveAsTemplate );
|
||||
connect( mActionLoadFromTemplate, &QAction::triggered, this, &QgsLayoutDesignerDialog::addItemsFromTemplate );
|
||||
connect( mActionDuplicateLayout, &QAction::triggered, this, &QgsLayoutDesignerDialog::duplicate );
|
||||
|
||||
connect( mActionZoomIn, &QAction::triggered, mView, &QgsLayoutView::zoomIn );
|
||||
connect( mActionZoomOut, &QAction::triggered, mView, &QgsLayoutView::zoomOut );
|
||||
@ -1319,6 +1321,32 @@ void QgsLayoutDesignerDialog::addItemsFromTemplate()
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutDesignerDialog::duplicate()
|
||||
{
|
||||
QString newTitle;
|
||||
if ( !QgisApp::instance()->uniqueLayoutTitle( this, newTitle, false, tr( "%1 copy" ).arg( currentLayout()->name() ) ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// provide feedback, since loading of template into duplicate layout will be hidden
|
||||
QDialog *dlg = new QgsBusyIndicatorDialog( tr( "Duplicating layout…" ) );
|
||||
dlg->setStyleSheet( QgisApp::instance()->styleSheet() );
|
||||
dlg->show();
|
||||
|
||||
QgsLayoutDesignerDialog *newDialog = QgisApp::instance()->duplicateLayout( currentLayout(), newTitle );
|
||||
|
||||
dlg->close();
|
||||
delete dlg;
|
||||
dlg = nullptr;
|
||||
|
||||
if ( !newDialog )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Duplicate layout" ),
|
||||
tr( "Layout duplication failed." ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayoutDesignerDialog::paste()
|
||||
{
|
||||
QPointF pt = mView->mapFromGlobal( QCursor::pos() );
|
||||
|
@ -268,6 +268,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
|
||||
void undoRedoOccurredForItems( const QSet< QString > itemUuids );
|
||||
void saveAsTemplate();
|
||||
void addItemsFromTemplate();
|
||||
void duplicate();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -205,6 +205,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
|
||||
#include "qgslayertreeutils.h"
|
||||
#include "qgslayertreeview.h"
|
||||
#include "qgslayertreeviewdefaultactions.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgslayoutcustomdrophandler.h"
|
||||
#include "qgslayoutdesignerdialog.h"
|
||||
#include "qgslayoutmanager.h"
|
||||
@ -7333,6 +7334,71 @@ bool QgisApp::uniqueComposerTitle( QWidget *parent, QString &composerTitle, bool
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgisApp::uniqueLayoutTitle( QWidget *parent, QString &title, bool acceptEmpty, const QString ¤tTitle )
|
||||
{
|
||||
if ( !parent )
|
||||
{
|
||||
parent = this;
|
||||
}
|
||||
bool ok = false;
|
||||
bool titleValid = false;
|
||||
QString newTitle = QString( currentTitle );
|
||||
QString chooseMsg = tr( "Create unique print layout title" );
|
||||
if ( acceptEmpty )
|
||||
{
|
||||
chooseMsg += '\n' + tr( "(title generated if left empty)" );
|
||||
}
|
||||
QString titleMsg = chooseMsg;
|
||||
|
||||
QStringList cNames;
|
||||
cNames << newTitle;
|
||||
#if 0 //TODO
|
||||
Q_FOREACH ( QgsComposition *c, QgsProject::instance()->layoutManager()->compositions() )
|
||||
{
|
||||
cNames << c->name();
|
||||
}
|
||||
#endif
|
||||
while ( !titleValid )
|
||||
{
|
||||
newTitle = QInputDialog::getText( parent,
|
||||
tr( "Layout title" ),
|
||||
titleMsg,
|
||||
QLineEdit::Normal,
|
||||
newTitle,
|
||||
&ok );
|
||||
if ( !ok )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( newTitle.isEmpty() )
|
||||
{
|
||||
if ( !acceptEmpty )
|
||||
{
|
||||
titleMsg = chooseMsg + "\n\n" + tr( "Title can not be empty!" );
|
||||
}
|
||||
else
|
||||
{
|
||||
titleValid = true;
|
||||
newTitle = QgsProject::instance()->layoutManager()->generateUniqueTitle();
|
||||
}
|
||||
}
|
||||
else if ( cNames.indexOf( newTitle, 1 ) >= 0 )
|
||||
{
|
||||
cNames[0] = QString(); // clear non-unique name
|
||||
titleMsg = chooseMsg + "\n\n" + tr( "Title already exists!" );
|
||||
}
|
||||
else
|
||||
{
|
||||
titleValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
title = newTitle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsComposer *QgisApp::createNewComposer( QString title )
|
||||
{
|
||||
if ( title.isEmpty() )
|
||||
@ -7441,6 +7507,21 @@ QgsComposer *QgisApp::duplicateComposer( QgsComposer *currentComposer, QString t
|
||||
return newComposer;
|
||||
}
|
||||
|
||||
QgsLayoutDesignerDialog *QgisApp::duplicateLayout( QgsLayout *layout, const QString &t )
|
||||
{
|
||||
QString title = t;
|
||||
if ( title.isEmpty() )
|
||||
{
|
||||
// TODO: inject a bit of randomness in auto-titles?
|
||||
title = tr( "%1 copy" ).arg( layout->name() );
|
||||
}
|
||||
|
||||
QgsLayout *newLayout = QgsProject::instance()->layoutManager()->duplicateLayout( layout, title );
|
||||
QgsLayoutDesignerDialog *dlg = openLayoutDesignerDialog( newLayout );
|
||||
dlg->activate();
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void QgisApp::deletePrintComposers()
|
||||
{
|
||||
QSet<QgsComposer *>::iterator it = mPrintComposers.begin();
|
||||
|
@ -361,6 +361,21 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
* \returns QString() if user cancels input dialog
|
||||
*/
|
||||
bool uniqueComposerTitle( QWidget *parent, QString &composerTitle, bool acceptEmpty, const QString ¤tTitle = QString() );
|
||||
|
||||
/**
|
||||
* Gets a unique title from user for new and duplicate layouts.
|
||||
*
|
||||
* The \a title argument will be filled with the new layout title.
|
||||
*
|
||||
* If \a acceptEmpty is true then empty titles will be acceptable (one will be generated).
|
||||
*
|
||||
* The \a currentTitle argument specifies a base name for initial title choice.
|
||||
*
|
||||
* \returns true if user did not cancel the dialog.
|
||||
*/
|
||||
bool uniqueLayoutTitle( QWidget *parent, QString &title, bool acceptEmpty, const QString ¤tTitle = QString() );
|
||||
|
||||
|
||||
//! Creates a new composer and returns a pointer to it
|
||||
QgsComposer *createNewComposer( QString title = QString() );
|
||||
|
||||
@ -383,6 +398,14 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
*/
|
||||
QgsComposer *duplicateComposer( QgsComposer *currentComposer, QString title = QString() );
|
||||
|
||||
/**
|
||||
* Duplicates a \a layout and adds it to the current project.
|
||||
*
|
||||
* If \a title is set, it will be used as the title for the new layout. If it is not set,
|
||||
* and auto-generated title will be used instead.
|
||||
*/
|
||||
QgsLayoutDesignerDialog *duplicateLayout( QgsLayout *layout, const QString &title = QString() );
|
||||
|
||||
//! Overloaded function used to sort menu entries alphabetically
|
||||
QMenu *createPopupMenu() override;
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgslayoutmanager.h"
|
||||
#include "qgslayout.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
@ -186,6 +187,38 @@ QgsComposition *QgsLayoutManager::duplicateComposition( const QString &name, con
|
||||
}
|
||||
}
|
||||
|
||||
QgsLayout *QgsLayoutManager::duplicateLayout( const QgsLayout *layout, const QString &newName )
|
||||
{
|
||||
QDomDocument currentDoc;
|
||||
|
||||
QgsReadWriteContext context;
|
||||
QDomElement elem = layout->writeXml( currentDoc, context );
|
||||
currentDoc.appendChild( elem );
|
||||
|
||||
std::unique_ptr< QgsLayout > newLayout = qgis::make_unique< QgsLayout >( mProject );
|
||||
bool ok = false;
|
||||
newLayout->loadFromTemplate( currentDoc, context, true, &ok );
|
||||
if ( !ok )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newLayout->setName( newName );
|
||||
#if 0 //TODO
|
||||
if ( !addComposition( newComposition ) )
|
||||
{
|
||||
delete newComposition;
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return newComposition;
|
||||
}
|
||||
#endif
|
||||
|
||||
return newLayout.release();
|
||||
}
|
||||
|
||||
QString QgsLayoutManager::generateUniqueTitle() const
|
||||
{
|
||||
QStringList names;
|
||||
|
@ -115,6 +115,13 @@ class CORE_EXPORT QgsLayoutManager : public QObject
|
||||
*/
|
||||
QgsComposition *duplicateComposition( const QString &name, const QString &newName );
|
||||
|
||||
/**
|
||||
* Duplicates an existing \a layout from the manager. The new
|
||||
* layout will automatically be stored in the manager.
|
||||
* Returns new the layout if duplication was successful.
|
||||
*/
|
||||
QgsLayout *duplicateLayout( const QgsLayout *layout, const QString &newName );
|
||||
|
||||
/**
|
||||
* Generates a unique title for a new composition, which does not
|
||||
* clash with any already contained by the manager.
|
||||
|
@ -62,6 +62,7 @@
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="mActionDuplicateLayout"/>
|
||||
<addaction name="mActionLoadFromTemplate"/>
|
||||
<addaction name="mActionSaveAsTemplate"/>
|
||||
</widget>
|
||||
@ -94,6 +95,8 @@
|
||||
<property name="title">
|
||||
<string>&Layout</string>
|
||||
</property>
|
||||
<addaction name="mActionDuplicateLayout"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="mActionLayoutProperties"/>
|
||||
<addaction name="mActionAddPages"/>
|
||||
<addaction name="separator"/>
|
||||
@ -1068,7 +1071,7 @@
|
||||
<normaloff>:/images/themes/default/mActionFileSaveAs.svg</normaloff>:/images/themes/default/mActionFileSaveAs.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save as &Template...</string>
|
||||
<string>Save as &Template…</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save as template</string>
|
||||
@ -1080,12 +1083,24 @@
|
||||
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Add Items from Template...</string>
|
||||
<string>&Add Items from Template…</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add items from template</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionDuplicateLayout">
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionDuplicateComposer.svg</normaloff>:/images/themes/default/mActionDuplicateComposer.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Duplicate Layout…</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Duplicate layout</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user