Skip to content

Commit

Permalink
Merge pull request #1246 from sqlitebrowser/save_filter_as_view
Browse files Browse the repository at this point in the history
Save current filter, sort column and display formats as a new view
  • Loading branch information
mgrojo authored Dec 1, 2017
2 parents e79c5db + 5da3d14 commit 882fc8d
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 37 deletions.
34 changes: 33 additions & 1 deletion src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,7 @@ void MainWindow::saveSqlResultsAsCsv()

void MainWindow::saveSqlResultsAsView()
{
qobject_cast<SqlExecutionArea*>(ui->tabSqlAreas->currentWidget())->saveAsView();
saveAsView(qobject_cast<SqlExecutionArea*>(ui->tabSqlAreas->currentWidget())->getModel()->query());
}

void MainWindow::loadExtension()
Expand Down Expand Up @@ -2719,3 +2719,35 @@ void MainWindow::openFindReplaceDialog()
findReplaceDialog->show();
}
}

void MainWindow::saveAsView(QString query)
{
// Let the user select a name for the new view and make sure it doesn't already exist
QString name;
while(true)
{
name = QInputDialog::getText(this, qApp->applicationName(), tr("Please specify the view name")).trimmed();
if(name.isNull())
return;
if(db.getObjectByName(sqlb::ObjectIdentifier("main", name)) != nullptr)
QMessageBox::warning(this, qApp->applicationName(), tr("There is already an object with that name. Please choose a different name."));
else
break;
}

// Create the view
if(db.executeSQL(QString("CREATE VIEW %1 AS %2;").arg(sqlb::escapeIdentifier(name)).arg(query)))
QMessageBox::information(this, qApp->applicationName(), tr("View successfully created."));
else
QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db.lastError()));
}


void MainWindow::saveFilterAsView()
{
if (m_browseTableModel->filterCount() > 0)
// Save as view a custom query without rowid
saveAsView(m_browseTableModel->customQuery(false));
else
QMessageBox::information(this, qApp->applicationName(), tr("There is no filter set for this table. View will not be created."));
}
2 changes: 2 additions & 0 deletions src/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class MainWindow : public QMainWindow
void activateFields(bool enable = true);
void enableEditing(bool enable_edit, bool enable_insertdelete);
void loadExtensionsFromSettings();
void saveAsView(QString query);

sqlb::ObjectIdentifier currentlyBrowsedTableName() const;

Expand Down Expand Up @@ -291,6 +292,7 @@ private slots:
void renameSqlTab(int index);
void setFindFrameVisibility(bool show);
void openFindReplaceDialog();
void saveFilterAsView();
};

#endif
30 changes: 30 additions & 0 deletions src/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonSaveFilterAsView">
<property name="toolTip">
<string>Save the current filter as a view</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="icons/icons.qrc">
<normaloff>:/icons/save_table</normaloff>:/icons/save_table</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
Expand Down Expand Up @@ -3021,6 +3035,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonSaveFilterAsView</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>saveFilterAsView()</slot>
<hints>
<hint type="sourcelabel">
<x>290</x>
<y>127</y>
</hint>
<hint type="destinationlabel">
<x>518</x>
<y>314</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>fileOpen()</slot>
Expand Down
22 changes: 0 additions & 22 deletions src/SqlExecutionArea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,6 @@ void SqlExecutionArea::saveAsCsv()
dialog.exec();
}

void SqlExecutionArea::saveAsView()
{
// Let the user select a name for the new view and make sure it doesn't already exist
QString name;
while(true)
{
name = QInputDialog::getText(this, qApp->applicationName(), tr("Please specify the view name")).trimmed();
if(name.isEmpty())
return;
if(db.getObjectByName(sqlb::ObjectIdentifier("main", name)) != nullptr)
QMessageBox::warning(this, qApp->applicationName(), tr("There is already an object with that name. Please choose a different name."));
else
break;
}

// Create the view
if(db.executeSQL(QString("CREATE VIEW %1 AS %2;").arg(sqlb::escapeIdentifier(name)).arg(model->query())))
QMessageBox::information(this, qApp->applicationName(), tr("View successfully created."));
else
QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db.lastError()));
}

