Kross
view.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 * view.cpp 00003 * This file is part of the KDE project 00004 * copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> 00005 * copyright (C) 2006-2007 Sebastian Sauer <mail@dipe.org> 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this program; see the file COPYING. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 ***************************************************************************/ 00020 00021 #include "view.h" 00022 #include "model.h" 00023 00024 #include <kross/core/manager.h> 00025 #include <kross/core/action.h> 00026 #include <kross/core/actioncollection.h> 00027 #include <kross/core/interpreter.h> 00028 00029 #include <QtCore/QFileInfo> 00030 #include <QtCore/QDir> 00031 #include <QtGui/QBoxLayout> 00032 #include <QtGui/QHeaderView> 00033 #include <QtGui/QTreeView> 00034 #include <QtGui/QLabel> 00035 00036 #include <kapplication.h> 00037 //#include <kdeversion.h> 00038 #include <kconfig.h> 00039 #include <kstandarddirs.h> 00040 #include <kmessagebox.h> 00041 #include <kpushbutton.h> 00042 #include <kfiledialog.h> 00043 #include <kmenu.h> 00044 #include <kpagedialog.h> 00045 #include <kaction.h> 00046 #include <kactioncollection.h> 00047 #include <kcombobox.h> 00048 #include <kicondialog.h> 00049 #include <klocale.h> 00050 #include <klineedit.h> 00051 #include <kurlrequester.h> 00052 00053 //#include <ktar.h> 00054 //#include <kio/netaccess.h> 00055 00056 using namespace Kross; 00057 00058 /********************************************************************************* 00059 * ActionCollectionEditor 00060 */ 00061 00062 namespace Kross { 00063 00065 class ActionCollectionEditor::Private 00066 { 00067 public: 00068 enum Type { ActionType, CollectionType }; 00069 const Type type; 00070 union { 00071 Action* action; 00072 ActionCollection* collection; 00073 }; 00074 00075 QString name() const { 00076 return type == ActionType ? action->name() : collection->name(); 00077 } 00078 QString text() const { 00079 return type == ActionType ? action->text() : collection->text(); 00080 } 00081 QString description() const { 00082 return type == ActionType ? action->description() : collection->description(); 00083 } 00084 QString iconName() const { 00085 return type == ActionType ? action->iconName() : collection->iconName(); 00086 } 00087 bool isEnabled() const { 00088 return type == ActionType ? action->isEnabled() : collection->isEnabled(); 00089 } 00090 00091 KLineEdit* nameedit; 00092 KLineEdit* textedit; 00093 KLineEdit* commentedit; 00094 KLineEdit* iconedit; 00095 KComboBox* interpreteredit; 00096 KUrlRequester* fileedit; 00097 //QCheckBox* enabledcheckbox; 00098 00099 explicit Private(Action* a) : type(ActionType), action(a) { Q_ASSERT(a); } 00100 explicit Private(ActionCollection* c) : type(CollectionType), collection(c) { Q_ASSERT(c); } 00101 }; 00102 00103 } 00104 00105 ActionCollectionEditor::ActionCollectionEditor(Action* action, QWidget* parent) 00106 : QWidget(parent), d(new Private(action)) 00107 { 00108 initGui(); 00109 } 00110 00111 ActionCollectionEditor::ActionCollectionEditor(ActionCollection* collection, QWidget* parent) 00112 : QWidget(parent), d(new Private(collection)) 00113 { 00114 initGui(); 00115 } 00116 00117 ActionCollectionEditor::~ActionCollectionEditor() 00118 { 00119 delete d; 00120 } 00121 00122 Action* ActionCollectionEditor::action() const 00123 { 00124 return d->type == Private::ActionType ? d->action : 0; 00125 } 00126 00127 ActionCollection* ActionCollectionEditor::collection() const 00128 { 00129 return d->type == Private::CollectionType ? d->collection : 0; 00130 } 00131 00132 QLineEdit* ActionCollectionEditor::nameEdit() const { return d->nameedit; } 00133 QLineEdit* ActionCollectionEditor::textEdit() const { return d->textedit; } 00134 QLineEdit* ActionCollectionEditor::commentEdit() const { return d->commentedit; } 00135 QLineEdit* ActionCollectionEditor::iconEdit() const { return d->iconedit; } 00136 QComboBox* ActionCollectionEditor::interpreterEdit() const { return d->interpreteredit; } 00137 KUrlRequester* ActionCollectionEditor::fileEdit() const { return d->fileedit; } 00138 00139 void ActionCollectionEditor::initGui() 00140 { 00141 QVBoxLayout* mainlayout = new QVBoxLayout(); 00142 setLayout(mainlayout); 00143 00144 QWidget* w = new QWidget(this); 00145 mainlayout->addWidget(w); 00146 QGridLayout* gridlayout = new QGridLayout(); 00147 gridlayout->setMargin(0); 00148 //gridlayout->setSpacing(0); 00149 w->setLayout(gridlayout); 00150 00151 QLabel* namelabel = new QLabel(i18n("Name:"), w); 00152 gridlayout->addWidget(namelabel, 0, 0); 00153 d->nameedit = new KLineEdit(w); 00154 namelabel->setBuddy(d->nameedit); 00155 d->nameedit->setText( d->name() ); 00156 d->nameedit->setEnabled(false); 00157 gridlayout->addWidget(d->nameedit, 0, 1); 00158 00159 QLabel* textlabel = new QLabel(i18n("Text:"), w); 00160 gridlayout->addWidget(textlabel, 1, 0); 00161 d->textedit = new KLineEdit(w); 00162 textlabel->setBuddy(d->textedit); 00163 d->textedit->setText( d->text() ); 00164 gridlayout->addWidget(d->textedit, 1, 1); 00165 00166 QLabel* commentlabel = new QLabel(i18n("Comment:"), w); 00167 gridlayout->addWidget(commentlabel, 2, 0); 00168 d->commentedit = new KLineEdit(w); 00169 commentlabel->setBuddy(d->commentedit); 00170 d->commentedit->setText( d->description() ); 00171 gridlayout->addWidget(d->commentedit, 2, 1); 00172 00173 QLabel* iconlabel = new QLabel(i18n("Icon:"), w); 00174 gridlayout->addWidget(iconlabel, 3, 0); 00175 QWidget* iconbox = new QWidget(w); 00176 QHBoxLayout* iconlayout = new QHBoxLayout(); 00177 iconlayout->setMargin(0); 00178 iconbox->setLayout(iconlayout); 00179 d->iconedit = new KLineEdit(iconbox); 00180 iconlabel->setBuddy(d->iconedit); 00181 d->iconedit->setText( d->iconName() ); 00182 iconlayout->addWidget(d->iconedit, 1); 00183 KIconButton* iconbutton = new KIconButton(iconbox); 00184 iconbutton->setIcon( d->iconName() ); 00185 connect(iconbutton, SIGNAL(iconChanged(QString)), d->iconedit, SLOT(setText(QString))); 00186 iconlayout->addWidget(iconbutton); 00187 gridlayout->addWidget(iconbox, 3, 1); 00188 00189 //QFrame* hr1 = new QFrame(w); 00190 //hr1->setFrameStyle(QFrame::HLine | QFrame::Sunken); 00191 //gridlayout->addWidget(hr1, 4, 0, -1, -1, Qt::AlignVCenter); 00192 00193 if( d->type == Private::ActionType ) { 00194 QLabel* interpreterlabel = new QLabel(i18n("Interpreter:"), w); 00195 gridlayout->addWidget(interpreterlabel, 4, 0); 00196 d->interpreteredit = new KComboBox(w); 00197 interpreterlabel->setBuddy(d->interpreteredit); 00198 d->interpreteredit->setMaxVisibleItems(10); 00199 d->interpreteredit->insertItems(0, Manager::self().interpreters()); 00200 d->interpreteredit->setEditable(true); 00201 //c->lineEdit()->setText( d->action->interpreter() ); 00202 int idx = Manager::self().interpreters().indexOf( d->action->interpreter() ); 00203 if( idx >= 0 ) 00204 d->interpreteredit->setCurrentIndex(idx); 00205 else 00206 d->interpreteredit->setEditText( d->action->interpreter() ); 00207 gridlayout->addWidget(d->interpreteredit, 4, 1); 00208 00209 QLabel* filelabel = new QLabel(i18n("File:"), w); 00210 gridlayout->addWidget(filelabel, 5, 0); 00211 d->fileedit = new KUrlRequester(w); 00212 filelabel->setBuddy(d->fileedit); 00213 QStringList mimetypes; 00214 foreach(const QString &interpretername, Manager::self().interpreters()) { 00215 InterpreterInfo* info = Manager::self().interpreterInfo(interpretername); 00216 Q_ASSERT( info ); 00217 mimetypes.append( info->mimeTypes().join(" ").trimmed() ); 00218 } 00219 //InterpreterInfo* info = Manager::self().interpreterInfo( Manager::self().interpreternameForFile( d->action->file() ) ); 00220 //const QString defaultmime = info ? info->mimeTypes().join(" ").trimmed() : QString(); 00221 d->fileedit->fileDialog()->setMimeFilter(mimetypes /*, defaultmime*/); 00222 d->fileedit->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ); 00223 d->fileedit->setUrl(KUrl(d->action->file()) ); 00224 gridlayout->addWidget(d->fileedit, 5, 1); 00225 } 00226 else { 00227 d->interpreteredit = 0; 00228 d->fileedit = 0; 00229 } 00230 00231 //d->enabledcheckbox = new QCheckBox(this); 00232 //d->enabledcheckbox->setText( i18n("Enabled") ); 00233 //d->enabledcheckbox->setChecked( d->isEnabled() ); 00234 //mainlayout->addWidget(d->enabledcheckbox); 00235 00236 mainlayout->addStretch(1); 00237 } 00238 00239 bool ActionCollectionEditor::isValid() 00240 { 00241 //TODO check also if such a name already exist. 00242 return ! d->nameedit->text().isEmpty(); 00243 } 00244 00245 void ActionCollectionEditor::commit() 00246 { 00247 switch( d->type ) { 00248 case Private::ActionType: { 00249 d->action->setText( d->textedit->text() ); 00250 d->action->setDescription( d->commentedit->text() ); 00251 d->action->setIconName( d->iconedit->text() ); 00252 d->action->setInterpreter( d->interpreteredit->currentText() ); 00253 d->action->setFile( d->fileedit->url().path() ); 00254 //d->action->setEnabled( d->enabledcheckbox->isChecked() ); 00255 } break; 00256 case Private::CollectionType: { 00257 d->collection->setText( d->textedit->text() ); 00258 d->collection->setDescription( d->commentedit->text() ); 00259 d->collection->setIconName( d->iconedit->text() ); 00260 //d->collection->setEnabled( d->enabledcheckbox->isChecked() ); 00261 } break; 00262 default: break; 00263 } 00264 } 00265 00266 /********************************************************************************* 00267 * ActionCollectionView 00268 */ 00269 00270 namespace Kross { 00271 00273 class ActionCollectionView::Private 00274 { 00275 public: 00276 bool modified; 00277 KActionCollection* collection; 00278 QMap< QString, KPushButton* > buttons; 00279 explicit Private() : modified(false) {} 00280 }; 00281 00282 } 00283 00284 ActionCollectionView::ActionCollectionView(QWidget* parent) 00285 : QTreeView(parent) 00286 , d(new Private()) 00287 { 00288 header()->hide(); 00289 setSelectionMode(QAbstractItemView::SingleSelection); 00290 setAlternatingRowColors(true); 00291 setRootIsDecorated(true); 00292 setSortingEnabled(false); 00293 setItemsExpandable(true); 00294 //setDragEnabled(true); 00295 //setAcceptDrops(true); 00296 setDropIndicatorShown(true); 00297 setDragDropMode(QAbstractItemView::InternalMove); 00298 00299 d->collection = new KActionCollection(this); 00300 00301 KAction* runaction = new KAction(KIcon("system-run"), i18n("Run"), this); 00302 runaction->setObjectName("run"); 00303 runaction->setToolTip( i18n("Execute the selected script.") ); 00304 runaction->setEnabled(false); 00305 d->collection->addAction("run", runaction); 00306 connect(runaction, SIGNAL(triggered()), this, SLOT(slotRun())); 00307 00308 KAction* stopaction = new KAction(KIcon("process-stop"), i18n("Stop"), this); 00309 stopaction->setObjectName("stop"); 00310 stopaction->setToolTip( i18n("Stop execution of the selected script.") ); 00311 stopaction->setEnabled(false); 00312 d->collection->addAction("stop", stopaction); 00313 connect(stopaction, SIGNAL(triggered()), this, SLOT(slotStop())); 00314 00315 KAction* editaction = new KAction(KIcon("document-properties"), i18n("Edit..."), this); 00316 editaction->setObjectName("edit"); 00317 editaction->setToolTip( i18n("Edit selected script.") ); 00318 editaction->setEnabled(false); 00319 d->collection->addAction("edit", editaction); 00320 connect(editaction, SIGNAL(triggered()), this, SLOT(slotEdit())); 00321 00322 KAction* addaction = new KAction(KIcon("list-add"), i18n("Add..."), this); 00323 addaction->setObjectName("add"); 00324 addaction->setToolTip( i18n("Add a new script.") ); 00325 //addaction->setEnabled(false); 00326 d->collection->addAction("add", addaction); 00327 connect(addaction, SIGNAL(triggered()), this, SLOT(slotAdd()) ); 00328 00329 KAction* removeaction = new KAction(KIcon("list-remove"), i18n("Remove"), this); 00330 removeaction->setObjectName("remove"); 00331 removeaction->setToolTip( i18n("Remove selected script.") ); 00332 removeaction->setEnabled(false); 00333 d->collection->addAction("remove", removeaction); 00334 connect(removeaction, SIGNAL(triggered()), this, SLOT(slotRemove()) ); 00335 00336 connect(this, SIGNAL(enabledChanged(const QString&)), this, SLOT(slotEnabledChanged(const QString&))); 00337 //expandAll(); 00338 } 00339 00340 ActionCollectionView::~ActionCollectionView() 00341 { 00342 delete d; 00343 } 00344 00345 void ActionCollectionView::setModel(QAbstractItemModel* m) 00346 { 00347 QTreeView::setModel(m); 00348 d->modified = false; 00349 00350 QItemSelectionModel* selectionmodel = new QItemSelectionModel(m, this); 00351 setSelectionModel(selectionmodel); 00352 00353 connect(selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), 00354 this, SLOT(slotSelectionChanged())); 00355 connect(m, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)), 00356 this, SLOT(slotDataChanged(const QModelIndex&,const QModelIndex&))); 00357 } 00358 00359 bool ActionCollectionView::isModified() const 00360 { 00361 return d->modified; 00362 } 00363 00364 void ActionCollectionView::setModified(bool modified) 00365 { 00366 d->modified = modified; 00367 } 00368 00369 KActionCollection* ActionCollectionView::actionCollection() const 00370 { 00371 return d->collection; 00372 } 00373 00374 KPushButton* ActionCollectionView::button(const QString& actionname) const 00375 { 00376 return d->buttons.contains(actionname) ? d->buttons[actionname] : 0; 00377 } 00378 00379 QItemSelection ActionCollectionView::itemSelection() const 00380 { 00381 QAbstractProxyModel* proxymodel = dynamic_cast< QAbstractProxyModel* >( model() ); 00382 QItemSelection selection = selectionModel()->selection(); 00383 return proxymodel ? proxymodel->mapSelectionToSource(selection) : selection; 00384 } 00385 00386 KPushButton* ActionCollectionView::createButton(QWidget* parentWidget, const QString& actionname) 00387 { 00388 QAction* action = d->collection->action(actionname); 00389 if( ! action ) return 0; 00390 //if( d->buttons.contains(actionname) ) delete d->buttons[]; 00391 KPushButton* btn = new KPushButton(parentWidget); 00392 btn->setText( action->text() ); 00393 btn->setToolTip( action->toolTip() ); 00394 btn->setIcon( KIcon(action->icon()) ); 00395 btn->setEnabled( action->isEnabled() ); 00396 if( parentWidget && parentWidget->layout() ) 00397 parentWidget->layout()->addWidget(btn); 00398 QObject::connect(btn, SIGNAL(clicked()), action, SLOT(trigger())); 00399 d->buttons.insert( actionname, btn ); 00400 return btn; 00401 } 00402 00403 void ActionCollectionView::slotEnabledChanged(const QString& actionname) 00404 { 00405 if( d->buttons.contains( actionname ) ) { 00406 QAction* action = d->collection->action( actionname ); 00407 d->buttons[ actionname ]->setEnabled( action ? action->isEnabled() : false ); 00408 } 00409 } 00410 00411 void ActionCollectionView::slotSelectionChanged() 00412 { 00413 bool startenabled = selectionModel()->hasSelection(); 00414 bool stopenabled = false; 00415 bool hasselection = selectionModel()->selectedIndexes().count() > 0; 00416 foreach(const QModelIndex &index, itemSelection().indexes()) { 00417 Action* action = ActionCollectionModel::action(index); 00418 if( startenabled && ! action ) 00419 startenabled = false; 00420 if( ! stopenabled ) 00421 stopenabled = (action && ! action->isFinalized()); 00422 } 00423 QAction* runaction = d->collection->action("run"); 00424 if( runaction ) { 00425 runaction->setEnabled(startenabled); 00426 emit enabledChanged("run"); 00427 } 00428 QAction* stopaction = d->collection->action("stop"); 00429 if( stopaction ) { 00430 stopaction->setEnabled(stopenabled); 00431 emit enabledChanged("stop"); 00432 } 00433 QAction* editaction = d->collection->action("edit"); 00434 if( editaction ) { 00435 editaction->setEnabled(hasselection); 00436 emit enabledChanged("edit"); 00437 } 00438 QAction* removeaction = d->collection->action("remove"); 00439 if( removeaction ) { 00440 removeaction->setEnabled(hasselection); 00441 emit enabledChanged("remove"); 00442 } 00443 } 00444 00445 void ActionCollectionView::slotDataChanged(const QModelIndex&, const QModelIndex&) 00446 { 00447 d->modified = true; 00448 } 00449 00450 void ActionCollectionView::slotRun() 00451 { 00452 if( ! selectionModel() ) return; 00453 QAction* stopaction = d->collection->action("stop"); 00454 00455 foreach(const QModelIndex &index, itemSelection().indexes()) { 00456 if( ! index.isValid() ) 00457 continue; 00458 if( stopaction ) { 00459 stopaction->setEnabled(true); 00460 emit enabledChanged("stop"); 00461 } 00462 Action* action = ActionCollectionModel::action(index); 00463 if( ! action ) 00464 continue; 00465 connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged())); 00466 action->trigger(); 00467 } 00468 slotSelectionChanged(); 00469 } 00470 00471 void ActionCollectionView::slotStop() 00472 { 00473 if( ! selectionModel() ) return; 00474 foreach(const QModelIndex &index, itemSelection().indexes()) { 00475 if( ! index.isValid() ) 00476 continue; 00477 Action* action = ActionCollectionModel::action(index); 00478 if( ! action ) 00479 continue; 00480 //connect(action, SIGNAL(started(Kross::Action*)), SLOT(slotSelectionChanged())); 00481 //connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged())); 00482 action->finalize(); 00483 } 00484 slotSelectionChanged(); 00485 } 00486 00487 void ActionCollectionView::slotEdit() 00488 { 00489 if( ! selectionModel() ) return; 00490 Action* action = 0; 00491 ActionCollection* collection = 0; 00492 foreach(const QModelIndex &index, itemSelection().indexes()) { 00493 if( ! index.isValid() ) continue; 00494 if( Action* a = ActionCollectionModel::action(index) ) 00495 action = a; 00496 else if( ActionCollection* c = ActionCollectionModel::collection(index) ) 00497 collection = c; 00498 else 00499 continue; 00500 break; 00501 } 00502 if( (! action) && (! collection) ) return; 00503 KPageDialog* dialog = new KPageDialog( this ); 00504 dialog->setCaption( i18n("Edit") ); 00505 dialog->setButtons( KDialog::Ok | KDialog::Cancel ); 00506 //dialog->enableButtonOk( false ); 00507 dialog->setFaceType( KPageDialog::Plain ); //Auto Plain List Tree Tabbed 00508 ActionCollectionEditor* editor = 00509 action ? new ActionCollectionEditor(action, dialog->mainWidget()) 00510 : new ActionCollectionEditor(collection, dialog->mainWidget()); 00511 dialog->addPage(editor, i18nc("@title:group Script properties", "General")); 00512 //dialog->addPage(new QWidget(this), i18n("Security")); 00513 dialog->resize( QSize(580, 200).expandedTo( dialog->minimumSizeHint() ) ); 00514 int result = dialog->exec(); 00515 if( result == QDialog::Accepted /*&& dialog->result() == KDialog::Ok*/ ) { 00516 editor->commit(); 00517 } 00518 dialog->delayedDestruct(); 00519 } 00520 00521 void ActionCollectionView::slotAdd() 00522 { 00523 00524 //TODO 00525 KMessageBox::sorry(0, "TODO"); 00526 00527 //ScriptManagerAddWizard wizard(this, collection); 00528 //int result = wizard.exec(); 00529 00530 #if 0 00531 if( ! selectionModel() ) return; 00532 ActionCollection* collection = 0; 00533 foreach(QModelIndex index, itemSelection().indexes()) { 00534 if( ! index.isValid() ) continue; 00535 if( ActionCollectionModel::action(index) ) { 00536 //TODO propably add the item right after the current selected one? 00537 QModelIndex parent = index; 00538 while( parent.isValid() && ! collection ) { 00539 parent = d->view->model()->parent(parent); 00540 collection = ActionCollectionModel::collection(parent); 00541 } 00542 if( collection ) break; // job done 00543 } 00544 else if( ActionCollection* c = ActionCollectionModel::collection(index) ) { 00545 collection = c; 00546 break; // job done 00547 } 00548 } 00549 ScriptManagerAddWizard wizard(this, collection); 00550 int result = wizard.exec(); 00551 Q_UNUSED(result); 00552 #endif 00553 } 00554 00555 void ActionCollectionView::slotRemove() 00556 { 00557 if( ! selectionModel() ) return; 00558 KMessageBox::sorry(0, "TODO"); 00559 } 00560 00561 #include "view.moc"
KDE 4.6 API Reference