From 95ea710466c973e028ef98aaeebda13f36d4c383 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 17 Feb 2016 04:38:53 +0100 Subject: [PATCH] Add widget for import errors --HG-- branch : feature-material-editor --- code/nel/tools/3d/mesh_editor/icons.qrc | 7 + .../3d/mesh_editor/icons/cross-circle.png | Bin 0 -> 689 bytes .../3d/mesh_editor/icons/exclamation.png | Bin 0 -> 613 bytes .../mesh_editor/icons/information-white.png | Bin 0 -> 651 bytes code/nel/tools/3d/mesh_editor/main_window.cpp | 14 + code/nel/tools/3d/mesh_editor/main_window.h | 4 + .../tools/3d/shared_widgets/error_list.cpp | 477 ++++++++++++++++++ code/nel/tools/3d/shared_widgets/error_list.h | 118 +++++ 8 files changed, 620 insertions(+) create mode 100644 code/nel/tools/3d/mesh_editor/icons.qrc create mode 100644 code/nel/tools/3d/mesh_editor/icons/cross-circle.png create mode 100644 code/nel/tools/3d/mesh_editor/icons/exclamation.png create mode 100644 code/nel/tools/3d/mesh_editor/icons/information-white.png create mode 100644 code/nel/tools/3d/shared_widgets/error_list.cpp create mode 100644 code/nel/tools/3d/shared_widgets/error_list.h diff --git a/code/nel/tools/3d/mesh_editor/icons.qrc b/code/nel/tools/3d/mesh_editor/icons.qrc new file mode 100644 index 000000000..31a9f782d --- /dev/null +++ b/code/nel/tools/3d/mesh_editor/icons.qrc @@ -0,0 +1,7 @@ + + + icons/cross-circle.png + icons/exclamation.png + icons/information-white.png + + diff --git a/code/nel/tools/3d/mesh_editor/icons/cross-circle.png b/code/nel/tools/3d/mesh_editor/icons/cross-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..d3b37afb85093a9b9578adf66d543559e9578143 GIT binary patch literal 689 zcmV;i0#5yjP)pb$kC;xkQ4}rBtxUqS-UttfAanG^qFNCS)6w`lff94g2BB< zySvJO=cS%)L$BQ)k9ijq#T$voZ=W0;?OhG~sR>Iym{yb%#mw5yj?&h3X(5+`Znrxl z+Gm>5!&FLP=jJkmnHb=D(y`@b`H!Ya_w#ug@TCW)oh^GCVJpz%)&W?eBxG>rlcr%d+rheH}a=4}|CELxe%}B|9=$bXiuk zaov8O4|3r!sHzIpYLyx>cuH>(7RV{}`(Wz2NSNsiz{UX!)73ExpX&n0aWtAB2voPG zcALYw_NY!X=mY%LYBh6EuY=?`kSrEwV4mk8b#?|`avTJ(ER!%319W>|t5h0(oVYjz zf7#f8PphlcfM}~+rUo6uXcA`HApfJ$DC15UKex9j{1xH5I7W1wOwx4UB@*Deu2Jdr zN`#phxOhFU94Gs+UROf^#<$H)xQG4HNThy@a1h~>ZdcV^H%pkAn}{8Umv{<=Rx6_j zf*cTpP>|z9GS+e&^U|`Ks%4e>2nYUim8nVHbw3wPGmZM^G2vs&`$v(-g}Lc-{wu%$ XhHnx2;pWVo00000NkvXXu0mjfwVykg literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/mesh_editor/icons/exclamation.png b/code/nel/tools/3d/mesh_editor/icons/exclamation.png new file mode 100644 index 0000000000000000000000000000000000000000..21fd8f78a511be27106355ee0af154a81b3332ea GIT binary patch literal 613 zcmV-r0-F7aP)`cGKci-IR3~>{==oNRbed0f`+i(5ey(R`eZs1y;NQERaAU3nU~|6-XB`kP4{d z*zskUv62#KS|N3$&z?E+|7SeoGaMlV&eFIyFSwKDij-%g{zJ;oX(Dt=@}_Rxvvte0 zS^p#v$})g|p}V?_h0>Z<))%p$tg+ZM?bHMm*Rb6N2|tM>{45&Q-3E*OR|2}y zvUIMtS}Hfp?VYc%z4Hx}@->i7Ou)tuD%Kq*@;{;=2!Ju{?;-ulEr-pG zG)Eqkr8LtBlEIA&inAiiMI()Wf$#e{Y3xIxpcv;bS}RO5>EYA#=s;x-ajtQ7-HC%Q zFib;ewOZhL9_&9_hK%e2KU;Uw-mXhB@{;NY`Co_=00#Y>+vU0IO9(|uZ_oj+zX$Dh z8@k;tq(TTpi~z()k&4wNrXBkbD@2M4oY+*Wjrrc;TZpqB2snc8-jf^=4|6c*Ls8e} z3E(F4FfU5z7U(watCjjfoPCga})X8!IUJpa3XF<_%MYrlWz zZSlbXqSvqXJ2c!mUg=Lyzlj_~+*z;lZvh4Xn6oUV^gx9+00000NkvXXu0mjfu=y3C literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/mesh_editor/icons/information-white.png b/code/nel/tools/3d/mesh_editor/icons/information-white.png new file mode 100644 index 0000000000000000000000000000000000000000..70052384af3a04962ea257a498c6dc43c0bcae93 GIT binary patch literal 651 zcmV;60(AX}P)lS&Y=R(c8TsYm|;ixm0?NTD7*cuFtgDYi(VCp~zRUPOY>_7o6uGf=BYr6giE ziM!kVbmnb$alu<3{NBgR?>Fzw>})QIBDlzqXsSQngJQ7+x_$*X*D8#$RWvUls^`2e zVmA!KrsLR0rg;jZ(GXg%=i>m$K*BPEvqt?+(RgtC5=@TA?&F?cJLvqWwc7Rya@Nqa zoq0hb)?}x-{%A(2Tvs4YEfBsNc;d$J{1!NgMmPD7D14+a8EZ#lcr$X&eG!C zgdik?_8(r&LJ)*-c=#1pU)b|`3GUx4z~);quq+!MKKUX< z?>4HySX?eDO?fOYH0cW@sem4O$r*}=R8YK0j_ty)WWIfbnWsLQIKSNOez$5@3oZ&3 zL`+1xSY?@K0{rO3nzV?THn#hz?NJkfqNpj*F7U5SRXH4VVoe%ARZGoQJJ;`-6hIR< z5;)fdk~87wFBSGXa-TG50L=Hu_4(Syj_;oQRs~U#IJ|#Z7N9-Zj#2#L4YaddAction(m_CommandLogDock->toggleViewAction()); } + // ErrorList (Error List) + { + m_ErrorListDock = new QDockWidget(this); + m_ErrorListDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + m_ErrorList = new CErrorList(m_ErrorListDock); + m_ErrorListDock->setWidget(m_ErrorList); + addDockWidget(Qt::BottomDockWidgetArea, m_ErrorListDock); + m_WidgetsMenu->addAction(m_ErrorListDock->toggleViewAction()); + tabifyDockWidget(m_CommandLogDock, m_ErrorListDock); + } + // GraphicsConfig (Graphics Configuration) { m_GraphicsConfigDock = new QDockWidget(this); @@ -381,6 +394,7 @@ void CMainWindow::createDockWindows() void CMainWindow::translateDockWindows() { m_CommandLogDock->setWindowTitle(tr("Console")); + m_ErrorListDock->setWindowTitle(tr("Error List")); m_GraphicsConfigDock->setWindowTitle(tr("Graphics Configuration")); m_AssetTreeDock->setWindowTitle(tr("Asset Database")); } diff --git a/code/nel/tools/3d/mesh_editor/main_window.h b/code/nel/tools/3d/mesh_editor/main_window.h index 74ecae5a1..36ba41eb1 100644 --- a/code/nel/tools/3d/mesh_editor/main_window.h +++ b/code/nel/tools/3d/mesh_editor/main_window.h @@ -63,6 +63,7 @@ namespace NLSOUND { namespace NLQT { class CCommandLogDisplayer; + class CErrorList; } class CGraphicsViewport; @@ -136,6 +137,9 @@ private: NLQT::CCommandLogDisplayer *m_CommandLog; QDockWidget *m_CommandLogDock; + NLQT::CErrorList *m_ErrorList; + QDockWidget *m_ErrorListDock; + CGraphicsConfig *m_GraphicsConfig; QScrollArea *m_GraphicsConfigScroll; QDockWidget *m_GraphicsConfigDock; diff --git a/code/nel/tools/3d/shared_widgets/error_list.cpp b/code/nel/tools/3d/shared_widgets/error_list.cpp new file mode 100644 index 000000000..caf270992 --- /dev/null +++ b/code/nel/tools/3d/shared_widgets/error_list.cpp @@ -0,0 +1,477 @@ +/* + +Copyright (C) 2015 by authors +Author: Jan Boon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// Source: https://github.com/kaetemi/errorlist + +#include "error_list.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace NLQT { + +#define DATAROLE_TYPE (Qt::UserRole + 0) +#define DATAROLE_TIMESTAMP (Qt::UserRole + 1) +#define DATAROLE_GROUP (Qt::UserRole + 2) +#define DATAROLE_MESSAGE (Qt::UserRole + 3) +#define DATAROLE_LINE (Qt::UserRole + 4) +#define DATAROLE_USERDATA (Qt::UserRole + 5) +#define DATAROLE_COLLAPSED (Qt::UserRole + 6) + +class CErrorListItem : public QListWidgetItem +{ +public: + CErrorListItem(const QIcon &icon, const QString &message) : QListWidgetItem(icon, message) + { + + } + + virtual bool operator<(const QListWidgetItem &other) const Q_DECL_OVERRIDE + { + time_t this_timestamp = data(DATAROLE_TIMESTAMP).toInt(); + time_t other_timestamp = other.data(DATAROLE_TIMESTAMP).toInt(); + return this_timestamp < other_timestamp; + } +}; + +const char *iconNames[] = { + ":/icons/cross-circle.png", + ":/icons/exclamation.png", + ":/icons/information-white.png" +}; + +const char *filterText[] = { + "Errors", + "Warnings", + "Messages" +}; + +CErrorList::CErrorList(QWidget *parent) : QWidget(parent), m_Collapse(true), m_CollapseBtn(NULL), m_Message(NULL) +{ + m_Filter[0] = true; + m_Filter[1] = true; + m_Filter[2] = true; + m_FilterBtn[0] = NULL; + m_FilterBtn[1] = NULL; + m_FilterBtn[2] = NULL; + m_FilterCounts[0] = 0; + m_FilterCounts[1] = 0; + m_FilterCounts[2] = 0; + + QVBoxLayout *layout = new QVBoxLayout(this); + + QHBoxLayout *buttons = new QHBoxLayout(this); + + QPushButton *clearBtn = new QPushButton(this); + clearBtn->setText(tr("Clear")); + connect(clearBtn, SIGNAL(clicked()), this, SLOT(clear())); + buttons->addWidget(clearBtn); + + QPushButton *collapseBtn = new QPushButton(this); + m_CollapseBtn = collapseBtn; + collapseBtn->setText(tr("Collapse")); + collapseBtn->setCheckable(true); + collapseBtn->setChecked(m_Collapse); + connect(collapseBtn, SIGNAL(toggled(bool)), this, SLOT(collapse(bool))); + buttons->addWidget(collapseBtn); + + buttons->addStretch(); + + QPushButton *errorBtn = new QPushButton(this); + m_FilterBtn[0] = errorBtn; + errorBtn->setIcon(QIcon(iconNames[0])); + updateFilterCount(0); + errorBtn->setCheckable(true); + errorBtn->setChecked(m_Filter[0]); + connect(errorBtn, SIGNAL(toggled(bool)), this, SLOT(filterError(bool))); + buttons->addWidget(errorBtn); + + QPushButton *warningBtn = new QPushButton(this); + m_FilterBtn[1] = warningBtn; + warningBtn->setIcon(QIcon(iconNames[1])); + updateFilterCount(1); + warningBtn->setCheckable(true); + warningBtn->setChecked(m_Filter[1]); + connect(warningBtn, SIGNAL(toggled(bool)), this, SLOT(filterWarning(bool))); + buttons->addWidget(warningBtn); + + QPushButton *messageBtn = new QPushButton(this); + m_FilterBtn[2] = messageBtn; + messageBtn->setIcon(QIcon(iconNames[2])); + updateFilterCount(2); + messageBtn->setCheckable(true); + messageBtn->setChecked(m_Filter[2]); + connect(messageBtn, SIGNAL(toggled(bool)), this, SLOT(filterMessage(bool))); + buttons->addWidget(messageBtn); + + layout->addLayout(buttons); + + QSplitter *splitter = new QSplitter(Qt::Vertical, this); + + m_List = new QListWidget(this); + m_List->setTextElideMode(Qt::ElideRight); + m_List->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // m_List->setSortingEnabled(true); + connect(m_List, &QListWidget::itemClicked, this, &CErrorList::listItemClicked); + connect(m_List, &QListWidget::itemDoubleClicked, this, &CErrorList::listItemDoubleClicked); + splitter->addWidget(m_List); + + QTextEdit *messageText = new QTextEdit(this); + m_Message = messageText; + messageText->setReadOnly(true); + messageText->setVisible(false); + messageText->setAcceptRichText(true); + splitter->addWidget(messageText); + + layout->addWidget(splitter); + + setLayout(layout); +} + +CErrorList::~CErrorList() +{ + +} + +void CErrorList::clear() +{ + m_CurrentMessage = NULL; + m_Message->setVisible(false); + m_CollapseItems.clear(); + m_List->clear(); + m_FilterCounts[0] = 0; + m_FilterCounts[1] = 0; + m_FilterCounts[2] = 0; + updateFilterCount(0); + updateFilterCount(1); + updateFilterCount(2); +} + +void CErrorList::clear(const QString &group) +{ + for (int i = 0; i < m_List->count(); ++i) + { + QListWidgetItem *item = m_List->item(i); + if (item->data(DATAROLE_GROUP).toString() == group) + { + if (m_CurrentMessage == item) + { + m_CurrentMessage = NULL; + m_Message->setVisible(false); + } + if (m_Collapse) + { + QString cs = getCollapseString(item); + std::map::iterator it + = m_CollapseItems.find(cs); + if (it != m_CollapseItems.end()) + m_CollapseItems.erase(it); + } + --m_FilterCounts[(int)item->data(DATAROLE_TYPE).toInt()]; + delete item; + --i; + } + } + updateFilterCount(0); + updateFilterCount(1); + updateFilterCount(2); +} + +void CErrorList::collapse(bool c) +{ + if (c != m_Collapse) + { + m_Collapse = c; + m_CollapseBtn->setChecked(c); + + if (c) + { + for (int i = 0; i < m_List->count(); ++i) + { + QListWidgetItem *item = m_List->item(i); + QString cs = getCollapseString(item); + QListWidgetItem *ref = m_CollapseItems[cs]; + + if (ref != NULL) + { + ref->setData(DATAROLE_COLLAPSED, ref->data(DATAROLE_COLLAPSED).toInt() + 1); + updateCollapseText(ref); + item->setData(DATAROLE_COLLAPSED, 0); + item->setHidden(true); + if (m_CurrentMessage == item) + { + m_CurrentMessage = NULL; + m_Message->setHidden(true); + } + } + else + { + m_CollapseItems[cs] = item; + } + } + } + else + { + m_CollapseItems.clear(); + for (int i = 0; i < m_List->count(); ++i) + { + int cc = m_List->item(i)->data(DATAROLE_COLLAPSED).toInt(); + if (cc > 1) + { + m_List->item(i)->setText(m_List->item(i)->data(DATAROLE_LINE).toString()); + } + if (cc == 0) + { + bool hide = !m_Filter[m_List->item(i)->data(DATAROLE_TYPE).toInt()]; + m_List->item(i)->setHidden(hide); + } + if (cc != 1) + { + m_List->item(i)->setData(DATAROLE_COLLAPSED, 1); + } + } + } + } +} + +void CErrorList::filter(ErrorType type, bool f) +{ + if (f != m_Filter[(int)type]) + { + m_Filter[(int)type] = f; + m_FilterBtn[(int)type]->setChecked(f); + + for (int i = 0; i < m_List->count(); ++i) + { + if (m_List->item(i)->data(DATAROLE_TYPE).toInt() == (int)type) + { + bool hide = + m_List->item(i)->data(DATAROLE_COLLAPSED).toInt() == 0 + || !f; + m_List->item(i)->setHidden(hide); + if (hide && m_CurrentMessage == m_List->item(i)) + { + m_CurrentMessage = NULL; + m_Message->setHidden(true); + } + } + } + } +} + +void CErrorList::updateFilterCount(int filter) +{ + m_FilterBtn[filter]->setText(QString(" ") + QString::number(m_FilterCounts[filter]) + " " + filterText[filter]); +} + +void CErrorList::filterError(bool f) +{ + filter(Error, f); +} + +void CErrorList::filterWarning(bool f) +{ + filter(Warning, f); +} + +void CErrorList::filterMessage(bool f) +{ + filter(Message, f); +} + +void CErrorList::markClear(const QString &group) +{ + for (int i = 0; i < m_List->count(); ++i) + { + QListWidgetItem *item = m_List->item(i); + if (item->data(DATAROLE_GROUP).toString() == group) + { + QString cs = getCollapseString(item); + m_MarkedClear.insert(cs); + } + } +} + +void CErrorList::clearMarked() +{ + for (int i = 0; i < m_List->count(); ++i) + { + QListWidgetItem *item = m_List->item(i); + QString cs = getCollapseString(item); + if (m_MarkedClear.find(cs) != m_MarkedClear.end()) + { + if (m_CurrentMessage == item) + { + m_CurrentMessage = NULL; + m_Message->setVisible(false); + } + if (m_Collapse) + { + QString cs = getCollapseString(item); + std::map::iterator it + = m_CollapseItems.find(cs); + if (it != m_CollapseItems.end()) + m_CollapseItems.erase(it); + } + --m_FilterCounts[(int)item->data(DATAROLE_TYPE).toInt()]; + delete item; + --i; + } + } +} + +void CErrorList::listItemClicked(QListWidgetItem *item) +{ + if (item != m_CurrentMessage) + { + if (item->isSelected()) + { + QString text = item->data(DATAROLE_MESSAGE).toString(); + m_Message->setHtml(text); + m_Message->setVisible(true); + } + else + { + m_CurrentMessage = NULL; + m_Message->setVisible(false); + } + } +} + +void CErrorList::listItemDoubleClicked(QListWidgetItem *item) +{ + emit request(item->data(DATAROLE_GROUP).toString(), item->data(DATAROLE_USERDATA).toMap()); +} + +QString CErrorList::getCollapseString(QListWidgetItem *item) +{ + return item->data(DATAROLE_GROUP).toString() + " / " + item->data(DATAROLE_LINE).toString(); +} + +void CErrorList::updateCollapseText(QListWidgetItem *item) +{ + item->setText(QString("(" + QString::number(item->data(DATAROLE_COLLAPSED).toInt()) + "x) " + item->data(DATAROLE_LINE).toString()));// .replace('\n', ' ').replace('\r', ' '))); +} + +void CErrorList::add(ErrorType type, const QString &group, time_t timestamp, const QString &message, const QMap &userData) +{ + QTextDocument doc; + doc.setHtml(message); + QString line = doc.toPlainText().replace('\n', ' ').replace('\r', ' '); + + CErrorListItem *item = new CErrorListItem(QIcon(iconNames[(int)type]), line); + item->setData(DATAROLE_TYPE, (int)type); + item->setData(DATAROLE_TIMESTAMP, timestamp); + item->setData(DATAROLE_GROUP, group); + item->setData(DATAROLE_MESSAGE, message); + item->setData(DATAROLE_LINE, line); + item->setData(DATAROLE_USERDATA, userData); + + QString cs = getCollapseString(item); + if (m_MarkedClear.find(cs) != m_MarkedClear.end()) + { + m_MarkedClear.erase(cs); + return; + } + + bool hide = m_Collapse; + if (hide) + { + QListWidgetItem *ref = m_CollapseItems[cs]; + hide = ref != NULL; + if (hide) + { + ref->setData(DATAROLE_COLLAPSED, ref->data(DATAROLE_COLLAPSED).toInt() + 1); + updateCollapseText(ref); + item->setData(DATAROLE_COLLAPSED, 0); + } + else + { + m_CollapseItems[cs] = item; + } + } + if (!hide) + { + item->setData(DATAROLE_COLLAPSED, 1); + hide = !m_Filter[(int)type]; + } + + m_List->addItem(item); + item->setHidden(hide); + ++m_FilterCounts[(int)type]; + updateFilterCount((int)type); +} + +void CErrorList::update(const QString &group, const QString &message) +{ + // NOTE: This does not play well with collapse, so you should only have one message present in the category + // Automatically adds a message if no message exists in the category + for (int i = 0; i < m_List->count(); ++i) + { + QListWidgetItem *item = m_List->item(i); + if (item->data(DATAROLE_GROUP).toString() == group) + { + QTextDocument doc; + doc.setHtml(message); + QString line = doc.toPlainText().replace('\n', ' ').replace('\r', ' '); + item->setData(DATAROLE_MESSAGE, message); + item->setData(DATAROLE_LINE, line); + item->setText(line); + return; + } + } + add(Message, group, message); +} + +void CErrorList::add(ErrorType type, const QString &group, time_t timestamp, const QString &message) +{ + QMap nullMap; + add(type, group, timestamp, message, nullMap); +} + +void CErrorList::add(ErrorType type, const QString &group, const QString &message, const QMap &userData) +{ + add(type, group, QDateTime::currentDateTime().toTime_t(), message, userData); +} + +void CErrorList::add(ErrorType type, const QString &group, const QString &message) +{ + QMap nullMap; + add(type, group, message, nullMap); +} + +} + +/* end of file */ \ No newline at end of file diff --git a/code/nel/tools/3d/shared_widgets/error_list.h b/code/nel/tools/3d/shared_widgets/error_list.h new file mode 100644 index 000000000..f90f52db5 --- /dev/null +++ b/code/nel/tools/3d/shared_widgets/error_list.h @@ -0,0 +1,118 @@ +/* + +Copyright (C) 2015 by authors +Author: Jan Boon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +// Source: https://github.com/kaetemi/errorlist + +#ifndef ERRORLIST_H +#define ERRORLIST_H + +#define ERRORLIST_EXPORT + +#include +#include + +#include +#include +#include +#include + +class QListWidgetItem; +class QListWidget; +class QPushButton; +class QTextEdit; + +namespace NLQT { + +class ERRORLIST_EXPORT CErrorList : public QWidget +{ + Q_OBJECT + +public: + enum ErrorType + { + Error, + Warning, + Message + }; + +public: + CErrorList(QWidget *parent); + virtual ~CErrorList(); + + void add(ErrorType type, const QString &group, time_t timestamp, const QString &message, const QMap &userData); + void add(ErrorType type, const QString &group, time_t timestamp, const QString &message); + void add(ErrorType type, const QString &group, const QString &message, const QMap &userData); + void add(ErrorType type, const QString &group, const QString &message); + + void update(const QString &group, const QString &message); + + void markClear(const QString &group); + void clearMarked(); + + void clear(const QString &group); + void filter(ErrorType type, bool f); + +signals: + void request(const QString &group, const QMap &userData); + +public slots: + void clear(); + void collapse(bool c); + void filterError(bool f); + void filterWarning(bool f); + void filterMessage(bool f); + +private slots: + void listItemClicked(QListWidgetItem *item); + void listItemDoubleClicked(QListWidgetItem *item); + +private: + void updateFilterCount(int filter); + static QString getCollapseString(QListWidgetItem *item); + static void updateCollapseText(QListWidgetItem *item); + +private: + QListWidget *m_List; + std::map m_CollapseItems; + bool m_Collapse; + QPushButton *m_CollapseBtn; + bool m_Filter[3]; + QPushButton *m_FilterBtn[3]; + int m_FilterCounts[3]; + QTextEdit *m_Message; + QListWidgetItem *m_CurrentMessage; + std::set m_MarkedClear; + +}; /* class CErrorList */ + +} + +#endif /* ERRORLIST_H */ + +/* end of file */