View Issue Details

IDProjectCategoryView StatusLast Update
0002215ardourbugspublic2012-01-10 18:00
Reportercolinf Assigned Topaul  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product VersionSVN/2.0-ongoing 
Summary0002215: "Remove" in region context menu always removes topmost region when clicking on overlapping regions
DescriptionWhen you right-click on an area containing two or more overlapping regions, "Remove" in the region sub-menus will always remove the topmost region, whichever sub-menu you chose it from.

Additional InformationI've attached a patch which is my attempt to fix this, but it could certainly do with someone who understands C++ & boost looking at it to see whether it really makes sense.

Also, from looking at the code, I think that "Add/Remove region sync point" suffers from the same bug, but I've neither tested nor tried to correct this.
TagsNo tags attached.

Activities

2008-04-23 13:52

 

remove-chosen-region.patch (4,546 bytes)   
Index: gtk2_ardour/editor_ops.cc
===================================================================
--- gtk2_ardour/editor_ops.cc	(revision 3279)
+++ gtk2_ardour/editor_ops.cc	(working copy)
@@ -195,6 +195,61 @@
 }
 
 void
+Editor::remove_region ()
+{
+
+	RegionSelection rs; 
+	get_regions_for_action (rs);
+	
+	if (!session) {
+		return;
+	}
+
+	if (rs.empty()) {
+		cerr << "rs.empty()" << endl;
+		return;
+	}
+
+	begin_reversible_command (_("remove region"));
+
+	list<boost::shared_ptr<Region> > regions_to_remove;
+
+	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+		// we can't just remove the region(s) in this loop because
+		// this removes them from the RegionSelection, and they thus
+		// disappear from underneath the iterator, and the ++i above
+		// SEGVs in a puzzling fashion.
+
+		// so, first iterate over the regions to be removed from rs and
+		// add them to the regions_to_remove list, and then
+		// iterate over the list to actually remove them.
+		
+		// I have no idea if this is good or right: I really ought to
+		// read up on boost and the standard c++ libs before trying
+		// stuff like this. however, it seems consistent with the
+		// rest of this file, and seems to work. XXX colinf.
+	        
+		regions_to_remove.push_back ((*i)->region());
+	}
+	
+	for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+		boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+	        if (!playlist) {
+			// is this check necessary?
+			cerr << "(*i)->region()->playlist() is NULL!" << endl;
+	        	continue;
+	        }
+
+	        XMLNode &before = playlist->get_state();
+		playlist->remove_region (*rl);
+	        XMLNode &after = playlist->get_state();
+		session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+	}
+	commit_reversible_command ();
+}
+
+#if 0
+void
 Editor::destroy_clicked_region ()
 {
 	uint32_t selected = selection->regions.size();
@@ -236,6 +291,7 @@
 		session->destroy_regions (r);
 	} 
 }
+#endif
 
 boost::shared_ptr<Region>
 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
@@ -3099,6 +3155,7 @@
 void
 Editor::remove_region_sync ()
 {
+	// XXX shouldn't this use get_regions_for_action(rs) too?
 	if (clicked_regionview) {
 		boost::shared_ptr<Region> region (clicked_regionview->region());
 		begin_reversible_command (_("remove sync"));
@@ -4396,6 +4453,7 @@
 void
 Editor::external_edit_region ()
 {
+	// XXX shouldn't this use get_regions_for_action(rs) too?	
 	if (!clicked_regionview) {
 		return;
 	}
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 3279)
+++ gtk2_ardour/editor.h	(working copy)
@@ -995,8 +995,11 @@
 	void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position, const RegionSelection&);
 	void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
 	void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
+	void remove_region ();
 	void remove_clicked_region ();
+#if 0
 	void destroy_clicked_region ();
+#endif
 	void edit_region ();
 	void rename_region ();
 	void duplicate_some_regions (RegionSelection&, float times);
Index: gtk2_ardour/editor_selection.cc
===================================================================
--- gtk2_ardour/editor_selection.cc	(revision 3279)
+++ gtk2_ardour/editor_selection.cc	(working copy)
@@ -721,9 +721,11 @@
 	*/
 
 	if (selection->regions.size() > 1) {
-		return true;
+		// return true;
 	}
 	
+	cerr << "selection->regions.size()  = " << selection->regions.size() << endl;
+	
 	begin_reversible_command (_("set selected regions"));
 	
 	selection->set (rv);
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 3279)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -1933,7 +1933,7 @@
 	items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
 	items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
 	items.push_back (SeparatorElem());
