Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add layout orientation to ErrorLogDockWidget #1100

Merged
merged 1 commit into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions Libs/Widgets/Resources/UI/ctkErrorLogWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,30 @@
<rect>
<x>0</x>
<y>0</y>
<width>754</width>
<height>429</height>
<width>463</width>
<height>428</height>
</rect>
</property>
<property name="windowTitle">
<string>Log messages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="ctkErrorLogGridLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<property name="spacing">
<number>1</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="ShowAllEntryButton">
Expand Down Expand Up @@ -72,7 +87,7 @@
</item>
</layout>
</item>
<item>
<item row="1" column="0">
<widget class="QTableView" name="ErrorLogTableView">
<property name="alternatingRowColors">
<bool>true</bool>
Expand All @@ -94,8 +109,9 @@
</attribute>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="ErrorLogDescription"/>
<item row="2" column="0">
<widget class="QTextBrowser" name="ErrorLogDescription">
</widget>
</item>
</layout>
</widget>
Expand Down
100 changes: 100 additions & 0 deletions Libs/Widgets/ctkErrorLogWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// Qt includes
#include <QDebug>
#include <QAbstractItemModel>
#include <QKeyEvent>
#include <QScrollBar>
#include <QStandardItemModel>

// CTK includes
Expand All @@ -37,6 +39,8 @@ class ctkErrorLogWidgetPrivate : public Ui_ctkErrorLogWidget
typedef ctkErrorLogWidgetPrivate Self;
ctkErrorLogWidgetPrivate(ctkErrorLogWidget& object);

Qt::Orientation LayoutOrientation;

ctkErrorLogLevel::LogLevels ErrorButtonFilter;
ctkErrorLogLevel::LogLevels WarningButtonFilter;
ctkErrorLogLevel::LogLevels InfoButtonFilter;
Expand All @@ -53,6 +57,7 @@ class ctkErrorLogWidgetPrivate : public Ui_ctkErrorLogWidget
ctkErrorLogWidgetPrivate::ctkErrorLogWidgetPrivate(ctkErrorLogWidget& object)
: q_ptr(&object)
{
this->LayoutOrientation = Qt::Vertical;
this->ErrorButtonFilter = ctkErrorLogLevel::Error | ctkErrorLogLevel::Critical | ctkErrorLogLevel::Fatal;
this->WarningButtonFilter = ctkErrorLogLevel::Warning;
this->InfoButtonFilter = ctkErrorLogLevel::Info | ctkErrorLogLevel::Debug | ctkErrorLogLevel::Trace | ctkErrorLogLevel::Status;
Expand All @@ -63,12 +68,20 @@ void ctkErrorLogWidgetPrivate::init()
{
Q_Q(ctkErrorLogWidget);

#if QT_VERSION >= QT_VERSION_CHECK(5,2,0)
this->ErrorLogDescription->setPlaceholderText(ctkErrorLogWidget::tr("Select messages in the list to see details here."));
#endif

// this->ShowAllEntryButton->setIcon();
this->ShowErrorEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxCritical));
this->ShowWarningEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxWarning));
this->ShowInfoEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxInformation));
this->ClearButton->setIcon(q->style()->standardIcon(QStyle::SP_DialogDiscardButton));

// Make the iconless "All" button the same height as other buttons that have icons
// (they are shown in the same row, so it does not look nice if their height is different)
this->ShowAllEntryButton->setFixedHeight(this->ShowErrorEntryButton->sizeHint().height());

QObject::connect(this->ShowAllEntryButton, SIGNAL(clicked()),
q, SLOT(setAllEntriesVisible()));

Expand All @@ -83,6 +96,12 @@ void ctkErrorLogWidgetPrivate::init()

QObject::connect(this->ClearButton, SIGNAL(clicked()),
q, SLOT(removeEntries()));

QScrollBar* verticalScrollBar = this->ErrorLogTableView->verticalScrollBar();
QObject::connect(verticalScrollBar, SIGNAL(valueChanged(int)),
q, SIGNAL(userViewed()));

this->ErrorLogTableView->installEventFilter(q);
}

// --------------------------------------------------------------------------
Expand Down Expand Up @@ -186,6 +205,53 @@ void ctkErrorLogWidget::setColumnHidden(int columnId, bool hidden) const
d->ErrorLogTableView->setColumnHidden(columnId, hidden);
}