void SqlExecutionArea::reloadSettings()
{
// Reload editor and table settings
Expand Down
1 change: 0 additions & 1 deletion src/SqlExecutionArea.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class SqlExecutionArea : public QWidget
public slots:
virtual void finishExecution(const QString& result, const bool ok);
virtual void saveAsCsv();
virtual void saveAsView();
virtual void reloadSettings();
void fetchedData();
void setFindFrameVisibility(bool show);
Expand Down
41 changes: 28 additions & 13 deletions src/sqlitetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ int SqliteTableModel::columnCount(const QModelIndex&) const
return m_headers.size();
}

int SqliteTableModel::filterCount() const
{
return m_mWhere.size();
}

QVariant SqliteTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
Expand Down Expand Up @@ -590,7 +595,7 @@ void SqliteTableModel::fetchData(unsigned int from, unsigned to)
});
}

void SqliteTableModel::buildQuery()
QString SqliteTableModel::customQuery(bool withRowid)
{
QString where;

Expand All @@ -600,41 +605,51 @@ void SqliteTableModel::buildQuery()

for(QMap<int, QString>::const_iterator i=m_mWhere.constBegin();i!=m_mWhere.constEnd();++i)
{
QString column;
if(m_vDisplayFormat.size())
column = QString("col%1").arg(i.key());
else
column = m_headers.at(i.key());
where.append(QString("%1 %2 AND ").arg(sqlb::escapeIdentifier(column)).arg(i.value()));
QString columnId = sqlb::escapeIdentifier(m_headers.at(i.key()));
if(m_vDisplayFormat.size() && m_vDisplayFormat.at(i.key()-1) != columnId)
columnId = sqlb::escapeIdentifier(m_headers.at(i.key()) + "_");
where.append(QString("%1 %2 AND ").arg(columnId).arg(i.value()));
}

// Remove last 'AND '
where.chop(4);
}

QString selector;
if (withRowid)
selector = sqlb::escapeIdentifier(m_headers.at(0)) + ",";

if(m_vDisplayFormat.empty())
{
selector = "*";
selector += "*";
} else {
for(int i=0;i<m_vDisplayFormat.size();i++)
selector += m_vDisplayFormat.at(i) + " AS " + QString("col%1").arg(i+1) + ",";
QString columnId;
for(int i=0;i<m_vDisplayFormat.size();i++) {
columnId = sqlb::escapeIdentifier(m_headers.at(i+1));
if (columnId != m_vDisplayFormat.at(i))
selector += m_vDisplayFormat.at(i) + " AS " + sqlb::escapeIdentifier(m_headers.at(i+1) + "_") + ",";
else
selector += columnId + ",";
}
selector.chop(1);
}

// Note: Building the SQL string is intentionally split into several parts here instead of arg()'ing it all together as one.
// The reason is that we're adding '%' characters automatically around search terms (and even if we didn't the user could add
// them manually) which means that e.g. searching for '1' results in another '%1' in the string which then totally confuses
// the QString::arg() function, resulting in an invalid SQL.
QString sql = QString("SELECT %1,%2 FROM %3 ")
.arg(sqlb::escapeIdentifier(m_headers.at(0)))
return QString("SELECT %1 FROM %2 ")
.arg(selector)
.arg(m_sTable.toString())
+ where
+ QString("ORDER BY %1 %2")
.arg(sqlb::escapeIdentifier(m_headers.at(m_iSortColumn)))
.arg(m_sSortOrder);
setQuery(sql, true);
}

void SqliteTableModel::buildQuery()
{
setQuery(customQuery(true), true);
}

void SqliteTableModel::removeCommentsFromQuery(QString& query) {
Expand Down
2 changes: 2 additions & 0 deletions src/sqlitetablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class SqliteTableModel : public QAbstractTableModel
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int totalRowCount() const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
int filterCount() const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
Expand All @@ -40,6 +41,7 @@ class SqliteTableModel : public QAbstractTableModel

void setQuery(const QString& sQuery, bool dontClearHeaders = false);
QString query() const { return m_sQuery; }
QString customQuery(bool withRowid);
void setTable(const sqlb::ObjectIdentifier& table, int sortColumn = 0, Qt::SortOrder sortOrder = Qt::AscendingOrder, const QVector<QString> &display_format = QVector<QString>());
void setChunkSize(size_t chunksize);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
Expand Down

0 comments on commit 882fc8d

Please sign in to comment.