From f60ddccd6d328a5cebc4d524246e33b399a8dfdd Mon Sep 17 00:00:00 2001
From: Florian Jung <flo@windfisch.org>
Date: Thu, 6 Oct 2011 11:37:57 +0000
Subject: you can now hide and show drumlist instruments squashed some minor
 bugs

---
 muse2/muse/icons.cpp              |  11 ++
 muse2/muse/icons.h                |   3 +
 muse2/muse/midiedit/dcanvas.cpp   |  32 +++++-
 muse2/muse/midiedit/dcanvas.h     |  15 ++-
 muse2/muse/midiedit/dlist.cpp     | 231 +++++++++++++++++++++++++++-----------
 muse2/muse/midiedit/dlist.h       |   5 +-
 muse2/muse/midiedit/drumedit.cpp  |  66 +++++++----
 muse2/muse/midiedit/drumedit.h    |  24 +++-
 muse2/muse/midiedit/scoreedit.cpp |   7 +-
 muse2/muse/song.cpp               |   8 +-
 muse2/muse/song.h                 |   4 +-
 muse2/xpm/eye.xpm                 |  22 ++++
 muse2/xpm/eye_crossed.xpm         |  23 ++++
 muse2/xpm/eye_gray.xpm            |  22 ++++
 14 files changed, 368 insertions(+), 105 deletions(-)
 create mode 100644 muse2/xpm/eye.xpm
 create mode 100644 muse2/xpm/eye_crossed.xpm
 create mode 100644 muse2/xpm/eye_gray.xpm

(limited to 'muse2')

diff --git a/muse2/muse/icons.cpp b/muse2/muse/icons.cpp
index 89a3a48e..34493d13 100644
--- a/muse2/muse/icons.cpp
+++ b/muse2/muse/icons.cpp
@@ -1,4 +1,5 @@
 //=========================================================
+//=========================================================
 //  MusE
 //  Linux Music Editor
 //  $Id: icons.cpp,v 1.13.2.8 2009/11/14 03:37:48 terminator356 Exp $
@@ -120,6 +121,10 @@
 #include "xpm/rec_echo_on.xpm"
 #include "xpm/rec_echo_off.xpm"
 
+#include "xpm/eye.xpm"
+#include "xpm/eye_gray.xpm"
+#include "xpm/eye_crossed.xpm"
+
 #include "xpm/up.xpm"
 #include "xpm/down.xpm"
 #include "xpm/bold.xpm"
@@ -331,6 +336,9 @@ QPixmap* homeIcon;
 QPixmap* backIcon;
 QPixmap* forwardIcon;
 QPixmap* muteIcon;
+QPixmap* eyeIcon;
+QPixmap* eyeCrossedIcon;
+QPixmap* eyeGrayIcon;
 QPixmap* upIcon;
 QPixmap* downIcon;
 QPixmap* boldIcon;
@@ -534,6 +542,9 @@ void initIcons()
       backIcon     = new MPIXMAP(back_xpm, "go-previous");
       forwardIcon  = new MPIXMAP(forward_xpm, "go-next");
       muteIcon     = new MPIXMAP(editmuteS_xpm, "audio-volume-muted");
+      eyeIcon      = new MPIXMAP(eye_xpm, NULL);
+      eyeCrossedIcon  = new MPIXMAP(eye_crossed_xpm, NULL);
+      eyeGrayIcon  = new MPIXMAP(eye_gray_xpm, NULL);
       upIcon       = new MPIXMAP(up_xpm, "go-up");
       downIcon     = new MPIXMAP(down_xpm, "go-down");
       boldIcon     = new MPIXMAP(bold_xpm, "format-text-bold");
diff --git a/muse2/muse/icons.h b/muse2/muse/icons.h
index 957f4a74..30852f81 100644
--- a/muse2/muse/icons.h
+++ b/muse2/muse/icons.h
@@ -85,6 +85,9 @@ extern QPixmap* homeIcon;
 extern QPixmap* backIcon;
 extern QPixmap* forwardIcon;
 extern QPixmap* muteIcon;
+extern QPixmap* eyeIcon;
+extern QPixmap* eyeCrossedIcon;
+extern QPixmap* eyeGrayIcon;
 extern QPixmap* upIcon;
 extern QPixmap* downIcon;
 extern QPixmap* boldIcon;
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index 34173780..c6b39e76 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -1317,8 +1317,11 @@ void DrumCanvas::rebuildOurDrumMap()
   
   if (!old_style_drummap_mode)
   {
+    bool need_update = false;
+    
     TrackList* tl=song->tracks();
     QList< QSet<Track*> > track_groups;
+    QVector<instrument_number_mapping_t> old_instrument_map = instrument_map;
     
     instrument_map.clear();
 
@@ -1396,6 +1399,9 @@ void DrumCanvas::rebuildOurDrumMap()
         
         bool mute=true;
         bool hidden=true;
+        
+        if (drumEditor->ignore_hide()) hidden=false;
+        
         for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && (mute || hidden); track++)
         {
           if (dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute == false)
@@ -1408,7 +1414,14 @@ void DrumCanvas::rebuildOurDrumMap()
         if (!hidden)
         {
           for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
-            dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute=mute; 
+          {
+            DrumMap* dm = &dynamic_cast<MidiTrack*>(*track)->drummap()[pitch];
+            if (dm->mute != mute)
+            {
+              dm->mute=mute; 
+              need_update = true;
+            }
+          }
           
           if (dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote != pitch)
             printf("THIS SHOULD NEVER HAPPEN: track's_drummap[pitch].anote (%i)!= pitch (%i) !!!\n",dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote,pitch);
@@ -1435,10 +1448,19 @@ void DrumCanvas::rebuildOurDrumMap()
     for (int i=0;i<size;i++)
       ourDrumMap[i] = dynamic_cast<MidiTrack*>(*instrument_map[i].tracks.begin())->drummap()[instrument_map[i].pitch];  
     
-    if (debugMsg) printf("rebuilt drummap, size is now %i\n",size);
+    if (instrument_map!=old_instrument_map)
+    {
+    if (debugMsg) printf("rebuilt drummap and instrument map, size is now %i\n",size);
     
-    songChanged(SC_EVENT_INSERTED); // force an update of the itemlist
-
-    emit ourDrumMapChanged();
+      songChanged(SC_EVENT_INSERTED); // force an update of the itemlist
+      emit ourDrumMapChanged(true);
+    }
+    else
+      emit ourDrumMapChanged(false);
+    
+    if (need_update)
+      song->update(SC_DRUMMAP, true); // i know, this causes a recursion, which possibly
+                                      // isn't the most elegant solution here. but it will
+                                      // never be an infinite recursion
   }
 }
diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h
index 9a45f6ac..8ecbdac9 100644
--- a/muse2/muse/midiedit/dcanvas.h
+++ b/muse2/muse/midiedit/dcanvas.h
@@ -73,6 +73,17 @@ struct instrument_number_mapping_t
     tracks=tr;
     pitch=p;
   }
+  
+  bool operator==(const instrument_number_mapping_t& that) //TODO maybe compare the Track* serial numbers, not the pointers themselves?
+  {
+    return (this->tracks == that.tracks && this->pitch==that.pitch);
+  }
+  
+  bool operator!=(const instrument_number_mapping_t& that)
+  {
+    return !operator==(that);
+  }
+  
 };
 
 //---------------------------------------------------------
@@ -122,7 +133,7 @@ class DrumCanvas : public EventCanvas {
       
    signals:
       void newWidth(int);
-      void ourDrumMapChanged();
+      void ourDrumMapChanged(bool /*instrumentMap changed as well?*/);
 
    private slots:
       void midiNote(int pitch, int velo);
@@ -156,7 +167,7 @@ class DrumCanvas : public EventCanvas {
       int pitch_and_track_to_instrument(int pitch, Track* track);
       DrumMap* getOurDrumMap() { return ourDrumMap; } //FINDMICH UGLY
       int getOurDrumMapSize() { return instrument_map.size(); } //FINDMICH UGLY
-      
+      QVector<instrument_number_mapping_t>& get_instrument_map() { return instrument_map; } //FINDMICH UGLY
       void propagate_drummap_change(int instrument); //FINDMICH move to drumedit
       void rebuildOurDrumMap();
       };
diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp
index 350f5e5e..c5379a15 100644
--- a/muse2/muse/midiedit/dlist.cpp
+++ b/muse2/muse/midiedit/dlist.cpp
@@ -33,6 +33,7 @@
 #include "pitchedit.h"
 #include "midiport.h"
 #include "drummap.h"
+#include "drumedit.h"
 #include "helper.h"
 #include "icons.h"
 #include "dlist.h"
@@ -56,13 +57,13 @@ void DList::draw(QPainter& p, const QRect& rect)
 
       p.setPen(Qt::black);
 
-      for (int i = 0; i < ourDrumMapSize; ++i) {
-            int yy = i * TH;
+      for (int instrument = 0; instrument < ourDrumMapSize; ++instrument) {
+            int yy = instrument * TH;
             if (yy+TH < y)
                   continue;
             if (yy > y + h)
                   break;
-            DrumMap* dm = &ourDrumMap[i];
+            DrumMap* dm = &ourDrumMap[instrument];
             if (dm == currentlySelected)
                   p.fillRect(x, yy, w, TH, Qt::yellow);
 //            else
@@ -71,6 +72,10 @@ void DList::draw(QPainter& p, const QRect& rect)
             p.save();
             p.setWorldMatrixEnabled(false);
             for (int k = 0; k < h->count(); ++k) {
+                  if (h->isSectionHidden(k))
+                      continue;
+                  
+                  
                   int x   = h->sectionPosition(k);
                   int w   = h->sectionSize(k);
                   //QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH));  // Gives inconsistent positions. Source shows wrong operation for our needs.
@@ -81,33 +86,72 @@ void DList::draw(QPainter& p, const QRect& rect)
                   //p.save();
                   //p.setWorldMatrixEnabled(false);
                   switch (k) {
-                        case COL_VOL:
+                        case COL_VOLUME:
                               s.setNum(dm->vol);
                               break;
-                        case COL_QNT:
+                        case COL_QUANT:
                               s.setNum(dm->quant);
                               break;
-                        case COL_LEN:
+                        case COL_NOTELENGTH:
                               s.setNum(dm->len);
                               break;
-                        case COL_ANOTE:
+                        case COL_NOTE:
                               s =  MusEUtil::pitch2string(dm->anote);
                               break;
-                        case COL_ENOTE:
+                        case COL_INPUTTRIGGER:
                               s =  MusEUtil::pitch2string(dm->enote);
                               break;
-                        case COL_LV1:
+                        case COL_LEVEL1:
                               s.setNum(dm->lv1);
                               break;
-                        case COL_LV2:
+                        case COL_LEVEL2:
                               s.setNum(dm->lv2);
                               break;
-                        case COL_LV3:
+                        case COL_LEVEL3:
                               s.setNum(dm->lv3);
                               break;
-                        case COL_LV4:
+                        case COL_LEVEL4:
                               s.setNum(dm->lv4);
                               break;
+                        case COL_HIDE:
+                        {
+                              bool hidden=false;
+                              bool shown=false;
+                              QSet<Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks;
+                              int pitch = dcanvas->get_instrument_map()[instrument].pitch;
+                              
+                              for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && !(hidden&&shown); track++)
+                                if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch])
+                                  hidden=true;
+                                else
+                                  shown=true;
+                              
+                              if (!hidden && !shown)
+                                printf("THIS SHOULD NEVER HAPPEN: in DList::draw(): instrument %i's track group is empty. strange...\n", instrument);
+                              
+                              const QPixmap* pm = NULL;
+                              
+                              if (shown && !hidden)
+                                    pm = eyeIcon;
+                              else if (!shown && hidden)
+                                    pm = eyeCrossedIcon;
+                              else if (shown && hidden)
+                                    pm = eyeGrayIcon;
+                              else //if (!shown && !hidden)
+                                    pm = NULL;
+                              
+                              if (pm)
+                              {
+                               // p.setPen(Qt::red);
+                                p.drawPixmap(
+                                   r.x() + r.width()/2 - pm->width()/2,
+                                   r.y() + r.height()/2 - pm->height()/2,
+                                   *pm);
+                               // p.setPen(Qt::black);
+                              }
+                                    
+                              break;
+                        }
                         case COL_MUTE:
                               if (dm->mute) {
                                     p.setPen(Qt::red);
@@ -123,10 +167,10 @@ void DList::draw(QPainter& p, const QRect& rect)
                               s = dm->name;
                               align = Qt::AlignVCenter | Qt::AlignLeft;
                               break;
-                        case COL_CHANNEL:
+                        case COL_OUTCHANNEL:
                               s.setNum(dm->channel+1);
                               break;
-                        case COL_PORT:
+                        case COL_OUTPORT:
                               s.sprintf("%d:%s", dm->port+1, midiPorts[dm->port].portname().toLatin1().constData());
                               align = Qt::AlignVCenter | Qt::AlignLeft;
                               break;
@@ -243,7 +287,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
       sInstrument = instrument;
       drag   = START_DRAG;
 
-      DCols col = DCols(x2col(x));
+      DrumColumn col = DrumColumn(x2col(x));
 
       int val;
       int incVal = 0;
@@ -257,7 +301,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
       // In that case, treat it as if a return was pressed
 
       if (button == Qt::LeftButton) {
-            if (((editEntry && editEntry != dm)  || col != selectedColumn) && editEntry != 0) {
+            if (editEntry && (editEntry != dm  || col != selectedColumn)) {
                   returnPressed();
                   }
             }
@@ -265,17 +309,35 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
       switch (col) {
             case COL_NONE:
                   break;
+            case COL_HIDE:
+                  if (button == Qt::LeftButton)
+                  {
+                    bool hidden=true;
+                    QSet<Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks;
+                    int pitch = dcanvas->get_instrument_map()[instrument].pitch;
+                    
+                    for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+                      if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] == false)
+                      {
+                        hidden=false;
+                        break;
+                      }
+                    
+                    for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+                      dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] = !hidden;
+                  }
+                  break;
             case COL_MUTE:
                   if (button == Qt::LeftButton)
                         dm->mute = !dm->mute;
                   break;
-            case COL_PORT: // this column isn't visible in new style drum mode
+            case COL_OUTPORT: // this column isn't visible in new style drum mode
                   if ((button == Qt::RightButton) || (button == Qt::LeftButton)) {
                         bool changeAll = ev->modifiers() & Qt::ControlModifier;
                         devicesPopupMenu(dm, mapx(x), mapy(instrument * TH), changeAll);
                         }
                   break;
-            case COL_VOL:
+            case COL_VOLUME:
                   val = dm->vol + incVal;
                   if (val < 0)
                         val = 0;
@@ -283,11 +345,11 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                         val = 999;
                   dm->vol = (unsigned char)val;      
                   break;
-            case COL_QNT:
+            case COL_QUANT:
                   dm->quant += incVal;
                   // ?? range
                   break;
-            case COL_ENOTE:
+            case COL_INPUTTRIGGER:
                   val = dm->enote + incVal;
                   if (val < 0)
                         val = 0;
@@ -310,13 +372,13 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                   }
                   dm->enote = val;
                   break;
-            case COL_LEN:
+            case COL_NOTELENGTH:
                   val = dm->len + incVal;
                   if (val < 0)
                         val = 0;
                   dm->len = val;
                   break;
-            case COL_ANOTE:
+            case COL_NOTE:
                   if (old_style_drummap_mode) //only allow changing in old style mode
                   {
                     val = dm->anote + incVal;
@@ -339,7 +401,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                   emit keyPressed(instrument, velocity);//(dm->anote, shift);
                   }
                   break;
-            case COL_CHANNEL: // this column isn't visible in new style drum mode
+            case COL_OUTCHANNEL: // this column isn't visible in new style drum mode
                   val = dm->channel + incVal;
                   if (val < 0)
                         val = 0;
@@ -370,7 +432,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                       }  
                   }      
                   break;
