view edgui.cpp @ 495:30145d17aebd

Move certain editor related targets to the actual TARGETS variable, and remove them from being separately specified in the "make clean" target, thusly cleaning them only when editor is enabled in build configuration.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 16 Nov 2012 19:18:03 +0200
parents d34922e6a244
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);
}