diff --git a/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h b/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h new file mode 100644 index 0000000000..639fb234d9 --- /dev/null +++ b/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h @@ -0,0 +1,45 @@ +/** @file privilegedlogwidget.h + * + * @authors Copyright (c) 2015 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * 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 2 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 + */ + +#ifndef CLIENT_UI_WIDGETS_PRIVILEGEDLOGWIDGET_H +#define CLIENT_UI_WIDGETS_PRIVILEGEDLOGWIDGET_H + +#include + +/** + * Special heads-up log for viewing information about the current task (for + * developers). + */ +class PrivilegedLogWidget : public de::GuiWidget +{ + Q_OBJECT + +public: + PrivilegedLogWidget(); + +public slots: + void showLog(); + void hideLog(); + +private: + DENG2_PRIVATE(d) +}; + + +#endif // CLIENT_UI_WIDGETS_PRIVILEGEDLOGWIDGET_H + diff --git a/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp b/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp new file mode 100644 index 0000000000..4c266ad500 --- /dev/null +++ b/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp @@ -0,0 +1,77 @@ +/** @file privilegedlogwidget.cpp + * + * @authors Copyright (c) 2015 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * 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 2 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 + */ + +#include "ui/widgets/privilegedlogwidget.h" +#include "ui/styledlogsinkformatter.h" +#include +#include + +using namespace de; + +DENG_GUI_PIMPL(PrivilegedLogWidget) +{ + StyledLogSinkFormatter formatter; + LogWidget *log = nullptr; + ButtonWidget *closeButton = nullptr; + + Instance(Public *i) : Base(i) + { + log = new LogWidget("privlog"); + log->setLogFormatter(formatter); + log->setPrivilegedEntries(true); + self.add(log); + + closeButton = new ButtonWidget; + closeButton->setSizePolicy(ui::Expand, ui::Expand); + closeButton->setImage(style().images().image("close.ringless")); + closeButton->setImageScale(toDevicePixels(.25f)); + closeButton->setImageColor(style().colors().colorf("altaccent")); + self.add(closeButton); + } +}; + +PrivilegedLogWidget::PrivilegedLogWidget() + : d(new Instance(this)) +{ + auto const &gap = style().rules().rule("gap"); + + hide(); + connect(d->log, SIGNAL(contentHeightIncreased(int)), this, SLOT(showLog())); + connect(d->closeButton, SIGNAL(pressed()), this, SLOT(hideLog())); + + d->log->rule() + .setInput(Rule::Left, rule().left() + gap) + .setInput(Rule::Top, rule().top() + gap) + .setInput(Rule::Right, (rule().left() + rule().midX()) / 2) + .setInput(Rule::Bottom, rule().midY() - gap); + + d->closeButton->rule() + .setInput(Rule::Top, d->log->rule().top()) + .setInput(Rule::Right, d->log->rule().right()); +} + +void PrivilegedLogWidget::showLog() +{ + show(); +} + +void PrivilegedLogWidget::hideLog() +{ + hide(); + d->log->clear(); +} diff --git a/doomsday/sdk/libappfw/include/de/widgets/logwidget.h b/doomsday/sdk/libappfw/include/de/widgets/logwidget.h index 10931d0b26..b8b9ededc9 100644 --- a/doomsday/sdk/libappfw/include/de/widgets/logwidget.h +++ b/doomsday/sdk/libappfw/include/de/widgets/logwidget.h @@ -49,6 +49,13 @@ class LIBAPPFW_PUBLIC LogWidget : public ScrollAreaWidget */ void setLogFormatter(LogSink::IFormatter &formatter); + /** + * Enables the showing of privileged messages. + * + * @param onlyPrivileged Only show privileged entries. + */ + void setPrivilegedEntries(bool onlyPrivileged); + /** * Returns the log sink that can be connected to a log buffer for receiving * log entries into the widget's buffer. diff --git a/doomsday/sdk/libappfw/src/widgets/logwidget.cpp b/doomsday/sdk/libappfw/src/widgets/logwidget.cpp index 157ea56e3b..e7aac4aafd 100644 --- a/doomsday/sdk/libappfw/src/widgets/logwidget.cpp +++ b/doomsday/sdk/libappfw/src/widgets/logwidget.cpp @@ -804,6 +804,11 @@ void LogWidget::setLogFormatter(LogSink::IFormatter &formatter) d->formatter = &formatter; } +void LogWidget::setPrivilegedEntries(bool onlyPrivileged) +{ + d->sink.setPrivileged(onlyPrivileged); +} + LogSink &LogWidget::logSink() { return d->sink; diff --git a/doomsday/sdk/libcore/include/de/core/log.h b/doomsday/sdk/libcore/include/de/core/log.h index d1cd5e8e81..786e8c5c65 100644 --- a/doomsday/sdk/libcore/include/de/core/log.h +++ b/doomsday/sdk/libcore/include/de/core/log.h @@ -80,6 +80,8 @@ #define LOGDEV_WARNING(str) LOGDEV_AT_LEVEL(de::LogEntry::Warning, str) #define LOGDEV_ERROR(str) LOGDEV_AT_LEVEL(de::LogEntry::Error, str) +#define LOG_WIP(str) LOG_AT_LEVEL(de::LogEntry::Privileged | de::LogEntry::Note, str) + // Custom combination of audiences #define LOG_XVERBOSE_TO(audflags, str) LOG_AT_LEVEL((audflags) | de::LogEntry::XVerbose, str) #define LOG_VERBOSE_TO(audflags, str) LOG_AT_LEVEL((audflags) | de::LogEntry::Verbose, str) @@ -288,13 +290,17 @@ class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable Network = (1 << NetworkBit), ///< Network domain: connections, packets, etc. // User groups - Dev = 0x8000000, /**< Native code developer (i.e., the programmer); can be + Dev = 0x08000000, /**< Native code developer (i.e., the programmer); can be combined with other flags to mark the entry for devs. If bit is not set, the entry is for the end-user. */ + Privileged = 0x04000000, /**< Work in progress. Entries with this flag are shown + regardless of log filtering, in a separate overlay. + Use this for whatever you are currently working on + (so there is no need to rely on qDebug). */ - AllDomains = 0xff0000, + AllDomains = 0x00ff0000, DomainMask = AllDomains, - ContextMask = 0xfff0000 + ContextMask = 0x0fff0000 }; static String contextToText(duint32 context) diff --git a/doomsday/sdk/libcore/include/de/core/memorylogsink.h b/doomsday/sdk/libcore/include/de/core/memorylogsink.h index a758cc727e..ce08e202bc 100644 --- a/doomsday/sdk/libcore/include/de/core/memorylogsink.h +++ b/doomsday/sdk/libcore/include/de/core/memorylogsink.h @@ -36,6 +36,8 @@ class DENG2_PUBLIC MemoryLogSink : public LogSink, public Lockable MemoryLogSink(LogEntry::Level minimumLevel = LogEntry::XVerbose); ~MemoryLogSink(); + void setPrivileged(bool onlyPrivileged); + LogSink &operator << (LogEntry const &entry); LogSink &operator << (String const &plainText); @@ -57,6 +59,7 @@ class DENG2_PUBLIC MemoryLogSink : public LogSink, public Lockable private: QList _entries; LogEntry::Level _minLevel; + bool _privileged; }; } // namespace de diff --git a/doomsday/sdk/libcore/src/core/logbuffer.cpp b/doomsday/sdk/libcore/src/core/logbuffer.cpp index 4d074d0065..abc2f369e4 100644 --- a/doomsday/sdk/libcore/src/core/logbuffer.cpp +++ b/doomsday/sdk/libcore/src/core/logbuffer.cpp @@ -194,6 +194,7 @@ bool LogBuffer::isEnabled(duint32 entryMetadata) const { DENG2_ASSERT(d->entryFilter != 0); DENG2_ASSERT(entryMetadata & LogEntry::DomainMask); // must have a domain + if(entryMetadata & LogEntry::Privileged) return true; // always passes return d->entryFilter->isLogEntryAllowed(entryMetadata); } diff --git a/doomsday/sdk/libcore/src/core/memorylogsink.cpp b/doomsday/sdk/libcore/src/core/memorylogsink.cpp index 559ee9b5e9..6942163cdc 100644 --- a/doomsday/sdk/libcore/src/core/memorylogsink.cpp +++ b/doomsday/sdk/libcore/src/core/memorylogsink.cpp @@ -20,7 +20,9 @@ namespace de { -MemoryLogSink::MemoryLogSink(LogEntry::Level minimumLevel) : _minLevel(minimumLevel) +MemoryLogSink::MemoryLogSink(LogEntry::Level minimumLevel) + : _minLevel(minimumLevel) + , _privileged(false) {} MemoryLogSink::~MemoryLogSink() @@ -30,6 +32,11 @@ MemoryLogSink::~MemoryLogSink() qDeleteAll(_entries); } +void MemoryLogSink::setPrivileged(bool onlyPrivileged) +{ + _privileged = onlyPrivileged; +} + void MemoryLogSink::clear() { DENG2_GUARD(this); @@ -40,6 +47,13 @@ void MemoryLogSink::clear() LogSink &MemoryLogSink::operator << (LogEntry const &entry) { + if((!_privileged && (entry.context() & LogEntry::Privileged)) || + (_privileged && !(entry.context() & LogEntry::Privileged))) + { + // Skip (non-)privileged entry. + return *this; + } + if(entry.level() >= _minLevel) { DENG2_GUARD(this);