/*****************************************************************************
* luaEngine Lua Engine for Qt
* Copyright (C) 2018-2019 Syping
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/

#include "LuaEngineRegistry.h"
#include "LuaEngineGui.h"
#include <QPlainTextEdit>
#include <QStackedWidget>
#include <QRadioButton>
#include <QProgressBar>
#include <QApplication>
#include <QMainWindow>
#include <QToolButton>
#include <QPushButton>
#include <QMessageBox>
#include <QMetaObject>
#include <QMetaMethod>
#include <QTextStream>
#include <QSpacerItem>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QSizePolicy>
#include <QTabWidget>
#include <QEventLoop>
#include <QTextEdit>
#include <QLineEdit>
#include <QGroupBox>
#include <QCheckBox>
#include <QToolBar>
#include <QMenuBar>
#include <QProcess>
#include <QWindow>
#include <QObject>
#include <QDialog>
#include <QTimer>
#include <QLabel>
#include <QDebug>

LuaEngineGui::LuaEngineGui(QObject *parent, bool loadBaseLibraries) : LuaEngine(parent, loadBaseLibraries)
{
    L = luaState();
    pushClass(L);
}

void LuaEngineGui::pushClass(lua_State *L_p)
{
    // Update UI
    pushFunction(L_p, "updateUi", updateUi);
    pushVariant(L_p, "AllEvents", (int)QEventLoop::AllEvents);
    pushVariant(L_p, "ExcludeUserInputEvents", (int)QEventLoop::ExcludeUserInputEvents);
    pushVariant(L_p, "ExcludeSocketNotifiers", (int)QEventLoop::ExcludeSocketNotifiers);
    pushVariant(L_p, "WaitForMoreEvents", (int)QEventLoop::WaitForMoreEvents);

    // File Dialog
    pushFunction(L_p, "showFileDialog", showFileDialog);
    pushVariant(L_p, "OpenFileDialog", 0);
    pushVariant(L_p, "SaveFileDialog", 1);
    pushVariant(L_p, "OpenFolderDialog", 2);

    // Message Box
    pushFunction(L_p, "showMessageBox", showMessageBox);
    pushVariant(L_p, "InfoMessageBox", 0);
    pushVariant(L_p, "WarningMessageBox", 1);
    pushVariant(L_p, "CriticalMessageBox", 2);
    pushVariant(L_p, "QuestionMessageBox", 3);

    // Gui
    pushVariant(L_p, "GuiExecuted", "GuiExecuted");

    // Object
    pushFunction(L_p, "getWindow", getWindow);
    pushFunction(L_p, "setObjectImage", setObjectImage);

    // Widget
    pushFunction(L_p, "closeWidget", closeWidget);
    pushFunction(L_p, "executeWidget", executeWidget);
    pushFunction(L_p, "showWidget", showWidget);
    pushFunction(L_p, "isWidgetChecked", isWidgetChecked);
    pushFunction(L_p, "isWidgetEnabled", isWidgetEnabled);
    pushFunction(L_p, "isWidgetVisible", isWidgetVisible);
    pushFunction(L_p, "getWidgetPixelRatio", getWidgetPixelRatio);
    pushFunction(L_p, "getWidgetText", getWidgetText);
    pushFunction(L_p, "setWidgetChecked", setWidgetChecked);
    pushFunction(L_p, "setWidgetEnabled", setWidgetEnabled);
    pushFunction(L_p, "setWidgetFixed", setWidgetFixed);
    pushFunction(L_p, "setWidgetLayout", setWidgetLayout);
    pushFunction(L_p, "setWidgetMaximum", setWidgetMaximum);
    pushFunction(L_p, "setWidgetMinimum", setWidgetMinimum);
    pushFunction(L_p, "setWidgetReadOnly", setWidgetReadOnly);
    pushFunction(L_p, "setWidgetSize", setWidgetSize);
    pushFunction(L_p, "setWidgetText", setWidgetText);
    pushFunction(L_p, "setWidgetValue", setWidgetValue);
    pushFunction(L_p, "setWidgetVisible", setWidgetVisible);
    pushFunction(L_p, "widgetAddText", widgetAddText);
    pushVariant(L_p, "ShowCurrent", 0);
    pushVariant(L_p, "ShowNormal", 1);
    pushVariant(L_p, "ShowDefault", 2);
    pushVariant(L_p, "ShowMinimised", 3);
    pushVariant(L_p, "ShowMaximised", 4);
    pushVariant(L_p, "ShowFullscreen", 5);

    // Check Box
    pushFunction(L_p, "createCheckBox", createCheckBox);

    // Dialog
    pushFunction(L_p, "createDialog", createDialog);

    // Group Box
    pushFunction(L_p, "createGroupBox", createGroupBox);

    // Label
    pushFunction(L_p, "createLabel", createLabel);

    // Layout
    pushFunction(L_p, "createLayout", createLayout);
    pushFunction(L_p, "layoutAddLayout", layoutAddLayout);
    pushFunction(L_p, "layoutAddWidget", layoutAddWidget);
    pushFunction(L_p, "setLayoutMargins", setLayoutMargins);
    pushVariant(L_p, "HorizontalLayout", 0);
    pushVariant(L_p, "VerticalLayout", 1);

    // Line Edit
    pushFunction(L_p, "createLineEdit", createLineEdit);

    // Main Window
    pushFunction(L_p, "createMainWindow", createMainWindow);
    pushFunction(L_p, "createCentralWidget", createCentralWidget);

    // Menu
    pushFunction(L_p, "createMenu", createMenu);
    pushFunction(L_p, "createMenuBar", createMenuBar);
    pushFunction(L_p, "createMenuEntry", createMenuEntry);
    pushFunction(L_p, "createMenuSeparator", createMenuSeparator);
    pushFunction(L_p, "setMenuShortcut", setMenuShortcut);

    // Plain Text Edit
    pushFunction(L_p, "createPlainTextEdit", createPlainTextEdit);

    // Progress Bar
    pushFunction(L_p, "createProgressBar", createProgressBar);

    // Push Button
    pushFunction(L_p, "createPushButton", createPushButton);

    // Radio Button
    pushFunction(L_p, "createRadioButton", createRadioButton);

    // Spacer Item
    pushFunction(L_p, "createSpacerItem", createSpacerItem);

    // Stack Switcher
    pushFunction(L_p, "createStackSwitch", createStackSwitch);
    pushFunction(L_p, "createWidgetStack", createWidgetStack);
    pushFunction(L_p, "addWidgetAsStack", addWidgetAsStack);

    // Tab Bar
    pushFunction(L_p, "createTabBar", createTabBar);
    pushFunction(L_p, "createWidgetTab", createWidgetTab);
    pushFunction(L_p, "addWidgetAsTab", addWidgetAsTab);

    // Text Edit
    pushFunction(L_p, "createTextEdit", createTextEdit);

    // Tool Bar
    pushFunction(L_p, "createToolBar", createToolBar);
    pushVariant(L_p, "AllToolBarAreas", (int)Qt::AllToolBarAreas);
    pushVariant(L_p, "LeftToolBarArea", (int)Qt::LeftToolBarArea);
    pushVariant(L_p, "RightToolBarArea", (int)Qt::RightToolBarArea);
    pushVariant(L_p, "TopToolBarArea", (int)Qt::TopToolBarArea);
    pushVariant(L_p, "BottomToolBarArea", (int)Qt::BottomToolBarArea);

    // Tool Button
    pushFunction(L_p, "createToolButton", createToolButton);

    // Size Policy
    pushVariant(L_p, "SizePolicyFixed", (int)QSizePolicy::Fixed);
    pushVariant(L_p, "SizePolicyMinimum", (int)QSizePolicy::Minimum);
    pushVariant(L_p, "SizePolicyMaximum", (int)QSizePolicy::Maximum);
    pushVariant(L_p, "SizePolicyPreferred", (int)QSizePolicy::Preferred);
    pushVariant(L_p, "SizePolicyExpanding", (int)QSizePolicy::Expanding);
    pushVariant(L_p, "SizePolicyIgnored", (int)QSizePolicy::Ignored);
}

void LuaEngineGui::pushClass(LuaEngine *luaEngine)
{
    pushClass(luaEngine->luaState());
}

int LuaEngineGui::updateUi(lua_State *L_p)
{
    QEventLoop::ProcessEventsFlags events = QEventLoop::AllEvents;
    if (getArgumentCount(L_p) >= 1) {
        events = (QEventLoop::ProcessEventsFlags)getVariant(L_p, 1).toInt();
    }
    QApplication::processEvents(events);
    return 0;
}

int LuaEngineGui::showFileDialog(lua_State *L_p)
{
    QWidget *parent = nullptr;
    QString dialogTitle = "LuaEngine";
    QString fileFormats = "All files (*)";
    QFileDialog::FileMode fileMode = QFileDialog::ExistingFile;
    QFileDialog::Options fileOptions;
    QFileDialog::AcceptMode fileAcceptMode = QFileDialog::AcceptOpen;
    if (getArgumentCount(L_p) >= 1) {
        switch (getVariant(L_p, 1).toInt()) {
        case 1:
            fileMode = QFileDialog::AnyFile;
            fileAcceptMode = QFileDialog::AcceptSave;
            break;
        case 2:
            fileFormats = QString();
            fileMode = QFileDialog::Directory;
            fileOptions = QFileDialog::ShowDirsOnly;
            break;
        }
        if (getArgumentCount(L_p) >= 2) {
            dialogTitle = getVariant(L_p, 2).toString();
            if (getArgumentCount(L_p) >= 3) {
                if (fileMode == QFileDialog::Directory) {
                    void *pointer = getPointer(L_p, 3);
                    if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
                        parent = (QWidget*)pointer;
                    }
                }
                else {
                    fileFormats = getVariant(L_p, 3).toString();
                    if (getArgumentCount(L_p) >= 4) {
                        void *pointer = getPointer(L_p, 4);
                        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
                            parent = (QWidget*)pointer;
                        }
                    }
                }
            }
        }
    }
    QFileDialog fileDialog(parent);
#if QT_VERSION >= 0x050900
    fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
    fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
    fileDialog.setWindowTitle(dialogTitle);
    fileDialog.setAcceptMode(fileAcceptMode);
    fileDialog.setNameFilter(fileFormats);
    fileDialog.setFileMode(fileMode);
    fileDialog.setOptions(fileOptions);
    if (fileDialog.exec()) {
        int returnInt = 0;
        for (const QString &fileName : fileDialog.selectedFiles()) {
            returnInt++;
            pushVariant(L_p, fileName);
        }
        return returnInt;
    }
    return 0;
}

int LuaEngineGui::showMessageBox(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        QWidget *parent = nullptr;
        QString boxMessage = getVariant(L_p, 2).toString();
        QString boxTitle = "LuaEngine";
        if (getArgumentCount(L_p) >= 3) {
            boxTitle = getVariant(L_p, 3).toString();
            if (getArgumentCount(L_p) >= 4) {
                void *pointer = getPointer(L_p, 4);
                if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
                    parent = (QWidget*)pointer;
                }
            }
        }
        int returnInt = 0;
        switch (getVariant(L_p, 1).toInt()) {
        case 1:
            QMessageBox::warning(parent, boxTitle, boxMessage);
            break;
        case 2:
            QMessageBox::critical(parent, boxTitle, boxMessage);
            break;
        case 3:
        {
            pushVariant(L_p, (QMessageBox::Yes == QMessageBox::question(parent, boxTitle, boxMessage)));
            returnInt = 1;
        }
            break;
        default:
            QMessageBox::information(parent, boxTitle, boxMessage);
        }
        return returnInt;
    }
    else {
        return 0;
    }
}

int LuaEngineGui::closeWidget(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            QWidget *widget = (QWidget*)pointer;
            widget->close();
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::executeWidget(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            QVariant isFixed = ((QObject*)pointer)->property("isFixed");
            QVariant isSizeSet = ((QObject*)pointer)->property("isSizeSet");
            if (isFixed.type() == QVariant::Bool && isFixed.toBool()) {
                if (!(isSizeSet.type() == QVariant::Bool && isSizeSet.toBool())) {
                    ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                    ((QWidget*)pointer)->setMaximumSize(((QWidget*)pointer)->sizeHint());
                }
            }
            else {
                if (!(isSizeSet.type() == QVariant::Bool && isSizeSet.toBool())) {
                    ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                    ((QWidget*)pointer)->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
                }
            }
            if (((QObject*)pointer)->inherits("QDialog")) {
                ((QDialog*)pointer)->exec();
            }
            else {
                ((QWidget*)pointer)->show();
                QEventLoop executeLoop;
                while (((QWidget*)pointer)->isVisible()) {
                    QTimer::singleShot(100, &executeLoop, SLOT(quit()));
                    executeLoop.exec();
                }
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::showWidget(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            int showMode = 0;
            if (getArgumentCount(L_p) >= 2) {
                showMode = getVariant(L_p, 2).toInt();
            }
            QVariant isFixed = ((QObject*)pointer)->property("isFixed");
            QVariant isSizeSet = ((QObject*)pointer)->property("isSizeSet");
            if (isFixed.type() == QVariant::Bool && isFixed.toBool()) {
                if (!(isSizeSet.type() == QVariant::Bool && isSizeSet.toBool())) {
                    ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                    ((QWidget*)pointer)->setMaximumSize(((QWidget*)pointer)->sizeHint());
                }
            }
            else {
                if (!(isSizeSet.type() == QVariant::Bool && isSizeSet.toBool())) {
                    ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                    ((QWidget*)pointer)->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
                }
            }
            switch (showMode) {
            case 1:
                ((QWidget*)pointer)->showNormal();
                break;
            case 2:
#ifdef Q_OS_ANDROID
                ((QWidget*)pointer)->showMaximized();
#else
                ((QWidget*)pointer)->showNormal();
#endif
                break;
            case 3:
                ((QWidget*)pointer)->showMinimized();
                break;
            case 4:
                ((QWidget*)pointer)->showMaximized();
                break;
            case 5:
                ((QWidget*)pointer)->showFullScreen();
                break;
            default:
                ((QWidget*)pointer)->show();
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setLayoutMargins(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 5) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
            ((QLayout*)pointer)->setContentsMargins(getVariant(L_p, 2).toInt(), getVariant(L_p, 3).toInt(), getVariant(L_p, 4).toInt(), getVariant(L_p, 5).toInt());
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setMenuShortcut(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QAction")) {
            ((QAction*)pointer)->setShortcut(QKeySequence::fromString(getVariant(L_p, 2).toString()));
            ((QAction*)pointer)->setShortcutContext(Qt::ApplicationShortcut);
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setObjectImage(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            QString imagePath = getVariant(L_p, 2).toString();
            if (QFileInfo(imagePath).isRelative()) {
                LuaEngine *engine = (LuaEngine*)engineRegistry->getEngine(L_p);
                QString engineType = engine->property("EngineType").toString();
                if (engineType == "Runtime") {
                    QString scriptPath = engine->property("ScriptPath").toString();
                    QString scriptDirPath = QFileInfo(scriptPath).canonicalPath();
                    QString newImagePath = QString("%1/%2").arg(scriptDirPath, imagePath);
                    if (QFile(newImagePath).exists()) {
                        imagePath = newImagePath;
                    }
                }
                else {
                    QString newImagePath = QString("%1/%2").arg(QApplication::applicationDirPath(), imagePath);
                    if (QFile(newImagePath).exists()) {
                        imagePath = newImagePath;
                    }
                }
            }
            double pixelRatio = 1;
            if (getArgumentCount(L_p) >= 3) {
                bool pixelRatioOk;
                double newPixelRatio = getVariant(L_p, 3).toDouble(&pixelRatioOk);
                if (pixelRatioOk) {
                    pixelRatio = newPixelRatio;
                }
            }
            if (((QObject*)pointer)->inherits("QAction")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                QIcon objectIcon;
                objectIcon.addPixmap(objectImage);
                ((QAction*)pointer)->setIcon(objectIcon);
            }
            else if (((QObject*)pointer)->inherits("QCheckBox")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                QIcon objectIcon;
                objectIcon.addPixmap(objectImage);
                ((QCheckBox*)pointer)->setIcon(objectIcon);
            }
            else if (((QObject*)pointer)->inherits("QLabel")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                ((QLabel*)pointer)->setPixmap(objectImage);
            }
            else if (((QObject*)pointer)->inherits("QPushButton")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                QIcon objectIcon;
                objectIcon.addPixmap(objectImage);
                ((QPushButton*)pointer)->setIcon(objectIcon);
            }
            else if (((QObject*)pointer)->inherits("QRadioButton")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                QIcon objectIcon;
                objectIcon.addPixmap(objectImage);
                ((QRadioButton*)pointer)->setIcon(objectIcon);
            }
            else if (((QObject*)pointer)->inherits("QToolButton")) {
                QPixmap objectImage(imagePath);
                objectImage.setDevicePixelRatio(pixelRatio);
                QIcon objectIcon;
                objectIcon.addPixmap(objectImage);
                ((QToolButton*)pointer)->setIcon(objectIcon);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetChecked(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            bool isChecked = true;
            if (getArgumentCount(L_p) >= 2) {
                isChecked = getVariant(L_p, 2).toBool();
            }
            if (((QObject*)pointer)->inherits("QCheckBox")) {
                ((QCheckBox*)pointer)->setChecked(isChecked);
            }
            else if (((QObject*)pointer)->inherits("QRadioButton")) {
                ((QRadioButton*)pointer)->setChecked(isChecked);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetEnabled(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            bool isEnabled = true;
            if (getArgumentCount(L_p) >= 2) {
                isEnabled = getVariant(L_p, 2).toBool();
            }
            if (((QObject*)pointer)->inherits("QWidget")) {
                ((QWidget*)pointer)->setEnabled(isEnabled);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetFixed(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            bool isFixed = true;
            if (getArgumentCount(L_p) >= 2) {
                isFixed = getVariant(L_p, 2).toBool();
            }
            ((QObject*)pointer)->setProperty("isFixed", isFixed);
            QVariant isSizeSet = ((QObject*)pointer)->property("isSizeSet");
            if (isFixed && ((QWidget*)pointer)->isVisible()) {
                ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                ((QWidget*)pointer)->setMaximumSize(((QWidget*)pointer)->sizeHint());
            }
            else if (isFixed && (isSizeSet.type() == QVariant::Bool && isSizeSet.toBool())) {
                ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->size());
                ((QWidget*)pointer)->setMaximumSize(((QWidget*)pointer)->size());
            }
            else if (((QWidget*)pointer)->isVisible()) {
                ((QWidget*)pointer)->setMinimumSize(((QWidget*)pointer)->sizeHint());
                ((QWidget*)pointer)->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetLayout(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            QWidget *widget = (QWidget*)pointer;
            void *l_pointer = getPointer(L_p, 2);
            if (l_pointer!= NULL && ((QObject*)l_pointer)->inherits("QLayout")) {
                widget->setLayout((QLayout*)l_pointer);
            }
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetMaximum(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QProgressBar")) {
                ((QProgressBar*)pointer)->setMaximum(getVariant(L_p, 2).toInt());
            }
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetMinimum(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QProgressBar")) {
                ((QProgressBar*)pointer)->setMinimum(getVariant(L_p, 2).toInt());
            }
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetReadOnly(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            bool isReadOnly = true;
            if (getArgumentCount(L_p) >= 2) {
                isReadOnly = getVariant(L_p, 2).toBool();
            }
            if (((QObject*)pointer)->inherits("QPlainTextEdit")) {
                ((QPlainTextEdit*)pointer)->setReadOnly(isReadOnly);
            }
            else if (((QObject*)pointer)->inherits("QTextEdit")) {
                ((QTextEdit*)pointer)->setReadOnly(isReadOnly);
            }
            else if (((QObject*)pointer)->inherits("QLineEdit")) {
                ((QLineEdit*)pointer)->setReadOnly(isReadOnly);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetSize(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 3) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            QVariant isFixed = ((QObject*)pointer)->property("isFixed");
            if (isFixed.type() == QVariant::Bool && isFixed.toBool()) {
                ((QWidget*)pointer)->setMinimumSize(getVariant(L_p, 2).toInt(), getVariant(L_p, 3).toInt());
                ((QWidget*)pointer)->setMaximumSize(getVariant(L_p, 2).toInt(), getVariant(L_p, 3).toInt());
                ((QWidget*)pointer)->resize(getVariant(L_p, 2).toInt(), getVariant(L_p, 3).toInt());
                ((QObject*)pointer)->setProperty("isSizeSet", true);
            }
            else {
                ((QWidget*)pointer)->resize(getVariant(L_p, 2).toInt(), getVariant(L_p, 3).toInt());
                ((QObject*)pointer)->setProperty("isSizeSet", true);
            }
            return 0;
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetText(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QCheckBox")) {
                ((QCheckBox*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QGroupBox")) {
                ((QGroupBox*)pointer)->setTitle(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QLabel")) {
                ((QLabel*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QLineEdit")) {
                ((QLineEdit*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QPlainTextEdit")) {
                ((QPlainTextEdit*)pointer)->setPlainText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QProgressBar")) {
                QString progressBarText = getVariant(L_p, 2).toString();
                ((QProgressBar*)pointer)->setFormat(progressBarText);
                ((QProgressBar*)pointer)->setTextVisible(!progressBarText.isEmpty());
            }
            else if (((QObject*)pointer)->inherits("QPushButton")) {
                ((QPushButton*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QRadioButton")) {
                ((QRadioButton*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QTextEdit")) {
                ((QTextEdit*)pointer)->setHtml(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QToolButton")) {
                ((QToolButton*)pointer)->setText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QWidget")) {
                ((QWidget*)pointer)->setWindowTitle(getVariant(L_p, 2).toString());
            }
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetValue(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QProgressBar")) {
                ((QProgressBar*)pointer)->setValue(getVariant(L_p, 2).toInt());
            }
        }
    }
    return 0;
}

int LuaEngineGui::setWidgetVisible(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QWidget")) {
                ((QWidget*)pointer)->setVisible(getVariant(L_p, 2).toBool());
            }
        }
    }
    return 0;
}

int LuaEngineGui::layoutAddLayout(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
            void *l_pointer = getPointer(L_p, 2);
            if (l_pointer!= NULL && ((QObject*)l_pointer)->inherits("QLayout")) {
                if (((QObject*)pointer)->inherits("QVBoxLayout")) {
                    QVBoxLayout *layout = (QVBoxLayout*)pointer;
                    layout->addLayout((QLayout*)l_pointer);
                }
                else if (((QObject*)pointer)->inherits("QHBoxLayout")) {
                    QHBoxLayout *layout = (QHBoxLayout*)pointer;
                    layout->addLayout((QLayout*)l_pointer);
                }
            }
        }
    }
    return 0;
}

int LuaEngineGui::layoutAddWidget(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
            QLayout *layout = (QLayout*)pointer;
            void *w_pointer = getPointer(L_p, 2);
            if (w_pointer!= NULL && ((QObject*)w_pointer)->inherits("QWidget")) {
                layout->addWidget((QWidget*)w_pointer);
            }
        }
    }
    return 0;
}

int LuaEngineGui::widgetAddText(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QLineEdit")) {
                ((QLineEdit*)pointer)->setText(((QLineEdit*)pointer)->text() + getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QPlainTextEdit")) {
                ((QPlainTextEdit*)pointer)->appendPlainText(getVariant(L_p, 2).toString());
            }
            else if (((QObject*)pointer)->inherits("QTextEdit")) {
                ((QTextEdit*)pointer)->append(getVariant(L_p, 2).toString());
            }
        }
    }
    return 0;
}

int LuaEngineGui::addWidgetAsStack(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *w_pointer = getPointer(L_p, 1);
        void *t_pointer = getPointer(L_p, 2);
        if (w_pointer != NULL && t_pointer != NULL && ((QObject*)w_pointer)->inherits("QWidget") && ((QObject*)t_pointer)->inherits("QStackedWidget")) {
            ((QStackedWidget*)t_pointer)->addWidget((QWidget*)w_pointer);
        }
    }
    return 0;
}

int LuaEngineGui::addWidgetAsTab(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 3) {
        void *w_pointer = getPointer(L_p, 1);
        void *t_pointer = getPointer(L_p, 3);
        if (w_pointer != NULL && t_pointer != NULL && ((QObject*)w_pointer)->inherits("QWidget") && ((QObject*)t_pointer)->inherits("QTabWidget")) {
            ((QTabWidget*)t_pointer)->addTab(((QWidget*)w_pointer), getVariant(L_p, 2).toString());
        }
    }
    return 0;
}

int LuaEngineGui::createCentralWidget(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMainWindow")) {
            QWidget *centralWidget = new QWidget((QWidget*)pointer);
            centralWidget->setObjectName(nameForPointer(centralWidget));
            ((QMainWindow*)pointer)->setCentralWidget(centralWidget);
            pushPointer(L_p, centralWidget);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createCheckBox(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString labelText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        labelText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QCheckBox *checkBox = new QCheckBox(parent);
    checkBox->setObjectName(nameForPointer(checkBox));
    checkBox->setText(labelText);
    if (layout != nullptr) {
        layout->addWidget(checkBox);
    }
    pushPointer(L_p, checkBox);
    return 1;
}

int LuaEngineGui::createDialog(lua_State *L_p)
{
    QWidget *parent = nullptr;
    QString windowTitle = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        windowTitle = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            void *pointer = getPointer(L_p, 2);
            if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
                parent = (QWidget*)pointer;
            }
        }
    }
    QDialog *dialog = new QDialog(parent);
#if QT_VERSION >= 0x050900
    dialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#else
    dialog->setWindowFlags(dialog->windowFlags()^Qt::WindowContextHelpButtonHint);
#endif
    dialog->setObjectName(nameForPointer(dialog));
    dialog->setWindowTitle(windowTitle);
    pushPointer(L_p, dialog);
    return 1;
}

int LuaEngineGui::createGroupBox(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString groupBoxTitle = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        groupBoxTitle = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QGroupBox *groupBox = new QGroupBox(parent);
    groupBox->setObjectName(nameForPointer(groupBox));
    groupBox->setTitle(groupBoxTitle);
    if (layout != nullptr) {
        layout->addWidget(groupBox);
    }
    pushPointer(L_p, groupBox);
    return 1;
}

int LuaEngineGui::createLabel(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString labelText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        labelText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QLabel *label = new QLabel(parent);
    label->setObjectName(nameForPointer(label));
    label->setText(labelText);
    if (layout != nullptr) {
        layout->addWidget(label);
    }
    pushPointer(L_p, label);
    return 1;
}

int LuaEngineGui::createLayout(lua_State *L_p)
{
    QWidget *parent = nullptr;
    QLayout *layoutParent = nullptr;
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 2);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMainWindow")) {
            parent = ((QMainWindow*)pointer)->centralWidget();
        }
        else if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            parent = (QWidget*)pointer;
        }
        else if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
            layoutParent = (QLayout*)pointer;
        }
    }
    void *layout;
    int layoutType = 0;
    if (getArgumentCount(L_p) >= 1) {
        layoutType = getVariant(L_p, 1).toInt();
    }
    switch (layoutType) {
    case 0:
        layout = new QHBoxLayout(parent);
        break;
    default:
        layout = new QVBoxLayout(parent);
    }
    ((QObject*)layout)->setObjectName(nameForPointer(layout));
    if (layoutParent != nullptr) {
        if (layoutParent->inherits("QVBoxLayout")) {
            ((QVBoxLayout*)layoutParent)->addLayout((QLayout*)layout);
        }
        else if (layoutParent->inherits("QHBoxLayout")) {
            ((QHBoxLayout*)layoutParent)->addLayout((QLayout*)layout);
        }
    }
    pushPointer(L_p, layout);
    return 1;
}

int LuaEngineGui::createLineEdit(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString editText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        editText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QLineEdit *lineEdit = new QLineEdit(parent);
    lineEdit->setObjectName(nameForPointer(lineEdit));
    lineEdit->setText(editText);
    if (layout != nullptr) {
        layout->addWidget(lineEdit);
    }
    pushPointer(L_p, lineEdit);
    return 1;
}

int LuaEngineGui::createMainWindow(lua_State *L_p)
{
    QWidget *parent = nullptr;
    QString windowTitle = "LuaEngine";
    bool centralWidget = true;
    if (getArgumentCount(L_p) >= 1) {
        windowTitle = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            centralWidget = getVariant(L_p, 2).toBool();
            if (getArgumentCount(L_p) >= 3) {
                void *pointer = getPointer(L_p, 3);
                if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
                    parent = (QWidget*)pointer;
                }
            }
        }
    }
    QMainWindow *mainWindow = new QMainWindow(parent);
    mainWindow->setObjectName(nameForPointer(mainWindow));
    mainWindow->setWindowTitle(windowTitle);
    if (centralWidget) {
        QWidget *centralWidget = new QWidget(mainWindow);
        centralWidget->setObjectName(nameForPointer(centralWidget));
        mainWindow->setCentralWidget(centralWidget);
    }
    pushPointer(L_p, mainWindow);
    return 1;
}

int LuaEngineGui::createMenu(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 2);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMenuBar")) {
            QMenu *menu = new QMenu((QWidget*)pointer);
            menu->setObjectName(nameForPointer(menu));
            menu->setTitle(getVariant(L_p, 1).toString());
            ((QMenuBar*)pointer)->addAction(menu->menuAction());
            pushPointer(L_p, menu);
            return 1;
        }
        else if (pointer != NULL && ((QObject*)pointer)->inherits("QMenu")) {
            QMenu *menu = new QMenu((QWidget*)pointer);
            menu->setObjectName(nameForPointer(menu));
            menu->setTitle(getVariant(L_p, 1).toString());
            ((QMenu*)pointer)->addAction(menu->menuAction());
            pushPointer(L_p, menu);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createMenuBar(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMainWindow")) {
            QMenuBar *menuBar = new QMenuBar((QWidget*)pointer);
            menuBar->setObjectName(nameForPointer(menuBar));
            ((QMainWindow*)pointer)->setMenuBar(menuBar);
            pushPointer(L_p, menuBar);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createMenuEntry(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 2);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMenu")) {
            QAction *action = new QAction(getVariant(L_p, 1).toString(), (QObject*)pointer);
            action->setObjectName(nameForPointer(action));
            ((QMenu*)pointer)->addAction(action);
            if (getArgumentCount(L_p) >= 3) {
                action->setShortcut(QKeySequence::fromString(getVariant(L_p, 3).toString()));
                action->setShortcutContext(Qt::ApplicationShortcut);
            }
            pushPointer(L_p, action);
            return 1;
        }
        else if (pointer != NULL && ((QObject*)pointer)->inherits("QToolBar")) {
            QAction *action = new QAction(getVariant(L_p, 1).toString(), (QObject*)pointer);
            action->setObjectName(nameForPointer(action));
            ((QToolBar*)pointer)->addAction(action);
            pushPointer(L_p, action);
        }
    }
    return 0;
}

int LuaEngineGui::createMenuSeparator(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMenu")) {
            QAction *action = ((QMenu*)pointer)->addSeparator();
            pushPointer(L_p, action);
            return 1;
        }
        else if (pointer != NULL && ((QObject*)pointer)->inherits("QToolBar")) {
            QAction *action = ((QToolBar*)pointer)->addSeparator();
            pushPointer(L_p, action);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createPlainTextEdit(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString editText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        editText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QPlainTextEdit *textEdit = new QPlainTextEdit(parent);
    textEdit->setObjectName(nameForPointer(textEdit));
    textEdit->setPlainText(editText);
    if (layout != nullptr) {
        layout->addWidget(textEdit);
    }
    pushPointer(L_p, textEdit);
    return 1;
}

int LuaEngineGui::createProgressBar(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    int value = 0;
    int minValue = 0;
    int maxValue = 100;
    if (getArgumentCount(L_p) >= 1) {
        value = getVariant(L_p, 1).toInt();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
            if (getArgumentCount(L_p) >= 4) {
                minValue = getVariant(L_p, 3).toInt();
                maxValue = getVariant(L_p, 4).toInt();
            }
        }
    }
    QProgressBar *progressBar = new QProgressBar(parent);
    progressBar->setObjectName(nameForPointer(progressBar));
    progressBar->setMinimum(minValue);
    progressBar->setMaximum(maxValue);
    progressBar->setValue(value);
    if (layout != nullptr) {
        layout->addWidget(progressBar);
    }
    pushPointer(L_p, progressBar);
    return 1;
}

int LuaEngineGui::createPushButton(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString buttonText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        buttonText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QPushButton *pushButton = new QPushButton(parent);
    pushButton->setObjectName(nameForPointer(pushButton));
    pushButton->setText(buttonText);
    if (layout != nullptr) {
        layout->addWidget(pushButton);
    }
    pushPointer(L_p, pushButton);
    return 1;
}

int LuaEngineGui::createRadioButton(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString labelText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        labelText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QRadioButton *radioButton = new QRadioButton(parent);
    radioButton->setObjectName(nameForPointer(radioButton));
    radioButton->setText(labelText);
    if (layout != nullptr) {
        layout->addWidget(radioButton);
    }
    pushPointer(L_p, radioButton);
    return 1;
}

int LuaEngineGui::createSpacerItem(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 3) {
        void *pointer = getPointer(L_p, 3);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
            if (((QObject*)pointer)->inherits("QVBoxLayout")) {
                QSpacerItem *spacerItem = new QSpacerItem(0, 0, (QSizePolicy::Policy)getVariant(L_p, 1).toInt(), (QSizePolicy::Policy)getVariant(L_p, 2).toInt());
                QVBoxLayout *layout = (QVBoxLayout*)pointer;
                layout->addSpacerItem(spacerItem);
                pushPointer(L_p, spacerItem);
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QHBoxLayout")) {
                QSpacerItem *spacerItem = new QSpacerItem(0, 0, (QSizePolicy::Policy)getVariant(L_p, 1).toInt(), (QSizePolicy::Policy)getVariant(L_p, 2).toInt());
                QHBoxLayout *layout = (QHBoxLayout*)pointer;
                layout->addSpacerItem(spacerItem);
                pushPointer(L_p, spacerItem);
                return 1;
            }
        }
    }
    return 0;
}

int LuaEngineGui::createStackSwitch(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    if (getArgumentCount(L_p) >= 1) {
        lpForPointer(getPointer(L_p, 1), &layout, &parent);
    }
    QStackedWidget *stackedWidget = new QStackedWidget(parent);
    stackedWidget->setObjectName(nameForPointer(stackedWidget));
    if (layout != nullptr) {
        layout->addWidget(stackedWidget);
    }
    pushPointer(L_p, stackedWidget);
    return 1;
}

int LuaEngineGui::createTabBar(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    if (getArgumentCount(L_p) >= 1) {
        lpForPointer(getPointer(L_p, 1), &layout, &parent);
    }
    QTabWidget *tabWidget = new QTabWidget(parent);
    tabWidget->setObjectName(nameForPointer(tabWidget));
    if (layout != nullptr) {
        layout->addWidget(tabWidget);
    }
    pushPointer(L_p, tabWidget);
    return 1;
}

int LuaEngineGui::createTextEdit(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString editText = "LuaEngine";
    if (getArgumentCount(L_p) >= 1) {
        editText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QTextEdit *textEdit = new QTextEdit(parent);
    textEdit->setObjectName(nameForPointer(textEdit));
    textEdit->setHtml(editText);
    if (layout != nullptr) {
        layout->addWidget(textEdit);
    }
    pushPointer(L_p, textEdit);
    return 1;
}

int LuaEngineGui::createToolBar(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QMainWindow")) {
            Qt::ToolBarArea toolBarArea = Qt::TopToolBarArea;
            if (getArgumentCount(L_p) >= 2) {
                toolBarArea = (Qt::ToolBarArea)getVariant(L_p, 2).toInt();
            }
            QToolBar *toolBar = new QToolBar((QWidget*)pointer);
            toolBar->setObjectName(nameForPointer(toolBar));
            ((QMainWindow*)pointer)->addToolBar(toolBarArea, toolBar);
            pushPointer(L_p, toolBar);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createToolButton(lua_State *L_p)
{
    QLayout *layout = nullptr;
    QWidget *parent = nullptr;
    QString buttonText = "...";
    if (getArgumentCount(L_p) >= 1) {
        buttonText = getVariant(L_p, 1).toString();
        if (getArgumentCount(L_p) >= 2) {
            lpForPointer(getPointer(L_p, 2), &layout, &parent);
        }
    }
    QToolButton *toolButton = new QToolButton(parent);
    toolButton->setObjectName(nameForPointer(toolButton));
    toolButton->setText(buttonText);
    if (layout != nullptr) {
        layout->addWidget(toolButton);
    }
    pushPointer(L_p, toolButton);
    return 1;
}

int LuaEngineGui::createWidgetStack(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QStackedWidget")) {
            QStackedWidget *stackedWidget = (QStackedWidget*)pointer;
            QWidget *widgetStack = new QWidget(stackedWidget);
            widgetStack->setObjectName(nameForPointer(widgetStack));
            stackedWidget->addWidget(widgetStack);
            pushPointer(L_p, widgetStack);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::createWidgetTab(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 2) {
        void *pointer = getPointer(L_p, 2);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QTabWidget")) {
            QTabWidget *tabWidget = (QTabWidget*)pointer;
            QWidget *widgetTab = new QWidget(tabWidget);
            widgetTab->setObjectName(nameForPointer(widgetTab));
            tabWidget->addTab(widgetTab, getVariant(L_p, 1).toString());
            pushPointer(L_p, widgetTab);
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::isWidgetChecked(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QCheckBox")) {
                pushVariant(L_p, ((QCheckBox*)pointer)->isChecked());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QRadioButton")) {
                pushVariant(L_p, ((QRadioButton*)pointer)->isChecked());
                return 1;
            }
        }
    }
    return 0;
}

int LuaEngineGui::isWidgetEnabled(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QWidget")) {
                pushVariant(L_p, ((QWidget*)pointer)->isEnabled());
                return 1;
            }
        }
    }
    return 0;
}

int LuaEngineGui::isWidgetVisible(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QWidget")) {
                pushVariant(L_p, ((QWidget*)pointer)->isVisible());
                return 1;
            }
        }
    }
    return 0;
}

int LuaEngineGui::getWindow(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            void *window = windowForObject((QObject*)pointer);
            if (window != nullptr) {
                pushPointer(L_p, window);
                return 1;
            }
        }
    }
    return 0;
}

int LuaEngineGui::getWidgetPixelRatio(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
            pushVariant(L_p, ((QWidget*)pointer)->devicePixelRatioF());
            return 1;
        }
    }
    return 0;
}

int LuaEngineGui::getWidgetText(lua_State *L_p)
{
    if (getArgumentCount(L_p) >= 1) {
        void *pointer = getPointer(L_p, 1);
        if (pointer != NULL) {
            if (((QObject*)pointer)->inherits("QCheckBox")) {
                pushVariant(L_p, ((QCheckBox*)pointer)->text());
                return 1;
            }
            if (((QObject*)pointer)->inherits("QGroupBox")) {
                pushVariant(L_p, ((QGroupBox*)pointer)->title());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QLabel")) {
                pushVariant(L_p, ((QLabel*)pointer)->text());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QLineEdit")) {
                pushVariant(L_p, ((QLineEdit*)pointer)->text());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QPlainTextEdit")) {
                pushVariant(L_p, ((QPlainTextEdit*)pointer)->toPlainText());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QProgressBar")) {
                pushVariant(L_p, ((QProgressBar*)pointer)->format());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QPushButton")) {
                pushVariant(L_p, ((QPushButton*)pointer)->text());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QRadioButton")) {
                pushVariant(L_p, ((QRadioButton*)pointer)->text());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QTextEdit")) {
                pushVariant(L_p, ((QTextEdit*)pointer)->toHtml());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QToolButton")) {
                pushVariant(L_p, ((QToolButton*)pointer)->text());
                return 1;
            }
            else if (((QObject*)pointer)->inherits("QWidget")) {
                pushVariant(L_p, ((QWidget*)pointer)->windowTitle());
                return 1;
            }
        }
    }
    return 0;
}

QWidget* LuaEngineGui::windowForObject(QObject *object)
{
    bool isWindow = false;
    QObject *w_object = object;
    while (!isWindow) {
        if (w_object->inherits("QDialog") || w_object->inherits("QMainWindow")) {
            isWindow = true;
        }
        else {
            QObject *parent = w_object->parent();
            if (parent != NULL) {
                w_object = parent;
            }
            else {
                break;
            }
        }
    }
    if (isWindow) {
        return (QWidget*)w_object;
    }
    return nullptr;
}

void LuaEngineGui::lpForPointer(void *pointer, QLayout **layout, QWidget **parent)
{
    if (pointer != NULL && ((QObject*)pointer)->inherits("QMainWindow")) {
        *parent = ((QMainWindow*)pointer)->centralWidget();
    }
    else if (pointer != NULL && ((QObject*)pointer)->inherits("QWidget")) {
        *parent = (QWidget*)pointer;
    }
    else if (pointer != NULL && ((QObject*)pointer)->inherits("QLayout")) {
        QWidget *widget = windowForObject((QObject*)pointer);
        if (widget != nullptr) {
            *layout = (QLayout*)pointer;
            *parent = widget;
        }
    }
}

QString LuaEngineGui::nameForPointer(void *pointer)
{
    QString nameStorage;
    QTextStream(&nameStorage) << "LuaEngineGui" << pointer;
    return nameStorage;
}