//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: canvas.cpp,v 1.2 2003/10/29 14:19:26 lunar_shuttle Exp $
//  (C) Copyright 1999 Werner Schweer (ws@seh.de)
//=========================================================

#include <stdio.h>
#include "canvas.h"
#include <qpainter.h>
#include "song.h"
#include "citem.h"
#include <qpopupmenu.h>
#include <qcursor.h>
#include "icons.h"
#include "../marker/marker.h"
#include "event.h"
#define ABS(x)  ((x) < 0) ? -(x) : (x)

//---------------------------------------------------------
//   Canvas
//---------------------------------------------------------

Canvas::Canvas(QWidget* parent, int sx, int sy, const char* name)
   : View(parent, sx, sy, name)
      {
      canvasTools = 0;
      itemPopupMenu = 0;
      drag    = DRAG_OFF;
      _tool   = PointerTool;
      pos[0]  = song->cpos();
      pos[1]  = song->lpos();
      pos[2]  = song->rpos();
      curPart = NULL;
      curPartId = -1;
      curItem = NULL;
      connect(song, SIGNAL(posChanged(int, int, bool)), this, SLOT(setPos(int, int, bool)));
      }

//---------------------------------------------------------
//   setPos
//    set one of three markers
//    idx   - 0-cpos  1-lpos  2-rpos
//    flag  - emit followEvent()
//---------------------------------------------------------

void Canvas::setPos(int idx, int val, bool adjustScrollbar)
      {
      if (pos[idx] == val)
            return;

      int opos = mapx(pos[idx]);
      int npos = mapx(val);

      if (adjustScrollbar && idx == 0) {
            switch (song->follow()) {
                  case  Song::NO:
                        break;
                  case Song::JUMP:
                        if (npos >= width()) {
                              int ppos =  val - rmapxDev(width()/8);
                              if (ppos < 0)
                                    ppos = 0;
                              emit followEvent(ppos);
                              opos = mapx(pos[idx]);
                              npos = mapx(val);
                              }
                        else if (npos < 0) {
                              int ppos =  val - rmapxDev(width()*3/4);
                              if (ppos < 0)
                                    ppos = 0;
                              emit followEvent(ppos);
                              opos = mapx(pos[idx]);
                              npos = mapx(val);
                              }
                        break;
                  case Song::CONTINUOUS:
                        if (npos > (width()/2)) {
                              int ppos =  pos[idx] - rmapxDev(width()/2);
                              if (ppos < 0)
                                    ppos = 0;
                              emit followEvent(ppos);
                              opos = mapx(pos[idx]);
                              npos = mapx(val);
                              }
                        else if (npos < (width()/2)) {
                              int ppos =  pos[idx] - rmapxDev(width()/2);
                              if (ppos < 0)
                                    ppos = 0;
                              emit followEvent(ppos);
                              opos = mapx(pos[idx]);
                              npos = mapx(val);
                              }
                        break;
                  }
            }

      int x;
      int w = 1;
      if (opos > npos) {
            w += opos - npos;
            x = npos;
            }
      else {
            w += npos - opos;
            x = opos;
            }
      pos[idx] = val;
      redraw(QRect(x-1, 0, w+2, height()));
      }

//---------------------------------------------------------
//   draw
//---------------------------------------------------------

