Logo Search packages:      
Sourcecode: rosegarden version File versions  Download package

notationview.cpp

// -*- c-basic-offset: 4 -*-

/*
    Rosegarden-4
    A sequencer and musical notation editor.

    This program is Copyright 2000-2006
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <bownie@bownie.com>

    The moral right of the authors to claim authorship of this work
    has been asserted.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/


#include <qstring.h>
#include <qregexp.h>
#include <qpaintdevicemetrics.h>
#include <qpixmap.h>
#include <qtimer.h>

#include <algorithm>

#include <kmessagebox.h>
#include <kstatusbar.h>
#include <klocale.h>
#include <kconfig.h>
#include <kstddirs.h>
#include <kglobal.h>
#include <kaction.h>
#include <kstdaction.h>
#include <kglobal.h>
#include <kapp.h>
#include <kprinter.h>

#include "NotationTypes.h"
#include "Quantizer.h"
#include "Selection.h"
#include "BaseProperties.h"

#include "Profiler.h"

#include "notationview.h"
#include "constants.h"
#include "colours.h"
#include "notationstrings.h"
#include "notepixmapfactory.h"
#include "notefont.h"
#include "notestyle.h"
#include "notationtool.h"
#include "notationstrings.h"
#include "barbuttons.h"
#include "loopruler.h"
#include "rosedebug.h"
#include "editcommands.h"
#include "notationcommands.h"
#include "segmentcommands.h"
#include "widgets.h"
#include "chordnameruler.h"
#include "temporuler.h"
#include "rawnoteruler.h"
#include "studiocontrol.h"
#include "notationhlayout.h"
#include "notationvlayout.h"
#include "ktmpstatusmsg.h"
#include "scrollbox.h"
#include "rosegardenguiview.h"
#include "trackeditor.h"
#include "trackbuttons.h"
//#include "tempoview.h"

//!!! TESTING:
#include "qcanvassimplesprite.h"
#include <qpixmap.h>
#include <qfont.h>
#include <qfontmetrics.h>
#include <qpainter.h>


using Rosegarden::Event;
using Rosegarden::Note;
using Rosegarden::Segment;
using Rosegarden::EventSelection;
using Rosegarden::Quantizer;
using Rosegarden::timeT;
using Rosegarden::Mark;
using namespace Rosegarden::Marks;


class NoteActionData
{
public:
    NoteActionData();
    NoteActionData(const QString& _title,
               QString _actionName,
               QString _pixmapName,
               int _keycode,
               bool _rest,
               Note::Type _noteType,
               int _dots);
    
    QString title;
    QString actionName;
    QString pixmapName;
    int keycode;
    bool rest;
    Note::Type noteType;
    int dots;
};

NoteActionData::NoteActionData()
    : title(0),
      actionName(0),
      pixmapName(0),
      keycode(0),
      rest(false),
      noteType(0),
      dots(0)
{
}

NoteActionData::NoteActionData(const QString& _title,
                         QString _actionName,
                         QString _pixmapName,
                         int _keycode,
                         bool _rest,
                         Note::Type _noteType,
                         int _dots)
    : title(_title),
      actionName(_actionName),
      pixmapName(_pixmapName),
      keycode(_keycode),
      rest(_rest),
      noteType(_noteType),
      dots(_dots)
{
}


class NoteChangeActionData
{
public:
    NoteChangeActionData();
    NoteChangeActionData(const QString &_title,
                   QString _actionName,
                   QString _pixmapName,
                   int _keycode,
                   bool _notationOnly,
                   Note::Type _noteType);

    QString title;
    QString actionName;
    QString pixmapName;
    int keycode;
    bool notationOnly;
    Note::Type noteType;
};

NoteChangeActionData::NoteChangeActionData()
    : title(0),
      actionName(0),
      pixmapName(0),
      keycode(0),
      notationOnly(false),
      noteType(0)
{
}

NoteChangeActionData::NoteChangeActionData(const QString& _title,
                                 QString _actionName,
                                 QString _pixmapName,
                                 int _keycode,
                                 bool _notationOnly,
                                 Note::Type _noteType)
    : title(_title),
      actionName(_actionName),
      pixmapName(_pixmapName),
      keycode(_keycode),
      notationOnly(_notationOnly),
      noteType(_noteType)
{
}


class MarkActionData
{
public:
    MarkActionData() :
      title(0),
      actionName(0),
      keycode(0) { }

    MarkActionData(const QString &_title,
               QString _actionName,
               int _keycode,
               Mark _mark) :
      title(_title),
      actionName(_actionName),
      keycode(_keycode),
      mark(_mark) { }

    QString title;
    QString actionName;
    int keycode;
    Mark mark;
};




//////////////////////////////////////////////////////////////////////

NotationView::NotationView(RosegardenGUIDoc *doc,
                           std::vector<Segment *> segments,
                           QWidget *parent,
                     bool showProgressive) :
    EditView(doc, segments, 1, parent, "notationview"),
    m_properties(getViewLocalPropertyPrefix()),
    m_selectionCounter(0),
    m_insertModeLabel(0),
    m_annotationsLabel(0),
    m_lilypondDirectivesLabel(0),
    m_progressBar(0),
    m_currentNotePixmap(0),
    m_hoveredOverNoteName(0),
    m_hoveredOverAbsoluteTime(0),
    m_currentStaff(-1),
    m_lastFinishingStaff(-1),
    m_title(0),
    m_subtitle(0),
    m_composer(0),
    m_copyright(0),
    m_insertionTime(0),
    m_deferredCursorMove(NoCursorMoveNeeded),
    m_lastNoteAction("crotchet"),
    m_fontName(NoteFontFactory::getDefaultFontName()),
    m_fontSize(NoteFontFactory::getDefaultSize(m_fontName)),
    m_pageMode(LinedStaff::LinearMode),
    m_leftGutter(20),
    m_notePixmapFactory(new NotePixmapFactory(m_fontName, m_fontSize)),
    m_hlayout(new NotationHLayout(&doc->getComposition(), m_notePixmapFactory,
                                  m_properties, this)),
    m_vlayout(new NotationVLayout(&doc->getComposition(), m_notePixmapFactory,
                                  m_properties, this)),
    m_chordNameRuler(0),
    m_tempoRuler(0),
    m_rawNoteRuler(0),
    m_annotationsVisible(false),
    m_lilypondDirectivesVisible(false),
    m_selectDefaultNote(0),
    m_fontCombo(0),
    m_fontSizeCombo(0),
    m_spacingCombo(0),
    m_fontSizeActionMenu(0),
    m_pannerDialog(new ScrollBoxDialog(this, ScrollBox::FixHeight)),
    m_renderTimer(0),
    m_playTracking(true),
    m_progressDisplayer(PROGRESS_NONE),
    m_inhibitRefresh(true),
    m_ok(false),
    m_printMode(false),
    m_printSize(8) // set in positionStaffs
{
    initActionDataMaps(); // does something only the 1st time it's called
    
    m_toolBox = new NotationToolBox(this);

    assert(segments.size() > 0);
    NOTATION_DEBUG << "NotationView ctor" << endl;


    // Initialise the display-related defaults that will be needed
    // by both the actions and the layout toolbar

    m_config->setGroup(NotationView::ConfigGroup);

    m_fontName = qstrtostr(m_config->readEntry
                     ("notefont",
                      strtoqstr(NoteFontFactory::getDefaultFontName())));

    try {
      (void)NoteFontFactory::getFont
          (m_fontName,
           NoteFontFactory::getDefaultSize(m_fontName));
    } catch (Rosegarden::Exception e) {
      m_fontName = NoteFontFactory::getDefaultFontName();
    }

    m_fontSize = m_config->readUnsignedNumEntry
      ((segments.size() > 1 ? "multistaffnotesize" : "singlestaffnotesize"),
       NoteFontFactory::getDefaultSize(m_fontName));

    int defaultSpacing = m_config->readNumEntry("spacing", 100);
    m_hlayout->setSpacing(defaultSpacing);

    int defaultProportion = m_config->readNumEntry("proportion", 60);
    m_hlayout->setProportion(defaultProportion);

    delete m_notePixmapFactory;
    m_notePixmapFactory = new NotePixmapFactory(m_fontName, m_fontSize);
    m_hlayout->setNotePixmapFactory(m_notePixmapFactory);
    m_vlayout->setNotePixmapFactory(m_notePixmapFactory);
    
    setupActions();
//     setupAddControlRulerMenu(); - too early for notation, moved to end of ctor.
    initLayoutToolbar();
    initStatusBar();
    
    setBackgroundMode(PaletteBase);

    QCanvas *tCanvas = new QCanvas(this);
    tCanvas->resize(width() * 2, height() * 2);

    setCanvasView(new NotationCanvasView(*this, tCanvas, getCentralWidget()));

    updateViewCaption();

    setTopBarButtons(new BarButtons(getDocument(),
                                    m_hlayout, m_leftGutter, 25,
                            false, getCentralWidget()));

    m_topBarButtons->getLoopRuler()->setBackgroundColor
      (Rosegarden::GUIPalette::getColour(Rosegarden::GUIPalette::InsertCursorRuler));

    m_chordNameRuler = new ChordNameRuler
      (m_hlayout, doc, segments, m_leftGutter, 20, getCentralWidget());
    addRuler(m_chordNameRuler);
    if (showProgressive) m_chordNameRuler->show();

    m_tempoRuler = new TempoRuler
      (m_hlayout, doc, factory(), m_leftGutter, 24, false, getCentralWidget());
    addRuler(m_tempoRuler);
    m_tempoRuler->hide();
    static_cast<TempoRuler *>(m_tempoRuler)->connectSignals();

    m_rawNoteRuler = new RawNoteRuler
      (m_hlayout, segments[0], m_leftGutter, 20, getCentralWidget());
    addRuler(m_rawNoteRuler);
    m_rawNoteRuler->show();

    // All toolbars should be created before this is called
    setAutoSaveSettings("NotationView", true);

    // All rulers must have been created before this is called,
    // or the program will crash
    readOptions();


    setBottomBarButtons(new BarButtons(getDocument(), m_hlayout, m_leftGutter, 25,
                               true, getBottomWidget()));

    for (unsigned int i = 0; i < segments.size(); ++i) {
        m_staffs.push_back(new NotationStaff
                     (canvas(), segments[i], 0, // snap
                      i, this,
                      m_fontName, m_fontSize));
    }

    //
    // layout
    //
    RosegardenProgressDialog* progressDlg = 0;

    if (showProgressive) {
      show();
        RosegardenProgressDialog::processEvents();

        NOTATION_DEBUG << "NotationView : setting up progress dialog" << endl;

        progressDlg = new RosegardenProgressDialog(i18n("Starting..."),
                                                   100, this);
      progressDlg->setAutoClose(false);
        progressDlg->setAutoReset(true);
        progressDlg->setMinimumDuration(1000);
        setupProgress(progressDlg);

        m_progressDisplayer = PROGRESS_DIALOG;
    }

    m_chordNameRuler->setStudio(&getDocument()->getStudio());

    m_currentStaff = 0;
    m_staffs[0]->setCurrent(true);

    m_config->setGroup(NotationView::ConfigGroup);
    int layoutMode = m_config->readNumEntry("layoutmode", 0);

    try {

      LinedStaff::PageMode mode = LinedStaff::LinearMode;
      if (layoutMode == 1) mode = LinedStaff::ContinuousPageMode;
      else if (layoutMode == 2) mode = LinedStaff::MultiPageMode;

        setPageMode(mode);

      for (unsigned int i = 0; i < m_staffs.size(); ++i) {
          m_staffs[i]->getSegment().getRefreshStatus
            (m_segmentsRefreshStatusIds[i]).setNeedsRefresh(false);
      }

        m_ok = true;

    } catch (ProgressReporter::Cancelled c) {
      // when cancelled, m_ok is false -- checked by calling method
        NOTATION_DEBUG << "NotationView ctor : layout Cancelled" << endl;
    }
    
    NOTATION_DEBUG << "NotationView ctor : m_ok = " << m_ok << endl;
    
    delete progressDlg;

    // at this point we can return if operation was cancelled
    if (!isOK()) { setOutOfCtor(); return; }
    

    // otherwise, carry on
    setupDefaultProgress();

    //
    // Connect signals
    //

    QObject::connect
      (getCanvasView(), SIGNAL(renderRequired(double, double)),
       this,            SLOT(slotCheckRendered(double, double)));

    m_topBarButtons->connectRulerToDocPointer(doc);
    m_bottomBarButtons->connectRulerToDocPointer(doc);

    // Disconnect the default connections for these signals from the
    // top ruler, and connect our own instead

    QObject::disconnect
      (m_topBarButtons->getLoopRuler(),
       SIGNAL(setPointerPosition(Rosegarden::timeT)), 0, 0);

    QObject::disconnect
      (m_topBarButtons->getLoopRuler(),
       SIGNAL(dragPointerToPosition(Rosegarden::timeT)), 0, 0);

    QObject::connect
      (m_topBarButtons->getLoopRuler(),
       SIGNAL(setPointerPosition(Rosegarden::timeT)),
       this, SLOT(slotSetInsertCursorPosition(Rosegarden::timeT)));

    QObject::connect
      (m_topBarButtons->getLoopRuler(),
       SIGNAL(dragPointerToPosition(Rosegarden::timeT)),
       this, SLOT(slotSetInsertCursorPosition(Rosegarden::timeT)));

    QObject::connect
        (getCanvasView(), SIGNAL(itemPressed(int, int, QMouseEvent*, NotationElement*)),
         this,            SLOT  (slotItemPressed(int, int, QMouseEvent*, NotationElement*)));

    QObject::connect
        (getCanvasView(), SIGNAL(activeItemPressed(QMouseEvent*, QCanvasItem*)),
         this,         SLOT  (slotActiveItemPressed(QMouseEvent*, QCanvasItem*)));

    QObject::connect
        (getCanvasView(), SIGNAL(nonNotationItemPressed(QMouseEvent*, QCanvasItem*)),
         this,         SLOT  (slotNonNotationItemPressed(QMouseEvent*, QCanvasItem*)));

    QObject::connect
        (getCanvasView(), SIGNAL(textItemPressed(QMouseEvent*, QCanvasItem*)),
         this,         SLOT  (slotTextItemPressed(QMouseEvent*, QCanvasItem*)));

    QObject::connect
        (getCanvasView(), SIGNAL(mouseMoved(QMouseEvent*)),
         this,         SLOT  (slotMouseMoved(QMouseEvent*)));

    QObject::connect
        (getCanvasView(), SIGNAL(mouseReleased(QMouseEvent*)),
         this,         SLOT  (slotMouseReleased(QMouseEvent*)));

    QObject::connect
        (getCanvasView(), SIGNAL(hoveredOverNoteChanged(const QString&)),
         this,         SLOT  (slotHoveredOverNoteChanged(const QString&)));

    QObject::connect
        (getCanvasView(), SIGNAL(hoveredOverAbsoluteTimeChanged(unsigned int)),
         this,         SLOT  (slotHoveredOverAbsoluteTimeChanged(unsigned int)));

    QObject::connect
      (getCanvasView(), SIGNAL(zoomIn()), this, SLOT(slotZoomIn()));

    QObject::connect
      (getCanvasView(), SIGNAL(zoomOut()), this, SLOT(slotZoomOut()));

    QObject::connect
      (m_pannerDialog->scrollbox(), SIGNAL(valueChanged(const QPoint &)),
       getCanvasView(), SLOT(slotSetScrollPos(const QPoint &)));

    QObject::connect
      (getCanvasView()->horizontalScrollBar(), SIGNAL(valueChanged(int)),
       m_pannerDialog->scrollbox(), SLOT(setViewX(int)));

    QObject::connect
      (getCanvasView()->verticalScrollBar(), SIGNAL(valueChanged(int)),
       m_pannerDialog->scrollbox(), SLOT(setViewY(int)));

    QObject::connect
      (doc, SIGNAL(pointerPositionChanged(Rosegarden::timeT)),
       this, SLOT(slotSetPointerPosition(Rosegarden::timeT)));
    QObject::connect
      (doc, SIGNAL(pointerDraggedToPosition(Rosegarden::timeT)),
       this, SLOT(slotSetPointerPosition(Rosegarden::timeT)));

    stateChanged("have_selection", KXMLGUIClient::StateReverse);
    stateChanged("have_notes_in_selection", KXMLGUIClient::StateReverse);
    stateChanged("have_rests_in_selection", KXMLGUIClient::StateReverse);
    stateChanged("have_multiple_staffs",
             (m_staffs.size() > 1 ? KXMLGUIClient::StateNoReverse :
                                    KXMLGUIClient::StateReverse));
    stateChanged("rest_insert_tool_current", KXMLGUIClient::StateReverse);
    slotTestClipboard();

    if (getSegmentsOnlyRestsAndClefs()) {
        m_selectDefaultNote->activate();
      stateChanged("note_insert_tool_current", 
                 KXMLGUIClient::StateNoReverse);
    } else {
        actionCollection()->action("select")->activate();
      stateChanged("note_insert_tool_current",
                 KXMLGUIClient::StateReverse);
    }

    Rosegarden::timeT start = doc->getComposition().getLoopStart();
    Rosegarden::timeT end = doc->getComposition().getLoopEnd();
    m_topBarButtons->getLoopRuler()->slotSetLoopMarker(start, end);
    m_bottomBarButtons->getLoopRuler()->slotSetLoopMarker(start, end);

    slotSetInsertCursorPosition(0);
    slotSetPointerPosition(doc->getComposition().getPosition());
    setCurrentSelection(0, false, true);
    slotUpdateInsertModeStatus();
    m_chordNameRuler->repaint();
    m_tempoRuler->repaint();
    m_rawNoteRuler->repaint();
    m_inhibitRefresh = false;

//    slotCheckRendered(0, getCanvasView()->visibleWidth());
//    getCanvasView()->repaintContents();
    updateView();

    QObject::connect
      (this,            SIGNAL(renderComplete()),
       getCanvasView(), SLOT(slotRenderComplete()));

    if (parent) {
      const TrackButtons * trackLabels = 
            ((RosegardenGUIView*)parent)->getTrackEditor()->getTrackButtons();
        QObject::connect
            (trackLabels,             SIGNAL(nameChanged()),
             this, SLOT(slotUpdateStaffName()));
    }

    setConfigDialogPageIndex(2);
    setOutOfCtor();

    // Property and Control Rulers
    //
    if (getCurrentSegment()->getViewFeatures()) slotShowVelocityControlRuler();
    setupControllerTabs();

    setupAddControlRulerMenu();
    setRewFFwdToAutoRepeat();

    slotCompositionStateUpdate();

    NOTATION_DEBUG << "NotationView ctor exiting" << endl;
}

//
// Notation Print mode
//
00583 NotationView::NotationView(RosegardenGUIDoc *doc,
                           std::vector<Segment *> segments,
                     QWidget *parent,
                     NotationView *referenceView)
    : EditView(doc, segments, 1, 0, "printview"),
    m_properties(getViewLocalPropertyPrefix()),
    m_selectionCounter(0),
    m_currentNotePixmap(0),
    m_hoveredOverNoteName(0),
    m_hoveredOverAbsoluteTime(0),
    m_lastFinishingStaff(-1),
    m_title(0),
    m_subtitle(0),
    m_composer(0),
    m_copyright(0),
    m_insertionTime(0),
    m_deferredCursorMove(NoCursorMoveNeeded),
    m_lastNoteAction("crotchet"),
    m_fontName(NoteFontFactory::getDefaultFontName()),
    m_fontSize(NoteFontFactory::getDefaultSize(m_fontName)),
    m_pageMode(LinedStaff::LinearMode),
    m_leftGutter(0),
    m_notePixmapFactory(new NotePixmapFactory(m_fontName, m_fontSize)),
    m_hlayout(new NotationHLayout(&doc->getComposition(), m_notePixmapFactory,
                          m_properties, this)),
    m_vlayout(new NotationVLayout(&doc->getComposition(), m_notePixmapFactory,
                                  m_properties, this)),
    m_chordNameRuler(0),
    m_tempoRuler(0),
    m_rawNoteRuler(0),
    m_annotationsVisible(false),
    m_lilypondDirectivesVisible(false),
    m_selectDefaultNote(0),
    m_fontCombo(0),
    m_fontSizeCombo(0),
    m_spacingCombo(0),
    m_fontSizeActionMenu(0),
    m_pannerDialog(0),
    m_renderTimer(0),
    m_playTracking(false),
    m_progressDisplayer(PROGRESS_NONE),
    m_inhibitRefresh(true),
    m_ok(false),
    m_printMode(true),
    m_printSize(8) // set in positionStaffs
{
    assert(segments.size() > 0);
    NOTATION_DEBUG << "NotationView print ctor" << endl;


    // Initialise the display-related defaults that will be needed
    // by both the actions and the layout toolbar

    m_config->setGroup(NotationView::ConfigGroup);

    if (referenceView) {
      m_fontName = referenceView->m_fontName;
    } else {
      m_fontName = qstrtostr(m_config->readEntry
                         ("notefont",
                        strtoqstr(NoteFontFactory::getDefaultFontName())));
    }


    // Force largest font size
    std::vector<int> sizes = NoteFontFactory::getAllSizes(m_fontName);
    m_fontSize = sizes[sizes.size()-1];

    if (referenceView) {
      m_hlayout->setSpacing(referenceView->m_hlayout->getSpacing());
      m_hlayout->setProportion(referenceView->m_hlayout->getProportion());
    } else {
      int defaultSpacing = m_config->readNumEntry("spacing", 100);
      m_hlayout->setSpacing(defaultSpacing);
      int defaultProportion = m_config->readNumEntry("proportion", 60);
      m_hlayout->setProportion(defaultProportion);
    }

    delete m_notePixmapFactory;
    m_notePixmapFactory = new NotePixmapFactory(m_fontName, m_fontSize);
    m_hlayout->setNotePixmapFactory(m_notePixmapFactory);
    m_vlayout->setNotePixmapFactory(m_notePixmapFactory);
    
    setBackgroundMode(PaletteBase);
    m_config->setGroup(NotationView::ConfigGroup);

    QCanvas *tCanvas = new QCanvas(this);
    tCanvas->resize(width() * 2, height() * 2);//!!! 

    setCanvasView(new NotationCanvasView(*this, tCanvas, getCentralWidget()));
    canvas()->retune(128); // tune for larger canvas

    for (unsigned int i = 0; i < segments.size(); ++i) {
        m_staffs.push_back(new NotationStaff(canvas(), segments[i], 0, // snap
                                             i, this,
                                             m_fontName, m_fontSize));
    }

    m_currentStaff = 0;
    m_staffs[0]->setCurrent(true);

    RosegardenProgressDialog* progressDlg = 0;

    if (parent) {

        RosegardenProgressDialog::processEvents();

      NOTATION_DEBUG << "NotationView : setting up progress dialog" << endl;

        progressDlg = new RosegardenProgressDialog(i18n("Preparing to print..."),
                                                   100, parent);
      progressDlg->setAutoClose(false);
        progressDlg->setAutoReset(true);
        progressDlg->setMinimumDuration(1000);
        setupProgress(progressDlg);

        m_progressDisplayer = PROGRESS_DIALOG;
    }

    try {

        setPageMode(LinedStaff::MultiPageMode); // also positions and renders the staffs!

      for (unsigned int i = 0; i < m_staffs.size(); ++i) {
          m_staffs[i]->getSegment().getRefreshStatus
            (m_segmentsRefreshStatusIds[i]).setNeedsRefresh(false);
      }

      m_ok = true;

    } catch (ProgressReporter::Cancelled c) {
      // when cancelled, m_ok is false -- checked by calling method
        NOTATION_DEBUG << "NotationView ctor : layout Cancelled" << endl;
    }

    NOTATION_DEBUG << "NotationView ctor : m_ok = " << m_ok << endl;
    
    delete progressDlg;

    if (!isOK()) {
        setOutOfCtor();
        return; // In case more code is added there later
    }

    setOutOfCtor(); // keep this as last call in the ctor
}


NotationView::~NotationView()
{
    NOTATION_DEBUG << "-> ~NotationView()" << endl;

    if (!m_printMode && m_ok) slotSaveOptions();

    delete m_chordNameRuler;

    delete m_renderTimer;

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      for (Segment::iterator j = m_staffs[i]->getSegment().begin();
           j != m_staffs[i]->getSegment().end(); ++j) {
          removeViewLocalProperties(*j);
      }
      delete m_staffs[i]; // this will erase all "notes" canvas items
    }
    
    PixmapArrayGC::deleteAll();
    Rosegarden::Profiles::getInstance()->dump();

    NOTATION_DEBUG << "<- ~NotationView()" << endl;
}

void
NotationView::removeViewLocalProperties(Rosegarden::Event *e)
{
    Event::PropertyNames names(e->getPropertyNames());
    std::string prefix(getViewLocalPropertyPrefix());

    for (Event::PropertyNames::iterator i = names.begin();
       i != names.end(); ++i) {
      if (i->getName().substr(0, prefix.size()) == prefix) {
          e->unset(*i);
      }
    }
}
    
const NotationProperties &
00770 NotationView::getProperties() const 
{
    return m_properties;
}

00775 void NotationView::positionStaffs()
{
    NOTATION_DEBUG << "NotationView::positionStaffs" << endl;

    m_config->setGroup(NotationView::ConfigGroup);
    m_printSize = m_config->readUnsignedNumEntry("printingnotesize", 5);

    int minTrack = 0, maxTrack = 0;
    bool haveMinTrack = false;
    typedef std::map<int, int> TrackIntMap;
    TrackIntMap trackHeights;
    TrackIntMap trackCoords;

    int pageWidth, pageHeight, leftMargin, topMargin;
    pageWidth = getPageWidth();
    pageHeight = getPageHeight();
    leftMargin = 0, topMargin = 0;
    getPageMargins(leftMargin, topMargin);

    int accumulatedHeight;
    int rowsPerPage = 1;
    int legerLines = 8;
    if (m_pageMode != LinedStaff::LinearMode) legerLines = 7;
    int rowGapPercent = (m_staffs.size() > 1 ? 40 : 10);
    int aimFor = -1;

    bool done = false;

    int titleHeight = 0;

    if (m_title) delete m_title;
    if (m_subtitle) delete m_subtitle;
    if (m_composer) delete m_composer;
    if (m_copyright) delete m_copyright;
    m_title = m_subtitle = m_composer = m_copyright = 0;

    if (m_pageMode == LinedStaff::MultiPageMode) {

      const Rosegarden::Configuration &metadata =
          getDocument()->getComposition().getMetadata();

      QFont defaultFont(NotePixmapFactory::defaultSerifFontFamily);
        m_config->setGroup(NotationView::ConfigGroup);
        QFont font = m_config->readFontEntry("textfont", &defaultFont);
      font.setPixelSize(m_fontSize * 5);
      QFontMetrics metrics(font);

      if (metadata.has(Rosegarden::CompositionMetadataKeys::Title)) {
          QString title(strtoqstr(metadata.get<Rosegarden::String>
                            (Rosegarden::CompositionMetadataKeys::Title)));
          m_title = new QCanvasText(title, font, canvas());
          m_title->setX(m_leftGutter + pageWidth/2 - metrics.width(title)/2);
          m_title->setY(20 + topMargin/4 + metrics.ascent());
          m_title->show();
          titleHeight += metrics.height() * 3/2 + topMargin/4;
      }
      
      font.setPixelSize(m_fontSize * 3);
      metrics = QFontMetrics(font);

      if (metadata.has(Rosegarden::CompositionMetadataKeys::Subtitle)) {
          QString subtitle(strtoqstr(metadata.get<Rosegarden::String>
                               (Rosegarden::CompositionMetadataKeys::Subtitle)));
          m_subtitle = new QCanvasText(subtitle, font, canvas());
          m_subtitle->setX(m_leftGutter + pageWidth/2 - metrics.width(subtitle)/2);
          m_subtitle->setY(20 + titleHeight + metrics.ascent());
          m_subtitle->show();
          titleHeight += metrics.height() * 3/2;
      }

      if (metadata.has(Rosegarden::CompositionMetadataKeys::Composer)) {
          QString composer(strtoqstr(metadata.get<Rosegarden::String>
                               (Rosegarden::CompositionMetadataKeys::Composer)));
          m_composer = new QCanvasText(composer, font, canvas());
          m_composer->setX(m_leftGutter + pageWidth - metrics.width(composer) - leftMargin);
          m_composer->setY(20 + titleHeight + metrics.ascent());
          m_composer->show();
          titleHeight += metrics.height() * 3/2;
      }
      
      font.setPixelSize(m_fontSize * 2);
      metrics = QFontMetrics(font);

      if (metadata.has(Rosegarden::CompositionMetadataKeys::Copyright)) {
          QString copyright(strtoqstr(metadata.get<Rosegarden::String>
                              (Rosegarden::CompositionMetadataKeys::Copyright)));
          m_copyright = new QCanvasText(copyright, font, canvas());
          m_copyright->setX(m_leftGutter + leftMargin);
          m_copyright->setY(20 + pageHeight - topMargin - metrics.descent());
          m_copyright->show();
      }
    } 

    while (1) {

      accumulatedHeight = 0;
      int maxTrackHeight = 0;

      trackHeights.clear();

      for (unsigned int i = 0; i < m_staffs.size(); ++i) {

          m_staffs[i]->setLegerLineCount(legerLines);

          int height = m_staffs[i]->getHeightOfRow();
          Rosegarden::TrackId trackId = m_staffs[i]->getSegment().getTrack();
          Rosegarden::Track *track =
            m_staffs[i]->getSegment().getComposition()->
            getTrackById(trackId);

          if (!track) continue; // This Should Not Happen, My Friend

          int trackPosition = track->getPosition();

          TrackIntMap::iterator hi = trackHeights.find(trackPosition);
          if (hi == trackHeights.end()) {
            trackHeights.insert(TrackIntMap::value_type
                            (trackPosition, height));
          } else if (height > hi->second) {
            hi->second = height;
          }
      
          if (height > maxTrackHeight) maxTrackHeight = height;

          if (trackPosition < minTrack || !haveMinTrack) {
            minTrack = trackPosition;
            haveMinTrack = true;
          }
          if (trackPosition > maxTrack) {
            maxTrack = trackPosition;
          }
      }

      for (int i = minTrack; i <= maxTrack; ++i) {
          TrackIntMap::iterator hi = trackHeights.find(i);
          if (hi != trackHeights.end()) {
            trackCoords[i] = accumulatedHeight;
            accumulatedHeight += hi->second;
          }
      }

      accumulatedHeight += maxTrackHeight * rowGapPercent / 100;

      if (done) break;

      if (m_pageMode != LinedStaff::MultiPageMode) {

          rowsPerPage = 0;
          done = true;
          break;

      } else {

          // Check how well all this stuff actually fits on the
          // page.  If things don't fit as well as we'd like, modify
          // at most one parameter so as to save some space, then
          // loop around again and see if it worked.  This iterative
          // approach is inefficient but the time spent here is
          // neglible in context, and it's a simple way to code it.

          int staffPageHeight = pageHeight - topMargin * 2 - titleHeight;
          rowsPerPage = staffPageHeight / accumulatedHeight;

          if (rowsPerPage < 1) {

            if (legerLines > 5) --legerLines;
            else if (rowGapPercent > 20) rowGapPercent -= 10;
            else if (legerLines > 4) --legerLines;
            else if (rowGapPercent > 0) rowGapPercent -= 10;
            else if (legerLines > 3) --legerLines;
            else if (m_printSize > 3) --m_printSize;
            else { // just accept that we'll have to overflow
                rowsPerPage = 1;
                done = true;
            }

          } else {

            if (aimFor == rowsPerPage) {

                titleHeight +=
                  (staffPageHeight - (rowsPerPage * accumulatedHeight)) / 2;

                done = true;

            } else {

                if (aimFor == -1) aimFor = rowsPerPage + 1;

                // we can perhaps accommodate another row, with care
                if (legerLines > 5) --legerLines;
                else if (rowGapPercent > 20) rowGapPercent -= 10;
                else if (legerLines > 3) --legerLines;
                else if (rowGapPercent > 0) rowGapPercent -= 10;
                else { // no, we can't
                  rowGapPercent = 0;
                  legerLines = 8;
                  done = true;
                }
            }
          }
      }
    }

    m_hlayout->setPageWidth(pageWidth - leftMargin * 2);

    int topGutter = 0;

    if (m_pageMode == LinedStaff::MultiPageMode) {

      topGutter = 20;

    } else if (m_pageMode == LinedStaff::ContinuousPageMode) {

      // fewer leger lines above staff than in linear mode --
      // compensate for this on the top staff
      topGutter = m_notePixmapFactory->getLineSpacing() * 2;
    }

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {

      Rosegarden::TrackId trackId = m_staffs[i]->getSegment().getTrack();
      Rosegarden::Track *track =
          m_staffs[i]->getSegment().getComposition()->
          getTrackById(trackId);

      if (!track) continue; // Once Again, My Friend, You Should Never See Me Here
      
      int trackPosition = track->getPosition();

      m_staffs[i]->setTitleHeight(titleHeight);
        m_staffs[i]->setRowSpacing(accumulatedHeight);
      
        if (trackPosition < maxTrack) {
            m_staffs[i]->setConnectingLineLength(trackHeights[trackPosition]);
        }

      if (trackPosition == minTrack &&
          m_pageMode != LinedStaff::LinearMode) {
          m_staffs[i]->setBarNumbersEvery(5);
      } else {
          m_staffs[i]->setBarNumbersEvery(0);
      }
        
      m_staffs[i]->setX(m_leftGutter);
      m_staffs[i]->setY(topGutter + trackCoords[trackPosition] + topMargin);
      m_staffs[i]->setPageWidth(pageWidth - leftMargin * 2);
      m_staffs[i]->setRowsPerPage(rowsPerPage);
        m_staffs[i]->setPageMode(m_pageMode);
      m_staffs[i]->setMargin(leftMargin);

      NOTATION_DEBUG << "NotationView::positionStaffs: set staff's page width to "
                   << (pageWidth - leftMargin * 2) << endl;

    }
}    

01032 void NotationView::positionPages()
{
    if (m_printMode) return;

    QPixmap background;
    QPixmap deskBackground;
    bool haveBackground = false;
    
    m_config->setGroup(Rosegarden::GeneralOptionsConfigGroup);
    if (m_config->readBoolEntry("backgroundtextures", true)) {
      QString pixmapDir =
          KGlobal::dirs()->findResource("appdata", "pixmaps/");
      if (background.load(QString("%1/misc/bg-paper-cream.xpm").
                      arg(pixmapDir))) {
          haveBackground = true;
      }
      // we're happy to ignore errors from this one:
      deskBackground.load(QString("%1/misc/bg-desktop.xpm").arg(pixmapDir));
    }

    int pageWidth = getPageWidth();
    int pageHeight = getPageHeight();
    int leftMargin = 0, topMargin = 0;
    getPageMargins(leftMargin, topMargin);
    int maxPageCount = 1;

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      int pageCount = m_staffs[i]->getPageCount();
      if (pageCount > maxPageCount) maxPageCount = pageCount;
    }
    
    for (unsigned int i = 0; i < m_pages.size(); ++i) {
      delete m_pages[i];
      delete m_pageNumbers[i];
    }
    m_pages.clear();
    m_pageNumbers.clear();
    
    if (m_pageMode != LinedStaff::MultiPageMode) {
      if (haveBackground) {
          canvas()->setBackgroundPixmap(background);
          getCanvasView()->setBackgroundMode(Qt::FixedPixmap);
          getCanvasView()->setPaletteBackgroundPixmap(background);
          getCanvasView()->setErasePixmap(background);
      }
    } else {
      if (haveBackground) {
          canvas()->setBackgroundPixmap(deskBackground);
          getCanvasView()->setBackgroundMode(Qt::FixedPixmap);
          getCanvasView()->setPaletteBackgroundPixmap(background);
          getCanvasView()->setErasePixmap(background);
      }
      
      QFont pageNumberFont;
      pageNumberFont.setPixelSize(m_fontSize * 2);
      QFontMetrics pageNumberMetrics(pageNumberFont);
      
      for (int page = 0; page < maxPageCount; ++page) {

          int x = m_leftGutter + pageWidth * page + leftMargin/4;
          int y = 20;
          int w = pageWidth - leftMargin/2;
          int h = pageHeight;
          
          QString str = QString("%1").arg(page + 1);
          QCanvasText *text = new QCanvasText(str, pageNumberFont, canvas());
          text->setX(m_leftGutter + pageWidth * page + pageWidth - pageNumberMetrics.width(str) - leftMargin);
          text->setY(y + h - pageNumberMetrics.descent() - topMargin);
          text->setZ(-999);
          text->show();
          m_pageNumbers.push_back(text);
          
          QCanvasRectangle *rect = new QCanvasRectangle(x, y, w, h, canvas());
          if (haveBackground) rect->setBrush(QBrush(Qt::white, background));
          rect->setPen(Qt::black);
          rect->setZ(-1000);
          rect->show();
          m_pages.push_back(rect);
      }
          
      updateThumbnails(false);
    }

    m_config->setGroup(NotationView::ConfigGroup);
}


void NotationView::slotUpdateStaffName()
{
    LinedStaff *staff = getLinedStaff(m_currentStaff);
    staff->drawStaffName();
}

01125 void NotationView::slotSaveOptions()
{
    m_config->setGroup(NotationView::ConfigGroup);

    m_config->writeEntry("Show Chord Name Ruler", getToggleAction("show_chords_ruler")->isChecked());
    m_config->writeEntry("Show Raw Note Ruler", getToggleAction("show_raw_note_ruler")->isChecked());
    m_config->writeEntry("Show Tempo Ruler",      getToggleAction("show_tempo_ruler")->isChecked());
    m_config->writeEntry("Show Annotations", m_annotationsVisible);
    m_config->writeEntry("Show LilyPond Directives", m_lilypondDirectivesVisible);

    m_config->sync();
}

void NotationView::setOneToolbar(const char *actionName,
                         const char *toolbarName)
{
    KToggleAction *action = getToggleAction(actionName);
    if (!action) {
      std::cerr << "WARNING: No such action as " << actionName << std::endl;
      return;
    }
    QWidget *toolbar = toolBar(toolbarName);
    if (!toolbar) {
      std::cerr << "WARNING: No such toolbar as " << toolbarName << std::endl;
      return;
    }
    action->setChecked(!toolbar->isHidden());
}
      

01155 void NotationView::readOptions()
{
    EditView::readOptions();

    setOneToolbar("show_tools_toolbar", "Tools Toolbar");
    setOneToolbar("show_notes_toolbar", "Notes Toolbar");
    setOneToolbar("show_rests_toolbar", "Rests Toolbar");
    setOneToolbar("show_clefs_toolbar", "Clefs Toolbar");
    setOneToolbar("show_group_toolbar", "Group Toolbar");
    setOneToolbar("show_marks_toolbar", "Marks Toolbar");
    setOneToolbar("show_layout_toolbar", "Layout Toolbar");
    setOneToolbar("show_transport_toolbar", "Transport Toolbar");
    setOneToolbar("show_accidentals_toolbar", "Accidentals Toolbar");
    setOneToolbar("show_meta_toolbar", "Meta Toolbar");

    m_config->setGroup(NotationView::ConfigGroup);

    bool opt;

    opt = m_config->readBoolEntry("Show Chord Name Ruler", false);
    getToggleAction("show_chords_ruler")->setChecked(opt);
    slotToggleChordsRuler();

    opt = m_config->readBoolEntry("Show Raw Note Ruler", true);
    getToggleAction("show_raw_note_ruler")->setChecked(opt);
    slotToggleRawNoteRuler();

    opt = m_config->readBoolEntry("Show Tempo Ruler", false);
    getToggleAction("show_tempo_ruler")->setChecked(opt);
    slotToggleTempoRuler();

    opt = m_config->readBoolEntry("Show Annotations", true);
    m_annotationsVisible = opt;
    getToggleAction("show_annotations")->setChecked(opt);
    slotUpdateAnnotationsStatus();
//    slotToggleAnnotations();
    
    opt = m_config->readBoolEntry("Show LilyPond Directives", true);
    m_lilypondDirectivesVisible = opt;
    getToggleAction("show_lilypond_directives")->setChecked(opt);
    slotUpdateLilyPondDirectivesStatus();
}

01198 void NotationView::setupActions()
{
    KStdAction::print(this, SLOT(slotFilePrint()), actionCollection());
    KStdAction::printPreview(this, SLOT(slotFilePrintPreview()),
                       actionCollection());

    EditViewBase::setupActions("notation.rc");
    EditView::setupActions();

    KRadioAction* noteAction = 0;
    
    // View menu stuff
    
    KActionMenu *fontActionMenu =
      new KActionMenu(i18n("Note &Font"), this, "note_font_actionmenu");

    std::set<std::string> fs(NoteFontFactory::getFontNames());
    std::vector<std::string> f(fs.begin(), fs.end());
    std::sort(f.begin(), f.end());
    
    for (std::vector<std::string>::iterator i = f.begin(); i != f.end(); ++i) {

      QString fontQName(strtoqstr(*i));

      KToggleAction *fontAction = 
          new KToggleAction
          (fontQName, 0, this, SLOT(slotChangeFontFromAction()),
           actionCollection(), "note_font_" + fontQName);

      fontAction->setChecked(*i == m_fontName);
      fontActionMenu->insert(fontAction);
    }

    actionCollection()->insert(fontActionMenu);

    m_fontSizeActionMenu =
      new KActionMenu(i18n("Si&ze"), this, "note_font_size_actionmenu");
    setupFontSizeMenu();

    actionCollection()->insert(m_fontSizeActionMenu);

    
    KActionMenu *spacingActionMenu =
      new KActionMenu(i18n("S&pacing"), this, "stretch_actionmenu");

    int defaultSpacing = m_hlayout->getSpacing();
    std::vector<int> spacings = NotationHLayout::getAvailableSpacings();

    for (std::vector<int>::iterator i = spacings.begin();
       i != spacings.end(); ++i) {
      
      KToggleAction *spacingAction =
          new KToggleAction
          (QString("%1%").arg(*i), 0, this,
           SLOT(slotChangeSpacingFromAction()),
           actionCollection(), QString("spacing_%1").arg(*i));

      spacingAction->setExclusiveGroup("spacing");
      spacingAction->setChecked(*i == defaultSpacing);
      spacingActionMenu->insert(spacingAction);
    }

    actionCollection()->insert(spacingActionMenu);
    
    KActionMenu *proportionActionMenu =
      new KActionMenu(i18n("Du&ration Factor"), this, "proportion_actionmenu");

    int defaultProportion = m_hlayout->getProportion();
    std::vector<int> proportions = NotationHLayout::getAvailableProportions();

    for (std::vector<int>::iterator i = proportions.begin();
       i != proportions.end(); ++i) {
      
      QString name = QString("%1%").arg(*i);
      if (*i == 0) name = i18n("None");

      KToggleAction *proportionAction =
          new KToggleAction
          (name, 0, this,
           SLOT(slotChangeProportionFromAction()),
           actionCollection(), QString("proportion_%1").arg(*i));

      proportionAction->setExclusiveGroup("proportion");
      proportionAction->setChecked(*i == defaultProportion);
      proportionActionMenu->insert(proportionAction);
    }

    actionCollection()->insert(proportionActionMenu);

    KActionMenu *styleActionMenu =
      new KActionMenu(i18n("Note &Style"), this, "note_style_actionmenu");

    std::vector<NoteStyleName> styles
          (NoteStyleFactory::getAvailableStyleNames());

    for (std::vector<NoteStyleName>::iterator i = styles.begin();
       i != styles.end(); ++i) {

      QString styleQName(strtoqstr(*i));

      KAction *styleAction =
          new KAction
          (styleQName, 0, this, SLOT(slotSetStyleFromAction()),
           actionCollection(), "style_" + styleQName);

      styleActionMenu->insert(styleAction);
    }

    actionCollection()->insert(styleActionMenu);

    KActionMenu *ornamentActionMenu =
      new KActionMenu(i18n("Use Ornament"), this, "ornament_actionmenu");



    new KAction
      (i18n("Insert Rest"), Key_P, this, SLOT(slotInsertRest()),
       actionCollection(), QString("insert_rest"));

    new KAction
      (i18n("Switch from Note to Rest"), Key_T, this,
       SLOT(slotSwitchFromNoteToRest()),
       actionCollection(), QString("switch_from_note_to_rest"));

    new KAction
      (i18n("Switch from Rest to Note"), Key_Y, this,
       SLOT(slotSwitchFromRestToNote()),
       actionCollection(), QString("switch_from_rest_to_note"));


    // setup Notes menu & toolbar
    QIconSet icon;
 
    for (NoteActionDataMap::Iterator actionDataIter = m_noteActionDataMap->begin();
       actionDataIter != m_noteActionDataMap->end();
       ++actionDataIter) {

        NoteActionData noteActionData = *actionDataIter;
        
        icon = QIconSet
          (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
           (noteActionData.pixmapName)));
        noteAction = new KRadioAction(noteActionData.title,
                              icon,
                              noteActionData.keycode,
                              this,
                                      SLOT(slotNoteAction()),
                                      actionCollection(),
                              noteActionData.actionName);
        noteAction->setExclusiveGroup("notes");

        if (noteActionData.noteType == Note::Crotchet &&
          noteActionData.dots == 0 && !noteActionData.rest) {
            m_selectDefaultNote = noteAction;
      }
    }

    // Note duration change actions
    for (NoteChangeActionDataMap::Iterator actionDataIter = m_noteChangeActionDataMap->begin();
       actionDataIter != m_noteChangeActionDataMap->end();
       ++actionDataIter) {

      NoteChangeActionData data = *actionDataIter;

        icon = QIconSet
          (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                                (data.pixmapName)));

      KAction *action = new KAction(data.title,
                              icon,
                              data.keycode,
                              this,
                              SLOT(slotNoteChangeAction()),
                              actionCollection(),
                              data.actionName);
    }

    //
    // Accidentals
    //
    static QString actionsAccidental[][4] = 
        {
            { i18n("No accidental"),  "1slotNoAccidental()",  "no_accidental",           "accidental-none" },
            { i18n("Follow previous accidental"),  "1slotFollowAccidental()",  "follow_accidental",           "accidental-follow" },
            { i18n("Sharp"),          "1slotSharp()",         "sharp_accidental",        "accidental-sharp" },
            { i18n("Flat"),           "1slotFlat()",          "flat_accidental",         "accidental-flat" },
            { i18n("Natural"),        "1slotNatural()",       "natural_accidental",      "accidental-natural" },
            { i18n("Double sharp"),   "1slotDoubleSharp()",   "double_sharp_accidental", "accidental-doublesharp" },
            { i18n("Double flat"),    "1slotDoubleFlat()",    "double_flat_accidental",  "accidental-doubleflat" }
        };

    for (unsigned int i = 0;
       i < sizeof(actionsAccidental)/sizeof(actionsAccidental[0]); ++i) {

        icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                        (actionsAccidental[i][3])));
        noteAction = new KRadioAction(actionsAccidental[i][0], icon, 0, this,
                                      actionsAccidental[i][1],
                                      actionCollection(), actionsAccidental[i][2]);
        noteAction->setExclusiveGroup("accidentals");
    }
    

    //
    // Clefs
    //

    // Treble
    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("clef-treble")));
    noteAction = new KRadioAction(i18n("&Treble Clef"), icon, 0, this,
                                  SLOT(slotTrebleClef()),
                                  actionCollection(), "treble_clef");
    noteAction->setExclusiveGroup("notes");

    // Tenor
    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("clef-tenor")));
    noteAction = new KRadioAction(i18n("Te&nor Clef"), icon, 0, this,
                                  SLOT(slotTenorClef()),
                                  actionCollection(), "tenor_clef");
    noteAction->setExclusiveGroup("notes");

    // Alto
    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("clef-alto")));
    noteAction = new KRadioAction(i18n("&Alto Clef"), icon, 0, this,
                                  SLOT(slotAltoClef()),
                                  actionCollection(), "alto_clef");
    noteAction->setExclusiveGroup("notes");

    // Bass
    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("clef-bass")));
    noteAction = new KRadioAction(i18n("&Bass Clef"), icon, 0, this,
                                  SLOT(slotBassClef()),
                                  actionCollection(), "bass_clef");
    noteAction->setExclusiveGroup("notes");


    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("text")));
    noteAction = new KRadioAction(i18n("&Text"), icon, Key_F8, this,
                                  SLOT(slotText()),
                                  actionCollection(), "text");
    noteAction->setExclusiveGroup("notes");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("fretboard")));
    noteAction = new KRadioAction(i18n("&Fretboard"), icon, Key_F9, this,
                                  SLOT(slotFretboard()),
                                  actionCollection(), "fretboard");
    noteAction->setExclusiveGroup("notes");

/*    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("lilypond")));
    noteAction = new KRadioAction(i18n("Lil&ypond Directive"), icon, Key_F9, this,
                                  SLOT(slotLilypondDirective()),
                                  actionCollection(), "lilypond_directive");
    noteAction->setExclusiveGroup("notes"); */


    //
    // Edition tools (eraser, selector...)
    //
    noteAction = new KRadioAction(i18n("&Erase"), "eraser", Key_F4,
                                  this, SLOT(slotEraseSelected()),
                                  actionCollection(), "erase");
    noteAction->setExclusiveGroup("notes");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("select")));
    noteAction = new KRadioAction(i18n("&Select"), icon, Key_F2,
                                  this, SLOT(slotSelectSelected()),
                                  actionCollection(), "select");
    noteAction->setExclusiveGroup("notes");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("step_by_step")));
    new KToggleAction(i18n("Ste&p Recording"), icon, 0, this,
                SLOT(slotToggleStepByStep()), actionCollection(),
                "toggle_step_by_step");


    // Edit menu
    new KAction(i18n("Select from Sta&rt"), 0, this,
            SLOT(slotEditSelectFromStart()), actionCollection(),
            "select_from_start");

    new KAction(i18n("Select to &End"), 0, this,
            SLOT(slotEditSelectToEnd()), actionCollection(),
            "select_to_end");

    new KAction(i18n("Select Whole St&aff"), Key_A + CTRL, this,
            SLOT(slotEditSelectWholeStaff()), actionCollection(),
            "select_whole_staff");

    new KAction(i18n("C&ut and Close"), CTRL + SHIFT + Key_X, this,
            SLOT(slotEditCutAndClose()), actionCollection(),
            "cut_and_close");

    new KAction(i18n("Pa&ste..."), CTRL + SHIFT + Key_V, this,
            SLOT(slotEditGeneralPaste()), actionCollection(),
            "general_paste");

    new KAction(i18n("De&lete"), Key_Delete, this,
            SLOT(slotEditDelete()), actionCollection(),
            "delete");

    //
    // Settings menu
    //
    int layoutMode = m_config->readNumEntry("layoutmode", 0);

    QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");

    QCanvasPixmap pixmap(pixmapDir + "/toolbar/linear-layout.xpm");
    icon = QIconSet(pixmap);
    KRadioAction *linearModeAction = new KRadioAction
        (i18n("&Linear Layout"), icon, 0, this, SLOT(slotLinearMode()),
         actionCollection(), "linear_mode");
    linearModeAction->setExclusiveGroup("layoutMode");
    if (layoutMode == 0) linearModeAction->setChecked(true);

    pixmap.load(pixmapDir + "/toolbar/continuous-page-mode.xpm");
    icon = QIconSet(pixmap);
    KRadioAction *continuousPageModeAction = new KRadioAction
        (i18n("&Continuous Page Layout"), icon, 0, this, SLOT(slotContinuousPageMode()),
         actionCollection(), "continuous_page_mode");
    continuousPageModeAction->setExclusiveGroup("layoutMode");
    if (layoutMode == 1) continuousPageModeAction->setChecked(true);

    pixmap.load(pixmapDir + "/toolbar/multi-page-mode.xpm");
    icon = QIconSet(pixmap);
    KRadioAction *multiPageModeAction = new KRadioAction
        (i18n("&Multiple Page Layout"), icon, 0, this, SLOT(slotMultiPageMode()),
         actionCollection(), "multi_page_mode");
    multiPageModeAction->setExclusiveGroup("layoutMode");
    if (layoutMode == 2) multiPageModeAction->setChecked(true);

    new KToggleAction(i18n("Show Ch&ord Name Ruler"), 0, this,
                      SLOT(slotToggleChordsRuler()),
                      actionCollection(), "show_chords_ruler");

    new KToggleAction(i18n("Show Ra&w Note Ruler"), 0, this,
                      SLOT(slotToggleRawNoteRuler()),
                      actionCollection(), "show_raw_note_ruler");

    new KToggleAction(i18n("Show &Tempo Ruler"), 0, this,
                      SLOT(slotToggleTempoRuler()),
                      actionCollection(), "show_tempo_ruler");

    new KToggleAction(i18n("Show &Annotations"), 0, this,
                      SLOT(slotToggleAnnotations()),
                      actionCollection(), "show_annotations");

    new KToggleAction(i18n("Show Lily&Pond Directives"), 0, this,
                      SLOT(slotToggleLilyPondDirectives()),
                      actionCollection(), "show_lilypond_directives");

    new KAction(i18n("Open L&yric Editor"), 0, this, SLOT(slotEditLyrics()),
            actionCollection(), "lyric_editor");

    //
    // Group menu
    //
    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-beam")));

    new KAction(NotesMenuBeamCommand::getGlobalName(), icon, Key_B + CTRL, this,
                SLOT(slotGroupBeam()), actionCollection(), "beam");

    new KAction(NotesMenuAutoBeamCommand::getGlobalName(), 0, this,
                SLOT(slotGroupAutoBeam()), actionCollection(), "auto_beam");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-unbeam")));

    new KAction(NotesMenuBreakCommand::getGlobalName(), icon, Key_U + CTRL, this,
                SLOT(slotGroupBreak()), actionCollection(), "break_group");
    
    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-simple-tuplet")));

    new KAction(AdjustMenuTupletCommand::getGlobalName(true), icon, Key_R + CTRL, this,
            SLOT(slotGroupSimpleTuplet()), actionCollection(), "simple_tuplet");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-tuplet")));

    new KAction(AdjustMenuTupletCommand::getGlobalName(false), icon, Key_T + CTRL, this,
            SLOT(slotGroupGeneralTuplet()), actionCollection(), "tuplet");

    new KAction(AdjustMenuUnTupletCommand::getGlobalName(), 0, this,
                SLOT(slotGroupUnTuplet()), actionCollection(), "break_tuplets");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("triplet")));
    (new KToggleAction(i18n("Trip&let Insert Mode"), icon, Key_G,
                   this, SLOT(slotUpdateInsertModeStatus()),
                       actionCollection(), "triplet_mode"))->
      setChecked(false);

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("chord")));
    (new KToggleAction(i18n("C&hord Insert Mode"), icon, Key_H,
                   this, SLOT(slotUpdateInsertModeStatus()),
                  actionCollection(), "chord_mode"))->
      setChecked(false);

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-grace")));

    new KAction(AdjustMenuGraceCommand::getGlobalName(), icon, 0, this,
            SLOT(slotGroupGrace()), actionCollection(), "grace");

    new KAction(AdjustMenuUnGraceCommand::getGlobalName(), 0, this,
            SLOT(slotGroupUnGrace()), actionCollection(), "ungrace");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-slur")));

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::Slur), icon, Key_ParenRight, this,
                SLOT(slotGroupSlur()), actionCollection(), "slur");

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::PhrasingSlur), 0, Key_ParenRight + CTRL, this,
                SLOT(slotGroupPhrasingSlur()), actionCollection(), "phrasing_slur");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-glissando")));

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::Glissando), icon, 0, this,
                SLOT(slotGroupGlissando()), actionCollection(), "glissando");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-crescendo")));

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::Crescendo), icon, Key_Less, this,
                SLOT(slotGroupCrescendo()), actionCollection(), "crescendo");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-decrescendo")));

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::Decrescendo), icon, Key_Greater, this,
                SLOT(slotGroupDecrescendo()), actionCollection(), "decrescendo");

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::QuindicesimaUp), 0, 0, this,
                SLOT(slotGroupOctave2Up()), actionCollection(), "octave_2up");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-ottava")));

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::OttavaUp), icon, 0, this,
                SLOT(slotGroupOctaveUp()), actionCollection(), "octave_up");

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::OttavaDown), 0, 0, this,
                SLOT(slotGroupOctaveDown()), actionCollection(), "octave_down");

    new KAction(NotesMenuAddIndicationCommand::getGlobalName
                (Rosegarden::Indication::QuindicesimaDown), 0, 0, this,
                SLOT(slotGroupOctave2Down()), actionCollection(), "octave_2down");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("group-chord")));
    new KAction(AdjustMenuMakeChordCommand::getGlobalName(), icon, 0, this,
            SLOT(slotGroupMakeChord()), actionCollection(), "make_chord");

    // setup Transforms menu
    new KAction(AdjustMenuNormalizeRestsCommand::getGlobalName(), Key_N + CTRL, this,
                SLOT(slotTransformsNormalizeRests()), actionCollection(),
                "normalize_rests");

    new KAction(AdjustMenuCollapseRestsCommand::getGlobalName(), 0, this,
                SLOT(slotTransformsCollapseRests()), actionCollection(),
                "collapse_rests_aggressively");

    new KAction(AdjustMenuCollapseNotesCommand::getGlobalName(), Key_Equal + CTRL, this,
                SLOT(slotTransformsCollapseNotes()), actionCollection(),
                "collapse_notes");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("transforms-tie")));

    new KAction(NotesMenuTieNotesCommand::getGlobalName(), icon, Key_AsciiTilde, this,
                SLOT(slotTransformsTieNotes()), actionCollection(),
                "tie_notes");

    new KAction(AdjustMenuUntieNotesCommand::getGlobalName(), 0, this,
                SLOT(slotTransformsUntieNotes()), actionCollection(),
                "untie_notes");

    new KAction(AdjustMenuMakeNotesViableCommand::getGlobalName(), 0, this,
            SLOT(slotTransformsMakeNotesViable()), actionCollection(),
            "make_notes_viable");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("transforms-decounterpoint")));

    new KAction(AdjustMenuDeCounterpointCommand::getGlobalName(), icon, 0, this,
            SLOT(slotTransformsDeCounterpoint()), actionCollection(),
            "de_counterpoint");

    new KAction(AdjustMenuChangeStemsCommand::getGlobalName(true),
            0, Key_PageUp + CTRL, this,
                SLOT(slotTransformsStemsUp()), actionCollection(),
                "stems_up");

    new KAction(AdjustMenuChangeStemsCommand::getGlobalName(false),
            0, Key_PageDown + CTRL, this,
                SLOT(slotTransformsStemsDown()), actionCollection(),
                "stems_down");

    new KAction(AdjustMenuRestoreStemsCommand::getGlobalName(), 0, this,
                SLOT(slotTransformsRestoreStems()), actionCollection(),
                "restore_stems");

    new KAction(AdjustMenuChangeSlurPositionCommand::getGlobalName(true),
            0, this,
                SLOT(slotTransformsSlursAbove()), actionCollection(),
                "slurs_above");

    new KAction(AdjustMenuChangeSlurPositionCommand::getGlobalName(false),
            0, this,
                SLOT(slotTransformsSlursBelow()), actionCollection(),
                "slurs_below");

    new KAction(AdjustMenuRestoreSlursCommand::getGlobalName(), 0, this,
                SLOT(slotTransformsRestoreSlurs()), actionCollection(),
                "restore_slurs");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Set, Rosegarden::Accidentals::DoubleFlat),
            0, this,
            SLOT(slotRespellDoubleFlat()), actionCollection(),
                "respell_doubleflat");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Set, Rosegarden::Accidentals::Flat),
            0, this,
            SLOT(slotRespellFlat()), actionCollection(),
                "respell_flat");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Set, Rosegarden::Accidentals::Natural),
            0, this,
            SLOT(slotRespellNatural()), actionCollection(),
                "respell_natural");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Set, Rosegarden::Accidentals::Sharp),
            0, this,
            SLOT(slotRespellSharp()), actionCollection(),
                "respell_sharp");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Set, Rosegarden::Accidentals::DoubleSharp),
            0, this,
            SLOT(slotRespellDoubleSharp()), actionCollection(),
                "respell_doublesharp");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Up, Rosegarden::Accidentals::NoAccidental),
            Key_Up + CTRL + SHIFT, this,
            SLOT(slotRespellUp()), actionCollection(),
                "respell_up");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Down, Rosegarden::Accidentals::NoAccidental),
            Key_Down + CTRL + SHIFT, this,
            SLOT(slotRespellDown()), actionCollection(),
                "respell_down");

    new KAction(RespellCommand::getGlobalName
            (RespellCommand::Restore, Rosegarden::Accidentals::NoAccidental),
            0, this,
            SLOT(slotRespellRestore()), actionCollection(),
                "respell_restore");

    new KAction(MakeAccidentalsCautionaryCommand::getGlobalName(true),
            0, this,
            SLOT(slotShowCautionary()), actionCollection(),
            "show_cautionary");

    new KAction(MakeAccidentalsCautionaryCommand::getGlobalName(false),
            0, this,
            SLOT(slotCancelCautionary()), actionCollection(),
            "cancel_cautionary");

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("quantize")));

    new KAction(EventQuantizeCommand::getGlobalName(), icon, Key_Equal, this,
                SLOT(slotTransformsQuantize()), actionCollection(),
                "quantize");

    new KAction(AdjustMenuFixNotationQuantizeCommand::getGlobalName(), 0,
            this, SLOT(slotTransformsFixQuantization()), actionCollection(),
                "fix_quantization");

    new KAction(AdjustMenuRemoveNotationQuantizeCommand::getGlobalName(), 0,
            this, SLOT(slotTransformsRemoveQuantization()), actionCollection(),
                "remove_quantization");

    new KAction(AdjustMenuInterpretCommand::getGlobalName(), 0,
            this, SLOT(slotTransformsInterpret()), actionCollection(),
            "interpret");

    new KAction(i18n("&Dump selected events to stderr"), 0, this,
            SLOT(slotDebugDump()), actionCollection(), "debug_dump");

    for (MarkActionDataMap::Iterator i = m_markActionDataMap->begin();
       i != m_markActionDataMap->end(); ++i) {

        const MarkActionData &markActionData = *i;

      icon = QIconSet(NotePixmapFactory::toQPixmap
                  (NotePixmapFactory::makeMarkMenuPixmap(markActionData.mark)));

      new KAction(markActionData.title,
                icon,
                markActionData.keycode,
                this,
                SLOT(slotAddMark()),
                actionCollection(),
                markActionData.actionName);
    }

    icon = QIconSet
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
        ("text-mark")));

    new KAction(NotesMenuAddTextMarkCommand::getGlobalName(), icon, 0, this,
                SLOT(slotMarksAddTextMark()), actionCollection(),
                "add_text_mark");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("0"), 0, Key_0 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_0");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("1"), 0, Key_1 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_1");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("2"), 0, Key_2 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_2");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("3"), 0, Key_3 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_3");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("4"), 0, Key_4 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_4");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("5"), 0, Key_5 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_5");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName("+"), 0, Key_9 + ALT, this,
                SLOT(slotMarksAddFingeringMarkFromAction()), actionCollection(),
                "add_fingering_plus");

    new KAction(NotesMenuAddFingeringMarkCommand::getGlobalName(), 0, 0, this,
                SLOT(slotMarksAddFingeringMark()), actionCollection(),
                "add_fingering_mark");

    new KAction(NotesMenuRemoveMarksCommand::getGlobalName(), 0, this,
                SLOT(slotMarksRemoveMarks()), actionCollection(),
                "remove_marks");

    new KAction(NotesMenuRemoveFingeringMarksCommand::getGlobalName(), 0, this,
                SLOT(slotMarksRemoveFingeringMarks()), actionCollection(),
                "remove_fingering_marks");

    new KAction(i18n("Ma&ke Ornament..."), 0, this,
            SLOT(slotMakeOrnament()), actionCollection(),
            "make_ornament");

    new KAction(i18n("Trigger &Ornament..."), 0, this,
            SLOT(slotUseOrnament()), actionCollection(),
            "use_ornament");

    new KAction(i18n("Remove Ornament..."), 0, this,
            SLOT(slotRemoveOrnament()), actionCollection(),
            "remove_ornament");

    static QString slashTitles[] = {
      i18n("&None"), "&1", "&2", "&3", "&4", "&5"
    };
    for (int i = 0; i <= 5; ++i) {
      new KAction(slashTitles[i], 0, this,
                SLOT(slotAddSlashes()), actionCollection(),
                QString("slashes_%1").arg(i));
    }

    new KAction(i18n("Add Fretboard"),
            0,
            this,
            SLOT(slotAddFretboard()),
            actionCollection(),
            "add_fretboard");

    new KAction(ClefInsertionCommand::getGlobalName(), 0, this,
                SLOT(slotEditAddClef()), actionCollection(),
                "add_clef");

    new KAction(KeyInsertionCommand::getGlobalName(), 0, this,
                SLOT(slotEditAddKeySignature()), actionCollection(),
                "add_key_signature");

    new KAction(SustainInsertionCommand::getGlobalName(true), 0, this,
                SLOT(slotEditAddSustainDown()), actionCollection(),
                "add_sustain_down");

    new KAction(SustainInsertionCommand::getGlobalName(false), 0, this,
                SLOT(slotEditAddSustainUp()), actionCollection(),
                "add_sustain_up");

    // setup Settings menu
    static QString actionsToolbars[][4] = 
        {
            { i18n("Show T&ools Toolbar"),  "1slotToggleToolsToolBar()",  "show_tools_toolbar",                    "palette-tools" },
            { i18n("Show &Notes Toolbar"),  "1slotToggleNotesToolBar()",  "show_notes_toolbar",                    "palette-notes" },
            { i18n("Show &Rests Toolbar"),  "1slotToggleRestsToolBar()",  "show_rests_toolbar",                    "palette-rests" },
            { i18n("Show &Accidentals Toolbar"),   "1slotToggleAccidentalsToolBar()",  "show_accidentals_toolbar", "palette-accidentals" },
            { i18n("Show Cle&fs Toolbar"),  "1slotToggleClefsToolBar()",  "show_clefs_toolbar",
          "palette-clefs" },
            { i18n("Show &Marks Toolbar"), "1slotToggleMarksToolBar()",   "show_marks_toolbar",
          "palette-marks" },
            { i18n("Show &Group Toolbar"), "1slotToggleGroupToolBar()",   "show_group_toolbar",
          "palette-group" },            
            { i18n("Show &Layout Toolbar"), "1slotToggleLayoutToolBar()", "show_layout_toolbar",
          "palette-font" },
            { i18n("Show Trans&port Toolbar"), "1slotToggleTransportToolBar()", "show_transport_toolbar",
        "palette-transport" },
            { i18n("Show M&eta Toolbar"), "1slotToggleMetaToolBar()", "show_meta_toolbar",
          "palette-meta" }
        };

    for (unsigned int i = 0;
       i < sizeof(actionsToolbars)/sizeof(actionsToolbars[0]); ++i) {

        icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap(actionsToolbars[i][3])));

        new KToggleAction(actionsToolbars[i][0], icon, 0,
                          this, actionsToolbars[i][1],
                          actionCollection(), actionsToolbars[i][2]);
    }

    new KAction(i18n("Cursor &Back"), 0, Key_Left, this,
            SLOT(slotStepBackward()), actionCollection(),
            "cursor_back");

    new KAction(i18n("Cursor &Forward"), 0, Key_Right, this,
            SLOT(slotStepForward()), actionCollection(),
            "cursor_forward");

    new KAction(i18n("Cursor Ba&ck Bar"), 0, Key_Left + CTRL, this,
            SLOT(slotJumpBackward()), actionCollection(),
            "cursor_back_bar");

    new KAction(i18n("Cursor For&ward Bar"), 0, Key_Right + CTRL, this,
            SLOT(slotJumpForward()), actionCollection(),
            "cursor_forward_bar");

    new KAction(i18n("Cursor Back and Se&lect"), SHIFT + Key_Left, this,
            SLOT(slotExtendSelectionBackward()), actionCollection(),
            "extend_selection_backward");

    new KAction(i18n("Cursor Forward and &Select"), SHIFT + Key_Right, this,
            SLOT(slotExtendSelectionForward()), actionCollection(),
            "extend_selection_forward");

    new KAction(i18n("Cursor Back Bar and Select"), SHIFT + CTRL + Key_Left, this,
            SLOT(slotExtendSelectionBackwardBar()), actionCollection(),
            "extend_selection_backward_bar");

    new KAction(i18n("Cursor Forward Bar and Select"), SHIFT + CTRL + Key_Right, this,
            SLOT(slotExtendSelectionForwardBar()), actionCollection(),
            "extend_selection_forward_bar");

