view editor/edgui.cpp @ 2208:90ec1ec89c56

Revamp the palette handling in lib64gfx somewhat, add helper functions to lib64util for handling external palette file options and add support for specifying one of the "internal" palettes or external (.act) palette file to gfxconv and 64vw.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Jun 2019 05:01:12 +0300
parents e2ac08228a0f
children
line wrap: on
line source

//
// Demo Editor -- Qt GUI setup parts and callbacks
// (C) Copyright 2012 Matti 'ccr' Hämäläinen <ccr@tnsp.org>
//
#include "edmain.h"

#include <QCloseEvent>
#include <QToolBar>
#include <QMenuBar>
#include <QStatusBar>
#include <QMenu>
#include <QProgressBar>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>



void DemoEditor::updateMenuStates()
{
    // Set window title based on document filename and changed status
    QString name;

    if (!currTimeline || currTimeline->filename.isEmpty())
        name = DOC_DEF_FILENAME;
    else
        name = currTimeline->filename;
    
    if (currTimeline != NULL)
    {
        if (currTimeline->tl != NULL && currTimeline->tl->name != NULL)
            name += " (" + QString(currTimeline->tl->name) + ")";

        if (currTimeline->touched())
            name = "*" + name;
    }

    setWindowTitle(name + " - " + QCoreApplication::applicationName());

    // Enable menu items based on states
    menuActSave->setEnabled(currTimeline != NULL&& currTimeline->touched());
    menuActSaveAs->setEnabled(currTimeline != NULL);
    
    // Enable undo/redo items and set their texts based on history status
    int historyLevels = undoHistory.size();
    QString itemText;
    bool itemEnabled;
    
    if (undoHistoryPos >= 0 && undoHistoryPos < historyLevels)
    {
        itemText = " " + undoHistory.at(undoHistoryPos)->state();
        itemEnabled = true;
    }
    else
    {
        itemText = "";
        itemEnabled = false;
    }
    
    menuActRedo->setEnabled(itemEnabled);
    menuActRedo->setText("&Redo" + itemText);

    if (undoHistoryPos > 0 && historyLevels > 0)
    {
        itemText = " " + undoHistory.at(undoHistoryPos - 1)->state();
        itemEnabled = true;
    }
    else
    {
        itemText = "";
        itemEnabled = false;
    }
    
    menuActUndo->setEnabled(itemEnabled);
    menuActUndo->setText("&Undo" + itemText);

    update();
}


//
// Show about dialog
//
void DemoEditor::actionAboutBox()
{
    QMessageBox::about(this,
    "About "+ QCoreApplication::applicationName(),
    "<h1>" + QCoreApplication::applicationName() +
    " v"+ QCoreApplication::applicationVersion() +"</h1><br>\n"
    "(C) Copyright 2012 Matti 'ccr' H&auml;m&auml;l&auml;inen<br>\n"
    "<br>\n"
    "<b>A demo editor TNSP dmlib engine.</b><br>\n");
}


//
// Show a dialog inquiring the user whether to save the current
// document if it has been modified since last save/load.
//
QMessageBox::StandardButton DemoEditor::showDocumentModifiedDialog()
{
    return QMessageBox::question(this,
        "The document has been modified.",
        "Do you want to save your changes?",
        QMessageBox::Discard | QMessageBox::Cancel | QMessageBox::Save,
        QMessageBox::Save);
}


//
// Generic error/warning dialog
//
void DemoEditor::showFileErrorDialog(QString operation, int code)
{
/*
    QString msg;
    
    QMessageBox::error(this,
    "A non-critical error occured",
    operation
*/
}


void DemoEditor::actionFileNew()
{
    bool okToCreate = true;

    if (currTimeline != NULL && currTimeline->touched())
    {
        okToCreate = false;
        switch (showDocumentModifiedDialog())
        {
            case QMessageBox::Discard:
                okToCreate = true;
                break;
            
            case QMessageBox::Save:
                actionFileSave();
                if (!currTimeline->touched())
                {
                    QMessageBox::information(this, 
                        "Document saved",
                        "The document was saved as " + currTimeline->filename);

                    okToCreate = true;
                }
                break;

            default:
                break;
        }
    }
    
    if (okToCreate)
        createNewFile();
}


void DemoEditor::actionFileOpen()
{
    bool okToOpen = true;

    if (currTimeline != NULL && currTimeline->touched())
    {
        okToOpen = false;

        switch (showDocumentModifiedDialog())
        {
            case QMessageBox::Discard:
                okToOpen = true;
                break;
            
            case QMessageBox::Save:
                actionFileSave();
                if (!currTimeline->touched())
                {
                    QMessageBox::information(this, 
                        "Document saved",
                        "The document was saved as " + currTimeline->filename);
                    
                    okToOpen = true;
                }
                break;

            default:
                break;
        }
    }
        
    if (okToOpen)
    {
        QFileDialog fdialog(this);

        fdialog.setAcceptMode(QFileDialog::AcceptOpen);
        fdialog.setFileMode(QFileDialog::ExistingFile);
        fdialog.setNameFilter("Demo timeline files (*.demo)");
        fdialog.setDefaultSuffix("demo");

        if (fdialog.exec())
            readFromFile(fdialog.selectedFiles()[0]);
    }
}


