00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "agentinstancewidget.h"
00021
00022 #include "agentfilterproxymodel.h"
00023 #include "agentinstance.h"
00024 #include "agentinstancemodel.h"
00025
00026 #include <KIcon>
00027 #include <KGlobal>
00028
00029 #include <QtCore/QUrl>
00030 #include <QtGui/QAbstractTextDocumentLayout>
00031 #include <QtGui/QApplication>
00032 #include <QtGui/QHBoxLayout>
00033 #include <QtGui/QListView>
00034 #include <QtGui/QPainter>
00035 #include <QtGui/QTextDocument>
00036
00037 namespace Akonadi {
00038 namespace Internal {
00039
00040 static void iconsEarlyCleanup();
00041
00042 struct Icons
00043 {
00044 Icons()
00045 : readyPixmap( KIcon( QLatin1String( "user-online" ) ).pixmap( QSize( 16, 16 ) ) )
00046 , syncPixmap( KIcon( QLatin1String( "network-connect" ) ).pixmap( QSize( 16, 16 ) ) )
00047 , errorPixmap( KIcon( QLatin1String( "dialog-error" ) ).pixmap( QSize( 16, 16 ) ) )
00048 , offlinePixmap( KIcon( QLatin1String( "network-disconnect" ) ).pixmap( QSize( 16, 16 ) ) )
00049 {
00050 qAddPostRoutine( iconsEarlyCleanup );
00051 }
00052 QPixmap readyPixmap, syncPixmap, errorPixmap, offlinePixmap;
00053 };
00054
00055 K_GLOBAL_STATIC( Icons, s_icons )
00056
00057
00058 void iconsEarlyCleanup() {
00059 Icons * const ic = s_icons;
00060 ic->readyPixmap = ic->syncPixmap = ic->errorPixmap = ic->offlinePixmap = QPixmap();
00061 }
00062
00066 class AgentInstanceWidgetDelegate : public QAbstractItemDelegate
00067 {
00068 public:
00069 AgentInstanceWidgetDelegate( QObject *parent = 0 );
00070
00071 virtual void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
00072 virtual QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const;
00073
00074 private:
00075 void drawFocus( QPainter*, const QStyleOptionViewItem&, const QRect& ) const;
00076
00077 QTextDocument* document( const QStyleOptionViewItem &option, const QModelIndex &index ) const;
00078 };
00079
00080 }
00081
00082 using Akonadi::Internal::AgentInstanceWidgetDelegate;
00083
00087 class AgentInstanceWidget::Private
00088 {
00089 public:
00090 Private( AgentInstanceWidget *parent )
00091 : mParent( parent )
00092 {
00093 }
00094
00095 void currentAgentInstanceChanged( const QModelIndex&, const QModelIndex& );
00096 void currentAgentInstanceDoubleClicked( const QModelIndex& );
00097
00098 AgentInstanceWidget *mParent;
00099 QListView *mView;
00100 AgentInstanceModel *mModel;
00101 AgentFilterProxyModel *proxy;
00102 };
00103
00104 void AgentInstanceWidget::Private::currentAgentInstanceChanged( const QModelIndex ¤tIndex, const QModelIndex &previousIndex )
00105 {
00106 AgentInstance currentInstance;
00107 if ( currentIndex.isValid() )
00108 currentInstance = currentIndex.data( AgentInstanceModel::InstanceRole ).value<AgentInstance>();
00109
00110 AgentInstance previousInstance;
00111 if ( previousIndex.isValid() )
00112 previousInstance = previousIndex.data( AgentInstanceModel::InstanceRole ).value<AgentInstance>();
00113
00114 emit mParent->currentChanged( currentInstance, previousInstance );
00115 }
00116
00117 void AgentInstanceWidget::Private::currentAgentInstanceDoubleClicked( const QModelIndex ¤tIndex )
00118 {
00119 AgentInstance currentInstance;
00120 if ( currentIndex.isValid() )
00121 currentInstance = currentIndex.data( AgentInstanceModel::InstanceRole ).value<AgentInstance>();
00122
00123 emit mParent->doubleClicked( currentInstance );
00124 }
00125
00126 AgentInstanceWidget::AgentInstanceWidget( QWidget *parent )
00127 : QWidget( parent ), d( new Private( this ) )
00128 {
00129 QHBoxLayout *layout = new QHBoxLayout( this );
00130 layout->setMargin( 0 );
00131
00132 d->mView = new QListView( this );
00133 d->mView->setContextMenuPolicy( Qt::NoContextMenu );
00134 d->mView->setItemDelegate( new Internal::AgentInstanceWidgetDelegate( d->mView ) );
00135 d->mView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
00136 d->mView->setAlternatingRowColors( true );
00137 d->mView->setSelectionMode( QAbstractItemView::ExtendedSelection );
00138 layout->addWidget( d->mView );
00139
00140 d->mModel = new AgentInstanceModel( this );
00141
00142 d->proxy = new AgentFilterProxyModel( this );
00143 d->proxy->setSourceModel( d->mModel );
00144 d->mView->setModel( d->proxy );
00145
00146 d->mView->selectionModel()->setCurrentIndex( d->mView->model()->index( 0, 0 ), QItemSelectionModel::Select );
00147 d->mView->scrollTo( d->mView->model()->index( 0, 0 ) );
00148
00149 connect( d->mView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00150 this, SLOT( currentAgentInstanceChanged( const QModelIndex&, const QModelIndex& ) ) );
00151 connect( d->mView, SIGNAL( doubleClicked( const QModelIndex& ) ),
00152 this, SLOT( currentAgentInstanceDoubleClicked( const QModelIndex& ) ) );
00153 }
00154
00155 AgentInstanceWidget::~AgentInstanceWidget()
00156 {
00157 delete d;
00158 }
00159
00160 AgentInstance AgentInstanceWidget::currentAgentInstance() const
00161 {
00162 QItemSelectionModel *selectionModel = d->mView->selectionModel();
00163 if ( !selectionModel )
00164 return AgentInstance();
00165
00166 QModelIndex index = selectionModel->currentIndex();
00167 if ( !index.isValid() )
00168 return AgentInstance();
00169
00170 return index.data( AgentInstanceModel::InstanceRole ).value<AgentInstance>();
00171 }
00172
00173 QList<AgentInstance> AgentInstanceWidget::selectedAgentInstances() const
00174 {
00175 QList<AgentInstance> list;
00176 QItemSelectionModel *selectionModel = d->mView->selectionModel();
00177 if ( !selectionModel )
00178 return list;
00179
00180 QModelIndexList indexes = selectionModel->selection().indexes();
00181
00182 foreach (const QModelIndex &index, indexes )
00183 {
00184 list.append( index.data( AgentInstanceModel::InstanceRole ).value<AgentInstance>() );
00185 }
00186
00187 return list;
00188 }
00189
00190 QAbstractItemView* AgentInstanceWidget::view() const
00191 {
00192 return d->mView;
00193 }
00194
00195
00196 AgentFilterProxyModel* AgentInstanceWidget::agentFilterProxyModel() const
00197 {
00198 return d->proxy;
00199 }
00200
00201
00202
00203
00204
00205 AgentInstanceWidgetDelegate::AgentInstanceWidgetDelegate( QObject *parent )
00206 : QAbstractItemDelegate( parent )
00207 {
00208 }
00209
00210 QTextDocument* AgentInstanceWidgetDelegate::document( const QStyleOptionViewItem &option, const QModelIndex &index ) const
00211 {
00212 if ( !index.isValid() )
00213 return 0;
00214
00215 const QString name = index.model()->data( index, Qt::DisplayRole ).toString();
00216 int status = index.model()->data( index, AgentInstanceModel::StatusRole ).toInt();
00217 uint progress = index.model()->data( index, AgentInstanceModel::ProgressRole ).toUInt();
00218 const QString statusMessage = index.model()->data( index, AgentInstanceModel::StatusMessageRole ).toString();
00219 const QStringList capabilities = index.model()->data( index, AgentInstanceModel::CapabilitiesRole ).toStringList();
00220
00221 QTextDocument *document = new QTextDocument( 0 );
00222
00223 const QVariant data = index.model()->data( index, Qt::DecorationRole );
00224 if ( data.isValid() && data.type() == QVariant::Icon ) {
00225 document->addResource( QTextDocument::ImageResource, QUrl( QLatin1String( "agent_icon" ) ),
00226 qvariant_cast<QIcon>( data ).pixmap( QSize( 64, 64 ) ) );
00227 }
00228
00229 if ( !index.data( AgentInstanceModel::OnlineRole ).toBool() )
00230 document->addResource( QTextDocument::ImageResource, QUrl( QLatin1String( "status_icon" ) ), s_icons->offlinePixmap );
00231 else if ( status == AgentInstance::Idle )
00232 document->addResource( QTextDocument::ImageResource, QUrl( QLatin1String( "status_icon" ) ), s_icons->readyPixmap );
00233 else if ( status == AgentInstance::Running )
00234 document->addResource( QTextDocument::ImageResource, QUrl( QLatin1String( "status_icon" ) ), s_icons->syncPixmap );
00235 else
00236 document->addResource( QTextDocument::ImageResource, QUrl( QLatin1String( "status_icon" ) ), s_icons->errorPixmap );
00237
00238
00239 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
00240 if ( cg == QPalette::Normal && !(option.state & QStyle::State_Active) )
00241 cg = QPalette::Inactive;
00242
00243 QColor textColor;
00244 if ( option.state & QStyle::State_Selected ) {
00245 textColor = option.palette.color( cg, QPalette::HighlightedText );
00246 } else {
00247 textColor = option.palette.color( cg, QPalette::Text );
00248 }
00249
00250 QString content = QString::fromLatin1(
00251 "<html style=\"color:%1\">"
00252 "<body>"
00253 "<table>"
00254 "<tr>"
00255 "<td rowspan=\"2\"><img src=\"agent_icon\"> </td>"
00256 "<td><b>%2</b></td>"
00257 "</tr>" ).arg(textColor.name().toUpper()).arg( name )
00258 + QString::fromLatin1(
00259 "<tr>"
00260 "<td><img src=\"status_icon\"/> %1 %2</td>"
00261 "</tr>" ).arg( statusMessage ).arg( status == 1 ? QString( QLatin1String( "(%1%)" ) ).arg( progress ) : QLatin1String( "" ) )
00262 + QLatin1String( "</table></body></html>" );
00263
00264 document->setHtml( content );
00265
00266 return document;
00267 }
00268
00269 void AgentInstanceWidgetDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
00270 {
00271 if ( !index.isValid() )
00272 return;
00273
00274 QTextDocument *doc = document( option, index );
00275 if ( !doc )
00276 return;
00277
00278 painter->setRenderHint( QPainter::Antialiasing );
00279
00280 QPen pen = painter->pen();
00281
00282 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
00283 if ( cg == QPalette::Normal && !(option.state & QStyle::State_Active) )
00284 cg = QPalette::Inactive;
00285
00286 QStyleOptionViewItemV4 opt(option);
00287 opt.showDecorationSelected = true;
00288 QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter );
00289
00290 painter->save();
00291 painter->translate( option.rect.topLeft() );
00292 doc->drawContents( painter );
00293 delete doc;
00294 painter->restore();
00295
00296 painter->setPen(pen);
00297
00298 drawFocus( painter, option, option.rect );
00299 }
00300
00301 QSize AgentInstanceWidgetDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
00302 {
00303 if ( !index.isValid() )
00304 return QSize( 0, 0 );
00305
00306 QTextDocument *doc = document( option, index );
00307 if ( !doc )
00308 return QSize( 0, 0 );
00309
00310 const QSize size = doc->documentLayout()->documentSize().toSize();
00311 delete doc;
00312
00313 return size;
00314 }
00315
00316 void AgentInstanceWidgetDelegate::drawFocus( QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect ) const
00317 {
00318 if ( option.state & QStyle::State_HasFocus ) {
00319 QStyleOptionFocusRect o;
00320 o.QStyleOption::operator=( option );
00321 o.rect = rect;
00322 o.state |= QStyle::State_KeyboardFocusChange;
00323 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled;
00324 o.backgroundColor = option.palette.color( cg, (option.state & QStyle::State_Selected)
00325 ? QPalette::Highlight : QPalette::Background );
00326 QApplication::style()->drawPrimitive( QStyle::PE_FrameFocusRect, &o, painter );
00327 }
00328 }
00329
00330 }
00331
00332 #include "agentinstancewidget.moc"