/*!!! not here yet
    new KAction(i18n("Move Selection Left"), Key_Minus, this,
            SLOT(slotMoveSelectionLeft()), actionCollection(),
            "move_selection_left");
*/

    new KAction(i18n("Cursor to St&art"), 0,
            /* #1025717: conflicting meanings for ctrl+a - dupe with Select All
              Key_A + CTRL, */ this,
            SLOT(slotJumpToStart()), actionCollection(),
            "cursor_start");

    new KAction(i18n("Cursor to &End"), 0, Key_E + CTRL, this,
            SLOT(slotJumpToEnd()), actionCollection(),
            "cursor_end");

    new KAction(i18n("Cursor &Up Staff"), 0, Key_Up + SHIFT, this,
            SLOT(slotCurrentStaffUp()), actionCollection(),
            "cursor_up_staff");

    new KAction(i18n("Cursor &Down Staff"), 0, Key_Down + SHIFT, this,
            SLOT(slotCurrentStaffDown()), actionCollection(),
            "cursor_down_staff");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-cursor-to-pointer")));
    new KAction(i18n("Cursor to &Playback Pointer"), icon, 0, this,
            SLOT(slotJumpCursorToPlayback()), actionCollection(),
            "cursor_to_playback_pointer");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-play")));
    new KAction(i18n("&Play"), icon, Key_Enter, this,
            SIGNAL(play()), actionCollection(), "play");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-stop")));
    new KAction(i18n("&Stop"), icon, Key_Insert, this,
            SIGNAL(stop()), actionCollection(), "stop");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-rewind")));
    new KAction(i18n("Re&wind"), icon, Key_End, this,
            SIGNAL(rewindPlayback()), actionCollection(),
            "playback_pointer_back_bar");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-ffwd")));
    new KAction(i18n("&Fast Forward"), icon, Key_PageDown, this,
            SIGNAL(fastForwardPlayback()), actionCollection(),
            "playback_pointer_forward_bar");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-rewind-end")));
    new KAction(i18n("Rewind to &Beginning"), icon, 0, this,
            SIGNAL(rewindPlaybackToBeginning()), actionCollection(),
            "playback_pointer_start");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-ffwd-end")));
    new KAction(i18n("Fast Forward to &End"), icon, 0, this,
            SIGNAL(fastForwardPlaybackToEnd()), actionCollection(),
            "playback_pointer_end");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                ("transport-pointer-to-cursor")));
    new KAction(i18n("Playback Pointer to &Cursor"), icon, 0, this,
            SLOT(slotJumpPlaybackToCursor()), actionCollection(),
            "playback_pointer_to_cursor");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                                                 ("transport-solo")));
    new KToggleAction(i18n("&Solo"), icon, 0, this,
                SLOT(slotToggleSolo()), actionCollection(),
                "toggle_solo");

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                                                 ("transport-tracking")));
    (new KToggleAction(i18n("Scro&ll to Follow Playback"), icon, Key_Pause, this,
                   SLOT(slotToggleTracking()), actionCollection(),
                   "toggle_tracking"))->setChecked(m_playTracking);

    icon = QIconSet(NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap
                    ("transport-panic")));
    new KAction(i18n("Panic"), icon, Key_P + CTRL + ALT, this,
                SIGNAL(panic()), actionCollection(), "panic");

    new KAction(i18n("Set Loop to Selection"), Key_Semicolon + CTRL, this,
            SLOT(slotPreviewSelection()), actionCollection(),
            "preview_selection");

    new KAction(i18n("Clear L&oop"), Key_Colon + CTRL, this,
            SLOT(slotClearLoop()), actionCollection(),
            "clear_loop");

    new KAction(i18n("Clear Selection"), Key_Escape, this,
            SLOT(slotClearSelection()), actionCollection(),
            "clear_selection");