void DemoEditor::actionFileSaveAs()
{
    if (!currTimeline)
    {
        qDebug() << "DemoEditor::actionFileSaveAs(): currTimeline == null";
        return;
    }

    QFileDialog fdialog(this);

    fdialog.setAcceptMode(QFileDialog::AcceptSave);
    fdialog.setFileMode(QFileDialog::AnyFile);
    fdialog.setNameFilter("Demo files (*.demo)");
    fdialog.setDefaultSuffix("demo");
    fdialog.setConfirmOverwrite(true);

    fdialog.selectFile(currTimeline->filename.isEmpty() ? currTimeline->filename : DOC_DEF_FILENAME);
    
    if (fdialog.exec())
        saveToFile(fdialog.selectedFiles()[0]);
}


void DemoEditor::actionFileSave()
{
    if (!currTimeline)
    {
        qDebug() << "DemoEditor::actionFileSave(): currTimeline == null";
        return;
    }

    // If filename has been set, save .. otherwise go to save as
    if (!currTimeline->filename.isEmpty())
        saveToFile(currTimeline->filename);
    else
        actionFileSaveAs();
}


void DemoEditor::closeEvent(QCloseEvent *event)
{
    bool okToClose = true;

    if (currTimeline && currTimeline->touched())
    {
        okToClose = false;
        switch (showDocumentModifiedDialog())
        {
            case QMessageBox::Discard:
                okToClose = true;
                break;
            
            case QMessageBox::Save:
                actionFileSave();
                if (!currTimeline->touched())
                    okToClose = true;
                break;
            
            default:
                break;
        }
    }
    
    if (okToClose)
        event->accept();
}


//
// Various menu actions
//
void DemoEditor::actionControlChanged(QAction *act)
{
//    demoView->setToolMode(act->data().toInt());
}


//
// Update statusbar message text
//
void DemoEditor::statusMsg(QString message)
{
    statusBar()->showMessage(message, 0);
}


//
// Set active element of an action group based on matching the data
//
void DemoEditor::setActionGroupChecked(QActionGroup *group, QVariant data)
{
    QList<QAction *> items = group->actions();

    for (int i = 0; i < items.size(); i++)
    {
        QAction *act = items.at(i);
        if (act->data() == data)
        {
            act->setChecked(true);
            return;
        }
    }
}


//
// Helper functions for creating GUI elements
//
QAction * DemoEditor::createToolButton(QActionGroup *group, QString name, QIcon icon, QString statustip, QVariant data)
{
    QAction *action = new QAction(icon, name, group);
    
    action->setStatusTip(statustip + ".");
    action->setCheckable(true);
    action->setData(data);
    
    return action;
}


QAction * DemoEditor::createMenuAction(QString name, const QKeySequence &shortcut, QString tooltip)
{
    QAction *action = new QAction(name, this);
    
    if (shortcut != QKeySequence(QKeySequence::UnknownKey))
        action->setShortcut(shortcut);
    
    if (!tooltip.isNull())
        action->setStatusTip(tooltip + ".");

    return action;
}


QAction * DemoEditor::createMenuGroupAction(QMenu *menu, QActionGroup *group, QString name, const QKeySequence &shortcut, QString tooltip, QVariant data)
{
    QAction *action = createMenuAction(name, shortcut, tooltip);
    
    action->setCheckable(true);
    action->setData(data);

    menu->addAction(action);
    group->addAction(action);

    return action;
}


#define MCONNECT(menu, act, slot) do { connect(act, SIGNAL(triggered()), this, SLOT(slot)); menu->addAction(act); } while(0)


