diff --git a/admin/render-icon.py b/admin/render-icon.py index 4b0d464ca..2f5c64592 100755 --- a/admin/render-icon.py +++ b/admin/render-icon.py @@ -20,10 +20,9 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import sys -import os -import os.path as Path import getopt from xml.dom import minidom +import os import shutil #svgDir = "svg" @@ -33,20 +32,16 @@ rsvgPath = "./rsvg-convert" artworkLayerPrefix = "artwork:" def createDirectory( name ): - if Path.isfile(name): - print "WARNING: moving %s to %s.bak because it's in the way." % (name,name) - bak_name = name + ".bak" - if Path.isfile(bak_name): - os.remove(bak_name) - os.rename(name,bak_name) - if not Path.isdir(name): + if os.path.isfile(name): + os.remove(name) + if not os.path.exists(name): os.mkdir(name) def copyMergeDirectory( src, dst ): listing = os.listdir(src) for file_name in listing: - src_file_path = Path.join(src, file_name) - dst_file_path = Path.join(dst, file_name) + src_file_path = os.path.join(src, file_name) + dst_file_path = os.path.join(dst, file_name) shutil.copyfile(src_file_path, dst_file_path) def getDocumentSize( svg_element ): @@ -165,19 +160,19 @@ def main(argv): print "Missing arguments in_path and out_dir." sys.exit(1) - if Path.isfile(out_dir): + if os.path.isfile(out_dir): print "Unable to use '%s' as output directory, because it\'s a file." % out_dir sys.exit(1) - if not Path.isdir(out_dir): + if not os.path.isdir(out_dir): print "Output directory '%s' not found." % out_dir sys.exit(1) # Create the icons folders - createDirectory(Path.join(out_dir, "48x48")) - createDirectory(Path.join(out_dir, "32x32")) - createDirectory(Path.join(out_dir, "24x24")) - createDirectory(Path.join(out_dir, "22x22")) - createDirectory(Path.join(out_dir, "16x16")) + createDirectory(os.path.join(out_dir, "48x48")) + createDirectory(os.path.join(out_dir, "32x32")) + createDirectory(os.path.join(out_dir, "24x24")) + createDirectory(os.path.join(out_dir, "22x22")) + createDirectory(os.path.join(out_dir, "16x16")) renderSvgIcon(in_path, out_dir) diff --git a/configure.ac b/configure.ac index 09f68cc21..eb78e6d9a 100644 --- a/configure.ac +++ b/configure.ac @@ -135,8 +135,13 @@ PKG_CHECK_MODULES(LUMIERA_COMMON_LIBS, [sigc++-2.0 >= 2.0.18]) # END Internatinalization ############## Gtk Dependancies + +# gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 for Debian Etch compatibility +# gtk+-2.0 >= 2.12 gtkmm-2.4 >= 2.12 for Debian Lenny compatibility + PKG_CHECK_MODULES(LUMIERA_GUI, [ - gtkmm-2.4 >= 2.8 gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 + gtk+-2.0 >= 2.8 gtkmm-2.4 >= 2.8 + gdl-1.0 >= 0.6.1 cairomm-1.0 >= 0.6.0 gavl >= 0.2.5 librsvg-2.0 >= 2.18.1]) # END Gtk Dependancies diff --git a/icons/svg/tool-arrow.svg b/icons/svg/tool-arrow.svg index 3f0b72102..84807f4fb 100644 --- a/icons/svg/tool-arrow.svg +++ b/icons/svg/tool-arrow.svg @@ -54,44 +54,6 @@ offset="1" id="stop8777" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-x="1280" + inkscape:window-y="24"> + + + + + + + + + + + + + - - - - - - - - - diff --git a/icons/svg/tool-i-beam.svg b/icons/svg/tool-i-beam.svg index da244f5bb..337a75027 100644 --- a/icons/svg/tool-i-beam.svg +++ b/icons/svg/tool-i-beam.svg @@ -19,29 +19,6 @@ inkscape:output_extension="org.inkscape.output.svg.inkscape"> - - - - - - - - @@ -54,44 +31,6 @@ offset="1" id="stop8777" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-x="1280" + inkscape:window-y="24"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + inkscape:window-y="24"> + + @@ -644,13 +130,12 @@ sodipodi:nodetypes="czcsc" id="path13699" d="M 139.5,84.9691 C 137.3345,87.776 134.73,88.4358 132.1148,88.4358 C 129.4995,88.4358 126.2207,87.9797 125.7142,84.9691 C 126.2637,82.2163 127.6839,80.5318 131.3314,80.5005 C 135.3174,80.4664 137.2533,83.0122 139.5,84.9691 z" - style="opacity:0.9;fill:url(#radialGradient15234);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164642;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + style="display:inline;opacity:0.90000000000000002;fill:url(#radialGradient15234);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164641999999999;stroke-opacity:1;visibility:visible;overflow:visible;enable-background:accumulate" /> diff --git a/icons/svg/track-enabled.svg b/icons/svg/track-enabled.svg index ab6af9f53..277b3d17c 100644 --- a/icons/svg/track-enabled.svg +++ b/icons/svg/track-enabled.svg @@ -31,15 +31,6 @@ offset="1" id="stop14234" /> - - @@ -78,747 +58,6 @@ offset="1" id="stop13606" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + inkscape:window-y="24"> + + + + + + + + diff --git a/icons/svg/track-locked.svg b/icons/svg/track-locked.svg index 3ff1d34a4..990c034b7 100644 --- a/icons/svg/track-locked.svg +++ b/icons/svg/track-locked.svg @@ -30,26 +30,6 @@ offset="1.0000000" id="stop9849" /> - - - @@ -91,16 +61,6 @@ offset="1" id="stop12075" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + gradientTransform="matrix(0.2913951,0,0,0.3423373,103.01101,72.677438)" + x1="10.907269" + y1="25.002281" + x2="30.875446" + y2="36.127281" /> + + + + + + + + inkscape:window-y="24"> - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/icons/svg/track-unlocked.svg b/icons/svg/track-unlocked.svg index beea19846..40866bf5f 100644 --- a/icons/svg/track-unlocked.svg +++ b/icons/svg/track-unlocked.svg @@ -19,6 +19,56 @@ inkscape:output_extension="org.inkscape.output.svg.inkscape"> + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + inkscape:window-y="24"> - - - - - - + style="display:inline"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index ded85c65c..8215c27f7 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -19,7 +19,7 @@ liblumierabackend_la_srcdir = $(top_srcdir)/src/backend lib_LTLIBRARIES += liblumierabackend.la liblumierabackend_la_CPPFLAGS = $(AM_CPPFLAGS) -liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall liblumierabackend_la_LIBADD = liblumiera.la liblumierabackend_la_SOURCES = \ diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 12d2c3108..16592de8e 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -72,7 +72,7 @@ gtkgui_la_SOURCES = \ # -# libgui is a convinience library used by lumigui and the gtkgui module +# libgui is a convenience library used by lumigui and the gtkgui module # noinst_LTLIBRARIES += libgui.la @@ -83,77 +83,76 @@ libgui_la_CPPFLAGS = $(AM_CPPFLAGS) \ $(LUMIERA_GUI_CFLAGS) -libgui_la_SOURCES = \ - $(lumigui_srcdir)/guinotificationfacade.cpp \ - $(lumigui_srcdir)/window-manager.cpp \ - $(lumigui_srcdir)/window-manager.hpp \ - $(lumigui_srcdir)/workspace/actions.cpp \ - $(lumigui_srcdir)/workspace/actions.hpp \ +libgui_la_SOURCES = \ + $(lumigui_srcdir)/guinotificationfacade.cpp \ + $(lumigui_srcdir)/window-manager.cpp \ + $(lumigui_srcdir)/window-manager.hpp \ + $(lumigui_srcdir)/workspace/actions.cpp \ + $(lumigui_srcdir)/workspace/actions.hpp \ $(lumigui_srcdir)/workspace/workspace-window.cpp \ $(lumigui_srcdir)/workspace/workspace-window.hpp \ - $(lumigui_srcdir)/dialogs/dialog.hpp \ - $(lumigui_srcdir)/dialogs/render.cpp \ - $(lumigui_srcdir)/dialogs/render.hpp \ + $(lumigui_srcdir)/dialogs/dialog.hpp \ + $(lumigui_srcdir)/dialogs/render.cpp \ + $(lumigui_srcdir)/dialogs/render.hpp \ $(lumigui_srcdir)/dialogs/preferences-dialog.cpp \ $(lumigui_srcdir)/dialogs/preferences-dialog.hpp \ - $(lumigui_srcdir)/dialogs/sequence-name.cpp \ - $(lumigui_srcdir)/dialogs/sequence-name.hpp \ - $(lumigui_srcdir)/panels/panel.cpp \ - $(lumigui_srcdir)/panels/panel.hpp \ - $(lumigui_srcdir)/panels/timeline-panel.cpp \ - $(lumigui_srcdir)/panels/timeline-panel.hpp \ - $(lumigui_srcdir)/panels/viewer-panel.cpp \ - $(lumigui_srcdir)/panels/viewer-panel.hpp \ - $(lumigui_srcdir)/panels/assets-panel.cpp \ - $(lumigui_srcdir)/panels/assets-panel.hpp \ - $(lumigui_srcdir)/widgets/video-display-widget.cpp \ - $(lumigui_srcdir)/widgets/video-display-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline-widget.cpp \ - $(lumigui_srcdir)/widgets/timeline-widget.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-view-window.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-view-window.hpp \ + $(lumigui_srcdir)/dialogs/sequence-name.cpp \ + $(lumigui_srcdir)/dialogs/sequence-name.hpp \ + $(lumigui_srcdir)/panels/panel.cpp \ + $(lumigui_srcdir)/panels/panel.hpp \ + $(lumigui_srcdir)/panels/timeline-panel.cpp \ + $(lumigui_srcdir)/panels/timeline-panel.hpp \ + $(lumigui_srcdir)/panels/viewer-panel.cpp \ + $(lumigui_srcdir)/panels/viewer-panel.hpp \ + $(lumigui_srcdir)/panels/assets-panel.cpp \ + $(lumigui_srcdir)/panels/assets-panel.hpp \ + $(lumigui_srcdir)/widgets/video-display-widget.cpp \ + $(lumigui_srcdir)/widgets/video-display-widget.hpp \ + $(lumigui_srcdir)/widgets/timeline-widget.cpp \ + $(lumigui_srcdir)/widgets/timeline-widget.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-view-window.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-view-window.hpp \ $(lumigui_srcdir)/widgets/timeline/timeline-header-container.cpp \ $(lumigui_srcdir)/widgets/timeline/timeline-header-container.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-group-track.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \ - $(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \ - $(lumigui_srcdir)/model/project.cpp \ - $(lumigui_srcdir)/model/project.hpp \ - $(lumigui_srcdir)/model/track-base.cpp \ - $(lumigui_srcdir)/model/track-base.hpp \ - $(lumigui_srcdir)/model/sequence.cpp \ - $(lumigui_srcdir)/model/sequence.hpp \ - $(lumigui_srcdir)/model/track.cpp \ - $(lumigui_srcdir)/model/track.hpp \ - $(lumigui_srcdir)/model/clip-track.cpp \ - $(lumigui_srcdir)/model/clip-track.hpp \ - $(lumigui_srcdir)/model/group-track.cpp \ - $(lumigui_srcdir)/model/group-track.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-body.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-body.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ruler.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ruler.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-tool.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-arrow-tool.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-ibeam-tool.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-track.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-track.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-clip-track.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-group-track.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \ + $(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \ + $(lumigui_srcdir)/model/project.cpp \ + $(lumigui_srcdir)/model/project.hpp \ + $(lumigui_srcdir)/model/track.cpp \ + $(lumigui_srcdir)/model/track.hpp \ + $(lumigui_srcdir)/model/clip-track.cpp \ + $(lumigui_srcdir)/model/clip-track.hpp \ + $(lumigui_srcdir)/model/parent-track.cpp \ + $(lumigui_srcdir)/model/parent-track.hpp \ + $(lumigui_srcdir)/model/group-track.cpp \ + $(lumigui_srcdir)/model/group-track.hpp \ $(lumigui_srcdir)/model/clip.cpp \ $(lumigui_srcdir)/model/clip.hpp \ - $(lumigui_srcdir)/output/displayer.cpp \ - $(lumigui_srcdir)/output/displayer.hpp \ - $(lumigui_srcdir)/output/gdkdisplayer.cpp \ - $(lumigui_srcdir)/output/gdkdisplayer.hpp \ + $(lumigui_srcdir)/model/sequence.cpp \ + $(lumigui_srcdir)/model/sequence.hpp \ + $(lumigui_srcdir)/output/displayer.cpp \ + $(lumigui_srcdir)/output/displayer.hpp \ + $(lumigui_srcdir)/output/gdkdisplayer.cpp \ + $(lumigui_srcdir)/output/gdkdisplayer.hpp \ $(lumigui_srcdir)/output/xvdisplayer.cpp \ $(lumigui_srcdir)/output/xvdisplayer.hpp - libgui_la_LIBADD = \ liblumieracommon.la \ liblumierabackend.la \ diff --git a/src/gui/gtk-lumiera.hpp b/src/gui/gtk-lumiera.hpp index c1800580a..4f3021b76 100644 --- a/src/gui/gtk-lumiera.hpp +++ b/src/gui/gtk-lumiera.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "lib/util.hpp" extern "C" { diff --git a/src/gui/model/group-track.cpp b/src/gui/model/group-track.cpp index a71d8db6c..c7572b4d9 100644 --- a/src/gui/model/group-track.cpp +++ b/src/gui/model/group-track.cpp @@ -28,12 +28,6 @@ namespace model { GroupTrack::GroupTrack() { } - -const std::list< boost::shared_ptr >& -GroupTrack::get_child_tracks() const -{ - return children; -} } // namespace model } // namespace gui diff --git a/src/gui/model/group-track.hpp b/src/gui/model/group-track.hpp index eb047cf37..de5ac8f4b 100644 --- a/src/gui/model/group-track.hpp +++ b/src/gui/model/group-track.hpp @@ -26,22 +26,16 @@ #ifndef GROUP_TRACK_HPP #define GROUP_TRACK_HPP -#include "track.hpp" +#include "parent-track.hpp" namespace gui { namespace model { -class GroupTrack : public Track +class GroupTrack : public ParentTrack { public: GroupTrack(); - - const std::list< boost::shared_ptr >& - get_child_tracks() const; - -private: - //----- Data -----// - std::list< boost::shared_ptr > children; + }; } // namespace model diff --git a/src/gui/model/track-base.cpp b/src/gui/model/parent-track.cpp similarity index 71% rename from src/gui/model/track-base.cpp rename to src/gui/model/parent-track.cpp index d6fd2357f..fa835e49a 100644 --- a/src/gui/model/track-base.cpp +++ b/src/gui/model/parent-track.cpp @@ -1,5 +1,5 @@ /* - track-base.cpp - Implementation of the TrackBase class + parent-track-.cpp - Implementation of the ParentTrack class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -20,31 +20,35 @@ * *****************************************************/ -#include "track.hpp" +#include "parent-track.hpp" namespace gui { namespace model { -const std::list< boost::shared_ptr > TrackBase::NoChildren; - -TrackBase::TrackBase() +ParentTrack::ParentTrack() { } -const std::list< boost::shared_ptr >& -TrackBase::get_child_tracks() const +std::list< boost::shared_ptr > +ParentTrack::get_child_tracks() const { - return NoChildren; + return tracks.to_list(); +} + +lumiera::observable_list< boost::shared_ptr >& +ParentTrack::get_child_track_list() +{ + return tracks; } const Glib::ustring -TrackBase::get_name() const +ParentTrack::get_name() const { return name; } void -TrackBase::set_name(const Glib::ustring &name) +ParentTrack::set_name(const Glib::ustring &name) { this->name = name; } diff --git a/src/gui/model/track-base.hpp b/src/gui/model/parent-track.hpp similarity index 68% rename from src/gui/model/track-base.hpp rename to src/gui/model/parent-track.hpp index 5ae555e01..f375dccb0 100644 --- a/src/gui/model/track-base.hpp +++ b/src/gui/model/parent-track.hpp @@ -1,5 +1,5 @@ /* - track-track.hpp - Definition of the TrackBase class + parent-track.hpp - Definition of the ParentTrack class Copyright (C) Lumiera.org 2008, Joel Holdsworth @@ -19,43 +19,48 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/** @file track-base.hpp - ** This file contains the definition of TrackBase, a class which +/** @file parent-track.hpp + ** This file contains the definition of ParentTrack, a class which ** represents a base functionality for tracks and sequences which ** are also track parents. This class wraps proc layer data */ -#include "../gtk-lumiera.hpp" +#include "track.hpp" +#include "lib/observable-list.hpp" -#ifndef TRACK_BASE_HPP -#define TRACK_BASE_HPP +#ifndef PARENT_TRACK_HPP +#define PARENT_TRACK_HPP namespace gui { namespace model { -class Track; - -class TrackBase +class ParentTrack : public Track { +protected: + ParentTrack(); + public: - TrackBase(); - virtual void add_child_track(Track* child) {}; - - virtual const std::list< boost::shared_ptr >& + + std::list< boost::shared_ptr > get_child_tracks() const; + + lumiera::observable_list< boost::shared_ptr >& + get_child_track_list(); const Glib::ustring get_name() const; void set_name(const Glib::ustring &name); private: + //----- Data -----// Glib::ustring name; - static const std::list< boost::shared_ptr > NoChildren; +protected: + lumiera::observable_list< boost::shared_ptr > tracks; }; } // namespace model } // namespace gui -#endif // TRACK_BASE_HPP +#endif // PARENT_TRACK_HPP diff --git a/src/gui/model/sequence.cpp b/src/gui/model/sequence.cpp index e480b02db..87d9d1dc7 100644 --- a/src/gui/model/sequence.cpp +++ b/src/gui/model/sequence.cpp @@ -49,11 +49,5 @@ Sequence::Sequence() // END TEST CODE } -const std::list< boost::shared_ptr >& -Sequence::get_child_tracks() const -{ - return tracks; -} - } // namespace model } // namespace gui diff --git a/src/gui/model/sequence.hpp b/src/gui/model/sequence.hpp index 2df7a3f11..02a2869c2 100644 --- a/src/gui/model/sequence.hpp +++ b/src/gui/model/sequence.hpp @@ -27,7 +27,7 @@ #ifndef SEQUENCE_HPP #define SEQUENCE_HPP -#include "track-base.hpp" +#include "parent-track.hpp" // TEST CODE #include "group-track.hpp" @@ -38,17 +38,14 @@ namespace model { class Track; -class Sequence : public TrackBase +class Sequence : public ParentTrack { public: Sequence(); - const std::list< boost::shared_ptr >& - get_child_tracks() const; private: - //----- Data -----// - std::list< boost::shared_ptr > tracks; + }; } // namespace model diff --git a/src/gui/model/track.cpp b/src/gui/model/track.cpp index 8541e17f9..03c8f88e5 100644 --- a/src/gui/model/track.cpp +++ b/src/gui/model/track.cpp @@ -24,11 +24,19 @@ namespace gui { namespace model { + +const std::list< boost::shared_ptr > Track::NoChildren; Track::Track() { } +std::list< boost::shared_ptr > +Track::get_child_tracks() const +{ + return Track::NoChildren; +} + } // namespace model } // namespace gui diff --git a/src/gui/model/track.hpp b/src/gui/model/track.hpp index 4fe852b30..60357f56e 100644 --- a/src/gui/model/track.hpp +++ b/src/gui/model/track.hpp @@ -24,7 +24,7 @@ ** represents a track, and wraps proc layer data */ -#include "track-base.hpp" +#include "../gtk-lumiera.hpp" #ifndef TRACK_HPP #define TRACK_HPP @@ -32,12 +32,17 @@ namespace gui { namespace model { -class Track : public TrackBase +class Track { -public: +protected: Track(); +public: + virtual std::list< boost::shared_ptr > + get_child_tracks() const; +protected: + static const std::list< boost::shared_ptr > NoChildren; }; } // namespace model diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index ec62d9e5f..7798fba76 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -85,6 +85,10 @@ TimelineWidget::TimelineWidget( attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND); set_tool(timeline::Arrow); + + // Receive notifications of changes to the tracks + sequence->get_child_track_list().signal_changed().connect( + sigc::mem_fun( this, &TimelineWidget::on_track_list_changed ) ); } TimelineWidget::~TimelineWidget() @@ -268,6 +272,16 @@ TimelineWidget::on_view_window_changed() viewWindow.get_time_offset()); } +void +TimelineWidget::on_add_track_command() +{ + REQUIRE(sequence); + + // # TEST CODE + sequence->get_child_track_list().push_back( + shared_ptr(new model::ClipTrack())); +} + /* ===== Internals ===== */ void @@ -275,13 +289,20 @@ TimelineWidget::update_tracks() { REQUIRE(sequence); + // Remove any tracks which are no longer present in the model + remove_orphaned_tracks(); + // Create timeline tracks from all the model tracks create_timeline_tracks(); // Update the header container ASSERT(headerContainer != NULL); + headerContainer->show_all_children(); headerContainer->update_headers(); + // Update the body + body->queue_draw(); + // Recalculate the total height of the timeline scrolled area totalHeight = 0; BOOST_FOREACH(shared_ptr track, @@ -296,6 +317,8 @@ void TimelineWidget::create_timeline_tracks() { REQUIRE(sequence); + REQUIRE(headerContainer != NULL); + REQUIRE(body != NULL); BOOST_FOREACH(shared_ptr child, sequence->get_child_tracks()) @@ -309,12 +332,11 @@ TimelineWidget::create_timeline_tracks_from_branch( REQUIRE(model_track); // Is a timeline UI track present in the map already? - const model::Track *track = model_track.get(); - if(!contains(trackMap, track)) + if(!contains(trackMap, model_track)) { // The timeline UI track is not present // We will need to create one - trackMap[model_track.get()] = + trackMap[model_track] = create_timeline_track_from_model_track(model_track); } @@ -333,21 +355,66 @@ TimelineWidget::create_timeline_track_from_model_track( // Choose a corresponding timeline track class from the model track's // class if(typeid(*model_track) == typeid(model::ClipTrack)) - return shared_ptr(new timeline::ClipTrack()); + return shared_ptr(new timeline::ClipTrack(*this)); else if(typeid(*model_track) == typeid(model::GroupTrack)) - return shared_ptr(new timeline::GroupTrack()); + return shared_ptr(new timeline::GroupTrack(*this)); ASSERT(NULL); // Unknown track type; return shared_ptr(); } +void +TimelineWidget::remove_orphaned_tracks() +{ + REQUIRE(sequence); + REQUIRE(headerContainer != NULL); + REQUIRE(body != NULL); + + std::map, + boost::shared_ptr > + orphan_track_map(trackMap); + + // Remove all tracks which are still present in the sequence + BOOST_FOREACH(shared_ptr child, + sequence->get_child_tracks()) + search_orphaned_tracks_in_branch(child, orphan_track_map); + + // orphan_track_map now contains all the orphaned tracks + // Remove them + std::pair, shared_ptr > + pair; + BOOST_FOREACH( pair, orphan_track_map ) + { + ENSURE(pair.first) + trackMap.erase(pair.first); + } +} + +void +TimelineWidget::search_orphaned_tracks_in_branch( + boost::shared_ptr model_track, + std::map, + boost::shared_ptr > &orphan_track_map) +{ + REQUIRE(model_track); + + // Is the timeline UI still present? + if(contains(orphan_track_map, model_track)) + orphan_track_map.erase(model_track); + + // Recurse to child tracks + BOOST_FOREACH(shared_ptr child, + model_track->get_child_tracks()) + search_orphaned_tracks_in_branch(child, orphan_track_map); +} + shared_ptr TimelineWidget::lookup_timeline_track( - shared_ptr model_track) + shared_ptr model_track) const { REQUIRE(sequence); - std::map >:: - const_iterator iterator = trackMap.find(model_track.get()); + std::map, shared_ptr >:: + const_iterator iterator = trackMap.find(model_track); if(iterator == trackMap.end()) { // The track is not present in the map @@ -360,7 +427,32 @@ TimelineWidget::lookup_timeline_track( ENSURE(iterator->second != NULL); return iterator->second; } + +boost::shared_ptr +TimelineWidget::lookup_model_track( + const timeline::Track *timeline_track) const +{ + REQUIRE(sequence); + std::pair, shared_ptr > + pair; + BOOST_FOREACH( pair, trackMap ) + { + if(pair.second.get() == timeline_track) + { + ENSURE(pair.first); + return pair.first; + } + } + + // The track is not present in the map + // We are in an error condition if the timeline track is not found + // - the timeline tracks must always be synchronous with the model + // tracks. + ENSURE(0); + return shared_ptr(); +} + void TimelineWidget::update_scroll() { @@ -442,6 +534,12 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) return true; } +void +TimelineWidget::on_track_list_changed() +{ + update_tracks(); +} + void TimelineWidget::on_playback_period_drag_released() { diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index f4b1d38d6..41ad86b75 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -154,6 +154,8 @@ protected: void on_view_window_changed(); + void on_add_track_command(); + /* ===== Utilities ===== */ protected: @@ -189,10 +191,21 @@ private: * @return The timeline track created, or an empty shared_ptr if * model_track has an unreckognised type (this is an error condition). **/ - static boost::shared_ptr + boost::shared_ptr create_timeline_track_from_model_track( boost::shared_ptr model_track); + /** + * Removes any UI tracks which no longer have corresponding model + * tracks present in the sequence. + **/ + void remove_orphaned_tracks(); + + void search_orphaned_tracks_in_branch( + boost::shared_ptr model_track, + std::map, + boost::shared_ptr > &orphan_track_map); + /** * Looks up a timeline UI track in trackMap that corresponds to a * given model_track. @@ -202,7 +215,18 @@ private: * error condition). **/ boost::shared_ptr lookup_timeline_track( - boost::shared_ptr model_track); + boost::shared_ptr model_track) const; + + /** + * Looks up a model track in trackMap that corresponds to a + * given timeline track. + * @param timeline_track The timeline UI track to look up. + * @returns The model track found, or an empty shared_ptr if + * timeline_track has no corresponding timeline UI track (this is an + * error condition). + **/ + boost::shared_ptr lookup_model_track( + const timeline::Track *timeline_track) const; // ----- Layout Functions ----- // @@ -214,6 +238,12 @@ private: int get_y_scroll_offset() const; // ----- Event Handlers -----// + + /** + * An event handler that receives notifications for when the + * sequence's track tree has been changed. + **/ + void on_track_list_changed(); void on_playback_period_drag_released(); @@ -243,7 +273,8 @@ protected: * widget is updated with update_tracks, timeline tracks are added and * removed from the map in correspondance with the tree. **/ - std::map > + std::map, + boost::shared_ptr > trackMap; // View State @@ -296,6 +327,7 @@ protected: friend class timeline::Tool; friend class timeline::ArrowTool; friend class timeline::IBeamTool; + friend class timeline::Track; }; } // namespace widgets diff --git a/src/gui/widgets/timeline/timeline-clip-track.cpp b/src/gui/widgets/timeline/timeline-clip-track.cpp index 8e9e0bd2d..c5d384bb0 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.cpp +++ b/src/gui/widgets/timeline/timeline-clip-track.cpp @@ -29,7 +29,8 @@ namespace gui { namespace widgets { namespace timeline { -ClipTrack::ClipTrack() +ClipTrack::ClipTrack(TimelineWidget &timeline_widget) : + Track(timeline_widget) { } diff --git a/src/gui/widgets/timeline/timeline-clip-track.hpp b/src/gui/widgets/timeline/timeline-clip-track.hpp index 0100763a3..5b5b33e75 100644 --- a/src/gui/widgets/timeline/timeline-clip-track.hpp +++ b/src/gui/widgets/timeline/timeline-clip-track.hpp @@ -41,7 +41,7 @@ class TimelineViewWindow; class ClipTrack : public timeline::Track { public: - ClipTrack(); + ClipTrack(TimelineWidget &timeline_widget); void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const; diff --git a/src/gui/widgets/timeline/timeline-group-track.cpp b/src/gui/widgets/timeline/timeline-group-track.cpp index 49c1077f1..570095bb1 100644 --- a/src/gui/widgets/timeline/timeline-group-track.cpp +++ b/src/gui/widgets/timeline/timeline-group-track.cpp @@ -28,7 +28,8 @@ namespace gui { namespace widgets { namespace timeline { -GroupTrack::GroupTrack() +GroupTrack::GroupTrack(TimelineWidget &timeline_widget) : + Track(timeline_widget) { } diff --git a/src/gui/widgets/timeline/timeline-group-track.hpp b/src/gui/widgets/timeline/timeline-group-track.hpp index 5e2368a54..46e0fdef7 100644 --- a/src/gui/widgets/timeline/timeline-group-track.hpp +++ b/src/gui/widgets/timeline/timeline-group-track.hpp @@ -36,7 +36,7 @@ namespace timeline { class GroupTrack : public timeline::Track { public: - GroupTrack(); + GroupTrack(TimelineWidget &timeline_widget); void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* constwindow) diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp index c9330d109..506eb0316 100644 --- a/src/gui/widgets/timeline/timeline-header-container.cpp +++ b/src/gui/widgets/timeline/timeline-header-container.cpp @@ -36,8 +36,8 @@ namespace gui { namespace widgets { namespace timeline { -TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget - *timeline_widget) : +TimelineHeaderContainer::TimelineHeaderContainer( + gui::widgets::TimelineWidget *timeline_widget) : Glib::ObjectBase("TimelineHeaderContainer"), timelineWidget(timeline_widget), margin(-1), @@ -61,6 +61,12 @@ TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget sigc::mem_fun(this, &TimelineHeaderContainer::on_hovering_track_changed) ); + // Create the context menu + Menu::MenuList& menu_list = contextMenu.items(); + menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), + sigc::mem_fun(timelineWidget, + &TimelineWidget::on_add_track_command) ) ); + // Install style properties register_styles(); } @@ -129,15 +135,43 @@ TimelineHeaderContainer::on_unrealize() bool TimelineHeaderContainer::on_button_press_event ( GdkEventButton* event) { - // Did the user press the button on an expander? - if(hoveringExpander != NULL) + REQUIRE(event != NULL); + + switch(event->button) { - // Yes? The prime for a release event - clickedExpander = hoveringExpander; - queue_draw(); + case 1: // Left Click + // Did the user press the button on an expander? + if(hoveringExpander != NULL) + { + // Yes? The prime for a release event + clickedExpander = hoveringExpander; + queue_draw(); + } + break; + + case 3: // Right Click + { + // Popup the context menu + shared_ptr header = header_from_point( + Gdk::Point(event->x, event->y)); + + // Are we hovering on a header? + if(header) + { + // Yes - show the header's context menu + header->show_header_context_menu( + event->button, event->time); + } + else + { + // No - show the default context menu + contextMenu.popup(event->button, event->time); + } + break; + } } - return Container::on_button_press_event(event); + return true; } bool TimelineHeaderContainer::on_button_release_event ( @@ -219,6 +253,12 @@ TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */, } } +void +TimelineHeaderContainer::on_remove(Widget* widget) +{ + // Do nothing - this is just to keep Gtk::Container happy +} + bool TimelineHeaderContainer::on_expose_event(GdkEventExpose *event) { @@ -351,11 +391,18 @@ void TimelineHeaderContainer::set_parent_recursive( boost::shared_ptr model_track) { - lookup_timeline_track(model_track)-> - get_header_widget().set_parent(*this); + // Set the header's parent widget + Widget &widget = lookup_timeline_track(model_track)-> + get_header_widget(); + + const Container *parent = widget.get_parent(); + if(parent == NULL) // Is the header unparented? + widget.set_parent(*this); + else if(parent != this) // The header is parented by another container + widget.reparent(*this); // Recurse through all the children - BOOST_FOREACH( boost::shared_ptr child, + BOOST_FOREACH( shared_ptr child, model_track->get_child_tracks() ) set_parent_recursive(child); } @@ -407,7 +454,8 @@ TimelineHeaderContainer::draw_header_decoration( lookup_timeline_track(model_track); // Get the cached header box - ASSERT(contains(headerBoxes, timeline_track)); + weak_ptr ptr(timeline_track); + ASSERT(contains(headerBoxes, ptr)); const Gdk::Rectangle &box = headerBoxes[timeline_track]; // Paint the box, if it will be visible @@ -449,6 +497,25 @@ TimelineHeaderContainer::draw_header_decoration( draw_header_decoration(child, clip_rect); } +boost::shared_ptr +TimelineHeaderContainer::header_from_point(const Gdk::Point &point) +{ + std::pair, Gdk::Rectangle> pair; + BOOST_FOREACH( pair, headerBoxes ) + { + // Hit test the rectangle + const Gdk::Rectangle &rect = pair.second; + + if(point.get_x() >= rect.get_x() && + point.get_x() < rect.get_x() + rect.get_width() && + point.get_y() >= rect.get_y() && + point.get_y() < rect.get_y() + rect.get_height()) + return pair.first; + } + + return shared_ptr(); +} + shared_ptr TimelineHeaderContainer::expander_button_from_point( const Gdk::Point &point) @@ -475,7 +542,8 @@ TimelineHeaderContainer::get_expander_button_rectangle( shared_ptr track) { REQUIRE(track != NULL); - ASSERT(contains(headerBoxes, track)); + weak_ptr ptr(track); + ASSERT(contains(headerBoxes, ptr)); const Gdk::Rectangle &box = headerBoxes[track]; return Gdk::Rectangle( @@ -497,7 +565,7 @@ TimelineHeaderContainer::lookup_timeline_track( return timeline_track; } -const std::list< boost::shared_ptr >& +const std::list< boost::shared_ptr > TimelineHeaderContainer::get_tracks() const { REQUIRE(timelineWidget != NULL); diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp index 082f1e871..517ed3bce 100644 --- a/src/gui/widgets/timeline/timeline-header-container.hpp +++ b/src/gui/widgets/timeline/timeline-header-container.hpp @@ -29,7 +29,6 @@ #define HEADER_CONTAINER_HPP #include "../../gtk-lumiera.hpp" -#include namespace gui { @@ -119,6 +118,12 @@ private: **/ void forall_vfunc(gboolean include_internals, GtkCallback callback, gpointer callback_data); + + /** + * An event handler that is called when a widget is removed from the + * container. + **/ + void on_remove(Widget* widget); /* ===== Events ===== */ private: @@ -166,12 +171,19 @@ private: model_track); /** - * Recursively causes all the visible track header widgets to call - * size_request( ). + * Recursively causes all the visible track header widgets in a branch + * to call size_request( ). **/ void size_request_recursive( boost::shared_ptr model_track); + /** + * Recursively calls a callback on all the header widgets in a branch. + * @param model_track The root track of the branch. + * @param callback The callback to apply to the branch. This includes + * model_track and all it's children. + * @param callback_data The user data parameter for the callback. + **/ void forall_vfunc_recursive( boost::shared_ptr model_track, GtkCallback callback, gpointer callback_data); @@ -187,10 +199,26 @@ private: void draw_header_decoration( boost::shared_ptr model_track, const Gdk::Rectangle &clip_rect); + + boost::shared_ptr header_from_point( + const Gdk::Point &point); + /** + * Given a point, expander_button_from_point finds the track of the + * expand button that this point is hovering over, if there is one. + * @param point The window coordiates point to hit-test. + * @return Returns a pointer to the track whose expander button is + * being hovered over, or NULL if no button has been found. + **/ boost::shared_ptr expander_button_from_point( const Gdk::Point &point); + /** + * Gets the rectangular hit-target area of a track header's expander + * button. + * @param track The track to get the expander button rectangle of. + * @return Returns the rectangle of the expander button of track. + **/ const Gdk::Rectangle get_expander_button_rectangle( boost::shared_ptr track); @@ -215,7 +243,7 @@ private: * @return Returns the track found, or returns NULL if no matching * track was found. **/ - const std::list< boost::shared_ptr >& + const std::list< boost::shared_ptr > get_tracks() const; /** @@ -243,7 +271,21 @@ private: */ Glib::RefPtr gdkWindow; - std::map, Gdk::Rectangle> + /** + * The Menu object which will be displayed as the context menu when + * the user right clicks on the header container. + * @remarks The context menu will be displayed when the user's right + * click is not processed by track headers. + **/ + Gtk::Menu contextMenu; + + /** + * A map of tracks to the rectangles of their headers. + * @remarks This map is used as a cache, so that the rectangles don't + * need to be perpetually recalculated. This cache is regenerated by + * the layout_headers method. + **/ + std::map, Gdk::Rectangle> headerBoxes; //----- User Interaction State -----// @@ -259,7 +301,13 @@ private: **/ int margin; + /** + * The style value which indicates the size to draw the expand button + * in pixels. + **/ int expand_button_size; + + friend class timeline::Track; }; } // namespace timeline diff --git a/src/gui/widgets/timeline/timeline-track.cpp b/src/gui/widgets/timeline/timeline-track.cpp index 8dc698969..05f49b523 100644 --- a/src/gui/widgets/timeline/timeline-track.cpp +++ b/src/gui/widgets/timeline/timeline-track.cpp @@ -20,16 +20,22 @@ * *****************************************************/ +#warning This header must soon be removed when we drop Etch compatibility +#include + #include "timeline-track.hpp" +#include "../timeline-widget.hpp" #include "../../window-manager.hpp" +using namespace boost; using namespace Gtk; namespace gui { namespace widgets { namespace timeline { -Track::Track() : +Track::Track(TimelineWidget &timeline_widget) : + timelineWidget(timeline_widget), expanded(true), enableButton(Gtk::StockID("track_enabled")), lockButton(Gtk::StockID("track_unlocked")) @@ -38,11 +44,27 @@ Track::Track() : buttonBar.append(lockButton); buttonBar.set_toolbar_style(TOOLBAR_ICONS); -//buttonBar.set_icon_size(WindowManager::MenuIconSize); -//TODO uncommented for now, doesn't compile on etch. 12/15/08 ichthyo + +#if 0 + buttonBar.set_icon_size(WindowManager::MenuIconSize); +#else +#warning This code soon be removed when we drop Etch compatibility + + // Temporary bodge for etch compatibility - will be removed soon + gtk_toolbar_set_icon_size (buttonBar.gobj(), + (GtkIconSize)(int)WindowManager::MenuIconSize); +#endif headerWidget.pack_start(titleBox, PACK_SHRINK); headerWidget.pack_start(buttonBar, PACK_SHRINK); + + // Setup the context menu + Menu::MenuList& menu_list = contextMenu.items(); + menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"), + sigc::mem_fun(timelineWidget, + &TimelineWidget::on_add_track_command) ) ); + menu_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"), + sigc::mem_fun(this, &Track::on_remove_track) ) ); } Gtk::Widget& @@ -57,16 +79,35 @@ Track::get_height() const return 100; } -bool Track::get_expanded() const +bool +Track::get_expanded() const { return expanded; } -void Track::set_expanded(bool expanded) +void +Track::set_expanded(bool expanded) { this->expanded = expanded; } +void +Track::show_header_context_menu(guint button, guint32 time) +{ + contextMenu.popup(button, time); +} + +void +Track::on_remove_track() +{ + shared_ptr model_track = + timelineWidget.lookup_model_track(this); + ASSERT(model_track); + ASSERT(timelineWidget.sequence); + + timelineWidget.sequence->get_child_track_list().remove(model_track); +} + } // namespace timeline } // namespace widgets } // namespace gui diff --git a/src/gui/widgets/timeline/timeline-track.hpp b/src/gui/widgets/timeline/timeline-track.hpp index 2c5aff97c..d5ad70538 100644 --- a/src/gui/widgets/timeline/timeline-track.hpp +++ b/src/gui/widgets/timeline/timeline-track.hpp @@ -25,6 +25,7 @@ #include "../../gtk-lumiera.hpp" #include "../../model/track.hpp" +#include "timeline-header-container.hpp" #ifndef TIMELINE_TRACK_HPP #define TIMELINE_TRACK_HPP @@ -38,7 +39,7 @@ class TimelineViewWindow; class Track { public: - Track(); + Track(TimelineWidget &timeline_widget); Gtk::Widget& get_header_widget(); @@ -47,12 +48,19 @@ public: bool get_expanded() const; void set_expanded(bool expanded); + + void show_header_context_menu(guint button, guint32 time); virtual void draw_track(Cairo::RefPtr cairo, TimelineViewWindow* const window) const = 0; private: + void on_remove_track(); + +private: + + TimelineWidget &timelineWidget; bool expanded; @@ -65,6 +73,8 @@ private: Gtk::Entry titleBox; Gtk::Toolbar buttonBar; + + Gtk::Menu contextMenu; }; diff --git a/src/gui/workspace/actions.cpp b/src/gui/workspace/actions.cpp index 3aaa73d6e..fcf81dab4 100644 --- a/src/gui/workspace/actions.cpp +++ b/src/gui/workspace/actions.cpp @@ -92,6 +92,11 @@ Actions::Actions(WorkspaceWindow &workspace_window) : actionGroup->add(Action::create("SequenceMenu", _("_Sequence"))); actionGroup->add(Action::create("SequenceAdd", _("_Add...")), sigc::mem_fun(*this, &Actions::on_menu_sequence_add)); + + // Track Menu + actionGroup->add(Action::create("TrackMenu", _("_Track"))); + actionGroup->add(Action::create("TrackAdd", _("_Add...")), + sigc::mem_fun(*this, &Actions::on_menu_track_add)); // Help Menu actionGroup->add(Action::create("HelpMenu", _("_Help")) ); @@ -186,6 +191,14 @@ Actions::on_menu_sequence_add() workspaceWindow.get_project()->add_new_sequence(dialog.get_name()); } +/* ===== Track Menu Event Handlers ===== */ + +void +Actions::on_menu_track_add() +{ + g_message("Hello"); +} + /* ===== View Menu Event Handlers ===== */ void diff --git a/src/gui/workspace/actions.hpp b/src/gui/workspace/actions.hpp index b3662591e..76034ac6e 100644 --- a/src/gui/workspace/actions.hpp +++ b/src/gui/workspace/actions.hpp @@ -71,6 +71,8 @@ private: void on_menu_view_viewer(); void on_menu_sequence_add(); + + void on_menu_track_add(); void on_menu_help_about(); diff --git a/src/gui/workspace/workspace-window.cpp b/src/gui/workspace/workspace-window.cpp index 96f33e4e8..5b9e49bd9 100644 --- a/src/gui/workspace/workspace-window.cpp +++ b/src/gui/workspace/workspace-window.cpp @@ -116,6 +116,9 @@ WorkspaceWindow::create_ui() " " " " " " + " " + " " + " " " " " " " " diff --git a/src/lib/observable-list.hpp b/src/lib/observable-list.hpp index ed7fec8d6..c672d2a1b 100644 --- a/src/lib/observable-list.hpp +++ b/src/lib/observable-list.hpp @@ -263,6 +263,19 @@ public: changed.emit(); } +public: + /* ===== Conversions ===== */ + + /** + * Returns a copy of this observable_list converted to an STL list + * object. + * @return Returns a copy of the STL list. + **/ + std::list to_list() const + { + return list; + } + public: /* ===== Signals ===== */