Skip to content

Commit

Permalink
Extend HANA's menu items
Browse files Browse the repository at this point in the history
  • Loading branch information
mrylov authored and nyalldawson committed Feb 3, 2021
1 parent 3965323 commit 45ad03c
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 33 deletions.
246 changes: 222 additions & 24 deletions src/providers/hana/qgshanadataitemguiprovider.cpp
Expand Up @@ -15,19 +15,19 @@
*
***************************************************************************/
#include "qgshanaconnection.h"
#include "qgshanaconnectionpool.h"
#include "qgshanadataitems.h"
#include "qgshanadataitemguiprovider.h"
#include "qgshananewconnection.h"
#include "qgshanaprovider.h"
#include "qgshanaproviderconnection.h"
#include "qgshanautils.h"
#include "qgsnewnamedialog.h"

#include <QInputDialog>
#include <QMessageBox>

void QgsHanaDataItemGuiProvider::populateContextMenu(
QgsDataItem *item, QMenu *menu, const QList<QgsDataItem *> &, QgsDataItemGuiContext )
QgsDataItem *item, QMenu *menu, const QList<QgsDataItem *> &, QgsDataItemGuiContext context )
{
if ( QgsHanaRootItem *rootItem = qobject_cast<QgsHanaRootItem *>( item ) )
{
Expand All @@ -51,13 +51,48 @@ void QgsHanaDataItemGuiProvider::populateContextMenu(
QAction *actionDelete = new QAction( tr( "Delete Connection" ), this );
connect( actionDelete, &QAction::triggered, this, [connItem] { deleteConnection( connItem ); } );
menu->addAction( actionDelete );

menu->addSeparator();

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

if ( QgsHanaSchemaItem *schemaItem = qobject_cast<QgsHanaSchemaItem *>( item ) )
{
QAction *actionRefresh = new QAction( tr( "Refresh" ), this );
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 );
connect( actionRename, &QAction::triggered, this, [schemaItem, context] { renameSchema( schemaItem, context ); } );
maintainMenu->addAction( actionRename );

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

menu->addMenu( maintainMenu );
}

if ( QgsHanaLayerItem *layerItem = qobject_cast< QgsHanaLayerItem * >( item ) )
{
const QgsHanaLayerProperty &layerInfo = layerItem->layerInfo();
if ( !layerInfo.isView )
{
QMenu *maintainMenu = new QMenu( tr( "Table Operations" ), menu );

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

menu->addMenu( maintainMenu );
}
}
}

Expand All @@ -66,38 +101,38 @@ bool QgsHanaDataItemGuiProvider::deleteLayer( QgsLayerItem *item, QgsDataItemGui
if ( QgsHanaLayerItem *layerItem = qobject_cast<QgsHanaLayerItem *>( item ) )
{
const QgsHanaLayerProperty &layerInfo = layerItem->layerInfo();
QString objectName = QStringLiteral( "%1.%2" ).arg( layerInfo.schemaName, layerInfo.tableName );
QString typeName = layerInfo.isView ? tr( "View" ) : tr( "Table" );

if ( QMessageBox::question( nullptr, tr( "Delete %1" ).arg( typeName ),
tr( "Are you sure you want to delete %1?" ).arg( objectName ),
const QString layerName = QStringLiteral( "%1.%2" ).arg( layerInfo.schemaName, layerInfo.tableName );
const QString caption = tr( layerInfo.isView ? "Delete View" : "Delete Table" );
if ( QMessageBox::question( nullptr, caption,
tr( "Are you sure you want to delete '%1'?" ).arg( layerName ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return true;

QgsHanaConnectionItem *connItem = qobject_cast<QgsHanaConnectionItem *>( layerItem->parent()->parent() );
QgsHanaConnectionRef conn( connItem->name() );
if ( conn.isNull() )
return false;

QString sql = QStringLiteral( "DROP TABLE %1.%2" )
.arg( QgsHanaUtils::quotedIdentifier( layerInfo.schemaName ), QgsHanaUtils::quotedIdentifier( layerInfo.tableName ) );

QString errMessage;
bool res = conn->execute( sql, &errMessage );
if ( !res )
QString errorMsg;
try
{
notify( tr( "Delete %1" ).arg( typeName ), errMessage, context, Qgis::MessageLevel::Warning );
QgsHanaProviderConnection providerConn( layerItem->uri(), {} );
providerConn.dropVectorTable( layerInfo.schemaName, layerInfo.tableName );
}
else
catch ( const QgsProviderConnectionException &ex )
{
errorMsg = ex.what();
}

if ( errorMsg.isEmpty() )
{
notify( tr( "Delete %1" ).arg( typeName ), tr( "%1 %2 deleted successfully." ).arg( typeName, objectName ),
context, Qgis::MessageLevel::Success );
notify( caption, tr( "'%1' deleted successfully." ).arg( layerName ), context, Qgis::MessageLevel::Success );

if ( layerItem->parent() )
layerItem->parent()->refresh();
return true;
}
else
{
notify( caption, errorMsg, context, Qgis::MessageLevel::Warning );
}
return res;
}

return false;
}

Expand Down Expand Up @@ -151,7 +186,7 @@ void QgsHanaDataItemGuiProvider::editConnection( QgsDataItem *item )

void QgsHanaDataItemGuiProvider::deleteConnection( QgsDataItem *item )
{
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Connection" ),
if ( QMessageBox::question( nullptr, tr( "Delete Connection" ),
tr( "Are you sure you want to delete the connection to %1?" ).arg( item->name() ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;
Expand All @@ -169,3 +204,166 @@ void QgsHanaDataItemGuiProvider::refreshConnection( QgsDataItem *item )
if ( item->parent() )
item->parent()->refreshConnections();
}

void QgsHanaDataItemGuiProvider::createSchema( QgsDataItem *item, QgsDataItemGuiContext context )
{
const QString schemaName = QInputDialog::getText( nullptr, tr( "Create Schema" ), tr( "Schema name:" ) );
if ( schemaName.isEmpty() )
return;

QString errorMsg;
try
{
QgsHanaProviderConnection providerConn( item->name() );
providerConn.createSchema( schemaName );
}
catch ( const QgsProviderConnectionException &ex )
{
errorMsg = ex.what();
}

if ( errorMsg.isEmpty() )
{
notify( tr( "New Schema" ), tr( "Schema '%1' created successfully." ).arg( schemaName ),
context, Qgis::MessageLevel::Success );

item->refresh();
// the parent should be updated
if ( item->parent() )
item->parent()->refreshConnections();
}
else
{
notify( tr( "New Schema" ), tr( "Unable to create schema '%1'\n%2" ).arg( schemaName, errorMsg ),
context, Qgis::MessageLevel::Warning );
}
}

void QgsHanaDataItemGuiProvider::deleteSchema( QgsHanaSchemaItem *schemaItem, QgsDataItemGuiContext context )
{
const QString schemaName = schemaItem->name();
const QString caption = tr( "Delete Schema" );
QString errorMsg;
try
{
QgsHanaProviderConnection providerConn( schemaItem->connectionName() );
const auto tables = providerConn.tables( schemaName );
if ( tables.empty() )
{
if ( QMessageBox::question( nullptr, caption,
tr( "Are you sure you want to delete '%1'?" ).arg( schemaName ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;
}
else
{
const int MAXIMUM_LISTED_ITEMS = 10;
QString tableNames;
for ( int i = 0; i < tables.size(); ++i )
{
const auto &tableProperty = tables.at( i );
if ( i < MAXIMUM_LISTED_ITEMS )
tableNames += tableProperty.tableName() + QLatin1Char( '\n' );
else
{
tableNames += QStringLiteral( "\n[%1 additional objects not listed]" ).arg( tables.size() - MAXIMUM_LISTED_ITEMS );
break;
}
}

if ( QMessageBox::question( nullptr, caption,
tr( "Schema '%1' contains objects:\n\n%2\n\nAre you sure you want to delete the schema and all these objects?" ).arg( schemaName, tableNames ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;
}

providerConn.dropSchema( schemaName, !tables.empty() );
}
catch ( const QgsProviderConnectionException &ex )
{
errorMsg = ex.what();
}

if ( errorMsg.isEmpty() )
{
notify( caption, tr( "Schema '%1' deleted successfully." ).arg( schemaName ),
context, Qgis::MessageLevel::Success );
if ( schemaItem->parent() )
schemaItem->parent()->refresh();
}
else
{
notify( caption, tr( "Unable to delete schema '%1'\n%2" ).arg( schemaName, errorMsg ),
context, Qgis::MessageLevel::Warning );
}
}

void QgsHanaDataItemGuiProvider::renameSchema( QgsHanaSchemaItem *schemaItem, QgsDataItemGuiContext context )
{
const QString schemaName = schemaItem->name();
const QString caption = tr( "Rename Schema" );
QgsNewNameDialog dlg( tr( "schema '%1'" ).arg( schemaName ), schemaName );
dlg.setWindowTitle( caption );
if ( dlg.exec() != QDialog::Accepted || dlg.name() == schemaName )
return;

const QString newSchemaName = dlg.name();
QString errorMsg;
try
{
QgsHanaProviderConnection providerConn( schemaItem->connectionName() );
providerConn.renameSchema( schemaName, newSchemaName );
}
catch ( const QgsProviderConnectionException &ex )
{
errorMsg = ex.what();
}

if ( errorMsg.isEmpty() )
{
notify( caption, tr( "Schema '%1' renamed successfully to '%2'." ).arg( schemaName, newSchemaName ),
context, Qgis::MessageLevel::Success );
if ( schemaItem->parent() )
schemaItem->parent()->refresh();
}
else
{
notify( caption, tr( "Unable to rename schema '%1'\n%2" ).arg( schemaName, errorMsg ),
context, Qgis::MessageLevel::Warning );
}
}

void QgsHanaDataItemGuiProvider::renameLayer( QgsHanaLayerItem *layerItem, QgsDataItemGuiContext context )
{
const QgsHanaLayerProperty &layerInfo = layerItem->layerInfo();
const QString caption = tr( "Rename Table" );
QgsNewNameDialog dlg( tr( "table '%1.%2'" ).arg( layerInfo.schemaName, layerInfo.tableName ), layerInfo.tableName );
dlg.setWindowTitle( caption );
if ( dlg.exec() != QDialog::Accepted || dlg.name() == layerInfo.tableName )
return;

const QString newLayerName = dlg.name();
QString errorMsg;
try
{
QgsHanaProviderConnection providerConn( layerItem->uri(), {} );
providerConn.renameVectorTable( layerInfo.schemaName, layerInfo.tableName, newLayerName );
}
catch ( const QgsProviderConnectionException &ex )
{
errorMsg = ex.what();
}

if ( errorMsg.isEmpty() )
{
notify( caption, tr( "'%1' renamed successfully to '%2'." ).arg( layerInfo.tableName, newLayerName ),
context, Qgis::MessageLevel::Success );
if ( layerItem->parent() )
layerItem->parent()->refresh();
}
else
{
notify( caption, tr( "Unable to rename '%1'\n%2" ).arg( layerInfo.tableName, errorMsg ),
context, Qgis::MessageLevel::Warning );
}
}
4 changes: 4 additions & 0 deletions src/providers/hana/qgshanadataitemguiprovider.h
Expand Up @@ -42,6 +42,10 @@ class QgsHanaDataItemGuiProvider : public QObject, public QgsDataItemGuiProvider
static void editConnection( QgsDataItem *item );
static void deleteConnection( QgsDataItem *item );
static void refreshConnection( QgsDataItem *item );
static void createSchema( QgsDataItem *item, QgsDataItemGuiContext context );
static void deleteSchema( QgsHanaSchemaItem *schemaItem, QgsDataItemGuiContext context );
static void renameSchema( QgsHanaSchemaItem *schemaItem, QgsDataItemGuiContext context );
static void renameLayer( QgsHanaLayerItem *layerItem, QgsDataItemGuiContext context );
};

#endif // QGSHANADATAITEMGUIPROVIDER_H
15 changes: 11 additions & 4 deletions src/providers/hana/qgshanadataitems.cpp
Expand Up @@ -230,14 +230,16 @@ QgsHanaLayerItem::QgsHanaLayerItem(
: QgsLayerItem( parent, name, path, QString(), layerType, QStringLiteral( "hana" ) )
, mLayerProperty( layerProperty )
{
mCapabilities |= Delete;
mCapabilities |= Delete | Fertile;
mUri = createUri();
setState( Populated );
setState( NotPopulated );
}

QString QgsHanaLayerItem::comments() const
QVector<QgsDataItem *> QgsHanaLayerItem::createChildren()
{
return mLayerProperty.tableComment;
QVector<QgsDataItem *> items;
items.push_back( new QgsFieldsItem( this, uri() + QStringLiteral( "/columns/ " ), createUri(), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) );
return items;
}

QString QgsHanaLayerItem::createUri() const
Expand Down Expand Up @@ -279,6 +281,11 @@ QString QgsHanaLayerItem::createUri() const
return uri.uri( false );
}

QString QgsHanaLayerItem::comments() const
{
return mLayerProperty.tableComment;
}

// ---------------------------------------------------------------------------
QgsHanaSchemaItem::QgsHanaSchemaItem(
QgsDataItem *parent,
Expand Down
4 changes: 3 additions & 1 deletion src/providers/hana/qgshanadataitems.h
Expand Up @@ -72,8 +72,8 @@ class QgsHanaSchemaItem : public QgsDatabaseSchemaItem
QgsHanaSchemaItem( QgsDataItem *parent, const QString &connectionName, const QString &name,
const QString &path );

const QString &connectionName() const { return mConnectionName; }
QVector<QgsDataItem *> createChildren() override;

// QgsDataItem interface
bool layerCollection() const override { return true; }

Expand All @@ -92,6 +92,8 @@ class QgsHanaLayerItem : public QgsLayerItem
QgsHanaLayerItem( QgsDataItem *parent, const QString &name, const QString &path,
QgsLayerItem::LayerType layerType, const QgsHanaLayerProperty &layerProperties );

QVector<QgsDataItem *> createChildren() override;

QString createUri() const;

QString comments() const override;
Expand Down

0 comments on commit 45ad03c

Please sign in to comment.