mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 19:02:48 +00:00

for compatibilty reasons automoc4 support is not removed but it shall be in the future. automoc4 has not been maintained for a while (last commit is from 2011) and the stable release is from 2009. CMake version >= 2.8.6 provides the functionality for mocking so I see no reason to not make use of it.
561 lines
19 KiB
C++
561 lines
19 KiB
C++
/***************************************************************************
|
|
* view.cpp
|
|
* This file is part of the KDE project
|
|
* copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
|
|
* copyright (C) 2006-2007 Sebastian Sauer <mail@dipe.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
***************************************************************************/
|
|
|
|
#include "view.h"
|
|
#include "model.h"
|
|
|
|
#include <kross/core/manager.h>
|
|
#include <kross/core/action.h>
|
|
#include <kross/core/actioncollection.h>
|
|
#include <kross/core/interpreter.h>
|
|
|
|
#include <QtCore/QFileInfo>
|
|
#include <QtCore/QDir>
|
|
#include <QtGui/QBoxLayout>
|
|
#include <QtGui/QHeaderView>
|
|
#include <QtGui/QTreeView>
|
|
#include <QtGui/QLabel>
|
|
|
|
#include <kapplication.h>
|
|
//#include <kdeversion.h>
|
|
#include <kconfig.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kmessagebox.h>
|
|
#include <kpushbutton.h>
|
|
#include <kfiledialog.h>
|
|
#include <kmenu.h>
|
|
#include <kpagedialog.h>
|
|
#include <kaction.h>
|
|
#include <kactioncollection.h>
|
|
#include <kcombobox.h>
|
|
#include <kicondialog.h>
|
|
#include <klocale.h>
|
|
#include <klineedit.h>
|
|
#include <kurlrequester.h>
|
|
|
|
//#include <ktar.h>
|
|
//#include <kio/netaccess.h>
|
|
|
|
using namespace Kross;
|
|
|
|
/*********************************************************************************
|
|
* ActionCollectionEditor
|
|
*/
|
|
|
|
namespace Kross {
|
|
|
|
/// \internal d-pointer class.
|
|
class ActionCollectionEditor::Private
|
|
{
|
|
public:
|
|
enum Type { ActionType, CollectionType };
|
|
const Type type;
|
|
union {
|
|
Action* action;
|
|
ActionCollection* collection;
|
|
};
|
|
|
|
QString name() const {
|
|
return type == ActionType ? action->name() : collection->name();
|
|
}
|
|
QString text() const {
|
|
return type == ActionType ? action->text() : collection->text();
|
|
}
|
|
QString description() const {
|
|
return type == ActionType ? action->description() : collection->description();
|
|
}
|
|
QString iconName() const {
|
|
return type == ActionType ? action->iconName() : collection->iconName();
|
|
}
|
|
bool isEnabled() const {
|
|
return type == ActionType ? action->isEnabled() : collection->isEnabled();
|
|
}
|
|
|
|
KLineEdit* nameedit;
|
|
KLineEdit* textedit;
|
|
KLineEdit* commentedit;
|
|
KLineEdit* iconedit;
|
|
KComboBox* interpreteredit;
|
|
KUrlRequester* fileedit;
|
|
//QCheckBox* enabledcheckbox;
|
|
|
|
explicit Private(Action* a) : type(ActionType), action(a) { Q_ASSERT(a); }
|
|
explicit Private(ActionCollection* c) : type(CollectionType), collection(c) { Q_ASSERT(c); }
|
|
};
|
|
|
|
}
|
|
|
|
ActionCollectionEditor::ActionCollectionEditor(Action* action, QWidget* parent)
|
|
: QWidget(parent), d(new Private(action))
|
|
{
|
|
initGui();
|
|
}
|
|
|
|
ActionCollectionEditor::ActionCollectionEditor(ActionCollection* collection, QWidget* parent)
|
|
: QWidget(parent), d(new Private(collection))
|
|
{
|
|
initGui();
|
|
}
|
|
|
|
ActionCollectionEditor::~ActionCollectionEditor()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
Action* ActionCollectionEditor::action() const
|
|
{
|
|
return d->type == Private::ActionType ? d->action : 0;
|
|
}
|
|
|
|
ActionCollection* ActionCollectionEditor::collection() const
|
|
{
|
|
return d->type == Private::CollectionType ? d->collection : 0;
|
|
}
|
|
|
|
QLineEdit* ActionCollectionEditor::nameEdit() const { return d->nameedit; }
|
|
QLineEdit* ActionCollectionEditor::textEdit() const { return d->textedit; }
|
|
QLineEdit* ActionCollectionEditor::commentEdit() const { return d->commentedit; }
|
|
QLineEdit* ActionCollectionEditor::iconEdit() const { return d->iconedit; }
|
|
QComboBox* ActionCollectionEditor::interpreterEdit() const { return d->interpreteredit; }
|
|
KUrlRequester* ActionCollectionEditor::fileEdit() const { return d->fileedit; }
|
|
|
|
void ActionCollectionEditor::initGui()
|
|
{
|
|
QVBoxLayout* mainlayout = new QVBoxLayout();
|
|
setLayout(mainlayout);
|
|
|
|
QWidget* w = new QWidget(this);
|
|
mainlayout->addWidget(w);
|
|
QGridLayout* gridlayout = new QGridLayout();
|
|
gridlayout->setMargin(0);
|
|
//gridlayout->setSpacing(0);
|
|
w->setLayout(gridlayout);
|
|
|
|
QLabel* namelabel = new QLabel(i18n("Name:"), w);
|
|
gridlayout->addWidget(namelabel, 0, 0);
|
|
d->nameedit = new KLineEdit(w);
|
|
namelabel->setBuddy(d->nameedit);
|
|
d->nameedit->setText( d->name() );
|
|
d->nameedit->setEnabled(false);
|
|
gridlayout->addWidget(d->nameedit, 0, 1);
|
|
|
|
QLabel* textlabel = new QLabel(i18n("Text:"), w);
|
|
gridlayout->addWidget(textlabel, 1, 0);
|
|
d->textedit = new KLineEdit(w);
|
|
textlabel->setBuddy(d->textedit);
|
|
d->textedit->setText( d->text() );
|
|
gridlayout->addWidget(d->textedit, 1, 1);
|
|
|
|
QLabel* commentlabel = new QLabel(i18n("Comment:"), w);
|
|
gridlayout->addWidget(commentlabel, 2, 0);
|
|
d->commentedit = new KLineEdit(w);
|
|
commentlabel->setBuddy(d->commentedit);
|
|
d->commentedit->setText( d->description() );
|
|
gridlayout->addWidget(d->commentedit, 2, 1);
|
|
|
|
QLabel* iconlabel = new QLabel(i18n("Icon:"), w);
|
|
gridlayout->addWidget(iconlabel, 3, 0);
|
|
QWidget* iconbox = new QWidget(w);
|
|
QHBoxLayout* iconlayout = new QHBoxLayout();
|
|
iconlayout->setMargin(0);
|
|
iconbox->setLayout(iconlayout);
|
|
d->iconedit = new KLineEdit(iconbox);
|
|
iconlabel->setBuddy(d->iconedit);
|
|
d->iconedit->setText( d->iconName() );
|
|
iconlayout->addWidget(d->iconedit, 1);
|
|
KIconButton* iconbutton = new KIconButton(iconbox);
|
|
iconbutton->setIcon( d->iconName() );
|
|
connect(iconbutton, SIGNAL(iconChanged(QString)), d->iconedit, SLOT(setText(QString)));
|
|
iconlayout->addWidget(iconbutton);
|
|
gridlayout->addWidget(iconbox, 3, 1);
|
|
|
|
//QFrame* hr1 = new QFrame(w);
|
|
//hr1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
|
|
//gridlayout->addWidget(hr1, 4, 0, -1, -1, Qt::AlignVCenter);
|
|
|
|
if( d->type == Private::ActionType ) {
|
|
QLabel* interpreterlabel = new QLabel(i18n("Interpreter:"), w);
|
|
gridlayout->addWidget(interpreterlabel, 4, 0);
|
|
d->interpreteredit = new KComboBox(w);
|
|
interpreterlabel->setBuddy(d->interpreteredit);
|
|
d->interpreteredit->setMaxVisibleItems(10);
|
|
d->interpreteredit->insertItems(0, Manager::self().interpreters());
|
|
d->interpreteredit->setEditable(true);
|
|
//c->lineEdit()->setText( d->action->interpreter() );
|
|
int idx = Manager::self().interpreters().indexOf( d->action->interpreter() );
|
|
if( idx >= 0 )
|
|
d->interpreteredit->setCurrentIndex(idx);
|
|
else
|
|
d->interpreteredit->setEditText( d->action->interpreter() );
|
|
gridlayout->addWidget(d->interpreteredit, 4, 1);
|
|
|
|
QLabel* filelabel = new QLabel(i18n("File:"), w);
|
|
gridlayout->addWidget(filelabel, 5, 0);
|
|
d->fileedit = new KUrlRequester(w);
|
|
filelabel->setBuddy(d->fileedit);
|
|
QStringList mimetypes;
|
|
foreach(const QString &interpretername, Manager::self().interpreters()) {
|
|
InterpreterInfo* info = Manager::self().interpreterInfo(interpretername);
|
|
Q_ASSERT( info );
|
|
mimetypes.append( info->mimeTypes().join(" ").trimmed() );
|
|
}
|
|
//InterpreterInfo* info = Manager::self().interpreterInfo( Manager::self().interpreternameForFile( d->action->file() ) );
|
|
//const QString defaultmime = info ? info->mimeTypes().join(" ").trimmed() : QString();
|
|
d->fileedit->fileDialog()->setMimeFilter(mimetypes /*, defaultmime*/);
|
|
d->fileedit->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly );
|
|
d->fileedit->setUrl(KUrl(d->action->file()) );
|
|
gridlayout->addWidget(d->fileedit, 5, 1);
|
|
}
|
|
else {
|
|
d->interpreteredit = 0;
|
|
d->fileedit = 0;
|
|
}
|
|
|
|
//d->enabledcheckbox = new QCheckBox(this);
|
|
//d->enabledcheckbox->setText( i18n("Enabled") );
|
|
//d->enabledcheckbox->setChecked( d->isEnabled() );
|
|
//mainlayout->addWidget(d->enabledcheckbox);
|
|
|
|
mainlayout->addStretch(1);
|
|
}
|
|
|
|
bool ActionCollectionEditor::isValid()
|
|
{
|
|
//TODO check also if such a name already exist.
|
|
return ! d->nameedit->text().isEmpty();
|
|
}
|
|
|
|
void ActionCollectionEditor::commit()
|
|
{
|
|
switch( d->type ) {
|
|
case Private::ActionType: {
|
|
d->action->setText( d->textedit->text() );
|
|
d->action->setDescription( d->commentedit->text() );
|
|
d->action->setIconName( d->iconedit->text() );
|
|
d->action->setInterpreter( d->interpreteredit->currentText() );
|
|
d->action->setFile( d->fileedit->url().path() );
|
|
//d->action->setEnabled( d->enabledcheckbox->isChecked() );
|
|
} break;
|
|
case Private::CollectionType: {
|
|
d->collection->setText( d->textedit->text() );
|
|
d->collection->setDescription( d->commentedit->text() );
|
|
d->collection->setIconName( d->iconedit->text() );
|
|
//d->collection->setEnabled( d->enabledcheckbox->isChecked() );
|
|
} break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* ActionCollectionView
|
|
*/
|
|
|
|
namespace Kross {
|
|
|
|
/// \internal d-pointer class.
|
|
class ActionCollectionView::Private
|
|
{
|
|
public:
|
|
bool modified;
|
|
KActionCollection* collection;
|
|
QMap< QString, KPushButton* > buttons;
|
|
explicit Private() : modified(false) {}
|
|
};
|
|
|
|
}
|
|
|
|
ActionCollectionView::ActionCollectionView(QWidget* parent)
|
|
: QTreeView(parent)
|
|
, d(new Private())
|
|
{
|
|
header()->hide();
|
|
setSelectionMode(QAbstractItemView::SingleSelection);
|
|
setAlternatingRowColors(true);
|
|
setRootIsDecorated(true);
|
|
setSortingEnabled(false);
|
|
setItemsExpandable(true);
|
|
//setDragEnabled(true);
|
|
//setAcceptDrops(true);
|
|
setDropIndicatorShown(true);
|
|
setDragDropMode(QAbstractItemView::InternalMove);
|
|
|
|
d->collection = new KActionCollection(this);
|
|
|
|
KAction* runaction = new KAction(KIcon("system-run"), i18n("Run"), this);
|
|
runaction->setObjectName("run");
|
|
runaction->setToolTip( i18n("Execute the selected script.") );
|
|
runaction->setEnabled(false);
|
|
d->collection->addAction("run", runaction);
|
|
connect(runaction, SIGNAL(triggered()), this, SLOT(slotRun()));
|
|
|
|
KAction* stopaction = new KAction(KIcon("process-stop"), i18n("Stop"), this);
|
|
stopaction->setObjectName("stop");
|
|
stopaction->setToolTip( i18n("Stop execution of the selected script.") );
|
|
stopaction->setEnabled(false);
|
|
d->collection->addAction("stop", stopaction);
|
|
connect(stopaction, SIGNAL(triggered()), this, SLOT(slotStop()));
|
|
|
|
KAction* editaction = new KAction(KIcon("document-properties"), i18n("Edit..."), this);
|
|
editaction->setObjectName("edit");
|
|
editaction->setToolTip( i18n("Edit selected script.") );
|
|
editaction->setEnabled(false);
|
|
d->collection->addAction("edit", editaction);
|
|
connect(editaction, SIGNAL(triggered()), this, SLOT(slotEdit()));
|
|
|
|
KAction* addaction = new KAction(KIcon("list-add"), i18n("Add..."), this);
|
|
addaction->setObjectName("add");
|
|
addaction->setToolTip( i18n("Add a new script.") );
|
|
//addaction->setEnabled(false);
|
|
d->collection->addAction("add", addaction);
|
|
connect(addaction, SIGNAL(triggered()), this, SLOT(slotAdd()) );
|
|
|
|
KAction* removeaction = new KAction(KIcon("list-remove"), i18n("Remove"), this);
|
|
removeaction->setObjectName("remove");
|
|
removeaction->setToolTip( i18n("Remove selected script.") );
|
|
removeaction->setEnabled(false);
|
|
d->collection->addAction("remove", removeaction);
|
|
connect(removeaction, SIGNAL(triggered()), this, SLOT(slotRemove()) );
|
|
|
|
connect(this, SIGNAL(enabledChanged(QString)), this, SLOT(slotEnabledChanged(QString)));
|
|
//expandAll();
|
|
}
|
|
|
|
ActionCollectionView::~ActionCollectionView()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void ActionCollectionView::setModel(QAbstractItemModel* m)
|
|
{
|
|
QTreeView::setModel(m);
|
|
d->modified = false;
|
|
|
|
QItemSelectionModel* selectionmodel = new QItemSelectionModel(m, this);
|
|
setSelectionModel(selectionmodel);
|
|
|
|
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
this, SLOT(slotSelectionChanged()));
|
|
connect(m, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
|
this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
|
|
}
|
|
|
|
bool ActionCollectionView::isModified() const
|
|
{
|
|
return d->modified;
|
|
}
|
|
|
|
void ActionCollectionView::setModified(bool modified)
|
|
{
|
|
d->modified = modified;
|
|
}
|
|
|
|
KActionCollection* ActionCollectionView::actionCollection() const
|
|
{
|
|
return d->collection;
|
|
}
|
|
|
|
KPushButton* ActionCollectionView::button(const QString& actionname) const
|
|
{
|
|
return d->buttons.contains(actionname) ? d->buttons[actionname] : 0;
|
|
}
|
|
|
|
QItemSelection ActionCollectionView::itemSelection() const
|
|
{
|
|
QAbstractProxyModel* proxymodel = dynamic_cast< QAbstractProxyModel* >( model() );
|
|
QItemSelection selection = selectionModel()->selection();
|
|
return proxymodel ? proxymodel->mapSelectionToSource(selection) : selection;
|
|
}
|
|
|
|
KPushButton* ActionCollectionView::createButton(QWidget* parentWidget, const QString& actionname)
|
|
{
|
|
QAction* action = d->collection->action(actionname);
|
|
if( ! action ) return 0;
|
|
//if( d->buttons.contains(actionname) ) delete d->buttons[];
|
|
KPushButton* btn = new KPushButton(parentWidget);
|
|
btn->setText( action->text() );
|
|
btn->setToolTip( action->toolTip() );
|
|
btn->setIcon( KIcon(action->icon()) );
|
|
btn->setEnabled( action->isEnabled() );
|
|
if( parentWidget && parentWidget->layout() )
|
|
parentWidget->layout()->addWidget(btn);
|
|
QObject::connect(btn, SIGNAL(clicked()), action, SLOT(trigger()));
|
|
d->buttons.insert( actionname, btn );
|
|
return btn;
|
|
}
|
|
|
|
void ActionCollectionView::slotEnabledChanged(const QString& actionname)
|
|
{
|
|
if( d->buttons.contains( actionname ) ) {
|
|
QAction* action = d->collection->action( actionname );
|
|
d->buttons[ actionname ]->setEnabled( action ? action->isEnabled() : false );
|
|
}
|
|
}
|
|
|
|
void ActionCollectionView::slotSelectionChanged()
|
|
{
|
|
bool startenabled = selectionModel()->hasSelection();
|
|
bool stopenabled = false;
|
|
bool hasselection = selectionModel()->selectedIndexes().count() > 0;
|
|
foreach(const QModelIndex &index, itemSelection().indexes()) {
|
|
Action* action = ActionCollectionModel::action(index);
|
|
if( startenabled && ! action )
|
|
startenabled = false;
|
|
if( ! stopenabled )
|
|
stopenabled = (action && ! action->isFinalized());
|
|
}
|
|
QAction* runaction = d->collection->action("run");
|
|
if( runaction ) {
|
|
runaction->setEnabled(startenabled);
|
|
emit enabledChanged("run");
|
|
}
|
|
QAction* stopaction = d->collection->action("stop");
|
|
if( stopaction ) {
|
|
stopaction->setEnabled(stopenabled);
|
|
emit enabledChanged("stop");
|
|
}
|
|
QAction* editaction = d->collection->action("edit");
|
|
if( editaction ) {
|
|
editaction->setEnabled(hasselection);
|
|
emit enabledChanged("edit");
|
|
}
|
|
QAction* removeaction = d->collection->action("remove");
|
|
if( removeaction ) {
|
|
removeaction->setEnabled(hasselection);
|
|
emit enabledChanged("remove");
|
|
}
|
|
}
|
|
|
|
void ActionCollectionView::slotDataChanged(const QModelIndex&, const QModelIndex&)
|
|
{
|
|
d->modified = true;
|
|
}
|
|
|
|
void ActionCollectionView::slotRun()
|
|
{
|
|
if( ! selectionModel() ) return;
|
|
QAction* stopaction = d->collection->action("stop");
|
|
|
|
foreach(const QModelIndex &index, itemSelection().indexes()) {
|
|
if( ! index.isValid() )
|
|
continue;
|
|
if( stopaction ) {
|
|
stopaction->setEnabled(true);
|
|
emit enabledChanged("stop");
|
|
}
|
|
Action* action = ActionCollectionModel::action(index);
|
|
if( ! action )
|
|
continue;
|
|
connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged()));
|
|
action->trigger();
|
|
}
|
|
slotSelectionChanged();
|
|
}
|
|
|
|
void ActionCollectionView::slotStop()
|
|
{
|
|
if( ! selectionModel() ) return;
|
|
foreach(const QModelIndex &index, itemSelection().indexes()) {
|
|
if( ! index.isValid() )
|
|
continue;
|
|
Action* action = ActionCollectionModel::action(index);
|
|
if( ! action )
|
|
continue;
|
|
//connect(action, SIGNAL(started(Kross::Action*)), SLOT(slotSelectionChanged()));
|
|
//connect(action, SIGNAL(finished(Kross::Action*)), SLOT(slotSelectionChanged()));
|
|
action->finalize();
|
|
}
|
|
slotSelectionChanged();
|
|
}
|
|
|
|
void ActionCollectionView::slotEdit()
|
|
{
|
|
if( ! selectionModel() ) return;
|
|
Action* action = 0;
|
|
ActionCollection* collection = 0;
|
|
foreach(const QModelIndex &index, itemSelection().indexes()) {
|
|
if( ! index.isValid() ) continue;
|
|
if( Action* a = ActionCollectionModel::action(index) )
|
|
action = a;
|
|
else if( ActionCollection* c = ActionCollectionModel::collection(index) )
|
|
collection = c;
|
|
else
|
|
continue;
|
|
break;
|
|
}
|
|
if( (! action) && (! collection) ) return;
|
|
KPageDialog* dialog = new KPageDialog( this );
|
|
dialog->setCaption( i18n("Edit") );
|
|
dialog->setButtons( KDialog::Ok | KDialog::Cancel );
|
|
//dialog->enableButtonOk( false );
|
|
dialog->setFaceType( KPageDialog::Plain ); //Auto Plain List Tree Tabbed
|
|
ActionCollectionEditor* editor =
|
|
action ? new ActionCollectionEditor(action, dialog->mainWidget())
|
|
: new ActionCollectionEditor(collection, dialog->mainWidget());
|
|
dialog->addPage(editor, i18nc("@title:group Script properties", "General"));
|
|
//dialog->addPage(new QWidget(this), i18n("Security"));
|
|
dialog->resize( QSize(580, 200).expandedTo( dialog->minimumSizeHint() ) );
|
|
int result = dialog->exec();
|
|
if( result == QDialog::Accepted /*&& dialog->result() == KDialog::Ok*/ ) {
|
|
editor->commit();
|
|
}
|
|
dialog->delayedDestruct();
|
|
}
|
|
|
|
void ActionCollectionView::slotAdd()
|
|
{
|
|
|
|
//TODO
|
|
KMessageBox::sorry(0, "TODO");
|
|
|
|
//ScriptManagerAddWizard wizard(this, collection);
|
|
//int result = wizard.exec();
|
|
|
|
#if 0
|
|
if( ! selectionModel() ) return;
|
|
ActionCollection* collection = 0;
|
|
foreach(QModelIndex index, itemSelection().indexes()) {
|
|
if( ! index.isValid() ) continue;
|
|
if( ActionCollectionModel::action(index) ) {
|
|
//TODO propably add the item right after the current selected one?
|
|
QModelIndex parent = index;
|
|
while( parent.isValid() && ! collection ) {
|
|
parent = d->view->model()->parent(parent);
|
|
collection = ActionCollectionModel::collection(parent);
|
|
}
|
|
if( collection ) break; // job done
|
|
}
|
|
else if( ActionCollection* c = ActionCollectionModel::collection(index) ) {
|
|
collection = c;
|
|
break; // job done
|
|
}
|
|
}
|
|
ScriptManagerAddWizard wizard(this, collection);
|
|
int result = wizard.exec();
|
|
Q_UNUSED(result);
|
|
#endif
|
|
}
|
|
|
|
void ActionCollectionView::slotRemove()
|
|
{
|
|
if( ! selectionModel() ) return;
|
|
KMessageBox::sorry(0, "TODO");
|
|
}
|
|
|
|
#include "moc_view.cpp"
|