void Canvas::draw(QPainter& p, const QRect& rect)
      {
//      printf("draw canvas %x virt %d\n", this, virt());

      int x = rect.x();
      int y = rect.y();
      int w = rect.width();
      int h = rect.height();
      int x2 = x + w;

      if (virt()) {
            drawCanvas(p, rect);

            //---------------------------------------------------
            // draw Canvas Items
            //---------------------------------------------------

            iCItem to(items.lower_bound(x2));
            for (iCItem i = items.begin(); i != to; ++i) {
                  if (i->second->intersects(rect))
                        drawItem(p, i->second, i->second->bbox().intersect(rect));
                  }
            to = moving.lower_bound(x2);
            for (iCItem i = moving.begin(); i != to; ++i) {
                  if (i->second->intersects(rect))
                        drawItem(p, i->second, i->second->bbox().intersect(rect));
                  }

            }
      else {
            p.save();
            setPainter(p);

            if (xmag < 0) {
                  x -= 1;
                  w += 2;
                  x = (x + xpos + rmapx(xorg)) * (-xmag);
                  w = w * (-xmag);
                  }
            else {
                  x = (x + xpos + rmapx(xorg)) / xmag;
                  w = (w + xmag - 1) / xmag;
                  x -= 1;
                  w += 2;
                  }
            if (ymag < 0) {
                  y -= 1;
                  h += 2;
                  y = (y + ypos + rmapy(yorg)) * (-ymag);
                  h = h * (-ymag);
                  }
            else {
                  y = (rect.y() + ypos + rmapy(yorg))/ymag;
                  h = (rect.height()+ymag-1)/ymag;
                  y -= 1;
                  h += 2;
                  }

            if (x < 0)
                  x = 0;
            if (y < 0)
                  y = 0;
            x2 = x + w;

            drawCanvas(p, QRect(x, y, w, h));
            p.restore();

            //---------------------------------------------------
            // draw Canvas Items
            //---------------------------------------------------

            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  CItem* ci = i->second;
                  QRect r(ci->bbox());
                  r.moveCenter(map((ci->pos())));
                  if (r.intersects(rect))
                        drawItem(p, ci, rect);
                  }
            for (iCItem i = moving.begin(); i != moving.end(); ++i) {
                  QRect r(i->second->bbox());
                  r.moveCenter(map(i->second->pos()));
                  if (r.intersects(rect))
                        drawItem(p, i->second, rect);
                  }
            setPainter(p);
            }

      //---------------------------------------------------
      //    draw marker
      //---------------------------------------------------

      int y2 = y + h;
      MarkerList* marker = song->marker();
      for (iMarker m = marker->begin(); m != marker->end(); ++m) {
            int xp = m->second.posTick();
            if (xp >= x && xp < x+w) {
                  p.setPen(green);
                  p.drawLine(xp, y, xp, y2);
                  }
            }

      //---------------------------------------------------
      //    draw location marker
      //---------------------------------------------------

      p.setPen(blue);
      if (pos[1] >= x && pos[1] < x2) {
            p.drawLine(pos[1], y, pos[1], y2);
            }
      if (pos[2] >= x && pos[2] < x2)
            p.drawLine(pos[2], y, pos[2], y2);
      p.setPen(red);
      if (pos[0] >= x && pos[0] < x2) {
            p.drawLine(pos[0], y, pos[0], y2);
            }

      //---------------------------------------------------
      //    draw lasso
      //---------------------------------------------------

      if (drag == DRAG_LASSO) {
            p.setPen(blue);
            p.setBrush(NoBrush);
            p.drawRect(lasso);
            }
      }

//---------------------------------------------------------
//   deselectAll
//---------------------------------------------------------

void Canvas::deselectAll()
      {
      for (iCItem i = items.begin(); i != items.end(); ++i)
            i->second->setSelected(false);
      }

//---------------------------------------------------------
//   selectItem
//---------------------------------------------------------

void Canvas::selectItem(CItem* e, bool flag)
      {
      e->setSelected(flag);
      }

//---------------------------------------------------------
//   startMoving
//    copy selection-List to moving-List
//---------------------------------------------------------

void Canvas::startMoving(const QPoint& pos, DragType)
      {
      for (iCItem i = items.begin(); i != items.end(); ++i) {
            if (i->second->isSelected()) {
                  i->second->setMoving(true);
                  moving.add(i->second);
                  }
            }
      moveItems(pos, 0);
      }

//---------------------------------------------------------
//   moveItems
//    dir = 0     move in all directions
//          1     move only horizontal
//          2     move only vertical
//---------------------------------------------------------

void Canvas::moveItems(const QPoint& pos, int dir = 0)
      {
      int dp = y2pitch(pos.y()) - y2pitch(start.y());
      int dx = pos.x() - start.x();
      if (dir == 1)
            dp = 0;
      else if (dir == 2)
            dx = 0;
      for (iCItem i = moving.begin(); i != moving.end(); ++i) {
            int x = i->second->pos().x();
            int y = i->second->pos().y();
            int nx = x + dx;
            int ny = pitch2y(y2pitch(y) + dp);
            QPoint mp(raster(QPoint(nx, ny)));
            if (i->second->mp() != mp) {
                  i->second->setMp(mp);
                  itemMoved(i->second, mp);
                  }
            }
      redraw();
      }

//---------------------------------------------------------
//   viewKeyPressEvent
//---------------------------------------------------------

void Canvas::viewKeyPressEvent(QKeyEvent* event)
      {
      keyPress(event);
      }

