File indexing completed on 2024-03-24 15:37:27
0001 /*************************************************************************** 0002 * actioncollectionview.cpp 0003 * This file is part of the KDE project 0004 * copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> 0005 * copyright (C) 2006-2007 Sebastian Sauer <mail@dipe.org> 0006 * 0007 * This program is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU Library General Public 0009 * License as published by the Free Software Foundation; either 0010 * version 2 of the License, or (at your option) any later version. 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this program; see the file COPYING. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 ***************************************************************************/ 0020 0021 #include "actioncollectionview.h" 0022 #include "actioncollectionmodel.h" 0023 0024 #include <kross/core/manager.h> 0025 #include <kross/core/action.h> 0026 #include <kross/core/actioncollection.h> 0027 #include <kross/core/interpreter.h> 0028 0029 #include <QAction> 0030 #include <QBoxLayout> 0031 #include <QDir> 0032 #include <QFileInfo> 0033 #include <QHeaderView> 0034 #include <QLabel> 0035 #include <QLineEdit> 0036 #include <QPushButton> 0037 0038 #include <kmessagebox.h> 0039 #include <kpagedialog.h> 0040 #include <kactioncollection.h> 0041 #include <kcombobox.h> 0042 #include <kiconbutton.h> 0043 #include <klocalizedstring.h> 0044 #include <kurlrequester.h> 0045 0046 //#include <ktar.h> 0047 //#include <kio/netaccess.h> 0048 0049 using namespace Kross; 0050 0051 /********************************************************************************* 0052 * ActionCollectionEditor 0053 */ 0054 0055 namespace Kross 0056 { 0057 0058 /// \internal d-pointer class. 0059 class ActionCollectionEditor::Private 0060 { 0061 public: 0062 enum Type { ActionType, CollectionType }; 0063 const Type type; 0064 union { 0065 Action *action; 0066 ActionCollection *collection; 0067 }; 0068 0069 QString name() const 0070 { 0071 return type == ActionType ? action->name() : collection->name(); 0072 } 0073 QString text() const 0074 { 0075 return type == ActionType ? action->text() : collection->text(); 0076 } 0077 QString description() const 0078 { 0079 return type == ActionType ? action->description() : collection->description(); 0080 } 0081 QString iconName() const 0082 { 0083 return type == ActionType ? action->iconName() : collection->iconName(); 0084 } 0085 bool isEnabled() const 0086 { 0087 return type == ActionType ? action->isEnabled() : collection->isEnabled(); 0088 } 0089 0090 QLineEdit *nameedit; 0091 QLineEdit *textedit; 0092 QLineEdit *commentedit; 0093 QLineEdit *iconedit; 0094 KComboBox *interpreteredit; 0095 KUrlRequester *fileedit; 0096 //QCheckBox* enabledcheckbox; 0097 0098 explicit Private(Action *a) : type(ActionType), action(a) 0099 { 0100 Q_ASSERT(a); 0101 } 0102 explicit Private(ActionCollection *c) : type(CollectionType), collection(c) 0103 { 0104 Q_ASSERT(c); 0105 } 0106 }; 0107 0108 } 0109 0110 ActionCollectionEditor::ActionCollectionEditor(Action *action, QWidget *parent) 0111 : QWidget(parent), d(new Private(action)) 0112 { 0113 initGui(); 0114 } 0115 0116 ActionCollectionEditor::ActionCollectionEditor(ActionCollection *collection, QWidget *parent) 0117 : QWidget(parent), d(new Private(collection)) 0118 { 0119 initGui(); 0120 } 0121 0122 ActionCollectionEditor::~ActionCollectionEditor() 0123 { 0124 delete d; 0125 } 0126 0127 Action *ActionCollectionEditor::action() const 0128 { 0129 return d->type == Private::ActionType ? d->action : nullptr; 0130 } 0131 0132 ActionCollection *ActionCollectionEditor::collection() const 0133 { 0134 return d->type == Private::CollectionType ? d->collection : nullptr; 0135 } 0136 0137 QLineEdit *ActionCollectionEditor::nameEdit() const 0138 { 0139 return d->nameedit; 0140 } 0141 QLineEdit *ActionCollectionEditor::textEdit() const 0142 { 0143 return d->textedit; 0144 } 0145 QLineEdit *ActionCollectionEditor::commentEdit() const 0146 { 0147 return d->commentedit; 0148 } 0149 QLineEdit *ActionCollectionEditor::iconEdit() const 0150 { 0151 return d->iconedit; 0152 } 0153 QComboBox *ActionCollectionEditor::interpreterEdit() const 0154 { 0155 return d->interpreteredit; 0156 } 0157 KUrlRequester *ActionCollectionEditor::fileEdit() const 0158 { 0159 return d->fileedit; 0160 } 0161 0162 void ActionCollectionEditor::initGui() 0163 { 0164 QVBoxLayout *mainlayout = new QVBoxLayout(); 0165 setLayout(mainlayout); 0166 0167 QWidget *w = new QWidget(this); 0168 mainlayout->addWidget(w); 0169 QGridLayout *gridlayout = new QGridLayout(); 0170 gridlayout->setContentsMargins(0, 0, 0, 0); 0171 //gridlayout->setSpacing(0); 0172 w->setLayout(gridlayout); 0173 0174 QLabel *namelabel = new QLabel(i18n("Name:"), w); 0175 gridlayout->addWidget(namelabel, 0, 0); 0176 d->nameedit = new QLineEdit(w); 0177 namelabel->setBuddy(d->nameedit); 0178 d->nameedit->setText(d->name()); 0179 d->nameedit->setEnabled(false); 0180 gridlayout->addWidget(d->nameedit, 0, 1); 0181 0182 QLabel *textlabel = new QLabel(i18n("Text:"), w); 0183 gridlayout->addWidget(textlabel, 1, 0); 0184 d->textedit = new QLineEdit(w); 0185 textlabel->setBuddy(d->textedit); 0186 d->textedit->setText(d->text()); 0187 gridlayout->addWidget(d->textedit, 1, 1); 0188 0189 QLabel *commentlabel = new QLabel(i18n("Comment:"), w); 0190 gridlayout->addWidget(commentlabel, 2, 0); 0191 d->commentedit = new QLineEdit(w); 0192 commentlabel->setBuddy(d->commentedit); 0193 d->commentedit->setText(d->description()); 0194 gridlayout->addWidget(d->commentedit, 2, 1); 0195 0196 QLabel *iconlabel = new QLabel(i18n("Icon:"), w); 0197 gridlayout->addWidget(iconlabel, 3, 0); 0198 QWidget *iconbox = new QWidget(w); 0199 QHBoxLayout *iconlayout = new QHBoxLayout(); 0200 iconlayout->setContentsMargins(0, 0, 0, 0); 0201 iconbox->setLayout(iconlayout); 0202 d->iconedit = new QLineEdit(iconbox); 0203 iconlabel->setBuddy(d->iconedit); 0204 d->iconedit->setText(d->iconName()); 0205 iconlayout->addWidget(d->iconedit, 1); 0206 KIconButton *iconbutton = new KIconButton(iconbox); 0207 iconbutton->setIcon(d->iconName()); 0208 connect(iconbutton, SIGNAL(iconChanged(QString)), d->iconedit, SLOT(setText(QString))); 0209 iconlayout->addWidget(iconbutton); 0210 gridlayout->addWidget(iconbox, 3, 1); 0211 0212 //QFrame* hr1 = new QFrame(w); 0213 //hr1->setFrameStyle(QFrame::HLine | QFrame::Sunken); 0214 //gridlayout->addWidget(hr1, 4, 0, -1, -1, Qt::AlignVCenter); 0215 0216 if (d->type == Private::ActionType) { 0217 QLabel *interpreterlabel = new QLabel(i18n("Interpreter:"), w); 0218 gridlayout->addWidget(interpreterlabel, 4, 0); 0219 d->interpreteredit = new KComboBox(w); 0220 interpreterlabel->setBuddy(d->interpreteredit); 0221 d->interpreteredit->setMaxVisibleItems(10); 0222 d->interpreteredit->insertItems(0, Manager::self().interpreters()); 0223 d->interpreteredit->setEditable(true); 0224 //c->lineEdit()->setText( d->action->interpreter() ); 0225 int idx = Manager::self().interpreters().indexOf(d->action->interpreter()); 0226 if (idx >= 0) { 0227 d->interpreteredit->setCurrentIndex(idx); 0228 } else { 0229 d->interpreteredit->setEditText(d->action->interpreter()); 0230 } 0231 gridlayout->addWidget(d->interpreteredit, 4, 1); 0232 0233 QLabel *filelabel = new QLabel(i18n("File:"), w); 0234 gridlayout->addWidget(filelabel, 5, 0); 0235 d->fileedit = new KUrlRequester(w); 0236 filelabel->setBuddy(d->fileedit); 0237 QStringList mimetypes; 0238 foreach (const QString &interpretername, Manager::self().interpreters()) { 0239 InterpreterInfo *info = Manager::self().interpreterInfo(interpretername); 0240 Q_ASSERT(info); 0241 mimetypes.append(info->mimeTypes().join(" ").trimmed()); 0242 } 0243 //InterpreterInfo* info = Manager::self().interpreterInfo( Manager::self().interpreternameForFile( d->action->file() ) ); 0244 //const QString defaultmime = info ? info->mimeTypes().join(" ").trimmed() : QString(); 0245 0246 d->fileedit->setMimeTypeFilters(mimetypes); 0247 d->fileedit->setMode(KFile::File | KFile::ExistingOnly | KFile::LocalOnly); 0248 d->fileedit->setUrl(QUrl::fromLocalFile(d->action->file())); 0249 gridlayout->addWidget(d->fileedit, 5, 1); 0250 } else { 0251 d->interpreteredit = nullptr; 0252 d->fileedit = nullptr; 0253 } 0254 0255 //d->enabledcheckbox = new QCheckBox(this); 0256 //d->enabledcheckbox->setText( i18n("Enabled") ); 0257 //d->enabledcheckbox->setChecked( d->isEnabled() ); 0258 //mainlayout->addWidget(d->enabledcheckbox); 0259 0260 mainlayout->addStretch(1); 0261 } 0262 0263 bool ActionCollectionEditor::isValid() 0264 { 0265 //TODO check also if such a name already exist. 0266 return ! d->nameedit->text().isEmpty(); 0267 } 0268 0269 void ActionCollectionEditor::commit() 0270 { 0271 switch (d->type) { 0272 case Private::ActionType: { 0273 d->action->setText(d->textedit->text()); 0274 d->action->setDescription(d->commentedit->text()); 0275 d->action->setIconName(d->iconedit->text()); 0276 d->action->setInterpreter(d->interpreteredit->currentText()); 0277 d->action->setFile(d->fileedit->url().path()); 0278 //d->action->setEnabled( d->enabledcheckbox->isChecked() ); 0279 } break; 0280 case Private::CollectionType: { 0281 d->collection->setText(d->textedit->text()); 0282 d->collection->setDescription(d->commentedit->text()); 0283 d->collection->setIconName(d->iconedit->text()); 0284 //d->collection->setEnabled( d->enabledcheckbox->isChecked() ); 0285 } break; 0286 default: break; 0287 } 0288 } 0289 0290 /********************************************************************************* 0291 * ActionCollectionView 0292 */ 0293 0294 namespace Kross 0295 { 0296 0297 /// \internal d-pointer class. 0298 class ActionCollectionView::Private 0299 { 0300 public: 0301 bool modified; 0302 KActionCollection *collection; 0303 QMap< QString, QPushButton * > buttons; 0304 explicit Private() : modified(false) {} 0305 }; 0306 0307 } 0308 0309 ActionCollectionView::ActionCollectionView(QWidget *parent) 0310 : QTreeView(parent) 0311 , d(new Private()) 0312 { 0313 header()->hide(); 0314 setSelectionMode(QAbstractItemView::SingleSelection); 0315 setAlternatingRowColors(true); 0316 setRootIsDecorated(true); 0317 setSortingEnabled(false); 0318 setItemsExpandable(true); 0319 //setDragEnabled(true); 0320 //setAcceptDrops(true); 0321 setDropIndicatorShown(true); 0322 setDragDropMode(QAbstractItemView::InternalMove); 0323 0324 d->collection = new KActionCollection(this); 0325 0326 QAction *runaction = new QAction(QIcon::fromTheme("system-run"), i18n("Run"), this); 0327 runaction->setObjectName("run"); 0328 runaction->setToolTip(i18n("Execute the selected script.")); 0329 runaction->setEnabled(false); 0330 d->collection->addAction("run", runaction); 0331 connect(runaction, SIGNAL(triggered()), this, SLOT(slotRun())); 0332 0333 QAction *stopaction = new QAction(QIcon::fromTheme("process-stop"), i18n("Stop"), this); 0334 stopaction->setObjectName("stop"); 0335 stopaction->setToolTip(i18n("Stop execution of the selected script.")); 0336 stopaction->setEnabled(false); 0337 d->collection->addAction("stop", stopaction); 0338 connect(stopaction, SIGNAL(triggered()), this, SLOT(slotStop())); 0339 0340 QAction *editaction = new QAction(QIcon::fromTheme("document-properties"), i18n("Edit..."), this); 0341 editaction->setObjectName("edit"); 0342 editaction->setToolTip(i18n("Edit selected script.")); 0343 editaction->setEnabled(false); 0344 d->collection->addAction("edit", editaction); 0345 connect(editaction, SIGNAL(triggered()), this, SLOT(slotEdit())); 0346 0347 QAction *addaction = new QAction(QIcon::fromTheme("list-add"), i18n("Add..."), this); 0348 addaction->setObjectName("add"); 0349 addaction->setToolTip(i18n("Add a new script.")); 0350 //addaction->setEnabled(false); 0351 d->collection->addAction("add", addaction); 0352 connect(addaction, SIGNAL(triggered()), this, SLOT(slotAdd())); 0353 0354 QAction *removeaction = new QAction(QIcon::fromTheme("list-remove"), i18n("Remove"), this); 0355 removeaction->setObjectName("remove"); 0356 removeaction->setToolTip(i18n("Remove selected script.")); 0357 removeaction->setEnabled(false); 0358 d->collection->addAction("remove", removeaction); 0359 connect(removeaction, SIGNAL(triggered()), this, SLOT(slotRemove())); 0360 0361 connect(this, SIGNAL(enabledChanged(QString)), this, SLOT(slotEnabledChanged(QString))); 0362 //expandAll(); 0363 } 0364 0365 ActionCollectionView::~ActionCollectionView() 0366 { 0367 delete d; 0368 } 0369 0370 void ActionCollectionView::setModel(QAbstractItemModel *m) 0371 { 0372 QTreeView::setModel(m); 0373 d->modified = false; 0374 0375 QItemSelectionModel *selectionmodel = new QItemSelectionModel(m, this); 0376 setSelectionModel(selectionmodel); 0377 0378 connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), 0379 this, SLOT(slotSelectionChanged())); 0380 connect(m, SIGNAL(dataChanged(QModelIndex,QModelIndex)), 0381 this, SLOT(slotDataChanged(QModelIndex,QModelIndex))); 0382 } 0383 0384 bool ActionCollectionView::isModified() const 0385 { 0386 return d->modified; 0387 } 0388 0389 void ActionCollectionView::setModified(bool modified) 0390 { 0391 d->modified = modified; 0392 } 0393 0394 KActionCollection *ActionCollectionView::actionCollection() const 0395 { 0396 return d->collection; 0397 } 0398 0399 QPushButton *ActionCollectionView::button(const QString &actionname) const 0400 { 0401 return d->buttons.contains(actionname) ? d->buttons[actionname] : nullptr; 0402 } 0403 0404 QItemSelection ActionCollectionView::itemSelection() const 0405 { 0406 QAbstractProxyModel *proxymodel = dynamic_cast< QAbstractProxyModel * >(model()); 0407 QItemSelection selection = selectionModel()->selection(); 0408 return proxymodel ? proxymodel->mapSelectionToSource(selection) : selection; 0409 } 0410 0411 QPushButton *ActionCollectionView::createButton(QWidget *parentWidget, const QString &actionname) 0412 { 0413 QAction *action = d->collection->action(actionname); 0414 if (! action) { 0415 return nullptr; 0416 } 0417 //if( d->buttons.contains(actionname) ) delete d->buttons[]; 0418 QPushButton *btn = new QPushButton(parentWidget); 0419 btn->setText(action->text()); 0420 btn->setToolTip(action->toolTip()); 0421 btn->setIcon(action->icon()); 0422 btn->setEnabled(action->isEnabled()); 0423 if (parentWidget && parentWidget->layout()) { 0424 parentWidget->layout()->addWidget(btn); 0425 } 0426 QObject::connect(btn, SIGNAL(clicked()), action, SLOT(trigger())); 0427 d->buttons.insert(actionname, btn); 0428 return btn; 0429 } 0430 0431 void ActionCollectionView::slotEnabledChanged(const QString &actionname) 0432 { 0433 if (d->buttons.contains(actionname)) { 0434 QAction *action = d->collection->action(actionname); 0435 d->buttons[ actionname ]->setEnabled(action ? action->isEnabled() : false); 0436 } 0437 } 0438 0439 void ActionCollectionView::slotSelectionChanged() 0440 { 0441 bool startenabled = selectionModel()->hasSelection(); 0442 bool stopenabled = false; 0443 bool hasselection = selectionModel()->selectedIndexes().count() > 0; 0444 foreach (const QModelIndex &index, itemSelection().indexes()) { 0445 Action *action = ActionCollectionModel::action(index); 0446 if (startenabled && ! action) { 0447 startenabled = false; 0448 } 0449 if (! stopenabled) { 0450 stopenabled = (action && ! action->isFinalized()); 0451 } 0452 } 0453 QAction *runaction = d->collection->action("run"); 0454 if (runaction) { 0455 runaction->setEnabled(startenabled); 0456 emit enabledChanged("run"); 0457 } 0458 QAction *stopaction = d->collection->action("stop"); 0459 if (stopaction) { 0460 stopaction->setEnabled(stopenabled); 0461 emit enabledChanged("stop"); 0462 } 0463 QAction *editaction = d->collection->action("edit"); 0464 if (editaction) { 0465 editaction->setEnabled(hasselection); 0466 emit enabledChanged("edit"); 0467 } 0468 QAction *removeaction = d->collection->action("remove"); 0469 if (removeaction) { 0470 removeaction->setEnabled(hasselection); 0471 emit enabledChanged("remove"); 0472 } 0473 } 0474 0475 void ActionCollectionView::slotDataChanged(const QModelIndex &, const QModelIndex &) 0476 { 0477 d->modified = true; 0478 } 0479 0480 void ActionCollectionView::slotRun() 0481 { 0482 if (! selectionModel()) { 0483 return; 0484 } 0485 QAction *stopaction = d->collection->action("stop"); 0486 0487 foreach (const QModelIndex &index, itemSelection().indexes()) { 0488 if (! index.isValid()) { 0489 continue; 0490 } 0491 if (stopaction) { 0492 stopaction->setEnabled(true); 0493 emit enabledChanged("stop"); 0494 } 0495 Action *action = ActionCollectionModel::action(index); 0496 if (! action) { 0497 continue; 0498 } 0499 connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged())); 0500 action->trigger(); 0501 } 0502 slotSelectionChanged(); 0503 } 0504 0505 void ActionCollectionView::slotStop() 0506 { 0507 if (! selectionModel()) { 0508 return; 0509 } 0510 foreach (const QModelIndex &index, itemSelection().indexes()) { 0511 if (! index.isValid()) { 0512 continue; 0513 } 0514 Action *action = ActionCollectionModel::action(index); 0515 if (! action) { 0516 continue; 0517 } 0518 //connect(action, SIGNAL(started(Kross::Action*)), SLOT(slotSelectionChanged())); 0519 //connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged())); 0520 action->finalize(); 0521 } 0522 slotSelectionChanged(); 0523 } 0524 0525 void ActionCollectionView::slotEdit() 0526 { 0527 if (! selectionModel()) { 0528 return; 0529 } 0530 Action *action = nullptr; 0531 ActionCollection *collection = nullptr; 0532 foreach (const QModelIndex &index, itemSelection().indexes()) { 0533 if (! index.isValid()) { 0534 continue; 0535 } 0536 if (Action *a = ActionCollectionModel::action(index)) { 0537 action = a; 0538 } else if (ActionCollection *c = ActionCollectionModel::collection(index)) { 0539 collection = c; 0540 } else { 0541 continue; 0542 } 0543 break; 0544 } 0545 if ((! action) && (! collection)) { 0546 return; 0547 } 0548 KPageDialog *dialog = new KPageDialog(this); 0549 dialog->setWindowTitle(i18n("Edit")); 0550 dialog->setFaceType(KPageDialog::Plain); //Auto Plain List Tree Tabbed 0551 ActionCollectionEditor *editor = 0552 action ? new ActionCollectionEditor(action, dialog) 0553 : new ActionCollectionEditor(collection, dialog); 0554 dialog->addPage(editor, i18nc("@title:group Script properties", "General")); 0555 //dialog->addPage(new QWidget(this), i18n("Security")); 0556 dialog->resize(QSize(580, 200).expandedTo(dialog->minimumSizeHint())); 0557 int result = dialog->exec(); 0558 if (result == QDialog::Accepted /*&& dialog->result() == KDialog::Ok*/) { 0559 editor->commit(); 0560 } 0561 dialog->deleteLater(); 0562 } 0563 0564 void ActionCollectionView::slotAdd() 0565 { 0566 0567 //TODO 0568 KMessageBox::error(nullptr, "TODO"); 0569 0570 //ScriptManagerAddWizard wizard(this, collection); 0571 //int result = wizard.exec(); 0572 0573 #if 0 0574 if (! selectionModel()) { 0575 return; 0576 } 0577 ActionCollection *collection = 0; 0578 foreach (QModelIndex index, itemSelection().indexes()) { 0579 if (! index.isValid()) { 0580 continue; 0581 } 0582 if (ActionCollectionModel::action(index)) { 0583 //TODO probably add the item right after the current selected one? 0584 QModelIndex parent = index; 0585 while (parent.isValid() && ! collection) { 0586 parent = d->view->model()->parent(parent); 0587 collection = ActionCollectionModel::collection(parent); 0588 } 0589 if (collection) { 0590 break; // job done 0591 } 0592 } else if (ActionCollection *c = ActionCollectionModel::collection(index)) { 0593 collection = c; 0594 break; // job done 0595 } 0596 } 0597 ScriptManagerAddWizard wizard(this, collection); 0598 int result = wizard.exec(); 0599 Q_UNUSED(result); 0600 #endif 0601 } 0602 0603 void ActionCollectionView::slotRemove() 0604 { 0605 if (! selectionModel()) { 0606 return; 0607 } 0608 KMessageBox::error(nullptr, "TODO"); 0609 } 0610 0611 #include "moc_actioncollectionview.cpp"