summaryrefslogtreecommitdiffstats
path: root/src/base/Clipboard.h
blob: e205e330caa66dd00ccba9c2be3977fc41c96bd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// -*- c-basic-offset: 4 -*-

/*
    Rosegarden
    A sequencer and musical notation editor.

    This program is Copyright 2000-2008
        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.
*/

#ifndef _CLIPBOARD_H_
#define _CLIPBOARD_H_

#include <set>
#include "Segment.h"
#include "Selection.h"

namespace Rosegarden
{
class EventSelection;

/**
 * Simple container for segments, that can serve as a clipboard for
 * editing operations.  Conceptually it has two "modes",
 * single-segment and multiple-segment, although there's no particular
 * distinction behind the scenes.  The Clipboard owns all the segments
 * it contains -- they should always be deep copies, not aliases.
 */

class Clipboard
{
public:
    typedef std::multiset<Segment *, Segment::SegmentCmp> segmentcontainer;
    typedef segmentcontainer::iterator iterator;
    typedef segmentcontainer::const_iterator const_iterator;

    Clipboard();
    Clipboard(const Clipboard &);
    Clipboard &operator=(const Clipboard &);
    virtual ~Clipboard();

    /**
     * Empty the clipboard.
     */
    void clear();
 
    /**
     * Return true if the clipboard is empty.
     */
    bool isEmpty() const;

    iterator       begin()       { return m_segments.begin(); }
    const_iterator begin() const { return m_segments.begin(); }
    iterator       end()         { return m_segments.end(); }
    const_iterator end() const   { return m_segments.end(); }
    
    /**
     * Return true if the clipboard only contains a single segment.
     * Single-segment and multi-segment are conceptually rather
     * separate -- for example, you can only paste into a segment
     * from a single-segment clipboard.
     */
    bool isSingleSegment() const;

    /**
     * Return true if the clipboard contains at least one segment
     * that originated as only part of another segment.  If a
     * paste is made from a clipboard with isPartial true, the
     * paste command will generally want to be sure to normalize
     * rests etc on the pasted region afterwards.
     */
    bool isPartial() const;

    /**
     * Return the single segment contained by the clipboard.
     * If the clipboard is empty or contains more than one segment,
     * returns null.  (Use the iterator accessors begin()/end() to
     * read from a clipboard for which isSingleSegment is false.)
     */
    Segment *getSingleSegment() const;

    /**
     * Add a new empty segment to the clipboard, and return a
     * pointer to it.  (The clipboard retains ownership.)
     */
    Segment *newSegment();

    /**
     * Add a new segment to the clipboard, containing copies of
     * the events in copyFrom.  (The clipboard retains ownership
     * of the new segment.)
     */
    Segment *newSegment(const Segment *copyFrom);

    /**
     * Add one or more new segments to the clipboard, containing
     * copies of the events in copyFrom found between from and to.  If
     * expandRepeats is true, include any events found in the
     * repeating trail of the segment within this time.  (The
     * clipboard retains ownership of the new segment(s).)
     *
     * This may insert more than one new segment, if it is required to
     * insert a repeating section of an audio segment.  For this
     * reason it does not return the inserted segment (even though in
     * most situations it will only insert one).
     */
    void newSegment(const Segment *copyFrom, timeT from, timeT to,
                    bool expandRepeats);

    /**
     * Add a new segment to the clipboard, containing copied of
     * the events in the given selection.
     */
    Segment *newSegment(const EventSelection *copyFrom);

    /**
     * Add a time signature selection to this clipboard, replacing any
     * that already exists.
     */
    void setTimeSignatureSelection(const TimeSignatureSelection &);

    bool hasTimeSignatureSelection() const { return m_haveTimeSigSelection; }

    /**
     * Remove any time signature selection from the clipboard.
     */
    void clearTimeSignatureSelection();

    /**
     * Retrieve any time signature selection found in the clipboard.
     */
    const TimeSignatureSelection &getTimeSignatureSelection() const;

    /**
     * Add a tempo selection to this clipboard, replacing any
     * that already exists.
     */
    void setTempoSelection(const TempoSelection &);

    bool hasTempoSelection() const { return m_haveTempoSelection; }

    /**
     * Remove any tempo selection from the clipboard.
     */
    void clearTempoSelection();

    /**
     * Retrieve any tempo selection found in the clipboard.
     */
    const TempoSelection &getTempoSelection() const;

    /**
     * Clear the current clipboard and re-fill it by copying from c.
     */
    void copyFrom(const Clipboard *c);

    /**
     * Get the earliest start time for anything in this clipboard,
     * or the start of the nominal range if there is one.
     */
    timeT getBaseTime() const;

    /**
     * Set nominal start and end times for the range in the clipboard,
     * if it is intended to cover a particular time range regardless
     * of whether the data in it covers the full range or not.
     */
    void setNominalRange(timeT start, timeT end);

    void clearNominalRange() { setNominalRange(0, 0); }

    bool hasNominalRange() const { return m_nominalStart != m_nominalEnd; }
    
    void getNominalRange(timeT &start, timeT &end);

private:
    segmentcontainer m_segments;
    bool m_partial;

    TimeSignatureSelection m_timeSigSelection;
    bool m_haveTimeSigSelection;

    TempoSelection m_tempoSelection;
    bool m_haveTempoSelection;

    timeT m_nominalStart;
    timeT m_nominalEnd;
};

}

#endif