diff options
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/dialogs')
25 files changed, 1275 insertions, 363 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.cpp index 7e084fb..26a9f52 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.cpp @@ -1,16 +1,18 @@ #include "aboutdialog.h" #include "ui_aboutdialog.h" #include "common/utils.h" -#include "sqlitestudio.h" #include "iconmanager.h" #include "services/extralicensemanager.h" #include "services/pluginmanager.h" +#include "services/sqliteextensionmanager.h" #include "formmanager.h" #include "iconmanager.h" +#include "mainwindow.h" #include <QDebug> #include <QFile> #include <QApplication> #include <QClipboard> +#include <QAction> AboutDialog::AboutDialog(InitialMode initialMode, QWidget *parent) : QDialog(parent), @@ -38,8 +40,8 @@ void AboutDialog::init(InitialMode initialMode) case DistributionType::PORTABLE: distName = tr("Portable distribution."); break; - case DistributionType::OSX_BOUNDLE: - distName = tr("MacOS X application boundle distribution."); + case DistributionType::OSX_BUNDLE: + distName = tr("MacOS X application bundle distribution."); break; case DistributionType::OS_MANAGED: distName = tr("Operating system managed distribution."); @@ -75,28 +77,21 @@ void AboutDialog::init(InitialMode initialMode) licenseContents.clear(); // Environment - ui->appDirEdit->setText(qApp->applicationDirPath()); - ui->cfgDirEdit->setText(CFG->getConfigDir()); - ui->pluginDirList->addItems(filterResourcePaths(PLUGINS->getPluginDirs())); - ui->iconDirList->addItems(filterResourcePaths(ICONMANAGER->getIconDirs())); - ui->formDirList->addItems(filterResourcePaths(FORMS->getFormDirs())); + ui->appDirEdit->setText(toNativePath(qApp->applicationDirPath())); + ui->cfgDirEdit->setText(toNativePath(CFG->getConfigDir())); + ui->pluginDirList->setPlainText(filterResourcePaths(PLUGINS->getPluginDirs()).join("\n")); + ui->iconDirList->setPlainText(filterResourcePaths(ICONMANAGER->getIconDirs()).join("\n")); + ui->formDirList->setPlainText(filterResourcePaths(FORMS->getFormDirs()).join("\n")); + ui->extensionDirList->setPlainText(filterResourcePaths(SQLITE_EXTENSIONS->getExtensionDirs()).join("\n")); ui->qtVerEdit->setText(QT_VERSION_STR); ui->sqlite3Edit->setText(CFG->getSqlite3Version()); - - QAction* copyAct; - for (QListWidget* w : {ui->pluginDirList, ui->iconDirList, ui->formDirList}) - { - copyAct = new QAction(tr("Copy"), w); - w->addAction(copyAct); - connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); - } } void AboutDialog::buildIndex() { static const QString entryTpl = QStringLiteral("<li>%1</li>"); QStringList entries; - for (const QString& idx : indexContents) + for (QString& idx : indexContents) entries += entryTpl.arg(idx); licenseContents.prepend(tr("<h3>Table of contents:</h3><ol>%2</ol>").arg(entries.join(""))); @@ -135,24 +130,8 @@ QStringList AboutDialog::filterResourcePaths(const QStringList& paths) if (path.startsWith(":")) continue; - output << path; + QString newPath = toNativePath(path); + output << newPath; } return output; } - -void AboutDialog::copy() -{ - QListWidget* list = dynamic_cast<QListWidget*>(sender()->parent()); - if (!list) - return; - - QList<QListWidgetItem*> items = list->selectedItems(); - if (items.size() == 0) - return; - - QStringList lines; - for (QListWidgetItem* item : items) - lines << item->text(); - - QApplication::clipboard()->setText(lines.join("\n")); -} diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.h index a43daec..73d891d 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.h @@ -34,9 +34,6 @@ class GUI_API_EXPORT AboutDialog : public QDialog Ui::AboutDialog *ui = nullptr; QStringList indexContents; QString licenseContents; - - private slots: - void copy(); }; #endif // ABOUTDIALOG_H diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.ui b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.ui index 16a6e1f..fda2099 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.ui +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/aboutdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>741</width> - <height>447</height> + <height>500</height> </rect> </property> <property name="windowTitle"> @@ -17,7 +17,7 @@ <item row="0" column="1"> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> - <number>0</number> + <number>2</number> </property> <widget class="QWidget" name="about"> <attribute name="title"> @@ -55,70 +55,51 @@ <string>Environment</string> </attribute> <layout class="QGridLayout" name="gridLayout_4"> - <item row="3" column="0"> - <widget class="QLabel" name="iconDirLabel"> - <property name="text"> - <string>Icon directories</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + <item row="1" column="2"> + <widget class="QLineEdit" name="cfgDirEdit"> + <property name="readOnly"> + <bool>true</bool> </property> </widget> </item> - <item row="2" column="2"> - <widget class="QListWidget" name="pluginDirList"> - <property name="contextMenuPolicy"> - <enum>Qt::ActionsContextMenu</enum> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> + <item row="7" column="2"> + <widget class="QLabel" name="sqlite3Edit"> + <property name="text"> + <string/> </property> </widget> </item> - <item row="4" column="0"> - <widget class="QLabel" name="formDirLabel"> + <item row="1" column="0"> + <widget class="QLabel" name="cfgDirLabel"> <property name="text"> - <string>Form directories</string> + <string>Configuration directory</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="3" column="2"> - <widget class="QListWidget" name="iconDirList"> - <property name="contextMenuPolicy"> - <enum>Qt::ActionsContextMenu</enum> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="pluginDirLabel"> + <item row="6" column="0"> + <widget class="QLabel" name="qtVerLabel"> <property name="text"> - <string>Plugin directories</string> + <string>Qt version:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLabel" name="cfgDirLabel"> - <property name="text"> - <string>Configuration directory</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + <item row="3" column="2"> + <widget class="QPlainTextEdit" name="iconDirList"> + <property name="readOnly"> + <bool>true</bool> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="appDirLabel"> + <item row="3" column="0"> + <widget class="QLabel" name="iconDirLabel"> <property name="text"> - <string>Application directory</string> + <string>Icon directories</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> @@ -126,12 +107,16 @@ </widget> </item> <item row="4" column="2"> - <widget class="QListWidget" name="formDirList"> - <property name="contextMenuPolicy"> - <enum>Qt::ActionsContextMenu</enum> + <widget class="QPlainTextEdit" name="formDirList"> + <property name="readOnly"> + <bool>true</bool> </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPlainTextEdit" name="pluginDirList"> + <property name="readOnly"> + <bool>true</bool> </property> </widget> </item> @@ -142,31 +127,34 @@ </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="qtVerLabel"> + <item row="6" column="2"> + <widget class="QLabel" name="qtVerEdit"> <property name="text"> - <string>Qt version:</string> + <string/> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="pluginDirLabel"> + <property name="text"> + <string>Plugin directories</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="5" column="2"> - <widget class="QLabel" name="qtVerEdit"> + <item row="0" column="0"> + <widget class="QLabel" name="appDirLabel"> <property name="text"> - <string/> + <string>Application directory</string> </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLineEdit" name="cfgDirEdit"> - <property name="readOnly"> - <bool>true</bool> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> - <item row="6" column="0"> + <item row="7" column="0"> <widget class="QLabel" name="sqlite3Label"> <property name="text"> <string>SQLite 3 version:</string> @@ -176,10 +164,30 @@ </property> </widget> </item> - <item row="6" column="2"> - <widget class="QLabel" name="sqlite3Edit"> + <item row="4" column="0"> + <widget class="QLabel" name="formDirLabel"> <property name="text"> - <string/> + <string>Form directories</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QPlainTextEdit" name="extensionDirList"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="extensionDirLabel"> + <property name="text"> + <string>SQLite extension directories</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.cpp index 1d7ba66..90f816f 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.cpp @@ -44,20 +44,21 @@ void BindParamsDialog::init() void BindParamsDialog::initEditors() { QStringList paramNames; - for (BindParam* param : bindParams) + for (BindParam*& param : bindParams) paramNames << param->originalName; MultiEditor* firstEditor = nullptr; MultiEditor* multiEditor = nullptr; QVector<QPair<QString, QVariant>> paramHistory = CFG->getBindParamHistory(paramNames); - for (BindParam* param : bindParams) + for (BindParam*& param : bindParams) { multiEditor = initEditor(param, paramHistory.size() > param->position ? paramHistory[param->position].second : QVariant()); if (firstEditor == nullptr) firstEditor = multiEditor; } - firstEditor->focusThisEditor(); + if (firstEditor) + firstEditor->focusThisEditor(); } MultiEditor* BindParamsDialog::initEditor(BindParam* param, const QVariant& cachedValue) diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.h index 666ffc4..99adca6 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/bindparamsdialog.h @@ -27,7 +27,7 @@ class BindParamsDialog : public QDialog static const int margins = 2; static const int spacing = 2; - static const int minimumFieldHeight = 80; + static const int minimumFieldHeight = 120; Ui::BindParamsDialog *ui; QVector<BindParam*> bindParams; diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.cpp index ebf9253..a217da6 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.cpp @@ -1,5 +1,6 @@ #include "columndialog.h" #include "common/unused.h" +#include "services/notifymanager.h" #include "ui_columndialog.h" #include "columndialogconstraintsmodel.h" #include "iconmanager.h" @@ -36,10 +37,6 @@ void ColumnDialog::init() ui->scale->setStrict(true, true); ui->precision->setStrict(true, true); - ui->typeCombo->addItem(""); - for (DataType::Enum type : DataType::getAllTypes()) - ui->typeCombo->addItem(DataType::toString(type)); - connect(ui->typeCombo, SIGNAL(currentTextChanged(QString)), this, SLOT(updateDataType())); constraintsModel = new ColumnDialogConstraintsModel(); @@ -54,7 +51,7 @@ void ColumnDialog::init() connect(ui->constraintsView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(editConstraint(QModelIndex))); connect(constraintsModel, SIGNAL(constraintsChanged()), this, SLOT(updateValidations())); connect(constraintsModel, SIGNAL(constraintsChanged()), this, SLOT(updateState())); - connect(ui->typeCombo, SIGNAL(currentTextChanged(const QString&)), this, SLOT(updateValidations())); + connect(ui->typeCombo, SIGNAL(currentTextChanged(QString)), this, SLOT(updateValidations())); connect(ui->scale, SIGNAL(modified()), this, SLOT(updateValidations())); connect(ui->precision, SIGNAL(modified()), this, SLOT(updateValidations())); @@ -617,7 +614,7 @@ void ColumnDialog::updateValidations() setValidState(tb, true); } - for (SqliteCreateTable::Column::Constraint* constr : column->constraints) + for (SqliteCreateTable::Column::Constraint*& constr : column->constraints) updateConstraint(constr); updateTypeValidations(); @@ -640,11 +637,40 @@ void ColumnDialog::setColumn(SqliteCreateTable::Column* value) constraintsModel->setColumn(column.data()); ui->name->setText(value->name); - if (value->type) + + SqliteCreateTable* createTable = dynamic_cast<SqliteCreateTable*>(value->parentStatement()); + if (createTable->strict) + { + ui->typeCombo->setEditable(false); + for (DataType::Enum& type : DataType::getStrictValues()) + ui->typeCombo->addItem(DataType::toString(type)); + + ui->scale->setVisible(false); + ui->precision->setVisible(false); + ui->sizeLabel->setVisible(false); + ui->sizeCommaLabel->setVisible(false); + + if (value->type) + { + int idx = ui->typeCombo->findText(value->type->name, Qt::MatchFixedString); + if (idx > -1) + ui->typeCombo->setCurrentIndex(idx); + else + notifyError(tr("Could not match valid STRICT table datatype from declared type: %1.").arg(value->type->name)); + } + } + else { - ui->typeCombo->setEditText(value->type->name); - ui->scale->setValue(value->type->scale, false); - ui->precision->setValue(value->type->precision, false); + ui->typeCombo->addItem(""); + for (DataType::Enum& type : DataType::getAllTypesForUiDropdown()) + ui->typeCombo->addItem(DataType::toString(type)); + + if (value->type) + { + ui->typeCombo->setEditText(value->type->name); + ui->scale->setValue(value->type->scale, false); + ui->precision->setValue(value->type->precision, false); + } } updateValidations(); diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.ui b/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.ui index 6094ab1..8ff75fd 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.ui +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/columndialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>467</width> - <height>393</height> + <height>431</height> </rect> </property> <property name="windowTitle"> @@ -37,7 +37,7 @@ </widget> </item> <item row="1" column="3"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="sizeCommaLabel"> <property name="text"> <string notr="true">,</string> </property> diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.cpp index be45873..8c80f6d 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.cpp @@ -1,6 +1,5 @@ #include "configdialog.h"
#include "ui_configdialog.h"
-#include "services/config.h"
#include "uiconfig.h"
#include "customconfigwidgetplugin.h"
#include "services/pluginmanager.h"
@@ -17,14 +16,18 @@ #include "plugins/confignotifiableplugin.h"
#include "mainwindow.h"
#include "common/unused.h"
-#include "sqlitestudio.h"
#include "configmapper.h"
#include "datatype.h"
#include "uiutils.h"
+#include "common/utils.h"
#include "translations.h"
#include "plugins/uiconfiguredplugin.h"
#include "dbtree/dbtree.h"
#include "common/compatibility.h"
+#include "windows/editorwindow.h"
+#include "syntaxhighlighterplugin.h"
+#include "sqleditor.h"
+#include "style.h"
#include <QSignalMapper>
#include <QLineEdit>
#include <QSpinBox>
@@ -39,7 +42,9 @@ #include <QTableWidget>
#include <QDesktopServices>
#include <QtUiTools/QUiLoader>
+#include <QItemDelegate>
#include <QKeySequenceEdit>
+#include <QPlainTextEdit>
#define GET_FILTER_STRING(Widget, WidgetType, Method) \
if (qobject_cast<WidgetType*>(Widget))\
@@ -50,6 +55,18 @@ if (w##WidgetType)\
return getFilterString(w##WidgetType) + " " + Widget->toolTip();
+class ConfigDialogItemDelegate : public QItemDelegate
+{
+ public:
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ QVariant userData = index.data(Qt::UserRole);
+ bool isCategory = userData.isValid() && userData.toBool();
+ QSize size = QItemDelegate::sizeHint(option, index);
+ return isCategory ? QSize(size.width(), size.height() * 1.7) : size;
+ }
+};
+
ConfigDialog::ConfigDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ConfigDialog)
@@ -59,12 +76,14 @@ ConfigDialog::ConfigDialog(QWidget *parent) : ConfigDialog::~ConfigDialog()
{
+ rollbackColorsConfig();
+
// Cancel transaction on CfgMain objects from plugins
rollbackPluginConfigs();
// Notify plugins about dialog being closed
UiConfiguredPlugin* cfgPlugin = nullptr;
- for (Plugin* plugin : PLUGINS->getLoadedPlugins())
+ for (Plugin*& plugin : PLUGINS->getLoadedPlugins())
{
cfgPlugin = dynamic_cast<UiConfiguredPlugin*>(plugin);
if (!cfgPlugin)
@@ -74,14 +93,14 @@ ConfigDialog::~ConfigDialog() }
// Delete UI and other resources
+ qDeleteAll(colorPreviewEditors);
delete ui;
safe_delete(configMapper);
- for (ConfigMapper* mapper : pluginConfigMappers.values())
+ for (ConfigMapper*& mapper : pluginConfigMappers)
delete mapper;
pluginConfigMappers.clear();
-
}
void ConfigDialog::configureDataEditors(const QString& dataTypeString)
@@ -161,6 +180,23 @@ QString ConfigDialog::getFilterString(QTableWidget *widget) return strList.join(" ");
}
+void ConfigDialog::showEvent(QShowEvent* event)
+{
+ UNUSED(event);
+ ui->categoriesTree->resizeColumnToContents(0);
+ int adjustedColumnWidth = ui->categoriesTree->columnWidth(0) + 4;
+ if (adjustedColumnWidth > ui->categoriesTree->width()) {
+ if (adjustedColumnWidth > (width() / 2))
+ adjustedColumnWidth = width() / 2;
+
+ QList<int> sizes = ui->splitter->sizes();
+ int rightPartSize = sizes[0] + sizes[1] - adjustedColumnWidth;
+ sizes[0] = adjustedColumnWidth;
+ sizes[1] = rightPartSize;
+ ui->splitter->setSizes(sizes);
+ }
+}
+
void ConfigDialog::init()
{
ui->setupUi(this);
@@ -184,12 +220,15 @@ void ConfigDialog::init() initDataEditors();
initShortcuts();
initLangs();
+ initTooltips();
+ initColors();
connect(ui->categoriesTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(switchPage(QTreeWidgetItem*)));
connect(ui->previewTabs, SIGNAL(currentChanged(int)), this, SLOT(updateStylePreview()));
connect(ui->activeStyleCombo, SIGNAL(currentTextChanged(QString)), this, SLOT(updateStylePreview()));
connect(ui->buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
connect(ui->hideBuiltInPluginsCheck, SIGNAL(toggled(bool)), this, SLOT(updateBuiltInPluginsVisibility()));
+ connect(ui->codeColorsResetBtn, SIGNAL(pressed()), this, SLOT(resetCodeSyntaxColors()));
QList<CfgEntry*> entries;
entries << CFG_UI.General.SortObjects
@@ -199,12 +238,13 @@ void ConfigDialog::init() << CFG_UI.General.ShowSystemObjects
<< CFG_UI.General.ShowVirtualTableLabels;
- for (CfgEntry* cfg : entries)
+ for (CfgEntry*& cfg : entries)
connect(cfg, SIGNAL(changed(QVariant)), this, SLOT(markRequiresSchemasRefresh()));
QStringList styles = QStyleFactory::keys();
styles.sort(Qt::CaseInsensitive);
ui->activeStyleCombo->addItems(styles);
+ ui->activeStyleCombo->setCurrentText(STYLE->name());
connect(ui->stackedWidget, SIGNAL(currentChanged(int)), this, SLOT(pageSwitched()));
@@ -214,8 +254,14 @@ void ConfigDialog::init() ui->updatesGroup->setVisible(false);
#endif
+ resettingColors = true;
load();
+ resettingColors = false;
+ colorChanged();
updateStylePreview();
+ updateColorsAfterLoad();
+
+ ui->categoriesTree->expandAll();
}
void ConfigDialog::load()
@@ -229,14 +275,28 @@ void ConfigDialog::load() void ConfigDialog::save()
{
if (MainWindow::getInstance()->currentStyle().compare(ui->activeStyleCombo->currentText(), Qt::CaseInsensitive) != 0)
+ {
+ QList<QWidget*> unmodifiedColors = prepareCodeSyntaxColorsForStyle();
+ bool wasDark = STYLE->isDark();
+
MainWindow::getInstance()->setStyle(ui->activeStyleCombo->currentText());
+ if (STYLE->isDark() != wasDark)
+ {
+ resettingColors = true; // to avoid mass events of color change on syntax page
+ adjustSyntaxColorsForStyle(unmodifiedColors);
+ resettingColors = false;
+ colorChanged();
+ }
+ }
+
QString loadedPlugins = collectLoadedPlugins();
storeSelectedFormatters();
CFG->beginMassSave();
CFG_CORE.General.LoadedPlugins.set(loadedPlugins);
configMapper->saveFromWidget(ui->stackedWidget, true);
commitPluginConfigs();
+ commitColorsConfig();
CFG->commitMassSave();
if (requiresSchemasRefresh)
@@ -302,7 +362,7 @@ void ConfigDialog::applyFilter(const QString &filter) QColor disabledColor = ui->categoriesTree->palette().color(QPalette::Disabled, QPalette::WindowText);
if (filter.isEmpty())
{
- for (QTreeWidgetItem* item : getAllCategoryItems())
+ for (QTreeWidgetItem*& item : getAllCategoryItems())
item->setForeground(0, normalColor);
return;
@@ -318,10 +378,11 @@ void ConfigDialog::applyFilter(const QString &filter) QHash<QWidget*, QTreeWidgetItem*> pageToCategoryItem = buildPageToCategoryItemMap();
QSet<QTreeWidgetItem*> matchedCategories;
- for (QWidget* page : pageToCategoryItem.keys())
+ for (auto it = pageToCategoryItem.keyBegin(), end = pageToCategoryItem.keyEnd(); it != end; ++it)
{
- for (QWidget* matched : matchedWidgets)
+ for (QWidget* matched : qAsConst(matchedWidgets))
{
+ QWidget* page = *it;
if (page->isAncestorOf(matched))
{
if (!pageToCategoryItem.contains(page))
@@ -336,10 +397,10 @@ void ConfigDialog::applyFilter(const QString &filter) }
}
- for (QTreeWidgetItem* item : getAllCategoryItems())
+ for (QTreeWidgetItem*& item : getAllCategoryItems())
item->setForeground(0, disabledColor);
- for (QTreeWidgetItem* item : matchedCategories)
+ for (QTreeWidgetItem* item : qAsConst(matchedCategories))
{
item->setForeground(0, normalColor);
while ((item = item->parent()) != nullptr)
@@ -350,7 +411,7 @@ void ConfigDialog::applyFilter(const QString &filter) QHash<QWidget*, QTreeWidgetItem*> ConfigDialog::buildPageToCategoryItemMap() const
{
QHash<QString,QTreeWidgetItem*> pageNameToCategoryItem;
- for (QTreeWidgetItem* item : getAllCategoryItems())
+ for (QTreeWidgetItem*& item : getAllCategoryItems())
pageNameToCategoryItem[item->statusTip(0)] = item;
QWidget* page = nullptr;
@@ -393,7 +454,7 @@ QList<MultiEditorWidgetPlugin*> ConfigDialog::getDefaultEditorsForType(DataType: });
QList<MultiEditorWidgetPlugin*> results;
- for (const PluginWithPriority& p: sortedPlugins)
+ for (PluginWithPriority& p: sortedPlugins)
results << p.second;
return results;
@@ -427,7 +488,7 @@ void ConfigDialog::updateDataTypeEditors() ui->dataEditorsAvailableList->sortItems();
- for (MultiEditorWidgetPlugin* plugin : sortedPlugins)
+ for (MultiEditorWidgetPlugin*& plugin : sortedPlugins)
addDataTypeEditor(plugin);
}
@@ -557,7 +618,7 @@ void ConfigDialog::addDataType(const QString& typeStr) void ConfigDialog::rollbackPluginConfigs()
{
CfgMain* mainCfg = nullptr;
- for (UiConfiguredPlugin* plugin : pluginConfigMappers.keys())
+ for (UiConfiguredPlugin*& plugin : pluginConfigMappers.keys())
{
mainCfg = plugin->getMainUiConfig();
if (mainCfg)
@@ -565,24 +626,68 @@ void ConfigDialog::rollbackPluginConfigs() }
}
+void ConfigDialog::rollbackColorsConfig()
+{
+ CFG_UI.Colors.rollback();
+}
+
void ConfigDialog::commitPluginConfigs()
{
CfgMain* mainCfg = nullptr;
- for (UiConfiguredPlugin* plugin : pluginConfigMappers.keys())
+ for (auto it = pluginConfigMappers.keyBegin(), end = pluginConfigMappers.keyEnd(); it != end; ++it)
{
- mainCfg = plugin->getMainUiConfig();
+ mainCfg = (*it)->getMainUiConfig();
if (mainCfg)
{
mainCfg->commit();
mainCfg->begin(); // be prepared for further changes after "Apply"
}
}
+
+ auto it = highlightingPluginForPreviewEditor.iterator();
+ while (it.hasNext())
+ {
+ auto item = it.next();
+ if (item.value()->getLanguageName() == "SQL")
+ continue;
+
+ item.value()->refreshFormats();
+ }
+}
+
+void ConfigDialog::commitColorsConfig()
+{
+ CFG_UI.Colors.commit();
+ CFG_UI.Colors.begin();
}
void ConfigDialog::connectMapperSignals(ConfigMapper* mapper)
{
- connect(mapper, SIGNAL(modified()), this, SLOT(markModified()));
- connect(mapper, SIGNAL(notifyEnabledWidgetModified(QWidget*, CfgEntry*, const QVariant&)), this, SLOT(notifyPluginsAboutModification(QWidget*, CfgEntry*, const QVariant&)));
+ connect(mapper, SIGNAL(modified(QWidget*)), this, SLOT(markModified()));
+ connect(mapper, SIGNAL(notifyEnabledWidgetModified(QWidget*,CfgEntry*,QVariant)), this, SLOT(notifyPluginsAboutModification(QWidget*,CfgEntry*,QVariant)));
+}
+
+QList<CfgMain*> ConfigDialog::getShortcutsCfgMains() const
+{
+ static const QString metaName = CFG_SHORTCUTS_METANAME;
+ QList<CfgMain*> mains;
+ for (CfgMain*& cfgMain : CfgMain::getInstances())
+ {
+ if (cfgMain->getMetaName() != metaName)
+ continue;
+
+ mains << cfgMain;
+ }
+ return mains;
+}
+
+QList<CfgCategory*> ConfigDialog::getShortcutsCfgCategories() const
+{
+ QList<CfgCategory*> categories;
+ for (CfgMain*& cfgMain : getShortcutsCfgMains())
+ categories.append(cfgMain->getCategories().values());
+
+ return categories;
}
void ConfigDialog::updateDataTypeListState()
@@ -792,23 +897,23 @@ void ConfigDialog::detailsClicked(const QString& pluginName) // Rows
QStringList rows;
- rows << row.arg(tr("Description:", "plugin details")).arg(PLUGINS->getDescription(pluginName));
- rows << row.arg(tr("Category:", "plugin details")).arg(type->getTitle());
- rows << row.arg(tr("Version:", "plugin details")).arg(PLUGINS->getPrintableVersion(pluginName));
- rows << row.arg(tr("Author:", "plugin details")).arg(PLUGINS->getAuthor(pluginName));
+ rows << row.arg(tr("Description:", "plugin details"), PLUGINS->getDescription(pluginName));
+ rows << row.arg(tr("Category:", "plugin details"), type->getTitle());
+ rows << row.arg(tr("Version:", "plugin details"), PLUGINS->getPrintableVersion(pluginName));
+ rows << row.arg(tr("Author:", "plugin details"), PLUGINS->getAuthor(pluginName));
rows << hline;
- rows << row.arg(tr("Internal name:", "plugin details")).arg(pluginName);
- rows << row.arg(tr("Dependencies:", "plugin details")).arg(PLUGINS->getDependencies(pluginName).join(", "));
- rows << row.arg(tr("Conflicts:", "plugin details")).arg(PLUGINS->getConflicts(pluginName).join(", "));
+ rows << row.arg(tr("Internal name:", "plugin details"), pluginName);
+ rows << row.arg(tr("Dependencies:", "plugin details"), PLUGINS->getDependencies(pluginName).join(", "));
+ rows << row.arg(tr("Conflicts:", "plugin details"), PLUGINS->getConflicts(pluginName).join(", "));
// Message
- QString pluginDetails = details.arg(PLUGINS->getTitle(pluginName)).arg(rows.join(""));
+ QString pluginDetails = details.arg(PLUGINS->getTitle(pluginName), rows.join(""));
QMessageBox::information(this, tr("Plugin details"), pluginDetails);
}
void ConfigDialog::failedToLoadPlugin(const QString& pluginName)
{
- QTreeWidgetItem* theItem = itemToPluginNameMap.valueByRight(pluginName);
+ QTreeWidgetItem* theItem = pluginListItemToPluginNameMap.valueByRight(pluginName);
if (!theItem)
{
qWarning() << "Plugin" << pluginName << "failed to load, but it could not be found on the plugins list in ConfigDialog.";
@@ -833,7 +938,7 @@ void ConfigDialog::loadUnloadPlugin(QTreeWidgetItem* item, int column) if (column != 0)
return;
- QString pluginName = itemToPluginNameMap.valueByLeft(item);
+ QString pluginName = pluginListItemToPluginNameMap.valueByLeft(item);
if (PLUGINS->isBuiltIn(pluginName))
return;
@@ -866,6 +971,10 @@ void ConfigDialog::pluginAboutToUnload(Plugin* plugin, PluginType* type) if (notifiablePlugin && notifiablePlugins.contains(notifiablePlugin))
notifiablePlugins.removeOne(notifiablePlugin);
+ // Update code colors page
+ if (type->isForPluginType<SyntaxHighlighterPlugin>())
+ highlighterPluginUnloaded(dynamic_cast<SyntaxHighlighterPlugin*>(plugin));
+
// Deinit page
deinitPluginPage(plugin);
@@ -879,6 +988,14 @@ void ConfigDialog::pluginLoaded(Plugin* plugin, PluginType* type, bool skipConfi if (type->isForPluginType<CodeFormatterPlugin>())
codeFormatterLoaded();
+ // Update code colors page
+ if (type->isForPluginType<SyntaxHighlighterPlugin>())
+ highlighterPluginLoaded(dynamic_cast<SyntaxHighlighterPlugin*>(plugin));
+
+ QTreeWidgetItem* listItem = pluginListItemToPluginNameMap.valueByRight(plugin->getName());
+ if (listItem && listItem->checkState(0) == Qt::Unchecked)
+ listItem->setCheckState(0, Qt::Checked);
+
// Init page
if (!initPluginPage(plugin, skipConfigLoading))
return;
@@ -901,7 +1018,9 @@ void ConfigDialog::pluginLoaded(Plugin* plugin, PluginType* type, bool skipConfi void ConfigDialog::pluginUnloaded(const QString& pluginName, PluginType* type)
{
- UNUSED(pluginName);
+ QTreeWidgetItem* item = pluginListItemToPluginNameMap.valueByRight(pluginName);
+ if (item && item->checkState(0) == Qt::Checked)
+ item->setCheckState(0, Qt::Unchecked);
// Update formatters page
if (type->isForPluginType<CodeFormatterPlugin>())
@@ -918,7 +1037,7 @@ void ConfigDialog::updatePluginCategoriesVisibility() void ConfigDialog::updateBuiltInPluginsVisibility()
{
bool hideBuiltIn = ui->hideBuiltInPluginsCheck->isChecked();
- QHashIterator<QTreeWidgetItem*,QString> it = itemToPluginNameMap.iterator();
+ QHashIterator<QTreeWidgetItem*,QString> it = pluginListItemToPluginNameMap.iterator();
while (it.hasNext())
{
it.next();
@@ -929,6 +1048,13 @@ void ConfigDialog::updateBuiltInPluginsVisibility() }
}
+void ConfigDialog::refreshColorsInSyntaxHighlighters()
+{
+ auto it = highlightingPluginForPreviewEditor.iterator();
+ while (it.hasNext())
+ it.next().value()->refreshFormats();
+}
+
void ConfigDialog::applyShortcutsFilter(const QString &filter)
{
QTreeWidgetItem* categoryItem = nullptr;
@@ -964,10 +1090,144 @@ void ConfigDialog::markRequiresSchemasRefresh() void ConfigDialog::notifyPluginsAboutModification(QWidget*, CfgEntry* key, const QVariant& value)
{
- for (ConfigNotifiablePlugin* plugin : notifiablePlugins)
+ for (ConfigNotifiablePlugin*& plugin : notifiablePlugins)
plugin->configModified(key, value);
}
+void ConfigDialog::resetCodeSyntaxColors()
+{
+ resettingColors = true;
+ for (QWidget*& widget : configMapper->getAllConfigWidgets(ui->commonCodeColorsGroup))
+ configMapper->applyConfigDefaultValueToWidget(widget);
+
+ resettingColors = false;
+ colorChanged();
+}
+
+void ConfigDialog::colorChanged()
+{
+ refreshColorsInSyntaxHighlighters();
+ for (QSyntaxHighlighter*& highligter : colorPreviewHighlighters)
+ highligter->rehighlight();
+
+ if (codePreviewSqlEditor)
+ codePreviewSqlEditor->colorsConfigChanged();
+}
+
+void ConfigDialog::adjustSyntaxColorsForStyle(QList<QWidget*>& unmodifiedColors)
+{
+ for (QWidget*& w : unmodifiedColors)
+ configMapper->applyConfigDefaultValueToWidget(w);
+}
+
+void ConfigDialog::highlighterPluginLoaded(SyntaxHighlighterPlugin* plugin)
+{
+ QPlainTextEdit* editor = nullptr;
+ if (plugin->getLanguageName() == "SQL")
+ {
+ // For SQL there is assumed just one, built-in plugin
+ codePreviewSqlEditor = new SqlEditor(ui->codeColorsPreviewTabWidget);
+ codePreviewSqlEditor->setShowLineNumbers(false);
+ codePreviewSqlEditor->setCurrentQueryHighlighting(true);
+ editor = codePreviewSqlEditor;
+ }
+ else
+ {
+ editor = new QPlainTextEdit(ui->codeColorsPreviewTabWidget);
+ editor->setFont(CFG_UI.Fonts.SqlEditor.get());
+ colorPreviewHighlighters << plugin->createSyntaxHighlighter(editor);
+ }
+
+ editor->setPlainText(plugin->previewSampleCode());
+ editor->setReadOnly(true);
+ colorPreviewEditors << editor;
+ highlightingPluginForPreviewEditor.insert(editor, plugin);
+ ui->codeColorsPreviewTabWidget->addTab(editor, plugin->getLanguageName());
+}
+
+void ConfigDialog::highlighterPluginUnloaded(SyntaxHighlighterPlugin* plugin)
+{
+ QPlainTextEdit* editor = highlightingPluginForPreviewEditor.valueByRight(plugin);
+ if (!editor)
+ {
+ qCritical() << "Highlighter plugin unloaded for which there is no preview editor! Application crash is possible. Plugin:" << plugin->getName();
+ return;
+ }
+
+ QTextDocument* document = editor->document();
+ QSyntaxHighlighter* highlighter = findFirst<QSyntaxHighlighter>(colorPreviewHighlighters, [document](auto highlighter) {return highlighter->document() == document;});
+
+ ui->codeColorsPreviewTabWidget->removeTab(ui->codeColorsPreviewTabWidget->indexOf(editor));
+ colorPreviewHighlighters.removeOne(highlighter);
+ colorPreviewEditors.removeOne(editor);
+ delete editor;
+
+ highlightingPluginForPreviewEditor.removeRight(plugin);
+}
+
+QList<QWidget*> ConfigDialog::prepareCodeSyntaxColorsForStyle()
+{
+ QList<QWidget*> unmodified;
+ for (QWidget*& w : configMapper->getAllConfigWidgets(ui->commonCodeColorsGroup))
+ {
+ CfgEntry* entry = configMapper->getConfigForWidget(w);
+ if (entry->getDefaultValue() == entry->get())
+ unmodified << w;
+ }
+ return unmodified;
+}
+
+void ConfigDialog::initColors()
+{
+ CFG_UI.Colors.begin();
+ connect(configMapper, &ConfigMapper::modified, this,
+ [this](QWidget* widget)
+ {
+ CfgEntry* key = configMapper->getBindConfigForWidget(widget);
+ if (!key)
+ {
+ qCritical() << "Missing CfgEntry in Colors configuration for widget" << widget->objectName();
+ return;
+ }
+
+ if (key->getCategory() != CFG_UI.Colors)
+ return;
+
+ configMapper->saveFromWidget(widget, key);
+ if (key->getName().endsWith("Custom"))
+ toggleColorButtonState(key);
+
+ if (resettingColors)
+ return;
+
+ colorChanged();
+ });
+}
+
+void ConfigDialog::updateColorsAfterLoad()
+{
+ QHash<QString, CfgEntry*> entries = CFG_UI.Colors.getEntries();
+ auto it = entries.begin();
+ while (it != entries.end())
+ {
+ if (it.key().endsWith("Custom"))
+ toggleColorButtonState(it.value());
+
+ it++;
+ }
+}
+
+void ConfigDialog::toggleColorButtonState(CfgEntry* colorCheckEntry)
+{
+ CfgEntry* colorKey = colorCheckEntry->getCategory()->getEntryByName(colorCheckEntry->getName().chopped(6));
+ if (colorKey)
+ {
+ QWidget* button = configMapper->getBindWidgetForConfig(colorKey);
+ if (button)
+ button->setEnabled(colorCheckEntry->get().toBool());
+ }
+}
+
void ConfigDialog::updatePluginCategoriesVisibility(QTreeWidgetItem* categoryItem)
{
categoryItem->setHidden(categoryItem->childCount() == 0);
@@ -976,7 +1236,7 @@ void ConfigDialog::updatePluginCategoriesVisibility(QTreeWidgetItem* categoryIte QString ConfigDialog::collectLoadedPlugins() const
{
QStringList loaded;
- QHashIterator<QTreeWidgetItem*,QString> it = itemToPluginNameMap.iterator();
+ QHashIterator<QTreeWidgetItem*,QString> it = pluginListItemToPluginNameMap.iterator();
while (it.hasNext())
{
it.next();
@@ -1147,8 +1407,7 @@ QTreeWidgetItem* ConfigDialog::createPluginsTypeItem(const QString& widgetName, if (item->statusTip(0) == widgetName)
return item;
}
- return nullptr;
-
+ return new QTreeWidgetItem({title});
}
QTreeWidgetItem* ConfigDialog::getItemByTitle(const QString& title) const
@@ -1195,23 +1454,24 @@ void ConfigDialog::initPlugins() // Recreate
QTreeWidgetItem *typeItem = nullptr;
- for (PluginType* pluginType : PLUGINS->getPluginTypes())
+ for (PluginType*& pluginType : PLUGINS->getPluginTypes())
{
typeItem = createPluginsTypeItem(pluginType->getConfigUiForm(), pluginType->getTitle());
- if (!typeItem)
- continue;
item->addChild(typeItem);
pluginTypeToItemMap[pluginType] = typeItem;
- for (Plugin* plugin : pluginType->getLoadedPlugins())
+ for (Plugin*& plugin : pluginType->getLoadedPlugins())
pluginLoaded(plugin, pluginType, true);
}
updatePluginCategoriesVisibility();
+ // Using old connect() syntax, becase the pointer syntax does not work correctly with signals declared in an interface class.
+ // At least that's the case with Qt 5.15.2.
connect(PLUGINS, SIGNAL(loaded(Plugin*,PluginType*)), this, SLOT(pluginLoaded(Plugin*,PluginType*)));
connect(PLUGINS, SIGNAL(aboutToUnload(Plugin*,PluginType*)), this, SLOT(pluginAboutToUnload(Plugin*,PluginType*)));
+ connect(PLUGINS, SIGNAL(unloaded(QString,PluginType*)), this, SLOT(pluginUnloaded(QString,PluginType*)));
}
void ConfigDialog::initPluginsPage()
@@ -1255,7 +1515,7 @@ void ConfigDialog::initPluginsPage() categoryRow = 0;
QList<PluginType*> pluginTypes = PLUGINS->getPluginTypes();
sSort(pluginTypes, PluginType::nameLessThan);
- for (PluginType* pluginType : pluginTypes)
+ for (PluginType*& pluginType : pluginTypes)
{
category = new QTreeWidgetItem({pluginType->getTitle()});
font.setItalic(false);
@@ -1275,7 +1535,7 @@ void ConfigDialog::initPluginsPage() itemRow = 0;
pluginNames = pluginType->getAllPluginNames();
sSort(pluginNames);
- for (const QString& pluginName : pluginNames)
+ for (QString& pluginName : pluginNames)
{
builtIn = PLUGINS->isBuiltIn(pluginName);
title = PLUGINS->getTitle(pluginName);
@@ -1290,10 +1550,10 @@ void ConfigDialog::initPluginsPage() category->addChild(item);
- itemToPluginNameMap.insert(item, pluginName);
+ pluginListItemToPluginNameMap.insert(item, pluginName);
// Details button
- detailsLabel = new QLabel(QString("<a href='%1'>%2</a> ").arg(pluginName).arg(tr("Details")), ui->pluginsList);
+ detailsLabel = new QLabel(QString("<a href='%1'>%2</a> ").arg(pluginName, tr("Details")), ui->pluginsList);
detailsLabel->setAlignment(Qt::AlignRight);
itemIndex = ui->pluginsList->model()->index(itemRow, 1, categoryIndex);
ui->pluginsList->setIndexWidget(itemIndex, detailsLabel);
@@ -1322,10 +1582,10 @@ void ConfigDialog::initPluginsPage() bool ConfigDialog::initPluginPage(Plugin* plugin, bool skipConfigLoading)
{
- if (!dynamic_cast<UiConfiguredPlugin*>(plugin))
+ UiConfiguredPlugin* cfgPlugin = dynamic_cast<UiConfiguredPlugin*>(plugin);
+ if (!cfgPlugin)
return false;
- UiConfiguredPlugin* cfgPlugin = dynamic_cast<UiConfiguredPlugin*>(plugin);
QString pluginName = plugin->getName();
QString formName = cfgPlugin->getConfigUiForm();
QWidget* widget = FORMS->createWidget(formName);
@@ -1398,7 +1658,7 @@ void ConfigDialog::initDataEditors() sSort(dataTypeList);
QListWidgetItem* item = nullptr;
- for (const QString& type : dataTypeList)
+ for (QString& type : dataTypeList)
{
item = new QListWidgetItem(type);
if (!DataType::getAllNames().contains(type))
@@ -1441,49 +1701,30 @@ void ConfigDialog::initShortcuts() ui->shortcutsTable->header()->setSectionResizeMode(2, QHeaderView::Fixed);
ui->shortcutsTable->header()->resizeSection(1, 150);
ui->shortcutsTable->header()->resizeSection(2, 26);
+ ui->shortcutsTable->header()->resizeSection(3, 26);
ui->shortcutsFilterEdit->setClearButtonEnabled(true);
new UserInputFilter(ui->shortcutsFilterEdit, this, SLOT(applyShortcutsFilter(QString)));
- static const QString metaName = CFG_SHORTCUTS_METANAME;
- QList<CfgCategory*> categories;
- for (CfgMain* cfgMain : CfgMain::getInstances())
- {
- if (cfgMain->getMetaName() != metaName)
- continue;
-
- for (CfgCategory* cat : cfgMain->getCategories().values())
- categories << cat;
- }
+ QList<CfgCategory*> categories = getShortcutsCfgCategories();
+ ui->shortcutsTable->setItemDelegate(new ConfigDialogItemDelegate());
sSort(categories, [](CfgCategory* cat1, CfgCategory* cat2) -> bool
{
return cat1->getTitle().compare(cat2->getTitle()) < 0;
});
- for (CfgCategory* cat : categories)
+ for (CfgCategory*& cat : categories)
initShortcuts(cat);
}
void ConfigDialog::initShortcuts(CfgCategory *cfgCategory)
{
- QTreeWidgetItem* item = nullptr;
- QFont font;
- QModelIndex categoryIndex;
- QModelIndex itemIndex;
- QKeySequenceEdit *sequenceEdit = nullptr;
- QToolButton* clearButton = nullptr;
- QString title;
- QSize itemSize;
-
// Font and metrics
- item = new QTreeWidgetItem({""});
- font = item->font(0);
-
- QFontMetrics fm(font);
- itemSize = QSize(-1, (fm.ascent() + fm.descent() + 4));
-
- delete item;
+ QTreeWidgetItem item({""});
+ QFont font = item.font(0);
+// QFontMetrics fm(font);
+// QSize itemSize = QSize(-1, -1);
// Creating...
QBrush categoryBg = ui->shortcutsTable->palette().button();
@@ -1493,47 +1734,63 @@ void ConfigDialog::initShortcuts(CfgCategory *cfgCategory) font.setItalic(false);
font.setBold(true);
category->setFont(0, font);
- for (int i = 0; i < 3; i++)
+ for (int i = 0; i < 4; i++)
{
+ category->setData(i, Qt::UserRole, true);
category->setBackground(i, categoryBg);
category->setForeground(i, categoryFg);
}
- category->setSizeHint(0, itemSize);
+// category->setSizeHint(0, itemSize);
category->setFlags(category->flags() ^ Qt::ItemIsSelectable);
ui->shortcutsTable->addTopLevelItem(category);
int categoryRow = ui->shortcutsTable->topLevelItemCount() - 1;
- categoryIndex = ui->shortcutsTable->model()->index(categoryRow, 0);
+ QModelIndex categoryIndex = ui->shortcutsTable->model()->index(categoryRow, 0);
int itemRow = 0;
QStringList entryNames = cfgCategory->getEntries().keys();
sSort(entryNames);
- for (const QString& entryName : entryNames)
+ for (QString& entryName : entryNames)
{
+ CfgEntry* cfgEntry = cfgCategory->getEntries()[entryName];
+
// Title
- title = cfgCategory->getEntries()[entryName]->getTitle();
- item = new QTreeWidgetItem(category, {title});
+ QString title = cfgEntry->getTitle();
+ new QTreeWidgetItem(category, {title});
// Key edit
- sequenceEdit = new QKeySequenceEdit(ui->shortcutsTable);
+ QKeySequenceEdit* sequenceEdit = new QKeySequenceEdit(ui->shortcutsTable);
sequenceEdit->setFixedWidth(150);
- sequenceEdit->setProperty("cfg", cfgCategory->getEntries()[entryName]->getFullKey());
- itemIndex = ui->shortcutsTable->model()->index(itemRow, 1, categoryIndex);
+ sequenceEdit->setProperty("cfg", cfgEntry->getFullKey());
+ QModelIndex itemIndex = ui->shortcutsTable->model()->index(itemRow, 1, categoryIndex);
ui->shortcutsTable->setIndexWidget(itemIndex, sequenceEdit);
configMapper->addExtraWidget(sequenceEdit);
// Clear button
- clearButton = new QToolButton(ui->shortcutsTable);
+ QToolButton* clearButton = new QToolButton(ui->shortcutsTable);
clearButton->setIcon(ICONS.CLEAR_LINEEDIT);
- connect(clearButton, &QToolButton::clicked, [this, sequenceEdit]()
+ clearButton->setToolTip(tr("Clear hotkey for this action"));
+ connect(clearButton, &QToolButton::clicked, this, [this, sequenceEdit]()
{
sequenceEdit->clear();
this->markModified();
-
});
itemIndex = ui->shortcutsTable->model()->index(itemRow, 2, categoryIndex);
ui->shortcutsTable->setIndexWidget(itemIndex, clearButton);
+ // Restore default value button
+ QToolButton* defaultButton = new QToolButton(ui->shortcutsTable);
+ defaultButton->setIcon(ICONS.RESTORE_DEFAULT);
+ defaultButton->setToolTip(tr("Restore original hotkey for this action"));
+ connect(defaultButton, &QToolButton::clicked, this, [this, sequenceEdit, cfgEntry]()
+ {
+ cfgEntry->reset();
+ sequenceEdit->setKeySequence(QKeySequence::fromString(cfgEntry->get().toString()));
+ this->markModified();
+ });
+ itemIndex = ui->shortcutsTable->model()->index(itemRow, 3, categoryIndex);
+ ui->shortcutsTable->setIndexWidget(itemIndex, defaultButton);
+
itemRow++;
}
@@ -1545,7 +1802,9 @@ void ConfigDialog::initLangs() QMap<QString, QString> langs = getAvailableLanguages();
int idx = 0;
int selected = -1;
- for (const QString& lang : langs.keys())
+ QStringList langList = langs.keys();
+ strSort(langList, Qt::CaseInsensitive);
+ for (QString& lang : langList)
{
ui->langCombo->addItem(lang, langs[lang]);
if (langs[lang] == SQLITESTUDIO->getCurrentLang())
@@ -1557,6 +1816,21 @@ void ConfigDialog::initLangs() ui->langCombo->setCurrentIndex(selected);
}
+void ConfigDialog::initTooltips()
+{
+ ui->execQueryUnderCursorCheck->setToolTip(ui->execQueryUnderCursorCheck->toolTip().arg(
+ GET_SHORTCUT_ENTRY(EditorWindow, EXEC_ONE_QUERY)->get().toString(),
+ GET_SHORTCUT_ENTRY(EditorWindow, EXEC_ALL_QUERIES)->get().toString()
+ ));
+
+ setValidStateTooltip(ui->commonCodeColorsGroup,
+ tr("Here you can configure colors for code syntax highlighting. "
+ "They are shared across different languages - not only for SQL, but also JavaScript and others. "
+ "By default a theme-based color is used. To define your own color, enable a custom color "
+ "by selecting a checkbox next to a particular color."));
+
+}
+
bool ConfigDialog::isPluginCategoryItem(QTreeWidgetItem *item) const
{
return item->parent() && item->parent()->parent() && item->parent()->parent() == getPluginsCategoryItem();
diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.h index f0ab1de..7f5abb3 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.h @@ -26,6 +26,13 @@ class ConfigMapper; class MultiEditorWidgetPlugin;
class ConfigNotifiablePlugin;
class UiConfiguredPlugin;
+class SyntaxHighlighterPlugin;
+class QPlainTextEdit;
+class QSyntaxHighlighter;
+class SqlEditor;
+
+#define CFG_UI_NAME "Ui"
+#define CFG_COLORS_NAME "Colors"
class GUI_API_EXPORT ConfigDialog : public QDialog
{
@@ -43,6 +50,9 @@ class GUI_API_EXPORT ConfigDialog : public QDialog static QString getFilterString(QListWidget* widget);
static QString getFilterString(QTableWidget* widget);
+ protected:
+ void showEvent(QShowEvent* event);
+
private:
void init();
void load();
@@ -57,6 +67,10 @@ class GUI_API_EXPORT ConfigDialog : public QDialog void initShortcuts();
void initShortcuts(CfgCategory* cfgCategory);
void initLangs();
+ void initTooltips();
+ void initColors();
+ void updateColorsAfterLoad();
+ void toggleColorButtonState(CfgEntry* colorCheckEntry);
void applyStyle(QWidget* widget, QStyle* style);
QTreeWidgetItem* getPluginsCategoryItem() const;
QTreeWidgetItem* getPluginsCategoryItem(PluginType* type) const;
@@ -83,13 +97,23 @@ class GUI_API_EXPORT ConfigDialog : public QDialog void setPluginNamesForDataTypeItem(QListWidgetItem* typeItem, const QStringList& pluginNames);
void addDataType(const QString& typeStr);
void rollbackPluginConfigs();
+ void rollbackColorsConfig();
void commitPluginConfigs();
+ void commitColorsConfig();
void connectMapperSignals(ConfigMapper* mapper);
+ QList<CfgMain*> getShortcutsCfgMains() const;
+ QList<CfgCategory*> getShortcutsCfgCategories() const;
+ void refreshColorsInSyntaxHighlighters();
+ void colorChanged();
+ QList<QWidget*> prepareCodeSyntaxColorsForStyle();
+ void adjustSyntaxColorsForStyle(QList<QWidget*>& unmodifiedColors);
+ void highlighterPluginLoaded(SyntaxHighlighterPlugin* plugin);
+ void highlighterPluginUnloaded(SyntaxHighlighterPlugin* plugin);
Ui::ConfigDialog *ui = nullptr;
QStyle* previewStyle = nullptr;
QHash<QString,QWidget*> nameToPage;
- BiHash<QTreeWidgetItem*,QString> itemToPluginNameMap;
+ BiHash<QTreeWidgetItem*,QString> pluginListItemToPluginNameMap;
QHash<PluginType*,QTreeWidgetItem*> pluginTypeToItemMap;
QHash<Plugin*,QTreeWidgetItem*> pluginToItemMap;
QHash<QString,QComboBox*> formatterLangToPluginComboMap;
@@ -102,6 +126,11 @@ class GUI_API_EXPORT ConfigDialog : public QDialog bool modifiedFlag = false;
QList<ConfigNotifiablePlugin*> notifiablePlugins;
bool requiresSchemasRefresh = false;
+ QList<QPlainTextEdit*> colorPreviewEditors;
+ SqlEditor* codePreviewSqlEditor = nullptr;
+ QList<QSyntaxHighlighter*> colorPreviewHighlighters;
+ BiHash<QPlainTextEdit*, SyntaxHighlighterPlugin*> highlightingPluginForPreviewEditor;
+ bool resettingColors = false;
private slots:
void refreshFormattersPage();
@@ -138,6 +167,7 @@ class GUI_API_EXPORT ConfigDialog : public QDialog void applyShortcutsFilter(const QString& filter);
void markRequiresSchemasRefresh();
void notifyPluginsAboutModification(QWidget*, CfgEntry* key, const QVariant& value);
+ void resetCodeSyntaxColors();
public slots:
void accept();
diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.ui b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.ui index 4452f63..475d7b0 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.ui +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/configdialog.ui @@ -6,8 +6,8 @@ <rect>
<x>0</x>
<y>0</y>
- <width>770</width>
- <height>539</height>
+ <width>866</width>
+ <height>580</height>
</rect>
</property>
<property name="windowTitle">
@@ -148,6 +148,18 @@ <normaloff>:/icons/img/config_font.png</normaloff>:/icons/img/config_font.png</iconset>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>Code colors</string>
+ </property>
+ <property name="statusTip">
+ <string notr="true">codeColorsPage</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../icons.qrc">
+ <normaloff>:/icons/img/config_colors.png</normaloff>:/icons/img/config_colors.png</iconset>
+ </property>
+ </item>
</item>
<item>
<property name="text">
@@ -163,6 +175,18 @@ </item>
<item>
<property name="text">
+ <string>Code assistant</string>
+ </property>
+ <property name="statusTip">
+ <string notr="true">codeAssistantPage</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../icons.qrc">
+ <normaloff>:/icons/img/code_assistant.png</normaloff>:/icons/img/code_assistant.png</iconset>
+ </property>
+ </item>
+ <item>
+ <property name="text">
<string>Data browsing</string>
</property>
<property name="statusTip">
@@ -217,7 +241,7 @@ </sizepolicy>
</property>
<property name="currentIndex">
- <number>1</number>
+ <number>4</number>
</property>
<widget class="QWidget" name="databaseListPage">
<layout class="QVBoxLayout" name="verticalLayout_36">
@@ -395,8 +419,8 @@ <rect>
<x>0</x>
<y>0</y>
- <width>564</width>
- <height>540</height>
+ <width>433</width>
+ <height>718</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_34">
@@ -406,41 +430,16 @@ <string>Data browsing and editing</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="2">
- <widget class="QSpinBox" name="rowsPerPageSpin">
- <property name="maximumSize">
- <size>
- <width>150</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>99999</number>
- </property>
- <property name="cfg" stdset="0">
- <string notr="true">General.NumberOfRowsPerPage</string>
- </property>
- </widget>
- </item>
<item row="2" column="2">
- <widget class="QSpinBox" name="initColWidthLimitSpin">
+ <widget class="QSpinBox" name="memPopulConfigsCheck">
<property name="toolTip">
- <string><p>When the data is read into grid view columns width is automatically adjusted. This value limits the initial width for the adjustment, but user can still resize the column manually over this limit.</p></string>
- </property>
- <property name="minimum">
- <number>10</number>
+ <string><p>Maximum number of configurations of Populate Table dialog stored in configuration. Value of 100 should be sufficient.</p></string>
</property>
<property name="maximum">
- <number>99999</number>
- </property>
- <property name="value">
- <number>600</number>
+ <number>999999</number>
</property>
<property name="cfg" stdset="0">
- <string notr="true">General.MaxInitialColumnWith</string>
+ <string notr="true">General.PopulateHistorySize</string>
</property>
</widget>
</item>
@@ -452,16 +451,42 @@ </widget>
</item>
<item row="2" column="0" colspan="2">
- <widget class="QLabel" name="initColWidthLimitLabel">
+ <widget class="QLabel" name="memPopulConfigsLabel">
<property name="toolTip">
- <string><p>When the data is read into grid view columns width is automatically adjusted. This value limits the initial width for the adjustment, but user can still resize the column manually over this limit.</p></string>
+ <string><p>Maximum number of configurations of Populate Table dialog stored in configuration. Value of 100 should be sufficient.</p></string>
+ </property>
+ <property name="text">
+ <string>Number of memorized table populating configurations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QCheckBox" name="limitColumnsVsRowsCheck">
+ <property name="toolTip">
+ <string><html><head/><body><p>If query results contain dozens (or hundreds) of columns, it is more likely that it will exhaust free memory of your computer by loading several gigabytes of data at once. SQLiteStudio may try to limit number of results displayed on one page in such cases to protect your computer. If you know that you don't work with big values in database, you can disable this limit and you will always see as many rows as defined per page.</p></body></html></string>
</property>
<property name="text">
- <string>Limit initial data column width to (in pixels):</string>
+ <string>Limit number of rows for in case of dozens of columns</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.LimitRowsForManyColumns</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3">
+ <widget class="QCheckBox" name="tolltipInDataViewCheck">
+ <property name="toolTip">
+ <string><p>When this is enabled and user holds mouse pointer over a cell in any data view (query results, a table data, a view data) a tooltip will appear with details about the cell - it includes details like column data type, constraints, ROWID and others.</p></string>
+ </property>
+ <property name="text">
+ <string>Show column and row details tooltip in data view</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.ShowDataViewTooltips</string>
</property>
</widget>
</item>
- <item row="6" column="0" colspan="3">
+ <item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="useDefaultForNullCheck">
<property name="toolTip">
<string><html><head/><body><p>Enable this to always enforce DEFAULT value when committing a NULL value for a column that has DEFAULT value defined, even though the column is allowed to contain NULL values.</p><p>Disable this option to use DEFAULT value exclusively when NULL value is committed for column with NOT NULL constraint.</p></body></html></string>
@@ -474,65 +499,118 @@ </property>
</widget>
</item>
- <item row="3" column="2">
- <widget class="QSpinBox" name="spinBox">
- <property name="toolTip">
- <string><p>Maximum number of configurations of Populate Table dialog stored in configuration. Value of 100 should be sufficient.</p></string>
+ <item row="0" column="2">
+ <widget class="QSpinBox" name="rowsPerPageSpin">
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="minimum">
+ <number>1</number>
</property>
<property name="maximum">
- <number>999999</number>
+ <number>99999</number>
</property>
<property name="cfg" stdset="0">
- <string notr="true">General.PopulateHistorySize</string>
+ <string notr="true">General.NumberOfRowsPerPage</string>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="2">
- <widget class="QLabel" name="label_2">
+ <item row="4" column="0" colspan="3">
+ <widget class="QCheckBox" name="keepNullWhenEmptyCheck">
<property name="toolTip">
- <string><p>Maximum number of configurations of Populate Table dialog stored in configuration. Value of 100 should be sufficient.</p></string>
+ <string><p>When editing a cell which used to have NULL value and entering empty string as new value, then this option determinates whether the new value should remain NULL (have this option enabled), or should it be overwritten with empty string value (have this option disabled).</p></string>
</property>
<property name="text">
- <string>Number of memorized table populating configurations</string>
+ <string>Keep NULL value when entering empty value</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.KeepNullWhenEmptyValue</string>
</property>
</widget>
</item>
- <item row="4" column="0" colspan="3">
- <widget class="QCheckBox" name="tolltipInDataViewCheck">
+ <item row="6" column="0">
+ <widget class="QCheckBox" name="useSciFormatForDoublesCheck">
<property name="toolTip">
- <string><p>When this is enabled and user holds mouse pointer over a cell in any data view (query results, a table data, a view data) a tooltip will appear with details about the cell - it includes details like column data type, constraints, ROWID and others.</p></string>
+ <string><html><head/><body><p>By default (when this option is disabled) a real number is displayed in the format of decimals with decimal point. In some cases, when the number is really small (several places after decimal point), the default representation may appear inaccurate. In such case you may want to enable this option to use the scientific notation (i.e. <span style=" font-style:italic;">5.3e-21</span>).</p></body></html></string>
</property>
<property name="text">
- <string>Show column and row details tooltip in data view</string>
+ <string>Use scientific notation for real numbers in the grid view</string>
</property>
<property name="cfg" stdset="0">
- <string notr="true">General.ShowDataViewTooltips</string>
+ <string notr="true">General.UseSciFormatForDoubles</string>
</property>
</widget>
</item>
- <item row="5" column="0" colspan="3">
- <widget class="QCheckBox" name="keepNullWhenEmptyCheck">
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="dataColumnWdGroup">
+ <property name="title">
+ <string>Data column width</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_9">
+ <item row="1" column="0" colspan="2">
+ <widget class="QCheckBox" name="enlargeColumnCheck">
<property name="toolTip">
- <string><p>When editing a cell which used to have NULL value and entering empty string as new value, then this option determinates whether the new value should remain NULL (have this option enabled), or should it be overwritten with empty string value (have this option disabled).</p></string>
+ <string><html><head/><body><p>When user enters new value into column and the value is bigger than the current column width, the application will enlarge the column to fit the new value, but not wider than the limit defined in the option above.</p></body></html></string>
</property>
<property name="text">
- <string>Keep NULL value when entering empty value</string>
+ <string>Enlarge column when entering value longer than current width</string>
</property>
<property name="cfg" stdset="0">
- <string notr="true">General.KeepNullWhenEmptyValue</string>
+ <string notr="true">General.EnlargeColumnForValue</string>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="3">
- <widget class="QCheckBox" name="checkBox">
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="initColWidthLimitSpin">
+ <property name="maximumSize">
+ <size>
+ <width>150</width>
+ <height>16777215</height>
+ </size>
+ </property>
<property name="toolTip">
- <string><html><head/><body><p>If query results contain dozens (or hundreds) of columns, it is more likely that it will exhaust free memory of your computer by loading several gigabytes of data at once. SQLiteStudio may try to limit number of results displayed on one page in such cases to protect your computer. If you know that you don't work with big values in database, you can disable this limit and you will always see as many rows as defined per page.</p></body></html></string>
+ <string><p>When the data is read into grid view columns width is automatically adjusted. This value limits the initial width for the adjustment, but user can still resize the column manually over this limit.</p></string>
+ </property>
+ <property name="minimum">
+ <number>10</number>
+ </property>
+ <property name="maximum">
+ <number>99999</number>
+ </property>
+ <property name="value">
+ <number>600</number>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.MaxInitialColumnWith</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="initColWidthLimitLabel">
+ <property name="toolTip">
+ <string><html><head/><body><p>When the data is read into grid view columns width is automatically adjusted. This value limits the initial width for the adjustment, but user can still resize the column manually over this limit. This value is also used when enlarging column upon new, longer value entered by the user (see option below).</p></body></html></string>
</property>
<property name="text">
- <string>Limit number of rows for in case of dozens of columns</string>
+ <string>Limit automatic data column width to (in pixels):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="keepColNameCheck">
+ <property name="toolTip">
+ <string><html><head/><body><p>Initial width of data columns will be set to at least show complete name of the column in the header. This can still be overwritten by the initial limit of column width specified in pixels (the setting above).</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Keep at least the width to show complete column name</string>
</property>
<property name="cfg" stdset="0">
- <string>General.LimitRowsForManyColumns</string>
+ <string notr="true">General.ColumnWidthForName</string>
</property>
</widget>
</item>
@@ -851,13 +929,13 @@ </property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="queryHistorySizeLabel">
+ <item row="2" column="0">
+ <widget class="QLabel" name="bindParamLimitLabel">
<property name="toolTip">
- <string>Number of queries kept in the history.</string>
+ <string><p>Maximum number of query parameters (:param, @param, $param, ?) stored in history. When you re-use parameter with the same name/position, SQLiteStudio will pre-initialize it with most recent memorized value (you will still be able to change it). Value of 1000 should be sufficient.</p></string>
</property>
<property name="text">
- <string>History size:</string>
+ <string>Number of memorized query parameters</string>
</property>
</widget>
</item>
@@ -877,7 +955,7 @@ <item row="3" column="0">
<widget class="QCheckBox" name="execQueryUnderCursorCheck">
<property name="toolTip">
- <string><p>If there is more than one query in the SQL editor window, then (if this option is enabled) only a single query will be executed - the one under the keyboard insertion cursor. Otherwise all queries will be executed. You can always limit queries to be executed by selecting those queries before calling to execute.</p></string>
+ <string><html><head/><body><p>If there is more than one query in the SQL editor window, then (if this option is enabled) only a single query will be executed - the one under the keyboard insertion cursor. Otherwise all queries will be executed. You can always limit queries to be executed by selecting those queries before calling to execute. You can also use dedicated shortcuts for executing in one mode or the other (currently configured to %1 for single query execution and %2 for all queries execution).</p></body></html></string>
</property>
<property name="text">
<string>Execute only the query under the cursor</string>
@@ -887,13 +965,39 @@ </property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="bindParamLimitLabel">
+ <item row="1" column="0">
+ <widget class="QLabel" name="queryHistorySizeLabel">
<property name="toolTip">
- <string><p>Maximum number of query parameters (:param, @param, $param, ?) stored in history. When you re-use parameter with the same name/position, SQLiteStudio will pre-initialize it with most recent memorized value (you will still be able to change it). Value of 1000 should be sufficient.</p></string>
+ <string>Number of queries kept in the history.</string>
</property>
<property name="text">
- <string>Number of memorized query parameters</string>
+ <string>History size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="wrapLinesInSqlEditorCheck">
+ <property name="toolTip">
+ <string><html><head/><body><p>If enabled, lines longer than the editor width will be wrapped, so horizontal scrolling will not be needed.</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Wrap lines in SQL editor</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.SqlEditorWrapWords</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QCheckBox" name="highlightCurrentQueryCheck">
+ <property name="toolTip">
+ <string><html><head/><body><p>Highlights entire query that is currently under the insertion cursor. It's the same query that will be executed when you hit &quot;Execute query&quot; hotkey or button (unless configured otherwise).</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Highlight current query</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">General.SqlEditorCurrQueryHighlight</string>
</property>
</widget>
</item>
@@ -941,7 +1045,7 @@ <string>Allow multiple instances of the application at the same time</string>
</property>
<property name="cfg" stdset="0">
- <string>General.AllowMultipleSessions</string>
+ <string notr="true">General.AllowMultipleSessions</string>
</property>
</widget>
</item>
@@ -985,6 +1089,387 @@ </item>
</layout>
</widget>
+ <widget class="QWidget" name="codeColorsPage">
+ <layout class="QGridLayout" name="gridLayout_6">
+ <property name="horizontalSpacing">
+ <number>15</number>
+ </property>
+ <item row="0" column="2">
+ <widget class="QTabWidget" name="codeColorsPreviewTabWidget"/>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <spacer name="codeColorsSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QGroupBox" name="commonCodeColorsGroup">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Code syntax colors</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="keywordFgCheck">
+ <property name="text">
+ <string>Keyword foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxKeywordFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="ColorButton" name="regularFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxForeground</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="ColorButton" name="blobFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxBlobFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="ColorButton" name="keywordFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxKeywordFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="ColorButton" name="validObjectsFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxValidObject</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="ColorButton" name="commentFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCommentFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="regularFgCheck">
+ <property name="text">
+ <string>Regular foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxForegroundCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QCheckBox" name="commentFgCheck">
+ <property name="text">
+ <string>Comment foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCommentFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="ColorButton" name="numberFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxNumberFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="numberFgCheck">
+ <property name="text">
+ <string>Number foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxNumberFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="19" column="1">
+ <widget class="ColorButton" name="matchedParBgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxParenthesisBg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QCheckBox" name="validObjectsFkCheck">
+ <property name="text">
+ <string>Valid objects foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxValidObjectCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="ColorButton" name="stringFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxStringFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="1">
+ <widget class="ColorButton" name="currQueryBgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>You can disable current query highlighting entirely on the General settings page.</p></body></html></string>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCurrentQueryBg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QCheckBox" name="blobFgCheck">
+ <property name="text">
+ <string>BLOB value foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxBlobFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="stringFgCheck">
+ <property name="text">
+ <string>String foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxStringFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="ColorButton" name="currLineBgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCurrentLineBg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="21" column="1">
+ <widget class="ColorButton" name="matchedParFgBtn">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxParenthesisFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="0">
+ <widget class="QCheckBox" name="bindParamFgCheck">
+ <property name="text">
+ <string>Bind parameter foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxBindParamFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="13" column="1">
+ <widget class="ColorButton" name="bindParamFgBtn">
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxBindParamFg</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="0">
+ <widget class="QCheckBox" name="currLineBgCheck">
+ <property name="text">
+ <string>Current line background</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCurrentLineBgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="0">
+ <widget class="QCheckBox" name="currQueryBgCheck">
+ <property name="text">
+ <string>Current query background</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxCurrentQueryBgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="19" column="0">
+ <widget class="QCheckBox" name="matchedParBgCheck">
+ <property name="text">
+ <string>Matched parenthesis background</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxParenthesisBgCustom</string>
+ </property>
+ </widget>
+ </item>
+ <item row="21" column="0">
+ <widget class="QCheckBox" name="matchedParFgCheck">
+ <property name="text">
+ <string>Matched parenthesis foreground</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">Colors.SyntaxParenthesisFgCustom</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item alignment="Qt::AlignRight">
+ <widget class="QPushButton" name="codeColorsResetBtn">
+ <property name="text">
+ <string>Reset to defaults</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
<widget class="QWidget" name="shortcutsPage">
<layout class="QVBoxLayout" name="verticalLayout_28">
<property name="leftMargin">
@@ -1053,7 +1538,12 @@ </column>
<column>
<property name="text">
- <string/>
+ <string notr="true"/>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true"/>
</property>
</column>
</widget>
@@ -1084,8 +1574,8 @@ <rect>
<x>0</x>
<y>0</y>
- <width>339</width>
- <height>264</height>
+ <width>364</width>
+ <height>283</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_31">
@@ -1503,10 +1993,13 @@ <widget class="QTextEdit" name="previewTextEdit">
<property name="html">
<string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Abcdefgh</span></p></body></html></string>
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Abcdefgh</span></p></body></html></string>
</property>
</widget>
</item>
@@ -1596,8 +2089,8 @@ p, li { white-space: pre-wrap; } <rect>
<x>0</x>
<y>0</y>
- <width>206</width>
- <height>298</height>
+ <width>222</width>
+ <height>313</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
@@ -1700,6 +2193,45 @@ p, li { white-space: pre-wrap; } </item>
</layout>
</widget>
+ <widget class="QWidget" name="codeAssistantPage">
+ <layout class="QGridLayout" name="gridLayout_10">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="codeAssistantGroup">
+ <property name="title">
+ <string>Code assistant settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_14">
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="autoTriggerAssistantCheck">
+ <property name="toolTip">
+ <string><html><head/><body><p>If this option is enabled, the code assistant will be triggered in cases, when user types for example <span style=" font-weight:700;">tableName.</span> to propose columns of the table. If the option is disabled, user will have to hit the assistant hotkey explicitly.</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Automatically trigger the assistant after a dot is typed after an object name</string>
+ </property>
+ <property name="cfg" stdset="0">
+ <string notr="true">CodeAssistant.AutoTrigger</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="codeAssistantSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</widget>
</item>
@@ -1717,29 +2249,23 @@ p, li { white-space: pre-wrap; } </widget>
</item>
</layout>
- <widget class="QWidget" name="layoutWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>100</width>
- <height>30</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_25"/>
- </widget>
</widget>
<customwidgets>
<customwidget>
+ <class>ConfigRadioButton</class>
+ <extends>QRadioButton</extends>
+ <header>common/configradiobutton.h</header>
+ </customwidget>
+ <customwidget>
<class>FontEdit</class>
<extends>QWidget</extends>
<header>common/fontedit.h</header>
<container>1</container>
</customwidget>
<customwidget>
- <class>ConfigRadioButton</class>
- <extends>QRadioButton</extends>
- <header>common/configradiobutton.h</header>
+ <class>ColorButton</class>
+ <extends>QPushButton</extends>
+ <header>common/colorbutton.h</header>
</customwidget>
</customwidgets>
<tabstops>
diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp index 1e56258..e6a53db 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.cpp @@ -1,4 +1,6 @@ #include "dbdialog.h" +#include "common/immediatetooltip.h" +#include "services/notifymanager.h" #include "ui_dbdialog.h" #include "services/pluginmanager.h" #include "plugins/dbplugin.h" @@ -18,6 +20,8 @@ #include <QFileDialog> #include <QComboBox> #include <QTimer> +#include <QMimeData> +#include <QDir> DbDialog::DbDialog(Mode mode, QWidget *parent) : QDialog(parent), @@ -42,14 +46,32 @@ void DbDialog::setPermanent(bool perm) ui->permamentCheckBox->setChecked(perm); } + +void DbDialog::dragEnterEvent(QDragEnterEvent* e) +{ + if (e->mimeData()->hasUrls()) + e->acceptProposedAction(); +} + +void DbDialog::dropEvent(QDropEvent* e) +{ + if (!e->isAccepted() && e->mimeData()->hasUrls()) + { + setPath(e->mimeData()->urls().first().toLocalFile()); + e->accept(); + } +} + QString DbDialog::getPath() { - return ui->fileEdit->text(); + QString newPath = QDir::fromNativeSeparators(ui->fileEdit->text()); + return newPath; } void DbDialog::setPath(const QString& path) { - ui->fileEdit->setText(path); + QString newPath = QDir::toNativeSeparators(path); + ui->fileEdit->setText(newPath); } QString DbDialog::getName() @@ -82,7 +104,7 @@ void DbDialog::showEvent(QShowEvent *e) int idx = ui->typeCombo->findText(db->getTypeLabel()); ui->typeCombo->setCurrentIndex(idx); - ui->fileEdit->setText(db->getPath()); + setPath(db->getPath()); ui->nameEdit->setText(db->getName()); disableTypeAutodetection = false; } @@ -111,8 +133,7 @@ void DbDialog::showEvent(QShowEvent *e) void DbDialog::init() { ui->setupUi(this); - - ui->browseCreateButton->setIcon(ICONS.PLUS); + connIconTooltip = new ImmediateTooltip(ui->testConnIcon); for (DbPlugin* dbPlugin : PLUGINS->getLoadedPlugins<DbPlugin>()) dbPlugins[dbPlugin->getLabel()] = dbPlugin; @@ -122,12 +143,10 @@ void DbDialog::init() typeLabels.sort(Qt::CaseInsensitive); ui->typeCombo->addItems(typeLabels); - ui->browseCreateButton->setVisible(true); ui->testConnIcon->setVisible(false); connect(ui->fileEdit, SIGNAL(textChanged(QString)), this, SLOT(fileChanged(QString))); connect(ui->nameEdit, SIGNAL(textEdited(QString)), this, SLOT(nameModified(QString))); - connect(ui->browseCreateButton, SIGNAL(clicked()), this, SLOT(browseClicked())); connect(ui->browseOpenButton, SIGNAL(clicked()), this, SLOT(browseClicked())); connect(ui->testConnButton, SIGNAL(clicked()), this, SLOT(testConnectionClicked())); connect(ui->typeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(dbTypeChanged(int))); @@ -145,7 +164,7 @@ void DbDialog::updateOptions() setUpdatesEnabled(false); // Remove olds - for (QWidget* w : optionWidgets) + for (QWidget*& w : optionWidgets) { ui->optionsGrid->removeWidget(w); delete w; @@ -153,8 +172,7 @@ void DbDialog::updateOptions() customBrowseHandler = nullptr; ui->pathGroup->setTitle(tr("File")); - ui->browseOpenButton->setToolTip(tr("Browse for existing database file on local computer")); - ui->browseCreateButton->setVisible(true); + ui->browseOpenButton->setToolTip(tr("Select new or existing file on local computer")); optionWidgets.clear(); optionKeyToWidget.clear(); @@ -191,7 +209,6 @@ void DbDialog::addOption(const DbPluginOption& option, int& row) // This option does not add any editor, but has it's own label for path edit. row--; ui->pathGroup->setTitle(option.label); - ui->browseCreateButton->setVisible(false); if (!option.toolTip.isEmpty()) ui->browseOpenButton->setToolTip(option.toolTip); @@ -450,7 +467,7 @@ void DbDialog::updateType() if (disableTypeAutodetection) return; - DbPlugin* validPlugin = SQLITESTUDIO->getDbManager()->getPluginForDbFile(ui->fileEdit->text()); + DbPlugin* validPlugin = SQLITESTUDIO->getDbManager()->getPluginForDbFile(getPath()); if (!validPlugin || validPlugin->getLabel() == ui->typeCombo->currentText()) return; @@ -476,14 +493,20 @@ QHash<QString, QVariant> DbDialog::collectOptions() return options; } -bool DbDialog::testDatabase() +bool DbDialog::testDatabase(QString& errorMsg) { if (ui->typeCombo->currentIndex() < 0) + { + errorMsg = tr("Database type not selected."); return false; + } - QString path = ui->fileEdit->text(); + QString path = getPath(); if (path.isEmpty()) + { + errorMsg = tr("Database path not specified."); return false; + } QUrl url(path); if (url.scheme().isEmpty()) @@ -491,7 +514,7 @@ bool DbDialog::testDatabase() QHash<QString, QVariant> options = collectOptions(); DbPlugin* plugin = dbPlugins[ui->typeCombo->currentText()]; - Db* testDb = plugin->getInstance("", path, options); + Db* testDb = plugin->getInstance("", path, options, &errorMsg); bool res = false; if (testDb) @@ -499,6 +522,7 @@ bool DbDialog::testDatabase() if (testDb->openForProbing()) { res = !testDb->exec("SELECT sqlite_version();")->getSingleCell().toString().isEmpty(); + errorMsg = testDb->getErrorText(); testDb->closeQuiet(); } delete testDb; @@ -546,7 +570,7 @@ bool DbDialog::validate() if (fileState) { - registeredDb = DBLIST->getByPath(ui->fileEdit->text()); + registeredDb = DBLIST->getByPath(getPath()); if (registeredDb && (mode == Mode::ADD || registeredDb != db)) { setValidState(ui->fileEdit, false, tr("This database is already on the list under name: %1").arg(registeredDb->getName())); @@ -601,6 +625,7 @@ void DbDialog::typeChanged(int index) { UNUSED(index); updateOptions(); + updateState(); } void DbDialog::valueForNameGenerationChanged() @@ -612,10 +637,9 @@ void DbDialog::valueForNameGenerationChanged() QString generatedName; DbPlugin* plugin = dbPlugins.count() > 0 ? dbPlugins[ui->typeCombo->currentText()] : nullptr; if (plugin) - generatedName = DBLIST->generateUniqueDbName(plugin, ui->fileEdit->text()); + generatedName = DBLIST->generateUniqueDbName(plugin, getPath()); else - generatedName = DBLIST->generateUniqueDbName(ui->fileEdit->text()); - + generatedName = DBLIST->generateUniqueDbName(getPath()); ui->nameEdit->setText(generatedName); } @@ -624,7 +648,7 @@ void DbDialog::browseForFile() { QString dir = getFileDialogInitPath(); QString path = QFileDialog::getOpenFileName(0, QString(), dir); - if (path.isNull()) + if (path.isEmpty()) return; QString key = helperToKey[dynamic_cast<QWidget*>(sender())]; @@ -645,18 +669,16 @@ void DbDialog::browseClicked() { if (customBrowseHandler) { - QString newUrl = customBrowseHandler(ui->fileEdit->text()); + QString newUrl = customBrowseHandler(getPath()); if (!newUrl.isNull()) { - ui->fileEdit->setText(newUrl); + setPath(newUrl); updateState(); } return; } - bool createMode = (sender() == ui->browseCreateButton); - - QFileInfo fileInfo(ui->fileEdit->text()); + QFileInfo fileInfo(getPath()); QString dir; if (ui->fileEdit->text().isEmpty()) dir = getFileDialogInitPath(); @@ -667,7 +689,7 @@ void DbDialog::browseClicked() else dir = getFileDialogInitPath(); - QString path = getDbPath(createMode, dir); + QString path = getDbPath(dir); if (path.isNull()) return; @@ -679,8 +701,19 @@ void DbDialog::browseClicked() void DbDialog::testConnectionClicked() { - ui->testConnIcon->setPixmap(testDatabase() ? ICONS.TEST_CONN_OK : ICONS.TEST_CONN_ERROR); + QString errorMsg; + bool ok = testDatabase(errorMsg); + ui->testConnIcon->setPixmap(ok ? ICONS.TEST_CONN_OK : ICONS.TEST_CONN_ERROR); + connIconTooltip->setToolTip(ok ? QString() : errorMsg); ui->testConnIcon->setVisible(true); + if (!ok) + { + QString path = getPath(); + if (!path.isEmpty()) + notifyWarn(QString("%1: %2").arg(getPath(), errorMsg)); + else + notifyWarn(errorMsg); + } } void DbDialog::dbTypeChanged(int index) diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.h index 3d1a9da..76cd3ec 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.h @@ -12,6 +12,7 @@ class DbPlugin; class QGridLayout; struct DbPluginOption; +class ImmediateTooltip; namespace Ui { class DbDialog; @@ -44,6 +45,8 @@ class GUI_API_EXPORT DbDialog : public QDialog protected: void changeEvent(QEvent *e); void showEvent(QShowEvent* e); + void dragEnterEvent(QDragEnterEvent* e); + void dropEvent(QDropEvent*e); private: void init(); @@ -53,7 +56,7 @@ class GUI_API_EXPORT DbDialog : public QDialog QVariant getValueFrom(DbPluginOption::Type type, QWidget* editor); void setValueFor(DbPluginOption::Type type, QWidget* editor, const QVariant& value); void updateType(); - bool testDatabase(); + bool testDatabase(QString& errorMsg); bool validate(); void updateState(); @@ -71,6 +74,7 @@ class GUI_API_EXPORT DbDialog : public QDialog bool disableTypeAutodetection = false; bool doAutoTest = false; bool nameManuallyEdited = false; + ImmediateTooltip* connIconTooltip = nullptr; static const constexpr int ADDITIONAL_ROWS_BEGIN_INDEX = 1; diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.ui b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.ui index 9878bec..f0ebe2a 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.ui +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/dbdialog.ui @@ -16,6 +16,9 @@ <height>0</height> </size> </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> <property name="windowTitle"> <string>Database</string> </property> @@ -46,20 +49,6 @@ <widget class="QLineEdit" name="fileEdit"/> </item> <item> - <widget class="QToolButton" name="browseCreateButton"> - <property name="toolTip"> - <string>Create new database file</string> - </property> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../icons.qrc"> - <normaloff>:/icons/img/plus.png</normaloff>:/icons/img/plus.png</iconset> - </property> - </widget> - </item> - <item> <widget class="QToolButton" name="browseOpenButton"> <property name="text"> <string/> diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/exportdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/exportdialog.cpp index 7dda03e..135bc9d 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/exportdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/exportdialog.cpp @@ -187,6 +187,7 @@ void ExportDialog::initQueryPage() return dbOk && queryOk; }); + ui->queryEdit->setAlwaysEnforceErrorsChecking(true); connect(ui->queryEdit, SIGNAL(errorsChecked(bool)), ui->queryPage, SIGNAL(completeChanged())); connect(ui->queryEdit, SIGNAL(textChanged()), ui->queryPage, SIGNAL(completeChanged())); @@ -619,7 +620,7 @@ void ExportDialog::updatePluginOptions(ExportPlugin* plugin, int& optionsRow) configMapper = new ConfigMapper(cfgMain); configMapper->bindToConfig(pluginOptionsWidget); - connect(configMapper, SIGNAL(modified()), this, SLOT(updateValidation())); + connect(configMapper, SIGNAL(modified(QWidget*)), this, SLOT(updateValidation())); plugin->validateOptions(); } diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/importdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/importdialog.cpp index 565feb4..f443f18 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/importdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/importdialog.cpp @@ -1,12 +1,9 @@ #include "importdialog.h" #include "dblistmodel.h" #include "dbobjlistmodel.h" -#include "common/widgetstateindicator.h" #include "uiutils.h" #include "common/widgetcover.h" #include "services/dbmanager.h" -#include "services/pluginmanager.h" -#include "sqlitestudio.h" #include "plugins/importplugin.h" #include "ui_importdialog.h" #include "configmapper.h" @@ -14,6 +11,8 @@ #include "common/utils.h" #include "uiconfig.h" #include "themetuner.h" +#include "iconmanager.h" +#include "mainwindow.h" #include <QDir> #include <QDebug> #include <QFileDialog> @@ -203,6 +202,7 @@ void ImportDialog::initDataSourcePage() void ImportDialog::removeOldOptions() { + pluginConfigOk.clear(); safe_delete(configMapper); safe_delete(pluginOptionsWidget); } @@ -284,7 +284,7 @@ void ImportDialog::updatePluginOptions(int& rows) configMapper = new ConfigMapper(cfgMain); configMapper->bindToConfig(pluginOptionsWidget); - connect(configMapper, SIGNAL(modified()), this, SLOT(updateValidation())); + connect(configMapper, SIGNAL(modified(QWidget*)), this, SLOT(updateValidation())); updateValidation(); } diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.cpp index ebf9beb..d5249d0 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.cpp @@ -13,7 +13,6 @@ #include "indexexprcolumndialog.h" #include "windows/editorwindow.h" #include "services/codeformatter.h" -#include "common/compatibility.h" #include <QDebug> #include <QGridLayout> #include <QSignalMapper> @@ -37,6 +36,10 @@ IndexDialog::IndexDialog(Db* db, const QString& index, QWidget* parent) : { existingIndex = true; init(); + + bool sysIdx = isSystemIndex(index); + ui->indexTab->setDisabled(sysIdx); + ui->ddlTab->setDisabled(sysIdx); } IndexDialog::~IndexDialog() @@ -709,15 +712,32 @@ void IndexDialog::preReject() preRejected = true; } +QString IndexDialog::getOriginalDdl() const +{ + SqliteCreateIndex* initialCreateIndex = originalCreateIndex->typeClone<SqliteCreateIndex>(); + initialCreateIndex->rebuildTokens(); + QString initialDdl = initialCreateIndex->detokenize(); + delete initialCreateIndex; + return initialDdl; +} + void IndexDialog::accept() { + QString initialDdl = getOriginalDdl(); rebuildCreateIndex(); + QString ddl = createIndex->detokenize(); + if (initialDdl == ddl) + { + // Nothing changed. Just close. + QDialog::accept(); + return; + } QStringList sqls; if (existingIndex) sqls << QString("DROP INDEX %1").arg(wrapObjIfNeeded(originalCreateIndex->index)); - sqls << createIndex->detokenize(); + sqls << ddl; if (!CFG_UI.General.DontShowDdlPreview.get()) { diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.h index 2e586d4..dd68137 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/indexdialog.h @@ -123,6 +123,7 @@ class GUI_API_EXPORT IndexDialog : public QDialog QStringList getExistingColumnExprs(const QString& exceptThis = QString()) const; QStringList getTableColumns() const; void preReject(); + QString getOriginalDdl() const; bool existingIndex = false; Db* db = nullptr; diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.cpp index d9f05ff..b68ce10 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.cpp @@ -1,3 +1,4 @@ +#include "iconmanager.h" #include "languagedialog.h" #include "ui_languagedialog.h" #include "uiconfig.h" @@ -43,3 +44,8 @@ void LanguageDialog::askedForDefaultLanguage() { CFG_UI.General.LanguageAsked.set(true); } + +void LanguageDialog::showEvent(QShowEvent*) +{ + setWindowIcon(ICONS.SQLITESTUDIO_APP); +} diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.h index d5fbed4..a11fc8a 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/languagedialog.h @@ -13,6 +13,9 @@ class GUI_API_EXPORT LanguageDialog : public QDialog { Q_OBJECT + protected: + void showEvent(QShowEvent*); + public: explicit LanguageDialog(QWidget *parent = 0); ~LanguageDialog(); diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/newversiondialog.ui b/SQLiteStudio3/guiSQLiteStudio/dialogs/newversiondialog.ui index 12794ce..045c245 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/newversiondialog.ui +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/newversiondialog.ui @@ -18,7 +18,6 @@ <widget class="QLabel" name="topLabel"> <property name="font"> <font> - <weight>75</weight> <bold>true</bold> </font> </property> @@ -35,12 +34,11 @@ <property name="font"> <font> <pointsize>16</pointsize> - <weight>75</weight> <bold>true</bold> </font> </property> <property name="text"> - <string>0.0.0</string> + <string notr="true">0.0.0</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/populateconfigdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/populateconfigdialog.cpp index 5dc506f..f4d93a4 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/populateconfigdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/populateconfigdialog.cpp @@ -2,9 +2,9 @@ #include "ui_populateconfigdialog.h" #include "plugins/populateplugin.h" #include "services/populatemanager.h" -#include "sqlitestudio.h" #include "formmanager.h" #include "configmapper.h" +#include "mainwindow.h" #include "uiutils.h" #include <QPushButton> #include <QDebug> @@ -55,7 +55,7 @@ void PopulateConfigDialog::init() ui->headerLabel->setText(headerString ); configMapper = new ConfigMapper(engine->getConfig()); - connect(configMapper, SIGNAL(modified()), this, SLOT(validateEngine())); + connect(configMapper, SIGNAL(modified(QWidget*)), this, SLOT(validateEngine())); connect(POPULATE_MANAGER, SIGNAL(validationResultFromPlugin(bool,CfgEntry*,QString)), this, SLOT(validationResultFromPlugin(bool,CfgEntry*,QString))); connect(POPULATE_MANAGER, SIGNAL(stateUpdateRequestFromPlugin(CfgEntry*,bool,bool)), this, SLOT(stateUpdateRequestFromPlugin(CfgEntry*,bool,bool))); diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/populatedialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/populatedialog.cpp index aae0d58..89fff04 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/populatedialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/populatedialog.cpp @@ -32,8 +32,13 @@ PopulateDialog::~PopulateDialog() void PopulateDialog::setDbAndTable(Db* db, const QString& table) { + QString oldTable = ui->tableCombo->currentText(); ui->databaseCombo->setCurrentText(db->getName()); ui->tableCombo->setCurrentText(table); + + // #4177 + if (oldTable == table) + refreshColumns(); } void PopulateDialog::init() @@ -48,7 +53,7 @@ void PopulateDialog::init() return p1->getTitle().compare(p2->getTitle()) < 0; }); - for (PopulatePlugin* plugin : plugins) + for (PopulatePlugin*& plugin : plugins) { pluginByName[plugin->getName()] = plugin; pluginTitles << plugin->getTitle(); @@ -103,7 +108,7 @@ void PopulateDialog::rebuildEngines(const QHash<QString, QPair<QString, QVariant int row = 0; QVariant config; QString pluginName; - for (const ColumnEntry& entry : columnEntries) + for (ColumnEntry& entry : columnEntries) { pluginName.clear(); if (columnConfig.contains(entry.column)) @@ -136,7 +141,7 @@ void PopulateDialog::refreshTables() void PopulateDialog::refreshColumns() { - for (const ColumnEntry& entry : columnEntries) + for (ColumnEntry& entry : columnEntries) { delete entry.check; delete entry.combo; @@ -319,7 +324,7 @@ void PopulateDialog::updateState() bool tableOk = !ui->tableCombo->currentText().isNull(); bool colCountOk = false; - for (const ColumnEntry& entry : columnEntries) + for (ColumnEntry& entry : columnEntries) { if (entry.check->isChecked()) { diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggercolumnsdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggercolumnsdialog.cpp index 7890b3c..896ef39 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggercolumnsdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggercolumnsdialog.cpp @@ -1,10 +1,13 @@ #include "triggercolumnsdialog.h" #include "ui_triggercolumnsdialog.h" -#include "uiutils.h" #include <QCheckBox> TriggerColumnsDialog::TriggerColumnsDialog(QWidget *parent, int globalX, int globalY) : +#ifdef Q_OS_OSX + QDialog(parent), +#else QDialog(parent, Qt::Popup), +#endif globalX(globalX), globalY(globalY), ui(new Ui::TriggerColumnsDialog) diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.cpp b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.cpp index 86862e2..5091613 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.cpp +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.cpp @@ -1,12 +1,10 @@ #include "triggerdialog.h" #include "ui_triggerdialog.h" -#include "parser/ast/sqliteselect.h" #include "services/notifymanager.h" #include "parser/ast/sqliteexpr.h" #include "triggercolumnsdialog.h" #include "common/utils_sql.h" #include "schemaresolver.h" -#include "parser/parser.h" #include "iconmanager.h" #include "db/chainexecutor.h" #include "dbtree/dbtree.h" @@ -208,11 +206,14 @@ void TriggerDialog::readTrigger() if (createTrigger->queries.size() > 0) { QStringList sqls; - for (SqliteQuery* query : createTrigger->queries) + for (SqliteQuery*& query : createTrigger->queries) sqls << query->detokenize(); ui->codeEdit->setPlainText(sqls.join(";\n")+";"); } + + rebuildTrigger(); + originalDdl = ddl; } void TriggerDialog::setupVirtualSqls() @@ -299,7 +300,7 @@ void TriggerDialog::rebuildTrigger() if (actionType == SqliteCreateTrigger::Event::UPDATE_OF) { QStringList colNames; - for (const QString& colName : selectedColumns) + for (QString& colName : selectedColumns) colNames << wrapObjIfNeeded(colName); columns = " "+colNames.join(", "); @@ -321,7 +322,7 @@ void TriggerDialog::rebuildTrigger() if (!scope.isNull()) scope.prepend(" "); - ddl = tempDdl.arg(trigName).arg(when).arg(action).arg(columns).arg(target).arg(scope).arg(precondition).arg(queries); + ddl = tempDdl.arg(trigName, when, action, columns, target, scope, precondition, queries); } void TriggerDialog::updateState() @@ -385,6 +386,12 @@ void TriggerDialog::tableChanged(const QString& newValue) void TriggerDialog::accept() { rebuildTrigger(); + if (originalDdl == ddl) + { + // Nothing changed. Just close. + QDialog::accept(); + return; + } QStringList sqls; if (existingTrigger) diff --git a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.h b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.h index 712ea5e..1eb7064 100644 --- a/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.h +++ b/SQLiteStudio3/guiSQLiteStudio/dialogs/triggerdialog.h @@ -50,6 +50,7 @@ class GUI_API_EXPORT TriggerDialog : public QDialog QStringList targetColumns; QStringList selectedColumns; QString ddl; + QString originalDdl; SqliteCreateTriggerPtr createTrigger; Ui::TriggerDialog *ui = nullptr; |