//    QString pixmapDir =
//    KGlobal::dirs()->findResource("appdata", "pixmaps/");
//    icon = QIconSet(QCanvasPixmap(pixmapDir + "/toolbar/eventfilter.xpm"));
    new KAction(i18n("&Filter Selection"), "filter", Key_F + CTRL, this,
                SLOT(slotFilterSelection()), actionCollection(),
                "filter_selection");

    new KAction(i18n("Push &Left"), 0, this,
            SLOT(slotFinePositionLeft()), actionCollection(),
            "fine_position_left");

    new KAction(i18n("Push &Right"), 0, this,
            SLOT(slotFinePositionRight()), actionCollection(),
            "fine_position_right");

    new KAction(i18n("Push &Up"), 0, this,
            SLOT(slotFinePositionUp()), actionCollection(),
            "fine_position_up");

    new KAction(i18n("Push &Down"), 0, this,
            SLOT(slotFinePositionDown()), actionCollection(),
            "fine_position_down");

    new KAction(i18n("Restore &Computed Positions"), 0, this,
            SLOT(slotFinePositionRestore()), actionCollection(),
            "fine_position_restore");

    new KAction(i18n("Make &Invisible"), 0, this,
            SLOT(slotMakeInvisible()), actionCollection(),
            "make_invisible");

    new KAction(i18n("Make &Visible"), 0, this,
            SLOT(slotMakeVisible()), actionCollection(),
            "make_visible");

    new KAction(i18n("Toggle Dot"), Key_Period, this,
            SLOT(slotToggleDot()), actionCollection(),
            "toggle_dot");

    new KAction(i18n("Add Dot"), Key_Period + CTRL, this,
            SLOT(slotAddDot()), actionCollection(),
            "add_dot");

    new KAction(i18n("Add Dot"), Key_Period + CTRL + ALT, this,
            SLOT(slotAddDotNotationOnly()), actionCollection(),
            "add_notation_dot");

    createGUI(getRCFileName(), false);
}

