Source

pynoto / src / Designer / DesignerWidget.cpp

Full commit
#include <QDebug>
#include <QFile>
#include <QPluginLoader>
#include <QMdiSubWindow>
#include <QMessageBox>
#include <QDir>
#include <QCloseEvent>
#include <QScrollBar>
#include <QTextCodec>
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerComponents>
#include <QtDesigner/QDesignerWidgetBoxInterface>
#include <QtDesigner/QDesignerFormEditorPluginInterface>
#include <QtDesigner/QDesignerFormWindowManagerInterface>
#include <QtDesigner/QDesignerObjectInspectorInterface>
#include <QtDesigner/QDesignerPropertyEditorInterface>

#include <QStringBuilder>
#include <QProcess>
#include "internals/qdesigner_integration_p.h"
#include "internals/pluginmanager_p.h"
#include "internals/formwindowbase_p.h"
#include "DesignerHeader.h"

#include "Include/PynotoApplication.h"
#include "Include/IProjectPlugin.h"
#include "Include/IProject.h"

#include "DesignerWidget.h"
#include "ui_DesignerWidget.h"

class PyNotoIntegration: public qdesigner_internal::QDesignerIntegration
{
public:
    PyNotoIntegration(QDesignerFormEditorInterface *core, QObject *parent = 0):
        qdesigner_internal::QDesignerIntegration(core, parent)
    {
        setSlotNavigationEnabled(true);
    }
};

namespace Designer
{

static QDesignerFormEditorInterface *_iface = NULL;

DesignerWidget::DesignerWidget(const QString& fileName, QWidget *parentWidget) :
    QWidget(parentWidget),
    _ui(new Ui::DesignerWidget),
    _fileName(fileName),
    _form(NULL)
{
    _ui->setupUi(this);
    _project = Aux::plugin<Project::IProjectPlugin*>("project")->project();
}

DesignerWidget::~DesignerWidget()
{
    delete _ui;
    delete _form;
    delete _designer;
}

void DesignerWidget::init()
{
    _ui->splitter_2->setStretchFactor(1, 100);
    if (!_iface){
        _iface = QDesignerComponents::createFormEditor(parentWidget());
        _iface->setTopLevel(parentWidget());
        QDesignerComponents::createTaskMenu(_iface, parentWidget());
        QDesignerComponents::initializePlugins(_iface);
        QDesignerComponents::initializeResources();
    }


    _wb = QDesignerComponents::createWidgetBox(_iface, this);
    _ui->widgetsPlace->layout()->addWidget(_wb);
    _iface->setWidgetBox(_wb);

    _oi = QDesignerComponents::createObjectInspector(_iface, this);
    _ui->objectsPlace->layout()->addWidget(_oi);
    _iface->setObjectInspector(_oi);

    _pe = QDesignerComponents::createPropertyEditor(_iface, this);
    _ui->propertyPlace->layout()->addWidget(_pe);
    _iface->setPropertyEditor(_pe);


    _ae = QDesignerComponents::createActionEditor(_iface, this);
    _ui->actionTabPlace->layout()->addWidget((QWidget*)_ae);
    _iface->setActionEditor(_ae);

    _ui->slotTabPLace->layout()->addWidget(QDesignerComponents::createSignalSlotEditor(_iface, this));

    _designer = new PyNotoIntegration(_iface, this);
    _iface->setIntegration(_designer);

    QList<QObject*> plugins = QPluginLoader::staticInstances();
    plugins += _iface->pluginManager()->instances();

    foreach (QObject *plugin, plugins) {
        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
            if (!formEditorPlugin->isInitialized()){
                formEditorPlugin->initialize(_iface);
            }
        }
    }

    connect(_designer->core()->formWindowManager()->actionUndo(), SIGNAL(changed()), SLOT(onUndoAvailable()));
    connect(_designer->core()->formWindowManager()->actionRedo(), SIGNAL(changed()), SLOT(onRedoAvailable()));
    connect(_designer->core()->formWindowManager()->actionCopy(), SIGNAL(changed()), SLOT(onCopyAvailable()));
    connect(_designer->core()->formWindowManager()->actionPaste(), SIGNAL(changed()), SLOT(onPasteAvailable()));
    connect(_designer, SIGNAL(navigateToSlot(QString,QString,QStringList)), SLOT(onNavigateToSlot(QString,QString,QStringList)));
}

