summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp')
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp590
1 files changed, 590 insertions, 0 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp
new file mode 100644
index 0000000..c9a7f28
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp
@@ -0,0 +1,590 @@
+#include "dbdialog.h"
+#include "ui_dbdialog.h"
+#include "services/pluginmanager.h"
+#include "plugins/dbplugin.h"
+#include "uiutils.h"
+#include "common/utils.h"
+#include "uiconfig.h"
+#include "services/dbmanager.h"
+#include "common/global.h"
+#include "iconmanager.h"
+#include "common/unused.h"
+#include <QDateTimeEdit>
+#include <QSpinBox>
+#include <QDebug>
+#include <QPushButton>
+#include <QFileDialog>
+#include <QComboBox>
+
+DbDialog::DbDialog(Mode mode, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::DbDialog),
+ mode(mode)
+{
+ init();
+}
+
+DbDialog::~DbDialog()
+{
+ delete ui;
+}
+
+void DbDialog::setDb(Db* db)
+{
+ this->db = db;
+}
+
+void DbDialog::setPermanent(bool perm)
+{
+ ui->permamentCheckBox->setChecked(perm);
+}
+
+QString DbDialog::getPath()
+{
+ return ui->fileEdit->text();
+}
+
+void DbDialog::setPath(const QString& path)
+{
+ ui->fileEdit->setText(path);
+}
+
+QString DbDialog::getName()
+{
+ return ui->nameEdit->text();
+}
+
+Db* DbDialog::getDb()
+{
+ if (ui->typeCombo->currentIndex() < 0)
+ return nullptr;
+
+ Db* testDb = nullptr;
+ QHash<QString, QVariant> options = collectOptions();
+ QString path = ui->fileEdit->text();
+ foreach (DbPlugin* plugin, dbPlugins)
+ {
+ if (options.contains(DB_PLUGIN) && options[DB_PLUGIN].toString() != plugin->getName())
+ continue;
+
+ testDb = plugin->getInstance("", path, options);
+ if (testDb)
+ return testDb;
+ }
+ return testDb;
+}
+
+bool DbDialog::isPermanent()
+{
+ return ui->permamentCheckBox->isChecked();
+}
+
+void DbDialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void DbDialog::showEvent(QShowEvent *e)
+{
+ if (db)
+ {
+ int idx = ui->typeCombo->findText(db->getTypeLabel());
+ ui->typeCombo->setCurrentIndex(idx);
+ ui->typeCombo->setEnabled(false); // converting to other type is in separate dialog, it's different feature
+
+ ui->generateCheckBox->setChecked(false);
+ ui->fileEdit->setText(db->getPath());
+ ui->nameEdit->setText(db->getName());
+ }
+ else if (ui->typeCombo->count() > 0)
+ {
+ int idx = ui->typeCombo->findText("SQLite3"); // we should have SQLite3 plugin
+ if (idx > -1)
+ ui->typeCombo->setCurrentIndex(idx);
+ else
+ ui->typeCombo->setCurrentIndex(0);
+ }
+
+ existingDatabaseNames = DBLIST->getDbNames();
+ if (mode == EDIT)
+ existingDatabaseNames.removeOne(db->getName());
+
+ updateOptions();
+ updateState();
+
+ QDialog::showEvent(e);
+}
+
+void DbDialog::init()
+{
+ ui->setupUi(this);
+
+ ui->browseButton->setIcon(ICONS.DATABASE_FILE);
+ dbPlugins = PLUGINS->getLoadedPlugins<DbPlugin>();
+ foreach (DbPlugin* dbPlugin, dbPlugins)
+ {
+ ui->typeCombo->addItem(dbPlugin->getLabel());
+ }
+
+ ui->browseButton->setVisible(true);
+ ui->testConnIcon->setVisible(false);
+
+ connect(ui->fileEdit, SIGNAL(textChanged(QString)), this, SLOT(fileChanged(QString)));
+ connect(ui->nameEdit, SIGNAL(textChanged(QString)), this, SLOT(nameModified(QString)));
+ connect(ui->generateCheckBox, SIGNAL(toggled(bool)), this, SLOT(generateNameSwitched(bool)));
+ connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseClicked()));
+ connect(ui->testConnButton, SIGNAL(clicked()), this, SLOT(testConnectionClicked()));
+ connect(ui->typeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(dbTypeChanged(int)));
+
+ generateNameSwitched(true);
+}
+
+void DbDialog::updateOptions()
+{
+ setUpdatesEnabled(false);
+
+ // Remove olds
+ foreach (QWidget* w, optionWidgets)
+ {
+ ui->gridLayout->removeWidget(w);
+ delete w;
+ }
+ adjustSize();
+
+ optionWidgets.clear();
+ optionKeyToWidget.clear();
+ optionKeyToType.clear();
+ helperToKey.clear();
+
+ lastWidgetInTabOrder = ui->permamentCheckBox;
+
+ // Retrieve new list
+ DbPlugin* plugin = nullptr;
+ if (dbPlugins.count() > 0)
+ {
+ int idx = ui->typeCombo->currentIndex();
+ if (idx > -1 )
+ {
+ plugin = dbPlugins[idx];
+ QList<DbPluginOption> optList = plugin->getOptionsList();
+ if (optList.size() > 0)
+ {
+ // Add new options
+ int row = ADDITIONAL_ROWS_BEGIN_INDEX;
+ foreach (DbPluginOption opt, optList)
+ addOption(opt, row++);
+ }
+ }
+ }
+
+ adjustSize();
+ setUpdatesEnabled(true);
+}
+
+void DbDialog::addOption(const DbPluginOption& option, int row)
+{
+ QLabel* label = new QLabel(option.label, this);
+ QWidget* editor = nullptr;
+ QWidget* editorHelper = nullptr; // TODO, based on plugins for Url handlers
+
+ editor = getEditor(option, editorHelper);
+ Q_ASSERT(editor != nullptr);
+
+ if (!option.toolTip.isNull())
+ editor->setToolTip(option.toolTip);
+
+ optionWidgets << label << editor;
+
+ optionKeyToWidget[option.key] = editor;
+ optionKeyToType[option.key] = option.type;
+ ui->gridLayout->addWidget(label, row, 0);
+ ui->gridLayout->addWidget(editor, row, 1);
+
+ setTabOrder(lastWidgetInTabOrder, editor);
+ lastWidgetInTabOrder = editor;
+
+ if (editorHelper)
+ {
+ ui->gridLayout->addWidget(editorHelper, row, 2);
+ optionWidgets << editorHelper;
+ helperToKey[editorHelper] = option.key;
+
+ setTabOrder(lastWidgetInTabOrder, editorHelper);
+ lastWidgetInTabOrder = editorHelper;
+ }
+
+ if (db && db->getConnectionOptions().contains(option.key))
+ setValueFor(option.type, editor, db->getConnectionOptions()[option.key]);
+}
+
+QWidget *DbDialog::getEditor(const DbPluginOption& opt, QWidget*& editorHelper)
+{
+ QWidget* editor = nullptr;
+ QLineEdit* le = nullptr;
+ editorHelper = nullptr;
+ switch (opt.type)
+ {
+ case DbPluginOption::STRING:
+ {
+ editor = new QLineEdit(this);
+ le = dynamic_cast<QLineEdit*>(editor);
+ connect(le, SIGNAL(textChanged(QString)), this, SLOT(propertyChanged()));
+ break;
+ }
+ case DbPluginOption::PASSWORD:
+ {
+ editor = new QLineEdit(this);
+ le = dynamic_cast<QLineEdit*>(editor);
+ le->setEchoMode(QLineEdit::Password);
+ connect(le, SIGNAL(textChanged(QString)), this, SLOT(propertyChanged()));
+ break;
+ }
+ case DbPluginOption::CHOICE:
+ {
+ QComboBox* cb = new QComboBox(this);
+ editor = cb;
+ cb->setEditable(!opt.choiceReadOnly);
+ cb->addItems(opt.choiceValues);
+ cb->setCurrentText(opt.defaultValue.toString());
+ connect(cb, SIGNAL(currentIndexChanged(QString)), this, SLOT(propertyChanged()));
+ break;
+ }
+ case DbPluginOption::INT:
+ {
+ QSpinBox* sb = new QSpinBox(this);
+ editor = sb;
+ if (!opt.minValue.isNull())
+ sb->setMinimum(opt.minValue.toInt());
+
+ if (!opt.maxValue.isNull())
+ sb->setMaximum(opt.maxValue.toInt());
+
+ if (!opt.defaultValue.isNull())
+ sb->setValue(opt.defaultValue.toInt());
+
+ connect(sb, SIGNAL(valueChanged(int)), this, SLOT(propertyChanged()));
+ break;
+ }
+ case DbPluginOption::FILE:
+ {
+ editor = new QLineEdit(this);
+ le = dynamic_cast<QLineEdit*>(editor);
+ editorHelper = new QPushButton(tr("Browse"), this);
+ connect(le, SIGNAL(textChanged(QString)), this, SLOT(propertyChanged()));
+ connect(editorHelper, SIGNAL(pressed()), this, SLOT(browseForFile()));
+ break;
+ }
+ case DbPluginOption::BOOL:
+ {
+ QCheckBox* cb = new QCheckBox(this);
+ editor = cb;
+ if (!opt.defaultValue.isNull())
+ cb->setChecked(opt.defaultValue.toBool());
+
+ connect(cb, SIGNAL(stateChanged(int)), this, SLOT(propertyChanged()));
+ break;
+ }
+ case DbPluginOption::DOUBLE:
+ {
+ QDoubleSpinBox* sb = new QDoubleSpinBox(this);
+ editor = sb;
+ if (!opt.minValue.isNull())
+ sb->setMinimum(opt.minValue.toDouble());
+
+ if (!opt.maxValue.isNull())
+ sb->setMaximum(opt.maxValue.toDouble());
+
+ if (!opt.defaultValue.isNull())
+ sb->setValue(opt.defaultValue.toDouble());
+
+ connect(sb, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged()));
+ break;
+ }
+ default:
+ // TODO plugin based handling of custom editors
+ qWarning() << "Unhandled DbDialog option for creating editor.";
+ break;
+ }
+
+ if (le)
+ {
+ le->setPlaceholderText(opt.placeholderText);
+ le->setText(opt.defaultValue.toString());
+ }
+
+ return editor;
+}
+
+QVariant DbDialog::getValueFrom(DbPluginOption::Type type, QWidget *editor)
+{
+ QVariant value;
+ switch (type)
+ {
+ case DbPluginOption::STRING:
+ case DbPluginOption::PASSWORD:
+ case DbPluginOption::FILE:
+ value = dynamic_cast<QLineEdit*>(editor)->text();
+ break;
+ case DbPluginOption::INT:
+ value = dynamic_cast<QSpinBox*>(editor)->value();
+ break;
+ case DbPluginOption::BOOL:
+ value = dynamic_cast<QCheckBox*>(editor)->isChecked();
+ break;
+ case DbPluginOption::DOUBLE:
+ value = dynamic_cast<QDoubleSpinBox*>(editor)->value();
+ break;
+ case DbPluginOption::CHOICE:
+ value = dynamic_cast<QComboBox*>(editor)->currentText();
+ break;
+ default:
+ // TODO plugin based handling of custom editors
+ qWarning() << "Unhandled DbDialog option for value.";
+ break;
+ }
+ return value;
+}
+
+void DbDialog::setValueFor(DbPluginOption::Type type, QWidget *editor, const QVariant &value)
+{
+ switch (type)
+ {
+ case DbPluginOption::STRING:
+ case DbPluginOption::FILE:
+ case DbPluginOption::PASSWORD:
+ dynamic_cast<QLineEdit*>(editor)->setText(value.toString());
+ break;
+ case DbPluginOption::INT:
+ dynamic_cast<QSpinBox*>(editor)->setValue(value.toInt());
+ break;
+ case DbPluginOption::BOOL:
+ dynamic_cast<QCheckBox*>(editor)->setChecked(value.toBool());
+ break;
+ case DbPluginOption::DOUBLE:
+ dynamic_cast<QDoubleSpinBox*>(editor)->setValue(value.toDouble());
+ break;
+ case DbPluginOption::CHOICE:
+ dynamic_cast<QComboBox*>(editor)->setCurrentText(value.toString());
+ break;
+ default:
+ qWarning() << "Unhandled DbDialog option to set value.";
+ // TODO plugin based handling of custom editors
+ break;
+ }
+}
+
+void DbDialog::updateType()
+{
+ QFileInfo file(ui->fileEdit->text());
+ if (!file.exists() || file.isDir())
+ {
+ ui->typeCombo->setEnabled(true);
+ return;
+ }
+
+ DbPlugin* validPlugin = nullptr;
+ QHash<QString,QVariant> options;
+ QString path = ui->fileEdit->text();
+ Db* probeDb = nullptr;
+ foreach (DbPlugin* plugin, dbPlugins)
+ {
+ probeDb = plugin->getInstance("", path, options);
+ if (probeDb)
+ {
+ delete probeDb;
+ probeDb = nullptr;
+
+ validPlugin = plugin;
+ break;
+ }
+ }
+
+ if (validPlugin)
+ ui->typeCombo->setCurrentText(validPlugin->getLabel());
+
+ ui->typeCombo->setEnabled(!validPlugin);
+}
+
+QHash<QString, QVariant> DbDialog::collectOptions()
+{
+ QHash<QString, QVariant> options;
+ if (ui->typeCombo->currentIndex() < 0)
+ return options;
+
+ for (const QString key : optionKeyToWidget.keys())
+ options[key] = getValueFrom(optionKeyToType[key], optionKeyToWidget[key]);
+
+ DbPlugin* plugin = nullptr;
+ if (dbPlugins.count() > 0)
+ {
+ plugin = dbPlugins[ui->typeCombo->currentIndex()];
+ options[DB_PLUGIN] = plugin->getName();
+ }
+
+ return options;
+}
+
+bool DbDialog::testDatabase()
+{
+ QString path = ui->fileEdit->text();
+ bool existed = QFile::exists(path);
+ bool res = getDb() != nullptr;
+ if (!existed)
+ {
+ QFile file(path);
+ file.remove();
+ }
+ return res;
+}
+
+bool DbDialog::validate()
+{
+ if (ui->fileEdit->text().isEmpty())
+ return false;
+
+ if (ui->nameEdit->text().isEmpty())
+ return false;
+
+ if (ui->typeCombo->count() == 0)
+ return false;
+
+ if (ui->typeCombo->currentIndex() < 0)
+ return false;
+
+ return true;
+}
+
+void DbDialog::updateState()
+{
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(validate());
+}
+
+void DbDialog::propertyChanged()
+{
+ ui->testConnIcon->setVisible(false);
+}
+
+void DbDialog::typeChanged(int index)
+{
+ UNUSED(index);
+ updateOptions();
+ updateState();
+}
+
+void DbDialog::valueForNameGenerationChanged()
+{
+ if (!ui->generateCheckBox->isChecked())
+ {
+ updateState();
+ return;
+ }
+
+ DbPlugin* plugin = nullptr;
+ if (dbPlugins.count() > 0)
+ {
+ plugin = dbPlugins[ui->typeCombo->currentIndex()];
+ QString generatedName = plugin->generateDbName(ui->fileEdit->text());
+ generatedName = generateUniqueName(generatedName, existingDatabaseNames);
+ ui->nameEdit->setText(generatedName);
+ }
+}
+
+void DbDialog::browseForFile()
+{
+ QString dir = getFileDialogInitPath();
+ QString path = QFileDialog::getOpenFileName(0, QString(), dir);
+ if (path.isNull())
+ return;
+
+ QString key = helperToKey[dynamic_cast<QWidget*>(sender())];
+ setValueFor(optionKeyToType[key], optionKeyToWidget[key], path);
+
+ setFileDialogInitPathByFile(path);
+}
+
+void DbDialog::generateNameSwitched(bool checked)
+{
+ if (checked)
+ {
+ ui->nameEdit->setPlaceholderText(tr("The name will be auto-generated"));
+ valueForNameGenerationChanged();
+ }
+ else
+ {
+ ui->nameEdit->setPlaceholderText(tr("Type the name"));
+ }
+
+ ui->nameEdit->setReadOnly(checked);
+}
+
+void DbDialog::fileChanged(const QString &arg1)
+{
+ UNUSED(arg1);
+ valueForNameGenerationChanged();
+ updateType();
+ propertyChanged();
+}
+
+void DbDialog::browseClicked()
+{
+ QFileInfo fileInfo(ui->fileEdit->text());
+ QString dir;
+ if (ui->fileEdit->text().isEmpty())
+ dir = getFileDialogInitPath();
+ else if (fileInfo.exists() && fileInfo.isFile())
+ dir = fileInfo.absolutePath();
+ else if (fileInfo.dir().exists())
+ dir = fileInfo.dir().absolutePath();
+ else
+ dir = getFileDialogInitPath();
+
+ QString path = getDbPath(dir);
+ if (path.isNull())
+ return;
+
+ setFileDialogInitPathByFile(path);
+
+ ui->fileEdit->setText(path);
+ updateState();
+}
+
+void DbDialog::testConnectionClicked()
+{
+ ui->testConnIcon->setPixmap(testDatabase() ? ICONS.TEST_CONN_OK : ICONS.TEST_CONN_ERROR);
+ ui->testConnIcon->setVisible(true);
+}
+
+void DbDialog::dbTypeChanged(int index)
+{
+ typeChanged(index);
+ propertyChanged();
+}
+
+void DbDialog::nameModified(const QString &arg1)
+{
+ UNUSED(arg1);
+ updateState();
+}
+
+void DbDialog::accept()
+{
+ QString name = getName();
+ QString path = getPath();
+ QHash<QString, QVariant> options = collectOptions();
+ bool perm = isPermanent();
+ bool result;
+ if (mode == ADD)
+ result = DBLIST->addDb(name, path, options, perm);
+ else
+ result = DBLIST->updateDb(db, name, path, options, perm);
+
+ if (result)
+ QDialog::accept();
+}