From 3d44ab9939ffe6400806fcf89c5892204f6c8ab8 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Sun, 22 Dec 2013 15:06:40 +0100 Subject: [PATCH 01/11] Dialog layout --- interface/resources/styles/checked.svg | 14 +++ interface/resources/styles/log_dialog.qss | 46 ++++++++++ interface/resources/styles/search.svg | 12 +++ interface/resources/styles/txt-file.svg | 15 +++ interface/resources/styles/unchecked.svg | 11 +++ interface/src/LogDisplay.cpp | 7 +- interface/src/LogDisplay.h | 2 +- interface/src/ui/LogDialog.cpp | 107 +++++++++++++++++++--- interface/src/ui/LogDialog.h | 18 +++- 9 files changed, 213 insertions(+), 19 deletions(-) create mode 100644 interface/resources/styles/checked.svg create mode 100644 interface/resources/styles/search.svg create mode 100644 interface/resources/styles/txt-file.svg create mode 100644 interface/resources/styles/unchecked.svg diff --git a/interface/resources/styles/checked.svg b/interface/resources/styles/checked.svg new file mode 100644 index 0000000000..03cee0794e --- /dev/null +++ b/interface/resources/styles/checked.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index fe3675f682..ab74f07a33 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -1,7 +1,53 @@ + QPlainTextEdit { font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; font-size: 16px; padding-left: 28px; + padding-top: 7px; color: #333333; background-color: #FFFFFF; + border: none; +} + +QLineEdit { + padding-left: 7px; + background-color: #CCCCCC; + border-width: 0; + border-top-right-radius: 9px; + border-bottom-right-radius: 9px; + color: #333333; + font-size: 12px; +} + +QPushButton#searchButton { + background: url(resources/styles/search.svg); + background-repeat: none; + background-position: left center; + background-origin: content; + padding-left: 7px; + background-color: #CCCCCC; + border-width: 0; + border-top-left-radius: 9px; + border-bottom-left-radius: 9px; +} + +QPushButton#revealLogButton { + background: url(resources/styles/txt-file.svg); + background-repeat: none; + background-position: left center; + background-origin: content; + padding-left: 10px; + background-color: #333333; + color: #BBBBBB; + border-width: 0; + border-radius: 9px; + font-size: 11px; +} + +QCheckBox::indicator:unchecked { + image: url(resources/styles/unchecked.svg); +} + +QCheckBox::indicator:checked { + image: url(resources/styles/checked.svg); } diff --git a/interface/resources/styles/search.svg b/interface/resources/styles/search.svg new file mode 100644 index 0000000000..b4701e8649 --- /dev/null +++ b/interface/resources/styles/search.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/interface/resources/styles/txt-file.svg b/interface/resources/styles/txt-file.svg new file mode 100644 index 0000000000..1c25cc90a7 --- /dev/null +++ b/interface/resources/styles/txt-file.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/interface/resources/styles/unchecked.svg b/interface/resources/styles/unchecked.svg new file mode 100644 index 0000000000..14f07c6625 --- /dev/null +++ b/interface/resources/styles/unchecked.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/interface/src/LogDisplay.cpp b/interface/src/LogDisplay.cpp index dc365a9ea0..5713a9c0c5 100644 --- a/interface/src/LogDisplay.cpp +++ b/interface/src/LogDisplay.cpp @@ -156,13 +156,16 @@ void LogDisplay::addMessage(const char* ptr) { pthread_mutex_unlock(& _mutex); } -QStringList LogDisplay::getLogData() { +QStringList LogDisplay::getLogData(QString searchText) { // wait for adding new log data whilr iterating over _lines pthread_mutex_lock(& _mutex); QStringList list; int i = 0; while (_lines[i] != *_lastLinePos) { - list.append(_lines[i++]); + if (searchText.isEmpty() || QString(_lines[i]).contains(searchText, Qt::CaseInsensitive)) { + list.append(_lines[i]); + } + i++; } pthread_mutex_unlock(& _mutex); return list; diff --git a/interface/src/LogDisplay.h b/interface/src/LogDisplay.h index 285325b180..ea06c873f5 100644 --- a/interface/src/LogDisplay.h +++ b/interface/src/LogDisplay.h @@ -44,7 +44,7 @@ public: static unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered static unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message - QStringList getLogData(); + QStringList getLogData(QString); signals: void logReceived(QString message); diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 013c60d993..4d67e4ae00 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -14,7 +14,17 @@ #include "ui/LogDialog.h" #include "LogDisplay.h" -const int INITIAL_WIDTH = 720; +const int TOP_BAR_HEIGHT = 46; +const int INITIAL_WIDTH = 720; +const int MINIMAL_WIDTH = 570; +const int ELEMENT_MARGIN = 7; +const int ELEMENT_HEIGHT = 32; +const int SEARCH_BUTTON_LEFT = 25; +const int SEARCH_BUTTON_WIDTH = 20; +const int SEARCH_TEXT_WIDTH = 240; +const int CHECKBOX_MARGIN = 12; +const int CHECKBOX_WIDTH = 140; +const int REVEAL_BUTTON_WIDTH = 122; const float INITIAL_HEIGHT_RATIO = 0.6f; int cursorMeta = qRegisterMetaType("QTextCursor"); @@ -23,46 +33,85 @@ int blockMeta = qRegisterMetaType("QTextBlock"); LogDialog::LogDialog(QWidget* parent) : QDialog(parent, Qt::Dialog) { setWindowTitle("Log"); - - _logTextBox = new QPlainTextEdit(this); - _logTextBox->setReadOnly(true); - _logTextBox->show(); + setAttribute(Qt::WA_DeleteOnClose); switchToResourcesParentIfRequired(); QFile styleSheet("resources/styles/log_dialog.qss"); - if (styleSheet.open(QIODevice::ReadOnly)) { setStyleSheet(styleSheet.readAll()); } + initControls(); + QDesktopWidget desktop; QRect screen = desktop.screenGeometry(); resize(INITIAL_WIDTH, static_cast(screen.height() * INITIAL_HEIGHT_RATIO)); move(screen.center() - rect().center()); - - setAttribute(Qt::WA_DeleteOnClose); + setMinimumWidth(MINIMAL_WIDTH); } LogDialog::~LogDialog() { deleteLater(); } -void LogDialog::showEvent(QShowEvent *e) { - _logTextBox->clear(); +void LogDialog::initControls() { - pthread_mutex_lock(& _mutex); - QStringList _logData = LogDisplay::instance.getLogData(); + int left; + _searchButton = new QPushButton(this); + // set object name for css styling + _searchButton->setObjectName("searchButton"); + left = SEARCH_BUTTON_LEFT; + _searchButton->setGeometry(left, ELEMENT_MARGIN, SEARCH_BUTTON_WIDTH, ELEMENT_HEIGHT); + left += SEARCH_BUTTON_WIDTH; + _searchButton->show(); + connect(_searchButton, SIGNAL(clicked()), SLOT(handleSearchButton())); + + _searchTextBox = new QLineEdit(this); + // disable blue outline in Mac + _searchTextBox->setAttribute(Qt::WA_MacShowFocusRect, false); + _searchTextBox->setGeometry(left, ELEMENT_MARGIN, SEARCH_TEXT_WIDTH, ELEMENT_HEIGHT); + left += SEARCH_TEXT_WIDTH + CHECKBOX_MARGIN; + _searchTextBox->show(); + connect(_searchTextBox, SIGNAL(textChanged(QString)), SLOT(handleSeachTextChanged(QString))); + + _extraDebuggingBox = new QCheckBox("Extra debugging", this); + _extraDebuggingBox->setGeometry(left, ELEMENT_MARGIN, CHECKBOX_WIDTH, ELEMENT_HEIGHT); + _extraDebuggingBox->show(); + connect(_extraDebuggingBox, SIGNAL(stateChanged(int)), SLOT(handleExtraDebuggingCheckbox(int))); + + _revealLogButton = new QPushButton("Reveal log file", this); + // set object name for css styling + _revealLogButton->setObjectName("revealLogButton"); + _revealLogButton->show(); + connect(_revealLogButton, SIGNAL(clicked()), SLOT(handleRevealButton())); + + _logTextBox = new QPlainTextEdit(this); + _logTextBox->setReadOnly(true); + _logTextBox->show(); + +} + +void LogDialog::showEvent(QShowEvent *e) { + _searchTextBox->clear(); + _searchTextBox->setText(""); + +/* pthread_mutex_lock(& _mutex); + QStringList _logData = LogDisplay::instance.getLogData(""); connect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); for(int i = 0; i < _logData.size(); ++i) { appendLogLine(_logData[i]); } - pthread_mutex_unlock(& _mutex); + pthread_mutex_unlock(& _mutex);*/ } void LogDialog::resizeEvent(QResizeEvent *e) { - _logTextBox->resize(width(), height()); + _logTextBox->setGeometry(0, TOP_BAR_HEIGHT, width(), height() - TOP_BAR_HEIGHT); + _revealLogButton->setGeometry(width() - ELEMENT_MARGIN - REVEAL_BUTTON_WIDTH, + ELEMENT_MARGIN, + REVEAL_BUTTON_WIDTH, + ELEMENT_HEIGHT); } void LogDialog::appendLogLine(QString logLine) { @@ -73,3 +122,33 @@ void LogDialog::appendLogLine(QString logLine) { _logTextBox->ensureCursorVisible(); } } + +void LogDialog::handleSearchButton() { + _searchTextBox->setFocus(); +} + +void LogDialog::handleRevealButton() { + +} + +void LogDialog::handleExtraDebuggingCheckbox(int state) { + +} + +void LogDialog::handleSeachTextChanged(QString searchText) { + + if (searchText.isEmpty()) { + connect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); + } else { + disconnect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); + } + + _logTextBox->clear(); + pthread_mutex_lock(& _mutex); + QStringList _logData = LogDisplay::instance.getLogData(searchText); + for(int i = 0; i < _logData.size(); ++i) { + appendLogLine(_logData[i]); + } + + pthread_mutex_unlock(& _mutex); +} diff --git a/interface/src/ui/LogDialog.h b/interface/src/ui/LogDialog.h index 808ac4a485..741d4b1845 100644 --- a/interface/src/ui/LogDialog.h +++ b/interface/src/ui/LogDialog.h @@ -11,6 +11,9 @@ #include #include +#include +#include +#include class LogDialog : public QDialog { Q_OBJECT @@ -22,14 +25,25 @@ public: public slots: void appendLogLine(QString logLine); +private slots: + void handleSearchButton(); + void handleRevealButton(); + void handleExtraDebuggingCheckbox(const int); + void handleSeachTextChanged(QString); + protected: - void resizeEvent(QResizeEvent* e); - void showEvent(QShowEvent* e); + void resizeEvent(QResizeEvent*); + void showEvent(QShowEvent*); private: + QPushButton* _searchButton; + QLineEdit* _searchTextBox; + QCheckBox* _extraDebuggingBox; + QPushButton* _revealLogButton; QPlainTextEdit* _logTextBox; pthread_mutex_t _mutex; + void initControls(); }; #endif From ee1eb25dfab98734a4152c4321182ebbacf2c8dc Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Sun, 22 Dec 2013 18:56:53 +0100 Subject: [PATCH 02/11] replace LogDisplay with File logger - added abstract logger interface --- interface/resources/styles/log_dialog.qss | 10 ++--- interface/src/AbstractLoggerInterface.h | 33 +++++++++++++++ interface/src/Application.cpp | 17 ++++---- interface/src/Application.h | 6 ++- interface/src/FileLogger.cpp | 38 +++++++++++++++++ interface/src/FileLogger.h | 28 +++++++++++++ interface/src/Menu.cpp | 2 - interface/src/Menu.h | 1 - interface/src/VoxelHideShowThread.cpp | 6 +-- interface/src/VoxelPacketProcessor.cpp | 3 +- interface/src/VoxelSystem.cpp | 6 +-- interface/src/ui/LogDialog.cpp | 51 +++++++++-------------- interface/src/ui/LogDialog.h | 8 +++- 13 files changed, 150 insertions(+), 59 deletions(-) create mode 100644 interface/src/AbstractLoggerInterface.h create mode 100644 interface/src/FileLogger.cpp create mode 100644 interface/src/FileLogger.h diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index ab74f07a33..522ed9c9d6 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -12,9 +12,9 @@ QPlainTextEdit { QLineEdit { padding-left: 7px; background-color: #CCCCCC; - border-width: 0; - border-top-right-radius: 9px; - border-bottom-right-radius: 9px; + border-width: 0; + border-top-right-radius: 9px; + border-bottom-right-radius: 9px; color: #333333; font-size: 12px; } @@ -39,8 +39,8 @@ QPushButton#revealLogButton { padding-left: 10px; background-color: #333333; color: #BBBBBB; - border-width: 0; - border-radius: 9px; + border-width: 0; + border-radius: 9px; font-size: 11px; } diff --git a/interface/src/AbstractLoggerInterface.h b/interface/src/AbstractLoggerInterface.h new file mode 100644 index 0000000000..13e3aa0ffb --- /dev/null +++ b/interface/src/AbstractLoggerInterface.h @@ -0,0 +1,33 @@ +// +// AbstractLoggerInterface.h +// interface +// +// Created by Stojce Slavkovski on 12/22/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__AbstractLoggerInterface__ +#define __interface__AbstractLoggerInterface__ + +#include +#include +#include + +class AbstractLoggerInterface : public QObject { + Q_OBJECT + +public: + inline bool extraDebugging() { return _extraDebugging; }; + inline void setExtraDebugging(bool debugging) { _extraDebugging = debugging; }; + + virtual void addMessage(QString) = 0; + virtual QStringList getLogData(QString) = 0; + +signals: + void logReceived(QString message); + +private: + bool _extraDebugging = false; +}; + +#endif /* defined(__hifi__AbstractAudioInterface__) */ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 08ffa436dc..a90aaab223 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -88,7 +88,7 @@ const float MIRROR_REARVIEW_BODY_DISTANCE = 1.f; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { fprintf(stdout, "%s", message.toLocal8Bit().constData()); - LogDisplay::instance.addMessage(message.toLocal8Bit().constData()); + Application::getInstance()->getLogger()->addMessage(message.toLocal8Bit().constData()); } Application::Application(int& argc, char** argv, timeval &startup_time) : @@ -149,6 +149,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : QFontDatabase::addApplicationFont("resources/styles/Inconsolata.otf"); _window->setWindowTitle("Interface"); + _logger = new FileLogger(); + qInstallMessageHandler(messageHandler); // call Menu getInstance static method to set up the menu @@ -1346,7 +1348,7 @@ void Application::idle() { // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing // details normally. - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging); + bool showWarnings = getLogger()->extraDebugging(); PerformanceWarning warn(showWarnings, "Application::idle()"); timeval check; @@ -2665,7 +2667,7 @@ void Application::queryOctree(NODE_TYPE serverType, PACKET_TYPE packetType, Node return; } - bool wantExtraDebugging = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging); + bool wantExtraDebugging = getLogger()->extraDebugging(); // These will be the same for all servers, so we can set them up once and then reuse for each server we send to. _voxelQuery.setWantLowResMoving(!Menu::getInstance()->isOptionChecked(MenuOption::DisableLowRes)); @@ -3349,11 +3351,6 @@ void Application::displayOverlay() { if (Menu::getInstance()->isOptionChecked(MenuOption::CoverageMap)) { renderCoverageMap(); } - - - if (Menu::getInstance()->isOptionChecked(MenuOption::Log)) { - LogDisplay::instance.render(_glWidget->width(), _glWidget->height()); - } // Show chat entry field if (_chatEntryOn) { @@ -4356,7 +4353,7 @@ void* Application::networkReceive(void* args) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::networkReceive()... _voxelProcessor.queueReceivedPacket()"); - bool wantExtraDebugging = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging); + bool wantExtraDebugging = app->getLogger()->extraDebugging(); if (wantExtraDebugging && app->_incomingPacket[0] == PACKET_TYPE_VOXEL_DATA) { int numBytesPacketHeader = numBytesForPacketHeader(app->_incomingPacket); unsigned char* dataAt = app->_incomingPacket + numBytesPacketHeader; @@ -4481,7 +4478,7 @@ void Application::loadScript() { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(_glWidget); + _logDialog = new LogDialog(_glWidget, getLogger()); _logDialog->show(); } else { _logDialog->close(); diff --git a/interface/src/Application.h b/interface/src/Application.h index e917f6d63d..4be944e028 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -69,6 +69,7 @@ #include "ui/RearMirrorTools.h" #include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" +#include "FileLogger.h" #include "ParticleTreeRenderer.h" #include "ParticleEditHandle.h" #include "ControllerScriptingInterface.h" @@ -201,7 +202,8 @@ public: VoxelShader& getVoxelShader() { return _voxelShader; } PointShader& getPointShader() { return _pointShader; } - + FileLogger* getLogger() { return _logger; } + glm::vec2 getViewportDimensions() const{ return glm::vec2(_glWidget->width(),_glWidget->height()); } NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; } NodeToJurisdictionMap& getParticleServerJurisdictions() { return _particleServerJurisdictions; } @@ -509,6 +511,8 @@ private: std::vector _avatarFades; ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; + + FileLogger* _logger; }; #endif /* defined(__interface__Application__) */ diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp new file mode 100644 index 0000000000..4fb9dc64d8 --- /dev/null +++ b/interface/src/FileLogger.cpp @@ -0,0 +1,38 @@ +// +// FileLogger.cpp +// hifi +// +// Created by Stojce Slavkovski on 12/22/13. +// +// + +#include "FileLogger.h" + +FileLogger::FileLogger() : _lines(NULL) { + setExtraDebugging(false); +} + +QStringList FileLogger::getLogData(QString searchText) { + + if (searchText.isEmpty()) { + return _lines; + } + + // wait for adding new log data while iterating over _lines +// pthread_mutex_lock(& _mutex); + QStringList filteredList; + for (int i = 0; i < _lines.size(); ++i) { + if (_lines[i].contains(searchText, Qt::CaseInsensitive)) { + filteredList.append(_lines[i]); + } + } +// pthread_mutex_unlock(& _mutex); + return filteredList; +} + +void FileLogger::addMessage(QString message) { + emit logReceived(message); + _lines.append(message); + + // TODO: append message to file +} \ No newline at end of file diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h new file mode 100644 index 0000000000..ba44c40005 --- /dev/null +++ b/interface/src/FileLogger.h @@ -0,0 +1,28 @@ +// +// FileLogger.h +// hifi +// +// Created by Stojce Slavkovski on 12/22/13. +// +// + +#ifndef hifi_FileLogger_h +#define hifi_FileLogger_h + +#include "AbstractLoggerInterface.h" + +class FileLogger : public AbstractLoggerInterface { + Q_OBJECT + +public: + FileLogger(); + + virtual void addMessage(QString); + virtual QStringList getLogData(QString); + +private: + QStringList _lines; + +}; + +#endif diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 98b807fea2..40f0c4b415 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -497,8 +497,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio); - - addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::ExtraDebugging); addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, Qt::CTRL | Qt::SHIFT | Qt::Key_V, this, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 73bb0472b4..ac33fc2d0e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -183,7 +183,6 @@ namespace MenuOption { const QString EchoServerAudio = "Echo Server Audio"; const QString EchoLocalAudio = "Echo Local Audio"; const QString ExportVoxels = "Export Voxels"; - const QString ExtraDebugging = "Extra Debugging"; const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes"; const QString HeadMouse = "Head Mouse"; const QString FaceMode = "Cycle Face Mode"; diff --git a/interface/src/VoxelHideShowThread.cpp b/interface/src/VoxelHideShowThread.cpp index bb64dd5b08..eba4e36a86 100644 --- a/interface/src/VoxelHideShowThread.cpp +++ b/interface/src/VoxelHideShowThread.cpp @@ -13,7 +13,7 @@ #include #include -#include "Menu.h" +#include "Application.h" #include "VoxelHideShowThread.h" VoxelHideShowThread::VoxelHideShowThread(VoxelSystem* theSystem) : @@ -30,8 +30,8 @@ bool VoxelHideShowThread::process() { _theSystem->checkForCulling(); uint64_t end = usecTimestampNow(); uint64_t elapsed = end - start; - - bool showExtraDebugging = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging); + + bool showExtraDebugging = Application::getInstance()->getLogger()->extraDebugging(); if (showExtraDebugging && elapsed > USECS_PER_FRAME) { printf("VoxelHideShowThread::process()... checkForCulling took %llu\n", elapsed); } diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index 2b78ff73d6..6e5d4ca85c 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -19,7 +19,8 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, uns "VoxelPacketProcessor::processPacket()"); const int WAY_BEHIND = 300; - if (packetsToProcessCount() > WAY_BEHIND && Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)) { + + if (packetsToProcessCount() > WAY_BEHIND && Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelPacketProcessor::processPacket() packets to process=%d\n", packetsToProcessCount()); } ssize_t messageLength = packetLength; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index f5a2a99ffb..d7c10215f8 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -612,7 +612,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { lockTree(); VoxelPacketData packetData(packetIsCompressed); packetData.loadFinalizedContent(dataAt, sectionLength); - if (Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)) { + if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelSystem::parseData() ... Got Packet Section" " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" " subsection:%d sectionLength:%d uncompressed:%d\n", @@ -973,7 +973,7 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo // not render these Voxels. We need to think about ways to keep the entire scene intact but maybe lower quality // possibly shifting down to lower LOD or something. This debug message is to help identify, if/when/how this // state actually occurs. - if (Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)) { + if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("OHHHH NOOOOOO!!!! updateNodeInArrays() BAILING (_voxelsInWriteArrays >= _maxVoxels)\n"); } return 0; @@ -1964,7 +1964,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY); } - bool extraDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging); + bool extraDebugDetails = Application::getInstance()->getLogger()->extraDebugging(); if (extraDebugDetails) { qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n", args.nodesScanned, args.nodesRemoved, args.nodesInside, diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 4d67e4ae00..4f211c5edc 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -12,7 +12,6 @@ #include "SharedUtil.h" #include "ui/LogDialog.h" -#include "LogDisplay.h" const int TOP_BAR_HEIGHT = 46; const int INITIAL_WIDTH = 720; @@ -27,11 +26,12 @@ const int CHECKBOX_WIDTH = 140; const int REVEAL_BUTTON_WIDTH = 122; const float INITIAL_HEIGHT_RATIO = 0.6f; -int cursorMeta = qRegisterMetaType("QTextCursor"); -int blockMeta = qRegisterMetaType("QTextBlock"); +int qTextCursorMeta = qRegisterMetaType("QTextCursor"); +int qTextBlockMeta = qRegisterMetaType("QTextBlock"); -LogDialog::LogDialog(QWidget* parent) : QDialog(parent, Qt::Dialog) { +LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : QDialog(parent, Qt::Dialog) { + _logger = logger; setWindowTitle("Log"); setAttribute(Qt::WA_DeleteOnClose); @@ -72,10 +72,13 @@ void LogDialog::initControls() { _searchTextBox->setGeometry(left, ELEMENT_MARGIN, SEARCH_TEXT_WIDTH, ELEMENT_HEIGHT); left += SEARCH_TEXT_WIDTH + CHECKBOX_MARGIN; _searchTextBox->show(); - connect(_searchTextBox, SIGNAL(textChanged(QString)), SLOT(handleSeachTextChanged(QString))); + connect(_searchTextBox, SIGNAL(textChanged(QString)), SLOT(handleSearchTextChanged(QString))); _extraDebuggingBox = new QCheckBox("Extra debugging", this); _extraDebuggingBox->setGeometry(left, ELEMENT_MARGIN, CHECKBOX_WIDTH, ELEMENT_HEIGHT); + if (_logger->extraDebugging()) { + _extraDebuggingBox->setCheckState(Qt::Checked); + } _extraDebuggingBox->show(); connect(_extraDebuggingBox, SIGNAL(stateChanged(int)), SLOT(handleExtraDebuggingCheckbox(int))); @@ -91,22 +94,12 @@ void LogDialog::initControls() { } -void LogDialog::showEvent(QShowEvent *e) { - _searchTextBox->clear(); - _searchTextBox->setText(""); - -/* pthread_mutex_lock(& _mutex); - QStringList _logData = LogDisplay::instance.getLogData(""); - - connect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); - for(int i = 0; i < _logData.size(); ++i) { - appendLogLine(_logData[i]); - } - - pthread_mutex_unlock(& _mutex);*/ +void LogDialog::showEvent(QShowEvent*) { + connect(_logger, SIGNAL(logReceived(QString)), this, SLOT(appendLogLine(QString))); + handleSearchTextChanged(""); } -void LogDialog::resizeEvent(QResizeEvent *e) { +void LogDialog::resizeEvent(QResizeEvent*) { _logTextBox->setGeometry(0, TOP_BAR_HEIGHT, width(), height() - TOP_BAR_HEIGHT); _revealLogButton->setGeometry(width() - ELEMENT_MARGIN - REVEAL_BUTTON_WIDTH, ELEMENT_MARGIN, @@ -117,7 +110,9 @@ void LogDialog::resizeEvent(QResizeEvent *e) { void LogDialog::appendLogLine(QString logLine) { if (isVisible()) { pthread_mutex_lock(& _mutex); - _logTextBox->appendPlainText(logLine.simplified()); + + QString line = logLine.replace(QRegExp("node"), "node"); + _logTextBox->appendHtml(line); pthread_mutex_unlock(& _mutex); _logTextBox->ensureCursorVisible(); } @@ -131,22 +126,16 @@ void LogDialog::handleRevealButton() { } -void LogDialog::handleExtraDebuggingCheckbox(int state) { - +void LogDialog::handleExtraDebuggingCheckbox(const int state) { + _logger->setExtraDebugging(state != 0); } -void LogDialog::handleSeachTextChanged(QString searchText) { - - if (searchText.isEmpty()) { - connect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); - } else { - disconnect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine); - } +void LogDialog::handleSearchTextChanged(const QString searchText) { _logTextBox->clear(); pthread_mutex_lock(& _mutex); - QStringList _logData = LogDisplay::instance.getLogData(searchText); - for(int i = 0; i < _logData.size(); ++i) { + QStringList _logData = _logger->getLogData(searchText); + for (int i = 0; i < _logData.size(); ++i) { appendLogLine(_logData[i]); } diff --git a/interface/src/ui/LogDialog.h b/interface/src/ui/LogDialog.h index 741d4b1845..ef3d125cb7 100644 --- a/interface/src/ui/LogDialog.h +++ b/interface/src/ui/LogDialog.h @@ -15,11 +15,13 @@ #include #include +#include "AbstractLoggerInterface.h" + class LogDialog : public QDialog { Q_OBJECT public: - LogDialog(QWidget* parent); + LogDialog(QWidget*, AbstractLoggerInterface*); ~LogDialog(); public slots: @@ -29,7 +31,7 @@ private slots: void handleSearchButton(); void handleRevealButton(); void handleExtraDebuggingCheckbox(const int); - void handleSeachTextChanged(QString); + void handleSearchTextChanged(const QString); protected: void resizeEvent(QResizeEvent*); @@ -43,6 +45,8 @@ private: QPlainTextEdit* _logTextBox; pthread_mutex_t _mutex; + AbstractLoggerInterface* _logger; + void initControls(); }; From 505ed5bc64f266b899ad9667675720171adfc017 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Sun, 22 Dec 2013 23:55:21 +0100 Subject: [PATCH 03/11] Storing log to file - initial --- interface/src/FileLogger.cpp | 20 ++++++++++++++++---- interface/src/FileLogger.h | 2 ++ interface/src/ui/LogDialog.cpp | 4 +--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 4fb9dc64d8..b9dadb4a8c 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -7,32 +7,44 @@ // #include "FileLogger.h" +#include "HifiSockAddr.h" +#include +#include FileLogger::FileLogger() : _lines(NULL) { + QHostAddress clientAddress = QHostAddress(getHostOrderLocalAddress()); + QDateTime now = QDateTime::currentDateTime(); + _fileName = QString("hifi-log_%1_%2.txt").arg(clientAddress.toString(), now.toString("yyyy-MM-dd_hh.mm.ss")); setExtraDebugging(false); } QStringList FileLogger::getLogData(QString searchText) { - if (searchText.isEmpty()) { return _lines; } // wait for adding new log data while iterating over _lines -// pthread_mutex_lock(& _mutex); + _mutex.lock(); QStringList filteredList; for (int i = 0; i < _lines.size(); ++i) { if (_lines[i].contains(searchText, Qt::CaseInsensitive)) { filteredList.append(_lines[i]); } } -// pthread_mutex_unlock(& _mutex); + _mutex.unlock(); return filteredList; } void FileLogger::addMessage(QString message) { + _mutex.lock(); emit logReceived(message); _lines.append(message); - // TODO: append message to file + QFile file(_fileName); + + if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + QTextStream out(&file); + out << message; + } + _mutex.unlock(); } \ No newline at end of file diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index ba44c40005..848bcd44d3 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -22,6 +22,8 @@ public: private: QStringList _lines; + QString _fileName; + QMutex _mutex; }; diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 4f211c5edc..ed1584aad6 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -110,9 +110,7 @@ void LogDialog::resizeEvent(QResizeEvent*) { void LogDialog::appendLogLine(QString logLine) { if (isVisible()) { pthread_mutex_lock(& _mutex); - - QString line = logLine.replace(QRegExp("node"), "node"); - _logTextBox->appendHtml(line); + _logTextBox->appendHtml(logLine.simplified()); pthread_mutex_unlock(& _mutex); _logTextBox->ensureCursorVisible(); } From 840d1a33ef67510fcca6d385c81883b233d039f2 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Mon, 23 Dec 2013 21:23:47 +0100 Subject: [PATCH 04/11] Reveal log file - change log location lo application data folder - reveal file in Finder (Explorer) implementation --- interface/src/AbstractLoggerInterface.h | 3 +- interface/src/Application.cpp | 8 ++-- interface/src/FileLogger.cpp | 19 +++++++-- interface/src/FileLogger.h | 1 + interface/src/ui/LogDialog.cpp | 2 +- libraries/shared/src/FileUtils.cpp | 56 +++++++++++++++++++++++++ libraries/shared/src/FileUtils.h | 21 ++++++++++ 7 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 libraries/shared/src/FileUtils.cpp create mode 100644 libraries/shared/src/FileUtils.h diff --git a/interface/src/AbstractLoggerInterface.h b/interface/src/AbstractLoggerInterface.h index 13e3aa0ffb..d53ada6cca 100644 --- a/interface/src/AbstractLoggerInterface.h +++ b/interface/src/AbstractLoggerInterface.h @@ -22,6 +22,7 @@ public: virtual void addMessage(QString) = 0; virtual QStringList getLogData(QString) = 0; + virtual void locateLog() = 0; signals: void logReceived(QString message); @@ -30,4 +31,4 @@ private: bool _extraDebugging = false; }; -#endif /* defined(__hifi__AbstractAudioInterface__) */ +#endif /* defined(__interface__AbstractLoggerInterface__) */ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a90aaab223..442b5f27a1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -141,7 +141,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _recentMaxPackets(0), _resetRecentMaxPacketsSoon(true), _swatch(NULL), - _pasteMode(false) + _pasteMode(false), + _logger(new FileLogger()) { _applicationStartupTime = startup_time; @@ -149,8 +150,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : QFontDatabase::addApplicationFont("resources/styles/Inconsolata.otf"); _window->setWindowTitle("Interface"); - _logger = new FileLogger(); - qInstallMessageHandler(messageHandler); // call Menu getInstance static method to set up the menu @@ -269,7 +268,8 @@ Application::~Application() { VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown Menu::getInstance()->deleteLater(); - + + delete _logger; delete _settings; delete _followMode; delete _glWidget; diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index b9dadb4a8c..5f652ec0f2 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -8,13 +8,23 @@ #include "FileLogger.h" #include "HifiSockAddr.h" +#include #include #include +#include +#include FileLogger::FileLogger() : _lines(NULL) { QHostAddress clientAddress = QHostAddress(getHostOrderLocalAddress()); QDateTime now = QDateTime::currentDateTime(); - _fileName = QString("hifi-log_%1_%2.txt").arg(clientAddress.toString(), now.toString("yyyy-MM-dd_hh.mm.ss")); + + _fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + QDir logDir(_fileName); + if (!logDir.exists(_fileName)) { + logDir.mkdir(_fileName); + } + + _fileName.append(QString("/hifi-log_%1_%2.txt").arg(clientAddress.toString(), now.toString("yyyy-MM-dd_hh.mm.ss"))); setExtraDebugging(false); } @@ -41,10 +51,13 @@ void FileLogger::addMessage(QString message) { _lines.append(message); QFile file(_fileName); - if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream out(&file); out << message; } _mutex.unlock(); -} \ No newline at end of file +} + +void FileLogger::locateLog() { + FileUtils::LocateFile(_fileName); +} diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index 848bcd44d3..fffbc5fa91 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -19,6 +19,7 @@ public: virtual void addMessage(QString); virtual QStringList getLogData(QString); + virtual void locateLog(); private: QStringList _lines; diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index ed1584aad6..5d6a404c76 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -121,7 +121,7 @@ void LogDialog::handleSearchButton() { } void LogDialog::handleRevealButton() { - + _logger->locateLog(); } void LogDialog::handleExtraDebuggingCheckbox(const int state) { diff --git a/libraries/shared/src/FileUtils.cpp b/libraries/shared/src/FileUtils.cpp new file mode 100644 index 0000000000..b58799104f --- /dev/null +++ b/libraries/shared/src/FileUtils.cpp @@ -0,0 +1,56 @@ +// +// FileUtils.cpp +// hifi +// +// Created by Stojce Slavkovski on 12/23/13. +// +// + +#include "FileUtils.h" +#include +#include + +void FileUtils::LocateFile(QString filePath) { + + // adopted from + // http://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt + // and + // http://lynxline.com/show-in-finder-show-in-explorer/ + + QFileInfo fileInfo(filePath); + if (!fileInfo.exists()) { + return; + } + + bool success = false; +#ifdef Q_OS_MAC + QStringList args; + args << "-e"; + args << "tell application \"Finder\""; + args << "-e"; + args << "activate"; + args << "-e"; + args << "select POSIX file \"" + fileInfo.absoluteFilePath().toUtf8() + "\""; + args << "-e"; + args << "end tell"; + success = QProcess::startDetached("osascript", args); +#endif + +#ifdef Q_OS_WIN + + QStringList args; + // don't send `select` command switch if `filePath` is folder + if (!fileInfo.isDir()) { + args << "/select,"; + } + args += QDir::toNativeSeparators(fileInfo.absoluteFilePath().toUtf8()); + success = QProcess::startDetached("explorer", args); + +#endif + + // fallback, open enclosing folder + if (!success) { + const QString folder = fileInfo.path(); + QDesktopServices::openUrl(QUrl::fromLocalFile(folder)); + } +} diff --git a/libraries/shared/src/FileUtils.h b/libraries/shared/src/FileUtils.h new file mode 100644 index 0000000000..a725e72ca1 --- /dev/null +++ b/libraries/shared/src/FileUtils.h @@ -0,0 +1,21 @@ +// +// FileUtils.h +// hifi +// +// Created by Stojce Slavkovski on 12/23/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef hifi_FileUtils_h +#define hifi_FileUtils_h + +#include + +class FileUtils { + +public: + static void LocateFile(QString); + +}; + +#endif From e0255721daee656c8f8434a8cc142ac8b34eafc6 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Tue, 24 Dec 2013 22:15:19 +0100 Subject: [PATCH 05/11] Search keyword highlighter --- interface/src/AbstractLoggerInterface.h | 2 +- interface/src/FileLogger.cpp | 27 +++----------------- interface/src/FileLogger.h | 4 +-- interface/src/ui/LogDialog.cpp | 34 ++++++++++++++++++++++--- interface/src/ui/LogDialog.h | 19 ++++++++++++++ 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/interface/src/AbstractLoggerInterface.h b/interface/src/AbstractLoggerInterface.h index d53ada6cca..36c0b73771 100644 --- a/interface/src/AbstractLoggerInterface.h +++ b/interface/src/AbstractLoggerInterface.h @@ -21,7 +21,7 @@ public: inline void setExtraDebugging(bool debugging) { _extraDebugging = debugging; }; virtual void addMessage(QString) = 0; - virtual QStringList getLogData(QString) = 0; + virtual QStringList getLogData() = 0; virtual void locateLog() = 0; signals: diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 5f652ec0f2..d1ef1bf83b 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -14,41 +14,22 @@ #include #include -FileLogger::FileLogger() : _lines(NULL) { - QHostAddress clientAddress = QHostAddress(getHostOrderLocalAddress()); - QDateTime now = QDateTime::currentDateTime(); - +FileLogger::FileLogger() : _logData(NULL) { _fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QDir logDir(_fileName); if (!logDir.exists(_fileName)) { logDir.mkdir(_fileName); } + QHostAddress clientAddress = QHostAddress(getHostOrderLocalAddress()); + QDateTime now = QDateTime::currentDateTime(); _fileName.append(QString("/hifi-log_%1_%2.txt").arg(clientAddress.toString(), now.toString("yyyy-MM-dd_hh.mm.ss"))); - setExtraDebugging(false); -} - -QStringList FileLogger::getLogData(QString searchText) { - if (searchText.isEmpty()) { - return _lines; - } - - // wait for adding new log data while iterating over _lines - _mutex.lock(); - QStringList filteredList; - for (int i = 0; i < _lines.size(); ++i) { - if (_lines[i].contains(searchText, Qt::CaseInsensitive)) { - filteredList.append(_lines[i]); - } - } - _mutex.unlock(); - return filteredList; } void FileLogger::addMessage(QString message) { _mutex.lock(); emit logReceived(message); - _lines.append(message); + _logData.append(message); QFile file(_fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index fffbc5fa91..e0cd0c5d5e 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -18,11 +18,11 @@ public: FileLogger(); virtual void addMessage(QString); - virtual QStringList getLogData(QString); + virtual QStringList getLogData() { return _logData; }; virtual void locateLog(); private: - QStringList _lines; + QStringList _logData; QString _fileName; QMutex _mutex; diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 5d6a404c76..4b5ee7f80a 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -25,6 +25,7 @@ const int CHECKBOX_MARGIN = 12; const int CHECKBOX_WIDTH = 140; const int REVEAL_BUTTON_WIDTH = 122; const float INITIAL_HEIGHT_RATIO = 0.6f; +const QString HIGHLIGHT_COLOR = "#3366CC"; int qTextCursorMeta = qRegisterMetaType("QTextCursor"); int qTextBlockMeta = qRegisterMetaType("QTextBlock"); @@ -91,12 +92,13 @@ void LogDialog::initControls() { _logTextBox = new QPlainTextEdit(this); _logTextBox->setReadOnly(true); _logTextBox->show(); + _highlighter = new KeywordHighlighter(_logTextBox->document()); } void LogDialog::showEvent(QShowEvent*) { connect(_logger, SIGNAL(logReceived(QString)), this, SLOT(appendLogLine(QString))); - handleSearchTextChanged(""); + showLogData(); } void LogDialog::resizeEvent(QResizeEvent*) { @@ -110,7 +112,9 @@ void LogDialog::resizeEvent(QResizeEvent*) { void LogDialog::appendLogLine(QString logLine) { if (isVisible()) { pthread_mutex_lock(& _mutex); - _logTextBox->appendHtml(logLine.simplified()); + if (logLine.contains(_searchTerm, Qt::CaseInsensitive)) { + _logTextBox->appendPlainText(logLine.simplified()); + } pthread_mutex_unlock(& _mutex); _logTextBox->ensureCursorVisible(); } @@ -129,13 +133,37 @@ void LogDialog::handleExtraDebuggingCheckbox(const int state) { } void LogDialog::handleSearchTextChanged(const QString searchText) { + _searchTerm = searchText; + _highlighter->keyword = searchText; + showLogData(); +} +void LogDialog::showLogData() { _logTextBox->clear(); pthread_mutex_lock(& _mutex); - QStringList _logData = _logger->getLogData(searchText); + QStringList _logData = _logger->getLogData(); for (int i = 0; i < _logData.size(); ++i) { appendLogLine(_logData[i]); } pthread_mutex_unlock(& _mutex); } + +KeywordHighlighter::KeywordHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent), keywordFormat() { + keywordFormat.setForeground(QColor(HIGHLIGHT_COLOR)); +} + +void KeywordHighlighter::highlightBlock(const QString &text) { + + if (keyword.isNull() || keyword.isEmpty()) { + return; + } + + int index = text.indexOf(keyword, 0, Qt::CaseInsensitive); + int length = keyword.length(); + + while (index >= 0) { + setFormat(index, length, keywordFormat); + index = text.indexOf(keyword, index + length, Qt::CaseInsensitive); + } +} diff --git a/interface/src/ui/LogDialog.h b/interface/src/ui/LogDialog.h index ef3d125cb7..9a0481546e 100644 --- a/interface/src/ui/LogDialog.h +++ b/interface/src/ui/LogDialog.h @@ -14,9 +14,25 @@ #include #include #include +#include #include "AbstractLoggerInterface.h" +class KeywordHighlighter : public QSyntaxHighlighter { + Q_OBJECT + +public: + KeywordHighlighter(QTextDocument *parent = 0); + QString keyword; + +protected: + void highlightBlock(const QString &text); + +private: + QTextCharFormat keywordFormat; + +}; + class LogDialog : public QDialog { Q_OBJECT @@ -44,10 +60,13 @@ private: QPushButton* _revealLogButton; QPlainTextEdit* _logTextBox; pthread_mutex_t _mutex; + QString _searchTerm; + KeywordHighlighter* _highlighter; AbstractLoggerInterface* _logger; void initControls(); + void showLogData(); }; #endif From 2b92194d356a2249de6d50887481f7a83fd4dbf6 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Sun, 29 Dec 2013 23:45:24 +0100 Subject: [PATCH 06/11] sytle changes on log dialog --- interface/resources/styles/log_dialog.qss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index 522ed9c9d6..00f90ca5ed 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -10,6 +10,7 @@ QPlainTextEdit { } QLineEdit { + font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; padding-left: 7px; background-color: #CCCCCC; border-width: 0; @@ -44,6 +45,10 @@ QPushButton#revealLogButton { font-size: 11px; } +QCheckBox { + font-family: Helvetica, Arial, sans-serif; +} + QCheckBox::indicator:unchecked { image: url(resources/styles/unchecked.svg); } From cd4fcb993f8978e5a1f8bf193a529a94bdbea78d Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Sun, 29 Dec 2013 23:52:26 +0100 Subject: [PATCH 07/11] removed unused 'LogDisplay' class --- interface/src/Application.cpp | 1 - interface/src/LogDisplay.cpp | 294 ---------------------------------- interface/src/LogDisplay.h | 82 ---------- 3 files changed, 377 deletions(-) delete mode 100644 interface/src/LogDisplay.cpp delete mode 100644 interface/src/LogDisplay.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 442b5f27a1..2c7289a64d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -51,7 +51,6 @@ #include "Application.h" #include "DataServerClient.h" #include "InterfaceVersion.h" -#include "LogDisplay.h" #include "Menu.h" #include "Swatch.h" #include "Util.h" diff --git a/interface/src/LogDisplay.cpp b/interface/src/LogDisplay.cpp deleted file mode 100644 index 5713a9c0c5..0000000000 --- a/interface/src/LogDisplay.cpp +++ /dev/null @@ -1,294 +0,0 @@ -// -// LogDisplay.cpp -// interface -// -// Created by Tobias Schwinger on 4/14/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#include -#include -#include - -#include - -#include "LogDisplay.h" -#include "Util.h" - -using namespace std; -FILE* const LogDisplay::DEFAULT_STREAM = 0l; - -// -// Singleton constructor -// -LogDisplay LogDisplay::instance; - -// -// State management -// - -LogDisplay::LogDisplay() : - _textRenderer(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT), - _stream(DEFAULT_STREAM), - _chars(0l), - _lines(0l), - _logWidth(DEFAULT_CONSOLE_WIDTH) { - - pthread_mutex_init(& _mutex, 0l); - - // allocate twice as much (so we have spare space for a copy not to block - // logging from other threads during 'render') - _chars = new char[CHARACTER_BUFFER_SIZE * 2]; - _charsEnd = _chars + CHARACTER_BUFFER_SIZE; - _lines = new char*[LINE_BUFFER_SIZE * 2]; - _linesEnd = _lines + LINE_BUFFER_SIZE; - - // initialize the log to all empty lines - _chars[0] = '\0'; - _writePos = _chars; - _writeLineStartPos = _chars; - _lastLinePos = _lines; - _writtenInLine = 0; - memset(_lines, 0, LINE_BUFFER_SIZE * sizeof(char*)); - - setCharacterSize(DEFAULT_CHAR_WIDTH, DEFAULT_CHAR_HEIGHT); -} - - -LogDisplay::~LogDisplay() { - - delete[] _chars; - delete[] _lines; -} - -void LogDisplay::setStream(FILE* stream) { - - pthread_mutex_lock(& _mutex); - _stream = stream; - pthread_mutex_unlock(& _mutex); -} - -void LogDisplay::setLogWidth(unsigned pixels) { - - pthread_mutex_lock(& _mutex); - _logWidth = pixels; - _lineLength = _logWidth / _charWidth; - pthread_mutex_unlock(& _mutex); -} - -void LogDisplay::setCharacterSize(unsigned width, unsigned height) { - - pthread_mutex_lock(& _mutex); - _charWidth = width; - _charHeight = height; - _lineLength = _logWidth / _charWidth; - pthread_mutex_unlock(& _mutex); -} - -// -// Logging -// - -void LogDisplay::addMessage(const char* ptr) { - - pthread_mutex_lock(& _mutex); - emit logReceived(ptr); - - // T-pipe, if requested - if (_stream != 0l) { - fprintf(_stream, "%s", ptr); - } - - while (*ptr != '\0') { - // process the characters - char c = *ptr++; - - if (c == '\t') { - - // found TAB -> write SPACE - c = ' '; - - } else if (c == '\n') { - - // found LF -> write NUL (c == '\0' tells us to wrap, below) - c = '\0'; - } - *_writePos++ = c; - - if (_writePos == _charsEnd) { - // reached the end of the circular character buffer? -> start over - _writePos = _chars; - } - - if (c == '\0') { - - // new line? store its start to the line buffer and mark next line as empty - ++_lastLinePos; - - if (_lastLinePos == _linesEnd) { - _lastLinePos = _lines; - _lastLinePos[1] = 0l; - } else if (_lastLinePos + 1 != _linesEnd) { - _lastLinePos[1] = 0l; - } else { - _lines[0] = 0l; - } - *_lastLinePos = _writeLineStartPos; - - // debug mode: make sure all line pointers we write here are valid - assert(! (_lastLinePos < _lines || _lastLinePos >= _linesEnd)); - assert(! (*_lastLinePos < _chars || *_lastLinePos >= _charsEnd)); - - // terminate line, unless done already - if (c != '\0') { - *_writePos++ = '\0'; - - if (_writePos == _charsEnd) { - _writePos = _chars; - } - } - - // remember start position in character buffer for next line and reset character count - _writeLineStartPos = _writePos; - } - } - - pthread_mutex_unlock(& _mutex); -} - -QStringList LogDisplay::getLogData(QString searchText) { - // wait for adding new log data whilr iterating over _lines - pthread_mutex_lock(& _mutex); - QStringList list; - int i = 0; - while (_lines[i] != *_lastLinePos) { - if (searchText.isEmpty() || QString(_lines[i]).contains(searchText, Qt::CaseInsensitive)) { - list.append(_lines[i]); - } - i++; - } - pthread_mutex_unlock(& _mutex); - return list; -} - -// -// Rendering -// - -void LogDisplay::render(unsigned screenWidth, unsigned screenHeight) { - - // rendering might take some time, so create a local copy of the portion we need - // instead of having to hold the mutex all the time - pthread_mutex_lock(& _mutex); - - // determine number of visible lines (integer division rounded up) - unsigned showLines = (screenHeight + _charHeight - 1) / _charHeight; - - char** lastLine = _lastLinePos; - char** firstLine = _lastLinePos; - - if (! *lastLine) { - // empty log - pthread_mutex_unlock(& _mutex); - return; - } - - // scan for first line - for (int n = 2; n <= showLines; ++n) { - - char** prevFirstLine = firstLine; - --firstLine; - if (firstLine < _lines) { - firstLine = _linesEnd - 1; - } - if (! *firstLine) { - firstLine = prevFirstLine; - showLines = n - 1; - break; - } - - // debug mode: make sure all line pointers we find here are valid - assert(! (firstLine < _lines || firstLine >= _linesEnd)); - assert(! (*firstLine < _chars || *firstLine >= _charsEnd)); - } - - // copy the line buffer portion into a contiguous region at _linesEnd - if (firstLine <= lastLine) { - - memcpy(_linesEnd, firstLine, showLines * sizeof(char*)); - - } else { - - unsigned atEnd = _linesEnd - firstLine; - memcpy(_linesEnd, firstLine, atEnd * sizeof(char*)); - memcpy(_linesEnd + atEnd, _lines, (showLines - atEnd) * sizeof(char*)); - } - - // copy relevant char buffer portion and determine information to remap the pointers - char* firstChar = *firstLine; - char* lastChar = *lastLine + strlen(*lastLine) + 1; - ptrdiff_t charOffset = _charsEnd - firstChar, charOffsetBeforeFirst = 0; - if (firstChar <= lastChar) { - - memcpy(_charsEnd, firstChar, lastChar - firstChar + 1); - - } else { - - unsigned atEnd = _charsEnd - firstChar; - memcpy(_charsEnd, firstChar, atEnd); - memcpy(_charsEnd + atEnd, _chars, lastChar + 1 - _chars); - - charOffsetBeforeFirst = _charsEnd + atEnd - _chars; - } - - // determine geometry information from font metrics - QFontMetrics const& fontMetrics = _textRenderer.metrics(); - int yStep = fontMetrics.lineSpacing(); - // scale - float xScale = float(_charWidth) / fontMetrics.width('*'); - float yScale = float(_charHeight) / yStep; - // scaled translation - int xStart = int((screenWidth - _logWidth) / xScale); - int yStart = screenHeight / yScale - fontMetrics.descent(); - - // first line to render - char** line = _linesEnd + showLines; - - // ok, now the lock can be released - we have all we need - // and won't hold it while talking to OpenGL - pthread_mutex_unlock(& _mutex); - - glPushMatrix(); - glScalef(xScale, yScale, 1.0f); - glColor3ub(GLubyte(TEXT_COLOR >> 16), - GLubyte((TEXT_COLOR >> 8) & 0xff), - GLubyte(TEXT_COLOR & 0xff)); - for (int y = yStart; y > 0; y -= yStep) { - - // debug mode: check line pointer is valid - assert(! (line < _linesEnd || line >= _linesEnd + (_linesEnd - _lines))); - - // get character pointer - if (--line < _linesEnd) { - break; - } - char* chars = *line; - - // debug mode: check char pointer we find is valid - assert(! (chars < _chars || chars >= _charsEnd)); - - // remap character pointer it to copied buffer - chars += chars >= firstChar ? charOffset : charOffsetBeforeFirst; - - // debug mode: check char pointer is still valid (in new range) - assert(! (chars < _charsEnd || chars >= _charsEnd + (_charsEnd - _chars))); - - // render the string - _textRenderer.draw(xStart, y, chars); - -//fprintf(stderr, "LogDisplay::render, message = \"%s\"\n", chars); - } - glPopMatrix(); -} - - diff --git a/interface/src/LogDisplay.h b/interface/src/LogDisplay.h deleted file mode 100644 index ea06c873f5..0000000000 --- a/interface/src/LogDisplay.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// LogDisplay.h -// interface -// -// Created by Tobias Schwinger on 4/14/13. -// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -// - -#ifndef __interface__LogDisplay__ -#define __interface__LogDisplay__ - -#include -#include - -#include "ui/TextRenderer.h" - -class LogDisplay : public QObject { - Q_OBJECT -public: - - static LogDisplay instance; - - void render(unsigned screenWidth, unsigned screenHeight); - - // log formatted message - void addMessage(const char* message); - - // settings - - static unsigned const TEXT_COLOR = 0xb299ff; // text foreground color (bytes, RGB) - - static FILE* const DEFAULT_STREAM; // = stdout; // stream to also log to (defined in .cpp) - static unsigned const DEFAULT_CHAR_WIDTH = 5; // width of a single character - static unsigned const DEFAULT_CHAR_HEIGHT = 16; // height of a single character - static unsigned const DEFAULT_CONSOLE_WIDTH = 400; // width of the (right-aligned) log console - - void setStream(FILE* stream); - void setLogWidth(unsigned pixels); - void setCharacterSize(unsigned width, unsigned height); - - // limits - - static unsigned const CHARACTER_BUFFER_SIZE = 16384; // number of character that are buffered - static unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered - static unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message - - QStringList getLogData(QString); - -signals: - void logReceived(QString message); - -private: - // use static 'instance' to access the single instance - LogDisplay(); - ~LogDisplay(); - - // don't copy/assign - LogDisplay(LogDisplay const&); // = delete; - LogDisplay& operator=(LogDisplay const&); // = delete; - - TextRenderer _textRenderer; - FILE* _stream; // FILE as secondary destination for log messages - char* _chars; // character buffer base address - char* _charsEnd; // character buffer, exclusive end - char** _lines; // line buffer base address - char** _linesEnd; // line buffer, exclusive end - - char* _writePos; // character position to write to - char* _writeLineStartPos; // character position where line being written starts - char** _lastLinePos; // last line in the log - unsigned _writtenInLine; // character counter for line wrapping - unsigned _lineLength; // number of characters before line wrap - - unsigned _logWidth; // width of the log in pixels - unsigned _charWidth; // width of a character in pixels - unsigned _charHeight; // height of a character in pixels - - pthread_mutex_t _mutex; -}; - -#endif - From 27e211de8d2771662710e5a2552f599779f69340 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Thu, 2 Jan 2014 23:10:21 +0100 Subject: [PATCH 08/11] possible fix for jenkins build error --- interface/src/AbstractLoggerInterface.h | 2 +- interface/src/FileLogger.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/AbstractLoggerInterface.h b/interface/src/AbstractLoggerInterface.h index 36c0b73771..d8a48fc2fd 100644 --- a/interface/src/AbstractLoggerInterface.h +++ b/interface/src/AbstractLoggerInterface.h @@ -28,7 +28,7 @@ signals: void logReceived(QString message); private: - bool _extraDebugging = false; + bool _extraDebugging; }; #endif /* defined(__interface__AbstractLoggerInterface__) */ diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index d1ef1bf83b..3ea429ff8c 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -15,6 +15,7 @@ #include FileLogger::FileLogger() : _logData(NULL) { + setExtraDebugging(false); _fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QDir logDir(_fileName); if (!logDir.exists(_fileName)) { From c0fcecad2c81447cd0eea8303850d5b8928231fa Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Thu, 2 Jan 2014 23:18:39 +0100 Subject: [PATCH 09/11] Jenkins build fix --- interface/src/FileLogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 3ea429ff8c..0d79eedb83 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -14,7 +14,7 @@ #include #include -FileLogger::FileLogger() : _logData(NULL) { +FileLogger::FileLogger() : _logData(NULL), _mutex() { setExtraDebugging(false); _fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QDir logDir(_fileName); From b7bcdf8f8c0448f83c62f261c471ed00ce31d4cd Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Thu, 2 Jan 2014 23:56:28 +0100 Subject: [PATCH 10/11] QMutex reference --- interface/src/FileLogger.h | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index e0cd0c5d5e..6a17032ae2 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -10,6 +10,7 @@ #define hifi_FileLogger_h #include "AbstractLoggerInterface.h" +#include class FileLogger : public AbstractLoggerInterface { Q_OBJECT From 38480283659e437e9ad6b3f9521811f726018d73 Mon Sep 17 00:00:00 2001 From: Stojce Slavkovski Date: Fri, 3 Jan 2014 00:11:24 +0100 Subject: [PATCH 11/11] changed locking to QMutexLocker --- interface/src/FileLogger.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 0d79eedb83..4c96dfcfa5 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -14,7 +14,7 @@ #include #include -FileLogger::FileLogger() : _logData(NULL), _mutex() { +FileLogger::FileLogger() : _logData(NULL) { setExtraDebugging(false); _fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); QDir logDir(_fileName); @@ -28,7 +28,7 @@ FileLogger::FileLogger() : _logData(NULL), _mutex() { } void FileLogger::addMessage(QString message) { - _mutex.lock(); + QMutexLocker locker(&_mutex); emit logReceived(message); _logData.append(message); @@ -37,7 +37,6 @@ void FileLogger::addMessage(QString message) { QTextStream out(&file); out << message; } - _mutex.unlock(); } void FileLogger::locateLog() {