/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "changeproperties.h" #include "invokemethod.h" #include "ambientproperties.h" #include "controlinfo.h" #include "docuwindow.h" #include #include #include QT_BEGIN_NAMESPACE QAxObject *ax_mainWindow = 0; static QTextEdit *debuglog = 0; static void redirectDebugOutput(QtMsgType type, const char*msg) { Q_UNUSED(type); debuglog->append(QLatin1String(msg)); } QT_END_NAMESPACE QT_USE_NAMESPACE MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUi(this); setObjectName(QLatin1String("MainWindow")); QAxScriptManager::registerEngine(QLatin1String("PerlScript"), QLatin1String(".pl")); QAxScriptManager::registerEngine(QLatin1String("Python"), QLatin1String(".py")); dlgInvoke = 0; dlgProperties = 0; dlgAmbient = 0; scripts = 0; debuglog = logDebug; oldDebugHandler = qInstallMsgHandler(redirectDebugOutput); QHBoxLayout *layout = new QHBoxLayout(Workbase); workspace = new QWorkspace(Workbase); layout->addWidget(workspace); layout->setMargin(0); connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(updateGUI())); connect(actionFileExit, SIGNAL(triggered()), qApp, SLOT(quit())); } MainWindow::~MainWindow() { qInstallMsgHandler(oldDebugHandler); debuglog = 0; } void MainWindow::on_actionFileNew_triggered() { QAxSelect select(this); if (select.exec()) { QAxWidget *container = new QAxWidget(workspace); container->setAttribute(Qt::WA_DeleteOnClose); container->setControl(select.clsid()); container->setObjectName(container->windowTitle()); workspace->addWindow(container); container->show(); } updateGUI(); } void MainWindow::on_actionFileLoad_triggered() { QString fname = QFileDialog::getOpenFileName(this, tr("Load"), QString(), QLatin1String("*.qax")); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::information(this, tr("Error Loading File"), tr("The file could not be opened for reading.\n%1").arg(fname)); return; } QAxWidget *container = new QAxWidget(workspace); workspace->addWindow(container); QDataStream d(&file); d >> *container; container->setObjectName(container->windowTitle()); container->show(); updateGUI(); } void MainWindow::on_actionFileSave_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QString fname = QFileDialog::getSaveFileName(this, tr("Save"), QString(), QLatin1String("*.qax")); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::information(this, tr("Error Saving File"), tr("The file could not be opened for writing.\n%1").arg(fname)); return; } QDataStream d(&file); d << *container; } void MainWindow::on_actionContainerSet_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QAxSelect select(this); if (select.exec()) container->setControl(select.clsid()); updateGUI(); } void MainWindow::on_actionContainerClear_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (container) container->clear(); updateGUI(); } void MainWindow::on_actionContainerProperties_triggered() { if (!dlgAmbient) { dlgAmbient = new AmbientProperties(this); dlgAmbient->setControl(workspace); } dlgAmbient->show(); } void MainWindow::on_actionControlInfo_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; ControlInfo info(this); info.setControl(container); info.exec(); } void MainWindow::on_actionControlProperties_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; if (!dlgProperties) { dlgProperties = new ChangeProperties(this); connect(container, SIGNAL(propertyChanged(QString)), dlgProperties, SLOT(updateProperties())); } dlgProperties->setControl(container); dlgProperties->show(); } void MainWindow::on_actionControlMethods_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; if (!dlgInvoke) dlgInvoke = new InvokeMethod(this); dlgInvoke->setControl(container); dlgInvoke->show(); } void MainWindow::on_VerbMenu_aboutToShow() { VerbMenu->clear(); QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QStringList verbs = container->verbs(); for (int i = 0; i < verbs.count(); ++i) { VerbMenu->addAction(verbs.at(i)); } if (!verbs.count()) { // no verbs? VerbMenu->addAction(tr("-- Object does not support any verbs --"))->setEnabled(false); } } void MainWindow::on_VerbMenu_triggered(QAction *action) { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; container->doVerb(action->text()); } void MainWindow::on_actionControlDocumentation_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QString docu = container->generateDocumentation(); if (docu.isEmpty()) return; DocuWindow *docwindow = new DocuWindow(docu, workspace, container); workspace->addWindow(docwindow); docwindow->show(); } void MainWindow::on_actionControlPixmap_triggered() { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QPixmap pm = QPixmap::grabWidget(container); QLabel *label = new QLabel(workspace); label->setAttribute(Qt::WA_DeleteOnClose); label->setPixmap(pm); label->setWindowTitle(tr("%1 - Pixmap").arg(container->windowTitle())); workspace->addWindow(label); label->show(); } void MainWindow::on_actionScriptingRun_triggered() { #ifndef QT_NO_QAXSCRIPT if (!scripts) return; // If we have only one script loaded we can use the cool dialog QStringList scriptList = scripts->scriptNames(); if (scriptList.count() == 1) { InvokeMethod scriptInvoke(this); scriptInvoke.setWindowTitle(tr("Execute Script Function")); scriptInvoke.setControl(scripts->script(scriptList[0])->scriptEngine()); scriptInvoke.exec(); return; } bool ok = false; QStringList macroList = scripts->functions(QAxScript::FunctionNames); QString macro = QInputDialog::getItem(this, tr("Select Macro"), tr("Macro:"), macroList, 0, true, &ok); if (!ok) return; QVariant result = scripts->call(macro); if (result.isValid()) logMacros->append(tr("Return value of %1: %2").arg(macro).arg(result.toString())); #endif } void MainWindow::on_actionScriptingLoad_triggered() { #ifndef QT_NO_QAXSCRIPT QString file = QFileDialog::getOpenFileName(this, tr("Open Script"), QString(), QAxScriptManager::scriptFileFilter()); if (file.isEmpty()) return; if (!scripts) { scripts = new QAxScriptManager(this); scripts->addObject(this); } QWidgetList widgets = workspace->windowList(); QWidgetList::Iterator it(widgets.begin()); while (it != widgets.end()) { QAxBase *ax = (QAxBase*)(*it)->qt_metacast("QAxBase"); ++it; if (!ax) continue; scripts->addObject(ax); } QAxScript *script = scripts->load(file, file); if (script) { connect(script, SIGNAL(error(int,QString,int,QString)), this, SLOT(logMacro(int,QString,int,QString))); actionScriptingRun->setEnabled(true); } #else QMessageBox::information(this, tr("Function not available"), tr("QAxScript functionality is not available with this compiler.")); #endif } void MainWindow::updateGUI() { QAxWidget *container = qobject_cast(workspace->activeWindow()); bool hasControl = container && !container->isNull(); actionFileNew->setEnabled(true); actionFileLoad->setEnabled(true); actionFileSave->setEnabled(hasControl); actionContainerSet->setEnabled(container != 0); actionContainerClear->setEnabled(hasControl); actionControlProperties->setEnabled(hasControl); actionControlMethods->setEnabled(hasControl); actionControlInfo->setEnabled(hasControl); actionControlDocumentation->setEnabled(hasControl); actionControlPixmap->setEnabled(hasControl); VerbMenu->setEnabled(hasControl); if (dlgInvoke) dlgInvoke->setControl(hasControl ? container : 0); if (dlgProperties) dlgProperties->setControl(hasControl ? container : 0); QWidgetList list = workspace->windowList(); QWidgetList::Iterator it = list.begin(); while (it != list.end()) { QWidget *container = *it; QAxWidget *ax = qobject_cast(container); if (ax) { container->disconnect(SIGNAL(signal(QString,int,void*))); if (actionLogSignals->isChecked()) connect(container, SIGNAL(signal(QString,int,void*)), this, SLOT(logSignal(QString,int,void*))); container->disconnect(SIGNAL(exception(int,QString,QString,QString))); connect(container, SIGNAL(exception(int,QString,QString,QString)), this, SLOT(logException(int,QString,QString,QString))); container->disconnect(SIGNAL(propertyChanged(QString))); if (actionLogProperties->isChecked()) connect(container, SIGNAL(propertyChanged(QString)), this, SLOT(logPropertyChanged(QString))); container->blockSignals(actionFreezeEvents->isChecked()); } ++it; } } void MainWindow::logPropertyChanged(const QString &prop) { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QVariant var = container->property(prop.toLatin1()); logProperties->append(tr("%1: Property Change: %2 - { %3 }").arg(container->windowTitle(), prop, var.toString())); } void MainWindow::logSignal(const QString &signal, int argc, void *argv) { QAxWidget *container = qobject_cast(workspace->activeWindow()); if (!container) return; QString paramlist; VARIANT *params = (VARIANT*)argv; for (int a = argc-1; a >= 0; --a) { if (a == argc-1) paramlist = QLatin1String(" - {"); QVariant qvar = VARIANTToQVariant(params[a], 0); paramlist += QLatin1String(" ") + qvar.toString(); if (a > 0) paramlist += QLatin1String(","); else paramlist += QLatin1String(" "); } if (argc) paramlist += QLatin1String("}"); logSignals->append(container->windowTitle() + QLatin1String(": ") + signal + paramlist); } void MainWindow::logException(int code, const QString&source, const QString&desc, const QString&help) { Q_UNUSED(desc); QAxWidget *container = qobject_cast(sender()); if (!container) return; QString str = tr("%1: Exception code %2 thrown by %3"). arg(container->windowTitle()).arg(code).arg(source); logDebug->append(str); logDebug->append(tr("\tDescription: %1").arg(desc)); if (!help.isEmpty()) logDebug->append(tr("\tHelp available at %1").arg(help)); else logDebug->append(tr("\tNo help available.")); } void MainWindow::logMacro(int code, const QString &description, int sourcePosition, const QString &sourceText) { /* FIXME This needs to be rewritten to not use string concatentation, such * that it can be translated in a sane way. */ QString message = tr("Script: "); if (code) message += QString::number(code) + QLatin1String(" "); message += QLatin1String("'") + description + QLatin1String("'"); if (sourcePosition) message += tr(" at position ") + QString::number(sourcePosition); if (!sourceText.isEmpty()) message += QLatin1String(" '") + sourceText + QLatin1String("'"); logMacros->append(message); }