Loading files
08cd531bbThis file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "rulecheckmessagesmodel.h"
#include "../utils/slinthelpers.h"
#include "../utils/uihelpers.h"
#include <librepcb/core/utils/toolbox.h>
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
RuleCheckMessagesModel::RuleCheckMessagesModel(QObject* parent) noexcept
: QObject(parent), mUnapprovedCount(0), mErrorCount(0), mActionWindowId(0) {
}
RuleCheckMessagesModel::~RuleCheckMessagesModel() noexcept {
}
/*******************************************************************************
* General Methods
******************************************************************************/
void RuleCheckMessagesModel::clear() noexcept {
mMessages.clear();
mApprovals.clear();
mAutoFixed.clear();
notify_reset();
updateCounters();
}
void RuleCheckMessagesModel::setAutofixHandler(
AutofixHandler handler) noexcept {
mAutofixHandler = handler;
notify_reset();
}
void RuleCheckMessagesModel::setMessages(
const RuleCheckMessageList& messages,
const QSet<SExpression>& approvals) noexcept {
mMessages = messages;
mApprovals = approvals;
mAutoFixed.clear();
sortMessages();
updateCounters();
}
/*******************************************************************************
* Implementations
******************************************************************************/
std::size_t RuleCheckMessagesModel::row_count() const {
return mMessages.size();
}
std::optional<ui::RuleCheckMessageData> RuleCheckMessagesModel::row_data(
std::size_t i) const {
if (auto msg = mMessages.value(i)) {
return ui::RuleCheckMessageData{
l2s(msg->getSeverity()), // Severity
q2s(msg->getMessage()), // Message
q2s(msg->getDescription()), // Description
mApprovals.contains(msg->getApproval()), // Approved
mAutoFixed.contains(msg->getApproval()), // Auto-fixed
mAutofixHandler && mAutofixHandler(msg, true), // Supports autofix
mActionWindowId, // Action window ID
ui::RuleCheckMessageAction::None, // Action
};
} else {
return std::nullopt;
}
}
void RuleCheckMessagesModel::set_row_data(
std::size_t i, const ui::RuleCheckMessageData& data) noexcept {
if (auto msg = mMessages.value(i)) {
mActionWindowId = data.action_window_id;
if (data.approved && (!mApprovals.contains(msg->getApproval()))) {
mApprovals.insert(msg->getApproval());
emit approvalChanged(msg->getApproval(), true);
sortMessages();
updateCounters();
} else if ((!data.approved) && mApprovals.contains(msg->getApproval())) {
mApprovals.remove(msg->getApproval());
emit approvalChanged(msg->getApproval(), false);
sortMessages();
updateCounters();
} else if (data.action == ui::RuleCheckMessageAction::Highlight) {
emit highlightRequested(msg, false, mActionWindowId);
} else if (data.action == ui::RuleCheckMessageAction::HighlightAndZoomTo) {
emit highlightRequested(msg, true, mActionWindowId);
} else if (data.action == ui::RuleCheckMessageAction::Autofix) {
QMetaObject::invokeMethod(
this,
[this, i, msg]() {
if (mAutofixHandler && mAutofixHandler(msg, false)) {
// If the message is approved, clean up the now obsolete approval.
if (mApprovals.contains(msg->getApproval())) {
mApprovals.remove(msg->getApproval());
emit approvalChanged(msg->getApproval(), false);
}
mAutoFixed.insert(msg->getApproval());
if (mMessages.value(i) == msg) {
notify_row_changed(i);
}
}
},
Qt::QueuedConnection);
} else if (data.action != ui::RuleCheckMessageAction::None) {
qWarning() << "Unhandled action in RuleCheckMessagesModel:"
<< static_cast<int>(data.action);
}
}
}
/*******************************************************************************
* Private Methods
******************************************************************************/
void RuleCheckMessagesModel::sortMessages() noexcept {
// Sort by approval state, severity and message.
Toolbox::sortNumeric(
mMessages,
[this](const QCollator& cmp,
const std::shared_ptr<const RuleCheckMessage>& lhs,
const std::shared_ptr<const RuleCheckMessage>& rhs) {
if (lhs && rhs) {
const bool lhsApproved = mApprovals.contains(lhs->getApproval());
const bool rhsApproved = mApprovals.contains(rhs->getApproval());
if (lhsApproved != rhsApproved) {
return rhsApproved;
} else if (lhs->getSeverity() != rhs->getSeverity()) {
return lhs->getSeverity() > rhs->getSeverity();
} else {
return cmp(lhs->getMessage(), rhs->getMessage());
}
} else {
return false;
}
},
Qt::CaseInsensitive, false);
notify_reset();
}
void RuleCheckMessagesModel::updateCounters() noexcept {
int unapproved = 0;
int errors = 0;
for (const auto& msg : std::as_const(mMessages)) {
if (!mApprovals.contains(msg->getApproval())) {
++unapproved;
}
if (msg->getSeverity() == RuleCheckMessage::Severity::Error) {
++errors;
}
}
if (unapproved != mUnapprovedCount) {
mUnapprovedCount = unapproved;
emit unapprovedCountChanged(mUnapprovedCount);
}
if (errors != mErrorCount) {
mErrorCount = errors;
emit errorCountChanged(mErrorCount);
}
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb