mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-29 07:19:46 -06:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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; };
|
||||
|
||||
};
|
||||
|
||||
|
||||
124
src/CondFormatManager.cpp
Normal file
124
src/CondFormatManager.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "CondFormatManager.h"
|
||||
#include "ui_CondFormatManager.h"
|
||||
#include "CondFormat.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include "QColorDialog"
|
||||
|
||||
CondFormatManager::CondFormatManager(const QVector<CondFormat>& 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<CondFormat> CondFormatManager::getCondFormats()
|
||||
{
|
||||
QVector<CondFormat> 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;
|
||||
}
|
||||
}
|
||||
46
src/CondFormatManager.h
Normal file
46
src/CondFormatManager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef CONDFORMATMANAGER_H
|
||||
#define CONDFORMATMANAGER_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "Palette.h"
|
||||
|
||||
namespace Ui {
|
||||
class CondFormatManager;
|
||||
}
|
||||
|
||||
class CondFormat;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
class CondFormatManager : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CondFormatManager(const QVector<CondFormat>& condFormats, const QString& encoding, QWidget *parent = nullptr);
|
||||
~CondFormatManager() override;
|
||||
|
||||
QVector<CondFormat> getCondFormats();
|
||||
private:
|
||||
enum Columns {
|
||||
ColumnForeground = 0,
|
||||
ColumnBackground = 1,
|
||||
ColumnFilter = 2
|
||||
};
|
||||
Ui::CondFormatManager *ui;
|
||||
QVector<CondFormat> 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
|
||||
179
src/CondFormatManager.ui
Normal file
179
src/CondFormatManager.ui
Normal file
@@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CondFormatManager</class>
|
||||
<widget class="QDialog" name="CondFormatManager">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>578</width>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Conditional Format Manager</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonUp">
|
||||
<property name="text">
|
||||
<string>&Up</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/up</normaloff>:/icons/up</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonDown">
|
||||
<property name="text">
|
||||
<string>&Down</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/down</normaloff>:/icons/down</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAdd">
|
||||
<property name="text">
|
||||
<string>&Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/field_add</normaloff>:/icons/field_add</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRemove">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/field_delete</normaloff>:/icons/field_delete</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="tableCondFormats">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Text color</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Background color</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Condition</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CondFormatManager</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CondFormatManager</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -25,6 +25,7 @@ signals:
|
||||
void delayedTextChanged(QString text);
|
||||
void addFilterAsCondFormat(QString text);
|
||||
void clearAllCondFormats();
|
||||
void editCondFormats();
|
||||
|
||||
protected:
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<FilterLineEdit*> filterWidgets;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "FindReplaceDialog.h"
|
||||
#include "Data.h"
|
||||
#include "CondFormat.h"
|
||||
#include "CondFormatManager.h"
|
||||
#include "RunSql.h"
|
||||
|
||||
#include <chrono>
|
||||
@@ -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<CondFormat> condFormatVector = condFormatDialog.getCondFormats();
|
||||
m_browseTableModel->setCondFormats(column, condFormatVector);
|
||||
browseTableSettings[currentlyBrowsedTableName()].condFormats[column] = condFormatVector;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::editEncryption()
|
||||
{
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
|
||||
@@ -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();
|
||||
|
||||
BIN
src/icons/clear_cond_formats.png
Normal file
BIN
src/icons/clear_cond_formats.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 445 B |
BIN
src/icons/color_swatch.png
Normal file
BIN
src/icons/color_swatch.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 209 B |
BIN
src/icons/edit_cond_formats.png
Normal file
BIN
src/icons/edit_cond_formats.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 573 B |
@@ -80,5 +80,8 @@
|
||||
<file alias="field_fk">page_foreign_key.png</file>
|
||||
<file alias="save_all">save_all.png</file>
|
||||
<file alias="word_wrap">page_white_text.png</file>
|
||||
<file alias="cond_formats">color_swatch.png</file>
|
||||
<file alias="clear_cond_formats">clear_cond_formats.png</file>
|
||||
<file alias="edit_cond_formats">edit_cond_formats.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user