bool
02141 NotationView::isInChordMode()
{
    return ((KToggleAction *)actionCollection()->action("chord_mode"))->
      isChecked();
}

bool
02148 NotationView::isInTripletMode()
{
    return ((KToggleAction *)actionCollection()->action("triplet_mode"))->
      isChecked();
}

void
02155 NotationView::setupFontSizeMenu(std::string oldFontName)
{
    if (oldFontName != "") {

      std::vector<int> sizes = NoteFontFactory::getScreenSizes(oldFontName);
      
      for (unsigned int i = 0; i < sizes.size(); ++i) {
          KAction *action =
            actionCollection()->action
            (QString("note_font_size_%1").arg(sizes[i]));
          m_fontSizeActionMenu->remove(action);

          // Don't delete -- that could cause a crash when this
          // function is called from the action itself.  Instead
          // we reuse and reinsert existing actions below.
      }
    }

    std::vector<int> sizes = NoteFontFactory::getScreenSizes(m_fontName);

    for (unsigned int i = 0; i < sizes.size(); ++i) {

      QString actionName = QString("note_font_size_%1").arg(sizes[i]);

      KToggleAction *sizeAction = dynamic_cast<KToggleAction *>
          (actionCollection()->action(actionName));

      if (!sizeAction) {
          sizeAction = 
            new KToggleAction(i18n("1 pixel", "%n pixels", sizes[i]),
                                  0, this,
                                  SLOT(slotChangeFontSizeFromAction()),
                                  actionCollection(), actionName);
      }

      sizeAction->setChecked(sizes[i] == m_fontSize);
      m_fontSizeActionMenu->insert(sizeAction);
    }
}