//---------------------------------------------------------
//   viewMousePressEvent
//---------------------------------------------------------

void Canvas::viewMousePressEvent(QMouseEvent* event)
      {
      keyState = event->state();

      // special events if right button is clicked while operations
      // like moving or drawing lasso is performed.
      if (event->stateAfter() & RightButton) {
            switch (drag) { 
                  case DRAG_LASSO: 
                        drag = DRAG_OFF; 
                        redraw(); 
                        return; 
                  case DRAG_MOVE: 
                        drag = DRAG_OFF; 
                        endMoveItems (start, MOVE_MOVE, 0); 
                        return; 
                  default: 
                  break; 
            } 
      }

      // ignore event if (another) button is already active:
      if (keyState & (LeftButton|RightButton|MidButton)) {
            return;
            }
      bool shift      = keyState & ShiftButton;
      bool alt        = keyState & AltButton;
      bool ctrl       = keyState & ControlButton; 
      start           = event->pos();

      //---------------------------------------------------
      //    set curItem to item mouse is pointing
      //    (if any)
      //---------------------------------------------------

      if (virt())
            curItem = items.find(start);
      else {
            curItem = 0;
            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  QRect box = i->second->bbox();
                  int x = rmapxDev(box.x());
                  int y = rmapyDev(box.y());
                  int w = rmapxDev(box.width());
                  int h = rmapyDev(box.height());
                  QRect r(x, y, w, h);
                  r.moveBy(i->second->pos().x(), i->second->pos().y());
                  if (r.contains(start)) {
                        curItem = i->second;
                        break;
                        }
                  }
            }

      if (curItem && (event->button() == QMouseEvent::MidButton)) {
            if (!curItem->isSelected()) {
                  selectItem(curItem, true);
                  updateSelection();
                  redraw();
                  }
            startDrag(curItem, shift);
            }
      else if (event->button() == QMouseEvent::RightButton) {
            if (curItem) {
                  itemPopupMenu = genItemPopup(curItem);
                  if (itemPopupMenu) {
                        int n = itemPopupMenu->exec(QCursor::pos());
                        if (n != -1)
                              itemPopup(curItem, n, start);
                        delete itemPopupMenu;
                        }
                  }
            else {
                  canvasPopupMenu = genCanvasPopup();
                  if (canvasPopupMenu) {
                        int n = canvasPopupMenu->exec(QCursor::pos(), 0);
                        if (n != -1)
                              canvasPopup(n);
                        delete canvasPopupMenu;
                        }
                  }
            }
      else if (event->button() == QMouseEvent::LeftButton) {
            switch (_tool) {
                  case PointerTool:
                        if (curItem) {
                              itemPressed(curItem);
                              if (curItem->part() != curPart) {
                                    curPart = curItem->part();
                                    curPartId = curPart->sn();
                                    curPartChanged();
                                    }
                              if (shift)
                                    drag = DRAG_COPY_START;
                              else if (alt) {
                                    drag = DRAG_CLONE_START;
// printf("CLONE start\n");
                                    }
                              else if (ctrl) { //Select all on the same pitch (e.g. same y-value) 
                                          deselectAll(); 
                                          for (iCItem i = items.begin(); i != items.end(); ++i) { 
                                                if (i->second->y() == curItem->y() ) 
                                                      selectItem(i->second, true); 
                                          } 
                                          updateSelection(); 
                                          redraw(); 
                                    } 
                              else
                                    drag = DRAG_MOVE_START;
                              }
                        else
                              drag = DRAG_LASSO_START;
                        setCursor();
                        break;

                  case RubberTool:
                        deleteItem(start);
                        drag = DRAG_DELETE;
                        setCursor();
                        break;

                  case PencilTool:
                        if (curItem) {
                              drag = DRAG_RESIZE;
                              setCursor();
                              int dx = start.x() - curItem->x();
                              curItem->setWidth(dx);
                              start.setX(curItem->x());
                              }
                        else {
                              drag = DRAG_NEW;
                              setCursor();
                              curItem = newItem(start, event->state());
                              if (curItem)
                                    items.add(curItem);
                              else {
                                    drag = DRAG_OFF;
                                    setCursor();
                                    }
                              }
                        deselectAll();
                        if (curItem)
                              selectItem(curItem, true);
                        updateSelection();
                        redraw();
                        break;

                  default:
                        break;
                  }
            }
      mousePress(event);
      }