-            case COL_LV1:
+            case COL_LEVEL1:
                   val = dm->lv1 + incVal;
                   if (val < 0)
                         val = 0;
@@ -378,7 +440,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                         val = 127;
                   dm->lv1 = val;
                   break;
-            case COL_LV2:
+            case COL_LEVEL2:
                   val = dm->lv2 + incVal;
                   if (val < 0)
                         val = 0;
@@ -386,7 +448,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                         val = 127;
                   dm->lv2 = val;
                   break;
-            case COL_LV3:
+            case COL_LEVEL3:
                   val = dm->lv3 + incVal;
                   if (val < 0)
                         val = 0;
@@ -394,7 +456,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                         val = 127;
                   dm->lv3 = val;
                   break;
-            case COL_LV4:
+            case COL_LEVEL4:
                   val = dm->lv4 + incVal;
                   if (val < 0)
                         val = 0;
@@ -403,7 +465,48 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
                   dm->lv4 = val;
                   break;
             case COL_NAME:
-                  emit keyPressed(instrument, 100); //Mapping done on other side, send index
+                  if (button == Qt::LeftButton)
+                      emit keyPressed(instrument, 100); //Mapping done on other side, send index
+                  else if (button == Qt::MidButton) // hide that instrument
+                  {
+                    QSet<Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks;
+                    int pitch = dcanvas->get_instrument_map()[instrument].pitch;
+                    for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+                      dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] = true;                    
+                  }
+                  else if (button == Qt::RightButton)
+                  {
+                    bool hidden=false;
+                    bool shown=false;
+                    QSet<Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks;
+                    int pitch = dcanvas->get_instrument_map()[instrument].pitch;
+                    
+                    for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && !(hidden&&shown); track++)
+                      if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch])
+                        hidden=true;
+                      else
+                        shown=true;
+
+                    QMenu* popup = new QMenu(NULL /* intendedly not "this" */); 
+                    QAction* hideAction = popup->addAction(tr("hide this instrument"));
+                    QAction* showAction = popup->addAction(tr("show this instrument"));
+                    showAction->setToolTip(tr("this turns a grayed out eye into a blue eye"));
+                    
+                    if (!hidden)
+                      showAction->setEnabled(false);
+                    if (!shown)
+                      hideAction->setEnabled(false);
+                    
+                    QAction* result = popup->exec(ev->globalPos());
+                    if (result==hideAction)
+                      for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+                        dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] = true;                    
+                    else if (result==showAction)
+                      for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+                        dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] = false;       
+                    
+                    delete popup;
+                  }
                   break;
 
             default:
@@ -429,13 +532,13 @@ void DList::viewMouseDoubleClickEvent(QMouseEvent* ev)
 
       int section = header->logicalIndexAt(x);
 
-      if ((section == COL_NAME || section == COL_VOL || section == COL_LEN || section == COL_LV1 ||
-         section == COL_LV2 || section == COL_LV3 || section == COL_LV4 || section == COL_QNT ||
-         (section == COL_CHANNEL && old_style_drummap_mode) ) && (ev->button() == Qt::LeftButton))
+      if ((section == COL_NAME || section == COL_VOLUME || section == COL_NOTELENGTH || section == COL_LEVEL1 ||
+         section == COL_LEVEL2 || section == COL_LEVEL3 || section == COL_LEVEL4 || section == COL_QUANT ||
+         (section == COL_OUTCHANNEL && old_style_drummap_mode) ) && (ev->button() == Qt::LeftButton))
          {
            lineEdit(instrument, section);
          }
-      else if (((section == COL_ANOTE && old_style_drummap_mode) || section == COL_ENOTE) && (ev->button() == Qt::LeftButton))
+      else if (((section == COL_NOTE && old_style_drummap_mode) || section == COL_INPUTTRIGGER) && (ev->button() == Qt::LeftButton))
         pitchEdit(instrument, section);
       else
             viewMousePressEvent(ev);
@@ -466,37 +569,37 @@ void DList::lineEdit(int line, int section)
                   editor->setText(dm->name);
                   break;
 
