#include "CondFormatManager.h" #include "ui_CondFormatManager.h" #include "CondFormat.h" #include "Settings.h" #include "FilterLineEdit.h" #include #include #include #include #include #include #include #include #include // Styled Item Delegate for non-editable columns (all except Condition) class DefaultDelegate: public QStyledItemDelegate { public: explicit DefaultDelegate(QObject* parent=nullptr): QStyledItemDelegate(parent) {} QWidget* createEditor(QWidget* /* parent */, const QStyleOptionViewItem& /* option */, const QModelIndex& /* index */) const override { return nullptr; } }; // Styled Item Delegate for the Condition column as a filter line editor. class FilterEditDelegate: public QStyledItemDelegate { public: explicit FilterEditDelegate(QObject* parent=nullptr): QStyledItemDelegate(parent) {} QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem& /* option */, const QModelIndex& /* index */) const override { FilterLineEdit* filterEditor = new FilterLineEdit(parent); filterEditor->setConditionFormatContextMenuEnabled(false); return filterEditor; } }; CondFormatManager::CondFormatManager(const std::vector& 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); // Make condition editable as a filter line editor. ui->tableCondFormats->setEditTriggers(QAbstractItemView::AllEditTriggers); ui->tableCondFormats->setItemDelegateForColumn(ColumnFilter, new FilterEditDelegate(this)); // Make columns not text-editable, except for the condition. for(int col = ColumnForeground; col < ColumnFilter; ++col) { ui->tableCondFormats->setItemDelegateForColumn(col, new DefaultDelegate(this)); ui->tableCondFormats->resizeColumnToContents(col); } connect(ui->buttonAdd, &QToolButton::clicked, this, &CondFormatManager::addNewItem); connect(ui->buttonRemove, &QToolButton::clicked, this, &CondFormatManager::removeItem); connect(ui->buttonDown, &QToolButton::clicked, this, &CondFormatManager::downItem); connect(ui->buttonUp, &QToolButton::clicked, this, &CondFormatManager::upItem); connect(ui->tableCondFormats, &QTreeWidget::itemClicked, this, &CondFormatManager::itemClicked); } CondFormatManager::~CondFormatManager() { delete ui; } void CondFormatManager::addNewItem() { // Clear focus from the current widget, so if there is some input, it is saved now. QWidget* currentWidget = ui->tableCondFormats->itemWidget(ui->tableCondFormats->currentItem(), ColumnFilter); if (currentWidget != nullptr) currentWidget->clearFocus(); QFont font = QFont(Settings::getValue("databrowser", "font").toString()); font.setPointSize(Settings::getValue("databrowser", "fontsize").toInt()); CondFormat newCondFormat("", QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()), m_condFormatPalette.nextSerialColor(Palette::appHasDarkTheme()), font, CondFormat::AlignLeft, m_encoding); addItem(newCondFormat); } void CondFormatManager::addItem(const CondFormat& aCondFormat) { int i = ui->tableCondFormats->topLevelItemCount(); QTreeWidgetItem *newItem = new QTreeWidgetItem(ui->tableCondFormats); newItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable); newItem->setForeground(ColumnForeground, aCondFormat.foregroundColor()); newItem->setBackground(ColumnForeground, aCondFormat.foregroundColor()); newItem->setForeground(ColumnBackground, aCondFormat.backgroundColor()); newItem->setBackground(ColumnBackground, aCondFormat.backgroundColor()); newItem->setToolTip(ColumnBackground, tr("Click to select color")); newItem->setToolTip(ColumnForeground, tr("Click to select color")); QFontComboBox* fontCombo = new QFontComboBox(ui->tableCondFormats); fontCombo->setCurrentFont(aCondFormat.font()); // Avoid that the font combo box gets too wide and work around a possible Qt bug where the box overlaps the next column. fontCombo->setMaximumWidth(150); ui->tableCondFormats->setItemWidget(newItem, ColumnFont, fontCombo); QSpinBox* sizeBox = new QSpinBox(ui->tableCondFormats); sizeBox->setMinimum(1); sizeBox->setValue(aCondFormat.font().pointSize()); ui->tableCondFormats->setItemWidget(newItem, ColumnSize, sizeBox); newItem->setCheckState(ColumnBold, aCondFormat.isBold() ? Qt::Checked : Qt::Unchecked); newItem->setCheckState(ColumnItalic, aCondFormat.isItalic() ? Qt::Checked : Qt::Unchecked); newItem->setCheckState(ColumnUnderline, aCondFormat.isUnderline() ? Qt::Checked : Qt::Unchecked); QComboBox* alignCombo = new QComboBox(ui->tableCondFormats); alignCombo->addItems(CondFormat::alignmentTexts()); alignCombo->setCurrentIndex(aCondFormat.alignment()); ui->tableCondFormats->setItemWidget(newItem, ColumnAlignment, alignCombo); newItem->setText(ColumnFilter, aCondFormat.filter()); ui->tableCondFormats->insertTopLevelItem(i, newItem); for(int col = ColumnForeground; col < ColumnFilter; ++col) { ui->tableCondFormats->resizeColumnToContents(col); } } void CondFormatManager::removeItem() { QTreeWidgetItem* item = ui->tableCondFormats->takeTopLevelItem(ui->tableCondFormats->currentIndex().row()); delete item; } void CondFormatManager::moveItem(int offset) { if (!ui->tableCondFormats->currentIndex().isValid()) return; int selectedRow = ui->tableCondFormats->currentIndex().row(); int newRow = selectedRow + offset; if(newRow < 0 || newRow >= ui->tableCondFormats->topLevelItemCount()) return; QTreeWidgetItem* item = ui->tableCondFormats->topLevelItem(selectedRow); // Rescue widgets, since they will be deleted, and add them later. QFontComboBox* fontCombo = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnFont)); QFontComboBox* fontCombo2 = new QFontComboBox(ui->tableCondFormats); fontCombo2->setCurrentFont(fontCombo->currentFont()); QSpinBox* sizeBox = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnSize)); QSpinBox* sizeBox2 = new QSpinBox(ui->tableCondFormats); sizeBox2->setValue(sizeBox->value()); sizeBox2->setMinimum(sizeBox->minimum()); QComboBox* alignCombo = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnAlignment)); QComboBox* alignCombo2 = new QComboBox(ui->tableCondFormats); alignCombo2->addItems(CondFormat::alignmentTexts()); alignCombo2->setCurrentIndex(alignCombo->currentIndex()); item = ui->tableCondFormats->takeTopLevelItem(selectedRow); ui->tableCondFormats->insertTopLevelItem(newRow, item); // Restore widgets and state ui->tableCondFormats->setItemWidget(item, ColumnFont, fontCombo2); ui->tableCondFormats->setItemWidget(item, ColumnSize, sizeBox2); ui->tableCondFormats->setItemWidget(item, ColumnAlignment, alignCombo2); ui->tableCondFormats->setCurrentIndex(ui->tableCondFormats->currentIndex().sibling(newRow, ui->tableCondFormats->currentIndex().column())); // This is added so the widgets are readjusted. Otherwise they can be misplaced when moving an item to the top. ui->tableCondFormats->adjustSize(); } void CondFormatManager::upItem() { moveItem(-1); } void CondFormatManager::downItem() { moveItem(+1); } std::vector CondFormatManager::getCondFormats() const { std::vector result; for (int i = 0; i < ui->tableCondFormats->topLevelItemCount(); ++i) { QTreeWidgetItem* item = ui->tableCondFormats->topLevelItem(i); QFontComboBox* fontCombo = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnFont)); QSpinBox* sizeBox = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnSize)); QFont font = fontCombo->currentFont(); font.setPointSize(sizeBox->value()); font.setBold(item->checkState(ColumnBold) == Qt::Checked); font.setItalic(item->checkState(ColumnItalic) == Qt::Checked); font.setUnderline(item->checkState(ColumnUnderline) == Qt::Checked); QComboBox* alignCombo = qobject_cast(ui->tableCondFormats->itemWidget(item, ColumnAlignment)); result.emplace_back(item->text(ColumnFilter), item->background(ColumnForeground).color(), item->background(ColumnBackground).color(), font, static_cast(alignCombo->currentIndex()), m_encoding); } return result; } void CondFormatManager::itemClicked(QTreeWidgetItem* item, int column) { switch (column) { case ColumnForeground: case ColumnBackground: { QColor color = QColorDialog::getColor(item->background(column).color(), this); if(color.isValid()) { item->setForeground(column, color); item->setBackground(column, color); } break; } case ColumnBold: case ColumnItalic: case ColumnUnderline: item->setCheckState(column, item->checkState(column) != Qt::Checked ? Qt::Checked : Qt::Unchecked); break; default: // Nothing to do break; } } void CondFormatManager::buttonBoxClicked(QAbstractButton* button) { if (button == ui->buttonBox->button(QDialogButtonBox::Cancel)) reject(); else if (button == ui->buttonBox->button(QDialogButtonBox::Ok)) accept(); else if (button == ui->buttonBox->button(QDialogButtonBox::Help)) QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki/Conditional-Formats")); else if (button == ui->buttonBox->button(QDialogButtonBox::Reset)) { if (QMessageBox::warning(this, QApplication::applicationName(), tr("Are you sure you want to clear all the conditional formats of this field?"), QMessageBox::Reset | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Reset) if(ui->tableCondFormats->model()->hasChildren()) ui->tableCondFormats->model()->removeRows(0, ui->tableCondFormats->model()->rowCount()); } }