//---------------------------------------------------------
//   viewMouseMoveEvent
//---------------------------------------------------------

void Canvas::viewMouseMoveEvent(QMouseEvent* event)
      {
      QPoint pos  = event->pos();
      QPoint dist = pos - start;
      int ax      = ABS(rmapx(dist.x()));
      int ay      = ABS(rmapy(dist.y()));
      bool moving = (ax >= 2) || (ay > 2);

      switch (drag) {
            case DRAG_LASSO_START:
                  if (!moving)
                        break;
                  drag = DRAG_LASSO;
                  setCursor();
                  // proceed with DRAG_LASSO:

            case DRAG_LASSO:
                  lasso = QRect(start.x(), start.y(), dist.x(), dist.y());
                  redraw();
                  break;

            case DRAG_MOVE_START:
            case DRAG_COPY_START:
            case DRAG_CLONE_START:
                  if (!moving)
                        break;
                  if (keyState & ControlButton) {
                        if (ax > ay) {
                              if (drag == DRAG_MOVE_START)
                                    drag = DRAGX_MOVE;
                              else if (drag == DRAG_COPY_START)
                                    drag = DRAGX_COPY;
                              else
                                    drag = DRAGX_CLONE;
                              }
                        else {
                              if (drag == DRAG_MOVE_START)
                                    drag = DRAGY_MOVE;
                              else if (drag == DRAG_COPY_START)
                                    drag = DRAGY_COPY;
                              else
                                    drag = DRAGY_CLONE;
                              }
                        }
                  else {
                        if (drag == DRAG_MOVE_START)
                              drag = DRAG_MOVE;
                        else if (drag == DRAG_COPY_START)
                              drag = DRAG_COPY;
                        else
                              drag = DRAG_CLONE;
                        }
                  setCursor();
                  if (!curItem->isSelected()) {
                        if (drag == DRAG_MOVE)
                              deselectAll();
                        selectItem(curItem, true);
                        updateSelection();
                        redraw();
                        }
                  DragType dt;
                  if (drag == DRAG_MOVE)
                        dt = MOVE_MOVE;
                  else if (drag == DRAG_COPY)
                        dt = MOVE_COPY;
                  else
                        dt = MOVE_CLONE;
                  startMoving(pos, dt);
                  break;

            case DRAG_MOVE:
            case DRAG_COPY:
            case DRAG_CLONE:
                  moveItems(pos, 0);
                  break;

            case DRAGX_MOVE:
            case DRAGX_COPY:
            case DRAGX_CLONE:
                  moveItems(pos, 1);
                  break;

            case DRAGY_MOVE:
            case DRAGY_COPY:
            case DRAGY_CLONE:
                  moveItems(pos, 2);
                  break;

            case DRAG_NEW:
            case DRAG_RESIZE:
                  if (dist.x()) {
                        if (dist.x() < 1)
                              curItem->setWidth(1);
                        else
                              curItem->setWidth(dist.x());
                        redraw();
                        }
                  break;
            case DRAG_DELETE:
                  deleteItem(pos);
                  break;

            case DRAG_OFF:
                  break;
            }
      mouseMove(pos);
      }

//---------------------------------------------------------
//   viewMouseReleaseEvent
//---------------------------------------------------------

