Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save current filter, sort column and display formats as a new view #1246

Merged
merged 3 commits into from
Dec 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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