#include <Common/Globals>
#include <Common/iLogger>
+#include <Common/iApp>
#include <QtGui>
// Return the message for the display role
case Qt::DisplayRole: {
- return mData.at(index.row()).text;
+ return mData.at(index.row()).simplified;
break;
}
mData.dequeue();
endRemoveRows();
}
+
+ emit messageAdded(index(mData.size() - 1, 0));
}
QString Model::details(QModelIndex const & index) const
{
Message const & m = mData.at(index.row());
- return tr("%1 %2.%3 %4 : %5\nOccurred in %6")
+ return tr("%1 %2 %3 : %4\nOccurred in %5")
.arg(m.dt.date().toString(Qt::DefaultLocaleShortDate))
- .arg(m.dt.time().toString(Qt::DefaultLocaleLongDate))
- .arg(m.dt.time().msec(), 3, 10, QChar('0'))
+ .arg(m.dt.time().toString("HH:mm:ss.zzz"))
.arg(tr(severityText(m.severity)))
.arg(m.text)
.arg(m.where);
for (int i = 0; i < mData.size(); ++i) {
Message const & m = mData.at(i);
- out << tr("%1 %2.%3 %4 : %5 (occurred in %6)\n")
+ out << tr("%1 %2 %3 : %4 (occurred in %5)\n")
.arg(m.dt.date().toString(Qt::DefaultLocaleShortDate))
- .arg(m.dt.time().toString(Qt::DefaultLocaleLongDate))
- .arg(m.dt.time().msec(), 3, 10, QChar('0'))
+ .arg(m.dt.time().toString("HH:mm:ss.zzz"))
.arg(tr(severityText(m.severity)))
.arg(m.text)
.arg(m.where)
//-------------------------------------------------------------------
-Widget::Widget(QWidget * parent, Qt::WindowFlags flags)
+Widget::Widget(QString const & source, QWidget * parent)
+ : QWidget(parent)
+ , mSource(source)
+ , mAutoScroll(true)
+{
+ QVBoxLayout * w = new QVBoxLayout;
+ setLayout(w);
+
+ mModel = new Model(this);
+ connect(mModel, SIGNAL(messageAdded(QModelIndex)), this, SLOT(messageAdded(QModelIndex)));
+
+ wList = new QListView;
+ wList->setModel(mModel);
+ wList->setUniformItemSizes(true);
+ connect(wList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex,QModelIndex)));
+ w->addWidget(wList);
+
+ wList->setContextMenuPolicy(Qt::ActionsContextMenu);
+
+ QAction * a = new QAction(tr("&Copy", VER_MODULE_NAME_STR), this);
+ a->setStatusTip(tr("Copies the selected message to the clipboard for pasting into other applications", VER_MODULE_NAME_STR));
+ connect(a, SIGNAL(triggered()), this, SLOT(copyToClipboard()));
+ wList->addAction(a);
+
+ a = new QAction(tr("&Save to ...", VER_MODULE_NAME_STR), this);
+ a->setStatusTip(tr("Saves all the messages to a file", VER_MODULE_NAME_STR));
+ connect(a, SIGNAL(triggered()), this, SLOT(saveToFile()));
+ wList->addAction(a);
+
+ wDetails = new QLabel;
+ wDetails->setWordWrap(true);
+ w->addWidget(wDetails);
+}
+
+void Widget::messageAdded(QModelIndex const & index)
+{
+ if (mAutoScroll)
+ wList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
+}
+
+void Widget::currentChanged(QModelIndex const & current, QModelIndex const & previous)
+{
+ Q_UNUSED(previous);
+
+ if (!current.isValid() || current.row() < 0 || current.row() > mModel->rowCount()) {
+ wDetails->clear();
+ return;
+ }
+
+ mAutoScroll = current.row() == (mModel->rowCount() - 1);
+
+ wDetails->setText(mModel->details(current));
+}
+
+void Widget::copyToClipboard()
+{
+ QModelIndex idx = wList->selectionModel()->currentIndex();
+ if (idx.isValid())
+ mModel->copyToClipboard(idx);
+}
+
+void Widget::saveToFile()
+{
+ QString fileName = QFileDialog::getSaveFileName(this,
+ tr("Save to file", VER_MODULE_NAME_STR),
+ Common::iApp::instance()->dataRootDir() + QString("%1_%2.txt").arg(mSource).arg(QDate::currentDate().toString("yyyyMMdd")),
+ tr("Text files (*.txt);;All files (*)", VER_MODULE_NAME_STR));
+ if (fileName.isEmpty())
+ return;
+
+ if (!mModel->saveToFile(fileName))
+ QMessageBox::critical(this, tr("Error", VER_MODULE_NAME_STR), mModel->errorString());
+}
+
+
+//-------------------------------------------------------------------
+
+Window::Window(QWidget * parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
{
- setObjectName(QString("%1-Widget").arg(VER_MODULE_NAME_STR));
+ setObjectName(QString("%1-Window").arg(VER_MODULE_NAME_STR));
+
+ setWindowTitle(tr("Messages"));
+
+ Common::iLogger * logger = Common::iLogger::instance();
+ EVAF_TEST_X(logger, "No iLogger interface");
+
+ mDefSource = logger->defaultSource();
+ if (mDefSource.isEmpty())
+ mDefSource = "Common";
+
+ QVBoxLayout * w = new QVBoxLayout;
+ w->setMargin(0);
+ setLayout(w);
+
+ wTabs = new QTabWidget;
+ w->addWidget(wTabs);
+
+ // Add the default source
+ Widget * s = new Widget(mDefSource);
+ mLogViews.insert(s->source(), s);
+ wTabs->addTab(s, s->source());
+
+ wStatusBar = new QStatusBar;
+ w->addWidget(wStatusBar);
+
+ QAction * a = new QAction(this);
+ a->setShortcut(Qt::Key_Escape);
+ connect(a, SIGNAL(triggered()), this, SLOT(close()));
+ addAction(a);
+
+ restoreSettings();
+
+ connect(logger, SIGNAL(loggerEvent(Common::iLogger::Severity,QString,QString,QString)), this, SLOT(loggerEvent(Common::iLogger::Severity,QString,QString,QString)));
+
+ show();
+
EVAF_INFO("%s created", qPrintable(objectName()));
}
-Widget::~Widget()
+Window::~Window()
{
+ mLogViews.clear();
+
+ saveSettings();
+
EVAF_INFO("%s destroyed", qPrintable(objectName()));
}
+bool Window::event(QEvent * e)
+{
+ if (e->type() == QEvent::StatusTip) {
+ QStatusTipEvent * event = static_cast<QStatusTipEvent *>(e);
+ wStatusBar->showMessage(event->tip());
+ return true;
+ }
+ return QWidget::event(e);
+}
+
+void Window::saveSettings()
+{
+ static int ver[4] = {VER_FILE_VERSION};
+ QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
+ settings.setValue(QString("%1/version/major").arg(objectName()), ver[0]);
+ settings.setValue(QString("%1/version/minor").arg(objectName()), ver[1]);
+ settings.setValue(QString("%1/geometry").arg(objectName()), saveGeometry());
+}
+
+void Window::restoreSettings()
+{
+ static int ver[4] = {VER_FILE_VERSION};
+ QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name());
+
+ // Ignore saved settings if the version number is not the same
+ // More intelligent checks can be implemented to allow upgrading from previous versions
+ QVariant v = settings.value(QString("%1/version/major").arg(objectName()));
+ if (!v.isValid() || v.toInt() != ver[0])
+ return;
+ v = settings.value(QString("%1/version/minor").arg(objectName()));
+ if (!v.isValid() || v.toInt() != ver[1])
+ return;
+
+ // Restore the geometry
+ restoreGeometry(settings.value(QString("%1/geometry").arg(objectName())).toByteArray());
+}
+
+void Window::loggerEvent(Common::iLogger::Severity severity, QString const & text, QString const & source, QString const & where)
+{
+ // Ignore messages with >=DEBUG severity level
+ if (severity >= Common::iLogger::Debug)
+ return;
+
+ // Find or create the log view widget for this source
+ Widget * w = 0;
+ QString s = source.isEmpty() ? mDefSource : source;
+ QHash<QString, Widget *>::const_iterator it = mLogViews.constFind(s);
+ if (it == mLogViews.constEnd()) {
+ w = new Widget(s);
+ mLogViews.insert(w->source(), w);
+ wTabs->addTab(w, w->source());
+ }
+ else
+ w = *it;
+
+ w->addMessage(severity, text, where);
+}
+
//-------------------------------------------------------------------
Module::Module()
: Plugins::iPlugin()
- , wWidget(0)
+ , wWindow(0)
{
setObjectName(QString("%1-Module").arg(VER_MODULE_NAME_STR));
EVAF_INFO("%s created", qPrintable(objectName()));
{
Q_UNUSED(args);
- wWidget = new Widget();
+ wWindow = new Window();
EVAF_INFO("%s initialized", qPrintable(objectName()));
void Module::done()
{
- if (wWidget) {
- delete wWidget;
- wWidget = 0;
+ if (wWindow) {
+ delete wWindow;
+ wWindow = 0;
}
EVAF_INFO("%s finalized", qPrintable(objectName()));