// --------------------------------------------------------------------------
void ctkErrorLogWidget::setLayoutOrientation(Qt::Orientation orientation)
{
Q_D(ctkErrorLogWidget);
if (d->LayoutOrientation == orientation)
{
return;
}

d->ctkErrorLogGridLayout->removeWidget(d->ErrorLogDescription);

int errorLogTableViewIndex = d->ctkErrorLogGridLayout->indexOf(d->ErrorLogTableView);
int errorLogTableViewRowIndex = -1;
int errorLogTableViewColIndex = -1;
int errorLogTableViewRowSpan = -1;
int errorLogTableViewColSpan = -1;

d->ctkErrorLogGridLayout->getItemPosition(errorLogTableViewIndex,
&errorLogTableViewRowIndex, &errorLogTableViewColIndex,
&errorLogTableViewRowSpan, &errorLogTableViewColSpan);

if (orientation == Qt::Vertical)
{
// Description is below message table
d->ctkErrorLogGridLayout->addWidget(d->ErrorLogDescription,
errorLogTableViewRowIndex + 1, errorLogTableViewColIndex, // row, col
1, 1); // rowSpan, colSpan
}
else
{
// Description is in a second column, beside the message table.
// Specifying rowSpan = -1 ensures the widget fills the entire second column.
d->ctkErrorLogGridLayout->addWidget(d->ErrorLogDescription,
0, errorLogTableViewColIndex + 1, // row, col
-1, 1); // rowSpan, colSpan
}

d->LayoutOrientation = orientation;
}

// --------------------------------------------------------------------------
Qt::Orientation ctkErrorLogWidget::layoutOrientation() const
{
Q_D(const ctkErrorLogWidget);
return d->LayoutOrientation;
}

// --------------------------------------------------------------------------
void ctkErrorLogWidget::setAllEntriesVisible(bool visibility)
{
Expand Down Expand Up @@ -259,13 +325,15 @@ void ctkErrorLogWidget::onLogLevelFilterChanged()
d->ShowErrorEntryButton->setChecked(logLevelFilter & d->ErrorButtonFilter);
d->ShowWarningEntryButton->setChecked(logLevelFilter & d->WarningButtonFilter);
d->ShowInfoEntryButton->setChecked(logLevelFilter & d->InfoButtonFilter);
emit userViewed();
}

// --------------------------------------------------------------------------
void ctkErrorLogWidget::removeEntries()
{
Q_ASSERT(this->errorLogModel());
this->errorLogModel()->clear();
emit userViewed();
}

// --------------------------------------------------------------------------
Expand Down Expand Up @@ -296,5 +364,37 @@ void ctkErrorLogWidget::onSelectionChanged(const QItemSelection & selected,

d->ErrorLogDescription->setText(descriptions.join("\n"));

emit userViewed();

// fprintf(stdout, "onSelectionChanged: %d\n", start.msecsTo(QTime::currentTime()));
}

//---------------------------------------------------------------------------
bool ctkErrorLogWidget::eventFilter(QObject* target, QEvent* event)
{
Q_D(ctkErrorLogWidget);
if (target == d->ErrorLogTableView && event->type() == QEvent::KeyPress)
{
// Make Home/End keys jump to first/last message in the list
// (without this, the keys would jump to the first/last cell in the current row)
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Home)
{
QModelIndex firstIndex = d->ErrorLogTableView->model()->index(0, 0);
QItemSelectionModel* select = d->ErrorLogTableView->selectionModel();
select->select(firstIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
d->ErrorLogTableView->scrollToTop();
return true;
}
else if (keyEvent->key() == Qt::Key_End)
{
int rowCount = d->ErrorLogTableView->model()->rowCount();
QModelIndex lastIndex = d->ErrorLogTableView->model()->index(rowCount - 1, 0);
QItemSelectionModel* select = d->ErrorLogTableView->selectionModel();
select->select(lastIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
d->ErrorLogTableView->scrollToBottom();
return true;
}
}
return this->Superclass::eventFilter(target, event);
}
20 changes: 20 additions & 0 deletions Libs/Widgets/ctkErrorLogWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class QModelIndex;
class CTK_WIDGETS_EXPORT ctkErrorLogWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(Qt::Orientation layoutOrientation READ layoutOrientation WRITE setLayoutOrientation)
public:
typedef QWidget Superclass;
explicit ctkErrorLogWidget(QWidget* parentWidget = 0);
Expand All @@ -49,7 +50,24 @@ class CTK_WIDGETS_EXPORT ctkErrorLogWidget : public QWidget
/// \sa ctkErrorLogModel::ColumnsIds
Q_INVOKABLE void setColumnHidden(int columnId, bool hidden) const;

/// This property describes how the list of errors and error description are organized.
/// The orientation must be Qt::Horizontal (the widgets are side-by-side) or Qt::Vertical (the widgets are above-under).
/// The default is Qt::Vertical.
Qt::Orientation layoutOrientation() const;

Q_SIGNALS:

/// Emitted if the user interacted with the widget to view messages
/// (scrolled the message list, changed filter criteria, etc.).
/// This can be useful if the application shows a "new message" notification
/// when a new message is logged: the application can hide the notification
/// when this signal is emitted, because it indicates that the user had a look
/// at the messages.
void userViewed();

public Q_SLOTS:
void setLayoutOrientation(Qt::Orientation orientation);

void setAllEntriesVisible(bool visibility = true);

void setErrorEntriesVisible(bool visibility);
Expand All @@ -70,6 +88,8 @@ protected Q_SLOTS:
void onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);

protected:
bool eventFilter(QObject* target, QEvent* event);

QScopedPointer<ctkErrorLogWidgetPrivate> d_ptr;

private:
Expand Down