//
// Create GUI elements
//
void DemoEditor::createMainGUI()
{
    QAction *act;
    QMenu *fileMenu, *editMenu, *viewMenu, *helpMenu;

    qDebug() << "- Constructing menus";

    //
    // File menu
    //
    fileMenu = menuBar()->addMenu("&File");

    act = createMenuAction("&New", QKeySequence::New, "Create a new demo timeline");
    MCONNECT(fileMenu, act, actionFileNew());

    menuActOpen = createMenuAction("&Open", QKeySequence::Open, "Open a demo timeline file");
    MCONNECT(fileMenu, menuActOpen, actionFileOpen());

    menuActSave = createMenuAction("&Save", QKeySequence::Save, "Save demo timeline");
    MCONNECT(fileMenu, menuActSave, actionFileSave());

    menuActSaveAs = createMenuAction("Save &as", QKeySequence::SaveAs, "Save demo timeline as a new file");
    MCONNECT(fileMenu, menuActSaveAs, actionFileSaveAs());

    fileMenu->addSeparator();

    QKeySequence qseq(Qt::CTRL + Qt::Key_Q);
    act = createMenuAction("&Quit", qseq, "Exit application");
    MCONNECT(fileMenu, act, close());


    //
    // Edit menu
    //
    editMenu = menuBar()->addMenu("&Edit");

    menuActUndo = createMenuAction("&Undo",  QKeySequence::Undo, "Undo last change");
    MCONNECT(editMenu, menuActUndo, performUndo());

    menuActRedo = createMenuAction("&Redo",  QKeySequence::Redo, "Redo last change");
    MCONNECT(editMenu, menuActRedo, performRedo());

#if 0
    editMenu->addSeparator();

    menuActCut = createMenuAction("Cu&t",  QKeySequence::Cut, "Cut object");
    MCONNECT(editMenu, menuActCut, actionCut());

    menuActCopy = createMenuAction("&Copy",  QKeySequence::Copy, "Copy object");
    MCONNECT(editMenu, menuActCopy, actionCopy());

    menuActPaste = createMenuAction("&Paste", QKeySequence::Paste, "Paste object");
    MCONNECT(editMenu, menuActPaste, actionPaste());

    menuActDelete = createMenuAction("&Delete", QKeySequence::Delete, "Delete object");
    MCONNECT(editMenu, menuActDelete, actionDelete());
#endif

    //
    // Help menu
    //
    helpMenu = menuBar()->addMenu("&Help");
    act = createMenuAction("About", 0, "Show information about application");
    MCONNECT(helpMenu, act, actionAboutBox());



    //
    // Controls toolbar
    //
    qDebug() << "- Constructing toolbars";

    actGroupControls = new QActionGroup(this);
    actGroupControls->setExclusive(true);
    connect(actGroupControls, SIGNAL(triggered(QAction*)), this, SLOT(actionControlChanged(QAction *)));
    
    createToolButton(actGroupControls, "Rewind", QIcon("rewind.png"),
        "Rewind to start of the timeline", CTRL_REWIND);

    createToolButton(actGroupControls, "Play start", QIcon("play1.png"),
        "Play from start", CTRL_PLAY_START);

    createToolButton(actGroupControls, "Play current", QIcon("play2.png"),
        "Play from current position", CTRL_PLAY_CURRENT);

    createToolButton(actGroupControls, "Pause", QIcon("pause.png"),
        "Pause", CTRL_PAUSE);


    QToolBar *controlButtons = new QToolBar("Player controls", this);
    controlButtons->setMovable(false);
    controlButtons->setFloatable(false);
    controlButtons->setIconSize(QSize(CTRL_ICON_SIZE, CTRL_ICON_SIZE));
    controlButtons->setToolButtonStyle(Qt::ToolButtonIconOnly);
    controlButtons->addActions(actGroupControls->actions());


    //
    // Effect resource view
    //
    qDebug() << "- Constructing effects resource view";

    resourceView = new QTableView(this);
    resourceView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    resourceView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    resourceView->setSelectionMode(QAbstractItemView::SingleSelection);
    resourceView->setSelectionBehavior(QAbstractItemView::SelectRows);
    resourceModel = new QEDResourceModel(this);
    resourceView->setModel(resourceModel);

    //
    // Construct the main screen
    //
    qDebug() << "- Constructing main screen layout";

    QWidget *sideVBoxContainer = new QWidget();
    QSizePolicy sideVBoxPolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
    sideVBoxPolicy.setHeightForWidth(sideVBoxContainer->sizePolicy().hasHeightForWidth());
    sideVBoxContainer->setSizePolicy(sideVBoxPolicy);

    QVBoxLayout *sideVBox = new QVBoxLayout(sideVBoxContainer);
    sideVBox->setSpacing(0);
    sideVBox->setContentsMargins(0, 0, 0, 0);
    sideVBox->addWidget(resourceView);
    sideVBox->addWidget(controlButtons);


    QWidget *holder = new QWidget();
    QVBoxLayout *verticalSplitter = new QVBoxLayout(holder);
    QHBoxLayout *horizSplitter = new QHBoxLayout();


    timelineScrollBar = new QScrollBar(Qt::Horizontal);
    connect(timelineScrollBar, SIGNAL(valueChanged(int)), this, SLOT(actionTimelineScrollChanged(int)));
    
    timelineAudioTrack = new QEDWaveTrackView();
    connect(timelineAudioTrack, SIGNAL(offsetChanged(float)), this, SLOT(actionOffsetChanged(float)));
    connect(timelineAudioTrack, SIGNAL(timeChanged(float)), this, SLOT(actionTimeChanged(float)));

    timelineView = new QEDTimelineView();
    connect(timelineView, SIGNAL(timelineChanged()), this, SLOT(actionTimelineChanged()));

    QScrollArea *scrollArea = new QScrollArea();
    scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
    scrollArea->setWidget(timelineView);
    scrollArea->setWidgetResizable(true);


    demoView = new QEDSWDemoView(this);

    verticalSplitter->addLayout(horizSplitter);
    verticalSplitter->addWidget(scrollArea);
    verticalSplitter->addWidget(timelineAudioTrack);
    verticalSplitter->addWidget(timelineScrollBar);

    horizSplitter->addWidget(sideVBoxContainer);
    horizSplitter->addWidget(demoView);


    updateTimelineView();

    setCentralWidget(holder);
}