Allow users to drag and drop fields from DB Schema dock to editor (#1250)

* Allow users to drag and drop fields from DB Schema dock to editor

This is the first attempt to provide the functionality described in #119.

Drag in the dock is enabled (it was only enabled in the Database Structure
tab). Then the fields are enabled for dragging and finally the MIME data
exported for the drag and drop is tailored for exporting only the escaped
field identifier.

This may interfere to other uses of drag&drop in the Database Structure.

* Allow the user to drag individual items from the DB Schema dock

By allowing extended selections of individual items in the dock version,
we let users select what they want to drag and drop. When dragging a list
of items from the Name column, a list of escaped identifiers with commas is
exported, making easier the composition of SELECT and other statements.

In this way, every item name can be dropped, without loosing the ability
of exporting the SQL statement for the item. It will just depend on which
column is selected.

For the DB Structure tab, the original behaviour of single row selection
is maintained. In that case, only the SQL column is exported, as before.

See issue #119.
This commit is contained in:
Manuel
2018-01-01 20:07:52 +01:00
committed by Martin Kleusberg
parent 27c657902e
commit 106e57eedc
2 changed files with 63 additions and 23 deletions

View File

@@ -66,9 +66,9 @@ Qt::ItemFlags DbStructureModel::flags(const QModelIndex &index) const
// All items are enabled and selectable
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
// Only enable dragging for entire table objects
// Only enable dragging for entire table objects and for fields (composition in SQL text editor)
QString type = data(index.sibling(index.row(), ColumnObjectType), Qt::DisplayRole).toString();
if(type == "table" || type == "view" || type == "index" || type == "trigger")
if(type == "table" || type == "field" || type == "view" || type == "index" || type == "trigger")
flags |= Qt::ItemIsDragEnabled;
return flags;
@@ -190,32 +190,43 @@ QStringList DbStructureModel::mimeTypes() const
QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
{
// We store the SQL data and the names data separately
QByteArray sqlData, namesData;
// Loop through selected indices
QByteArray d;
for(const QModelIndex& index : indices)
{
// Only export data for valid indices and only for the SQL column, i.e. only once per row
if(index.isValid() && index.column() == ColumnSQL)
{
// Add the SQL code used to create the object
d = d.append(data(index, Qt::DisplayRole).toString() + ";\n");
// Only export data for valid indices and only once per row (SQL column or Name column).
// For names, export an escaped identifier of the item for statement composition in SQL editor.
// Commas are included for a list of identifiers.
if(index.isValid()) {
QString objectType = data(index.sibling(index.row(), ColumnObjectType), Qt::DisplayRole).toString();
// If it is a table also add the content
if(data(index.sibling(index.row(), ColumnObjectType), Qt::DisplayRole).toString() == "table")
if(index.column() == ColumnName)
namesData.append(sqlb::escapeIdentifier(data(index, Qt::DisplayRole).toString()) + ", ");
if(objectType != "field" && index.column() == ColumnSQL)
{
SqliteTableModel tableModel(m_db);
sqlb::ObjectIdentifier objid(data(index.sibling(index.row(), ColumnSchema), Qt::DisplayRole).toString(),
data(index.sibling(index.row(), ColumnName), Qt::DisplayRole).toString());
tableModel.setTable(objid);
tableModel.waitForFetchingFinished();
for(int i=0; i < tableModel.rowCount(); ++i)
// Add the SQL code used to create the object
sqlData.append(data(index, Qt::DisplayRole).toString() + ";\n");
// If it is a table also add the content
if(objectType == "table")
{
QString insertStatement = "INSERT INTO " + objid.toString() + " VALUES(";
for(int j=1; j < tableModel.columnCount(); ++j)
insertStatement += QString("'%1',").arg(tableModel.data(tableModel.index(i, j)).toString());
insertStatement.chop(1);
insertStatement += ");\n";
d = d.append(insertStatement);
SqliteTableModel tableModel(m_db);
sqlb::ObjectIdentifier objid(data(index.sibling(index.row(), ColumnSchema), Qt::DisplayRole).toString(),
data(index.sibling(index.row(), ColumnName), Qt::DisplayRole).toString());
tableModel.setTable(objid);
tableModel.waitForFetchingFinished();
for(int i=0; i < tableModel.rowCount(); ++i)
{
QString insertStatement = "INSERT INTO " + objid.toString() + " VALUES(";
for(int j=1; j < tableModel.columnCount(); ++j)
insertStatement += QString("'%1',").arg(tableModel.data(tableModel.index(i, j)).toString());
insertStatement.chop(1);
insertStatement += ");\n";
sqlData.append(insertStatement);
}
}
}
}
@@ -224,7 +235,13 @@ QMimeData* DbStructureModel::mimeData(const QModelIndexList& indices) const
// Create the MIME data object
QMimeData* mime = new QMimeData();
mime->setProperty("db_file", m_db.currentFile()); // Also save the file name to avoid dropping an object on the same database as it comes from
mime->setData("text/plain", d);
// When we have both SQL and Names data (probable row selection mode) we give precedence to the SQL data
if (sqlData.length() == 0 && namesData.length() > 0) {
// Remove last ", "
namesData.chop(2);
mime->setData("text/plain", namesData);
} else
mime->setData("text/plain", sqlData);
return mime;
}

View File

@@ -63,6 +63,11 @@
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="whatsThis">
<string>This is the structure of the opened database.
You can drag SQL sentences from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'.
</string>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
@@ -1119,9 +1124,27 @@
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QTreeView" name="treeSchemaDock">
<property name="whatsThis">
<string>This is the structure of the opened database.
You can drag multiple object names from the Name column and drop them into the SQL editor .
You can drag SQL sentences from the Schema column and drop them into the SQL editor or into other applications.
</string>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>