LinedStaff *
02196 NotationView::getLinedStaff(int i) 
{
    return getNotationStaff(i);
}

LinedStaff *
02202 NotationView::getLinedStaff(const Rosegarden::Segment &segment)
{
    return getNotationStaff(segment);
}

NotationStaff *
02208 NotationView::getNotationStaff(const Segment &segment)
{
    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
        if (&(m_staffs[i]->getSegment()) == &segment) return m_staffs[i];
    }
    return 0;
}

02216 void NotationView::initLayoutToolbar()
{
    KToolBar *layoutToolbar = toolBar("Layout Toolbar");
    
    if (!layoutToolbar) {
      std::cerr
            << "NotationView::initLayoutToolbar() : layout toolbar not found"
          << std::endl;
        return;
    }

    new QLabel(i18n("  Font:  "), layoutToolbar, "font label");

    //
    // font combo
    //
    m_fontCombo = new KComboBox(layoutToolbar);
    m_fontCombo->setEditable(false);

    std::set<std::string> fs(NoteFontFactory::getFontNames());
    std::vector<std::string> f(fs.begin(), fs.end());
    std::sort(f.begin(), f.end());

    bool foundFont = false;

    for (std::vector<std::string>::iterator i = f.begin(); i != f.end(); ++i) {

      QString fontQName(strtoqstr(*i));

        m_fontCombo->insertItem(fontQName);
        if (fontQName.lower() == strtoqstr(m_fontName).lower()) {
            m_fontCombo->setCurrentItem(m_fontCombo->count() - 1);
          foundFont = true;
        }
    }

    if (!foundFont) {
      KMessageBox::sorry
          (this, i18n("Unknown font \"%1\", using default").arg
           (strtoqstr(m_fontName)));
      m_fontName = NoteFontFactory::getDefaultFontName();
    }
    
    connect(m_fontCombo, SIGNAL(activated(const QString &)),
            this,        SLOT(slotChangeFont(const QString &)));

    new QLabel(i18n("  Size:  "), layoutToolbar, "size label");

    QString value;

    //
    // font size combo
    //
    std::vector<int> sizes = NoteFontFactory::getScreenSizes(m_fontName);
    m_fontSizeCombo = new KComboBox(layoutToolbar, "font size combo");

    for (std::vector<int>::iterator i = sizes.begin(); i != sizes.end(); ++i) {

        value.setNum(*i);
        m_fontSizeCombo->insertItem(value);
    }
    // set combo's current value to default
    value.setNum(m_fontSize);
    m_fontSizeCombo->setCurrentText(value);

    connect(m_fontSizeCombo, SIGNAL(activated(const QString&)),
            this, SLOT(slotChangeFontSizeFromStringValue(const QString&)));

    new QLabel(i18n("  Spacing:  "), layoutToolbar, "spacing label");

    //
    // spacing combo
    //
    int defaultSpacing = m_hlayout->getSpacing();
    std::vector<int> spacings = NotationHLayout::getAvailableSpacings();

    m_spacingCombo = new KComboBox(layoutToolbar, "spacing combo");
    for (std::vector<int>::iterator i = spacings.begin(); i != spacings.end(); ++i) {

        value.setNum(*i);
        value += "%";
        m_spacingCombo->insertItem(value);
    }
    // set combo's current value to default
    value.setNum(defaultSpacing); value += "%";
    m_spacingCombo->setCurrentText(value);
    
    connect(m_spacingCombo, SIGNAL(activated(const QString&)),
            this, SLOT(slotChangeSpacingFromStringValue(const QString&)));
}

