1/***************************************************************************
2 * Copyright (C) 2009 by Ben Cooksley <ben@eclipse.endoftheinternet.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *
18 ***************************************************************************/
19
20#include "SolidActions.h"
21#include "ActionItem.h"
22
23#include <KUrl>
24#include <KDialog>
25#include <KAboutData>
26#include <KMessageBox>
27#include <KDesktopFile>
28#include <KIO/NetAccess>
29#include <KStandardDirs>
30#include <KPluginFactory>
31#include <KBuildSycocaProgressDialog>
32
33#include <QComboBox>
34#include <QPushButton>
35
36#include <Solid/DeviceInterface>
37#include <Solid/Predicate>
38
39K_PLUGIN_FACTORY( SolidActionsFactory, registerPlugin<SolidActions>(); )
40K_EXPORT_PLUGIN( SolidActionsFactory("kcmsolidactions", "kcm_solid_actions") )
41
42SolidActions::SolidActions(QWidget* parent, const QVariantList&)
43 : KCModule(SolidActionsFactory::componentData(), parent)
44{
45 KAboutData * about = new KAboutData("Device Actions", 0, ki18n("Solid Device Actions Editor"), "1.1",
46 ki18n("Solid Device Actions Control Panel Module"),
47 KAboutData::License_GPL,
48 ki18n("(c) 2009 Solid Device Actions team"));
49 about->addAuthor(ki18n("Ben Cooksley"), ki18n("Maintainer"), "ben@eclipse.endoftheinternet.org");
50 setAboutData(about);
51 setButtons(KCModule::Help);
52
53 // Prepare main display dialog
54 actionModel = new ActionModel( this );
55 mainUi.setupUi( this );
56 mainUi.TvActions->setModel( actionModel );
57 mainUi.TvActions->setHeaderHidden( true );
58 mainUi.TvActions->setRootIsDecorated( false );
59 mainUi.TvActions->setSelectionMode( QAbstractItemView::SingleSelection );
60 mainUi.PbAddAction->setGuiItem( KStandardGuiItem::add() );
61 mainUi.PbEditAction->setIcon( KIcon("document-edit") );
62
63 connect( mainUi.PbAddAction, SIGNAL(clicked()), this, SLOT(slotShowAddDialog()) );
64 connect( mainUi.PbEditAction, SIGNAL(clicked()), this, SLOT(editAction()) );
65 connect( mainUi.PbDeleteAction, SIGNAL(clicked()), this, SLOT(deleteAction()) );
66 connect( mainUi.TvActions->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(toggleEditDelete()) );
67 connect( mainUi.TvActions, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(editAction()) );
68
69 // Prepare + connect up with Edit dialog
70 editUi = new ActionEditor(this);
71 connect( editUi, SIGNAL(accepted()), this, SLOT(acceptActionChanges()) );
72
73 // Prepare + connect up add action dialog
74 addDialog = new KDialog(this);
75 addUi.setupUi( addDialog->mainWidget() );
76 addDialog->setInitialSize( QSize(300, 100) ); // Set a sensible default size
77
78 slotTextChanged( addUi.LeActionName->text() );
79 connect( addUi.LeActionName, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)) );
80 connect( addDialog, SIGNAL(okClicked()), this, SLOT(addAction()) );
81}
82
83SolidActions::~SolidActions()
84{
85 delete editUi;
86 delete actionModel;
87}
88
89void SolidActions::slotShowAddDialog()
90{
91 addDialog->show();
92 addUi.LeActionName->setFocus();
93 addUi.LeActionName->clear();
94}
95
96void SolidActions::slotTextChanged( const QString & text )
97{
98 addDialog->enableButtonOk( !text.isEmpty() );
99}
100
101void SolidActions::load()
102{
103 fillActionsList();
104}
105
106void SolidActions::defaults()
107{
108}
109
110void SolidActions::save()
111{
112}
113
114void SolidActions::addAction()
115{
116 QString enteredName = addUi.LeActionName->text();
117 KDesktopFile templateDesktop(KStandardDirs::locate("data", "kcmsolidactions/solid-action-template.desktop")); // Lets get the template
118
119 // Lets get a desktop file
120 QString internalName = enteredName; // copy the name the user entered -> we will be making mods
121 internalName.replace(QChar(' '), QChar('-'), Qt::CaseSensitive); // replace spaces with dashes
122 QString filePath = KStandardDirs::locateLocal("data", 0); // Get the location on disk for "data"
123 filePath = filePath + "solid/actions/" + internalName + ".desktop"; // Create a file path for new action
124
125 // Fill in an initial template
126 KDesktopFile * newDesktop = templateDesktop.copyTo(filePath);
127 newDesktop->actionGroup("open").writeEntry("Name", enteredName); // ditto
128 delete newDesktop; // Force file to be written
129
130 // Prepare to open the editDialog
131 fillActionsList();
132 QList<ActionItem*> actionList = actionModel->actionList();
133 QModelIndex newAction;
134 foreach( ActionItem * newItem, actionList ) { // Lets find our new action
135 if( newItem->desktopMasterPath == filePath ) {
136 int position = actionList.indexOf( newItem );
137 newAction = actionModel->index( position, 0, QModelIndex() ); // Grab it
138 break;
139 }
140 }
141
142 mainUi.TvActions->setCurrentIndex( newAction ); // Set it as currently active
143 editAction(); // Open the edit dialog
144}
145
146void SolidActions::editAction()
147{
148 ActionItem * selectedItem = selectedAction();
149 if( !selectedItem ) {
150 return;
151 }
152
153 // We should error out here if we have to
154 if( !selectedItem->predicate().isValid() ) {
155 KMessageBox::error(this, i18n("It appears that the predicate for this action is not valid."), i18n("Error Parsing Device Conditions"));
156 return;
157 }
158
159 // Display us!
160 editUi->setActionToEdit( selectedItem );
161 editUi->setWindowIcon( windowIcon() );
162 editUi->show();
163}
164
165void SolidActions::deleteAction()
166{
167 ActionItem * action = selectedAction();
168 if( action->isUserSupplied() ) { // Is the action user supplied?
169 KIO::NetAccess::del( KUrl(action->desktopMasterPath), this); // Remove the main desktop file then
170 }
171 KIO::NetAccess::del( KUrl(action->desktopWritePath), this); // Remove the modified desktop file now
172 fillActionsList(); // Update the list of actions
173}
174
175ActionItem * SolidActions::selectedAction()
176{
177 QModelIndex action = mainUi.TvActions->currentIndex();
178 ActionItem * actionItem = actionModel->data( action, Qt::UserRole ).value<ActionItem*>();
179 return actionItem;
180}
181
182void SolidActions::fillActionsList()
183{
184 mainUi.TvActions->selectionModel()->clearSelection();
185 actionModel->buildActionList();
186 mainUi.TvActions->header()->setResizeMode( 0, QHeaderView::Stretch );
187 mainUi.TvActions->header()->setResizeMode( 1, QHeaderView::ResizeToContents );
188 toggleEditDelete();
189}
190
191void SolidActions::acceptActionChanges()
192{
193 // Re-read the actions list to ensure changes are reflected
194 KBuildSycocaProgressDialog::rebuildKSycoca(this);
195 fillActionsList();
196}
197
198void SolidActions::toggleEditDelete()
199{
200 bool toggle = true;
201
202 if( !mainUi.TvActions->currentIndex().isValid() ) { // Is an action selected?
203 mainUi.PbDeleteAction->setText( i18n("No Action Selected") ); // Set a friendly disabled text
204 mainUi.PbDeleteAction->setIcon( KIcon() );
205 toggle = false;
206 }
207
208 mainUi.PbEditAction->setEnabled(toggle); // Change them to the new state
209 mainUi.PbDeleteAction->setEnabled(toggle); // Ditto
210
211 if( !toggle ) {
212 return;
213 }
214
215 KUrl writeDesktopFile( selectedAction()->desktopWritePath ); // Get the write desktop file
216 // What functionality do we need to change?
217 if( selectedAction()->isUserSupplied() ) {
218 // We are able to directly delete it, enable full delete functionality
219 mainUi.PbDeleteAction->setGuiItem( KStandardGuiItem::remove() );
220 } else if( KIO::NetAccess::exists(writeDesktopFile, KIO::NetAccess::SourceSide, this) ) { // Does the write file exist?
221 // We are able to revert, lets show it
222 mainUi.PbDeleteAction->setGuiItem( KStandardGuiItem::discard() );
223 } else {
224 // We cannot do anything then, disable delete functionality
225 mainUi.PbDeleteAction->setText( i18n("Cannot be deleted") );
226 mainUi.PbDeleteAction->setIcon( KIcon() );
227 mainUi.PbDeleteAction->setEnabled( false );
228 }
229}
230
231#include "SolidActions.moc"
232