-	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
+	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region)));
 
 	/* OK, stick the region submenu at the top of the list, and then add
 	   the standard items.
remove-chosen-region.patch (4,546 bytes)   

2008-05-01 17:21

 

region-context-menu-3300.patch (11,130 bytes)   
Index: gtk2_ardour/editor_ops.cc
===================================================================
--- gtk2_ardour/editor_ops.cc	(revision 3300)
+++ gtk2_ardour/editor_ops.cc	(working copy)
@@ -196,6 +196,56 @@
 }
 
 void
+Editor::remove_region ()
+{
+
+	RegionSelection rs; 
+	get_regions_for_action (rs);
+	
+	if (!session) {
+		return;
+	}
+
+	if (rs.empty()) {
+		cerr << "rs.empty()" << endl;
+		return;
+	}
+
+	begin_reversible_command (_("remove region"));
+
+	list<boost::shared_ptr<Region> > regions_to_remove;
+
+	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+		// we can't just remove the region(s) in this loop because
+		// this removes them from the RegionSelection, and they thus
+		// disappear from underneath the iterator, and the ++i above
+		// SEGVs in a puzzling fashion.
+
+		// so, first iterate over the regions to be removed from rs and
+		// add them to the regions_to_remove list, and then
+		// iterate over the list to actually remove them.
+	        
+		regions_to_remove.push_back ((*i)->region());
+	}
+	
+	for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+		boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+	        if (!playlist) {
+			// is this check necessary?
+			cerr << "(*i)->region()->playlist() is NULL!" << endl;
+	        	continue;
+	        }
+
+	        XMLNode &before = playlist->get_state();
+		playlist->remove_region (*rl);
+	        XMLNode &after = playlist->get_state();
+		session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+	}
+	commit_reversible_command ();
+}
+
+#if 0
+void
 Editor::destroy_clicked_region ()
 {
 	uint32_t selected = selection->regions.size();
@@ -237,6 +287,7 @@
 		session->destroy_regions (r);
 	} 
 }
+#endif
 
 boost::shared_ptr<Region>
 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
@@ -3136,15 +3187,23 @@
 void
 Editor::remove_region_sync ()
 {
-	if (clicked_regionview) {
-		boost::shared_ptr<Region> region (clicked_regionview->region());
-		begin_reversible_command (_("remove sync"));
-                XMLNode &before = region->playlist()->get_state();
-		region->clear_sync_position ();
-                XMLNode &after = region->playlist()->get_state();
-		session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
-		commit_reversible_command ();
+	RegionSelection rs; 
+
+	get_regions_for_action (rs);
+
+	if (rs.empty()) {
+		return;
 	}
+
+	begin_reversible_command (_("remove sync"));
+	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+
+                XMLNode &before = (*i)->region()->playlist()->get_state();
+		(*i)->region()->clear_sync_position ();
+                XMLNode &after = (*i)->region()->playlist()->get_state();
+		session->add_command(new MementoCommand<Playlist>(*((*i)->region()->playlist()), &before, &after));
+	}
+	commit_reversible_command ();
 }
 
 void
@@ -4433,6 +4492,7 @@
 void
 Editor::external_edit_region ()
 {
+	// XXX shouldn't this use get_regions_for_action(rs) too?	
 	if (!clicked_regionview) {
 		return;
 	}
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 3300)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -1599,8 +1599,16 @@
 		
 		if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
 			Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
-			for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-				add_region_context_items (atv->audio_view(), (*i), edit_items);
+			if (selection->regions.size() > 1) {
+				// there's already a multiple selection: just add a 
+				// single region context menu that will act on all 
+				// selected regions
+				boost::shared_ptr<Region> dummy_region; // = NULL		
+				add_region_context_items (atv->audio_view(), dummy_region, edit_items);			
+			} else {
+				for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+					add_region_context_items (atv->audio_view(), (*i), edit_items);
+				}
 			}
 			delete regions;
 		}
@@ -1638,10 +1646,17 @@
 				add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
 			}
 
-			for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-				add_region_context_items (atv->audio_view(), (*i), edit_items);
+			if (selection->regions.size() > 1) {
+				// there's already a multiple selection: just add a 
+				// single region context menu that will act on all 
+				// selected regions
+				boost::shared_ptr<Region> dummy_region; // = NULL		
+				add_region_context_items (atv->audio_view(), dummy_region, edit_items);			
+			} else {
+				for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+					add_region_context_items (atv->audio_view(), (*i), edit_items);
+				}
 			}
-
 			delete regions;
 		}
 	}
@@ -1772,18 +1787,27 @@
 	
 	boost::shared_ptr<AudioRegion> ar;
 
+	cerr << "add_region_context_items()" << endl;
+
 	if (region) {
 		ar = boost::dynamic_pointer_cast<AudioRegion> (region);
-	}
 
-	/* when this particular menu pops up, make the relevant region 
-	   become selected.
-	*/
+		/* when this particular menu pops up, make the relevant region 
+		   become selected.
+		*/
 
