00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #include <App/Application.h>
00027 #include <Base/Console.h>
00028 #include <Base/Exception.h>
00029
00030
00031 #include "WidgetFactory.h"
00032 #include "PrefWidgets.h"
00033 #include "PropertyPage.h"
00034
00035
00036 using namespace Gui;
00037
00038
00039 Gui::WidgetFactoryInst* Gui::WidgetFactoryInst::_pcSingleton = NULL;
00040
00041 WidgetFactoryInst& WidgetFactoryInst::instance()
00042 {
00043 if (_pcSingleton == 0L)
00044 _pcSingleton = new WidgetFactoryInst;
00045 return *_pcSingleton;
00046 }
00047
00048 void WidgetFactoryInst::destruct ()
00049 {
00050 if (_pcSingleton != 0)
00051 delete _pcSingleton;
00052 _pcSingleton = 0;
00053 }
00054
00060 QWidget* WidgetFactoryInst::createWidget (const char* sName, QWidget* parent) const
00061 {
00062 QWidget* w = (QWidget*)Produce(sName);
00063
00064
00065 if (!w) {
00066 #ifdef FC_DEBUG
00067 Base::Console().Warning("\"%s\" is not registered\n", sName);
00068 #else
00069 Base::Console().Log("\"%s\" is not registered\n", sName);
00070 #endif
00071 return 0;
00072 }
00073
00074 try {
00075 #ifdef FC_DEBUG
00076 const char* cName = dynamic_cast<QWidget*>(w)->metaObject()->className();
00077 Base::Console().Log("Widget of type '%s' created.\n", cName);
00078 #endif
00079 }
00080 catch (...) {
00081 #ifdef FC_DEBUG
00082 Base::Console().Error("%s does not inherit from \"QWidget\"\n", sName);
00083 #else
00084 Base::Console().Log("%s does not inherit from \"QWidget\"\n", sName);
00085 #endif
00086 delete w;
00087 return 0;
00088 }
00089
00090
00091 if (parent)
00092 w->setParent(parent);
00093
00094 return w;
00095 }
00096
00102 Gui::Dialog::PreferencePage* WidgetFactoryInst::createPreferencePage (const char* sName, QWidget* parent) const
00103 {
00104 Gui::Dialog::PreferencePage* w = (Gui::Dialog::PreferencePage*)Produce(sName);
00105
00106
00107 if (!w) {
00108 #ifdef FC_DEBUG
00109 Base::Console().Warning("\"%s\" is not registered\n", sName);
00110 #else
00111 Base::Console().Log("\"%s\" is not registered\n", sName);
00112 #endif
00113 return 0;
00114 }
00115
00116 if (qobject_cast<Gui::Dialog::PreferencePage*>(w)) {
00117 #ifdef FC_DEBUG
00118 Base::Console().Log("Preference page of type '%s' created.\n", w->metaObject()->className());
00119 #endif
00120 }
00121 else {
00122 #ifdef FC_DEBUG
00123 Base::Console().Error("%s does not inherit from 'Gui::Dialog::PreferencePage'\n", sName);
00124 #endif
00125 delete w;
00126 return 0;
00127 }
00128
00129
00130 if (parent)
00131 w->setParent(parent);
00132
00133 return w;
00134 }
00135
00143 QWidget* WidgetFactoryInst::createPrefWidget(const char* sName, QWidget* parent, const char* sPref)
00144 {
00145 QWidget* w = createWidget(sName);
00146
00147 if (!w)
00148 return 0;
00149
00150
00151 w->setParent(parent);
00152
00153 try {
00154 dynamic_cast<PrefWidget*>(w)->setEntryName(sPref);
00155 dynamic_cast<PrefWidget*>(w)->restorePreferences();
00156 }
00157 catch (...) {
00158 #ifdef FC_DEBUG
00159 Base::Console().Error("%s does not inherit from \"PrefWidget\"\n", w->metaObject()->className());
00160 #endif
00161 delete w;
00162 return 0;
00163 }
00164
00165 return w;
00166 }
00167
00168
00169
00170 UiLoader::UiLoader(QObject* parent)
00171 : QUiLoader(parent)
00172 {
00173
00174
00175 clearPluginPaths();
00176 this->cw = availableWidgets();
00177 }
00178
00179 UiLoader::~UiLoader()
00180 {
00181 }
00182
00183 QWidget* UiLoader::createWidget(const QString & className, QWidget * parent,
00184 const QString& name)
00185 {
00186 if (this->cw.contains(className))
00187 return QUiLoader::createWidget(className, parent, name);
00188 QWidget* w = 0;
00189 if (WidgetFactory().CanProduce((const char*)className.toAscii()))
00190 w = WidgetFactory().createWidget((const char*)className.toAscii(), parent);
00191 if (w) w->setObjectName(name);
00192 return w;
00193 }
00194
00195
00196
00197 WidgetFactorySupplier* WidgetFactorySupplier::_pcSingleton = 0L;
00198
00199 WidgetFactorySupplier & WidgetFactorySupplier::instance()
00200 {
00201
00202 if (!_pcSingleton)
00203 _pcSingleton = new WidgetFactorySupplier;
00204 return *_pcSingleton;
00205 }
00206
00207 void WidgetFactorySupplier::destruct()
00208 {
00209
00210 WidgetFactoryInst::destruct();
00211 delete _pcSingleton;
00212 _pcSingleton=0;
00213 }
00214
00215
00216
00217 PrefPageUiProducer::PrefPageUiProducer (const char* filename, const char* group)
00218 : fn(QString::fromUtf8(filename))
00219 {
00220 WidgetFactoryInst::instance().AddProducer(filename, this);
00221 Gui::Dialog::DlgPreferencesImp::addPage(filename, group);
00222 }
00223
00224 PrefPageUiProducer::~PrefPageUiProducer()
00225 {
00226 }
00227
00228 void* PrefPageUiProducer::Produce () const
00229 {
00230 QWidget* page = new Gui::Dialog::PreferenceUiForm(fn);
00231 return (void*)page;
00232 }
00233
00234
00235
00236
00237
00242 ContainerDialog::ContainerDialog( QWidget* templChild )
00243 : QDialog( QApplication::activeWindow())
00244 {
00245 setModal(true);
00246 setWindowTitle( templChild->objectName() );
00247 setObjectName( templChild->objectName() );
00248
00249 setSizeGripEnabled( TRUE );
00250 MyDialogLayout = new QGridLayout(this);
00251
00252 buttonOk = new QPushButton(this);
00253 buttonOk->setObjectName(QLatin1String("buttonOK"));
00254 buttonOk->setText( tr( "&OK" ) );
00255 buttonOk->setAutoDefault( TRUE );
00256 buttonOk->setDefault( TRUE );
00257
00258 MyDialogLayout->addWidget( buttonOk, 1, 0 );
00259 QSpacerItem* spacer = new QSpacerItem( 210, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
00260 MyDialogLayout->addItem( spacer, 1, 1 );
00261
00262 buttonCancel = new QPushButton(this);
00263 buttonCancel->setObjectName(QLatin1String("buttonCancel"));
00264 buttonCancel->setText( tr( "&Cancel" ) );
00265 buttonCancel->setAutoDefault( TRUE );
00266
00267 MyDialogLayout->addWidget( buttonCancel, 1, 2 );
00268
00269 templChild->setParent(this);
00270
00271 MyDialogLayout->addWidget( templChild, 0, 0, 0, 2 );
00272 resize( QSize(307, 197).expandedTo(minimumSizeHint()) );
00273
00274
00275 connect( buttonOk, SIGNAL( clicked() ), this, SLOT( accept() ) );
00276 connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
00277 }
00278
00280 ContainerDialog::~ContainerDialog()
00281 {
00282 }
00283
00284
00285
00286
00287
00288
00289
00290 PyTypeObject PyResource::Type = {
00291 PyObject_HEAD_INIT(&PyType_Type)
00292 0,
00293 "PyResource",
00294 sizeof(PyResource),
00295 0,
00296
00297 PyDestructor,
00298 0,
00299 __getattr,
00300 __setattr,
00301 0,
00302 __repr,
00303 0,
00304 0,
00305 0,
00306 0,
00307 0,
00308 };
00309
00310
00311
00312
00313 PyMethodDef PyResource::Methods[] = {
00314 {"GetValue", (PyCFunction) svalue, Py_NEWARGS},
00315 {"SetValue", (PyCFunction) ssetValue, Py_NEWARGS},
00316 {"Show", (PyCFunction) sshow, Py_NEWARGS},
00317 {"Connect", (PyCFunction) sconnect, Py_NEWARGS},
00318
00319 {NULL, NULL}
00320 };
00321
00322
00323
00324
00325 PyParentObject PyResource::Parents[] = {&PyObjectBase::Type,&PyResource::Type, NULL};
00326
00327
00328
00329
00330 PyResource::PyResource(PyTypeObject *T)
00331 : PyObjectBase(0, T), myDlg(0L)
00332 {
00333 }
00334
00335 PyObject *PyResource::PyMake(PyObject *ignored, PyObject *args)
00336 {
00337
00338 return 0;
00339 }
00340
00341
00342
00343
00344 PyResource::~PyResource()
00345 {
00346 delete myDlg;
00347 for (std::vector<SignalConnect*>::iterator it = mySingals.begin(); it != mySingals.end(); ++it) {
00348 SignalConnect* sc = *it;
00349 delete sc;
00350 }
00351 }
00352
00353
00354
00355
00356 PyObject *PyResource::_getattr(char *attr)
00357 {
00358 _getattr_up(PyObjectBase);
00359 return 0;
00360 }
00361
00362 int PyResource::_setattr(char *attr, PyObject *value)
00363 {
00364 return PyObjectBase::_setattr(attr, value);
00365 return 0;
00366 }
00367
00373 void PyResource::load( const char* name )
00374 {
00375 QString fn = QString::fromUtf8(name);
00376 QFileInfo fi(fn);
00377
00378
00379 if (fi.isRelative()) {
00380 QString cwd = QDir::currentPath ();
00381 QString home= QDir(QString::fromUtf8(App::GetApplication().GetHomePath())).path();
00382
00383
00384
00385
00386 if (!fi.exists()) {
00387 if (cwd == home) {
00388 QString what = QObject::tr("Cannot find file %1").arg(fi.absoluteFilePath());
00389 throw Base::Exception(what.toUtf8().constData());
00390 }
00391 else {
00392 fi.setFile( QDir(home), fn );
00393
00394 if (!fi.exists()) {
00395 QString what = QObject::tr("Cannot find file %1 neither in %2 nor in %3")
00396 .arg(fn).arg(cwd).arg(home);
00397 throw Base::Exception(what.toUtf8().constData());
00398 }
00399 else {
00400 fn = fi.absoluteFilePath();
00401 }
00402 }
00403 }
00404 }
00405 else {
00406 if (!fi.exists()) {
00407 QString what = QObject::tr("Cannot find file %1").arg(fn);
00408 throw Base::Exception(what.toUtf8().constData());
00409 }
00410 }
00411
00412 QWidget* w=0;
00413 try {
00414 UiLoader loader;
00415 #if QT_VERSION >= 0x040500
00416 loader.setLanguageChangeEnabled(true);
00417 #endif
00418 QFile file(fn);
00419 if (file.open(QFile::ReadOnly))
00420 w = loader.load(&file, QApplication::activeWindow());
00421 file.close();
00422 }
00423 catch (...) {
00424 throw Base::Exception("Cannot create resource");
00425 }
00426
00427 if (!w)
00428 throw Base::Exception("Invalid widget.");
00429
00430 if (w->inherits("QDialog")) {
00431 myDlg = (QDialog*)w;
00432 }
00433 else {
00434 myDlg = new ContainerDialog(w);
00435 }
00436 }
00437
00444 bool PyResource::connect(const char* sender, const char* signal, PyObject* cb)
00445 {
00446 if ( !myDlg )
00447 return false;
00448
00449 QObject* objS=0L;
00450 QList<QWidget*> list = myDlg->findChildren<QWidget*>();
00451 QList<QWidget*>::const_iterator it = list.begin();
00452 QObject *obj;
00453 QString sigStr = QString::fromAscii("2%1").arg(QString::fromAscii(signal));
00454
00455 while ( it != list.end() ) {
00456 obj = *it;
00457 ++it;
00458 if (obj->objectName() == QLatin1String(sender)) {
00459 objS = obj;
00460 break;
00461 }
00462 }
00463
00464 if (objS) {
00465 SignalConnect* sc = new SignalConnect(this, cb, objS);
00466 mySingals.push_back(sc);
00467 return QObject::connect(objS, sigStr.toAscii(), sc, SLOT ( onExecute() ) );
00468 }
00469 else
00470 qWarning( "'%s' does not exist.\n", sender );
00471
00472 return false;
00473 }
00474
00479 PyObject *PyResource::connect(PyObject *args)
00480 {
00481 char *psSender;
00482 char *psSignal;
00483
00484 PyObject *result = NULL;
00485 PyObject *temp;
00486
00487 if (PyArg_ParseTuple(args, "ssOset_callback", &psSender, &psSignal, &temp)) {
00488 if (!PyCallable_Check(temp)) {
00489 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
00490 return NULL;
00491 }
00492
00493 Py_XINCREF(temp);
00494 std::string sSender = psSender;
00495 std::string sSignal = psSignal;
00496
00497 if (!connect(psSender, psSignal, temp)) {
00498
00499 Py_XDECREF(temp);
00500 }
00501
00502
00503 Py_INCREF(Py_None);
00504 result = Py_None;
00505 }
00506
00507 return result;
00508 }
00509
00513 PyObject *PyResource::show(PyObject *args)
00514 {
00515 if (myDlg) {
00516
00517 myDlg->showMinimized();
00518
00519 #ifdef Q_WS_X11
00520
00521
00522
00523 myDlg->hide();
00524 myDlg->show();
00525 #endif
00526
00527 myDlg->showNormal();
00528 myDlg->exec();
00529 }
00530
00531 Py_INCREF(Py_None);
00532 return Py_None;
00533 }
00534
00540 PyObject *PyResource::value(PyObject *args)
00541 {
00542 char *psName;
00543 char *psProperty;
00544 if (!PyArg_ParseTuple(args, "ss", &psName, &psProperty))
00545 return NULL;
00546
00547 QVariant v;
00548 if (myDlg) {
00549 QList<QWidget*> list = myDlg->findChildren<QWidget*>();
00550 QList<QWidget*>::const_iterator it = list.begin();
00551 QObject *obj;
00552
00553 bool fnd = false;
00554 while ( it != list.end() ) {
00555 obj = *it;
00556 ++it;
00557 if (obj->objectName() == QLatin1String(psName)) {
00558 fnd = true;
00559 v = obj->property(psProperty);
00560 break;
00561 }
00562 }
00563
00564 if ( !fnd )
00565 qWarning( "'%s' not found.\n", psName );
00566 }
00567
00568 PyObject *pItem=0;
00569 switch (v.type())
00570 {
00571 case QVariant::StringList:
00572 {
00573 QStringList str = v.toStringList();
00574 int nSize = str.count();
00575 PyObject* slist = PyList_New(nSize);
00576 for (int i=0; i<nSize;++i) {
00577 PyObject* item = PyString_FromString(str[i].toAscii());
00578 PyList_SetItem(slist, i, item);
00579 }
00580 } break;
00581 case QVariant::ByteArray:
00582 break;
00583 case QVariant::String:
00584 pItem = PyString_FromString(v.toString().toAscii());
00585 break;
00586 case QVariant::Double:
00587 pItem = PyFloat_FromDouble(v.toDouble());
00588 break;
00589 case QVariant::Bool:
00590 pItem = PyInt_FromLong(v.toBool() ? 1 : 0);
00591 break;
00592 case QVariant::UInt:
00593 pItem = PyLong_FromLong(v.toUInt());
00594 break;
00595 case QVariant::Int:
00596 pItem = PyInt_FromLong(v.toInt());
00597 break;
00598 default:
00599 pItem = PyString_FromString("");
00600 break;
00601 }
00602
00603 return pItem;
00604 }
00605
00611 PyObject *PyResource::setValue(PyObject *args)
00612 {
00613 char *psName;
00614 char *psProperty;
00615 PyObject *psValue;
00616 if (!PyArg_ParseTuple(args, "ssO", &psName, &psProperty, &psValue))
00617 return NULL;
00618
00619 QVariant v;
00620 if (PyString_Check(psValue)) {
00621 v = QString::fromAscii(PyString_AsString(psValue));
00622 }
00623 else if (PyInt_Check(psValue)) {
00624 int val = PyInt_AsLong(psValue);
00625 v = val;
00626 }
00627 else if (PyLong_Check(psValue)) {
00628 unsigned int val = PyLong_AsLong(psValue);
00629 v = val;
00630 }
00631 else if (PyFloat_Check(psValue)) {
00632 v = PyFloat_AsDouble(psValue);
00633 }
00634 else if (PyList_Check(psValue)) {
00635 QStringList str;
00636 int nSize = PyList_Size(psValue);
00637 for (int i=0; i<nSize;++i) {
00638 PyObject* item = PyList_GetItem(psValue, i);
00639 if (!PyString_Check(item))
00640 continue;
00641
00642 char* pItem = PyString_AsString(item);
00643 str.append(QString::fromAscii(pItem));
00644 }
00645
00646 v = str;
00647 }
00648 else {
00649 PyErr_SetString(PyExc_AssertionError, "Unsupported type");
00650 return NULL;
00651 }
00652
00653 if (myDlg) {
00654 QList<QWidget*> list = myDlg->findChildren<QWidget*>();
00655 QList<QWidget*>::const_iterator it = list.begin();
00656 QObject *obj;
00657
00658 bool fnd = false;
00659 while ( it != list.end() ) {
00660 obj = *it;
00661 ++it;
00662 if (obj->objectName() == QLatin1String(psName)) {
00663 fnd = true;
00664 obj->setProperty(psProperty, v);
00665 break;
00666 }
00667 }
00668
00669 if ( !fnd )
00670 qWarning( "'%s' not found.\n", psName );
00671 }
00672
00673 Py_INCREF(Py_None);
00674 return Py_None;
00675 }
00676
00677
00678
00679 SignalConnect::SignalConnect( Base::PyObjectBase* res, PyObject* cb, QObject* sender)
00680 : myResource(res), myCallback(cb), mySender(sender)
00681 {
00682 }
00683
00684 SignalConnect::~SignalConnect()
00685 {
00686 Py_XDECREF(myCallback);
00687 }
00688
00692 void SignalConnect::onExecute()
00693 {
00694 PyObject *arglist;
00695 PyObject *result;
00696
00697
00698 arglist = Py_BuildValue("(O)", myResource);
00699 result = PyEval_CallObject(myCallback, arglist);
00700 (void)result;
00701 Py_DECREF(arglist);
00702 }
00703
00704 #include "moc_WidgetFactory.cpp"