/**************************************************************************** | |
** | |
** 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 <QtGui> | |
#include <qt_windows.h> | |
#include <ActiveQt/ActiveQt> | |
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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(workspace->activeWindow()); | |
if (!container) | |
return; | |
ControlInfo info(this); | |
info.setControl(container); | |
info.exec(); | |
} | |
void MainWindow::on_actionControlProperties_triggered() | |
{ | |
QAxWidget *container = qobject_cast<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(workspace->activeWindow()); | |
if (!container) | |
return; | |
container->doVerb(action->text()); | |
} | |
void MainWindow::on_actionControlDocumentation_triggered() | |
{ | |
QAxWidget *container = qobject_cast<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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<QAxWidget*>(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); | |
} |