-	region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
+		region_menu->signal_map_event().connect (
+			bind (
+				mem_fun(*this, &Editor::set_selected_regionview_from_map_event), 
+				sv, 
+				boost::weak_ptr<Region>(region)
+			)
+		);
 
-	items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
-	items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+		items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
+		items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+	}
+
 	items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
 	items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
 	items.push_back (SeparatorElem());
@@ -1803,49 +1827,51 @@
 
 	sigc::connection fooc;
 
-	items.push_back (CheckMenuElem (_("Lock")));
-	CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
-	if (region->locked()) {
-		region_lock_item->set_active();
-	}
-	region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
+	if (region) {
+		items.push_back (CheckMenuElem (_("Lock")));
+		CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
+		if (region->locked()) {
+			region_lock_item->set_active();
+		}
+		region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
 
-	items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
-	CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
+		items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
+		CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
 
-	switch (region->positional_lock_style()) {
-	case Region::MusicTime:
-		bbt_glue_item->set_active (true);
-		break;
-	default:
-		bbt_glue_item->set_active (false);
-		break;
-	}
+		switch (region->positional_lock_style()) {
+		case Region::MusicTime:
+			bbt_glue_item->set_active (true);
+			break;
+		default:
+			bbt_glue_item->set_active (false);
+			break;
+		}
 
-	bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
+		bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
 
-	items.push_back (CheckMenuElem (_("Mute")));
-	CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
-	fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
-	if (region->muted()) {
-		fooc.block (true);
-		region_mute_item->set_active();
-		fooc.block (false);
-	}
-	
-	if (!Profile->get_sae()) {
-		items.push_back (CheckMenuElem (_("Opaque")));
-		CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
-		fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
-		if (region->opaque()) {
+		items.push_back (CheckMenuElem (_("Mute")));
+		CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
+		fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
+		if (region->muted()) {
 			fooc.block (true);
-			region_opaque_item->set_active();
+			region_mute_item->set_active();
 			fooc.block (false);
 		}
+	
+		if (!Profile->get_sae()) {
+			items.push_back (CheckMenuElem (_("Opaque")));
+			CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
+			fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
+			if (region->opaque()) {
+				fooc.block (true);
+				region_opaque_item->set_active();
+				fooc.block (false);
+			}
+		}
 	}
 
 	items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
-	if (region->at_natural_position()) {
+	if (region && region->at_natural_position()) {
 		items.back().set_sensitive (false);
 	}
 	
@@ -1933,7 +1959,7 @@
 	items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
 	items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
 	items.push_back (SeparatorElem());
-	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
+	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region)));
 
 	/* OK, stick the region submenu at the top of the list, and then add
 	   the standard items.
@@ -1944,7 +1970,7 @@
 	*/
 
 	string::size_type pos = 0;
-	string menu_item_name = region->name();
+	string menu_item_name = (region) ? region->name() : _("Selected regions");
 
 	while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
 		menu_item_name.replace (pos, 1, "__");
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 3300)
+++ gtk2_ardour/editor.h	(working copy)
@@ -995,8 +995,11 @@
 	void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position, const RegionSelection&);
 	void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
 	void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
+	void remove_region ();
 	void remove_clicked_region ();
+#if 0
 	void destroy_clicked_region ();
+#endif
 	void edit_region ();
 	void rename_region ();
 	void duplicate_some_regions (RegionSelection&, float times);

region-context-menu-3300.patch (11,130 bytes)   

colinf

2008-05-01 17:28

updater   ~0004912

And here's a version of the patch (region-context-menu-3300.patch) which does correct the behaviour of "Remove region sync point" ("Add region sync point" was correct before).

It also tries to behave better if multiple regions are selected: in that case, it will simply create one context menu, titled "Selected regions", instead of a separate sub-menu for each region at that point, and the items in that menu will affect all the selected regions.

2008-05-01 19:55

 

region-context-menu-single-regions.patch (4,829 bytes)   
Index: gtk2_ardour/editor_ops.cc
===================================================================
--- gtk2_ardour/editor_ops.cc	(revision 3302)
+++ gtk2_ardour/editor_ops.cc	(working copy)
@@ -196,6 +196,55 @@
 }
 
 void
