From 217563fd475dccccc2a444e9f22ca495b6c5a92f Mon Sep 17 00:00:00 2001 From: mgrojo Date: Sat, 23 Mar 2019 22:14:18 +0100 Subject: [PATCH] Dialog and foreground configuration for conditional formats A new dialog for editing conditional formats that can be invoked from the filter line editor or from the data browser contextual menus. The dialog allows adding and removing conditional formats, changing the priority order and editing foreground colour, background colour and filter condition. The conditional formats have been expanded to allow defining the foreground colour. By default is the setting configured by user. This is a continuation of the functionality introduced in PR #1503. --- CMakeLists.txt | 3 + src/CondFormat.cpp | 8 +- src/CondFormat.h | 8 +- src/CondFormatManager.cpp | 124 +++++++++++++++++++++ src/CondFormatManager.h | 46 ++++++++ src/CondFormatManager.ui | 179 +++++++++++++++++++++++++++++++ src/ExtendedTableWidget.cpp | 7 ++ src/ExtendedTableWidget.h | 1 + src/FilterLineEdit.cpp | 24 +++-- src/FilterLineEdit.h | 1 + src/FilterTableHeader.cpp | 7 ++ src/FilterTableHeader.h | 2 + src/MainWindow.cpp | 26 ++++- src/MainWindow.h | 1 + src/icons/clear_cond_formats.png | Bin 0 -> 445 bytes src/icons/color_swatch.png | Bin 0 -> 209 bytes src/icons/edit_cond_formats.png | Bin 0 -> 573 bytes src/icons/icons.qrc | 3 + src/sqlitetablemodel.cpp | 51 ++++++--- src/sqlitetablemodel.h | 4 + src/src.pro | 5 +- 21 files changed, 466 insertions(+), 34 deletions(-) create mode 100644 src/CondFormatManager.cpp create mode 100644 src/CondFormatManager.h create mode 100644 src/CondFormatManager.ui create mode 100644 src/icons/clear_cond_formats.png create mode 100644 src/icons/color_swatch.png create mode 100644 src/icons/edit_cond_formats.png diff --git a/CMakeLists.txt b/CMakeLists.txt index f8839a5e..04f4be09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ set(SQLB_MOC_HDR src/FindReplaceDialog.h src/ExtendedScintilla.h src/FileExtensionManager.h + src/CondFormatManager.h src/CipherSettings.h src/DotenvFormat.h src/Palette.h @@ -200,6 +201,7 @@ set(SQLB_SRC src/FindReplaceDialog.cpp src/ExtendedScintilla.cpp src/FileExtensionManager.cpp + src/CondFormatManager.cpp src/Data.cpp src/CipherSettings.cpp src/DotenvFormat.cpp @@ -228,6 +230,7 @@ set(SQLB_FORMS src/RemotePushDialog.ui src/FindReplaceDialog.ui src/FileExtensionManager.ui + src/CondFormatManager.ui ) set(SQLB_RESOURCES diff --git a/src/CondFormat.cpp b/src/CondFormat.cpp index a8d99969..9d87c3ca 100644 --- a/src/CondFormat.cpp +++ b/src/CondFormat.cpp @@ -2,11 +2,13 @@ #include "Settings.h" #include "Data.h" -CondFormat::CondFormat(const QString& filter, const QColor& color, const QString& encoding) +CondFormat::CondFormat(const QString& filter, const QColor& foreground, const QColor& background, const QString& encoding) : m_filter(filter), - m_color(color) + m_fgColor(foreground), + m_bgColor(background) { - m_sqlCondition = filterToSqlCondition(filter, encoding); + if (!filter.isEmpty()) + m_sqlCondition = filterToSqlCondition(filter, encoding); } QString CondFormat::filterToSqlCondition(const QString& value, const QString& encoding) diff --git a/src/CondFormat.h b/src/CondFormat.h index f2ded3a6..9e1d69b4 100644 --- a/src/CondFormat.h +++ b/src/CondFormat.h @@ -9,19 +9,21 @@ class CondFormat { public: CondFormat() {}; - explicit CondFormat(const QString& filter, const QColor& color, const QString& encoding = QString()); + explicit CondFormat(const QString& filter, const QColor& foreground, const QColor& background, const QString& encoding = QString()); static QString filterToSqlCondition(const QString& value, const QString& encoding = QString()); private: QString m_sqlCondition; QString m_filter; - QColor m_color; + QColor m_bgColor; + QColor m_fgColor; public: QString sqlCondition() const { return m_sqlCondition; }; QString filter() const { return m_filter; }; - QColor color() const { return m_color; }; + QColor backgroundColor() const { return m_bgColor; }; + QColor foregroundColor() const { return m_fgColor; }; }; diff --git a/src/CondFormatManager.cpp b/src/CondFormatManager.cpp new file mode 100644 index 00000000..7b8db97c --- /dev/null +++ b/src/CondFormatManager.cpp @@ -0,0 +1,124 @@ +#include "CondFormatManager.h" +#include "ui_CondFormatManager.h" +#include "CondFormat.h" +#include "Settings.h" + +#include "QColorDialog" + +CondFormatManager::CondFormatManager(const QVector& condFormats, const QString& encoding, QWidget *parent) : + QDialog(parent), + ui(new Ui::CondFormatManager), + m_condFormats(condFormats), + m_encoding(encoding) +{ + ui->setupUi(this); + + for(const CondFormat& aCondFormat : condFormats) + addItem(aCondFormat); + + ui->tableCondFormats->setEditTriggers(QAbstractItemView::AllEditTriggers); + + connect(ui->buttonAdd, SIGNAL(clicked(bool)), this, SLOT(addNewItem())); + connect(ui->buttonRemove, SIGNAL(clicked(bool)), this, SLOT(removeItem())); + + connect(ui->buttonDown, SIGNAL(clicked(bool)), this, SLOT(downItem())); + connect(ui->buttonUp, SIGNAL(clicked(bool)), this, SLOT(upItem())); + + connect(ui->tableCondFormats, &QTreeWidget::itemDoubleClicked, this, &CondFormatManager::itemDoubleClicked); +} + +CondFormatManager::~CondFormatManager() +{ + delete ui; +} + +void CondFormatManager::addNewItem() +{ + CondFormat newCondFormat("", QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()), + m_condFormatPalette.nextSerialColor(Palette::appHasDarkTheme()), + m_encoding); + addItem(newCondFormat); +} + +void CondFormatManager::addItem(const CondFormat& aCondFormat) +{ + int i = ui->tableCondFormats->topLevelItemCount(); + QTreeWidgetItem *newItem = new QTreeWidgetItem({aCondFormat.foregroundColor().name(), + aCondFormat.backgroundColor().name(), aCondFormat.filter()}); + newItem->setForeground(ColumnForeground, aCondFormat.foregroundColor()); + newItem->setBackground(ColumnForeground, aCondFormat.foregroundColor()); + newItem->setForeground(ColumnBackground, aCondFormat.backgroundColor()); + newItem->setBackground(ColumnBackground, aCondFormat.backgroundColor()); + ui->tableCondFormats->insertTopLevelItem(i, newItem); + ui->tableCondFormats->openPersistentEditor(newItem, ColumnFilter); +} + +void CondFormatManager::removeItem() +{ + QTreeWidgetItem* item = ui->tableCondFormats->takeTopLevelItem(ui->tableCondFormats->currentIndex().row()); + delete item; +} + +void CondFormatManager::upItem() +{ + if (ui->tableCondFormats->selectedItems().isEmpty()) return; + + int selectedRow = ui->tableCondFormats->currentIndex().row(); + if(selectedRow == 0) + return; + + QTreeWidgetItem* item; + item = ui->tableCondFormats->takeTopLevelItem(selectedRow); + ui->tableCondFormats->insertTopLevelItem(selectedRow-1, item); + ui->tableCondFormats->setCurrentIndex(ui->tableCondFormats->currentIndex().sibling(selectedRow-1, + ui->tableCondFormats->currentIndex().column())); +} + +void CondFormatManager::downItem() +{ + if (ui->tableCondFormats->selectedItems().isEmpty()) return; + + int selectedRow = ui->tableCondFormats->currentIndex().row(); + if(selectedRow == ui->tableCondFormats->topLevelItemCount() - 1) + return; + + QTreeWidgetItem* item; + item = ui->tableCondFormats->takeTopLevelItem(selectedRow); + ui->tableCondFormats->insertTopLevelItem(selectedRow+1, item); + ui->tableCondFormats->setCurrentIndex(ui->tableCondFormats->currentIndex().sibling(selectedRow+1, + ui->tableCondFormats->currentIndex().column())); +} + +QVector CondFormatManager::getCondFormats() +{ + QVector result; + for (int i = 0; i < ui->tableCondFormats->topLevelItemCount(); ++i) + { + QTreeWidgetItem* item = ui->tableCondFormats->topLevelItem(i); + CondFormat aCondFormat(item->text(ColumnFilter), + item->background(ColumnForeground).color(), + item->background(ColumnBackground).color(), m_encoding); + result.append(aCondFormat); + } + return result; +} + + +void CondFormatManager::itemDoubleClicked(QTreeWidgetItem* item, int column) +{ + switch (column) { + case ColumnForeground: + case ColumnBackground: { + QColor color = QColorDialog::getColor(item->background(column).color(), this); + if(color.isValid()) { + item->setTextColor(column, color); + item->setBackgroundColor(column, color); + item->setText(column, color.name()); + } + break; + } + case ColumnFilter: + // Nothing to do + break; + } +} diff --git a/src/CondFormatManager.h b/src/CondFormatManager.h new file mode 100644 index 00000000..9cfdb4b0 --- /dev/null +++ b/src/CondFormatManager.h @@ -0,0 +1,46 @@ +#ifndef CONDFORMATMANAGER_H +#define CONDFORMATMANAGER_H + +#include + +#include "Palette.h" + +namespace Ui { + class CondFormatManager; +} + +class CondFormat; +class QTreeWidgetItem; + +class CondFormatManager : public QDialog +{ + Q_OBJECT + +public: + explicit CondFormatManager(const QVector& condFormats, const QString& encoding, QWidget *parent = nullptr); + ~CondFormatManager() override; + + QVector getCondFormats(); +private: + enum Columns { + ColumnForeground = 0, + ColumnBackground = 1, + ColumnFilter = 2 + }; + Ui::CondFormatManager *ui; + QVector m_condFormats; + Palette m_condFormatPalette; + QString m_encoding; + +private slots: + void addNewItem(); + void addItem(const CondFormat& aCondFormat); + void removeItem(); + void upItem(); + void downItem(); + +public slots: + void itemDoubleClicked(QTreeWidgetItem* item, int column); +}; + +#endif // CONDFORMATMANAGER_H diff --git a/src/CondFormatManager.ui b/src/CondFormatManager.ui new file mode 100644 index 00000000..61f82ce8 --- /dev/null +++ b/src/CondFormatManager.ui @@ -0,0 +1,179 @@ + + + CondFormatManager + + + + 0 + 0 + 578 + 463 + + + + Conditional Format Manager + + + + + + + + &Up + + + + :/icons/up:/icons/up + + + + + + + &Down + + + + :/icons/down:/icons/down + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Add + + + + :/icons/field_add:/icons/field_add + + + + + + + &Remove + + + + :/icons/field_delete:/icons/field_delete + + + + + + + + + QAbstractScrollArea::AdjustToContents + + + QAbstractItemView::AllEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectItems + + + 0 + + + false + + + true + + + false + + + false + + + 150 + + + + Text color + + + + + Background color + + + + + Condition + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + CondFormatManager + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CondFormatManager + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ExtendedTableWidget.cpp b/src/ExtendedTableWidget.cpp index 3bf8b901..40f1660e 100644 --- a/src/ExtendedTableWidget.cpp +++ b/src/ExtendedTableWidget.cpp @@ -253,6 +253,7 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) : QAction* lessEqualAction = new QAction(tr("Less or equal"), m_contextMenu); QAction* inRangeAction = new QAction(tr("Between this and..."), m_contextMenu); QAction* regexpAction = new QAction(tr("Regular expression"), m_contextMenu); + QAction* condFormatAction = new QAction(QIcon(":/icons/edit_cond_formats"), tr("Edit Conditional Formats..."), m_contextMenu); QAction* nullAction = new QAction(QIcon(":/icons/set_to_null"), tr("Set to NULL"), m_contextMenu); QAction* copyAction = new QAction(QIcon(":/icons/copy"), tr("Copy"), m_contextMenu); @@ -272,6 +273,7 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) : filterMenu->addAction(lessEqualAction); filterMenu->addAction(inRangeAction); filterMenu->addAction(regexpAction); + m_contextMenu->addAction(condFormatAction); m_contextMenu->addSeparator(); m_contextMenu->addAction(nullAction); @@ -309,11 +311,13 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) : copyWithHeadersAction->setEnabled(enabled); copyAsSQLAction->setEnabled(enabled); printAction->setEnabled(enabled); + condFormatAction->setEnabled(enabled); // Hide filter actions when there isn't any filters bool hasFilters = m_tableHeader->hasFilters(); filterAction->setVisible(hasFilters); filterMenu->menuAction()->setVisible(hasFilters); + condFormatAction->setVisible(hasFilters); // Try to find out whether the current view is editable and (de)activate menu options according to that bool editable = editTriggers() != QAbstractItemView::NoEditTriggers; @@ -354,6 +358,9 @@ ExtendedTableWidget::ExtendedTableWidget(QWidget* parent) : connect(regexpAction, &QAction::triggered, [&]() { useAsFilter(QString ("/"), /* binary */ false, QString ("/")); }); + connect(condFormatAction, &QAction::triggered, [&]() { + emit editCondFormats(currentIndex().column()); + }); connect(nullAction, &QAction::triggered, [&]() { for(const QModelIndex& index : selectedIndexes()) diff --git a/src/ExtendedTableWidget.h b/src/ExtendedTableWidget.h index 79298987..b7337b40 100644 --- a/src/ExtendedTableWidget.h +++ b/src/ExtendedTableWidget.h @@ -68,6 +68,7 @@ signals: void switchTable(bool next); // 'next' parameter is set to true if next table should be selected and to false if previous table should be selected void openFileFromDropEvent(QString); void selectedRowsToBeDeleted(); + void editCondFormats(int column); private: void copyMimeData(const QModelIndexList& fromIndices, QMimeData* mimeData, const bool withHeaders, const bool inSQL); diff --git a/src/FilterLineEdit.cpp b/src/FilterLineEdit.cpp index cd33cee5..d8fe7634 100644 --- a/src/FilterLineEdit.cpp +++ b/src/FilterLineEdit.cpp @@ -108,13 +108,22 @@ void FilterLineEdit::showContextMenu(const QPoint &pos) // This has to be created here, otherwise the set of enabled options would not update accordingly. QMenu* editContextMenu = createStandardContextMenu(); editContextMenu->addSeparator(); - QString conditionalFormatLabel = text().isEmpty() ? tr("Clear All Conditional Formats") : tr("Use for Conditional Format"); - QAction* conditionalFormatAction = new QAction(conditionalFormatLabel, editContextMenu); - connect(conditionalFormatAction, &QAction::triggered, [&]() { - if (text().isEmpty()) - emit clearAllCondFormats(); - else - emit addFilterAsCondFormat(text()); + + QAction* conditionalFormatAction; + if (text().isEmpty()) { + conditionalFormatAction = new QAction(QIcon(":/icons/clear_cond_formats"), tr("Clear All Conditional Formats"), editContextMenu); + connect(conditionalFormatAction, &QAction::triggered, [&]() { + emit clearAllCondFormats(); + }); + } else { + conditionalFormatAction = new QAction(QIcon(":/icons/cond_formats"), tr("Use for Conditional Format"), editContextMenu); + connect(conditionalFormatAction, &QAction::triggered, [&]() { + emit addFilterAsCondFormat(text()); + }); + } + QAction* editCondFormatsAction = new QAction(QIcon(":/icons/edit_cond_formats"), tr("Edit Conditional Formats..."), editContextMenu); + connect(editCondFormatsAction, &QAction::triggered, [&]() { + emit editCondFormats(); }); editContextMenu->addSeparator(); @@ -184,6 +193,7 @@ void FilterLineEdit::showContextMenu(const QPoint &pos) }); editContextMenu->addAction(conditionalFormatAction); + editContextMenu->addAction(editCondFormatsAction); filterMenu->addAction(whatsThisAction); filterMenu->addSeparator(); diff --git a/src/FilterLineEdit.h b/src/FilterLineEdit.h index 553af5ee..5efb8fee 100644 --- a/src/FilterLineEdit.h +++ b/src/FilterLineEdit.h @@ -25,6 +25,7 @@ signals: void delayedTextChanged(QString text); void addFilterAsCondFormat(QString text); void clearAllCondFormats(); + void editCondFormats(); protected: void keyReleaseEvent(QKeyEvent* event) override; diff --git a/src/FilterTableHeader.cpp b/src/FilterTableHeader.cpp index 6a205e9f..73171f24 100644 --- a/src/FilterTableHeader.cpp +++ b/src/FilterTableHeader.cpp @@ -38,6 +38,7 @@ void FilterTableHeader::generateFilters(int number, bool showFirst) connect(l, SIGNAL(delayedTextChanged(QString)), this, SLOT(inputChanged(QString))); connect(l, SIGNAL(addFilterAsCondFormat(QString)), this, SLOT(addFilterAsCondFormat(QString))); connect(l, SIGNAL(clearAllCondFormats()), this, SLOT(clearAllCondFormats())); + connect(l, SIGNAL(editCondFormats()), this, SLOT(editCondFormats())); filterWidgets.push_back(l); } @@ -102,6 +103,12 @@ void FilterTableHeader::clearAllCondFormats() emit clearAllCondFormats(sender()->property("column").toInt()); } +void FilterTableHeader::editCondFormats() +{ + // Just get the column number and the new value and send them to anybody interested in editting conditional formatting + emit editCondFormats(sender()->property("column").toInt()); +} + void FilterTableHeader::clearFilters() { for(FilterLineEdit* filterLineEdit : filterWidgets) diff --git a/src/FilterTableHeader.h b/src/FilterTableHeader.h index 5d946713..8f5c5232 100644 --- a/src/FilterTableHeader.h +++ b/src/FilterTableHeader.h @@ -27,6 +27,7 @@ signals: void filterChanged(int column, QString value); void addCondFormat(int column, QString filter); void clearAllCondFormats(int column); + void editCondFormats(int column); protected: void updateGeometries() override; @@ -35,6 +36,7 @@ private slots: void inputChanged(const QString& new_value); void addFilterAsCondFormat(const QString& filter); void clearAllCondFormats(); + void editCondFormats(); private: QList filterWidgets; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 369a1cff..b2437563 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -28,6 +28,7 @@ #include "FindReplaceDialog.h" #include "Data.h" #include "CondFormat.h" +#include "CondFormatManager.h" #include "RunSql.h" #include @@ -175,6 +176,8 @@ void MainWindow::init() connect(ui->dataTable->filterHeader(), SIGNAL(filterChanged(int,QString)), this, SLOT(updateFilter(int,QString))); connect(ui->dataTable->filterHeader(), SIGNAL(addCondFormat(int,QString)), this, SLOT(addCondFormat(int,QString))); connect(ui->dataTable->filterHeader(), SIGNAL(clearAllCondFormats(int)), this, SLOT(clearAllCondFormats(int))); + connect(ui->dataTable->filterHeader(), SIGNAL(editCondFormats(int)), this, SLOT(editCondFormats(int))); + connect(ui->dataTable, SIGNAL(editCondFormats(int)), this, SLOT(editCondFormats(int))); connect(m_browseTableModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataTableSelectionChanged(QModelIndex))); // Select in table the rows correspoding to the selected points in plot @@ -2653,7 +2656,8 @@ static void loadBrowseDataTableSettings(BrowseDataTableSettings& settings, QXmlS while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != "column") { if(xml.name() == "format") { CondFormat newCondFormat(xml.attributes().value("condition").toString(), - QColor(xml.attributes().value("color").toString()), + QColor(xml.attributes().value("foreground").toString()), + QColor(xml.attributes().value("background").toString()), settings.encoding); settings.condFormats[index].append(newCondFormat); xml.skipCurrentElement(); @@ -2956,7 +2960,8 @@ static void saveBrowseDataTableSettings(const BrowseDataTableSettings& object, Q for(auto format : iter.value()) { xml.writeStartElement("format"); xml.writeAttribute("condition", format.filter()); - xml.writeAttribute("color", format.color().name()); + xml.writeAttribute("background", format.backgroundColor().name()); + xml.writeAttribute("foreground", format.foregroundColor().name()); xml.writeEndElement(); } xml.writeEndElement(); @@ -3171,7 +3176,11 @@ void MainWindow::updateFilter(int column, const QString& value) void MainWindow::addCondFormat(int column, const QString& value) { - CondFormat newCondFormat(value, m_condFormatPalette.nextSerialColor(Palette::appHasDarkTheme()), m_browseTableModel->encoding()); + // Create automatically a new conditional format with the next serial background color according to the theme and the regular foreground + // color in the settings. + CondFormat newCondFormat(value, QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()), + m_condFormatPalette.nextSerialColor(Palette::appHasDarkTheme()), + m_browseTableModel->encoding()); m_browseTableModel->addCondFormat(column, newCondFormat); browseTableSettings[currentlyBrowsedTableName()].condFormats[column].append(newCondFormat); } @@ -3183,6 +3192,17 @@ void MainWindow::clearAllCondFormats(int column) browseTableSettings[currentlyBrowsedTableName()].condFormats[column].clear(); } +void MainWindow::editCondFormats(int column) +{ + CondFormatManager condFormatDialog(browseTableSettings[currentlyBrowsedTableName()].condFormats[column], + m_browseTableModel->encoding(), this); + if (condFormatDialog.exec()) { + QVector condFormatVector = condFormatDialog.getCondFormats(); + m_browseTableModel->setCondFormats(column, condFormatVector); + browseTableSettings[currentlyBrowsedTableName()].condFormats[column] = condFormatVector; + } +} + void MainWindow::editEncryption() { #ifdef ENABLE_SQLCIPHER diff --git a/src/MainWindow.h b/src/MainWindow.h index 1adbb091..9d902e91 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -275,6 +275,7 @@ private slots: void updateFilter(int column, const QString& value); void addCondFormat(int column, const QString& value); void clearAllCondFormats(int column); + void editCondFormats(int column); void editEncryption(); void on_actionClearFilters_triggered(); void copyCurrentCreateStatement(); diff --git a/src/icons/clear_cond_formats.png b/src/icons/clear_cond_formats.png new file mode 100644 index 0000000000000000000000000000000000000000..1646b12c5974e34e012a94d7a8fb11ff4e64cfa9 GIT binary patch literal 445 zcmV;u0Yd(XP)XBBR{{&Wx(21g_0%Xwv_n$(;^+1M4e8NOfI#c=KL?!WJETrYIp^LsMf1(DSo z;U+C_^=G^_=iYw?1_p+oKbRPdoI)8m?jB%ZIMl+x#V^31ATQ7S?&kkO1_p-71ikS8 z^AiRR2}K45uOfuM8zdQ+|1l~M7Y00H4BswnW#HbF#qjg{3x;nD3=E$?F*E#SW_U(a z7#xX^ZeZi(u9g-4!@|P!gyHk+KMW6EGXMSkLZjC;k_h{kHThqfC`(hFmxSO zSd?`bB$R({-*5T0gITA{|Fu6pn0eqpx>}JTL$UWimE@yNe}L98c)I$ztaD0e0sx43 BPNV<; literal 0 HcmV?d00001 diff --git a/src/icons/edit_cond_formats.png b/src/icons/edit_cond_formats.png new file mode 100644 index 0000000000000000000000000000000000000000..3b69aa0755ba936155700234910b16da2b7beb69 GIT binary patch literal 573 zcmV-D0>b@?P)Q3Dah>_TagQ-m$d(v0_V(!m)T)O474U6d~*>kR~*)xB_j-*@iEJ@Ahu z%5AitAFf!-oAbG^qQ)(`G8mfwRB7l(wXFuX>x$Ys%Ui=jJ-F)K#hDvoWjVU4O7+Cs zFCnDlZL-(QJGo(5rn_o5bQZJu0#XJL2;!}M7~y>#z5-5Fidt(3Ei7;*?^Dc9Q_N2P zm^7em2tVgqYY5HAv+g{>T{ZZaUL+K*C;R0COfSF z>~WSU%)F$jdt3lWU+2siYQsj4w2_^7O<`u1#-H$x0=auV{0;7pKKk=Ncs3AIiHjoy z!z;ed+XO}~n`Sho&mCwPWMTFxacliIIF`Bg3mWL~gfxI+(49+k-es3w!BldRbiTyi zgUu8sQhZ-nBys(fP`#*~^71k;WPookZelf5qS7|$+oL$|KT{nU_1}eaE!C>;{7ItL z3DyYkE_H{(lFg~XDN)ukbsn!#x|AGitRfOJ(Ccpage_foreign_key.png save_all.png page_white_text.png + color_swatch.png + clear_cond_formats.png + edit_cond_formats.png diff --git a/src/sqlitetablemodel.cpp b/src/sqlitetablemodel.cpp index a500687c..d24f1b7d 100644 --- a/src/sqlitetablemodel.cpp +++ b/src/sqlitetablemodel.cpp @@ -234,6 +234,26 @@ QVariant SqliteTableModel::headerData(int section, Qt::Orientation orientation, return QString("%1").arg(section + 1); } +QColor SqliteTableModel::getMatchingCondFormatColor(int column, const QString& value, int role) const +{ + bool isNumber; + value.toFloat(&isNumber); + QString sql; + // For each conditional format for this column, + // if the condition matches the current data, return the associated colour. + for (const CondFormat& eachCondFormat : m_mCondFormats.value(column)) { + if (isNumber && !eachCondFormat.sqlCondition().contains("'")) + sql = QString("SELECT %1 %2").arg(value, eachCondFormat.sqlCondition()); + else + sql = QString("SELECT '%1' %2").arg(value, eachCondFormat.sqlCondition()); + + // Query the DB for the condition, waiting in case there is a loading in progress. + if (m_db.querySingleValueFromDb(sql, false, DBBrowserDB::Wait) == "1") + return role == Qt::ForegroundRole ? eachCondFormat.foregroundColor() : eachCondFormat.backgroundColor(); + } + return QColor(); +} + QVariant SqliteTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -291,6 +311,15 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const return QColor(Settings::getValue("databrowser", "null_fg_colour").toString()); else if (nosync_isBinary(index)) return QColor(Settings::getValue("databrowser", "bin_fg_colour").toString()); + else if (m_mCondFormats.contains(index.column())) { + QString value = cached_row->at(index.column()); + // Unlock before querying from DB + lock.unlock(); + QColor condFormatColor = getMatchingCondFormatColor(index.column(), value, role); + if (condFormatColor.isValid()) + return condFormatColor; + } + // Regular case (not null, not binary and no matching conditional format) return QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()); } else if (role == Qt::BackgroundRole) { if(!row_available) @@ -301,23 +330,11 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const return QColor(Settings::getValue("databrowser", "bin_bg_colour").toString()); else if (m_mCondFormats.contains(index.column())) { QString value = cached_row->at(index.column()); - bool isNumber; - value.toFloat(&isNumber); - QString sql; - // For each conditional format for this column, - // if the condition matches the current data, return the associated colour. - for (const CondFormat& eachCondFormat : m_mCondFormats.value(index.column())) { - if (isNumber && !eachCondFormat.sqlCondition().contains("'")) - sql = QString("SELECT %1 %2").arg(value, eachCondFormat.sqlCondition()); - else - sql = QString("SELECT '%1' %2").arg(value, eachCondFormat.sqlCondition()); - - // Unlock before querying from DB - lock.unlock(); - // Query the DB for the condition, waiting in case there is a loading in progress. - if (m_db.querySingleValueFromDb(sql, false, DBBrowserDB::Wait) == "1") - return eachCondFormat.color(); - } + // Unlock before querying from DB + lock.unlock(); + QColor condFormatColor = getMatchingCondFormatColor(index.column(), value, role); + if (condFormatColor.isValid()) + return condFormatColor; } // Regular case (not null, not binary and no matching conditional format) return QColor(Settings::getValue("databrowser", "reg_bg_colour").toString()); diff --git a/src/sqlitetablemodel.h b/src/sqlitetablemodel.h index 0fb3b1d9..f769a861 100644 --- a/src/sqlitetablemodel.h +++ b/src/sqlitetablemodel.h @@ -148,6 +148,10 @@ private: QByteArray encode(const QByteArray& str) const; QByteArray decode(const QByteArray& str) const; + // Return matching conditional format color or invalid color, otherwise. + // Only Qt::ForegroundRole and Qt::BackgroundRole are expected in role (Qt::ItemDataRole) + QColor getMatchingCondFormatColor(int column, const QString& value, int role) const; + DBBrowserDB& m_db; /// counts numbers of clearCache() since instantiation; using this diff --git a/src/src.pro b/src/src.pro index e9535e62..63d19cc9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -66,6 +66,7 @@ HEADERS += \ FindReplaceDialog.h \ ExtendedScintilla.h \ FileExtensionManager.h \ + CondFormatManager.h \ Data.h \ CipherSettings.h \ DotenvFormat.h \ @@ -115,6 +116,7 @@ SOURCES += \ FindReplaceDialog.cpp \ ExtendedScintilla.cpp \ FileExtensionManager.cpp \ + CondFormatManager.cpp \ Data.cpp \ CipherSettings.cpp \ DotenvFormat.cpp \ @@ -148,7 +150,8 @@ FORMS += \ RemoteDock.ui \ RemotePushDialog.ui \ FindReplaceDialog.ui \ - FileExtensionManager.ui + FileExtensionManager.ui \ + CondFormatManager.ui TRANSLATIONS += \ translations/sqlb_ar_SA.ts \