Skip to content

Commit

Permalink
Drag & Drop or Copy & Paste insert statements from the DB Schema dock
Browse files Browse the repository at this point in the history
See issue #3817
  • Loading branch information
mgrojo committed Dec 12, 2024
1 parent 3aaa752 commit ff830e7
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 12 deletions.
37 changes: 30 additions & 7 deletions src/DbStructureModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
#include <QMimeData>
#include <QMessageBox>
#include <QApplication>
#include <QClipboard>

DbStructureModel::DbStructureModel(DBBrowserDB& db, QObject* parent)
: QAbstractItemModel(parent),
m_db(db),
browsablesRootItem(nullptr),
m_dropQualifiedNames(false),
m_dropEnquotedNames(false),
m_dropSelectQuery(true)
m_dropSelectQuery(true),
m_dropInsert(false)
{
// Create root item and use its columns to store the header strings
QStringList header;
Expand Down Expand Up @@ -210,7 +212,7 @@ QStringList DbStructureModel::mimeTypes() const
QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
{
// We store the SQL data and the names data separately
QByteArray sqlData, namesData;
QByteArray sqlData, namesData, parametersData;

// For dropping SELECT queries, these variables take account of
// whether all objects are of the same type and belong to the same table.
Expand All @@ -235,6 +237,8 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
// For names, export a (qualified) (escaped) identifier of the item for statement composition in SQL editor.
if(objectType == "field") {
namesData.append(getNameForDropping(item->text(ColumnSchema), item->parent()->text(ColumnName), item->text(ColumnName)).toUtf8());
parametersData.append(QString("?" + item->text(ColumnName) + ", ").toUtf8());

QString table = getNameForDropping(item->text(ColumnSchema), item->parent()->text(ColumnName), "");
if (tableSet.isEmpty() || tableSet == table) {
tableSet = table;
Expand Down Expand Up @@ -299,14 +303,27 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
else if (namesData.endsWith("."))
namesData.chop(1);

if (parametersData.endsWith(", "))
parametersData.chop(2);
else if (parametersData.endsWith("."))
parametersData.chop(1);

if (tableSet.endsWith("."))
tableSet.chop(1);

if (m_dropSelectQuery && !tableSet.isEmpty() && tableSet != "*" && !objectTypeSet.isEmpty()) {
if (objectTypeSet == "field") {
namesData = ("SELECT " + QString::fromUtf8(namesData) + " FROM " + tableSet + ";").toUtf8();
} else if (objectTypeSet == "table") {
namesData = ("SELECT * FROM " + tableSet + ";").toUtf8();
if (!tableSet.isEmpty() && tableSet != "*" && !objectTypeSet.isEmpty()) {
if (m_dropSelectQuery) {
if (objectTypeSet == "field") {
namesData = ("SELECT " + QString::fromUtf8(namesData) + " FROM " + tableSet + ";\n").toUtf8();
} else if (objectTypeSet == "table") {
namesData = ("SELECT * FROM " + tableSet + ";").toUtf8();
}
} else if (m_dropInsert) {
if (objectTypeSet == "field") {
namesData = ("INSERT INTO " + tableSet + " (" + QString::fromUtf8(namesData) + ") VALUES (" + parametersData + ");\n").toUtf8();
} else if (objectTypeSet == "table") {
namesData = ("INSERT INTO " + tableSet + " DEFAULT VALUES;\n").toUtf8();
}
}
}
mime->setData("text/plain", namesData);
Expand All @@ -315,6 +332,12 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
return mime;
}

void DbStructureModel::copy(const QModelIndexList& indices) const
{
QMimeData *mimeData = DbStructureModel::mimeData(indices);
qApp->clipboard()->setMimeData(mimeData);
}

bool DbStructureModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int, int, const QModelIndex&)
{
if(action == Qt::IgnoreAction)
Expand Down
5 changes: 5 additions & 0 deletions src/DbStructureModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class DbStructureModel : public QAbstractItemModel
QMimeData* mimeData(const QModelIndexList& indices) const override;
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override;

// Copy selected items to clipboard
void copy(const QModelIndexList& indices) const;

enum Columns
{
ColumnName,
Expand All @@ -41,6 +44,7 @@ public slots:
void setDropQualifiedNames(bool value) { m_dropQualifiedNames = value; }
void setDropEnquotedNames(bool value) { m_dropEnquotedNames = value; }
void setDropSelectQuery(bool value) { m_dropSelectQuery = value; }
void setDropInsert(bool value) { m_dropInsert = value; }

private:
DBBrowserDB& m_db;
Expand All @@ -49,6 +53,7 @@ public slots:
bool m_dropQualifiedNames;
bool m_dropEnquotedNames;
bool m_dropSelectQuery;
bool m_dropInsert;

void buildTree(QTreeWidgetItem* parent, const std::string& schema);
QTreeWidgetItem* addNode(const std::string& schema, const std::string& name, const std::string& object_type, const std::string& sql, QTreeWidgetItem* parent_item, const std::string& data_type = {}, const std::string& icon_suffix = {});
Expand Down
43 changes: 38 additions & 5 deletions src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,30 @@ void MainWindow::init()
popupSchemaDockMenu->addAction(ui->actionPopupSchemaDockDetachDatabase);
popupSchemaDockMenu->addSeparator();
popupSchemaDockMenu->addAction(ui->actionDropSelectQueryCheck);
popupSchemaDockMenu->addAction(ui->actionDropInsertCheck);
popupSchemaDockMenu->addAction(ui->actionDropNamesCheck);

QActionGroup* dropGroup = new QActionGroup(popupSchemaDockMenu);
dropGroup->addAction(ui->actionDropSelectQueryCheck);
dropGroup->addAction(ui->actionDropInsertCheck);
dropGroup->addAction(ui->actionDropNamesCheck);

popupSchemaDockMenu->addSeparator();
popupSchemaDockMenu->addAction(ui->actionDropQualifiedCheck);
popupSchemaDockMenu->addAction(ui->actionEnquoteNamesCheck);

popupSchemaDockMenu->addSeparator();
QAction* copyAction = new QAction(QIcon(":/icons/copy"), tr("Copy"), popupSchemaDockMenu);
copyAction->setShortcut(QKeySequence::Copy);
popupSchemaDockMenu->addAction(copyAction);
connect(copyAction, &QAction::triggered, this, [=]() {
dbStructureModel->copy(ui->treeSchemaDock->selectionModel()->selectedIndexes());
});
auto copyShortcut = new QShortcut(QKeySequence::Copy, ui->treeSchemaDock);
connect(copyShortcut, &QShortcut::activated, this, [=]() {
dbStructureModel->copy(ui->treeSchemaDock->selectionModel()->selectedIndexes());
});

popupOpenDbMenu = new QMenu(this);
popupOpenDbMenu->addAction(ui->fileOpenAction);
popupOpenDbMenu->addAction(ui->fileOpenReadOnlyAction);
Expand Down Expand Up @@ -419,14 +440,16 @@ void MainWindow::init()
connect(ui->dockEdit, &QDockWidget::visibilityChanged, this, &MainWindow::toggleEditDock);
connect(remoteDock, SIGNAL(openFile(QString)), this, SLOT(fileOpen(QString)));
connect(ui->actionDropSelectQueryCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropSelectQuery);
connect(ui->actionDropInsertCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropInsert);
connect(ui->actionDropNamesCheck, &QAction::toggled, dbStructureModel,
[this]() {
dbStructureModel->setDropSelectQuery(false);
dbStructureModel->setDropInsert(false);
});
connect(ui->actionDropQualifiedCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropQualifiedNames);
connect(ui->actionEnquoteNamesCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropEnquotedNames);
connect(&db, &DBBrowserDB::databaseInUseChanged, this, &MainWindow::updateDatabaseBusyStatus);

ui->actionDropSelectQueryCheck->setChecked(Settings::getValue("SchemaDock", "dropSelectQuery").toBool());
ui->actionDropQualifiedCheck->setChecked(Settings::getValue("SchemaDock", "dropQualifiedNames").toBool());
ui->actionEnquoteNamesCheck->setChecked(Settings::getValue("SchemaDock", "dropEnquotedNames").toBool());

connect(ui->actionSqlStop, &QAction::triggered, this, [this]() {
if(execute_sql_worker && execute_sql_worker->isRunning())
execute_sql_worker->stop();
Expand Down Expand Up @@ -770,6 +793,7 @@ void MainWindow::closeEvent( QCloseEvent* event )

Settings::setValue("SQLLogDock", "Log", ui->comboLogSubmittedBy->currentText());
Settings::setValue("SchemaDock", "dropSelectQuery", ui->actionDropSelectQueryCheck->isChecked());
Settings::setValue("SchemaDock", "dropInsert", ui->actionDropInsertCheck->isChecked());
Settings::setValue("SchemaDock", "dropQualifiedNames", ui->actionDropQualifiedCheck->isChecked());
Settings::setValue("SchemaDock", "dropEnquotedNames", ui->actionEnquoteNamesCheck->isChecked());

Expand Down Expand Up @@ -2423,7 +2447,16 @@ void MainWindow::reloadSettings()

sqlb::setIdentifierQuoting(static_cast<sqlb::escapeQuoting>(Settings::getValue("editor", "identifier_quotes").toInt()));

ui->tabSqlAreas->setTabsClosable(Settings::getValue("editor", "close_button_on_tabs").toBool());
ui->tabSqlAreas->setTabsClosable(
Settings::getValue("editor", "close_button_on_tabs").toBool());

ui->actionDropSelectQueryCheck->setChecked(Settings::getValue("SchemaDock", "dropSelectQuery").toBool());
ui->actionDropInsertCheck->setChecked(Settings::getValue("SchemaDock", "dropInsert").toBool());
ui->actionDropNamesCheck->setChecked(!ui->actionDropSelectQueryCheck->isChecked() &&
!ui->actionDropInsertCheck->isChecked());

ui->actionDropQualifiedCheck->setChecked(Settings::getValue("SchemaDock", "dropQualifiedNames").toBool());
ui->actionEnquoteNamesCheck->setChecked(Settings::getValue("SchemaDock", "dropEnquotedNames").toBool());
}

void MainWindow::checkNewVersion(const bool automatic)
Expand Down
28 changes: 28 additions & 0 deletions src/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -2415,6 +2415,34 @@ You can drag SQL statements from the Schema column and drop them into the SQL ed
<string>When dragging fields from the same table or a single table, drop a SELECT query into the editor</string>
</property>
</action>
<action name="actionDropNamesCheck">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Drag &amp;&amp; Drop Names</string>
</property>
<property name="statusTip">
<string>When dragging fields or tables, drop just the names into the editor</string>
</property>
<property name="whatsThis">
<string>When dragging fields or tables, drop just the names into the editor</string>
</property>
</action>
<action name="actionDropInsertCheck">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Drag &amp;&amp; Drop INSERT Statement</string>
</property>
<property name="statusTip">
<string>When dragging fields from the same table or a single table, drop an INSERT statement into the editor</string>
</property>
<property name="whatsThis">
<string>When dragging fields from the same table or a single table, drop an INSERT statement into the editor</string>
</property>
</action>
<action name="actionDropQualifiedCheck">
<property name="checkable">
<bool>true</bool>
Expand Down
3 changes: 3 additions & 0 deletions src/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,9 @@ QVariant Settings::getDefaultValue(const std::string& group, const std::string&
if(name == "dropSelectQuery")
return true;

if(name == "dropInsert")
return false;

if(name == "dropQualifiedNames")
return false;

Expand Down

0 comments on commit ff830e7

Please sign in to comment.