mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
290 lines
7.8 KiB
C++
290 lines
7.8 KiB
C++
![]() |
/*
|
||
|
This file is part of Akonadi.
|
||
|
|
||
|
Copyright (c) 2009 KDAB
|
||
|
Author: Till Adam <adam@kde.org>
|
||
|
|
||
|
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, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||
|
USA.
|
||
|
*/
|
||
|
|
||
|
#include "jobtrackermodel.h"
|
||
|
#include "jobtracker.h"
|
||
|
|
||
|
#include <KGlobal>
|
||
|
#include <KLocale>
|
||
|
#include <QtCore/QStringList>
|
||
|
#include <QtCore/QModelIndex>
|
||
|
#include <QtCore/QDebug>
|
||
|
#include <QtCore/QDateTime>
|
||
|
#include <QFont>
|
||
|
#include <QPair>
|
||
|
|
||
|
#include <cassert>
|
||
|
|
||
|
class JobTrackerModel::Private
|
||
|
{
|
||
|
public:
|
||
|
Private( const char *name, JobTrackerModel* _q )
|
||
|
: q( _q ), tracker( name )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
int rowForParentId( int parentid )
|
||
|
{
|
||
|
const int grandparentid = tracker.parentId( parentid );
|
||
|
int row = -1;
|
||
|
if ( grandparentid == -1 )
|
||
|
{
|
||
|
const QString session = tracker.sessionForId( parentid );
|
||
|
if ( !session.isEmpty() ) {
|
||
|
row = tracker.sessions().indexOf( session );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// offset of the parent in the list of children of the grandparent
|
||
|
row = tracker.jobNames( grandparentid ).indexOf( tracker.jobForId( parentid ) );
|
||
|
}
|
||
|
return row;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
JobTrackerModel* const q;
|
||
|
public:
|
||
|
JobTracker tracker;
|
||
|
};
|
||
|
|
||
|
JobTrackerModel::JobTrackerModel( const char *name, QObject* parent )
|
||
|
:QAbstractItemModel( parent ), d( new Private( name, this ) )
|
||
|
{
|
||
|
connect( &d->tracker, SIGNAL(reset()),
|
||
|
this, SIGNAL(modelReset()) );
|
||
|
connect( &d->tracker, SIGNAL(added(QList<QPair<int,int> >)),
|
||
|
this, SLOT(jobsAdded(QList<QPair<int,int> >)) );
|
||
|
connect( &d->tracker, SIGNAL(updated(QList<QPair<int,int> >)),
|
||
|
this, SLOT(jobsUpdated(QList<QPair<int,int> >)) );
|
||
|
}
|
||
|
|
||
|
JobTrackerModel::~JobTrackerModel()
|
||
|
{
|
||
|
delete d;
|
||
|
}
|
||
|
|
||
|
QModelIndex JobTrackerModel::index(int row, int column, const QModelIndex & parent) const
|
||
|
{
|
||
|
if ( !parent.isValid() ) // session, at top level
|
||
|
{
|
||
|
if ( row < 0 || row >= d->tracker.sessions().size() )
|
||
|
return QModelIndex();
|
||
|
return createIndex( row, column, d->tracker.idForSession( d->tracker.sessions().at(row) ) );
|
||
|
}
|
||
|
// non-toplevel job
|
||
|
const QStringList jobs = d->tracker.jobNames( parent.internalId() );
|
||
|
if ( row >= jobs.size() ) return QModelIndex();
|
||
|
return createIndex( row, column, d->tracker.idForJob( jobs.at( row ) ) );
|
||
|
}
|
||
|
|
||
|
QModelIndex JobTrackerModel::parent(const QModelIndex & idx) const
|
||
|
{
|
||
|
if ( !idx.isValid() ) return QModelIndex();
|
||
|
|
||
|
const int parentid = d->tracker.parentId( idx.internalId() );
|
||
|
if ( parentid == -1 ) return QModelIndex(); // top level session
|
||
|
|
||
|
const int row = d->rowForParentId( parentid );
|
||
|
if ( row >= 0 ) {
|
||
|
return createIndex( row, 0, parentid );
|
||
|
} else {
|
||
|
return QModelIndex();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int JobTrackerModel::rowCount(const QModelIndex & parent) const
|
||
|
{
|
||
|
if ( !parent.isValid() )
|
||
|
{
|
||
|
return d->tracker.sessions().size();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return d->tracker.jobNames( parent.internalId() ).size();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int JobTrackerModel::columnCount(const QModelIndex & parent) const
|
||
|
{
|
||
|
Q_UNUSED( parent );
|
||
|
return 7;
|
||
|
}
|
||
|
|
||
|
static QString formatTimeWithMsec( const QTime &time )
|
||
|
{
|
||
|
return QString(KGlobal::locale()->formatTime( time, true )
|
||
|
+ QString::fromLatin1( ".%1" ).arg( time.msec(), 3, 10, QLatin1Char('0') ) );
|
||
|
}
|
||
|
|
||
|
static QString formatDurationWithMsec( qint64 msecs )
|
||
|
{
|
||
|
QTime time( 0, 0, 0 );
|
||
|
time = time.addMSecs( msecs );
|
||
|
return formatTimeWithMsec( time );
|
||
|
}
|
||
|
|
||
|
QVariant JobTrackerModel::data(const QModelIndex & idx, int role) const
|
||
|
{
|
||
|
// top level items are sessions
|
||
|
if ( !idx.parent().isValid() )
|
||
|
{
|
||
|
if ( role == Qt::DisplayRole )
|
||
|
{
|
||
|
const QStringList sessions = d->tracker.sessions();
|
||
|
if( idx.column() == 0 && idx.row() <= sessions.size()) {
|
||
|
return sessions.at(idx.row());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else // not top level, so a job or subjob
|
||
|
{
|
||
|
const int id = idx.internalId();
|
||
|
const JobInfo info = d->tracker.info( id );
|
||
|
if ( role == Qt::DisplayRole )
|
||
|
{
|
||
|
switch ( idx.column() ) {
|
||
|
case 0:
|
||
|
return info.id;
|
||
|
case 1:
|
||
|
return formatTimeWithMsec( info.timestamp.time() );
|
||
|
case 2:
|
||
|
if ( info.startedTimestamp.isNull() || info.timestamp.isNull() )
|
||
|
return QString();
|
||
|
return formatDurationWithMsec( info.timestamp.msecsTo( info.startedTimestamp ) );
|
||
|
case 3:
|
||
|
if ( info.endedTimestamp.isNull() || info.startedTimestamp.isNull() )
|
||
|
return QString();
|
||
|
return formatDurationWithMsec( info.startedTimestamp.msecsTo( info.endedTimestamp ) );
|
||
|
case 4:
|
||
|
return info.type;
|
||
|
case 5:
|
||
|
return info.stateAsString();
|
||
|
case 6:
|
||
|
return info.debugString;
|
||
|
}
|
||
|
}
|
||
|
else if ( role == Qt::ForegroundRole ) {
|
||
|
if ( info.state == JobInfo::Failed )
|
||
|
return Qt::red;
|
||
|
}
|
||
|
else if ( role == Qt::FontRole ) {
|
||
|
if ( info.state == JobInfo::Running ) {
|
||
|
QFont f;
|
||
|
f.setBold( true );
|
||
|
return f;
|
||
|
}
|
||
|
}
|
||
|
else if ( role == Qt::ToolTipRole ) {
|
||
|
if ( info.state == JobInfo::Failed )
|
||
|
return info.error;
|
||
|
}
|
||
|
}
|
||
|
return QVariant();
|
||
|
}
|
||
|
|
||
|
QVariant JobTrackerModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||
|
{
|
||
|
if ( role == Qt::DisplayRole )
|
||
|
{
|
||
|
if ( orientation == Qt::Horizontal )
|
||
|
{
|
||
|
switch ( section ) {
|
||
|
case 0:
|
||
|
return QLatin1String("Job ID");
|
||
|
case 1:
|
||
|
return QLatin1String("Created");
|
||
|
case 2:
|
||
|
return QLatin1String("Wait time"); // duration (time started - time created)
|
||
|
case 3:
|
||
|
return QLatin1String("Job duration"); // duration (time ended - time started)
|
||
|
case 4:
|
||
|
return QLatin1String("Job Type");
|
||
|
case 5:
|
||
|
return QLatin1String("State");
|
||
|
case 6:
|
||
|
return QLatin1String("Info");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return QVariant();
|
||
|
}
|
||
|
|
||
|
void JobTrackerModel::resetTracker()
|
||
|
{
|
||
|
d->tracker.triggerReset();
|
||
|
}
|
||
|
|
||
|
|
||
|
bool JobTrackerModel::isEnabled() const
|
||
|
{
|
||
|
return d->tracker.isEnabled();
|
||
|
}
|
||
|
|
||
|
void JobTrackerModel::setEnabled( bool on )
|
||
|
{
|
||
|
d->tracker.setEnabled( on );
|
||
|
}
|
||
|
|
||
|
void JobTrackerModel::jobsAdded( const QList< QPair< int, int > > & jobs )
|
||
|
{
|
||
|
// TODO group them by parent? It's likely that multiple jobs for the same
|
||
|
// parent will come in in the same batch, isn't it?
|
||
|
#define PAIR QPair<int, int> // the parser in foreach barfs otherwise
|
||
|
Q_FOREACH( const PAIR& job, jobs ) {
|
||
|
const int pos = job.first;
|
||
|
const int parentId = job.second;
|
||
|
QModelIndex parentIdx;
|
||
|
if ( parentId != -1 ) {
|
||
|
const int row = d->rowForParentId( parentId );
|
||
|
if ( row >= 0 ) {
|
||
|
parentIdx = createIndex( row, 0, parentId );
|
||
|
}
|
||
|
}
|
||
|
beginInsertRows( parentIdx, pos, pos );
|
||
|
endInsertRows();
|
||
|
const QModelIndex idx = index( pos, 0, parentIdx );
|
||
|
}
|
||
|
#undef PAIR
|
||
|
}
|
||
|
|
||
|
void JobTrackerModel::jobsUpdated( const QList< QPair< int, int > > & jobs )
|
||
|
{
|
||
|
// TODO group them by parent? It's likely that multiple jobs for the same
|
||
|
// parent will come in in the same batch, isn't it?
|
||
|
#define PAIR QPair<int, int> // the parser in foreach barfs otherwise
|
||
|
Q_FOREACH( const PAIR& job, jobs ) {
|
||
|
const int pos = job.first;
|
||
|
const int parentId = job.second;
|
||
|
QModelIndex parentIdx;
|
||
|
if ( parentId != -1 ) {
|
||
|
const int row = d->rowForParentId( parentId );
|
||
|
if ( row >= 0 ) {
|
||
|
parentIdx = createIndex( row, 0, parentId );
|
||
|
}
|
||
|
}
|
||
|
dataChanged( index( pos, 0, parentIdx ), index( pos, 3, parentIdx ) );
|
||
|
}
|
||
|
#undef PAIR
|
||
|
}
|
||
|
|