QWidget* DesignerWidget::header()
{
    DesignerHeader * head = new DesignerHeader;
    head->setFileName(_fileName);
    connect(this, SIGNAL(modificationChanged(bool)), head, SLOT(modificationChanged(bool)));
    connect(head, SIGNAL(switchWidgets()), SLOT(onSwitchWidgets()));
    connect(head, SIGNAL(switchTabOrder()), SLOT(onSwitchTabOrder()));
    connect(head, SIGNAL(switchBuddies()), SLOT(onSwitchBuddies()));
    return head;
}

bool DesignerWidget::save()
{
    QFile file(_fileName);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
        file.write(_form->contents().toUtf8());
        file.close();
        _form->setDirty(false);
        onFormChanged();
        renderPyFile();
        return true;
    }
    return false;
}

bool DesignerWidget::load()
{
    if (!QFile::exists(_fileName))
        return false;

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    _form = qobject_cast<qdesigner_internal::FormWindowBase *>(_iface->formWindowManager()->createFormWindow(this));
    _form->setFileName(_fileName);

    QFile f(_fileName);
    f.open(QIODevice::ReadOnly | QIODevice::Text);
    _form->setContents(f.readAll());
    f.close();

    qdesigner_internal::FormWindowBase::setupDefaultAction(_form);
    _designer->setupFormWindow(_form);

    QMdiSubWindow *wnd = _ui->formPlace->addSubWindow(_form, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
    const QSize containerSize = _form->mainContainer()->size();
    const QSize containerMinimumSize = _form->mainContainer()->minimumSize();
    const QSize containerMaximumSize = _form->mainContainer()->maximumSize();
    const QSize decorationSize = wnd->geometry().size() - wnd->contentsRect().size();

    wnd->resize(containerSize+decorationSize);
    wnd->setMinimumSize(containerMinimumSize+decorationSize);

    if( containerMaximumSize == QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) )
        wnd->setMaximumSize(containerMaximumSize);
    else
        wnd->setMaximumSize(containerMaximumSize+decorationSize);
    wnd->setWindowTitle( _form->mainContainer()->windowTitle() );
    wnd->show();

    _iface->formWindowManager()->setActiveFormWindow(_form);
    connect(_form, SIGNAL(changed()), SLOT(onFormChanged()));
    _form->setDirty(false);
    return true;
}

bool DesignerWidget::reload()
{
    QFile f(_fileName);
    f.open(QIODevice::ReadOnly | QIODevice::Text);
    _form->setContents(f.readAll());
    f.close();
    return true;
}


void DesignerWidget::showEvent(QShowEvent *)
{
    _ui->splitter_2->setSizes(QList<int>() << 250 << _ui->splitter_2->width() - 450 << 250);
}


bool DesignerWidget::isUndoAvailable()
{
    return _designer->core()->formWindowManager()->actionUndo()->isEnabled();
}

bool DesignerWidget::isRedoAvailable()
{
    return _designer->core()->formWindowManager()->actionRedo()->isEnabled();
}

bool DesignerWidget::canCopy()
{
    return _designer->core()->formWindowManager()->actionCopy()->isEnabled();
}

bool DesignerWidget::canPaste()
{
    return _designer->core()->formWindowManager()->actionPaste()->isEnabled();
}

QString DesignerWidget::fileName()
{
    return _fileName;
}

void DesignerWidget::onUndoAvailable()
{
    emit undoAvailable(_designer->core()->formWindowManager()->actionUndo()->isEnabled());
}

void DesignerWidget::onRedoAvailable()
{
    emit redoAvailable(_designer->core()->formWindowManager()->actionRedo()->isEnabled());
}

void DesignerWidget::onCopyAvailable()
{
    emit copyAvailable(_designer->core()->formWindowManager()->actionCopy()->isEnabled());
}

void DesignerWidget::onPasteAvailable()
{
    emit pasteAvailable(_designer->core()->formWindowManager()->actionPaste()->isEnabled());
}