void Canvas::viewMouseReleaseEvent(QMouseEvent* event)
      {
// printf("release %x %x\n", event->state(), event->button());

      if (event->state() & (LeftButton|RightButton|MidButton) & ~(event->button())) {
            printf("ignore %x  %x\n", keyState, event->button());
            return;
            }

      QPoint pos = event->pos();
      bool shift = event->state() & ShiftButton;
      bool redrawFlag = false;

      switch (drag) {
            case DRAG_MOVE_START:
            case DRAG_COPY_START:
            case DRAG_CLONE_START:
                  if (!shift)
                        deselectAll();
                  selectItem(curItem, !(shift && curItem->isSelected()));
                  updateSelection();
                  redrawFlag = true;
                  itemReleased(curItem, curItem->pos());
                  break;
            case DRAG_COPY:
                  endMoveItems(pos, MOVE_COPY, 0);
                  break;
            case DRAGX_COPY:
                  endMoveItems(pos, MOVE_COPY, 1);
                  break;
            case DRAGY_COPY:
                  endMoveItems(pos, MOVE_COPY, 2);
                  break;
            case DRAG_MOVE:
                  endMoveItems(pos, MOVE_MOVE, 0);
                  break;
            case DRAGX_MOVE:
                  endMoveItems(pos, MOVE_MOVE, 1);
                  break;
            case DRAGY_MOVE:
                  endMoveItems(pos, MOVE_MOVE, 2);
                  break;
            case DRAG_CLONE:
                  endMoveItems(pos, MOVE_CLONE, 0);
                  break;
            case DRAGX_CLONE:
                  endMoveItems(pos, MOVE_CLONE, 1);
                  break;
            case DRAGY_CLONE:
                  endMoveItems(pos, MOVE_CLONE, 2);
                  break;
            case DRAG_OFF:
                  break;
            case DRAG_RESIZE:
                  resizeItem(curItem, false);
                  break;
            case DRAG_NEW:
                  newItem(curItem, false);
                  redrawFlag = true;
                  break;
            case DRAG_LASSO_START:
                  lasso.setRect(-1, -1, -1, -1);
                  if (!shift)
                        deselectAll();
                  updateSelection();
                  redrawFlag = true;
                  break;

            case DRAG_LASSO:
                  if (!shift)
                        deselectAll();
                  lasso = lasso.normalize();
                  selectLasso(shift);
                  updateSelection();
                  redrawFlag = true;
                  break;

            case DRAG_DELETE:
                  break;
            }
      drag = DRAG_OFF;
      if (redrawFlag)
            redraw();
      setCursor();
      }

//---------------------------------------------------------
//   selectLasso
//---------------------------------------------------------

void Canvas::selectLasso(bool toggle)
      {
      int n = 0;
      if (virt()) {
            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  if (i->second->intersects(lasso)) {
                        selectItem(i->second, !(toggle && i->second->isSelected()));
                        ++n;
                        }
                  }
            }
      else {
            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  QRect box = i->second->bbox();
                  int x = rmapxDev(box.x());
                  int y = rmapyDev(box.y());
                  int w = rmapxDev(box.width());
                  int h = rmapyDev(box.height());
                  QRect r(x, y, w, h);
                  r.moveBy(i->second->pos().x(), i->second->pos().y());
                  if (r.intersects(lasso)) {
                        selectItem(i->second, !(toggle && i->second->isSelected()));
                        ++n;
                        }
                  }
            }
      if (n) {
            updateSelection();
            redraw();
            }
      }

//---------------------------------------------------------
//   endMoveItems
//    dir = 0     move in all directions
//          1     move only horizontal
//          2     move only vertical
//---------------------------------------------------------

void Canvas::endMoveItems(const QPoint& pos, DragType dragtype, int dir)
      {
      startUndo(dragtype);

      int dp = y2pitch(pos.y()) - y2pitch(start.y());
      int dx = pos.x() - start.x();

      if (dir == 1)
            dp = 0;
      else if (dir == 2)
            dx = 0;
      for (iCItem i = moving.begin(); i != moving.end(); ++i) {
            int x = i->second->pos().x();
            int y = i->second->pos().y();
            int nx = x + dx;
            int ny = pitch2y(y2pitch(y) + dp);
            QPoint newpos = raster(QPoint(nx, ny));
            selectItem(i->second, true);
            if (moveItem(i->second, newpos, dragtype))
                  i->second->move(newpos);
            if (moving.size() == 1) {
                  itemReleased(curItem, newpos);
                  }
            if (dragtype == MOVE_COPY || dragtype == MOVE_CLONE)
                  selectItem(i->second, false);
            }
      endUndo(dragtype);
      moving.clear();
      updateSelection();
      redraw();
      }

//---------------------------------------------------------
//   deleteItem
//---------------------------------------------------------

void Canvas::deleteItem(const QPoint& p)
      {
      if (virt()) {
            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  if (i->second->contains(p)) {
                        if (deleteItem(i->second))
                              selectItem(i->second, false);
                        else {
                              if (drag == DRAG_DELETE)
                                    drag = DRAG_OFF;
                              }
                        break;
                        }
                  }
            }
      else {
            for (iCItem i = items.begin(); i != items.end(); ++i) {
                  QRect box = i->second->bbox();
                  int x = rmapxDev(box.x());
                  int y = rmapyDev(box.y());
                  int w = rmapxDev(box.width());
                  int h = rmapyDev(box.height());
                  QRect r(x, y, w, h);
                  r.moveBy(i->second->pos().x(), i->second->pos().y());
                  if (r.contains(p)) {
                        if (deleteItem(i->second)) {
                              selectItem(i->second, false);
                              break;
                              }
                        }
                  }
            }
      }