02307 void NotationView::initStatusBar()
{
    KStatusBar* sb = statusBar();

    m_hoveredOverNoteName = new QLabel(sb);
    m_hoveredOverNoteName->setMinimumWidth(32);

    m_hoveredOverAbsoluteTime = new QLabel(sb);
    m_hoveredOverAbsoluteTime->setMinimumWidth(160);

    sb->addWidget(m_hoveredOverAbsoluteTime);
    sb->addWidget(m_hoveredOverNoteName);

    QHBox *hbox = new QHBox(sb);
    m_currentNotePixmap = new QLabel(hbox);
    m_currentNotePixmap->setMinimumWidth(20);
    m_insertModeLabel = new QLabel(hbox);
    m_annotationsLabel = new QLabel(hbox);
    m_lilypondDirectivesLabel = new QLabel(hbox);
    sb->addWidget(hbox);

    sb->insertItem(KTmpStatusMsg::getDefaultMsg(),
                   KTmpStatusMsg::getDefaultId(), 1);
    sb->setItemAlignment(KTmpStatusMsg::getDefaultId(), 
                         AlignLeft | AlignVCenter);

    m_selectionCounter = new QLabel(sb);
    sb->addWidget(m_selectionCounter);

    m_progressBar = new RosegardenProgressBar(100, true, sb);
    m_progressBar->setMinimumWidth(100);
    sb->addWidget(m_progressBar);
}

02341 QSize NotationView::getViewSize()
{
    return canvas()->size();
}

02346 void NotationView::setViewSize(QSize s)
{
    canvas()->resize(s.width(), s.height());
}


void
02353 NotationView::setPageMode(LinedStaff::PageMode pageMode)
{
    m_pageMode = pageMode;

    if (pageMode != LinedStaff::LinearMode) {
      if (m_topBarButtons) m_topBarButtons->hide();
      if (m_bottomBarButtons) m_bottomBarButtons->hide();
      if (m_chordNameRuler) m_chordNameRuler->hide();
      if (m_rawNoteRuler) m_rawNoteRuler->hide();
      if (m_tempoRuler) m_tempoRuler->hide();
    } else {
      if (m_topBarButtons) m_topBarButtons->show();
      if (m_bottomBarButtons) m_bottomBarButtons->show();
      if (m_chordNameRuler && getToggleAction("show_chords_ruler")->isChecked())
          m_chordNameRuler->show();
      if (m_rawNoteRuler && getToggleAction("show_raw_note_ruler")->isChecked())
          m_rawNoteRuler->show();
      if (m_tempoRuler && getToggleAction("show_tempo_ruler")->isChecked())
          m_tempoRuler->show();
    }

    stateChanged("linear_mode",
             (pageMode == LinedStaff::LinearMode ? KXMLGUIClient::StateNoReverse :
                                                   KXMLGUIClient::StateReverse));

    int pageWidth = getPageWidth();
    int topMargin = 0, leftMargin = 0;
    getPageMargins(leftMargin, topMargin);

    m_hlayout->setPageMode(pageMode != LinedStaff::LinearMode);
    m_hlayout->setPageWidth(pageWidth - leftMargin * 2);

    NOTATION_DEBUG << "NotationView::setPageMode: set layout's page width to "
               << (pageWidth - leftMargin * 2) << endl;

    positionStaffs();

    bool layoutApplied = applyLayout();
    if (!layoutApplied) KMessageBox::sorry(0, "Couldn't apply layout");
    else {
        for (unsigned int i = 0; i < m_staffs.size(); ++i) {
          m_staffs[i]->markChanged();
        }
    }

    positionPages();

    if (!m_printMode) {
      updateView();
      slotSetInsertCursorPosition(getInsertionTime(), false, false);
      slotSetPointerPosition(getDocument()->getComposition().getPosition(), false);
    }

    Rosegarden::Profiles::getInstance()->dump();
}   

int
02410 NotationView::getPageWidth()
{
    if (m_pageMode != LinedStaff::MultiPageMode) {

      if (isInPrintMode() && getCanvasView() && getCanvasView()->canvas())
          return getCanvasView()->canvas()->width();
      
      if (getCanvasView()) {
          return
            getCanvasView()->width() -
            getCanvasView()->verticalScrollBar()->width() -
            m_leftGutter - 10;
      }

      return width() - 50;

    } else {

      //!!! For the moment we use A4 for this calculation
      
      double printSizeMm = 25.4 * ((double)m_printSize / 72.0);
      double mmPerPixel = printSizeMm / (double)m_notePixmapFactory->getSize();
      return (int)(210.0 / mmPerPixel);
    }
}

int
02437 NotationView::getPageHeight()
{
    if (m_pageMode != LinedStaff::MultiPageMode) {

      if (isInPrintMode() && getCanvasView() && getCanvasView()->canvas())
          return getCanvasView()->canvas()->height();
      
      if (getCanvasView()) {
          return getCanvasView()->height();
      }

      return (height() > 200 ? height() - 100 : height());

    } else {

      //!!! For the moment we use A4 for this calculation
      
      double printSizeMm = 25.4 * ((double)m_printSize / 72.0);
      double mmPerPixel = printSizeMm / (double)m_notePixmapFactory->getSize();
      return (int)(297.0 / mmPerPixel);
    }
}

void
02461 NotationView::getPageMargins(int &left, int &top)
{
    if (m_pageMode != LinedStaff::MultiPageMode) {

      left = 0;
      top = 0;

    } else {

      //!!! For the moment we use A4 for this calculation
      
      double printSizeMm = 25.4 * ((double)m_printSize / 72.0);
      double mmPerPixel = printSizeMm / (double)m_notePixmapFactory->getSize();
      left = (int)(20.0 / mmPerPixel);
      top  = (int)(15.0 / mmPerPixel);
    }
}

/// Scrolls the view such that the given time is centered
void
NotationView::scrollToTime(timeT t) {

    double notationViewLayoutCoord = m_hlayout->getXForTime(t);

    // Doesn't appear to matter which staff we use
    //!!! actually it probably does matter, if they don't have the same extents
    double notationViewCanvasCoord =
      getLinedStaff(0)->getCanvasCoordsForLayoutCoords
      (notationViewLayoutCoord, 0).first;

    // HK: I could have sworn I saw a hard-coded scroll happen somewhere
    // (i.e. a default extra scroll to make up for the staff not beginning on
    // the left edge) but now I can't find it.
    getCanvasView()->slotScrollHorizSmallSteps
      (int(notationViewCanvasCoord));// + DEFAULT_STAFF_OFFSET);
}

Rosegarden::RulerScale*
NotationView::getHLayout()
{
    return m_hlayout;
}

void
NotationView::paintEvent(QPaintEvent *e)
{
    m_inPaintEvent = true;

    // This is duplicated here from EditViewBase, because (a) we need
    // to know about the segment being removed before we try to check
    // the staff names etc., and (b) it's not safe to call close()
    // from EditViewBase::paintEvent if we're then going to try to do
    // some more work afterwards in this function

    if (isCompositionModified()) {
      
        // Check if one of the segments we display has been removed
        // from the composition.
        //
      // For the moment we'll have to close the view if any of the
      // segments we handle has been deleted.

      for (unsigned int i = 0; i < m_segments.size(); ++i) {

          if (!m_segments[i]->getComposition()) {
            // oops, I think we've been deleted
            close();
            return;
          }
      }
    }

    int topMargin = 0, leftMargin = 0;
    getPageMargins(leftMargin, topMargin);

    if (m_pageMode == LinedStaff::ContinuousPageMode) {
      // relayout if the window width changes significantly in continuous page mode
      int diff = int(getPageWidth() - leftMargin*2 - m_hlayout->getPageWidth());
      if (diff < -10 || diff > 10) {
          setPageMode(m_pageMode);
          refreshSegment(0, 0, 0);
      }
      
    } else if (m_pageMode == LinedStaff::LinearMode) {
      // resize canvas again if the window height has changed significantly
      if (getCanvasView() && getCanvasView()->canvas()) {
          int diff = int(getPageHeight() - getCanvasView()->canvas()->height());
          if (diff > 10) {
            readjustCanvasSize();
          }
      }
    }

    // check for staff name changes
    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      if (!m_staffs[i]->isStaffNameUpToDate()) {
          refreshSegment(0);
          break;
      }
    }

    m_inPaintEvent = false;

    EditView::paintEvent(e);

    m_inPaintEvent = false;

    // now deal with any backlog of insertable notes that appeared
    // during paint (because it's not safe to modify a segment from
    // within a sub-event-loop in a processEvents call from a paint)
    if (!m_pendingInsertableNotes.empty()) {
      std::vector<std::pair<int, int> > notes = m_pendingInsertableNotes;
      m_pendingInsertableNotes.clear();
      for (unsigned int i = 0; i < notes.size(); ++i) {
          slotInsertableNoteEventReceived(notes[i].first, notes[i].second, true);
      }
    }

    slotSetOperationNameAndStatus(i18n("  Ready."));
}

bool NotationView::applyLayout(int staffNo, timeT startTime, timeT endTime)
{
    slotSetOperationNameAndStatus(i18n("Laying out score..."));
    RosegardenProgressDialog::processEvents();

    m_hlayout->setStaffCount(m_staffs.size());

    Rosegarden::Profiler profiler("NotationView::applyLayout");
    unsigned int i;

    for (i = 0; i < m_staffs.size(); ++i) {

        if (staffNo >= 0 && (int)i != staffNo) continue;

        slotSetOperationNameAndStatus(i18n("Laying out staff %1...").arg(i + 1));
        RosegardenProgressDialog::processEvents();

        m_hlayout->resetStaff(*m_staffs[i], startTime, endTime);
        m_vlayout->resetStaff(*m_staffs[i], startTime, endTime);
        m_hlayout->scanStaff(*m_staffs[i], startTime, endTime);
        m_vlayout->scanStaff(*m_staffs[i], startTime, endTime);
    }

    slotSetOperationNameAndStatus(i18n("Reconciling staffs..."));
    RosegardenProgressDialog::processEvents();

    m_hlayout->finishLayout(startTime, endTime);
    m_vlayout->finishLayout(startTime, endTime);

    // find the last finishing staff for future use

    timeT lastFinishingStaffEndTime = 0;
    bool haveEndTime = false;
    m_lastFinishingStaff = -1;

    timeT firstStartingStaffStartTime = 0;
    bool haveStartTime = false;
    int firstStartingStaff = -1;

    for (i = 0; i < m_staffs.size(); ++i) {

      timeT thisStartTime = m_staffs[i]->getSegment().getStartTime();
      if (thisStartTime < firstStartingStaffStartTime || !haveStartTime) {
          firstStartingStaffStartTime = thisStartTime;
          haveStartTime = true;
          firstStartingStaff = i;
      }

        timeT thisEndTime = m_staffs[i]->getSegment().getEndTime();
        if (thisEndTime > lastFinishingStaffEndTime || !haveEndTime) {
            lastFinishingStaffEndTime = thisEndTime;
          haveEndTime = true;
            m_lastFinishingStaff = i;
        }
    }

    readjustCanvasSize();
    if (m_topBarButtons) {
      m_topBarButtons->update();
    }
    if (m_bottomBarButtons) {
      m_bottomBarButtons->update();
    }
    if (m_rawNoteRuler && m_rawNoteRuler->isVisible()) {
      m_rawNoteRuler->update();
    }

    return true;
}


void NotationView::setCurrentSelectedNote(const char *pixmapName,
                                          bool rest, Note::Type n, int dots)
{
    NoteInserter* inserter = 0;

    if (rest)
        inserter = dynamic_cast<NoteInserter*>(m_toolBox->getTool(RestInserter::ToolName));
    else
        inserter = dynamic_cast<NoteInserter*>(m_toolBox->getTool(NoteInserter::ToolName));

    inserter->slotSetNote(n);
    inserter->slotSetDots(dots);

    setTool(inserter);

    m_currentNotePixmap->setPixmap
        (NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap(pixmapName)));

    emit changeCurrentNote(rest, n);
}

02674 void NotationView::setCurrentSelectedNote(NoteActionData noteAction)
{
    setCurrentSelectedNote(noteAction.pixmapName,
                           noteAction.rest,
                           noteAction.noteType,
                           noteAction.dots);
}


02683 void NotationView::setCurrentSelection(EventSelection* s, bool preview,
                               bool redrawNow)
{
    //!!! rather too much here shared with matrixview -- could much of
    // this be in editview?

    if (m_currentEventSelection == s) return;
    NOTATION_DEBUG << "XXX " << endl;

    EventSelection *oldSelection = m_currentEventSelection;
    m_currentEventSelection = s;

    // positionElements is overkill here, but we hope it's not too
    // much overkill (if that's not a contradiction)

    timeT startA, endA, startB, endB;

    if (oldSelection) {
      startA = oldSelection->getStartTime();
      endA   = oldSelection->getEndTime();
      startB = s ? s->getStartTime() : startA;
      endB   = s ? s->getEndTime()   : endA;
    } else {
      // we know they can't both be null -- first thing we tested above
      startA = startB = s->getStartTime();
      endA   = endB   = s->getEndTime();
    }

    // refreshSegment takes start==end to mean refresh everything
    if (startA == endA) ++endA;
    if (startB == endB) ++endB;

    bool updateRequired = true;

    // play previews if appropriate -- also permits an optimisation
    // for the case where the selection is unchanged (quite likely
    // when sweeping) 

    if (s && preview) {

      bool foundNewEvent = false;

      for (EventSelection::eventcontainer::iterator i =
             s->getSegmentEvents().begin();
           i != s->getSegmentEvents().end(); ++i) {
          
          if (oldSelection && oldSelection->getSegment() == s->getSegment()
            && oldSelection->contains(*i)) continue;
            
          foundNewEvent = true;

          long pitch;
          if (!(*i)->get<Rosegarden::Int>(Rosegarden::BaseProperties::PITCH,
                                  pitch)) continue;

          long velocity = -1;
          (void)(*i)->get<Rosegarden::Int>(Rosegarden::BaseProperties::VELOCITY,
                                   velocity);

            if (!((*i)->has(Rosegarden::BaseProperties::TIED_BACKWARD)&&
                  (*i)->get<Rosegarden::Bool>
                           (Rosegarden::BaseProperties::TIED_BACKWARD)))
              playNote(s->getSegment(), pitch, velocity);
      }

      if (!foundNewEvent) {
          if (oldSelection &&
            oldSelection->getSegment() == s->getSegment() &&
            oldSelection->getSegmentEvents().size() ==
            s->getSegmentEvents().size()) updateRequired = false;
      }
    }

    if (updateRequired) {

      if (!s || !oldSelection ||
          (endA >= startB && endB >= startA &&
           oldSelection->getSegment() == s->getSegment())) {
          
          // the regions overlap: use their union and just do one refresh

          Segment &segment(s ? s->getSegment() :
                       oldSelection->getSegment());

          if (redrawNow) {
            // recolour the events now
            getLinedStaff(segment)->positionElements(std::min(startA, startB),
                                        std::max(endA, endB));
          } else {
            // mark refresh status and then request a repaint
            segment.getRefreshStatus
                (m_segmentsRefreshStatusIds
                 [getLinedStaff(segment)->getId()]).
                push(std::min(startA, startB), std::max(endA, endB));
          }

      } else {
          // do two refreshes, one for each -- here we know neither is null

          if (redrawNow) {
            // recolour the events now
            getLinedStaff(oldSelection->getSegment())->positionElements(startA,
                                                       endA);
            
            getLinedStaff(s->getSegment())->positionElements(startB, endB);
          } else {
            // mark refresh status and then request a repaint

            oldSelection->getSegment().getRefreshStatus
                (m_segmentsRefreshStatusIds
                 [getLinedStaff(oldSelection->getSegment())->getId()]).
                push(startA, endA);
            
            s->getSegment().getRefreshStatus
                (m_segmentsRefreshStatusIds
                 [getLinedStaff(s->getSegment())->getId()]).
                push(startB, endB);
          }
      }

      if (s) {
          // make the staff containing the selection current
          int staffId = getLinedStaff(s->getSegment())->getId();
          if (staffId != m_currentStaff) slotSetCurrentStaff(staffId);
      }
    }

    delete oldSelection;

    statusBar()->changeItem(KTmpStatusMsg::getDefaultMsg(),
                      KTmpStatusMsg::getDefaultId());

    if (s) {
      int eventsSelected = s->getSegmentEvents().size();
        m_selectionCounter->setText
          (i18n("  1 event selected ",
              "  %n events selected ", eventsSelected));
    } else {
      m_selectionCounter->setText(i18n("  No selection "));
    }
    m_selectionCounter->update();

    setMenuStates();

    if (redrawNow) updateView();
    else update();

    NOTATION_DEBUG << "XXX " << endl;
}

