summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/guiSQLiteStudio/dbtree
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/dbtree')
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.cpp232
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.h23
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.cpp36
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.h1
4 files changed, 240 insertions, 52 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.cpp b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.cpp
index 62d7368..fbe0a38 100644
--- a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.cpp
+++ b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.cpp
@@ -24,6 +24,9 @@
#include "services/importmanager.h"
#include "windows/editorwindow.h"
#include "uiconfig.h"
+#include "themetuner.h"
+#include "dialogs/dbconverterdialog.h"
+#include "querygenerator.h"
#include <QApplication>
#include <QClipboard>
#include <QAction>
@@ -34,8 +37,7 @@
#include <QDebug>
#include <QKeyEvent>
#include <QMimeData>
-#include <themetuner.h>
-#include <dialogs/dbconverterdialog.h>
+#include <QDebug>
CFG_KEYS_DEFINE(DbTree)
QHash<DbTreeItem::Type,QList<DbTreeItem::Type>> DbTree::allowedTypesInside;
@@ -140,6 +142,10 @@ void DbTree::createActions()
createAction(REFRESH_SCHEMAS, ICONS.DATABASE_RELOAD, tr("Refresh all database schemas"), this, SLOT(refreshSchemas()), this);
createAction(REFRESH_SCHEMA, ICONS.DATABASE_RELOAD, tr("Refresh selected database schema"), this, SLOT(refreshSchema()), this);
createAction(ERASE_TABLE_DATA, ICONS.ERASE_TABLE_DATA, tr("Erase table data"), this, SLOT(eraseTableData()), this);
+ createAction(GENERATE_SELECT, "SELECT", this, SLOT(generateSelectForTable()), this);
+ createAction(GENERATE_INSERT, "INSERT", this, SLOT(generateInsertForTable()), this);
+ createAction(GENERATE_UPDATE, "UPDATE", this, SLOT(generateUpdateForTable()), this);
+ createAction(GENERATE_DELETE, "DELETE", this, SLOT(generateDeleteForTable()), this);
}
void DbTree::updateActionStates(const QStandardItem *item)
@@ -194,6 +200,7 @@ void DbTree::updateActionStates(const QStandardItem *item)
case DbTreeItem::Type::TABLE:
enabled << EDIT_TABLE << DEL_TABLE << EXPORT_TABLE << IMPORT_TABLE << POPULATE_TABLE << ADD_COLUMN << CREATE_SIMILAR_TABLE;
enabled << RESET_AUTOINCREMENT << ADD_INDEX << ADD_TRIGGER << ERASE_TABLE_DATA;
+ enabled << GENERATE_SELECT << GENERATE_INSERT << GENERATE_UPDATE << GENERATE_DELETE;
break;
case DbTreeItem::Type::VIRTUAL_TABLE:
// TODO change below when virtual tables can be edited
@@ -329,6 +336,12 @@ void DbTree::setupActionsForMenu(DbTreeItem* currItem, QMenu* contextMenu)
groupEntry += RENAME_GROUP;
groupEntry += DELETE_GROUP;
+ ActionEntry genQueryEntry(ICONS.GENERATE_QUERY, tr("Generate query for table"));
+ genQueryEntry += GENERATE_SELECT;
+ genQueryEntry += GENERATE_INSERT;
+ genQueryEntry += GENERATE_UPDATE;
+ genQueryEntry += GENERATE_DELETE;
+
if (currItem)
{
DbTreeItem* parentItem = currItem->parentDbTreeItem();
@@ -392,6 +405,7 @@ void DbTree::setupActionsForMenu(DbTreeItem* currItem, QMenu* contextMenu)
actions += ActionEntry(ADD_INDEX);
actions += ActionEntry(ADD_TRIGGER);
actions += ActionEntry(_separator);
+ actions += genQueryEntry;
actions += ActionEntry(IMPORT_TABLE);
actions += ActionEntry(EXPORT_TABLE);
actions += ActionEntry(POPULATE_TABLE);
@@ -635,11 +649,13 @@ bool DbTree::areDbTreeItemsValidForItem(QList<DbTreeItem*> srcItems, const DbTre
for (DbTreeItem* srcItem : srcItems)
{
- if (srcItem)
- srcTypes << srcItem->getType();
- else
+ if (!srcItem)
+ {
srcTypes << DbTreeItem::Type::ITEM_PROTOTYPE;
+ continue;
+ }
+ srcTypes << srcItem->getType();
if (srcItem->getDb())
srcDbs << srcItem->getDb();
}
@@ -653,6 +669,18 @@ bool DbTree::areDbTreeItemsValidForItem(QList<DbTreeItem*> srcItems, const DbTre
return false;
}
+ // Support for d&d reordering of db objects
+ static const QHash<DbTreeItem::Type, DbTreeItem::Type> reorderingTypeToParent = {
+ {DbTreeItem::Type::TABLE, DbTreeItem::Type::TABLES},
+ {DbTreeItem::Type::TRIGGER, DbTreeItem::Type::TRIGGERS},
+ {DbTreeItem::Type::VIEW, DbTreeItem::Type::VIEWS},
+ {DbTreeItem::Type::INDEX, DbTreeItem::Type::INDEXES}
+ };
+
+ if (srcTypes.toSet().size() == 1 && srcDbs.size() == 1 && dstItem && *(srcDbs.begin()) == dstItem->getDb() && reorderingTypeToParent[srcTypes.first()] == dstType)
+ return true;
+
+ // No other d&d within same db
if (dstItem && dstItem->getDb() && srcDbs.contains(dstItem->getDb()))
return false;
@@ -706,6 +734,16 @@ Db* DbTree::getSelectedDb()
return item->getDb();
}
+QSet<Db*> DbTree::getSelectedDatabases()
+{
+ QList<DbTreeItem*> items = ui->treeView->selectionItems();
+ QSet<Db*> dbList;
+ for (DbTreeItem* item : items)
+ dbList << item->getDb();
+
+ return dbList;
+}
+
Db* DbTree::getSelectedOpenDb()
{
Db* db = getSelectedDb();
@@ -872,6 +910,72 @@ void DbTree::deleteItem(DbTreeItem* item)
}
}
+void DbTree::deleteSelected(DbTreeItem::Type itemType)
+{
+ deleteSelected([itemType](DbTreeItem* item)
+ {
+ return item->getType() == itemType;
+ });
+}
+
+QHash<Db*, QList<DbTreeItem*>> DbTree::groupByDb(const QList<DbTreeItem*> items)
+{
+ QHash<Db*, QList<DbTreeItem*>> grouped;
+ for (DbTreeItem* item : items)
+ grouped[item->getDb()] << item;
+
+ return grouped;
+}
+
+QStringList DbTree::itemsToNames(const QList<DbTreeItem*>& items)
+{
+ QStringList names;
+ for (DbTreeItem* item : items)
+ names << item->text();
+
+ return names;
+}
+
+QString DbTree::getSelectedTableName() const
+{
+ DbTreeItem* item = ui->treeView->currentItem();
+ QString table = item->getTable();
+ if (table.isNull())
+ return QString();
+
+ return table;
+}
+
+QString DbTree::getSelectedIndexName() const
+{
+ DbTreeItem* item = ui->treeView->currentItem();
+ QString idx = item->getIndex();
+ if (idx.isNull())
+ return QString();
+
+ return idx;
+}
+
+QString DbTree::getSelectedTriggerName() const
+{
+ DbTreeItem* item = ui->treeView->currentItem();
+ QString trig = item->getTrigger();
+ if (trig.isNull())
+ return QString();
+
+ return trig;
+}
+
+QString DbTree::getSelectedViewName() const
+{
+ DbTreeItem* item = ui->treeView->currentItem();
+ QString view= item->getView();
+ if (view.isNull())
+ return QString();
+
+ return view;
+}
+
void DbTree::refreshSchema(Db* db)
{
@@ -1012,15 +1116,29 @@ void DbTree::editDb()
void DbTree::removeDb()
{
- Db* db = getSelectedDb();
- if (!db)
+ QList<Db*> dbList = getSelectedDatabases().toList();
+ if (dbList.isEmpty())
return;
- QMessageBox::StandardButton result = QMessageBox::question(this, tr("Delete database"), tr("Are you sure you want to delete database '%1'?").arg(db->getName().left(ITEM_TEXT_LIMIT)));
+ QString msg;
+ if (dbList.size() == 1)
+ {
+ msg = tr("Are you sure you want to remove database '%1' from the list?").arg(dbList.first()->getName().left(ITEM_TEXT_LIMIT));
+ }
+ else
+ {
+ QStringList dbNames;
+ for (Db* db : dbList)
+ dbNames << db->getName().left(ITEM_TEXT_LIMIT);
+
+ msg = tr("Are you sure you want to remove following databases from the list:\n%1").arg(dbNames.join(",\n"));
+ }
+ QMessageBox::StandardButton result = QMessageBox::question(this, tr("Remove database"), msg);
if (result != QMessageBox::Yes)
return;
- DBLIST->removeDb(db);
+ for (Db* db : dbList)
+ DBLIST->removeDb(db);
}
void DbTree::connectToDb()
@@ -1097,8 +1215,7 @@ void DbTree::editTable()
if (!db || !db->isValid())
return;
- DbTreeItem* item = ui->treeView->currentItem();
- QString table = item->getTable();
+ QString table = getSelectedTableName();
if (table.isNull())
{
qWarning() << "Tried to edit table, while table wasn't selected in DbTree.";
@@ -1110,20 +1227,7 @@ void DbTree::editTable()
void DbTree::delTable()
{
- Db* db = getSelectedOpenDb();
- if (!db || !db->isValid())
- return;
-
- DbTreeItem* item = ui->treeView->currentItem();
- QString table = item->getTable();
- if (table.isNull())
- {
- qWarning() << "Tried to drop table, while table wasn't selected in DbTree.";
- return;
- }
-
- DbObjectDialogs dialogs(db);
- dialogs.dropObject(table); // TODO add database prefix when supported
+ deleteSelected(DbTreeItem::Type::TABLE);
}
void DbTree::addIndex()
@@ -1145,8 +1249,7 @@ void DbTree::editIndex()
if (!db || !db->isValid())
return;
- DbTreeItem* item = ui->treeView->currentItem();
- QString index = item->getIndex();
+ QString index = getSelectedIndexName();
DbObjectDialogs dialogs(db);
dialogs.editIndex(index);
@@ -1154,7 +1257,7 @@ void DbTree::editIndex()
void DbTree::delIndex()
{
- delSelectedObject();
+ deleteSelected(DbTreeItem::Type::INDEX);
}
void DbTree::addTrigger()
@@ -1177,8 +1280,7 @@ void DbTree::editTrigger()
if (!db || !db->isValid())
return;
- DbTreeItem* item = ui->treeView->currentItem();
- QString trigger = item->getTrigger();
+ QString trigger = getSelectedTriggerName();
DbObjectDialogs dialogs(db);
dialogs.editTrigger(trigger);
@@ -1186,7 +1288,7 @@ void DbTree::editTrigger()
void DbTree::delTrigger()
{
- delSelectedObject();
+ deleteSelected(DbTreeItem::Type::TRIGGER);
}
void DbTree::addView()
@@ -1205,8 +1307,7 @@ void DbTree::editView()
if (!db || !db->isValid())
return;
- DbTreeItem* item = ui->treeView->currentItem();
- QString view = item->getView();
+ QString view = getSelectedViewName();
if (view.isNull())
{
qWarning() << "Tried to edit view, while view wasn't selected in DbTree.";
@@ -1218,7 +1319,7 @@ void DbTree::editView()
void DbTree::delView()
{
- delSelectedObject();
+ deleteSelected(DbTreeItem::Type::VIEW);
}
void DbTree::exportTable()
@@ -1334,11 +1435,12 @@ void DbTree::vacuumDb()
if (!db || !db->isValid())
return;
- SqlQueryPtr res = db->exec("VACUUM;");
- if (res->isError())
- notifyError(tr("Error while executing VACUUM on the database %1: %2").arg(db->getName(), res->getErrorText()));
- else
- notifyInfo(tr("VACUUM execution finished successfully."));
+ EditorWindow* win = MAINWINDOW->openSqlEditor(db, "VACUUM;");
+ if (!win)
+ return;
+
+ win->getMdiWindow()->rename(tr("Vacuum (%1)").arg(db->getName()));
+ win->execute();
}
void DbTree::integrityCheck()
@@ -1347,16 +1449,11 @@ void DbTree::integrityCheck()
if (!db || !db->isValid())
return;
- EditorWindow* win = MAINWINDOW->openSqlEditor();
- if (!win->setCurrentDb(db))
- {
- qCritical() << "Created EditorWindow had not got requested database:" << db->getName();
- win->close();
+ EditorWindow* win = MAINWINDOW->openSqlEditor(db, "PRAGMA integrity_check;");
+ if (!win)
return;
- }
win->getMdiWindow()->rename(tr("Integrity check (%1)").arg(db->getName()));
- win->setContents("PRAGMA integrity_check;");
win->execute();
}
@@ -1493,12 +1590,19 @@ void DbTree::currentChanged(const QModelIndex &current, const QModelIndex &previ
updateActionStates(treeModel->itemFromIndex(current));
}
-void DbTree::deleteSelected()
+void DbTree::deleteSelected(ItemFilterFunc filterFunc)
{
QModelIndexList idxList = ui->treeView->getSelectedIndexes();
QList<DbTreeItem*> items;
- foreach (const QModelIndex& idx, idxList)
- items << dynamic_cast<DbTreeItem*>(treeModel->itemFromIndex(idx));
+ DbTreeItem* item;
+ for (const QModelIndex& idx : idxList)
+ {
+ item = dynamic_cast<DbTreeItem*>(treeModel->itemFromIndex(idx));
+ if (filterFunc && !filterFunc(item))
+ continue;
+
+ items << item;
+ }
deleteItems(items);
}
@@ -1615,6 +1719,36 @@ void DbTree::refreshFont()
ui->treeView->doItemsLayout();
}
+void DbTree::generateSelectForTable()
+{
+ Db* db = getSelectedDb();
+ QString table = getSelectedTableName();
+
+ QueryGenerator generator;
+ QString sql = generator.generateSelectFromTable(db, table);
+ MAINWINDOW->openSqlEditor(db, sql);
+}
+
+void DbTree::generateInsertForTable()
+{
+ Db* db = getSelectedDb();
+ QString table = getSelectedTableName();
+
+ QueryGenerator generator;
+ QString sql = generator.generateInsertToTable(db, table);
+ MAINWINDOW->openSqlEditor(db, sql);
+}
+
+void DbTree::generateUpdateForTable()
+{
+
+}
+
+void DbTree::generateDeleteForTable()
+{
+
+}
+
void DbTree::setupDefShortcuts()
{
setShortcutContext({
diff --git a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.h b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.h
index 2f5583e..ea415a4 100644
--- a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.h
+++ b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtree.h
@@ -7,6 +7,7 @@
#include "dbtree/dbtreeitem.h"
#include "guiSQLiteStudio_global.h"
#include <QDockWidget>
+#include <QSet>
class WidgetCover;
class QAction;
@@ -85,6 +86,10 @@ class GUI_API_EXPORT DbTree : public QDockWidget, public ExtActionContainer
CREATE_SIMILAR_TABLE,
RESET_AUTOINCREMENT,
ERASE_TABLE_DATA,
+ GENERATE_SELECT,
+ GENERATE_UPDATE,
+ GENERATE_INSERT,
+ GENERATE_DELETE,
_separator // Never use it directly, it's just for menu setup
};
@@ -111,6 +116,7 @@ class GUI_API_EXPORT DbTree : public QDockWidget, public ExtActionContainer
QToolBar* getToolBar(int toolbar) const;
Db* getSelectedDb();
Db* getSelectedOpenDb();
+ QSet<Db*> getSelectedDatabases();
static bool isItemDraggable(const DbTreeItem* item);
@@ -120,6 +126,8 @@ class GUI_API_EXPORT DbTree : public QDockWidget, public ExtActionContainer
void closeEvent(QCloseEvent* e);
private:
+ typedef std::function<bool(DbTreeItem*)> ItemFilterFunc;
+
void setActionEnabled(int action, bool enabled);
TableWindow* openTable(DbTreeItem* item);
TableWindow* openTable(Db* db, const QString& database, const QString& table);
@@ -133,9 +141,16 @@ class GUI_API_EXPORT DbTree : public QDockWidget, public ExtActionContainer
void filterUndeletableItems(QList<DbTreeItem*>& items);
void filterItemsWithParentInList(QList<DbTreeItem*>& items);
void deleteItem(DbTreeItem* item);
+ void deleteSelected(DbTreeItem::Type itemType);
+ QHash<Db*, QList<DbTreeItem*>> groupByDb(const QList<DbTreeItem*> items);
+ QStringList itemsToNames(const QList<DbTreeItem*>& items);
+ QString getSelectedTableName() const;
+ QString getSelectedIndexName() const;
+ QString getSelectedTriggerName() const;
+ QString getSelectedViewName() const;
+
static bool areDbTreeItemsValidForItem(QList<DbTreeItem*> srcItems, const DbTreeItem* dstItem);
static bool areUrlsValidForItem(const QList<QUrl>& srcUrls, const DbTreeItem* dstItem);
-
static void initDndTypes();
Ui::DbTree *ui = nullptr;
@@ -194,13 +209,17 @@ class GUI_API_EXPORT DbTree : public QDockWidget, public ExtActionContainer
void editColumn(DbTreeItem* item);
void delColumn(DbTreeItem* item);
void currentChanged(const QModelIndex & current, const QModelIndex & previous);
- void deleteSelected();
+ void deleteSelected(ItemFilterFunc filterFunc = nullptr);
void deleteItems(const QList<DbTreeItem*>& itemsToDelete);
void refreshSchema();
void dbConnected(Db* db);
void dbDisconnected(Db* db);
void updateDbIcon(Db* db);
void refreshFont();
+ void generateSelectForTable();
+ void generateInsertForTable();
+ void generateUpdateForTable();
+ void generateDeleteForTable();
};
int qHash(DbTree::Action action);
diff --git a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.cpp b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.cpp
index c0f527f..c11221d 100644
--- a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.cpp
+++ b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.cpp
@@ -13,6 +13,7 @@
#include "dialogs/errorsconfirmdialog.h"
#include "dialogs/versionconvertsummarydialog.h"
#include "db/invaliddb.h"
+#include "services/notifymanager.h"
#include <QMimeData>
#include <QDebug>
#include <QFile>
@@ -1040,7 +1041,10 @@ bool DbTreeModel::dropDbTreeItem(const QList<DbTreeItem*>& srcItems, DbTreeItem*
return false;
if (srcItem->getDb() == dstItem->getDb())
+ {
+ invokeStdDropAction = true;
return true;
+ }
return dropDbObjectItem(srcItems, dstItem, defaultAction);
}
@@ -1135,6 +1139,8 @@ QCheckBox* DbTreeModel::createCopyOrMoveMenuCheckBox(QMenu* menu, const QString&
bool DbTreeModel::dropUrls(const QList<QUrl>& urls)
{
+ QString filePath;
+ bool autoTest = false;
for (const QUrl& url : urls)
{
if (!url.isLocalFile())
@@ -1143,13 +1149,41 @@ bool DbTreeModel::dropUrls(const QList<QUrl>& urls)
continue;
}
+ autoTest = false;
+ filePath = url.toLocalFile();
+ if (CFG_UI.General.BypassDbDialogWhenDropped.get())
+ {
+ if (quickAddDroppedDb(filePath))
+ {
+ continue;
+ }
+ else
+ {
+ notifyWarn(tr("Could not add dropped database file '%1' automatically. Manual setup is necessary.").arg(filePath));
+ autoTest = true;
+ }
+ }
+
DbDialog dialog(DbDialog::ADD, MAINWINDOW);
- dialog.setPath(url.toLocalFile());
+ dialog.setPath(filePath);
+ dialog.setDoAutoTest(autoTest);
dialog.exec();
}
return false;
}
+bool DbTreeModel::quickAddDroppedDb(const QString& filePath)
+{
+ DbPlugin* plugin = DBLIST->getPluginForDbFile(filePath);
+ if (!plugin)
+ return false;
+
+ QString name = DBLIST->generateUniqueDbName(plugin, filePath);
+ QHash<QString,QVariant> opts;
+ opts[DB_PLUGIN] = plugin->getName();
+ return DBLIST->addDb(name, filePath, opts, !CFG_UI.General.NewDbNotPermanentByDefault.get());
+}
+
void DbTreeModel::moveOrCopyDbObjects(const QList<DbTreeItem*>& srcItems, DbTreeItem* dstItem, bool move, bool includeData, bool includeIndexes, bool includeTriggers)
{
if (srcItems.size() == 0)
diff --git a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.h b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.h
index ee97e87..122421a 100644
--- a/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.h
+++ b/SQLiteStudio3/guiSQLiteStudio/dbtree/dbtreemodel.h
@@ -85,6 +85,7 @@ class GUI_API_EXPORT DbTreeModel : public QStandardItemModel
bool dropDbObjectItem(const QList<DbTreeItem*>& srcItems, DbTreeItem* dstItem, Qt::DropAction defaultAction);
QCheckBox* createCopyOrMoveMenuCheckBox(QMenu* menu, const QString& label);
bool dropUrls(const QList<QUrl>& urls);
+ bool quickAddDroppedDb(const QString& filePath);
void moveOrCopyDbObjects(const QList<DbTreeItem*>& srcItems, DbTreeItem* dstItem, bool move, bool includeData, bool includeIndexes, bool includeTriggers);
static bool confirmReferencedTables(const QStringList& tables);