Oops, don't translate the mimetype, thanks Lukas for the heads up
[kdepim.git] / akonadiconsole / agentwidget.cpp
blob9fc497129cc58097ed7e4286eeb7122899d003da
1 /*
2 This file is part of Akonadi.
4 Copyright (c) 2006 Tobias Koenig <tokoe@kde.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 USA.
22 #include "agentwidget.h"
24 #include <akonadi/agenttypedialog.h>
25 #include <akonadi/agentinstancewidget.h>
26 #include <akonadi/agentmanager.h>
27 #include <akonadi/agentinstancecreatejob.h>
28 #include <akonadi/control.h>
30 #include <KDebug>
31 #include <KLocale>
32 #include <KMessageBox>
33 #include <KStandardGuiItem>
35 #include <QtGui/QGridLayout>
36 #include <QtGui/QMenu>
37 #include <QtGui/QPushButton>
38 #include <QDBusInterface>
39 #include <QDBusMessage>
40 #include <QMetaObject>
41 #include <QMetaMethod>
42 #include <QResizeEvent>
44 using namespace Akonadi;
46 AgentWidget::AgentWidget( QWidget *parent )
47 : QWidget( parent )
49 ui.setupUi( this );
51 connect( ui.instanceWidget, SIGNAL(doubleClicked(Akonadi::AgentInstance)), SLOT(configureAgent()) );
52 connect( ui.instanceWidget, SIGNAL(currentChanged(Akonadi::AgentInstance,Akonadi::AgentInstance)),
53 SLOT(currentChanged(Akonadi::AgentInstance)) );
54 connect( ui.instanceWidget, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showContextMenu(QPoint)) );
56 connect( ui.instanceWidget->view()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection)) );
58 currentChanged( ui.instanceWidget->currentAgentInstance() );
60 ui.addButton->setGuiItem( KStandardGuiItem::add() );
61 connect( ui.addButton, SIGNAL( clicked() ), this, SLOT( addAgent() ) );
63 ui.removeButton->setGuiItem( KStandardGuiItem::remove() );
64 connect( ui.removeButton, SIGNAL( clicked() ), this, SLOT( removeAgent() ) );
66 ui.configButton->setGuiItem( KStandardGuiItem::configure() );
67 connect( ui.configButton, SIGNAL( clicked() ), this, SLOT( configureAgent() ) );
69 mSyncMenu = new QMenu( i18n("Synchronize"), this );
70 mSyncMenu->addAction( i18n("Synchronize All"), this, SLOT(synchronizeAgent()) );
71 mSyncMenu->addAction( i18n("Synchronize Collection Tree"), this, SLOT(synchronizeTree()) );
72 mSyncMenu->setIcon( KIcon("view-refresh" ) );
73 ui.syncButton->setMenu( mSyncMenu );
74 ui.syncButton->setIcon( KIcon( "view-refresh" ) );
75 connect( ui.syncButton, SIGNAL( clicked() ), this, SLOT( synchronizeAgent() ) );
77 ui.abortButton->setIcon( KIcon("dialog-cancel") );
78 connect( ui.abortButton, SIGNAL(clicked()), this, SLOT(abortAgent()) );
79 ui.restartButton->setIcon( KIcon( "system-reboot" ) ); //FIXME: Is using system-reboot icon here a good idea?
80 connect( ui.restartButton, SIGNAL(clicked()), SLOT(restartAgent()) );
82 Control::widgetNeedsAkonadi( this );
85 void AgentWidget::addAgent()
87 Akonadi::AgentTypeDialog dlg( this );
88 if ( dlg.exec() ) {
89 const AgentType agentType = dlg.agentType();
91 if ( agentType.isValid() ) {
92 AgentInstanceCreateJob *job = new AgentInstanceCreateJob( agentType, this );
93 job->configure( this );
94 job->start(); // TODO: check result
99 void AgentWidget::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
101 Q_UNUSED( selected );
102 Q_UNUSED( deselected );
104 const bool multiSelection = ui.instanceWidget->view()->selectionModel()->selectedRows().size() > 1;
105 // Only agent removal, sync and restart is possible when multiple items are selected.
106 ui.configButton->setDisabled( multiSelection );
110 void AgentWidget::removeAgent()
112 QList<AgentInstance> list = ui.instanceWidget->selectedAgentInstances();
113 if ( !list.isEmpty() )
115 if ( KMessageBox::questionYesNo( this,
116 i18np( "Do you really want to delete the selected agent instance?",
117 "Do you really want to delete these %1 agent instances?",
118 list.size() ),
119 i18n( "Multiple Agent Deletion" ),
120 KStandardGuiItem::del(),
121 KStandardGuiItem::cancel(),
122 QString(),
123 KMessageBox::Dangerous )
124 == KMessageBox::Yes )
126 foreach( const AgentInstance &agent, list )
127 AgentManager::self()->removeInstance( agent );
132 void AgentWidget::configureAgent()
134 AgentInstance agent = ui.instanceWidget->currentAgentInstance();
135 if ( agent.isValid() )
136 agent.configure( this );
139 void AgentWidget::synchronizeAgent()
141 QList<AgentInstance> list = ui.instanceWidget->selectedAgentInstances();
142 if ( !list.isEmpty() )
143 foreach( AgentInstance agent, list )
144 agent.synchronize();
147 void AgentWidget::toggleOnline()
149 AgentInstance agent = ui.instanceWidget->currentAgentInstance();
150 if ( agent.isValid() )
151 agent.setIsOnline( !agent.isOnline() );
154 void AgentWidget::synchronizeTree()
156 QList<AgentInstance> list = ui.instanceWidget->selectedAgentInstances();
157 if ( !list.isEmpty() )
158 foreach( AgentInstance agent, list )
159 agent.synchronizeCollectionTree();
162 void AgentWidget::abortAgent()
164 QList<AgentInstance> list = ui.instanceWidget->selectedAgentInstances();
165 if ( !list.isEmpty() )
166 foreach( AgentInstance agent, list )
167 agent.abortCurrentTask();
170 void AgentWidget::restartAgent()
172 AgentInstance agent = ui.instanceWidget->currentAgentInstance();
173 if ( agent.isValid() )
174 agent.restart();
177 void AgentWidget::cloneAgent()
179 mCloneSource = ui.instanceWidget->currentAgentInstance();
180 if ( !mCloneSource.isValid() )
181 return;
182 const AgentType agentType = mCloneSource.type();
183 if ( agentType.isValid() ) {
184 AgentInstanceCreateJob *job = new AgentInstanceCreateJob( agentType, this );
185 connect( job, SIGNAL(result(KJob*)), SLOT(cloneAgent(KJob*)) );
186 job->start();
187 } else {
188 kWarning() << "WTF?";
192 void AgentWidget::cloneAgent( KJob* job )
194 if ( job->error() ) {
195 KMessageBox::error( this, i18n("Cloneing agent failed: %1.", job->errorText() ) );
196 return;
199 AgentInstance cloneTarget = static_cast<AgentInstanceCreateJob*>( job )->instance();
200 Q_ASSERT( cloneTarget.isValid() );
201 Q_ASSERT( mCloneSource.isValid() );
203 QDBusInterface sourceIface( QString::fromLatin1("org.freedesktop.Akonadi.Agent.%1").arg( mCloneSource.identifier() ),
204 "/Settings" );
205 if ( !sourceIface.isValid() ) {
206 kError() << "Unable to obtain KConfigXT D-Bus interface of source agent" << mCloneSource.identifier();
207 return;
210 QDBusInterface targetIface( QString::fromLatin1("org.freedesktop.Akonadi.Agent.%1").arg( cloneTarget.identifier() ),
211 "/Settings" );
212 if ( !targetIface.isValid() ) {
213 kError() << "Unable to obtain KConfigXT D-Bus interface of target agent" << cloneTarget.identifier();
214 return;
217 cloneTarget.setName( mCloneSource.name() + " (Clone)" );
219 // iterate over all getter methods in the source interface and call the
220 // corresponding setter in the target interface
221 for ( int i = 0; i < sourceIface.metaObject()->methodCount(); ++i ) {
222 const QMetaMethod method = sourceIface.metaObject()->method( i );
223 if ( QByteArray( method.typeName() ).isEmpty() ) // returns void
224 continue;
225 const QByteArray signature( method.signature() );
226 if ( signature.isEmpty() )
227 continue;
228 if ( signature.startsWith( "set" ) || !signature.contains( "()" ) ) // setter or takes parameters // krazy:exclude=strings
229 continue;
230 if ( signature.startsWith( "Introspect" ) ) // D-Bus stuff // krazy:exclude=strings
231 continue;
232 const QString methodName = QString::fromLatin1( signature.left( signature.indexOf( '(' ) ) );
233 const QDBusMessage reply = sourceIface.call( methodName );
234 if ( !reply.arguments().count() == 1 ) {
235 kError() << "call to method" << signature << "failed: " << reply.arguments() << reply.errorMessage();
236 continue;
238 const QString setterName = QLatin1String("set") + methodName.at( 0 ).toUpper() + methodName.mid( 1 );
239 targetIface.call( setterName, reply.arguments().at( 0 ) );
242 cloneTarget.reconfigure();
245 void AgentWidget::currentChanged(const Akonadi::AgentInstance& instance)
247 ui.removeButton->setEnabled( instance.isValid() );
248 ui.configButton->setEnabled( instance.isValid() );
249 ui.syncButton->setEnabled( instance.isValid() );
250 ui.restartButton->setEnabled( instance.isValid() );
252 if ( instance.isValid() ) {
253 ui.identifierLabel->setText( instance.identifier() );
254 ui.typeLabel->setText( instance.type().name() );
255 QString onlineStatus = ( instance.isOnline() ? i18n( "Online" ) : i18n( "Offline" ) );
256 QString agentStatus;
257 switch( instance.status() ) {
258 case AgentInstance::Idle: agentStatus = i18n( "Idle" ); break;
259 case AgentInstance::Running: agentStatus = i18n( "Running (%1%)", instance.progress() ); break;
260 case AgentInstance::Broken: agentStatus = i18n( "Broken" ); break;
262 ui.statusLabel->setText( i18nc( "Two statuses, for example \"Online, Running (66%)\" or \"Offline, Broken\"",
263 "%1, %2", onlineStatus, agentStatus ) );
264 ui.statusMessageLabel->setText( instance.statusMessage() );
265 ui.capabilitiesLabel->setText( instance.type().capabilities().join( ", " ) );
266 ui.mimeTypeLabel->setText( instance.type().mimeTypes().join( ", " ) );
267 } else {
268 ui.identifierLabel->setText( QString() );
269 ui.typeLabel->setText( QString() );
270 ui.statusLabel->setText( QString() );
271 ui.capabilitiesLabel->setText( QString() );
272 ui.mimeTypeLabel->setText( QString() );
276 void AgentWidget::showContextMenu(const QPoint& pos)
278 QMenu menu( this );
279 menu.addAction( KIcon("list-add"), i18n("Add Agent..."), this, SLOT(addAgent()) );
280 menu.addAction( KIcon("edit-copy"), i18n("Clone Agent"), this, SLOT(cloneAgent()) );
281 menu.addSeparator();
282 menu.addMenu( mSyncMenu );
283 menu.addAction( KIcon("dialog-cancel"), i18n("Abort Activity"), this, SLOT(abortAgent()) );
284 menu.addAction( KIcon("system-reboot"), i18n("Restart Agent"), this, SLOT(restartAgent()) ); //FIXME: Is using system-reboot icon here a good idea?
285 menu.addAction( KIcon("network-disconnect"), i18n("Toggle Online/Offline"), this, SLOT(toggleOnline()) );
286 menu.addAction( KIcon("configure"), i18n("Configure..."), this, SLOT(configureAgent()) );
287 menu.addAction( KIcon("list-remove"), i18n("Remove Agent"), this, SLOT(removeAgent()) );
288 menu.exec( mapToGlobal( pos ) );
291 void AgentWidget::resizeEvent( QResizeEvent *event )
293 ui.detailsBox->setVisible( event->size().height() > 400 );
296 #include "agentwidget.moc"