+Editor::remove_region ()
+{
+
+	RegionSelection rs; 
+	get_regions_for_action (rs);
+	
+	if (!session) {
+		return;
+	}
+
+	if (rs.empty()) {
+		cerr << "rs.empty()" << endl;
+		return;
+	}
+
+	begin_reversible_command (_("remove region"));
+
+	list<boost::shared_ptr<Region> > regions_to_remove;
+
+	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+		// we can't just remove the region(s) in this loop because
+		// this removes them from the RegionSelection, and they thus
+		// disappear from underneath the iterator, and the ++i above
+		// SEGVs in a puzzling fashion.
+
+		// so, first iterate over the regions to be removed from rs and
+		// add them to the regions_to_remove list, and then
+		// iterate over the list to actually remove them.
+	        
+		regions_to_remove.push_back ((*i)->region());
+	}
+	
+	for (list<boost::shared_ptr<Region> >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) {
+		boost::shared_ptr<Playlist> playlist = (*rl)->playlist();
+	        if (!playlist) {
+			// is this check necessary?
+			cerr << "(*i)->region()->playlist() is NULL!" << endl;
+	        	continue;
+	        }
+
+	        XMLNode &before = playlist->get_state();
+		playlist->remove_region (*rl);
+	        XMLNode &after = playlist->get_state();
+		session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+	}
+	commit_reversible_command ();
+}
+
+void
 Editor::destroy_clicked_region ()
 {
 	uint32_t selected = selection->regions.size();
@@ -3136,15 +3185,23 @@
 void
 Editor::remove_region_sync ()
 {
-	if (clicked_regionview) {
-		boost::shared_ptr<Region> region (clicked_regionview->region());
-		begin_reversible_command (_("remove sync"));
-                XMLNode &before = region->playlist()->get_state();
-		region->clear_sync_position ();
-                XMLNode &after = region->playlist()->get_state();
-		session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
-		commit_reversible_command ();
+	RegionSelection rs; 
+
+	get_regions_for_action (rs);
+
+	if (rs.empty()) {
+		return;
 	}
+
+	begin_reversible_command (_("remove sync"));
+	for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
+
+                XMLNode &before = (*i)->region()->playlist()->get_state();
+		(*i)->region()->clear_sync_position ();
+                XMLNode &after = (*i)->region()->playlist()->get_state();
+		session->add_command(new MementoCommand<Playlist>(*((*i)->region()->playlist()), &before, &after));
+	}
+	commit_reversible_command ();
 }
 
 void
@@ -4433,6 +4490,7 @@
 void
 Editor::external_edit_region ()
 {
+	// XXX shouldn't this use get_regions_for_action(rs) too?	
 	if (!clicked_regionview) {
 		return;
 	}
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 3302)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -1933,7 +1933,7 @@
 	items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
 	items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
 	items.push_back (SeparatorElem());
-	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
+	items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region)));
 
 	/* OK, stick the region submenu at the top of the list, and then add
 	   the standard items.
Index: gtk2_ardour/editor_selection.cc
===================================================================
--- gtk2_ardour/editor_selection.cc	(revision 3302)
+++ gtk2_ardour/editor_selection.cc	(working copy)
@@ -716,14 +716,6 @@
 		return true;
 	}
 
-	/* don't reset the selection if its something other than 
-	   a single other region.
-	*/
-
-	if (selection->regions.size() > 1) {
-		return true;
-	}
-	
 	begin_reversible_command (_("set selected regions"));
 	
 	selection->set (rv);
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 3302)
+++ gtk2_ardour/editor.h	(working copy)
@@ -995,6 +995,7 @@
 	void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position, const RegionSelection&);
 	void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
 	void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
+	void remove_region ();
 	void remove_clicked_region ();
 	void destroy_clicked_region ();
 	void edit_region ();

colinf

2008-05-01 19:56

updater   ~0004914

Here (region-context-menu-single-regions.patch) is a less intrusive version, that won't let the region context menus work on multiple region selections, but always forces the selection to a single region when the context menu pops up, regardless of what was selected before.

paul

2008-06-18 22:38

administrator   ~0005054

second patch applied and committed. works very nicely. great stuff.

colinf

2012-01-10 18:00

updater   ~0012537

Closing my old issues: this is long since fixed.

Issue History

Date Modified Username Field Change
2008-04-23 13:52 colinf New Issue
2008-04-23 13:52 colinf File Added: remove-chosen-region.patch
2008-05-01 17:21 colinf File Added: region-context-menu-3300.patch
2008-05-01 17:28 colinf Note Added: 0004912
2008-05-01 19:55 colinf File Added: region-context-menu-single-regions.patch
2008-05-01 19:56 colinf Note Added: 0004914
2008-06-18 22:38 paul cost => 0.00
2008-06-18 22:38 paul Status new => resolved
2008-06-18 22:38 paul Resolution open => fixed
2008-06-18 22:38 paul Assigned To => paul
2008-06-18 22:38 paul Note Added: 0005054
2012-01-10 18:00 colinf Note Added: 0012537
2012-01-10 18:00 colinf Status resolved => closed