aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/guiSQLiteStudio/multieditor
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2014-12-06 17:33:25 -0500
committerLibravatarUnit 193 <unit193@ubuntu.com>2014-12-06 17:33:25 -0500
commit7167ce41b61d2ba2cdb526777a4233eb84a3b66a (patch)
treea35c14143716e1f2c98f808c81f89426045a946f /SQLiteStudio3/guiSQLiteStudio/multieditor
Imported Upstream version 2.99.6upstream/2.99.6
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/multieditor')
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.cpp366
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.h96
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.cpp215
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.h68
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.cpp87
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.h37
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.cpp275
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.h84
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.cpp49
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.h29
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.cpp94
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.h50
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.cpp109
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.h42
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.cpp184
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.h87
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.cpp90
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.h38
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.cpp23
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.h33
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidgetplugin.h17
21 files changed, 2073 insertions, 0 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.cpp
new file mode 100644
index 0000000..2bae2f9
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.cpp
@@ -0,0 +1,366 @@
+#include "multieditor.h"
+#include "multieditortext.h"
+#include "multieditornumeric.h"
+#include "multieditordatetime.h"
+#include "multieditordate.h"
+#include "multieditortime.h"
+#include "multieditorbool.h"
+#include "multieditorhex.h"
+#include "mainwindow.h"
+#include "common/unused.h"
+#include "services/notifymanager.h"
+#include "services/pluginmanager.h"
+#include "multieditorwidgetplugin.h"
+#include "uiconfig.h"
+#include "dialogs/configdialog.h"
+#include "formview.h"
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QTabWidget>
+#include <QTabBar>
+#include <QLabel>
+#include <QCheckBox>
+#include <QVariant>
+#include <QEvent>
+#include <QGraphicsColorizeEffect>
+#include <QToolButton>
+#include <QDebug>
+#include <QKeyEvent>
+
+static QHash<QString,bool> missingEditorPluginsAlreadyWarned;
+
+MultiEditor::MultiEditor(QWidget *parent) :
+ QWidget(parent)
+{
+ init();
+}
+
+void MultiEditor::init()
+{
+ QVBoxLayout* vbox = new QVBoxLayout();
+ vbox->setMargin(margins);
+ vbox->setSpacing(spacing);
+ setLayout(vbox);
+
+ QWidget* top = new QWidget();
+ layout()->addWidget(top);
+
+ QHBoxLayout* hbox = new QHBoxLayout();
+ hbox->setMargin(0);
+ hbox->setSpacing(0);
+ top->setLayout(hbox);
+
+ nullCheck = new QCheckBox(tr("Null value", "multieditor"));
+ hbox->addWidget(nullCheck);
+
+ hbox->addStretch();
+
+ stateLabel = new QLabel();
+ hbox->addWidget(stateLabel);
+
+ hbox->addSpacing(50);
+
+ tabs = new QTabWidget();
+ layout()->addWidget(tabs);
+ tabs->tabBar()->installEventFilter(this);
+
+ configBtn = new QToolButton();
+ configBtn->setToolTip(tr("Configure editors for this data type"));
+ configBtn->setIcon(ICONS.CONFIGURE);
+ configBtn->setFocusPolicy(Qt::NoFocus);
+ configBtn->setAutoRaise(true);
+ configBtn->setEnabled(false);
+ connect(configBtn, SIGNAL(clicked()), this, SLOT(configClicked()));
+ tabs->setCornerWidget(configBtn);
+
+ QGraphicsColorizeEffect* effect = new QGraphicsColorizeEffect();
+ effect->setColor(Qt::black);
+ effect->setStrength(0.5);
+ nullEffect = effect;
+ tabs->setGraphicsEffect(effect);
+
+ connect(tabs, &QTabWidget::currentChanged, this, &MultiEditor::tabChanged);
+ connect(nullCheck, &QCheckBox::stateChanged, this, &MultiEditor::nullStateChanged);
+ connect(this, SIGNAL(modified()), this, SLOT(setModified()));
+}
+
+void MultiEditor::tabChanged(int idx)
+{
+ int prevTab = currentTab;
+ currentTab = idx;
+
+ MultiEditorWidget* newEditor = editors[idx];
+ newEditor->setFocus();
+
+ if (prevTab < 0)
+ return;
+
+ if (newEditor->isUpToDate())
+ return;
+
+ MultiEditorWidget* prevEditor = editors[prevTab];
+ newEditor->setValue(prevEditor->getValue());
+ newEditor->setUpToDate(true);
+}
+
+void MultiEditor::nullStateChanged(int state)
+{
+ bool checked = (state == Qt::Checked);
+
+ if (checked)
+ valueBeforeNull = getValueOmmitNull();
+
+ updateNullEffect();
+ updateValue(checked ? QVariant() : valueBeforeNull);
+
+ if (!checked)
+ valueBeforeNull.clear();
+
+ tabs->setEnabled(!checked);
+ emit modified();
+}
+
+void MultiEditor::invalidateValue()
+{
+ if (invalidatingDisabled)
+ return;
+
+ QObject* obj = sender();
+ if (!obj)
+ {
+ qWarning() << "No sender object while invalidating MultiEditor value.";
+ return;
+ }
+
+ QWidget* editorWidget = nullptr;
+ for (int i = 0; i < tabs->count(); i++)
+ {
+ editorWidget = tabs->widget(i);
+ if (editorWidget == obj)
+ continue; // skip sender
+
+ dynamic_cast<MultiEditorWidget*>(editorWidget)->setUpToDate(false);
+ }
+
+ emit modified();
+}
+
+void MultiEditor::setModified()
+{
+ valueModified = true;
+}
+
+void MultiEditor::addEditor(MultiEditorWidget* editorWidget)
+{
+ editorWidget->setReadOnly(readOnly);
+ connect(editorWidget, SIGNAL(valueModified()), this, SLOT(invalidateValue()));
+ editors << editorWidget;
+ tabs->addTab(editorWidget, editorWidget->getTabLabel().replace("&", "&&"));
+ editorWidget->installEventFilter(this);
+}
+
+void MultiEditor::showTab(int idx)
+{
+ tabs->setCurrentIndex(idx);
+}
+
+void MultiEditor::setValue(const QVariant& value)
+{
+ nullCheck->setChecked(!value.isValid() || value.isNull());
+ valueBeforeNull = value;
+ updateVisibility();
+ updateValue(value);
+ valueModified = false;
+}
+
+QVariant MultiEditor::getValue() const
+{
+ if (nullCheck->isChecked())
+ return QVariant();
+
+ return getValueOmmitNull();
+}
+
+bool MultiEditor::isModified() const
+{
+ return valueModified;
+}
+
+bool MultiEditor::eventFilter(QObject* obj, QEvent* event)
+{
+ if (event->type() == QEvent::Wheel)
+ {
+ QWidget::event(event);
+ return true;
+ }
+
+ return QWidget::eventFilter(obj, event);
+}
+
+bool MultiEditor::getReadOnly() const
+{
+ return readOnly;
+}
+
+void MultiEditor::setReadOnly(bool value)
+{
+ readOnly = value;
+
+ for (int i = 0; i < tabs->count(); i++)
+ dynamic_cast<MultiEditorWidget*>(tabs->widget(i))->setReadOnly(value);
+
+ stateLabel->setVisible(readOnly);
+ nullCheck->setEnabled(!readOnly);
+ updateVisibility();
+ updateLabel();
+}
+
+void MultiEditor::setDeletedRow(bool value)
+{
+ deleted = value;
+ updateLabel();
+}
+
+void MultiEditor::setDataType(const DataType& dataType)
+{
+ this->dataType = dataType;
+
+ foreach (MultiEditorWidget* editorWidget, getEditorTypes(dataType))
+ addEditor(editorWidget);
+
+ showTab(0);
+ configBtn->setEnabled(true);
+}
+
+void MultiEditor::focusThisEditor()
+{
+ MultiEditorWidget* w = dynamic_cast<MultiEditorWidget*>(tabs->currentWidget());
+ if (!w)
+ return;
+
+ w->focusThisWidget();
+}
+
+void MultiEditor::loadBuiltInEditors()
+{
+ PLUGINS->loadBuiltInPlugin(new MultiEditorBoolPlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorDateTimePlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorDatePlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorHexPlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorTextPlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorTimePlugin);
+ PLUGINS->loadBuiltInPlugin(new MultiEditorNumericPlugin);
+}
+
+QList<MultiEditorWidget*> MultiEditor::getEditorTypes(const DataType& dataType)
+{
+ QList<MultiEditorWidget*> editors;
+
+ QString typeStr = dataType.toString().trimmed().toUpper();
+ QHash<QString,QVariant> editorsOrder = CFG_UI.General.DataEditorsOrder.get();
+ if (editorsOrder.contains(typeStr))
+ {
+ MultiEditorWidgetPlugin* plugin = nullptr;
+ for (const QString& editorPluginName : editorsOrder[typeStr].toStringList())
+ {
+ plugin = dynamic_cast<MultiEditorWidgetPlugin*>(PLUGINS->getLoadedPlugin(editorPluginName));
+ if (!plugin)
+ {
+ if (!missingEditorPluginsAlreadyWarned.contains(editorPluginName))
+ {
+ notifyWarn(tr("Data editor plugin '%1' not loaded, while it is defined for editing '%1' data type."));
+ missingEditorPluginsAlreadyWarned[editorPluginName] = true;
+ }
+ continue;
+ }
+
+ editors << plugin->getInstance();
+ }
+ }
+
+ if (editors.size() > 0)
+ return editors;
+
+ //
+ // Prepare default list of editors
+ //
+ QList<MultiEditorWidgetPlugin*> plugins = PLUGINS->getLoadedPlugins<MultiEditorWidgetPlugin>();
+
+ typedef QPair<int,MultiEditorWidget*> EditorWithPriority;
+
+ QList<EditorWithPriority> sortedEditors;
+ EditorWithPriority editorWithPrio;
+ for (MultiEditorWidgetPlugin* plugin : plugins)
+ {
+ if (!plugin->validFor(dataType))
+ continue;
+
+ editorWithPrio.first = plugin->getPriority(dataType);
+ editorWithPrio.second = plugin->getInstance();
+ sortedEditors << editorWithPrio;
+ }
+
+ qSort(sortedEditors.begin(), sortedEditors.end(), [=](const EditorWithPriority& ed1, const EditorWithPriority& ed2) -> bool
+ {
+ return ed1.first < ed2.first;
+ });
+
+ for (const EditorWithPriority& e : sortedEditors)
+ editors << e.second;
+
+ return editors;
+}
+
+void MultiEditor::configClicked()
+{
+ ConfigDialog config(MAINWINDOW);
+ config.configureDataEditors(dataType.toString());
+ config.exec();
+}
+
+void MultiEditor::updateVisibility()
+{
+ tabs->setVisible(!readOnly || !nullCheck->isChecked());
+ nullCheck->setVisible(!readOnly || nullCheck->isChecked());
+ updateNullEffect();
+}
+
+void MultiEditor::updateNullEffect()
+{
+ nullEffect->setEnabled(tabs->isVisible() && nullCheck->isChecked());
+ if (tabs->isVisible())
+ {
+ for (int i = 0; i < tabs->count(); i++)
+ dynamic_cast<MultiEditorWidget*>(tabs->widget(i))->update();
+
+ nullEffect->update();
+ }
+}
+
+void MultiEditor::updateValue(const QVariant& newValue)
+{
+ invalidatingDisabled = true;
+ MultiEditorWidget* editorWidget = nullptr;
+ for (int i = 0; i < tabs->count(); i++)
+ {
+ editorWidget = dynamic_cast<MultiEditorWidget*>(tabs->widget(i));
+ editorWidget->setValue(newValue);
+ editorWidget->setUpToDate(true);
+ }
+ invalidatingDisabled = false;
+}
+
+void MultiEditor::updateLabel()
+{
+ if (deleted)
+ stateLabel->setText("<i>"+tr("Deleted", "multieditor")+"<i>");
+ else if (readOnly)
+ stateLabel->setText("<i>"+tr("Read only", "multieditor")+"<i>");
+ else
+ stateLabel->setText("");
+}
+
+QVariant MultiEditor::getValueOmmitNull() const
+{
+ return dynamic_cast<MultiEditorWidget*>(tabs->currentWidget())->getValue();
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.h
new file mode 100644
index 0000000..2576c97
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditor.h
@@ -0,0 +1,96 @@
+#ifndef MULTIEDITOR_H
+#define MULTIEDITOR_H
+
+#include "guiSQLiteStudio_global.h"
+#include "datagrid/sqlquerymodelcolumn.h"
+#include <QWidget>
+#include <QVariant>
+
+class QCheckBox;
+class QTabWidget;
+class MultiEditorWidget;
+class QLabel;
+class MultiEditorWidgetPlugin;
+class QToolButton;
+
+class GUI_API_EXPORT MultiEditor : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant value READ getValue WRITE setValue)
+
+ public:
+ enum BuiltInEditor
+ {
+ TEXT,
+ NUMERIC,
+ BOOLEAN,
+ DATE,
+ TIME,
+ DATETIME,
+ HEX
+ };
+
+ explicit MultiEditor(QWidget *parent = 0);
+
+ void addEditor(MultiEditorWidget* editorWidget);
+ void showTab(int idx);
+
+ void setValue(const QVariant& value);
+ QVariant getValue() const;
+ bool isModified() const;
+ bool eventFilter(QObject* obj, QEvent* event);
+ bool getReadOnly() const;
+ void setReadOnly(bool value);
+ void setDeletedRow(bool value);
+ void setDataType(const DataType& dataType);
+ void focusThisEditor();
+
+ static void loadBuiltInEditors();
+
+ private:
+ void init();
+ void updateVisibility();
+ void updateNullEffect();
+ void updateValue(const QVariant& newValue);
+ void updateLabel();
+ QVariant getValueOmmitNull() const;
+
+ static QList<MultiEditorWidget*> getEditorTypes(const DataType& dataType);
+
+ static const int margins = 2;
+ static const int spacing = 2;
+
+ QCheckBox* nullCheck = nullptr;
+ QTabWidget* tabs = nullptr;
+ QList<MultiEditorWidget*> editors;
+ QLabel* stateLabel = nullptr;
+ bool readOnly = false;
+ bool deleted = false;
+ bool invalidatingDisabled = false;
+ QGraphicsEffect* nullEffect = nullptr;
+ bool valueModified = false;
+ QVariant valueBeforeNull;
+ QToolButton* configBtn = nullptr;
+ DataType dataType;
+
+ /**
+ * @brief currentTab
+ * Hold current tab index. It might seem as duplicate for tabs->currentIndex,
+ * but this is necessary when we want to know what was the previous tab,
+ * while being in tabChanged() slot.
+ */
+ int currentTab = -1;
+
+ private slots:
+ void configClicked();
+ void tabChanged(int idx);
+ void nullStateChanged(int state);
+ void invalidateValue();
+ void setModified();
+
+ signals:
+ void modified();
+};
+
+#endif // MULTIEDITOR_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.cpp
new file mode 100644
index 0000000..ed7c260
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.cpp
@@ -0,0 +1,215 @@
+#include "multieditorbool.h"
+#include <QVBoxLayout>
+#include <QCheckBox>
+#include <QVariant>
+
+QStringList MultiEditorBool::validValues;
+
+MultiEditorBool::MultiEditorBool(QWidget* parent)
+ : MultiEditorWidget(parent)
+{
+ setLayout(new QVBoxLayout());
+ checkBox = new QCheckBox();
+ layout()->addWidget(checkBox);
+ connect(checkBox, &QCheckBox::stateChanged, this, &MultiEditorBool::stateChanged);
+}
+
+void MultiEditorBool::staticInit()
+{
+ validValues << "true" << "false"
+ << "yes" << "no"
+ << "on" << "off"
+ << "1" << "0";
+}
+
+void MultiEditorBool::setValue(const QVariant& value)
+{
+ switch (value.userType())
+ {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ boolValue = value.toBool();
+ upperCaseValue = false;
+ valueFormat = BOOL;
+ break;
+ default:
+ boolValue = valueFromString(value.toString());
+ break;
+ }
+
+ updateLabel();
+ checkBox->setChecked(boolValue);
+}
+
+bool MultiEditorBool::valueFromString(const QString& strValue)
+{
+ if (strValue.isEmpty())
+ {
+ upperCaseValue = false;
+ valueFormat = BOOL;
+ return false;
+ }
+
+ int idx = validValues.indexOf(strValue.toLower());
+ if (idx < 0)
+ {
+ upperCaseValue = false;
+ valueFormat = BOOL;
+ return true;
+ }
+
+ upperCaseValue = strValue[0].isUpper();
+ switch (idx)
+ {
+ case 0:
+ case 1:
+ valueFormat = TRUE_FALSE;
+ break;
+ case 2:
+ case 3:
+ valueFormat = YES_NO;
+ break;
+ case 4:
+ case 5:
+ valueFormat = ON_OFF;
+ break;
+ case 6:
+ case 7:
+ valueFormat = ONE_ZERO;
+ break;
+ }
+ return !(bool)(idx % 2);
+}
+
+QVariant MultiEditorBool::getValue()
+{
+ QString value;
+ switch (valueFormat)
+ {
+ case MultiEditorBool::TRUE_FALSE:
+ value = boolValue ? "true" : "false";
+ break;
+ case MultiEditorBool::ON_OFF:
+ value = boolValue ? "on" : "off";
+ break;
+ case MultiEditorBool::YES_NO:
+ value = boolValue ? "yes" : "no";
+ break;
+ case MultiEditorBool::ONE_ZERO:
+ case MultiEditorBool::BOOL:
+ value = boolValue ? "1" : "0";
+ break;
+ }
+
+ if (value.isNull())
+ value = boolValue ? "1" : "0";
+
+ if (upperCaseValue)
+ value = value.toUpper();
+
+ return value;
+}
+
+void MultiEditorBool::setReadOnly(bool value)
+{
+ readOnly = value;
+}
+
+QList<QWidget*> MultiEditorBool::getNoScrollWidgets()
+{
+ QList<QWidget*> list;
+ list << checkBox;
+ return list;
+}
+
+QString MultiEditorBool::getTabLabel()
+{
+ return tr("Boolean");
+}
+
+void MultiEditorBool::focusThisWidget()
+{
+ checkBox->setFocus();
+}
+
+void MultiEditorBool::updateLabel()
+{
+ checkBox->setText(getValue().toString());
+}
+
+void MultiEditorBool::stateChanged(int state)
+{
+ if (readOnly && ((bool)state) != boolValue)
+ {
+ checkBox->setChecked(boolValue);
+ return;
+ }
+
+ boolValue = checkBox->isChecked();
+ updateLabel();
+ emit valueModified();
+}
+
+MultiEditorWidget* MultiEditorBoolPlugin::getInstance()
+{
+ return new MultiEditorBool();
+}
+
+bool MultiEditorBoolPlugin::validFor(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BOOLEAN:
+ return true;
+ case DataType::BLOB:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ }
+ return false;
+}
+
+int MultiEditorBoolPlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BOOLEAN:
+ return 1;
+ case DataType::BLOB:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ }
+ return 100;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.h
new file mode 100644
index 0000000..f328cf0
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorbool.h
@@ -0,0 +1,68 @@
+#ifndef MULTIEDITORBOOL_H
+#define MULTIEDITORBOOL_H
+
+#include "guiSQLiteStudio_global.h"
+#include "multieditorwidget.h"
+#include "multieditorwidgetplugin.h"
+#include "plugins/builtinplugin.h"
+#include <QStringList>
+
+class QCheckBox;
+
+class GUI_API_EXPORT MultiEditorBool : public MultiEditorWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit MultiEditorBool(QWidget* parent = 0);
+
+ static void staticInit();
+
+ void setValue(const QVariant& boolValue);
+ QVariant getValue();
+ void setReadOnly(bool boolValue);
+ QList<QWidget*> getNoScrollWidgets();
+ QString getTabLabel();
+ void focusThisWidget();
+
+ private:
+ enum Format
+ {
+ TRUE_FALSE,
+ ON_OFF,
+ YES_NO,
+ ONE_ZERO,
+ BOOL
+ };
+
+ bool valueFromString(const QString& strValue);
+ void updateLabel();
+
+ static QStringList validValues;
+
+ QCheckBox* checkBox = nullptr;
+ Format valueFormat = ONE_ZERO;
+ bool upperCaseValue = false;
+ bool readOnly = false;
+ bool boolValue = false;
+
+ private slots:
+ void stateChanged(int state);
+};
+
+class GUI_API_EXPORT MultiEditorBoolPlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Boolean data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Boolean")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORBOOL_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.cpp
new file mode 100644
index 0000000..44178f8
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.cpp
@@ -0,0 +1,87 @@
+#include "multieditordate.h"
+#include <QDateEdit>
+
+QStringList MultiEditorDate::formats;
+
+MultiEditorDate::MultiEditorDate(QWidget* parent)
+ : MultiEditorDateTime(parent)
+{
+ setDisplayFormat(formats.first());
+}
+
+QString MultiEditorDate::getTabLabel()
+{
+ return tr("Date");
+}
+
+void MultiEditorDate::staticInit()
+{
+ formats << "yyyy-MM-dd";
+}
+
+QStringList MultiEditorDate::getParsingFormats()
+{
+ return MultiEditorDateTime::getParsingFormats();
+}
+
+
+MultiEditorWidget*MultiEditorDatePlugin::getInstance()
+{
+ return new MultiEditorDate();
+}
+
+bool MultiEditorDatePlugin::validFor(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ case DataType::DATE:
+ return true;
+ }
+ return false;
+}
+
+int MultiEditorDatePlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::TIME:
+ case DataType::DATETIME:
+ case DataType::unknown:
+ break;
+ case DataType::DATE:
+ return 1;
+ }
+ return 10;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.h
new file mode 100644
index 0000000..b6f6d7c
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordate.h
@@ -0,0 +1,37 @@
+#ifndef MULTIEDITORDATE_H
+#define MULTIEDITORDATE_H
+
+#include "multieditordatetime.h"
+
+class GUI_API_EXPORT MultiEditorDate : public MultiEditorDateTime
+{
+ public:
+ explicit MultiEditorDate(QWidget *parent = 0);
+
+ QString getTabLabel();
+
+ static void staticInit();
+
+ protected:
+ QStringList getParsingFormats();
+
+ private:
+ static QStringList formats;
+};
+
+class GUI_API_EXPORT MultiEditorDatePlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Date data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Date")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORDATE_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.cpp
new file mode 100644
index 0000000..bd1e244
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.cpp
@@ -0,0 +1,275 @@
+#include "multieditordatetime.h"
+#include "common/utils.h"
+#include "common/unused.h"
+#include <QDateTimeEdit>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QVariant>
+#include <QString>
+#include <QDebug>
+#include <QCalendarWidget>
+#include <QWheelEvent>
+#include <QTableView>
+#include <QLabel>
+
+QStringList MultiEditorDateTime::formats;
+
+MultiEditorDateTime::MultiEditorDateTime(QWidget *parent) :
+ MultiEditorWidget(parent)
+{
+ QVBoxLayout* vbox = new QVBoxLayout();
+ setLayout(vbox);
+ dateTimeEdit = new QDateTimeEdit();
+ dateTimeLabel = new QLabel();
+ calendar = new QCalendarWidget();
+ // Extending width, becuase day labels are truncated on some systems.
+ calendar->setFixedSize(calendar->sizeHint() + QSize(80, 0));
+
+ vbox->addWidget(dateTimeEdit);
+ vbox->addWidget(dateTimeLabel);
+ vbox->addWidget(calendar);
+
+ setDisplayFormat(formats.first());
+
+ connect(calendar, &QCalendarWidget::selectionChanged, this, &MultiEditorDateTime::calendarDateChanged);
+ connect(dateTimeEdit, &QDateTimeEdit::dateChanged, this, &MultiEditorDateTime::dateChanged);
+ connect(dateTimeEdit, &QDateTimeEdit::timeChanged, this, &MultiEditorDateTime::timeChanged);
+
+ setFocusProxy(dateTimeEdit);
+ updateCalendarDisplay();
+}
+
+void MultiEditorDateTime::staticInit()
+{
+ formats << "yyyy-MM-dd hh:mm:ss"
+ << "yyyy-MM-dd hh:mm"
+ << "yyyy-MM-dd"
+ << "yyyy-MM-dd hh:mm:ss.z"
+ << "yyyy-MM-ddThh:mm"
+ << "yyyy-MM-ddThh:mm:ss"
+ << "yyyy-MM-ddThh:mm:ss.z";
+}
+
+void MultiEditorDateTime::setDisplayFormat(const QString& format)
+{
+ dateTimeEdit->setDisplayFormat(format);
+ dateTimeEdit->setMaximumWidth(dateTimeEdit->sizeHint().width());
+}
+
+void MultiEditorDateTime::setValue(const QVariant& value)
+{
+ switch (value.userType())
+ {
+ case QVariant::DateTime:
+ dateTimeEdit->setDateTime(value.toDateTime());
+ break;
+ case QVariant::Date:
+ dateTimeEdit->setDate(value.toDate());
+ break;
+ default:
+ {
+ dateTimeEdit->setDateTime(fromString(value.toString()));
+ break;
+ }
+ }
+ updateReadOnlyDisplay();
+}
+
+QVariant MultiEditorDateTime::getValue()
+{
+ if (formatType == STRING)
+ return dateTimeEdit->dateTime().toString(originalValueFormat);
+ else if (formatType == UNIXTIME)
+ return dateTimeEdit->dateTime().toTime_t();
+ else if (formatType == JULIAN_DAY)
+ return toJulian(dateTimeEdit->dateTime());
+ else
+ return dateTimeEdit->dateTime().toString(dateTimeEdit->displayFormat());
+}
+
+QList<QWidget*> MultiEditorDateTime::getNoScrollWidgets()
+{
+ QList<QWidget*> list;
+ list << dateTimeEdit << calendar;
+
+ QObject* obj = calendar->findChild<QTableView*>("qt_calendar_calendarview");
+ if (obj)
+ {
+ QTableView* view = dynamic_cast<QTableView*>(obj);
+ if (view)
+ list << view->viewport();
+ }
+
+ return list;
+}
+
+QDateTime MultiEditorDateTime::fromString(const QString& value)
+{
+ QDateTime dateTime;
+ foreach (const QString& format, getParsingFormats())
+ {
+ dateTime = QDateTime::fromString(value, format);
+ if (dateTime.isValid())
+ {
+ formatType = STRING;
+ originalValueFormat = format;
+ return dateTime;
+ }
+ }
+
+ // Try with unixtime
+ bool ok;
+ uint unixtime = value.toUInt(&ok);
+ if (ok)
+ {
+ dateTime = QDateTime::fromTime_t(unixtime);
+ formatType = UNIXTIME;
+ return dateTime;
+ }
+
+ // Try with Julian day
+ double jd = value.toDouble(&ok);
+ if (ok)
+ {
+ dateTime = toGregorian(jd);
+ formatType = JULIAN_DAY;
+ return dateTime;
+ }
+
+ formatType = OTHER;
+ return QDateTime();
+}
+
+void MultiEditorDateTime::calendarDateChanged()
+{
+ if (updatingCalendar)
+ return;
+
+ dateTimeEdit->setDate(calendar->selectedDate());
+ emit valueModified();
+}
+
+void MultiEditorDateTime::dateChanged(const QDate& date)
+{
+ updatingCalendar = true;
+ calendar->setSelectedDate(date);
+ updatingCalendar = false;
+ emit valueModified();
+}
+
+void MultiEditorDateTime::timeChanged(const QTime& time)
+{
+ UNUSED(time);
+ emit valueModified();
+}
+
+bool MultiEditorDateTime::getReadOnly() const
+{
+ return readOnly;
+}
+
+void MultiEditorDateTime::setReadOnly(bool value)
+{
+ readOnly = value;
+ dateTimeEdit->setVisible(!readOnly);
+ dateTimeLabel->setVisible(readOnly);
+ updateReadOnlyDisplay();
+}
+
+QString MultiEditorDateTime::getTabLabel()
+{
+ return tr("Date & time");
+}
+
+void MultiEditorDateTime::focusThisWidget()
+{
+ dateTimeEdit->setFocus();
+}
+
+QStringList MultiEditorDateTime::getParsingFormats()
+{
+ return formats;
+}
+
+void MultiEditorDateTime::updateReadOnlyDisplay()
+{
+ if (!readOnly)
+ return;
+
+ dateTimeLabel->setText(getValue().toString());
+ QDate date = dateTimeEdit->date();
+ calendar->setMinimumDate(date);
+ calendar->setMaximumDate(date);
+ calendar->setSelectedDate(date);
+}
+
+void MultiEditorDateTime::updateCalendarDisplay()
+{
+ if (!showCalendars)
+ {
+ calendar->setVisible(false);
+ return;
+ }
+}
+
+MultiEditorWidget*MultiEditorDateTimePlugin::getInstance()
+{
+ return new MultiEditorDateTime();
+}
+
+bool MultiEditorDateTimePlugin::validFor(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ case DataType::DATE:
+ case DataType::DATETIME:
+ return true;
+ }
+ return false;
+}
+
+int MultiEditorDateTimePlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ case DataType::DATE:
+ return 2;
+ case DataType::DATETIME:
+ return 1;
+ }
+ return 10;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.h
new file mode 100644
index 0000000..59bd111
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordatetime.h
@@ -0,0 +1,84 @@
+#ifndef MULTIEDITORDATETIME_H
+#define MULTIEDITORDATETIME_H
+
+#include "multieditorwidget.h"
+#include "multieditorwidgetplugin.h"
+#include "plugins/builtinplugin.h"
+#include <QStringList>
+#include <QDateTime>
+
+class QCalendarWidget;
+class QDateTimeEdit;
+class QLabel;
+
+class GUI_API_EXPORT MultiEditorDateTime : public MultiEditorWidget
+{
+ Q_OBJECT
+ public:
+ explicit MultiEditorDateTime(QWidget *parent = 0);
+
+ static void staticInit();
+
+ void setValue(const QVariant& value);
+ QVariant getValue();
+ bool needsValueUpdate();
+
+ QList<QWidget*> getNoScrollWidgets();
+
+ bool getReadOnly() const;
+ void setReadOnly(bool value);
+ QString getTabLabel();
+ void focusThisWidget();
+
+ protected:
+ void updateCalendarDisplay();
+ void setDisplayFormat(const QString& format);
+
+ virtual QStringList getParsingFormats();
+
+ QDateTimeEdit* dateTimeEdit = nullptr;
+ bool showCalendars = true;
+
+ private:
+ enum FormatType
+ {
+ STRING,
+ JULIAN_DAY,
+ UNIXTIME,
+ OTHER
+ };
+
+ void updateReadOnlyDisplay();
+ QDateTime fromString(const QString& value);
+
+ static QStringList formats;
+
+ QLabel* dateTimeLabel = nullptr;
+ QCalendarWidget* calendar = nullptr;
+ QString originalValueFormat;
+ FormatType formatType;
+ bool updatingCalendar = false;
+ bool readOnly = false;
+
+ private slots:
+ void calendarDateChanged();
+ void dateChanged(const QDate& date);
+ void timeChanged(const QTime& time);
+};
+
+class GUI_API_EXPORT MultiEditorDateTimePlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Date and time data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Date and time")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORDATETIME_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.cpp
new file mode 100644
index 0000000..5e3985c
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.cpp
@@ -0,0 +1,49 @@
+#include "multieditordialog.h"
+#include "multieditor.h"
+#include <QDialogButtonBox>
+#include <QVBoxLayout>
+
+MultiEditorDialog::MultiEditorDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ multiEditor = new MultiEditor();
+
+ QVBoxLayout* vbox = new QVBoxLayout();
+ vbox->addWidget(multiEditor);
+ setLayout(vbox);
+
+ multiEditor->setReadOnly(false);
+
+ buttonBox = new QDialogButtonBox(Qt::Horizontal);
+ buttonBox->addButton(QDialogButtonBox::Ok);
+ buttonBox->addButton(QDialogButtonBox::Cancel);
+ vbox->addWidget(buttonBox);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+MultiEditorDialog::~MultiEditorDialog()
+{
+ delete multiEditor;
+}
+
+void MultiEditorDialog::setValue(const QVariant& value)
+{
+ multiEditor->setValue(value);
+}
+
+QVariant MultiEditorDialog::getValue()
+{
+ return multiEditor->getValue();
+}
+
+void MultiEditorDialog::setDataType(const DataType& dataType)
+{
+ multiEditor->setDataType(dataType);
+}
+
+void MultiEditorDialog::setReadOnly(bool readOnly)
+{
+ multiEditor->setReadOnly(readOnly);
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.h
new file mode 100644
index 0000000..ffbbd9c
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditordialog.h
@@ -0,0 +1,29 @@
+#ifndef MULTIEDITORDIALOG_H
+#define MULTIEDITORDIALOG_H
+
+#include "datagrid/sqlquerymodelcolumn.h"
+#include "guiSQLiteStudio_global.h"
+#include <QDialog>
+
+class MultiEditor;
+class QDialogButtonBox;
+
+class GUI_API_EXPORT MultiEditorDialog : public QDialog
+{
+ Q_OBJECT
+ public:
+ explicit MultiEditorDialog(QWidget *parent = 0);
+ ~MultiEditorDialog();
+
+ void setValue(const QVariant& value);
+ QVariant getValue();
+
+ void setDataType(const DataType& dataType);
+ void setReadOnly(bool readOnly);
+
+ private:
+ MultiEditor* multiEditor = nullptr;
+ QDialogButtonBox* buttonBox = nullptr;
+};
+
+#endif // MULTIEDITORDIALOG_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.cpp
new file mode 100644
index 0000000..5a3cd28
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.cpp
@@ -0,0 +1,94 @@
+#include "multieditorhex.h"
+#include "qhexedit2/qhexedit.h"
+#include "common/unused.h"
+#include <QVBoxLayout>
+
+MultiEditorHex::MultiEditorHex()
+{
+ setLayout(new QVBoxLayout());
+ hexEdit = new QHexEdit();
+ layout()->addWidget(hexEdit);
+
+ //hexEdit->setTabChangesFocus(true);
+
+ connect(hexEdit, SIGNAL(dataChanged()), this, SLOT(modificationChanged()));
+ setFocusProxy(hexEdit);
+}
+
+MultiEditorHex::~MultiEditorHex()
+{
+}
+
+void MultiEditorHex::setValue(const QVariant& value)
+{
+ hexEdit->setData(value.toByteArray());
+}
+
+QVariant MultiEditorHex::getValue()
+{
+ return hexEdit->data();
+}
+
+void MultiEditorHex::setReadOnly(bool value)
+{
+ hexEdit->setReadOnly(value);
+}
+
+QString MultiEditorHex::getTabLabel()
+{
+ return tr("Hex");
+}
+
+void MultiEditorHex::focusThisWidget()
+{
+ hexEdit->setFocus();
+}
+
+QList<QWidget*> MultiEditorHex::getNoScrollWidgets()
+{
+ return QList<QWidget*>();
+}
+
+void MultiEditorHex::modificationChanged()
+{
+ emit valueModified();
+}
+
+MultiEditorWidget*MultiEditorHexPlugin::getInstance()
+{
+ return new MultiEditorHex();
+}
+
+bool MultiEditorHexPlugin::validFor(const DataType& dataType)
+{
+ UNUSED(dataType);
+ return true;
+}
+
+int MultiEditorHexPlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ return 1;
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::BOOLEAN:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ }
+ return 100;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.h
new file mode 100644
index 0000000..5fd32a0
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorhex.h
@@ -0,0 +1,50 @@
+#ifndef MULTIEDITORHEX_H
+#define MULTIEDITORHEX_H
+
+#include "multieditorwidget.h"
+#include "multieditorwidgetplugin.h"
+#include "plugins/builtinplugin.h"
+#include <QVariant>
+#include <QSharedPointer>
+
+class QHexEdit;
+class QBuffer;
+
+class GUI_API_EXPORT MultiEditorHex : public MultiEditorWidget
+{
+ Q_OBJECT
+ public:
+ explicit MultiEditorHex();
+ ~MultiEditorHex();
+
+ void setValue(const QVariant& value);
+ QVariant getValue();
+ void setReadOnly(bool value);
+ QString getTabLabel();
+ void focusThisWidget();
+
+ QList<QWidget*> getNoScrollWidgets();
+
+ private:
+ QHexEdit* hexEdit = nullptr;
+
+ private slots:
+ void modificationChanged();
+};
+
+class GUI_API_EXPORT MultiEditorHexPlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Hexadecimal data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Hexadecimal")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORHEX_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.cpp
new file mode 100644
index 0000000..198f71b
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.cpp
@@ -0,0 +1,109 @@
+#include "multieditornumeric.h"
+#include "common/numericspinbox.h"
+#include <QVariant>
+#include <QVBoxLayout>
+
+MultiEditorNumeric::MultiEditorNumeric(QWidget* parent)
+ : MultiEditorWidget(parent)
+{
+ setLayout(new QVBoxLayout());
+ spinBox = new NumericSpinBox();
+ layout()->addWidget(spinBox);
+
+ connect(spinBox, SIGNAL(modified()), this, SIGNAL(valueModified()));
+
+ setFocusProxy(spinBox);
+}
+
+void MultiEditorNumeric::setValue(const QVariant& value)
+{
+ spinBox->setValue(value);
+}
+
+QVariant MultiEditorNumeric::getValue()
+{
+ return spinBox->getValue();
+}
+
+void MultiEditorNumeric::setReadOnly(bool value)
+{
+ spinBox->setReadOnly(value);
+}
+
+QString MultiEditorNumeric::getTabLabel()
+{
+ return tr("Number");
+}
+
+void MultiEditorNumeric::focusThisWidget()
+{
+ spinBox->setFocus();
+}
+
+QList<QWidget*> MultiEditorNumeric::getNoScrollWidgets()
+{
+ QList<QWidget*> list;
+ list << spinBox;
+ return list;
+}
+
+MultiEditorWidget*MultiEditorNumericPlugin::getInstance()
+{
+ return new MultiEditorNumeric();
+}
+
+bool MultiEditorNumericPlugin::validFor(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ return true;
+ case DataType::BOOLEAN:
+ case DataType::BLOB:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ }
+ return false;
+}
+
+int MultiEditorNumericPlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ return 1;
+ case DataType::BOOLEAN:
+ case DataType::BLOB:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ case DataType::unknown:
+ break;
+ }
+ return 10;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.h
new file mode 100644
index 0000000..65d0409
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditornumeric.h
@@ -0,0 +1,42 @@
+#ifndef MULTIEDITORNUMERIC_H
+#define MULTIEDITORNUMERIC_H
+
+#include "multieditorwidget.h"
+#include "multieditorwidgetplugin.h"
+#include "plugins/builtinplugin.h"
+
+class NumericSpinBox;
+
+class GUI_API_EXPORT MultiEditorNumeric : public MultiEditorWidget
+{
+ public:
+ explicit MultiEditorNumeric(QWidget *parent = 0);
+
+ void setValue(const QVariant& value);
+ QVariant getValue();
+ void setReadOnly(bool value);
+ QString getTabLabel();
+ void focusThisWidget();
+
+ QList<QWidget*> getNoScrollWidgets();
+
+ private:
+ NumericSpinBox* spinBox = nullptr;
+};
+
+class GUI_API_EXPORT MultiEditorNumericPlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Numeric data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Numeric types")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORNUMERIC_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.cpp
new file mode 100644
index 0000000..05db8e0
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.cpp
@@ -0,0 +1,184 @@
+#include "multieditortext.h"
+#include "common/unused.h"
+#include <QPlainTextEdit>
+#include <QVariant>
+#include <QVBoxLayout>
+#include <QAction>
+#include <QMenu>
+
+CFG_KEYS_DEFINE(MultiEditorText)
+
+MultiEditorText::MultiEditorText(QWidget *parent) :
+ MultiEditorWidget(parent)
+{
+ setLayout(new QVBoxLayout());
+ textEdit = new QPlainTextEdit();
+ layout()->addWidget(textEdit);
+ initActions();
+ setupMenu();
+
+ setFocusProxy(textEdit);
+ textEdit->setContextMenuPolicy(Qt::CustomContextMenu);
+ textEdit->setTabChangesFocus(true);
+
+ connect(textEdit, &QPlainTextEdit::modificationChanged, this, &MultiEditorText::modificationChanged);
+ connect(textEdit, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showCustomMenu(QPoint)));
+}
+
+void MultiEditorText::setValue(const QVariant& value)
+{
+ textEdit->setPlainText(value.toString());
+}
+
+QVariant MultiEditorText::getValue()
+{
+ return textEdit->toPlainText();
+}
+
+void MultiEditorText::setReadOnly(bool value)
+{
+ textEdit->setReadOnly(value);
+}
+
+QString MultiEditorText::getTabLabel()
+{
+ return tr("Text");
+}
+
+QToolBar* MultiEditorText::getToolBar(int toolbar) const
+{
+ UNUSED(toolbar);
+ return nullptr;
+}
+
+void MultiEditorText::focusThisWidget()
+{
+ textEdit->setFocus();
+}
+
+QList<QWidget*> MultiEditorText::getNoScrollWidgets()
+{
+ // We don't return text, we want it to be scrolled.
+ QList<QWidget*> list;
+ return list;
+}
+
+void MultiEditorText::modificationChanged(bool changed)
+{
+ if (changed)
+ emit valueModified();
+}
+
+void MultiEditorText::deleteSelected()
+{
+ textEdit->textCursor().removeSelectedText();
+}
+
+void MultiEditorText::showCustomMenu(const QPoint& point)
+{
+ contextMenu->popup(textEdit->mapToGlobal(point));
+}
+
+void MultiEditorText::updateUndoAction(bool enabled)
+{
+ actionMap[UNDO]->setEnabled(enabled);
+}
+
+void MultiEditorText::updateRedoAction(bool enabled)
+{
+ actionMap[REDO]->setEnabled(enabled);
+}
+
+void MultiEditorText::updateCopyAction(bool enabled)
+{
+ actionMap[CUT]->setEnabled(enabled);
+ actionMap[COPY]->setEnabled(enabled);
+ actionMap[DELETE]->setEnabled(enabled);
+}
+
+void MultiEditorText::toggleTabFocus()
+{
+ textEdit->setTabChangesFocus(actionMap[TAB_CHANGES_FOCUS]->isChecked());
+}
+
+void MultiEditorText::createActions()
+{
+ createAction(TAB_CHANGES_FOCUS, tr("Tab changes focus"), this, SLOT(toggleTabFocus()), this);
+ createAction(CUT, ICONS.ACT_CUT, tr("Cut"), textEdit, SLOT(cut()), this);
+ createAction(COPY, ICONS.ACT_COPY, tr("Copy"), textEdit, SLOT(copy()), this);
+ createAction(PASTE, ICONS.ACT_PASTE, tr("Paste"), textEdit, SLOT(paste()), this);
+ createAction(DELETE, ICONS.ACT_DELETE, tr("Delete"), this, SLOT(deleteSelected()), this);
+ createAction(UNDO, ICONS.ACT_UNDO, tr("Undo"), textEdit, SLOT(undo()), this);
+ createAction(REDO, ICONS.ACT_REDO, tr("Redo"), textEdit, SLOT(redo()), this);
+
+ actionMap[CUT]->setEnabled(false);
+ actionMap[COPY]->setEnabled(false);
+ actionMap[DELETE]->setEnabled(false);
+ actionMap[UNDO]->setEnabled(false);
+ actionMap[REDO]->setEnabled(false);
+
+ actionMap[TAB_CHANGES_FOCUS]->setCheckable(true);
+ actionMap[TAB_CHANGES_FOCUS]->setChecked(true);
+
+ connect(textEdit, &QPlainTextEdit::undoAvailable, this, &MultiEditorText::updateUndoAction);
+ connect(textEdit, &QPlainTextEdit::redoAvailable, this, &MultiEditorText::updateRedoAction);
+ connect(textEdit, &QPlainTextEdit::copyAvailable, this, &MultiEditorText::updateCopyAction);
+}
+
+void MultiEditorText::setupDefShortcuts()
+{
+ BIND_SHORTCUTS(MultiEditorText, Action);
+}
+
+void MultiEditorText::setupMenu()
+{
+ contextMenu = new QMenu(this);
+ contextMenu->addAction(actionMap[TAB_CHANGES_FOCUS]);
+ contextMenu->addSeparator();
+ contextMenu->addAction(actionMap[UNDO]);
+ contextMenu->addAction(actionMap[REDO]);
+ contextMenu->addSeparator();
+ contextMenu->addAction(actionMap[CUT]);
+ contextMenu->addAction(actionMap[COPY]);
+ contextMenu->addAction(actionMap[PASTE]);
+ contextMenu->addAction(actionMap[DELETE]);
+}
+
+MultiEditorWidget* MultiEditorTextPlugin::getInstance()
+{
+ return new MultiEditorText();
+}
+
+bool MultiEditorTextPlugin::validFor(const DataType& dataType)
+{
+ UNUSED(dataType);
+ return true;
+}
+
+int MultiEditorTextPlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::TIME:
+ return 10;
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::unknown:
+ break;
+ }
+ return 1;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.h
new file mode 100644
index 0000000..bd814ce
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortext.h
@@ -0,0 +1,87 @@
+#ifndef MULTIEDITORTEXT_H
+#define MULTIEDITORTEXT_H
+
+#include "multieditorwidget.h"
+#include "multieditorwidgetplugin.h"
+#include "common/extactioncontainer.h"
+#include "plugins/builtinplugin.h"
+
+class QPlainTextEdit;
+class QMenu;
+
+CFG_KEY_LIST(MultiEditorText, QObject::tr("Cell text value editor"),
+ CFG_KEY_ENTRY(CUT, QKeySequence::Cut, QObject::tr("Cut selected text"))
+ CFG_KEY_ENTRY(COPY, QKeySequence::Copy, QObject::tr("Copy selected text"))
+ CFG_KEY_ENTRY(PASTE, QKeySequence::Paste, QObject::tr("Paste from clipboard"))
+ CFG_KEY_ENTRY(DELETE, QKeySequence::Delete, QObject::tr("Delete selected text"))
+ CFG_KEY_ENTRY(UNDO, QKeySequence::Undo, QObject::tr("Undo"))
+ CFG_KEY_ENTRY(REDO, QKeySequence::Redo, QObject::tr("Redo"))
+)
+
+class GUI_API_EXPORT MultiEditorText : public MultiEditorWidget, public ExtActionContainer
+{
+ Q_OBJECT
+ Q_ENUMS(Action)
+
+ public:
+ enum Action
+ {
+ TAB_CHANGES_FOCUS,
+ CUT,
+ COPY,
+ PASTE,
+ DELETE,
+ UNDO,
+ REDO
+ };
+
+ enum ToolBar
+ {
+ };
+
+ explicit MultiEditorText(QWidget *parent = 0);
+
+ void setValue(const QVariant& value);
+ QVariant getValue();
+ void setReadOnly(bool value);
+ QString getTabLabel();
+ QToolBar* getToolBar(int toolbar) const;
+ void focusThisWidget();
+ QList<QWidget*> getNoScrollWidgets();
+
+ protected:
+ void createActions();
+ void setupDefShortcuts();
+
+ private:
+ void setupMenu();
+
+ QPlainTextEdit* textEdit = nullptr;
+ QMenu* contextMenu = nullptr;
+
+ private slots:
+ void modificationChanged(bool changed);
+ void deleteSelected();
+ void showCustomMenu(const QPoint& point);
+ void updateUndoAction(bool enabled);
+ void updateRedoAction(bool enabled);
+ void updateCopyAction(bool enabled);
+ void toggleTabFocus();
+};
+
+class GUI_API_EXPORT MultiEditorTextPlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Standard text data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Text")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORTEXT_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.cpp
new file mode 100644
index 0000000..8b49715
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.cpp
@@ -0,0 +1,90 @@
+#include "multieditortime.h"
+#include <QTimeEdit>
+
+QStringList MultiEditorTime::formats;
+
+MultiEditorTime::MultiEditorTime(QWidget *parent)
+ : MultiEditorDateTime(parent)
+{
+ showCalendars = false;
+ updateCalendarDisplay();
+ setDisplayFormat(formats.first());
+}
+
+QString MultiEditorTime::getTabLabel()
+{
+ return tr("Time");
+}
+
+void MultiEditorTime::staticInit()
+{
+ formats << "hh:mm:ss"
+ << "hh:mm:ss.zzz"
+ << "hh:mm";
+}
+
+QStringList MultiEditorTime::getParsingFormats()
+{
+ return formats;
+}
+
+MultiEditorWidget*MultiEditorTimePlugin::getInstance()
+{
+ return new MultiEditorTime();
+}
+
+bool MultiEditorTimePlugin::validFor(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::unknown:
+ break;
+ case DataType::TIME:
+ return true;
+ }
+ return false;
+}
+
+int MultiEditorTimePlugin::getPriority(const DataType& dataType)
+{
+ switch (dataType.getType())
+ {
+ case DataType::BLOB:
+ case DataType::BOOLEAN:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::INT:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::NONE:
+ case DataType::STRING:
+ case DataType::TEXT:
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::DATE:
+ case DataType::DATETIME:
+ case DataType::unknown:
+ break;
+ case DataType::TIME:
+ return 1;
+ }
+ return 10;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.h
new file mode 100644
index 0000000..56bf60e
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditortime.h
@@ -0,0 +1,38 @@
+#ifndef MULTIEDITORTIME_H
+#define MULTIEDITORTIME_H
+
+#include "multieditordatetime.h"
+#include "guiSQLiteStudio_global.h"
+
+class GUI_API_EXPORT MultiEditorTime : public MultiEditorDateTime
+{
+ public:
+ explicit MultiEditorTime(QWidget *parent = 0);
+
+ QString getTabLabel();
+
+ static void staticInit();
+
+ protected:
+ QStringList getParsingFormats();
+
+ private:
+ static QStringList formats;
+};
+
+class GUI_API_EXPORT MultiEditorTimePlugin : public BuiltInPlugin, public MultiEditorWidgetPlugin
+{
+ Q_OBJECT
+
+ SQLITESTUDIO_PLUGIN_AUTHOR("sqlitestudio.pl")
+ SQLITESTUDIO_PLUGIN_DESC("Time data editor.")
+ SQLITESTUDIO_PLUGIN_TITLE("Time")
+ SQLITESTUDIO_PLUGIN_VERSION(10000)
+
+ public:
+ MultiEditorWidget* getInstance();
+ bool validFor(const DataType& dataType);
+ int getPriority(const DataType& dataType);
+};
+
+#endif // MULTIEDITORTIME_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.cpp b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.cpp
new file mode 100644
index 0000000..caea9a5
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.cpp
@@ -0,0 +1,23 @@
+#include "multieditorwidget.h"
+
+MultiEditorWidget::MultiEditorWidget(QWidget *parent) :
+ QWidget(parent)
+{
+}
+
+void MultiEditorWidget::installEventFilter(QObject* filterObj)
+{
+ QObject::installEventFilter(filterObj);
+ foreach (QWidget* w, getNoScrollWidgets())
+ w->installEventFilter(filterObj);
+}
+
+bool MultiEditorWidget::isUpToDate() const
+{
+ return upToDate;
+}
+
+void MultiEditorWidget::setUpToDate(bool value)
+{
+ upToDate = value;
+}
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.h
new file mode 100644
index 0000000..14bac26
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidget.h
@@ -0,0 +1,33 @@
+#ifndef MULTIEDITORWIDGET_H
+#define MULTIEDITORWIDGET_H
+
+#include "guiSQLiteStudio_global.h"
+#include <QWidget>
+
+class GUI_API_EXPORT MultiEditorWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit MultiEditorWidget(QWidget *parent = 0);
+
+ virtual void setValue(const QVariant& value) = 0;
+ virtual QVariant getValue() = 0;
+ virtual void setReadOnly(bool value) = 0;
+ virtual QList<QWidget*> getNoScrollWidgets() = 0;
+ virtual QString getTabLabel() = 0;
+ virtual void focusThisWidget() = 0;
+
+ void installEventFilter(QObject* filterObj);
+
+ bool isUpToDate() const;
+ void setUpToDate(bool value);
+
+ private:
+ bool upToDate = true;
+
+ signals:
+ void valueModified();
+};
+
+#endif // MULTIEDITORWIDGET_H
diff --git a/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidgetplugin.h b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidgetplugin.h
new file mode 100644
index 0000000..011bde5
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/multieditor/multieditorwidgetplugin.h
@@ -0,0 +1,17 @@
+#ifndef MULTIEDITORWIDGETPLUGIN_H
+#define MULTIEDITORWIDGETPLUGIN_H
+
+#include "plugins/plugin.h"
+#include "datagrid/sqlquerymodelcolumn.h"
+
+class MultiEditorWidget;
+
+class GUI_API_EXPORT MultiEditorWidgetPlugin : public virtual Plugin
+{
+ public:
+ virtual MultiEditorWidget* getInstance() = 0;
+ virtual bool validFor(const DataType& dataType) = 0;
+ virtual int getPriority(const DataType& dataType) = 0;
+};
+
+#endif // MULTIEDITORWIDGETPLUGIN_H