#include "qt/view/QtErrorView.h" #include #include #include #include #include #include #include #include #include #include #include "qt/utility/utilityQt.h" #include "qt/element/QtTable.h" #include "settings/ColorScheme.h" #include "utility/messaging/type/MessageErrorFilterChanged.h" #include "utility/messaging/type/MessageShowErrors.h" #include "utility/ResourcePaths.h" #include "qt/view/QtViewWidgetWrapper.h" QIcon QtErrorView::s_errorIcon; class SelectableDelegate : public QStyledItemDelegate { QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; QWidget* SelectableDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index); QLineEdit* lineEdit = dynamic_cast(editor); if (lineEdit != nullptr) { lineEdit->setReadOnly(true); } return editor; } QtErrorView::QtErrorView(ViewLayout* viewLayout) : ErrorView(viewLayout) , m_clearFunctor(std::bind(&QtErrorView::doClear, this)) , m_refreshFunctor(std::bind(&QtErrorView::doRefreshView, this)) , m_addErrorsFunctor(std::bind(&QtErrorView::doAddErrors, this, std::placeholders::_1, std::placeholders::_2)) , m_setErrorIdFunctor(std::bind(&QtErrorView::doSetErrorId, this, std::placeholders::_1)) , m_ignoreRowSelection(false) { s_errorIcon = QIcon(QString((ResourcePaths::getGuiPath().str() + "/indexing_dialog/error.png").c_str())); } QtErrorView::~QtErrorView() { } void QtErrorView::createWidgetWrapper() { setWidgetWrapper(std::make_shared(new QFrame())); } void QtErrorView::initView() { QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this); QBoxLayout* layout = new QVBoxLayout(); layout->setContentsMargins(0, 0, 0, 5); layout->setSpacing(0); widget->setLayout(layout); m_table = new QtTable(this); m_model = new QStandardItemModel(this); m_table->setModel(m_model); m_table->setItemDelegate(new SelectableDelegate()); // Setup Table Headers m_model->setColumnCount(6); m_table->setColumnWidth(COLUMN::TYPE, 70); m_table->setColumnWidth(COLUMN::MESSAGE, 450); m_table->setColumnWidth(COLUMN::FILE, 300); m_table->setColumnWidth(COLUMN::LINE, 50); m_table->setColumnHidden(COLUMN::ID, true); QStringList headers; headers << "Type" << "Message" << "File" << "Line" << "Indexed"; m_model->setHorizontalHeaderLabels(headers); connect(m_table->selectionModel(), &QItemSelectionModel::currentRowChanged, [=](const QModelIndex& index, const QModelIndex& previousIndex) { if (index.isValid() && !m_ignoreRowSelection) { if (m_model->item(index.row(), COLUMN::FILE) == nullptr) { return; } MessageShowErrors(m_model->item(index.row(), COLUMN::ID)->text().toUInt()).dispatch(); } }); layout->addWidget(m_table); // Setup Checkboxes QBoxLayout* checkboxes = new QHBoxLayout(); checkboxes->addSpacing(15); m_showFatals = createFilterCheckbox("fatals", true, checkboxes); m_showErrors = createFilterCheckbox("errors", true, checkboxes); m_showNonIndexedFatals = createFilterCheckbox("fatals in non-indexed files", true, checkboxes); m_showNonIndexedErrors = createFilterCheckbox("errors in non-indexed files", false, checkboxes); checkboxes->addStretch(); layout->addLayout(checkboxes); doRefreshView(); } void QtErrorView::refreshView() { m_refreshFunctor(); } void QtErrorView::clear() { m_clearFunctor(); } void QtErrorView::addErrors(const std::vector& errors, bool scrollTo) { m_addErrorsFunctor(errors, scrollTo); } void QtErrorView::setErrorId(Id errorId) { m_setErrorIdFunctor(errorId); } void QtErrorView::doRefreshView() { setStyleSheet(); } void QtErrorView::doClear() { if (!m_model->index(0, 0).data(Qt::DisplayRole).toString().isEmpty()) { m_model->removeRows(0, m_model->rowCount()); } m_errors.clear(); } void QtErrorView::doAddErrors(const std::vector& errors, bool scrollTo) { for (const ErrorInfo& error : errors) { m_errors.push_back(error); addErrorToTable(error); } if (scrollTo) { m_table->showLastRow(); } else { m_table->showFirstRow(); } } void QtErrorView::doSetErrorId(Id errorId) { QList items = m_model->findItems(QString::number(errorId), Qt::MatchExactly, COLUMN::ID); if (items.size() == 1) { m_ignoreRowSelection = true; m_table->selectRow(items.at(0)->row()); m_ignoreRowSelection = false; } } void QtErrorView::setStyleSheet() const { QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this); utility::setWidgetBackgroundColor(widget, ColorScheme::getInstance()->getColor("error/background")); QPalette palette(m_showErrors->palette()); palette.setColor(QPalette::WindowText, QColor(ColorScheme::getInstance()->getColor("table/text/normal").c_str())); //palette.setColor(QPalette::Text, QColor(ColorScheme::getInstance()->getColor("error/text/normal").c_str())); //palette.setColor(QPalette::ButtonText, QColor(ColorScheme::getInstance()->getColor("error/text/normal").c_str())); //m_showErrors->setAutoFillBackground(true); m_showErrors->setPalette(palette); m_showFatals->setPalette(palette); m_showNonIndexedErrors->setPalette(palette); m_showNonIndexedFatals->setPalette(palette); //widget->setStyleSheet( //utility::getStyleSheet(ResourcePaths::getGuiPath() + "error_view/error_view.css").c_str() //); m_table->updateRows(); } void QtErrorView::addErrorToTable(const ErrorInfo& error) { if (!isShownError(error)) { return; } int rowNumber = m_table->getFilledRowCount(); if (rowNumber < m_model->rowCount()) { m_model->insertRow(rowNumber); } m_model->setItem(rowNumber, COLUMN::TYPE, new QStandardItem(error.fatal ? "FATAL" : "ERROR")); m_model->item(rowNumber, COLUMN::TYPE)->setForeground(QBrush(Qt::red)); m_model->item(rowNumber, COLUMN::TYPE)->setTextAlignment(Qt::AlignCenter); m_model->setItem(rowNumber, COLUMN::MESSAGE, new QStandardItem(error.message.c_str())); m_model->item(rowNumber, COLUMN::MESSAGE)->setIcon(s_errorIcon); m_model->setItem(rowNumber, COLUMN::FILE, new QStandardItem(error.filePath.str().c_str())); m_model->item(rowNumber, COLUMN::FILE)->setToolTip(error.filePath.str().c_str()); m_model->setItem(rowNumber, COLUMN::LINE, new QStandardItem(QString::number(error.lineNumber))); m_model->setItem(rowNumber, COLUMN::INDEXED, new QStandardItem(error.indexed ? "yes" : "no")); m_model->setItem(rowNumber, COLUMN::ID, new QStandardItem(QString::number(error.id))); m_table->updateRows(); } QCheckBox* QtErrorView::createFilterCheckbox(const QString& name, bool checked, QBoxLayout* layout) { QCheckBox* checkbox = new QCheckBox(name); checkbox->setChecked(checked); connect(checkbox, &QCheckBox::stateChanged, [=](int) { m_table->selectionModel()->clearSelection(); ErrorFilter filter; filter.error = m_showErrors->isChecked(); filter.fatal = m_showFatals->isChecked(); filter.unindexedError = m_showNonIndexedErrors->isChecked(); filter.unindexedFatal = m_showNonIndexedFatals->isChecked(); MessageErrorFilterChanged(filter).dispatch(); } ); layout->addWidget(checkbox); layout->addSpacing(25); return checkbox; } bool QtErrorView::isShownError(const ErrorInfo& error) { if (!error.fatal && error.indexed && m_showErrors->isChecked()) { return true; } if (error.fatal && error.indexed && m_showFatals->isChecked()) { return true; } if (!error.fatal && !error.indexed && m_showNonIndexedErrors->isChecked()) { return true; } if (error.fatal && !error.indexed && m_showNonIndexedFatals->isChecked()) { return true; } return false; }