02833 void NotationView::setSingleSelectedEvent(int staffNo, Event *event,
                                bool preview, bool redrawNow)
{
    setSingleSelectedEvent(getStaff(staffNo)->getSegment(), event,
                     preview, redrawNow);
}

02840 void NotationView::setSingleSelectedEvent(Segment &segment, Event *event,
                                bool preview, bool redrawNow)
{
    EventSelection *selection = new EventSelection(segment);
    selection->addEvent(event);
    setCurrentSelection(selection, preview, redrawNow);
}

02848 bool NotationView::canPreviewAnotherNote()
{
    static time_t lastCutOff = 0;
    static int sinceLastCutOff = 0;

    time_t now = time(0);
    ++sinceLastCutOff;

    if ((now - lastCutOff) > 0) {
      sinceLastCutOff = 0;
      lastCutOff = now;
      NOTATION_DEBUG << "NotationView::canPreviewAnotherNote: reset" << endl;
    } else {
      if (sinceLastCutOff >= 20) {
          // don't permit more than 20 notes per second or so, to
          // avoid gungeing up the sound drivers
          NOTATION_DEBUG << "Rejecting preview (too busy)" << endl;
          return false;
      }
      NOTATION_DEBUG << "NotationView::canPreviewAnotherNote: ok" << endl;
    }

    return true;
}

02873 void NotationView::playNote(Rosegarden::Segment &s, int pitch, int velocity)
{
    Rosegarden::Composition &comp = getDocument()->getComposition();
    Rosegarden::Studio &studio = getDocument()->getStudio();
    Rosegarden::Track *track = comp.getTrackById(s.getTrack());

    Rosegarden::Instrument *ins =
        studio.getInstrumentById(track->getInstrument());

    // check for null instrument
    //
    if (ins == 0) return;

    if (!canPreviewAnotherNote()) return;

    if (velocity < 0) velocity = Rosegarden::MidiMaxValue;

    Rosegarden::MappedEvent mE(ins->getId(),
                               Rosegarden::MappedEvent::MidiNoteOneShot,
                               pitch + s.getTranspose(),
                               velocity,
                               Rosegarden::RealTime::zeroTime,
                               Rosegarden::RealTime(0, 250000000),
                               Rosegarden::RealTime::zeroTime);

    Rosegarden::StudioControl::sendMappedEvent(mE);
}

02901 void NotationView::showPreviewNote(int staffNo, double layoutX,
                           int pitch, int height,
                           const Rosegarden::Note &note,
                           int velocity)
{ 
    m_staffs[staffNo]->showPreviewNote(layoutX, height, note);
    playNote(m_staffs[staffNo]->getSegment(), pitch, velocity);
}

02910 void NotationView::clearPreviewNote()
{
    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      m_staffs[i]->clearPreviewNote();
    }
}

02917 void NotationView::setNotePixmapFactory(NotePixmapFactory* f)
{
    delete m_notePixmapFactory;
    m_notePixmapFactory = f;
    if (m_hlayout) m_hlayout->setNotePixmapFactory(m_notePixmapFactory);
    if (m_vlayout) m_vlayout->setNotePixmapFactory(m_notePixmapFactory);
}


NotationCanvasView* NotationView::getCanvasView()
{
    return dynamic_cast<NotationCanvasView *>(m_canvasView);
}

Rosegarden::Segment *
NotationView::getCurrentSegment()
{
    Rosegarden::Staff *staff = getCurrentStaff();
    return (staff ? &staff->getSegment() : 0);
}

LinedStaff *
NotationView::getCurrentLinedStaff()
{
    return getLinedStaff(m_currentStaff);
}

timeT
02945 NotationView::getInsertionTime()
{
    return m_insertionTime;
}


timeT
02952 NotationView::getInsertionTime(Rosegarden::Clef &clef,
                         Rosegarden::Key &key)
{
    // This fuss is solely to recover the clef and key: we already
    // set m_insertionTime to the right value when we first placed
    // the insert cursor.  We could get clef and key directly from
    // the segment but the staff has a more efficient lookup

    LinedStaff *staff = m_staffs[m_currentStaff];
    double layoutX = staff->getLayoutXOfInsertCursor();
    if (layoutX < 0) layoutX = 0;
    Rosegarden::Event *clefEvt = 0, *keyEvt = 0;
    (void)staff->getElementUnderLayoutX(layoutX, clefEvt, keyEvt);
    
    if (clefEvt) clef = Rosegarden::Clef(*clefEvt);
    else clef = Rosegarden::Clef();

    if (keyEvt) key = Rosegarden::Key(*keyEvt);
    else key = Rosegarden::Key();

    return m_insertionTime;
}


LinedStaff*
02977 NotationView::getStaffForCanvasCoords(int x, int y) const
{
    for (unsigned int i = 0; i < m_staffs.size(); ++i) {

      LinedStaff *s = m_staffs[i];

//    NOTATION_DEBUG << "NotationView::getStaffForCanvasCoords(" << x << "," << y << "): looking at staff " << i << endl;

        if (s->containsCanvasCoords(x, y)) {
          
          LinedStaff::LinedStaffCoords coords = 
            s->getLayoutCoordsForCanvasCoords(x, y);

//        NOTATION_DEBUG << "NotationView::getStaffForCanvasCoords(" << x << "," << y << "): layout coords are (" << coords.first << "," << coords.second << ")" << endl;

          int barNo = m_hlayout->getBarForX(coords.first);
//        NOTATION_DEBUG << "NotationView::getStaffForCanvasCoords(" << x << "," << y << "): bar number " << barNo << endl;
          // 931067: < instead of <= in conditional:
          if (barNo >= m_hlayout->getFirstVisibleBarOnStaff(*s) &&
            barNo < m_hlayout->getLastVisibleBarOnStaff(*s)) {
//          NOTATION_DEBUG << "NotationView::getStaffForCanvasCoords(" << x << "," << y << "): it's within range for staff " << i << m_hlayout->getFirstVisibleBarOnStaff(*s) << "->" << m_hlayout->getLastVisibleBarOnStaff(*s) << ", returning true" << endl;
            return m_staffs[i];
          }
//        NOTATION_DEBUG << "NotationView::getStaffForCanvasCoords(" << x << "," << y << "): out of range for this staff " << i << " (" << m_hlayout->getFirstVisibleBarOnStaff(*s) << "->" << m_hlayout->getLastVisibleBarOnStaff(*s) << ")" << endl;
      }
    }

    return 0;
}

03007 void NotationView::updateView()
{
    slotCheckRendered
      (getCanvasView()->contentsX(),
       getCanvasView()->contentsX() + getCanvasView()->visibleWidth());
    canvas()->update();
}

03015 void NotationView::print(bool previewOnly)
{
    if (m_staffs.size() == 0) {
        KMessageBox::error(0, "Nothing to print");
        return;
    }

    Rosegarden::Profiler profiler("NotationView::print");

    // We need to be in multi-page mode at this point

    int pageWidth = getPageWidth();
    int pageHeight = getPageHeight();
    int leftMargin = 0, topMargin = 0;
    getPageMargins(leftMargin, topMargin);
    int maxPageCount = 1;

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      int pageCount = m_staffs[i]->getPageCount();
      NOTATION_DEBUG << "NotationView::print(): staff " << i << " reports " << pageCount << " pages " << endl;
      if (pageCount > maxPageCount) maxPageCount = pageCount;
    }

    KPrinter printer(true, QPrinter::HighResolution);

    printer.setPageSelection(KPrinter::ApplicationSide);
    printer.setMinMax(1, maxPageCount + 1);

    if (previewOnly) printer.setPreviewOnly(true);
    else if (!printer.setup((QWidget *)parent())) return;
    
    QPaintDeviceMetrics pdm(&printer);
    QPainter printpainter(&printer);

    // Ideally we should aim to retain the aspect ratio and to move the
    // staffs so as to be centred after scaling.  But because we haven't
    // got around to the latter, let's lose the former too and just
    // expand to fit.

    // Retain aspect ratio when scaling
    double ratioX = (double)pdm.width()  / (double)(pageWidth - leftMargin*2),
         ratioY = (double)pdm.height() / (double)(pageHeight - topMargin*2);
    double ratio = std::min(ratioX, ratioY);
    printpainter.scale(ratio, ratio);

//    printpainter.scale((double)pdm.width()  / (double)(pageWidth - leftMargin*2),
//                 (double)pdm.height() / (double)(pageHeight - topMargin*2));
    printpainter.translate(-leftMargin, -topMargin);

    QValueList<int> pages = printer.pageList();

    for (QValueList<int>::Iterator pli = pages.begin();
       pli != pages.end(); ) { // incremented just below
      
      int page = *pli - 1;
      ++pli;
      if (page < 0 || page >= maxPageCount) continue;

      NOTATION_DEBUG << "Printing page " << page << endl;

      QRect pageRect(m_leftGutter + leftMargin + pageWidth * page,
                   topMargin,
                   pageWidth - leftMargin,
                   pageHeight - topMargin);
      
      for (size_t i = 0; i < m_staffs.size(); ++i) {

          LinedStaff *staff = m_staffs[i];
          
          LinedStaff::LinedStaffCoords cc0 = staff->getLayoutCoordsForCanvasCoords
            (pageRect.x(), pageRect.y());

          LinedStaff::LinedStaffCoords cc1 = staff->getLayoutCoordsForCanvasCoords
            (pageRect.x() + pageRect.width(), pageRect.y() + pageRect.height());

          timeT t0 = m_hlayout->getTimeForX(cc0.first);
          timeT t1 = m_hlayout->getTimeForX(cc1.first);

          m_staffs[i]->setPrintPainter(&printpainter);
          m_staffs[i]->checkRendered(t0, t1);
      }

      // Supplying doublebuffer==true to this method appears to
        // slow down printing considerably but without it we get
      // all sorts of horrible artifacts (possibly related to
      // mishandling of pixmap masks?) in qt-3.0.  Let's permit
      // it as a "hidden" option.

      m_config->setGroup(NotationView::ConfigGroup);

      NOTATION_DEBUG << "NotationView::print: calling QCanvas::drawArea" << endl;

      {
          Rosegarden::Profiler profiler("NotationView::print(QCanvas::drawArea)");

      if (m_config->readBoolEntry("forcedoublebufferprinting", false)) {
          getCanvasView()->canvas()->drawArea(pageRect, &printpainter, true);
      } else {
#if QT_VERSION >= 0x030100
          getCanvasView()->canvas()->drawArea(pageRect, &printpainter, false);
#else
          getCanvasView()->canvas()->drawArea(pageRect, &printpainter, true);
#endif
      }

      }

      NOTATION_DEBUG << "NotationView::print: QCanvas::drawArea done" << endl;

      for (size_t i = 0; i < m_staffs.size(); ++i) {

          LinedStaff *staff = m_staffs[i];
          
          LinedStaff::LinedStaffCoords cc0 = staff->getLayoutCoordsForCanvasCoords
            (pageRect.x(), pageRect.y());

          LinedStaff::LinedStaffCoords cc1 = staff->getLayoutCoordsForCanvasCoords
            (pageRect.x() + pageRect.width(), pageRect.y() + pageRect.height());

          timeT t0 = m_hlayout->getTimeForX(cc0.first);
          timeT t1 = m_hlayout->getTimeForX(cc1.first);

          m_staffs[i]->renderPrintable(t0, t1);
      }

        printpainter.translate(-pageWidth, 0);

      if (pli != pages.end() && *pli - 1 < maxPageCount) printer.newPage();
      
      for (size_t i = 0; i < m_staffs.size(); ++i) {
          m_staffs[i]->markChanged(); // recover any memory used for this page
          PixmapArrayGC::deleteAll();
      }
    }

    for (size_t i = 0; i < m_staffs.size(); ++i) {
      for (Segment::iterator j = m_staffs[i]->getSegment().begin();
           j != m_staffs[i]->getSegment().end(); ++j) {
          removeViewLocalProperties(*j);
      }
      delete m_staffs[i];
    }
    m_staffs.clear();
    
    printpainter.end();

    Rosegarden::Profiles::getInstance()->dump();
}

void
03165 NotationView::updateThumbnails(bool complete)
{
    if (m_pageMode != LinedStaff::MultiPageMode) return;

    int pageWidth = getPageWidth();
    int pageHeight = getPageHeight();
    int leftMargin = 0, topMargin = 0;
    getPageMargins(leftMargin, topMargin);
    int maxPageCount = 1;

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
      int pageCount = m_staffs[i]->getPageCount();
      if (pageCount > maxPageCount) maxPageCount = pageCount;
    }

    int thumbScale = 20;
    QPixmap thumbnail(canvas()->width() / thumbScale,
                  canvas()->height() / thumbScale);
    thumbnail.fill(Qt::white);
    QPainter thumbPainter(&thumbnail);

    if (complete) {

      thumbPainter.scale(1.0 / double(thumbScale), 1.0 / double(thumbScale));
      thumbPainter.setPen(Qt::black);
      thumbPainter.setBrush(Qt::white);

/*
      QCanvas *canvas = getCanvasView()->canvas();
      canvas->drawArea(QRect(0, 0, canvas->width(), canvas->height()),
                   &thumbPainter, false);
*/
      // hide small texts, as we get a crash in Xft when trying to
      // render them at this scale
      if (m_title) m_title->hide();
      if (m_subtitle) m_subtitle->hide();
      if (m_composer) m_composer->hide();
      if (m_copyright) m_copyright->hide();

      for (size_t page = 0; page < static_cast<size_t>(maxPageCount); ++page) {

          bool havePageNumber = ((m_pageNumbers.size() > page) &&
                           (m_pageNumbers[page] != 0));
          if (havePageNumber) m_pageNumbers[page]->hide();

          QRect pageRect(m_leftGutter + leftMargin * 2 + pageWidth * page,
                     topMargin * 2,
                     pageWidth - leftMargin*3,
                     pageHeight - topMargin*3);

          QCanvas *canvas = getCanvasView()->canvas();
          canvas->drawArea(pageRect, &thumbPainter, false);

          if (havePageNumber) m_pageNumbers[page]->show();
      }

      if (m_title) m_title->show();
      if (m_subtitle) m_subtitle->show();
      if (m_composer) m_composer->show();
      if (m_copyright) m_copyright->show();

    } else {

      thumbPainter.setPen(Qt::black);

      for (int page = 0; page < maxPageCount; ++page) {

          int x = m_leftGutter + pageWidth * page + leftMargin/4;
          int y = 20;
          int w = pageWidth - leftMargin/2;
          int h = pageHeight;
          
          QString str = QString("%1").arg(page + 1);
          
          thumbPainter.drawRect(x / thumbScale, y / thumbScale,
                          w / thumbScale, h / thumbScale);
          
          int tx = (x + w/2) / thumbScale, ty = (y + h/2) / thumbScale;
          tx -= thumbPainter.fontMetrics().width(str)/2;
          thumbPainter.drawText(tx, ty, str);
      }
    }

    thumbPainter.end();
    if (m_pannerDialog) m_pannerDialog->scrollbox()->setThumbnail(thumbnail);
}
    