-                  case COL_VOL: {
+                  case COL_VOLUME: {
                   editor->setText(QString::number(dm->vol));
                   break;
                   }
                   
-                  case COL_LEN: {
+                  case COL_NOTELENGTH: {
                   editor->setText(QString::number(dm->len));
                   break;
                   }
 
-                  case COL_LV1:
+                  case COL_LEVEL1:
                   editor->setText(QString::number(dm->lv1));
                   break;
 
-                  case COL_LV2:
+                  case COL_LEVEL2:
                   editor->setText(QString::number(dm->lv2));
                   break;
 
-                  case COL_LV3:
+                  case COL_LEVEL3:
                   editor->setText(QString::number(dm->lv3));
                   break;
 
-                  case COL_LV4:
+                  case COL_LEVEL4:
                   editor->setText(QString::number(dm->lv4));
                   break;
 
-                  case COL_QNT:
+                  case COL_QUANT:
                   editor->setText(QString::number(dm->quant));
                   break;
 
-                  case COL_CHANNEL:
+                  case COL_OUTCHANNEL:
                   editor->setText(QString::number(dm->channel+1));
                   break;
             }
@@ -530,11 +633,11 @@ void DList::pitchEdit(int line, int section)
             int colh = rmapy(TH);
             selectedColumn = section; //Store selected column to have an idea of which one was selected when return is pressed
             switch (section) {
-                  case COL_ENOTE:
+                  case COL_INPUTTRIGGER:
                   pitch_editor->setValue(dm->enote);
                   break;
 
-                  case COL_ANOTE:
+                  case COL_NOTE:
                   pitch_editor->setValue(dm->anote);
                   break;
             }
@@ -608,24 +711,24 @@ void DList::returnPressed()
             
             switch (selectedColumn)
             {
-              case COL_VOL:
+              case COL_VOLUME:
                   if (val > 999) //changed from 200 to 999 by flo93
                   val = 999;
                   if (val < 0)
                   val = 0;
                   break;
                   
-              case COL_LV1:
-              case COL_LV2:
-              case COL_LV3:
-              case COL_LV4:
+              case COL_LEVEL1:
+              case COL_LEVEL2:
+              case COL_LEVEL3:
+              case COL_LEVEL4:
                   if (val > 127) //Check bounds for lv1-lv4 values
                   val = 127;
                   if (val < 0)
                   val = 0;
                   break;
                   
-              case COL_CHANNEL:
+              case COL_OUTCHANNEL:
                   val--;
                   if (val >= 16)
                   val = 15;
@@ -643,35 +746,35 @@ void DList::returnPressed()
                   editEntry->name = editor->text();
                   break;
 
-            case COL_LEN:
+            case COL_NOTELENGTH:
                   editEntry->len = atoi(editor->text().toAscii().constData());
                   break;
 
-            case COL_VOL:
+            case COL_VOLUME:
                   editEntry->vol = val;
                   break;
 
-            case COL_LV1:
+            case COL_LEVEL1:
                   editEntry->lv1 = val;
                   break;
 
-            case COL_LV2:
+            case COL_LEVEL2:
                   editEntry->lv2 = val;
                   break;
 
-            case COL_LV3:
+            case COL_LEVEL3:
                   editEntry->lv3 = val;
                   break;
 
-            case COL_LV4:
+            case COL_LEVEL4:
                   editEntry->lv4 = val;
                   break;
 
-            case COL_QNT:
+            case COL_QUANT:
                   editEntry->quant = val;
                   break;
 
-            case COL_CHANNEL:
+            case COL_OUTCHANNEL:
                   editEntry->channel = val;
                   break;
 
@@ -708,7 +811,7 @@ void DList::pitchEdited()
       
       DrumMap editEntryOld=*editEntry;
       switch(selectedColumn) {
-            case COL_ANOTE:
+            case COL_NOTE:
                if (old_style_drummap_mode) //should actually be always true, but to be sure...
                {
                     if(val != editEntry->anote)
@@ -724,7 +827,7 @@ void DList::pitchEdited()
                   printf("ERROR: THIS SHOULD NEVER HAPPEN: pitch edited of anote in new style mode!\n");
                break;
 
-            case COL_ENOTE:
+            case COL_INPUTTRIGGER:
                if (old_style_drummap_mode)
                {
                   //Check if there is any other drumMap with the same inmap value (there should be one (and only one):-)
@@ -798,7 +901,7 @@ DList::DList(QHeaderView* h, QWidget* parent, int ymag, DrumCanvas* dcanvas_, bo
       ourDrumMap=dcanvas->getOurDrumMap();
       ourDrumMapSize=dcanvas->getOurDrumMapSize();
       old_style_drummap_mode=oldstyle;
-      connect(dcanvas, SIGNAL(ourDrumMapChanged()), SLOT(ourDrumMapChanged()));
+      connect(dcanvas, SIGNAL(ourDrumMapChanged(bool)), SLOT(ourDrumMapChanged(bool)));
       
       if (!h){
       h = new QHeaderView(Qt::Horizontal, parent);}
@@ -884,13 +987,13 @@ void DList::viewMouseReleaseEvent(QMouseEvent* ev)
       bool shift = ev->modifiers() & Qt::ShiftModifier;
       unsigned instrument = y / TH;
 
-      DCols col = DCols(x2col(x));
+      DrumColumn col = DrumColumn(x2col(x));
 
       switch (col) {
             case COL_NAME:
                   emit keyReleased(instrument, shift);
                   break;
-            case COL_ANOTE:
+            case COL_NOTE:
                   emit keyReleased(instrument, shift);
                   break;
             default:
@@ -910,14 +1013,16 @@ int DList::getSelectedInstrument()
       }
 
 
-void DList::ourDrumMapChanged()
+void DList::ourDrumMapChanged(bool instrMapChanged)
 {
   int selIdx = currentlySelected - ourDrumMap;
   
   ourDrumMap=dcanvas->getOurDrumMap();
   ourDrumMapSize=dcanvas->getOurDrumMapSize();
   
-  editEntry=NULL;
+  if (instrMapChanged)
+    editEntry=NULL;
+  
   if (selIdx >= ourDrumMapSize) selIdx=ourDrumMapSize-1;
   currentlySelected = &ourDrumMap[selIdx];
 
diff --git a/muse2/muse/midiedit/dlist.h b/muse2/muse/midiedit/dlist.h
index 1d87f3dc..cc3f3edc 100644
--- a/muse2/muse/midiedit/dlist.h
+++ b/muse2/muse/midiedit/dlist.h
@@ -131,7 +131,7 @@ class DList : public MusEWidget::View {
    public slots:
       void tracklistChanged();
       void songChanged(int);
-      void ourDrumMapChanged();
+      void ourDrumMapChanged(bool);
    
    public:
       void lineEdit(int line, int section);
@@ -141,9 +141,6 @@ class DList : public MusEWidget::View {
       ~DList();
       int getSelectedInstrument();
 
-enum DCols { COL_MUTE=0, COL_NAME, COL_VOL, COL_QNT, COL_ENOTE, COL_LEN,
-         COL_ANOTE, COL_CHANNEL, COL_PORT,
-         COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1};
       };
 
 #endif // __DLIST_H_
diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp
index 92cc765a..c98d0632 100644
--- a/muse2/muse/midiedit/drumedit.cpp
+++ b/muse2/muse/midiedit/drumedit.cpp
@@ -80,27 +80,12 @@ static const char* map_file_save_pattern[] = {
 int DrumEdit::_rasterInit = 96;
 int DrumEdit::_dlistWidthInit = 50;
 int DrumEdit::_dcanvasWidthInit = 300;
+bool DrumEdit::_ignore_hide_init = false;
 
 static const int xscale = -10;
 static const int yscale = 1;
 static const int drumeditTools = MusEWidget::PointerTool | MusEWidget::PencilTool | MusEWidget::RubberTool | MusEWidget::CursorTool | MusEWidget::DrawTool;
 
-enum DrumColumn {
-  COL_MUTE = 0,
-  COL_NAME,
-  COL_VOLUME,
-  COL_QUANT,
-  COL_INPUTTRIGGER,
-  COL_NOTELENGTH,
-  COL_NOTE,
-  COL_OUTCHANNEL,
-  COL_OUTPORT,
-  COL_LEVEL1,
-  COL_LEVEL2,
-  COL_LEVEL3,
-  COL_LEVEL4,
-  COL_NONE = -1
-};
 
 //---------------------------------------------------------
 //   setHeaderWhatsThis
@@ -108,6 +93,7 @@ enum DrumColumn {
 
 void DrumEdit::setHeaderWhatsThis()
       {
+      header->setWhatsThis(COL_HIDE, tr("hide instrument"));
       header->setWhatsThis(COL_MUTE, tr("mute instrument"));
       header->setWhatsThis(COL_NAME, tr("sound name"));
       header->setWhatsThis(COL_VOLUME, tr("volume percent"));
@@ -129,6 +115,7 @@ void DrumEdit::setHeaderWhatsThis()
 
 void DrumEdit::setHeaderToolTips()
       {
+      header->setToolTip(COL_HIDE, tr("hide instrument"));
       header->setToolTip(COL_MUTE, tr("mute instrument"));
       header->setToolTip(COL_NAME, tr("sound name"));
       header->setToolTip(COL_VOLUME, tr("volume percent"));
@@ -178,6 +165,7 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
       QSignalMapper *signalMapper = new QSignalMapper(this);
       
       _group_mode = GROUP_SAME_CHANNEL;
+      _ignore_hide = _ignore_hide_init;
       
       //---------Pulldown Menu----------------------------
       menuFile = menuBar()->addMenu(tr("&File"));
@@ -299,15 +287,19 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
         groupNoneAction = menuGrouping->addAction(tr("Don't group"));
         groupChanAction = menuGrouping->addAction(tr("Group by channel"));
         groupMaxAction  = menuGrouping->addAction(tr("Group maximally"));
+        QAction* ignoreHideAction = settingsMenu->addAction(tr("Also show hidden events"));
         settingsMenu->addSeparator();
         
         groupNoneAction->setCheckable(true);
         groupChanAction->setCheckable(true);
         groupMaxAction ->setCheckable(true);
+        ignoreHideAction->setCheckable(true);
+        ignoreHideAction->setChecked(_ignore_hide);
         
         connect(groupNoneAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
         connect(groupChanAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
         connect(groupMaxAction,  SIGNAL(triggered()), signalMapper, SLOT(map()));
+        connect(ignoreHideAction,  SIGNAL(toggled(bool)), SLOT(set_ignore_hide(bool)));
 
         signalMapper->setMapping(groupNoneAction, DrumCanvas::CMD_GROUP_NONE);
         signalMapper->setMapping(groupChanAction, DrumCanvas::CMD_GROUP_CHAN);
@@ -450,7 +442,7 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
       connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
       connect(canvas, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn()));
       connect(canvas, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut()));
-      connect(canvas, SIGNAL(ourDrumMapChanged()), SLOT(ourDrumMapChanged()));
+      connect(canvas, SIGNAL(ourDrumMapChanged(bool)), SLOT(ourDrumMapChanged(bool)));
       time->setOrigin(offset, 0);
 
       QList<int> mops;
@@ -474,6 +466,7 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
       //
       header = new MusEWidget::Header(split1w1, "header");
       header->setFixedHeight(31);
+      header->setColumnLabel(tr("H"), COL_HIDE, 20);
       header->setColumnLabel(tr("M"), COL_MUTE, 20);
       header->setColumnLabel(tr("Sound"), COL_NAME, 120);
       header->setColumnLabel(tr("Vol"), COL_VOLUME);
@@ -496,6 +489,11 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
         header->hideSection(COL_OUTPORT);
         header->hideSection(COL_OUTCHANNEL);
       }
+      
+      if (!old_style_drummap_mode() && _ignore_hide)
+        header->showSection(COL_HIDE);
+      else
+        header->hideSection(COL_HIDE);
 
       dlist = new DList(header, split1w1, yscale, (DrumCanvas*)canvas, old_style_drummap_mode());
       // p3.3.44
@@ -749,6 +747,7 @@ void DrumEdit::writeStatus(int level, Xml& xml) const
       xml.intTag(level, "xmag", hscroll->mag());
       xml.intTag(level, "ypos", vscroll->pos());
       xml.intTag(level, "ymag", vscroll->mag());
+      xml.intTag(level, "ignore_hide", _ignore_hide);
       xml.tag(level, "/drumedit");
       }
 
@@ -796,6 +795,8 @@ void DrumEdit::readStatus(Xml& xml)
                               vscroll->setMag(xml.parseInt());
                         else if (tag == "ypos")
                               vscroll->setPos(xml.parseInt());
+                        else if (tag == "ignore_hide")
+                              _ignore_hide=xml.parseInt();
                         else
                               xml.unknown("DrumEdit");
                         break;
@@ -832,6 +833,8 @@ void DrumEdit::readConfiguration(Xml& xml)
                               _dcanvasWidthInit = xml.parseInt();
                         else if (tag == "dlistwidth")
                               _dlistWidthInit = xml.parseInt();
+                        else if (tag == "ignore_hide_init")
+                              _ignore_hide_init = xml.parseInt();
                         else if (tag == "topwin")
                               TopWin::readConfiguration(DRUM, xml);
                         else
@@ -857,6 +860,7 @@ void DrumEdit::writeConfiguration(int level, Xml& xml)
       xml.intTag(level, "raster", _rasterInit);
       xml.intTag(level, "dlistwidth", _dlistWidthInit);
       xml.intTag(level, "dcanvaswidth", _dcanvasWidthInit);
+      xml.intTag(level, "ignore_hide_init", _ignore_hide_init);
       TopWin::writeConfiguration(DRUM, level,xml);
       xml.tag(level, "/drumedit");
       }
@@ -1177,7 +1181,7 @@ void DrumEdit::keyPressEvent(QKeyEvent* event)
             return;
       }
       else if (key == Qt::Key_F2) {
-            dlist->lineEdit(dlist->getSelectedInstrument(),(int)DList::COL_NAME);
+            dlist->lineEdit(dlist->getSelectedInstrument(),(int)COL_NAME);
             return;
             }
       else if (key == shortcuts[SHRT_INSTRUMENT_STEP_UP].key) {
@@ -1383,11 +1387,14 @@ bool DrumEdit::old_style_drummap_mode()
   return false;
 }
 
-void DrumEdit::ourDrumMapChanged()
+void DrumEdit::ourDrumMapChanged(bool instrMapChanged)
 {
-  int vmin,vmax;
-  vscroll->range(&vmin, &vmax);
-  vscroll->setRange(vmin, dynamic_cast<DrumCanvas*>(canvas)->getOurDrumMapSize()*TH);
+  if (instrMapChanged)
+  {
+    int vmin,vmax;
+    vscroll->range(&vmin, &vmax);
+    vscroll->setRange(vmin, dynamic_cast<DrumCanvas*>(canvas)->getOurDrumMapSize()*TH);
+  }
 }
 
 void DrumEdit::updateGroupingActions()
@@ -1402,3 +1409,18 @@ void DrumEdit::updateGroupingActions()
   groupChanAction->setChecked(_group_mode==GROUP_SAME_CHANNEL);
   groupMaxAction ->setChecked(_group_mode==GROUP_MAX);
 }
+
+void DrumEdit::set_ignore_hide(bool val)
+{
+  _ignore_hide=val;
+  _ignore_hide_init=val;
+  // this may only called be from the action's toggled signal.
+  // if called otherwise, the action's checked state isn't updated!
+
+  if (!old_style_drummap_mode() && _ignore_hide)
+    header->showSection(COL_HIDE);
+  else
+    header->hideSection(COL_HIDE);
+  
+  ((DrumCanvas*)(canvas))->rebuildOurDrumMap();
+}
diff --git a/muse2/muse/midiedit/drumedit.h b/muse2/muse/midiedit/drumedit.h
index 743d6151..4b0a39b8 100644
--- a/muse2/muse/midiedit/drumedit.h
+++ b/muse2/muse/midiedit/drumedit.h
@@ -61,6 +61,24 @@ class Splitter;
 class Toolbar1;
 }
 
+enum DrumColumn {
+  COL_HIDE = 0,
+  COL_MUTE,
+  COL_NAME,
+  COL_VOLUME,
+  COL_QUANT,
+  COL_INPUTTRIGGER,
+  COL_NOTELENGTH,
+  COL_NOTE,
+  COL_OUTCHANNEL,
+  COL_OUTPORT,
+  COL_LEVEL1,
+  COL_LEVEL2,
+  COL_LEVEL3,
+  COL_LEVEL4,
+  COL_NONE = -1
+};
+
 //---------------------------------------------------------
 //   DrumEdit
 //---------------------------------------------------------
@@ -73,6 +91,7 @@ class DrumEdit : public MidiEditor {
   
    private:
       group_mode_t _group_mode;
+      bool _ignore_hide;
       
       Event selEvent;
       MidiPart* selPart;
@@ -95,6 +114,7 @@ class DrumEdit : public MidiEditor {
 
       static int _rasterInit;
       static int _dlistWidthInit, _dcanvasWidthInit;
+      static bool _ignore_hide_init;
 
       QAction *loadAction, *saveAction, *resetAction;
       QAction *cutAction, *copyAction, *copyRangeAction, *pasteAction, *pasteDialogAction, *deleteAction;
@@ -130,6 +150,7 @@ class DrumEdit : public MidiEditor {
       void songChanged1(int);
       void setStep(QString);
       void updateGroupingActions();
+      void set_ignore_hide(bool);
 
    public slots:
       void setSelection(int, Event&, Part*);
@@ -137,7 +158,7 @@ class DrumEdit : public MidiEditor {
       void execDeliveredScript(int);
       void execUserScript(int);
       CtrlEdit* addCtrl();
-      void ourDrumMapChanged();
+      void ourDrumMapChanged(bool);
       virtual void updateHScrollRange();
 
    signals:
@@ -153,6 +174,7 @@ class DrumEdit : public MidiEditor {
       
       bool old_style_drummap_mode();
       group_mode_t group_mode() { return _group_mode; }
+      bool ignore_hide() { return _ignore_hide; }
       };
 
 #endif
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 64258f60..e82ab7ad 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4591,11 +4591,11 @@ void ScoreCanvas::add_new_parts(const std::map< Part*, std::set<Part*> >& param)
  *     from clipboard failed. ignoring this one... ) [ not reproducible ]
  * 
  * CURRENT TODO
- * ! o fix sigedit boxes (see also "important todo")
  *   o fix valgrind problems
- *
+ * 
  * > o drum editor: channel-stuff
- *        o dialog for maintaining drum lists, hide etc
+ *        o clearly state in the changelog: when having multiple drumeditors open,
+ *          the mute-column may not work, because another editor is overriding this.
  *        o respect "_drummap_tied_to_patch": IMPLEMENT
  *        o save hide, ordering, track's drumlists
  * 				o "copy drumlist" from one track to another
@@ -4615,7 +4615,6 @@ void ScoreCanvas::add_new_parts(const std::map< Part*, std::set<Part*> >& param)
  *   o all places where i added doubleclick-edits: only react on left-click double clicks!
  *   o support "new style" reordering with old style drum tracks as well
  *     (not swapping but inserting!)
- * ! o fix sigedit boxes (see also "current todo")
  *   o add "dotted quarter" quantize option (for 6/8 beat)
  *   o ticks-to-quarter spinboxes
  *   o newly created windows have to be focussed!
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index a994b0e6..db2bcad5 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -1468,11 +1468,13 @@ void Song::rewindStart()
 //   update
 //---------------------------------------------------------
 
-void Song::update(int flags)
+void Song::update(int flags, bool allowRecursion)
       {
       static int level = 0;         // DEBUG
-      if (level) {
-            printf("Song::update %08x, level %d\n", flags, level);
+      if (level && !allowRecursion) {
+            printf("THIS SHOULD NEVER HAPPEN: unallowed recursion in Song::update(%08x), level %d!\n"
+                   "                          the songChanged() signal is NOT emitted. this will\n"
+                   "                          probably cause windows being not up-to-date.\n", flags, level);
             return;
             }
       ++level;
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index 79e5521f..ad77d723 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -379,7 +379,9 @@ class Song : public QObject {
 
    public slots:
       void seekTo(int tick);
-      void update(int flags = -1);
+      void update(int flags = -1, bool allowRecursion=false); // use allowRecursion with care! this
+                                                              // could lock up muse if you aren't sure
+                                                              // that your recursion will be finite!
       void beat();
 
       void undo();
diff --git a/muse2/xpm/eye.xpm b/muse2/xpm/eye.xpm
new file mode 100644
index 00000000..74e5bcc1
--- /dev/null
+++ b/muse2/xpm/eye.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * eye_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #0000FD",
+"                ",
+"                ",
+"                ",
+"      ....      ",
+"    ........    ",
+"  ...      ...  ",
+" ...  ++++  ... ",
+"...  ++++++  ...",
+"..   ++++++   ..",
+"...  ++++++  ...",
+" ...  ++++  ... ",
+"  ...      ...  ",
+"    ........    ",
+"      ....      ",
+"                ",
+"                "};
diff --git a/muse2/xpm/eye_crossed.xpm b/muse2/xpm/eye_crossed.xpm
new file mode 100644
index 00000000..65dca19c
--- /dev/null
+++ b/muse2/xpm/eye_crossed.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * eye_crossed_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #E10E08",
+"+	c #000000",
+"@	c #0000FD",
+"                ",
+"             .. ",
+"            ....",
+"      ++++ .... ",
+"    ++++++....  ",
+"  +++    ....+  ",
+" +++  @@....+++ ",
+"+++  @@....  +++",
+"++   @....@   ++",
+"+++  ....@@  +++",
+" +++....@@  +++ ",
+"  +....    +++  ",
+"  ....++++++    ",
+" .... ++++      ",
+"  ..            ",
+"                "};
diff --git a/muse2/xpm/eye_gray.xpm b/muse2/xpm/eye_gray.xpm
new file mode 100644
index 00000000..8d5a7d9d
--- /dev/null
+++ b/muse2/xpm/eye_gray.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * eye_gray_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #292929",
+"+	c #535353",
+"                ",
+"                ",
+"                ",
+"      ....      ",
+"    ........    ",
+"  ...      ...  ",
+" ...  ++++  ... ",
+"...  ++++++  ...",
+"..   ++++++   ..",
+"...  ++++++  ...",
+" ...  ++++  ... ",
+"  ...      ...  ",
+"    ........    ",
+"      ....      ",
+"                ",
+"                "};
-- 
cgit v1.2.3