Commit a677b4ff authored by Etienne Delclaux's avatar Etienne Delclaux
Browse files

Add dtkWidgetsLogView (include dtkLogModel creation and attachModel to dtkLogger)

parent 9de24bd3
......@@ -24,13 +24,15 @@ set(${PROJECT_NAME}_HEADERS
dtkLogger.h
dtkLogger_p.h
dtkLogEngine.h
dtkLogDestination.h)
dtkLogDestination.h
dtkLogModel.h)
set(${PROJECT_NAME}_SOURCES
dtkLog.cpp
dtkLogger.cpp
dtkLogEngine.cpp
dtkLogDestination.cpp)
dtkLogDestination.cpp
dtkLogModel.cpp)
## #################################################################
## Build rules
......
......@@ -13,6 +13,7 @@
// Code:
#include "dtkLogDestination.h"
#include "dtkLogModel.h"
// /////////////////////////////////////////////////////////////////
// dtkLogDestination
......@@ -78,5 +79,32 @@ void dtkLogDestinationFile::write(const QString& message)
d->stream.flush();
}
// /////////////////////////////////////////////////////////////////
// dtkLogDestinationModel
// /////////////////////////////////////////////////////////////////
class dtkLogDestinationModelPrivate
{
public:
dtkLogModel *model;
};
dtkLogDestinationModel::dtkLogDestinationModel(dtkLogModel *model) : d(new dtkLogDestinationModelPrivate)
{
d->model = model;
}
dtkLogDestinationModel::~dtkLogDestinationModel(void)
{
delete d;
d = NULL;
}
void dtkLogDestinationModel::write(const QString& message)
{
d->model->append(message);
}
//
// dtkLogDestination.cpp ends here
......@@ -68,6 +68,25 @@ private:
dtkLogDestinationFilePrivate *d;
};
// /////////////////////////////////////////////////////////////////
// dtkLogDestinationList
// /////////////////////////////////////////////////////////////////
class dtkLogDestinationModelPrivate;
class DTKLOG_EXPORT dtkLogDestinationModel : public dtkLogDestination
{
public:
dtkLogDestinationModel(dtkLogModel *model);
~dtkLogDestinationModel(void);
public:
void write(const QString& message);
private:
dtkLogDestinationModelPrivate *d;
};
// /////////////////////////////////////////////////////////////////
// dtkLogDestinationPointer
// /////////////////////////////////////////////////////////////////
......
/* dtkLogModel.cpp ---
*
* Author: Julien Wintz
* Copyright (C) 2008-2011 - Julien Wintz, Inria.
* Created: Mon Mar 5 10:25:48 2012 (+0100)
* Version: $Id$
* Last-Updated: Mon Mar 5 12:29:52 2012 (+0100)
* By: Julien Wintz
* Update #: 18
*/
/* Commentary:
*
*/
/* Change log:
*
*/
#include "dtkLogModel.h"
class dtkLogModelPrivate
{
public:
QStringList logs;
};
dtkLogModel::dtkLogModel(QObject *parent) : QAbstractListModel(parent), d(new dtkLogModelPrivate)
{
}
void dtkLogModel::append(const QString& message)
{
int row = d->logs.count();
beginInsertRows(QModelIndex(), row, row);
d->logs.append(message);
endInsertRows();
}
int dtkLogModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return d->logs.count();
}
QVariant dtkLogModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= d->logs.size())
return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole)
return d->logs.at(index.row());
return QVariant();
}
Qt::ItemFlags dtkLogModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled;
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}
bool dtkLogModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.row() >= 0 && index.row() < d->logs.size()
&& (role == Qt::EditRole || role == Qt::DisplayRole)) {
d->logs.replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return false;
}
bool dtkLogModel::insertRows(int row, int count, const QModelIndex &parent)
{
if (count < 1 || row < 0 || row > rowCount(parent))
return false;
beginInsertRows(QModelIndex(), row, row + count - 1);
for (int r = 0; r < count; ++r)
d->logs.insert(row, QString());
endInsertRows();
return true;
}
bool dtkLogModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (count <= 0 || row < 0 || (row + count) > rowCount(parent))
return false;
beginRemoveRows(QModelIndex(), row, row + count - 1);
for (int r = 0; r < count; ++r)
d->logs.removeAt(row);
endRemoveRows();
return true;
}
static bool ascendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2)
{
return s1.first < s2.first;
}
static bool decendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2)
{
return s1.first > s2.first;
}
void dtkLogModel::sort(int, Qt::SortOrder order)
{
emit layoutAboutToBeChanged();
QList<QPair<QString, int> > list;
for (int i = 0; i < d->logs.count(); ++i)
list.append(QPair<QString, int>(d->logs.at(i), i));
if (order == Qt::AscendingOrder)
qSort(list.begin(), list.end(), ascendingLessThan);
else
qSort(list.begin(), list.end(), decendingLessThan);
d->logs.clear();
QVector<int> forwarding(list.count());
for (int i = 0; i < list.count(); ++i) {
d->logs.append(list.at(i).first);
forwarding[list.at(i).second] = i;
}
QModelIndexList oldList = persistentIndexList();
QModelIndexList newList;
for (int i = 0; i < oldList.count(); ++i)
newList.append(index(forwarding.at(oldList.at(i).row()), 0));
changePersistentIndexList(oldList, newList);
emit layoutChanged();
}
Qt::DropActions dtkLogModel::supportedDropActions(void) const
{
return QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
}
/* dtkLogModel.h ---
*
* Author: Julien Wintz
* Copyright (C) 2008-2011 - Julien Wintz, Inria.
* Created: Mon Mar 5 10:13:44 2012 (+0100)
* Version: $Id$
* Last-Updated: Mon Mar 5 11:14:39 2012 (+0100)
* By: Julien Wintz
* Update #: 27
*/
/* Commentary:
*
*/
/* Change log:
*
*/
#ifndef DTKLOGMODEL_H
#define DTKLOGMODEL_H
#include "dtkLogExport.h"
#include <QtCore>
class dtkLogModelPrivate;
class DTKLOG_EXPORT dtkLogModel : public QAbstractListModel
{
Q_OBJECT
public:
dtkLogModel(QObject *parent = 0);
public:
void append(const QString& message);
public:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
public:
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
public:
Qt::ItemFlags flags(const QModelIndex &index) const;
public:
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
public:
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
public:
Qt::DropActions supportedDropActions(void) const;
private:
dtkLogModelPrivate *d;
};
#endif
......@@ -15,6 +15,7 @@
#include "dtkLogger.h"
#include "dtkLogger_p.h"
#include "dtkLogDestination.h"
#include "dtkLogModel.h"
dtkLogger& dtkLogger::instance(void)
{
......@@ -86,6 +87,26 @@ void dtkLogger::detachFile(const QString& path)
d->files.remove(path);
}
void dtkLogger::attachModel(dtkLogModel *model)
{
if(d->models.contains(model))
return;
d->models[model] = dtkLogDestinationPointer(new dtkLogDestinationModel(model));
d->destinations << d->models[model];
}
void dtkLogger::detachModel(dtkLogModel *model)
{
if(!d->models.contains(model))
return;
d->destinations.removeOne(d->models[model]);
d->models.remove(model);
}
dtkLogger::dtkLogger(void) : d(new dtkLoggerPrivate)
{
d->level = dtkLog::Info;
......
......@@ -19,6 +19,8 @@
#include <QtCore>
class dtkLogModel;
class DTKLOG_EXPORT dtkLogger
{
public:
......@@ -40,6 +42,10 @@ public:
void attachFile(const QString& path);
void detachFile(const QString& path);
public:
void attachModel(dtkLogModel *model);
void detachModel(dtkLogModel *model);
private:
dtkLogger(void);
dtkLogger(const dtkLogger& other);
......
......@@ -34,8 +34,9 @@ public:
QHash<dtkLogDestinationPointer, dtkLog::Level> levels;
public:
dtkLogDestinationPointer console;
QHash<QString, dtkLogDestinationPointer> files;
dtkLogDestinationPointer console;
QHash<QString, dtkLogDestinationPointer> files;
QHash<dtkLogModel *, dtkLogDestinationPointer> models;
public:
QList<dtkLogDestinationPointer> destinations;
......
......@@ -19,6 +19,8 @@ project(dtkWidgets)
## #################################################################
set(${PROJECT_NAME}_HEADERS
dtkWidgetsLogView.h
dtkWidgetsLogView_p.h
dtkWidgetsTag.h
dtkWidgetsTagCloud.h
dtkWidgetsTagCloudController.h
......@@ -31,6 +33,7 @@ set(${PROJECT_NAME}_HEADERS
dtkWidgetsTagCloudView.h)
set(${PROJECT_NAME}_SOURCES
dtkWidgetsLogView.cpp
dtkWidgetsTag.cpp
dtkWidgetsTagCloud.cpp
dtkWidgetsTagCloudController.cpp
......
/* dtkWidgetsLogView.cpp ---
*
* Author: Julien Wintz
* Copyright (C) 2008-2011 - Julien Wintz, Inria.
* Created: Fri Mar 2 15:13:52 2012 (+0100)
* Version: $Id$
* Last-Updated: Tue Apr 24 12:29:06 2012 (+0200)
* By: Julien Wintz
* Update #: 362
*/
/* Commentary:
*
*/
/* Change log:
*
*/
#include <dtkLog/dtkLog.h>
#include <dtkLog/dtkLogModel.h>
#include "dtkWidgetsLogView.h"
#include "dtkWidgetsLogView_p.h"
// /////////////////////////////////////////////////////////////////
// dtkWidgetsLogViewBar
// /////////////////////////////////////////////////////////////////
dtkWidgetsLogViewBar::dtkWidgetsLogViewBar(QWidget *parent) : QFrame(parent)
{
QPushButton *b_trace = new QPushButton("Trace", this);
QPushButton *b_debug = new QPushButton("Debug", this);
QPushButton *b_info = new QPushButton("Info", this);
QPushButton *b_warn = new QPushButton("Warn", this);
QPushButton *b_error = new QPushButton("Error", this);
QPushButton *b_fatal = new QPushButton("Fatal", this);
b_trace->setCheckable(true);
b_debug->setCheckable(true);
b_info->setCheckable(true);
b_warn->setCheckable(true);
b_error->setCheckable(true);
b_fatal->setCheckable(true);
b_trace->setChecked(true);
b_debug->setChecked(true);
b_info->setChecked(true);
b_warn->setChecked(true);
b_error->setChecked(true);
b_fatal->setChecked(true);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(b_trace);
layout->addWidget(b_debug);
layout->addWidget(b_info);
layout->addWidget(b_warn);
layout->addWidget(b_error);
layout->addWidget(b_fatal);
connect(b_trace, SIGNAL(clicked(bool)), this, SIGNAL(displayTrace(bool)));
connect(b_debug, SIGNAL(clicked(bool)), this, SIGNAL(displayDebug(bool)));
connect(b_info, SIGNAL(clicked(bool)), this, SIGNAL(displayInfo(bool)));
connect(b_warn, SIGNAL(clicked(bool)), this, SIGNAL(displayWarn(bool)));
connect(b_error, SIGNAL(clicked(bool)), this, SIGNAL(displayError(bool)));
connect(b_fatal, SIGNAL(clicked(bool)), this, SIGNAL(displayFatal(bool)));
}
dtkWidgetsLogViewBar::~dtkWidgetsLogViewBar(void)
{
}
// /////////////////////////////////////////////////////////////////
// dtkWidgetsLogViewTree
// /////////////////////////////////////////////////////////////////
dtkWidgetsLogViewTree::dtkWidgetsLogViewTree(QWidget *parent) : QTreeWidget(parent)
{
this->setAttribute(Qt::WA_MacShowFocusRect, false);
this->setFrameShape(QFrame::HLine);
this->setHeaderHidden(true);
this->runtime = new QTreeWidgetItem(QStringList() << "Runtime log");
this->file = new QTreeWidgetItem(QStringList() << "File log");
this->file->addChild(new QTreeWidgetItem(QStringList() << dtkLogPath(qApp)));
this->addTopLevelItem(this->runtime);
this->addTopLevelItem(this->file);
connect(this, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(onItemClicked(QTreeWidgetItem *, int)));
}
dtkWidgetsLogViewTree::~dtkWidgetsLogViewTree(void)
{
}
void dtkWidgetsLogViewTree::onItemClicked(QTreeWidgetItem *item, int)
{
if (item == this->runtime)
emit runtimeClicked();
else if (item == this->file)
;
else
emit fileClicked(item->text(0));
}
// /////////////////////////////////////////////////////////////////
// dtkWidgetsLogViewList
// /////////////////////////////////////////////////////////////////
dtkWidgetsLogViewList::dtkWidgetsLogViewList(QWidget *parent) : QListView(parent)
{
this->model = new dtkLogModel(this);
this->proxy = new QSortFilterProxyModel(this);
this->proxy->setFilterKeyColumn(0);
this->setModel(this->proxy);
this->setAlternatingRowColors(true);
this->setAttribute(Qt::WA_MacShowFocusRect, false);
this->setFrameShape(QFrame::NoFrame);
this->setRuntime();
}
dtkWidgetsLogViewList::~dtkWidgetsLogViewList(void)
{
qDeleteAll(this->models);
}
void dtkWidgetsLogViewList::setAutoScroll(bool autoScroll)
{
if(autoScroll)
connect(this->model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(scrollToBottom()));
else
disconnect(this->model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(scrollToBottom()));
}
void dtkWidgetsLogViewList::setRuntime(void)
{
dtkLogger::instance().attachModel(this->model);
this->proxy->setSourceModel(this->model);
}
void dtkWidgetsLogViewList::setFile(const QString& path)
{
if (this->models.contains(path))
this->models.remove(path);
QFile file(path);
if(!file.open(QFile::ReadOnly))
qDebug() << "Unable to read file" << path;
QString contents = file.readAll();
file.close();
QStringListModel *model = new QStringListModel(contents.split("\n"));
this->proxy->setSourceModel(model);
this->models.insert(path, model);
// QFileSystemWatcher *watcher = new QFileSystemWatcher(QStringList() << path, this);
// connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(setFile(const QString&)));
}
void dtkWidgetsLogViewList::setFilter(const QRegExp& expression)
{
this->proxy->setFilterRegExp(expression);
}
// /////////////////////////////////////////////////////////////////
// dtkWidgetsLogViewPrivate
// /////////////////////////////////////////////////////////////////
QRegExp dtkWidgetsLogViewPrivate::expression(void)
{
if(this->exclude.isEmpty())
return QRegExp();
QString patterns;
foreach(QString pattern, this->exclude)
patterns.append(QString("%1|").arg(pattern));
patterns.chop(1);
return QRegExp(QString("^(?!%1).*").arg(patterns), Qt::CaseSensitive, QRegExp::RegExp2);
}
// /////////////////////////////////////////////////////////////////
// dtkWidgetsLogView
// /////////////////////////////////////////////////////////////////
dtkWidgetsLogView::dtkWidgetsLogView(QWidget *parent) : QWidget(parent), d(new dtkWidgetsLogViewPrivate)
{
d->bar = new dtkWidgetsLogViewBar(this);
d->tree = new dtkWidgetsLogViewTree(this);
d->tree->setMaximumWidth(200);
d->list = new dtkWidgetsLogViewList(this);
d->checkbox_auto_scroll = new QCheckBox("Auto scroll", this);
d->checkbox_auto_scroll->setTristate(false);
QVBoxLayout *list_view_layout = new QVBoxLayout;
list_view_layout->addWidget(d->checkbox_auto_scroll);
list_view_layout->addWidget(d->list);
QHBoxLayout *h_layout = new QHBoxLayout;
h_layout->setContentsMargins(0, 0, 0, 0);
h_layout->setSpacing(0);
h_layout->addWidget(d->tree);
h_layout->addLayout(list_view_layout);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);