void NotationView::refreshSegment(Segment *segment,
                          timeT startTime, timeT endTime)
{
    NOTATION_DEBUG << "*** " << endl;

    if (m_inhibitRefresh) return;
    NOTATION_DEBUG << "NotationView::refreshSegment(" << segment << "," << startTime << "," << endTime << ")" << endl;
    Rosegarden::Profiler foo("NotationView::refreshSegment");

    emit usedSelection();

    if (segment) {
        LinedStaff *staff = getLinedStaff(*segment);
        if (staff) applyLayout(staff->getId(), startTime, endTime);
    } else {
        applyLayout(-1, startTime, endTime);
    }

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {

        Segment *ssegment = &m_staffs[i]->getSegment();
        bool thisStaff = (ssegment == segment || segment == 0);
      m_staffs[i]->markChanged(startTime, endTime, !thisStaff);
    }

    PixmapArrayGC::deleteAll();

    statusBar()->changeItem(KTmpStatusMsg::getDefaultMsg(),
                      KTmpStatusMsg::getDefaultId());

    Event::dumpStats(std::cerr);
    if (m_deferredCursorMove == NoCursorMoveNeeded) {
      slotSetInsertCursorPosition(getInsertionTime(), false, false);
    } else {
      doDeferredCursorMove();
    }
    slotSetPointerPosition(getDocument()->getComposition().getPosition(), false);

    if (m_currentEventSelection &&
      m_currentEventSelection->getSegmentEvents().size() == 0) {
      delete m_currentEventSelection;
      m_currentEventSelection = 0;
      //!!!??? was that the right thing to do?
    }

    setMenuStates();
    slotSetOperationNameAndStatus(i18n("  Ready."));
    NOTATION_DEBUG << "*** " << endl;
}


03304 void NotationView::setMenuStates()
{
    // 1. set selection-related states

    // Clear states first, then enter only those ones that apply
    // (so as to avoid ever clearing one after entering another, in
    // case the two overlap at all)
    stateChanged("have_selection", KXMLGUIClient::StateReverse);
    stateChanged("have_notes_in_selection", KXMLGUIClient::StateReverse);
    stateChanged("have_rests_in_selection", KXMLGUIClient::StateReverse);

    if (m_currentEventSelection) {

      NOTATION_DEBUG << "NotationView::setMenuStates: Have selection; it's " << m_currentEventSelection << " covering range from " << m_currentEventSelection->getStartTime() << " to " << m_currentEventSelection->getEndTime() << " (" << m_currentEventSelection->getSegmentEvents().size() << " events)" << endl;

      stateChanged("have_selection", KXMLGUIClient::StateNoReverse);
      if (m_currentEventSelection->contains
          (Rosegarden::Note::EventType)) {
          stateChanged("have_notes_in_selection",
                   KXMLGUIClient::StateNoReverse);
      }
      if (m_currentEventSelection->contains
          (Rosegarden::Note::EventRestType)) {
          stateChanged("have_rests_in_selection",
                   KXMLGUIClient::StateNoReverse);
      }
    }

    // 2. set inserter-related states

    // #1372863 -- RestInserter is a subclass of NoteInserter, so we
    // need to test dynamic_cast<RestInserter *> before
    // dynamic_cast<NoteInserter *> (which will succeed for both)

    if (dynamic_cast<RestInserter *>(m_tool)) {
      NOTATION_DEBUG << "Have rest inserter " << endl;
      stateChanged("note_insert_tool_current", StateReverse);
      stateChanged("rest_insert_tool_current", StateNoReverse);
    } else if (dynamic_cast<NoteInserter *>(m_tool)) {
      NOTATION_DEBUG << "Have note inserter " << endl;
      stateChanged("note_insert_tool_current", StateNoReverse);
      stateChanged("rest_insert_tool_current", StateReverse);
    } else {
      NOTATION_DEBUG << "Have neither inserter " << endl;
      stateChanged("note_insert_tool_current", StateReverse);
      stateChanged("rest_insert_tool_current", StateReverse);
    }
}


#define UPDATE_PROGRESS(n) \
      progressCount += (n); \
      if (progressTotal > 0) { \
          emit setProgress(progressCount * 100 / progressTotal); \
          RosegardenProgressDialog::processEvents(); \
      }

    
03362 void NotationView::readjustCanvasSize()
{
    Rosegarden::Profiler profiler("NotationView::readjustCanvasSize");

    double maxWidth = 0.0;
    int maxHeight = 0;

    slotSetOperationNameAndStatus(i18n("Sizing and allocating canvas..."));
    RosegardenProgressDialog::processEvents();

    int progressTotal = m_staffs.size() + 2;
    int progressCount = 0;

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {

        LinedStaff &staff = *m_staffs[i];

        staff.sizeStaff(*m_hlayout);
      UPDATE_PROGRESS(1);

        if (staff.getTotalWidth() + staff.getX() > maxWidth) {
            maxWidth = staff.getTotalWidth() + staff.getX() + 1;
        }

        if (staff.getTotalHeight() + staff.getY() > maxHeight) {
            maxHeight = staff.getTotalHeight() + staff.getY() + 1;
        }
    }

    int topMargin = 0, leftMargin = 0;
    getPageMargins(leftMargin, topMargin);

    int pageWidth = getPageWidth();
    int pageHeight = getPageHeight();

    NOTATION_DEBUG << "NotationView::readjustCanvasSize: maxHeight is "
               << maxHeight << ", page height is " << pageHeight << endl
                   << " - maxWidth is " << maxWidth << ", page width is " << pageWidth << endl;


    if (m_pageMode == LinedStaff::LinearMode) {
      maxWidth = ((maxWidth / pageWidth) + 1) * pageWidth;
      if (maxHeight < pageHeight) maxHeight = pageHeight;
    } else {
      if (maxWidth  < pageWidth) maxWidth  = pageWidth;
      if (maxHeight < pageHeight + topMargin*2)
          maxHeight = pageHeight + topMargin*2;
    }

    // now get the EditView to do the biz
    readjustViewSize(QSize(int(maxWidth), maxHeight), true);

    UPDATE_PROGRESS(2);

    if (m_pannerDialog) {
    
      if (m_pageMode != LinedStaff::MultiPageMode) {
          m_pannerDialog->hide();

      } else {

          m_pannerDialog->show();

          m_pannerDialog->setPageSize
            (QSize(canvas()->width(),
                   canvas()->height()));

          m_pannerDialog->scrollbox()->setViewSize
            (QSize(getCanvasView()->width(),
                   getCanvasView()->height()));
      }
    }
}


// Slots: These are here because they use the note action data map
// or mark action data map


03441 void NotationView::slotNoteAction()
{
    const QObject* sigSender = sender();

    NoteActionDataMap::Iterator noteAct =
      m_noteActionDataMap->find(sigSender->name());
    
    if (noteAct != m_noteActionDataMap->end()) {
      m_lastNoteAction = sigSender->name();
        setCurrentSelectedNote(*noteAct);
      setMenuStates();
    } else {
        std::cerr << "NotationView::slotNoteAction() : couldn't find NoteActionData named '"
                             << sigSender->name() << "'\n";
    }
}
    
// Reactivate the last note that was activated
03459 void NotationView::slotLastNoteAction()
{
    KAction *action = actionCollection()->action(m_lastNoteAction);
    if (!action) action = actionCollection()->action("crotchet");

    if (action) {
      action->activate();
    } else {
        std::cerr << "NotationView::slotNoteAction() : couldn't find action named '"
                             << m_lastNoteAction << "' or 'crotchet'\n";
    }
}

void NotationView::slotAddMark()
{
    const QObject *s = sender();
    if (!m_currentEventSelection) return;

    MarkActionDataMap::Iterator i = m_markActionDataMap->find(s->name());

    if (i != m_markActionDataMap->end()) {
      addCommandToHistory(new NotesMenuAddMarkCommand
                      ((*i).mark, *m_currentEventSelection));
    }
}

void NotationView::slotNoteChangeAction()
{
    const QObject* sigSender = sender();

    NoteChangeActionDataMap::Iterator noteAct =
      m_noteChangeActionDataMap->find(sigSender->name());
    
    if (noteAct != m_noteChangeActionDataMap->end()) {
      slotSetNoteDurations((*noteAct).noteType, (*noteAct).notationOnly);
    } else {
        std::cerr << "NotationView::slotNoteChangeAction() : couldn't find NoteChangeAction named '"
                             << sigSender->name() << "'\n";
    }
}

03500 void NotationView::initActionDataMaps()
{
    static bool called = false;
    static int keys[] =
    { Key_0, Key_3, Key_6, Key_8, Key_4, Key_2, Key_1, Key_5 };
    
    if (called) return;
    called = true;

    m_noteActionDataMap = new NoteActionDataMap;

    for (int rest = 0; rest < 2; ++rest) {
      for (int dots = 0; dots < 2; ++dots) {
          for (int type = Note::Longest; type >= Note::Shortest; --type) {
            if (dots && (type == Note::Longest)) continue;

            QString refName
                (NotationStrings::getReferenceName(Note(type, dots), rest == 1));

            QString shortName(refName);
            shortName.replace(QRegExp("-"), "_");

            QString titleName
                (NotationStrings::getNoteName(Note(type, dots)));

            titleName = titleName.left(1).upper() +
                        titleName.right(titleName.length()-1);

            if (rest) {
                titleName.replace(QRegExp(i18n("note")), i18n("rest"));
            }

            int keycode = keys[type - Note::Shortest];
            if (dots) // keycode += CTRL; -- used below for note change action
                keycode = 0;
            if (rest) // keycode += SHIFT; -- can't do shift+numbers
                keycode = 0;

            m_noteActionDataMap->insert
                (shortName, NoteActionData
                 (titleName, shortName, refName, keycode,
                  rest > 0, type, dots));
          }
      }
    }

    m_noteChangeActionDataMap = new NoteChangeActionDataMap;

    for (int notationOnly = 0; notationOnly <= 1; ++notationOnly) {
      for (int type = Note::Longest; type >= Note::Shortest; --type) {

          QString refName
            (NotationStrings::getReferenceName(Note(type, 0), false));
      
          QString shortName(QString("change_%1%2")
                        .arg(notationOnly ? "notation_" : "").arg(refName));
          shortName.replace(QRegExp("-"), "_");

          QString titleName
            (NotationStrings::getNoteName(Note(type, 0)));

          titleName = titleName.left(1).upper() +
            titleName.right(titleName.length()-1);

          int keycode = keys[type - Note::Shortest];
          keycode += CTRL;
          if (notationOnly) keycode += ALT;
      
          m_noteChangeActionDataMap->insert
            (shortName, NoteChangeActionData
             (titleName, shortName, refName, keycode,
              notationOnly ? true : false, type));
      }
    }

    m_markActionDataMap = new MarkActionDataMap;

    std::vector<Mark> marks = Rosegarden::Marks::getStandardMarks();
    for (unsigned int i = 0; i < marks.size(); ++i) {

      Mark mark = marks[i];
      QString markName(strtoqstr(mark));
      QString actionName = QString("add_%1").arg(markName);

      m_markActionDataMap->insert
          (actionName, MarkActionData
           (NotesMenuAddMarkCommand::getGlobalName(mark),
            actionName, 0, mark));
    }
           
}

void NotationView::setupProgress(KProgress* bar)
{
    if (bar) {
        NOTATION_DEBUG << "NotationView::setupProgress(bar)\n";

        connect(m_hlayout, SIGNAL(setProgress(int)),
                bar,       SLOT(setValue(int)));

        connect(m_hlayout, SIGNAL(incrementProgress(int)),
                bar,       SLOT(advance(int)));

        connect(this,      SIGNAL(setProgress(int)),
                bar,       SLOT(setValue(int)));

        connect(this,      SIGNAL(incrementProgress(int)),
                bar,       SLOT(advance(int)));

        for (unsigned int i = 0; i < m_staffs.size(); ++i) {
            connect(m_staffs[i], SIGNAL(setProgress(int)),
                    bar,         SLOT(setValue(int)));

            connect(m_staffs[i], SIGNAL(incrementProgress(int)),
                    bar,         SLOT(advance(int)));
        }
    }

}

void NotationView::setupProgress(RosegardenProgressDialog* dialog)
{
    NOTATION_DEBUG << "NotationView::setupProgress(dialog)" << endl;
    disconnectProgress();
    
    if (dialog) {
        setupProgress(dialog->progressBar());

      connect(dialog, SIGNAL(cancelClicked()),
            m_hlayout, SLOT(slotCancel()));

        for (unsigned int i = 0; i < m_staffs.size(); ++i) {
            connect(m_staffs[i], SIGNAL(setOperationName(QString)),
                    this,        SLOT(slotSetOperationNameAndStatus(QString)));

            connect(dialog, SIGNAL(cancelClicked()),
                    m_staffs[i], SLOT(slotCancel()));
        }
    
        connect(this, SIGNAL(setOperationName(QString)),
                dialog, SLOT(slotSetOperationName(QString)));
        m_progressDisplayer = PROGRESS_DIALOG;
    }
    
}

void NotationView::slotSetOperationNameAndStatus(QString name)
{
    emit setOperationName(name);
    statusBar()->changeItem(QString("  %1").arg(name),
                      KTmpStatusMsg::getDefaultId());
}

void NotationView::disconnectProgress()
{
    NOTATION_DEBUG << "NotationView::disconnectProgress()" << endl;

    m_hlayout->disconnect();
    disconnect(SIGNAL(setProgress(int)));
    disconnect(SIGNAL(incrementProgress(int)));
    disconnect(SIGNAL(setOperationName(QString)));

    for (unsigned int i = 0; i < m_staffs.size(); ++i) {
        m_staffs[i]->disconnect();
    }
}

void NotationView::setupDefaultProgress()
{
    if (m_progressDisplayer != PROGRESS_BAR) {
        NOTATION_DEBUG << "NotationView::setupDefaultProgress()" << endl;
        disconnectProgress();
        setupProgress(m_progressBar);
        m_progressDisplayer = PROGRESS_BAR;
    }
}

void NotationView::updateViewCaption()
{
    if (m_segments.size() == 1) {

      Rosegarden::TrackId trackId = m_segments[0]->getTrack();
      Rosegarden::Track *track =
          m_segments[0]->getComposition()->getTrackById(trackId);

      int trackPosition = -1;
      if (track) trackPosition = track->getPosition();
//    std::cout << std::endl << std::endl << std::endl << "DEBUG TITLE BAR: " << getDocument()->getTitle() << std::endl << std::endl << std::endl;
        setCaption(i18n("%1 - Segment Track #%2 - Notation")
                   .arg(getDocument()->getTitle())
                   .arg(trackPosition + 1));

    } else if (m_segments.size() == getDocument()->getComposition().getNbSegments()) {

        setCaption(i18n("%1 - All Segments - Notation")
                   .arg(getDocument()->getTitle()));

    } else {

        setCaption(i18n("%1 - Segment - Notation", "%1 - %n Segments - Notation", m_segments.size())
                   .arg(getDocument()->getTitle()));

    }
}


NotationView::NoteActionDataMap* NotationView::m_noteActionDataMap = 0;
NotationView::NoteChangeActionDataMap* NotationView::m_noteChangeActionDataMap = 0;
NotationView::MarkActionDataMap* NotationView::m_markActionDataMap = 0;
const char* const NotationView::ConfigGroup = Rosegarden::NotationViewConfigGroup;


#include "notationview.moc"

Generated by  Doxygen 1.6.0   Back to index