//---------------------------------------------------------
//   setTool
//---------------------------------------------------------

void Canvas::setTool(int t)
      {
      if (_tool == Tool(t))
            return;
      _tool = Tool(t);
      setCursor();
      }

//---------------------------------------------------------
//   setCursor
//---------------------------------------------------------

void Canvas::setCursor()
      {
      switch (drag) {
            case DRAGX_MOVE:
            case DRAGX_COPY:
            case DRAGX_CLONE:
                  QWidget::setCursor(QCursor(SizeHorCursor));
                  break;

            case DRAGY_MOVE:
            case DRAGY_COPY:
            case DRAGY_CLONE:
                  QWidget::setCursor(QCursor(SizeVerCursor));
                  break;

            case DRAG_MOVE:
            case DRAG_COPY:
            case DRAG_CLONE:
                  QWidget::setCursor(QCursor(SizeAllCursor));
                  break;

            case DRAG_RESIZE:
//                  QWidget::setCursor(QCursor(SizeHorCursor));
//                  break;

            case DRAG_DELETE:
            case DRAG_COPY_START:
            case DRAG_CLONE_START:
            case DRAG_MOVE_START:
            case DRAG_NEW:
            case DRAG_LASSO_START:
            case DRAG_LASSO:
            case DRAG_OFF:
                  switch(_tool) {
                        case PencilTool:
                              QWidget::setCursor(QCursor(*pencilIcon, 4, 15));
                              break;
                        case RubberTool:
                              QWidget::setCursor(QCursor(*deleteIcon, 4, 15));
                              break;
                        case GlueTool:
                              QWidget::setCursor(QCursor(*glueIcon, 4, 15));
                              break;
                        case CutTool:
                              QWidget::setCursor(QCursor(*cutIcon, 4, 15));
                              break;
                        case MuteTool:
                              QWidget::setCursor(QCursor(*editmuteIcon, 4, 15));
                              break;
                        default:
                              QWidget::setCursor(QCursor(ArrowCursor));
                              break;
                        }
                  break;
            }
      }

//---------------------------------------------------------
//   keyPress
//---------------------------------------------------------

void Canvas::keyPress(QKeyEvent* event)
      {
      //Alt-P, shortcut for both DrumEditor and PianoRoll. Sets locators to include selected events 
      if (event->key() == Key_P && event->state() & AltButton) {
            int tick_max = 0;
            int tick_min = INT_MAX;
            bool found = false;

            for (iCItem i= items.begin(); i != items.end(); i++) {
                  if (!i->second->isSelected())
                        continue;

                  int tick = i->second->x();
                  int len = i->second->event()->lenTick();
                  found = true;
                  if (tick + len > tick_max)
                        tick_max = tick + len;
                  if (tick < tick_min)
                        tick_min = tick;
            }
            if (found) {
                  song->setPos(1, tick_min);
                  song->setPos(2, tick_max);
            }
      }
      else
            event->ignore();
      }

//---------------------------------------------------------
//   isSingleSelection
//---------------------------------------------------------

bool Canvas::isSingleSelection()
      {
      return selectionSize() == 1;
      }

//---------------------------------------------------------
//   selectionSize
//---------------------------------------------------------

int Canvas::selectionSize()
      {
      int n = 0;
      for (iCItem i = items.begin(); i != items.end(); ++i) {
            if (i->second->isSelected())
                  ++n;
            }
      return n;
      }

//---------------------------------------------------------
//   genCanvasPopup
//---------------------------------------------------------

QPopupMenu* Canvas::genCanvasPopup()
      {
      if (canvasTools == 0)
            return 0;
      QPopupMenu* canvasPopup = new QPopupMenu(this);

      for (unsigned i = 0; i < 9; ++i) {
            if ((canvasTools & (1 << i))==0)
                  continue;
            canvasPopup->insertItem(**toolList[i].icon, tr(toolList[i].tip), 1<<i);
            }
      canvasPopup->setActiveItem(0);
      return canvasPopup;
      }

//---------------------------------------------------------
//   canvasPopup
//---------------------------------------------------------

void Canvas::canvasPopup(int n)
      {
      setTool(n);
      emit toolChanged(n);
      }