void DesignerWidget::undo()
{
    _designer->core()->formWindowManager()->actionUndo()->trigger();
    emit modificationChanged(_form->isDirty());
}

void DesignerWidget::redo()
{
    _designer->core()->formWindowManager()->actionRedo()->trigger();
    emit modificationChanged(_form->isDirty());
}

void DesignerWidget::copy()
{
    _designer->core()->formWindowManager()->actionCopy()->trigger();
}

void DesignerWidget::cut()
{
    _designer->core()->formWindowManager()->actionCut()->trigger();
}

void DesignerWidget::paste()
{
    _designer->core()->formWindowManager()->actionPaste()->trigger();
}

void DesignerWidget::del()
{
    _designer->core()->formWindowManager()->actionDelete()->trigger();
}

void DesignerWidget::onFormChanged()
{
    emit modificationChanged(_form->isDirty());
}

bool DesignerWidget::isModified()
{
    return _form->isDirty();
}

void DesignerWidget::onSwitchWidgets()
{
    QDesignerFormWindowManagerInterface *formWindowManager = _iface->formWindowManager();
    for (int i=0; i<formWindowManager->formWindowCount(); ++i) {
        QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
        if (formWindow == _form)
            formWindow->editWidgets();
    }
}

void DesignerWidget::onSwitchTabOrder()
{
    QDesignerFormWindowManagerInterface *formWindowManager = _designer->core()->formWindowManager();
    for (int i=0; i<formWindowManager->formWindowCount(); ++i) {
        QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
        if (formWindow == _form)
            formWindow->setCurrentTool(3);
    }
}

void DesignerWidget::onSwitchBuddies()
{
    QDesignerFormWindowManagerInterface *formWindowManager = _designer->core()->formWindowManager();
    for (int i=0; i<formWindowManager->formWindowCount(); ++i) {
        QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
        if (formWindow == _form)
            formWindow->setCurrentTool(2);
    }
}

void DesignerWidget::onNavigateToSlot(const QString& objectName, const QString& signalSignature, const QStringList& parameterNames)
{
    qDebug() << "navigate" << objectName << signalSignature << parameterNames;
}

void DesignerWidget::renderPyFile()
{
    QString uic = _project->pythonUic();
    if (!uic.isEmpty()){
        QFileInfo info = QFileInfo(_fileName);
        QString pyFile = info.absoluteDir().path() % QDir::separator() % "Ui_" % info.baseName() % ".py";

        QStringList args;
        args << uic;
        args << "-o";
        args << pyFile;
        args << _fileName;
        QProcess proc;
        proc.start(_project->interpretExec(), args);
        proc.waitForFinished();
        QFile file(pyFile);
        if (file.open(QIODevice::ReadOnly)){
            QString cnt = file.readAll();
            file.close();

            QRegExp from("_fromUtf8\\(\"(.*)\"\\)");
            from.setMinimal(true);
            cnt = cnt.replace(from, "\"\\1\"");
            cnt = cnt.replace(QRegExp("try:.+lambda s: s"), "");

            cnt = cnt.replace("try:\n\t_fromUtf8 = QtCore.QString.fromUtf8\nexcept AttributeError:\n\t_fromUtf8 = lambda s: s", "");

            QFile out(pyFile);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
                QTextStream tout(&file);
                tout << cnt;
                out.close();
            }
        }
    }
}

void DesignerWidget::activate()
{
    _iface->setIntegration(_designer);
    _iface->setObjectInspector(_oi);
    _iface->setWidgetBox(_wb);
    _iface->setPropertyEditor(_pe);
    _iface->setActionEditor(_ae);

    _iface->formWindowManager()->setActiveFormWindow(_form);

    emit undoAvailable(_designer->core()->formWindowManager()->actionUndo()->isEnabled());
    emit redoAvailable(_designer->core()->formWindowManager()->actionRedo()->isEnabled());
    emit copyAvailable(_designer->core()->formWindowManager()->actionCopy()->isEnabled());
    emit pasteAvailable(_designer->core()->formWindowManager()->actionPaste()->isEnabled());
    emit modificationChanged(isModified());
}

}