Skip to content

Commit

Permalink
Fix leak of QActions in browser right click menu
Browse files Browse the repository at this point in the history
Since these actions are created anew whenever we show the menu,
they should be parented to the menu so that they get correctly
cleaned up as soon as the menu is destroyed.
  • Loading branch information
nyalldawson committed Jul 15, 2021
1 parent 14c645e commit d9b6eda
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/app/browser/qgsinbuiltdataitemproviders.cpp
Expand Up @@ -75,7 +75,7 @@ void QgsAppDirectoryItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe

QgsSettings settings;

QAction *actionRefresh = new QAction( tr( "Refresh" ), this );
QAction *actionRefresh = new QAction( tr( "Refresh" ), menu );
connect( actionRefresh, &QAction::triggered, this, [ = ] { directoryItem->refresh(); } );
menu->addAction( actionRefresh );

Expand Down
18 changes: 8 additions & 10 deletions src/gui/providers/ogr/qgsgeopackageitemguiprovider.cpp
Expand Up @@ -50,7 +50,7 @@ void QgsGeoPackageItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu
// Check capabilities
if ( layerItem->capabilities2() & Qgis::BrowserItemCapability::Rename )
{
QAction *actionRenameLayer = new QAction( tr( "Rename Layer '%1'…" ).arg( layerItem->name() ), this );
QAction *actionRenameLayer = new QAction( tr( "Rename Layer '%1'…" ).arg( layerItem->name() ), menu );
QVariantMap data;
const QString uri = layerItem->uri();
const QString providerKey = layerItem->providerKey();
Expand All @@ -66,11 +66,11 @@ void QgsGeoPackageItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu

if ( QgsGeoPackageRootItem *rootItem = qobject_cast< QgsGeoPackageRootItem * >( item ) )
{
QAction *actionNew = new QAction( tr( "New Connection…" ), rootItem->parent() );
QAction *actionNew = new QAction( tr( "New Connection…" ), menu );
connect( actionNew, &QAction::triggered, rootItem, &QgsGeoPackageRootItem::newConnection );
menu->addAction( actionNew );

QAction *actionCreateDatabase = new QAction( tr( "Create Database…" ), rootItem->parent() );
QAction *actionCreateDatabase = new QAction( tr( "Create Database…" ), menu );
QPointer< QgsGeoPackageRootItem > rootItemPointer( rootItem );
connect( actionCreateDatabase, &QAction::triggered, this, [this, rootItemPointer ]
{
Expand All @@ -83,24 +83,22 @@ void QgsGeoPackageItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu
{
if ( QgsOgrDbConnection::connectionList( QStringLiteral( "GPKG" ) ).contains( collectionItem->name() ) )
{
QAction *actionDeleteConnection = new QAction( tr( "Remove Connection" ), collectionItem->parent() );
QAction *actionDeleteConnection = new QAction( tr( "Remove Connection" ), menu );
connect( actionDeleteConnection, &QAction::triggered, collectionItem, &QgsGeoPackageConnectionItem::deleteConnection );
menu->addAction( actionDeleteConnection );
}
else
{
// Add to stored connections
QAction *actionAddConnection = new QAction( tr( "Add Connection" ), collectionItem->parent() );
QAction *actionAddConnection = new QAction( tr( "Add Connection" ), menu );
connect( actionAddConnection, &QAction::triggered, collectionItem, &QgsGeoPackageCollectionItem::addConnection );
menu->addAction( actionAddConnection );
}

QAction *sep = new QAction( collectionItem->parent() );
sep->setSeparator( true );
menu->addAction( sep );
menu->addSeparator();

QString message = QObject::tr( "Delete %1…" ).arg( collectionItem->name() );
QAction *actionDelete = new QAction( message, collectionItem->parent() );
QAction *actionDelete = new QAction( message, menu );
QString collectionPath = collectionItem->path();
QString collectionName = collectionItem->name();
QPointer< QgsDataItem > parent( collectionItem->parent() );
Expand All @@ -111,7 +109,7 @@ void QgsGeoPackageItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu
menu->addAction( actionDelete );

// Run VACUUM
QAction *actionVacuumDb = new QAction( tr( "Compact Database (VACUUM)" ), collectionItem->parent() );
QAction *actionVacuumDb = new QAction( tr( "Compact Database (VACUUM)" ), menu );
QVariantMap dataVacuum;
const QString name = collectionItem->name();
const QString path = collectionItem->path();
Expand Down
4 changes: 2 additions & 2 deletions src/gui/providers/ogr/qgsogritemguiprovider.cpp
Expand Up @@ -38,7 +38,7 @@ void QgsOgrItemGuiProvider::populateContextMenu(
{
// Messages are different for files and tables
QString message = layerItem->isSubLayer() ? QObject::tr( "Delete Layer “%1”…" ).arg( layerItem->name() ) : QObject::tr( "Delete File “%1”…" ).arg( layerItem->name() );
QAction *actionDeleteLayer = new QAction( message, layerItem->parent() );
QAction *actionDeleteLayer = new QAction( message, menu );
QVariantMap data;
data.insert( QStringLiteral( "isSubLayer" ), layerItem->isSubLayer() );
data.insert( QStringLiteral( "uri" ), layerItem->uri() );
Expand All @@ -54,7 +54,7 @@ void QgsOgrItemGuiProvider::populateContextMenu(
const bool isFolder = QFileInfo( collectionItem->path() ).isDir();
// Messages are different for files and tables
QString message = QObject::tr( "Delete %1 “%2”…" ).arg( isFolder ? tr( "Folder" ) : tr( "File" ), collectionItem->name() );
QAction *actionDeleteCollection = new QAction( message, collectionItem->parent() );
QAction *actionDeleteCollection = new QAction( message, menu );

QVariantMap data;
data.insert( QStringLiteral( "path" ), collectionItem->path() );
Expand Down
12 changes: 6 additions & 6 deletions src/gui/vectortile/qgsvectortiledataitemguiprovider.cpp
Expand Up @@ -30,32 +30,32 @@ void QgsVectorTileDataItemGuiProvider::populateContextMenu( QgsDataItem *item, Q
{
if ( QgsVectorTileLayerItem *layerItem = qobject_cast< QgsVectorTileLayerItem * >( item ) )
{
QAction *actionEdit = new QAction( tr( "Edit…" ), this );
QAction *actionEdit = new QAction( tr( "Edit…" ), menu );
connect( actionEdit, &QAction::triggered, this, [layerItem] { editConnection( layerItem ); } );
menu->addAction( actionEdit );

QAction *actionDelete = new QAction( tr( "Delete" ), this );
QAction *actionDelete = new QAction( tr( "Delete" ), menu );
connect( actionDelete, &QAction::triggered, this, [layerItem] { deleteConnection( layerItem ); } );
menu->addAction( actionDelete );
}

if ( QgsVectorTileRootItem *rootItem = qobject_cast< QgsVectorTileRootItem * >( item ) )
{
QAction *actionNew = new QAction( tr( "New Generic Connection…" ), this );
QAction *actionNew = new QAction( tr( "New Generic Connection…" ), menu );
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionNewArcGISConnection = new QAction( tr( "New ArcGIS Vector Tile Service Connection…" ), this );
QAction *actionNewArcGISConnection = new QAction( tr( "New ArcGIS Vector Tile Service Connection…" ), menu );
connect( actionNewArcGISConnection, &QAction::triggered, this, [rootItem] { newArcGISConnection( rootItem ); } );
menu->addAction( actionNewArcGISConnection );

menu->addSeparator();

QAction *actionSaveXyzTilesServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveXyzTilesServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveXyzTilesServers, &QAction::triggered, this, [] { saveXyzTilesServers(); } );
menu->addAction( actionSaveXyzTilesServers );

QAction *actionLoadXyzTilesServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadXyzTilesServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadXyzTilesServers, &QAction::triggered, this, [rootItem] { loadXyzTilesServers( rootItem ); } );
menu->addAction( actionLoadXyzTilesServers );
}
Expand Down
4 changes: 2 additions & 2 deletions src/providers/arcgisrest/qgsarcgisrestdataitemguiprovider.cpp
Expand Up @@ -32,11 +32,11 @@ void QgsArcGisRestDataItemGuiProvider::populateContextMenu( QgsDataItem *item, Q
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}
Expand Down
4 changes: 2 additions & 2 deletions src/providers/db2/qgsdb2dataitemguiprovider.cpp
Expand Up @@ -30,11 +30,11 @@ void QgsDb2DataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *m
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}
Expand Down
4 changes: 2 additions & 2 deletions src/providers/geonode/qgsgeonodedataitemguiprovider.cpp
Expand Up @@ -29,11 +29,11 @@ void QgsGeoNodeDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMen
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}
Expand Down
4 changes: 2 additions & 2 deletions src/providers/mssql/qgsmssqldataitemguiprovider.cpp
Expand Up @@ -33,11 +33,11 @@ void QgsMssqlDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}
Expand Down
26 changes: 13 additions & 13 deletions src/providers/postgres/qgspostgresdataitemguiprovider.cpp
Expand Up @@ -31,58 +31,58 @@ void QgsPostgresDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe
{
if ( QgsPGRootItem *rootItem = qobject_cast< QgsPGRootItem * >( item ) )
{
QAction *actionNew = new QAction( tr( "New Connection…" ), this );
QAction *actionNew = new QAction( tr( "New Connection…" ), menu );
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}

if ( QgsPGConnectionItem *connItem = qobject_cast< QgsPGConnectionItem * >( item ) )
{
QAction *actionRefresh = new QAction( tr( "Refresh" ), this );
QAction *actionRefresh = new QAction( tr( "Refresh" ), menu );
connect( actionRefresh, &QAction::triggered, this, [connItem] { refreshConnection( connItem ); } );
menu->addAction( actionRefresh );

menu->addSeparator();

QAction *actionEdit = new QAction( tr( "Edit Connection…" ), this );
QAction *actionEdit = new QAction( tr( "Edit Connection…" ), menu );
connect( actionEdit, &QAction::triggered, this, [connItem] { editConnection( connItem ); } );
menu->addAction( actionEdit );

QAction *actionDelete = new QAction( tr( "Delete Connection" ), this );
QAction *actionDelete = new QAction( tr( "Delete Connection" ), menu );
connect( actionDelete, &QAction::triggered, this, [connItem] { deleteConnection( connItem ); } );
menu->addAction( actionDelete );

menu->addSeparator();

QAction *actionCreateSchema = new QAction( tr( "New Schema…" ), this );
QAction *actionCreateSchema = new QAction( tr( "New Schema…" ), menu );
connect( actionCreateSchema, &QAction::triggered, this, [connItem, context] { createSchema( connItem, context ); } );
menu->addAction( actionCreateSchema );

}

if ( QgsPGSchemaItem *schemaItem = qobject_cast< QgsPGSchemaItem * >( item ) )
{
QAction *actionRefresh = new QAction( tr( "Refresh" ), this );
QAction *actionRefresh = new QAction( tr( "Refresh" ), menu );
connect( actionRefresh, &QAction::triggered, this, [schemaItem] { schemaItem->refresh(); } );
menu->addAction( actionRefresh );

menu->addSeparator();

QMenu *maintainMenu = new QMenu( tr( "Schema Operations" ), menu );

QAction *actionRename = new QAction( tr( "Rename Schema…" ), this );
QAction *actionRename = new QAction( tr( "Rename Schema…" ), menu );
connect( actionRename, &QAction::triggered, this, [schemaItem, context] { renameSchema( schemaItem, context ); } );
maintainMenu->addAction( actionRename );

QAction *actionDelete = new QAction( tr( "Delete Schema…" ), this );
QAction *actionDelete = new QAction( tr( "Delete Schema…" ), menu );
connect( actionDelete, &QAction::triggered, this, [schemaItem, context] { deleteSchema( schemaItem, context ); } );
maintainMenu->addAction( actionDelete );

Expand All @@ -96,20 +96,20 @@ void QgsPostgresDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe

QMenu *maintainMenu = new QMenu( tr( "%1 Operations" ).arg( typeName ), menu );

QAction *actionRenameLayer = new QAction( tr( "Rename %1…" ).arg( typeName ), this );
QAction *actionRenameLayer = new QAction( tr( "Rename %1…" ).arg( typeName ), menu );
connect( actionRenameLayer, &QAction::triggered, this, [layerItem, context] { renameLayer( layerItem, context ); } );
maintainMenu->addAction( actionRenameLayer );

if ( !layerInfo.isView )
{
QAction *actionTruncateLayer = new QAction( tr( "Truncate %1…" ).arg( typeName ), this );
QAction *actionTruncateLayer = new QAction( tr( "Truncate %1…" ).arg( typeName ), menu );
connect( actionTruncateLayer, &QAction::triggered, this, [layerItem, context] { truncateTable( layerItem, context ); } );
maintainMenu->addAction( actionTruncateLayer );
}

if ( layerInfo.isMaterializedView )
{
QAction *actionRefreshMaterializedView = new QAction( tr( "Refresh Materialized View…" ), this );
QAction *actionRefreshMaterializedView = new QAction( tr( "Refresh Materialized View…" ), menu );
connect( actionRefreshMaterializedView, &QAction::triggered, this, [layerItem, context] { refreshMaterializedView( layerItem, context ); } );
maintainMenu->addAction( actionRefreshMaterializedView );
}
Expand Down
6 changes: 3 additions & 3 deletions src/providers/spatialite/qgsspatialitedataitemguiprovider.cpp
Expand Up @@ -36,18 +36,18 @@ void QgsSpatiaLiteDataItemGuiProvider::populateContextMenu( QgsDataItem *item, Q
{
if ( QgsSLRootItem *rootItem = qobject_cast< QgsSLRootItem * >( item ) )
{
QAction *actionNew = new QAction( tr( "New Connection…" ), this );
QAction *actionNew = new QAction( tr( "New Connection…" ), menu );
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionCreateDatabase = new QAction( tr( "Create Database…" ), this );
QAction *actionCreateDatabase = new QAction( tr( "Create Database…" ), menu );
connect( actionCreateDatabase, &QAction::triggered, this, [rootItem] { createDatabase( rootItem ); } );
menu->addAction( actionCreateDatabase );
}

if ( QgsSLConnectionItem *connItem = qobject_cast< QgsSLConnectionItem * >( item ) )
{
QAction *actionDelete = new QAction( tr( "Delete" ), this );
QAction *actionDelete = new QAction( tr( "Delete" ), menu );
connect( actionDelete, &QAction::triggered, this, [connItem] { deleteConnection( connItem ); } );
menu->addAction( actionDelete );
}
Expand Down
12 changes: 6 additions & 6 deletions src/providers/wcs/qgswcsdataitemguiprovider.cpp
Expand Up @@ -28,32 +28,32 @@ void QgsWcsDataItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *m
{
if ( QgsWCSRootItem *rootItem = qobject_cast< QgsWCSRootItem * >( item ) )
{
QAction *actionNew = new QAction( tr( "New Connection…" ), this );
QAction *actionNew = new QAction( tr( "New Connection…" ), menu );
connect( actionNew, &QAction::triggered, this, [rootItem] { newConnection( rootItem ); } );
menu->addAction( actionNew );

QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), this );
QAction *actionSaveServers = new QAction( tr( "Save Connections…" ), menu );
connect( actionSaveServers, &QAction::triggered, this, [] { saveConnections(); } );
menu->addAction( actionSaveServers );

QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), this );
QAction *actionLoadServers = new QAction( tr( "Load Connections…" ), menu );
connect( actionLoadServers, &QAction::triggered, this, [rootItem] { loadConnections( rootItem ); } );
menu->addAction( actionLoadServers );
}

if ( QgsWCSConnectionItem *connItem = qobject_cast< QgsWCSConnectionItem * >( item ) )
{
QAction *actionRefresh = new QAction( tr( "Refresh" ), this );
QAction *actionRefresh = new QAction( tr( "Refresh" ), menu );
connect( actionRefresh, &QAction::triggered, this, [connItem] { refreshConnection( connItem ); } );
menu->addAction( actionRefresh );

menu->addSeparator();

QAction *actionEdit = new QAction( tr( "Edit…" ), this );
QAction *actionEdit = new QAction( tr( "Edit…" ), menu );
connect( actionEdit, &QAction::triggered, this, [connItem] { editConnection( connItem ); } );
menu->addAction( actionEdit );

QAction *actionDelete = new QAction( tr( "Delete" ), this );
QAction *actionDelete = new QAction( tr( "Delete" ), menu );
connect( actionDelete, &QAction::triggered, this, [connItem] { deleteConnection( connItem ); } );
menu->addAction( actionDelete );
}
Expand Down

0 comments on commit d9b6eda

Please sign in to comment.