~ubuntu-branches/ubuntu/trusty/muse/trusty

« back to all changes in this revision

Viewing changes to muse/widgets/canvas.cpp

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2013-08-28 16:25:57 UTC
  • mfrom: (1.1.16)
  • Revision ID: package-import@ubuntu.com-20130828162557-27ulrksfvm64td50
Tags: 2.1.2-1
* New upstream bugfix release.
* Refresh patches.
* Fix doc links.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
//  Linux Music Editor
4
4
//    $Id: canvas.cpp,v 1.10.2.17 2009/05/03 04:14:01 terminator356 Exp $
5
5
//  (C) Copyright 1999 Werner Schweer (ws@seh.de)
6
 
//  Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
 
6
//  Additions, modifications (C) Copyright 2011-2013 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
7
7
//
8
8
//  This program is free software; you can redistribute it and/or
9
9
//  modify it under the terms of the GNU General Public License
22
22
//=========================================================
23
23
 
24
24
#include <stdio.h>
 
25
#include <math.h>
25
26
 
26
27
#include "canvas.h"
27
28
 
28
29
#include <QApplication>
 
30
#include <QDesktopWidget>
29
31
#include <QMenu>
30
32
#include <QPainter>
31
33
#include <QCursor>
33
35
#include <QKeyEvent>
34
36
#include <QMouseEvent>
35
37
#include <QWheelEvent>
 
38
#include <QRect>
36
39
 
37
40
#include <vector>
38
41
 
 
42
#include "gconfig.h"
39
43
#include "song.h"
40
44
#include "event.h"
41
45
#include "citem.h"
43
47
#include "../marker/marker.h"
44
48
#include "part.h"
45
49
#include "fastlog.h"
 
50
#include "menutitleitem.h"
 
51
#include "shortcuts.h"
46
52
 
47
53
#define ABS(x)  ((x) < 0) ? -(x) : (x)
48
54
 
68
74
      hscrollDir = HSCROLL_NONE;
69
75
      vscrollDir = VSCROLL_NONE;
70
76
      scrollTimer=NULL;
 
77
      ignore_mouse_move = false;
71
78
      
72
 
      scrollSpeed=10;    // hardcoded scroll jump
 
79
      scrollSpeed=30;    // hardcoded scroll jump
73
80
 
74
81
      drag    = DRAG_OFF;
75
82
      _tool   = PointerTool;
79
86
      curPart = NULL;
80
87
      curPartId = -1;
81
88
      curItem = NULL;
 
89
      newCItem = NULL;
82
90
      connect(MusEGlobal::song, SIGNAL(posChanged(int, unsigned, bool)), this, SLOT(setPos(int, unsigned, bool)));
83
91
      }
84
92
 
85
93
Canvas::~Canvas()
86
94
{
87
95
  items.clearDelete();
 
96
 
 
97
  if(newCItem)
 
98
  {
 
99
    if(newCItem->event().empty() && newCItem->part()) // Was it a new part, with no event?
 
100
      delete newCItem->part();
 
101
    delete newCItem;
 
102
  }
88
103
}
89
104
 
90
105
//---------------------------------------------------------
164
179
//---------------------------------------------------------
165
180
 
166
181
void Canvas::draw(QPainter& p, const QRect& rect)
167
 
      {
 
182
{
168
183
//      printf("draw canvas %x virt %d\n", this, virt());
169
184
 
170
185
      int x = rect.x();
175
190
 
176
191
      std::vector<CItem*> list1;
177
192
      std::vector<CItem*> list2;
178
 
      //std::vector<CItem*> list3;
179
193
      std::vector<CItem*> list4;
180
194
 
181
195
      if (virt()) {
186
200
            //---------------------------------------------------
187
201
 
188
202
            iCItem to(items.lower_bound(x2));
189
 
            
190
 
            /*
191
 
            // Draw items from other parts behind all others.
192
 
            // Only for items with events (not arranger parts).
193
 
            for(iCItem i = items.begin(); i != to; ++i)
194
 
            { 
195
 
              CItem* ci = i->second;
196
 
              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
197
 
              ci->part()->hasHiddenEvents();
198
 
              if(!ci->event().empty() && ci->part() != curPart)
199
 
                drawItem(p, ci, rect);
200
 
            }
201
 
                
202
 
            // Draw unselected parts behind selected.
203
 
            for (iCItem i = items.begin(); i != to; ++i) 
204
 
            {
205
 
                  CItem* ci = i->second;
206
 
                  if((!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
207
 
                     && !(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))  // p4.0.29 
208
 
                  {
209
 
                        drawItem(p, ci, rect);
210
 
                  }      
211
 
            }
212
 
            
213
 
            // Draw selected parts in front of unselected.
214
 
            for (iCItem i = items.begin(); i != to; ++i) 
215
 
            {
216
 
                CItem* ci = i->second;
217
 
                if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
218
 
                //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) 
219
 
                //   || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))
220
 
                {
221
 
                      drawItem(p, ci, rect);
222
 
                }      
223
 
            }  
224
 
            */
225
 
            
226
 
            // p4.0.29
227
203
            for(iCItem i = items.begin(); i != to; ++i)
228
204
            { 
229
205
              CItem* ci = i->second;
240
216
                // Draw selected parts in front of all others.
241
217
                if(ci->isSelected()) 
242
218
                  list4.push_back(ci);
243
 
                // Draw clone parts, and parts with hidden events, in front of others all except selected.
244
 
                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))
245
 
                // Draw clone parts in front of others all except selected.
246
 
                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1))
247
 
                //  list3.push_back(ci);
248
219
                else  
249
220
                  // Draw unselected parts.
250
221
                  list2.push_back(ci);
257
228
            sz = list2.size();
258
229
            for(i = 0; i != sz; ++i) 
259
230
              drawItem(p, list2[i], rect);
260
 
            //sz = list3.size();
261
 
            //for(i = 0; i != sz; ++i) 
262
 
            //  drawItem(p, list3[i], rect);
263
231
            sz = list4.size();
264
232
            for(i = 0; i != sz; ++i) 
265
233
              drawItem(p, list4[i], rect);
266
234
            
 
235
            // Draw items being moved, a special way in their original location.
267
236
            to = moving.lower_bound(x2);
268
237
            for (iCItem i = moving.begin(); i != to; ++i) 
269
 
            {
270
238
                  drawItem(p, i->second, rect);
271
 
            }
272
239
 
 
240
            // Draw special top item for new recordings etc.
273
241
            drawTopItem(p,rect);
274
242
 
 
243
            // Draw special new item for first-time placement.
 
244
            // It is not in the item list yet. It will be added when mouse released.
 
245
            if(newCItem)
 
246
              drawItem(p, newCItem, rect);
275
247
      }
276
248
      else {  
277
249
            p.save();
308
280
                  y = 0;
309
281
            x2 = x + w;
310
282
 
311
 
            drawCanvas(p, QRect(x, y, w, h));
 
283
            QRect new_rect(x, y, w, h);
 
284
            drawCanvas(p, new_rect);
312
285
            p.restore();
313
286
 
314
287
            //---------------------------------------------------
315
288
            // draw Canvas Items
316
289
            //---------------------------------------------------
317
290
            
318
 
            /*
319
 
            // Draw items from other parts behind all others.
320
 
            // Only for items with events (not arranger parts).
321
 
            for(iCItem i = items.begin(); i != items.end(); ++i)
322
 
            { 
323
 
              CItem* ci = i->second;
324
 
              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
325
 
              ci->part()->hasHiddenEvents();
326
 
              if(!ci->event().empty() && ci->part() != curPart)
327
 
                drawItem(p, ci, rect);
328
 
            }
329
 
                
330
 
            // Draw unselected parts behind selected.
331
 
            for (iCItem i = items.begin(); i != items.end(); ++i) {
332
 
                  CItem* ci = i->second;
333
 
                  if(!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
334
 
                    {
335
 
                        drawItem(p, ci, rect);
336
 
                    }      
337
 
                  }
338
 
            
339
 
            // Draw selected parts in front of unselected.
340
 
            for (iCItem i = items.begin(); i != items.end(); ++i) {
341
 
                  CItem* ci = i->second;
342
 
                  if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
343
 
                  //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) 
344
 
                  //   || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))
345
 
                  {    
346
 
                      drawItem(p, ci, rect);
347
 
                  }    
348
 
                } 
349
 
            */
350
 
            
351
 
            // p4.0.29
352
291
            for(iCItem i = items.begin(); i != items.end(); ++i)
353
292
            { 
354
293
              CItem* ci = i->second;
365
304
                // Draw selected parts in front of all others.
366
305
                if(ci->isSelected()) 
367
306
                  list4.push_back(ci);
368
 
                // Draw clone parts, and parts with hidden events, in front of others all except selected.
369
 
                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))
370
 
                // Draw clone parts in front of others all except selected.
371
 
                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1))
372
 
                //  list3.push_back(ci);
373
307
                else  
374
308
                  // Draw unselected parts.
375
309
                  list2.push_back(ci);
382
316
            sz = list2.size();
383
317
            for(i = 0; i != sz; ++i) 
384
318
              drawItem(p, list2[i], rect);
385
 
            //sz = list3.size();
386
 
            //for(i = 0; i != sz; ++i) 
387
 
            //  drawItem(p, list3[i], rect);
388
319
            sz = list4.size();
389
320
            for(i = 0; i != sz; ++i) 
390
321
              drawItem(p, list4[i], rect);
391
 
            
 
322
 
 
323
            // Draw items being moved, a special way in their original location.
392
324
            for (iCItem i = moving.begin(); i != moving.end(); ++i) 
393
 
                  {
394
325
                        drawItem(p, i->second, rect);
395
 
                  }
396
 
            drawTopItem(p, QRect(x,y,w,h));
 
326
            
 
327
            // Draw special top item for new recordings etc.
 
328
            drawTopItem(p, new_rect);
 
329
 
 
330
            // Draw special new item for first-time placement.
 
331
            // It is not in the item list yet. It will be added when mouse released.
 
332
            if(newCItem)
 
333
              drawItem(p, newCItem, rect);
 
334
            
397
335
            p.save();
398
336
            setPainter(p);
399
337
      }
407
345
      p.setWorldMatrixEnabled(false);
408
346
      
409
347
      int my = mapy(y);
410
 
      //int y2 = y + h;
411
348
      int my2 = mapy(y + h);
412
349
      MusECore::MarkerList* marker = MusEGlobal::song->marker();
413
350
      for (MusECore::iMarker m = marker->begin(); m != marker->end(); ++m) {
414
351
            int xp = m->second.tick();
415
352
            if (xp >= x && xp < x+w) {
416
353
                  p.setPen(Qt::green);
417
 
                  //p.drawLine(xp, y, xp, y2);
418
354
                  p.drawLine(mapx(xp), my, mapx(xp), my2);
419
355
                  }
420
356
            }
426
362
      p.setPen(Qt::blue);
427
363
      int mx;
428
364
      if (pos[1] >= unsigned(x) && pos[1] < unsigned(x2)) {
429
 
            //p.drawLine(pos[1], y, pos[1], y2);
430
365
            mx = mapx(pos[1]);
431
366
            p.drawLine(mx, my, mx, my2);
432
367
            }
433
368
      if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) {
434
 
            //p.drawLine(pos[2], y, pos[2], y2);
435
369
            mx = mapx(pos[2]);
436
370
            p.drawLine(mx, my, mx, my2);
437
371
            }
438
372
      p.setPen(Qt::red);
439
373
      if (pos[0] >= unsigned(x) && pos[0] < unsigned(x2)) {
440
 
            //p.drawLine(pos[0], y, pos[0], y2);
441
374
            mx = mapx(pos[0]);
442
375
            p.drawLine(mx, my, mx, my2);
443
376
            }
444
377
      
 
378
      if(drag == DRAG_ZOOM)
 
379
        p.drawPixmap(mapFromGlobal(global_start), *zoomAtIcon);
 
380
      
445
381
      //p.restore();
446
382
      //p.setWorldMatrixEnabled(true);
447
383
      p.setWorldMatrixEnabled(wmtxen);
457
393
            }
458
394
      
459
395
      //---------------------------------------------------
460
 
      //    draw moving items
 
396
      //    draw outlines of potential drop places of moving items
461
397
      //---------------------------------------------------
462
398
      
463
399
      if(virt()) 
472
408
          drawMoving(p, i->second, rect);
473
409
        setPainter(p);
474
410
      }
475
 
      }
 
411
}
476
412
 
477
413
#define WHEEL_STEPSIZE 40
478
414
#define WHEEL_DELTA   120
490
426
    if (shift) { // scroll horizontally
491
427
        int delta       = -ev->delta() / WHEEL_DELTA;
492
428
        int xpixelscale = 5*MusECore::fast_log10(rmapxDev(1));
493
 
 
494
429
        if (xpixelscale <= 0)
495
430
              xpixelscale = 1;
496
 
 
497
431
        int scrollstep = WHEEL_STEPSIZE * (delta);
498
 
        ///if (ev->state() == Qt::ShiftModifier)
499
 
  //      if (((QInputEvent*)ev)->modifiers() == Qt::ShiftModifier)
500
432
        scrollstep = scrollstep / 10;
501
 
 
502
433
        int newXpos = xpos + xpixelscale * scrollstep;
503
 
 
504
434
        if (newXpos < 0)
505
435
              newXpos = 0;
506
 
 
507
 
        //setYPos(newYpos);
508
436
        emit horizontalScroll((unsigned)newXpos);
509
437
 
510
438
    } else if (ctrl) {  // zoom horizontally
511
 
      emit horizontalZoom(ev->delta()>0, ev->x());
 
439
      emit horizontalZoom(ev->delta()>0, ev->globalPos());
512
440
    } else { // scroll vertically
513
441
        int delta       = ev->delta() / WHEEL_DELTA;
514
442
        int ypixelscale = rmapyDev(1);
515
 
 
516
443
        if (ypixelscale <= 0)
517
444
              ypixelscale = 1;
518
 
 
519
445
        int scrollstep = WHEEL_STEPSIZE * (-delta);
520
 
        ///if (ev->state() == Qt::ShiftModifier)
521
 
  //      if (((QInputEvent*)ev)->modifiers() == Qt::ShiftModifier)
522
446
        scrollstep = scrollstep / 2;
523
 
 
524
447
        int newYpos = ypos + ypixelscale * scrollstep;
525
 
 
526
448
        if (newYpos < 0)
527
449
              newYpos = 0;
528
 
 
529
 
        //setYPos(newYpos);
530
450
        emit verticalScroll((unsigned)newYpos);
531
 
 
532
451
    }
533
 
 
534
452
}
535
453
 
536
454
void Canvas::redirectedWheelEvent(QWheelEvent* ev)
562
480
//    copy selection-List to moving-List
563
481
//---------------------------------------------------------
564
482
 
565
 
void Canvas::startMoving(const QPoint& pos, DragType)
 
483
void Canvas::startMoving(const QPoint& pos, DragType, bool rasterize)
566
484
      {
567
485
      for (iCItem i = items.begin(); i != items.end(); ++i) {
568
486
            if (i->second->isSelected()) {
570
488
                  moving.add(i->second);
571
489
                  }
572
490
            }
573
 
      moveItems(pos, 0);
 
491
      moveItems(pos, 0, rasterize);
574
492
      }
575
493
 
576
494
//---------------------------------------------------------
580
498
//          2     move only vertical
581
499
//---------------------------------------------------------
582
500
 
583
 
void Canvas::moveItems(const QPoint& pos, int dir = 0, bool rasterize)
 
501
void Canvas::moveItems(const QPoint& pos, int dir, bool rasterize)
584
502
      {
585
 
      int dp;
586
 
      if(rasterize)
587
 
        dp = y2pitch(pos.y()) - y2pitch(start.y());
588
 
      else  
589
 
        dp = pos.y() - start.y();
 
503
      int dp = y2pitch(pos.y()) - y2pitch(start.y());
590
504
      int dx = pos.x() - start.x();
591
505
      if (dir == 1)
592
506
            dp = 0;
598
512
            int nx = x + dx;
599
513
            int ny;
600
514
            QPoint mp;
 
515
            ny = pitch2y(y2pitch(y) + dp);
601
516
            if(rasterize)
602
 
            {
603
 
              ny = pitch2y(y2pitch(y) + dp);
604
517
              mp = raster(QPoint(nx, ny));
605
 
            }  
606
 
            else  
607
 
            {  
608
 
              ny = y + dp;
 
518
            else
609
519
              mp = QPoint(nx, ny);
610
 
            }  
 
520
            
611
521
            if (i->second->mp() != mp) {
612
522
                  i->second->setMp(mp);
613
523
                  itemMoved(i->second, mp);
626
536
      }
627
537
 
628
538
//---------------------------------------------------------
 
539
//   viewKeyReleaseEvent
 
540
//---------------------------------------------------------
 
541
 
 
542
void Canvas::viewKeyReleaseEvent(QKeyEvent* event)
 
543
      {
 
544
      keyRelease(event);
 
545
      }
 
546
 
 
547
//---------------------------------------------------------
629
548
//   viewMousePressEvent
630
549
//---------------------------------------------------------
631
550
 
634
553
      if (!mousePress(event))
635
554
          return;
636
555
 
637
 
      ///keyState = event->state();
638
 
      keyState = ((QInputEvent*)event)->modifiers();
 
556
      keyState = event->modifiers();
639
557
      button = event->button();
640
 
 
641
558
      //printf("viewMousePressEvent buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());
642
559
      
643
560
      // special events if right button is clicked while operations
644
561
      // like moving or drawing lasso is performed.
645
 
      ///if (event->stateAfter() & Qt::RightButton) {
646
 
      if (event->buttons() & Qt::RightButton & ~(event->button())) {
 
562
      if (event->buttons() & Qt::RightButton & ~(button)) {
647
563
          //printf("viewMousePressEvent special buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());
648
564
          switch (drag) {
649
565
              case DRAG_LASSO:
660
576
      }
661
577
 
662
578
      // ignore event if (another) button is already active:
663
 
      ///if (keyState & (Qt::LeftButton|Qt::RightButton|Qt::MidButton)) {
664
 
      if (event->buttons() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(event->button())) {
 
579
      if (event->buttons() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(button)) {
665
580
            //printf("viewMousePressEvent ignoring buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());
666
581
            return;
667
582
            }
 
583
            
668
584
      bool alt        = keyState & Qt::AltModifier;
669
585
      bool ctrl       = keyState & Qt::ControlModifier;
 
586
      
670
587
      start           = event->pos();
671
 
 
 
588
      ev_pos          = start;
 
589
      global_start    = event->globalPos();
 
590
      ev_global_pos   = global_start;
 
591
      
672
592
      //---------------------------------------------------
673
593
      //    set curItem to item mouse is pointing
674
594
      //    (if any)
687
607
                  int w = rmapxDev(box.width());
688
608
                  int h = rmapyDev(box.height());
689
609
                  QRect r(x, y, w, h);
690
 
                  ///r.moveBy(i->second->pos().x(), i->second->pos().y());
691
610
                  r.translate(i->second->pos().x(), i->second->pos().y());
692
611
                  if (r.contains(start)) {
693
612
                        if(i->second->isSelected())
707
626
                    curItem = ius->second;
708
627
            }
709
628
 
710
 
      if (curItem && (event->button() == Qt::MidButton)) {
 
629
      if (curItem && (button == Qt::MidButton)) {
711
630
            deleteItem(start); // changed from "start drag" to "delete" by flo93
712
631
            drag = DRAG_DELETE;
713
632
            setCursor();
714
633
            }
715
 
      else if (event->button() == Qt::RightButton) {
 
634
      else if (button == Qt::RightButton) {
716
635
            if (curItem) {
717
 
                  if (ctrl) {
 
636
                  if (ctrl && virt()) {       // Non-virt width is meaningless, such as drums.
718
637
                        drag = DRAG_RESIZE;
719
638
                        setCursor();
720
639
                        int dx = start.x() - curItem->x();
745
664
                        }
746
665
                  }
747
666
            }
748
 
      else if (event->button() == Qt::LeftButton) {
 
667
      else if (button == Qt::LeftButton) {
749
668
            switch (_tool) {
750
669
                  case PointerTool:
751
670
                        if (curItem) {
752
671
                              itemPressed(curItem);
753
 
                              // Changed by T356. Alt is default reserved for moving the whole window in KDE. Changed to Shift-Alt.
754
 
                              // Hmm, nope, shift-alt is also reserved sometimes. Must find a way to bypass, 
755
 
                              //  why make user turn off setting? Left alone for now...
756
 
                              if (ctrl)
 
672
                              // Alt alone is usually reserved for moving a window in X11. Ignore shift + alt.
 
673
                              if (ctrl && !alt)
757
674
                                    drag = DRAG_COPY_START;
758
 
                              else if (alt) {
 
675
                              else if (ctrl && alt) 
759
676
                                    drag = DRAG_CLONE_START;
760
 
                                    }
761
 
                              else
 
677
                              else if (!ctrl && !alt)
762
678
                                    drag = DRAG_MOVE_START;
763
679
                              }
764
680
                        else
774
690
 
775
691
                  case PencilTool:
776
692
                        if (curItem) {
777
 
                              drag = DRAG_RESIZE;
778
 
                              setCursor();
779
 
                              int dx = start.x() - curItem->x();
780
 
                              curItem->setWidth(dx);
781
 
                              start.setX(curItem->x());
 
693
                                if(!virt()) { // Non-virt width is meaningless, such as drums.
 
694
                                  itemPressed(curItem);
 
695
                                  // Alt alone is usually reserved for moving a window in X11. Ignore shift + alt.
 
696
                                  if (ctrl && !alt)
 
697
                                        drag = DRAG_COPY_START;
 
698
                                  else if (ctrl && alt)
 
699
                                        drag = DRAG_CLONE_START;
 
700
                                  else if (!ctrl && !alt)
 
701
                                        drag = DRAG_MOVE_START;
 
702
                                  setCursor();
 
703
                                  break;
 
704
                                }
 
705
                                else {
 
706
                                  drag = DRAG_RESIZE;
 
707
                                  setCursor();
 
708
                                  int dx = start.x() - curItem->x();
 
709
                                  curItem->setWidth(dx);
 
710
                                  start.setX(curItem->x());
 
711
                                }
782
712
                              }
783
713
                        else {
784
714
                              drag = DRAG_NEW;
785
715
                              setCursor();
786
 
                              curItem = newItem(start, event->modifiers());
 
716
                              curItem = newItem(start, keyState);
787
717
                              if (curItem)
788
 
                                    items.add(curItem);
 
718
                                    newCItem = curItem;
789
719
                              else {
790
720
                                    drag = DRAG_OFF;
791
721
                                    setCursor();
798
728
                        redraw();
799
729
                        break;
800
730
 
 
731
                  case PanTool:
 
732
                        {
 
733
                          drag = DRAG_PAN;
 
734
                          setCursor();
 
735
                          if(MusEGlobal::config.borderlessMouse)
 
736
                          {
 
737
                            QRect r = QApplication::desktop()->screenGeometry();
 
738
                            ignore_mouse_move = true;      // Avoid recursion.
 
739
                            QCursor::setPos( QPoint(r.width()/2, r.height()/2) );
 
740
                          }
 
741
                        }
 
742
                        break;
 
743
                        
 
744
                  case ZoomTool:
 
745
                        {
 
746
                          drag = DRAG_ZOOM;
 
747
                          setCursor();
 
748
                          if(MusEGlobal::config.borderlessMouse)
 
749
                          {
 
750
                            QRect r = QApplication::desktop()->screenGeometry();
 
751
                            ignore_mouse_move = true;      // Avoid recursion.
 
752
                            QCursor::setPos( QPoint(r.width()/2, r.height()/2) );
 
753
                          }
 
754
                          // Update the small zoom drawing area
 
755
                          QPoint pt = mapFromGlobal(global_start);
 
756
                          update(pt.x(), pt.y(), zoomIcon->width(), zoomIcon->height());
 
757
                        }
 
758
                        break;
 
759
 
801
760
                  default:
802
761
                        break;
803
762
                  }
807
766
void Canvas::scrollTimerDone()
808
767
{
809
768
      //printf("Canvas::scrollTimerDone drag:%d doScroll:%d\n", drag, doScroll);
810
 
      
811
 
      if (drag != DRAG_OFF && doScroll)
 
769
      if (doScroll && drag != DRAG_OFF && drag != DRAG_ZOOM)
812
770
      {
813
771
        //printf("Canvas::scrollTimerDone drag != DRAG_OFF && doScroll\n");
814
 
        
 
772
        int modifiers = QApplication::keyboardModifiers();
 
773
        bool ctrl  = modifiers & Qt::ControlModifier;
 
774
        bool meta  = modifiers & Qt::MetaModifier;
 
775
        bool alt   = modifiers & Qt::AltModifier;
 
776
        bool right_button = QApplication::mouseButtons() & Qt::RightButton;
 
777
        bool scrollDoResize = ((!ctrl && !right_button) || meta || alt) && virt();  // Non-virt width is meaningless, such as drums.
 
778
        int dx = 0;
 
779
        int dy = 0;
815
780
        bool doHMove = false;
816
781
        bool doVMove = false;
817
 
        int hoff = rmapx(xOffset())+mapx(xorg)-1;
818
 
        int curxpos;
819
782
        switch(hscrollDir)
820
783
        {  
821
784
          case HSCROLL_RIGHT:
822
 
            hoff += scrollSpeed;
823
785
            switch(drag) 
824
786
            {
825
787
              case DRAG_NEW:
833
795
              case DRAG_MOVE:
834
796
              case DRAG_COPY:
835
797
              case DRAG_CLONE:
836
 
                emit horizontalScrollNoLimit(hoff);
 
798
              case DRAG_PAN:
 
799
                emit horizontalScrollNoLimit(xpos + scrollSpeed);
837
800
                canScrollLeft = true;
838
 
                ev_pos.setX(rmapxDev(rmapx(ev_pos.x()) + scrollSpeed));
 
801
                dx = rmapxDev(scrollSpeed);
 
802
                ev_pos.setX(ev_pos.x() + dx);
839
803
                doHMove = true;
840
804
              break;
841
805
              default:  
842
806
                if(canScrollRight)
843
807
                {
844
 
                  curxpos = xpos;
845
 
                  emit horizontalScroll(hoff);
 
808
                  int curxpos = xpos;
 
809
                  emit horizontalScroll(xpos + scrollSpeed);
846
810
                  if(xpos <= curxpos)
847
 
                  {  
848
811
                    canScrollRight = false;
849
 
                  }
850
812
                  else
851
813
                  {
852
814
                    canScrollLeft = true;
853
 
                    ev_pos.setX(rmapxDev(rmapx(ev_pos.x()) + scrollSpeed));
 
815
                    dx = rmapxDev(scrollSpeed);
 
816
                    ev_pos.setX(ev_pos.x() + dx);
854
817
                    doHMove = true;
855
818
                  }  
856
819
                }  
857
 
                else
858
 
                {  
859
 
                }
860
820
              break;
861
821
            }
862
822
          break;  
863
823
          case HSCROLL_LEFT:
864
824
            if(canScrollLeft)
865
825
            {
866
 
              curxpos = xpos;
867
 
              hoff -= scrollSpeed;
868
 
              emit horizontalScroll(hoff);
 
826
              int curxpos = xpos;
 
827
              emit horizontalScroll(xpos - scrollSpeed);
869
828
              if(xpos >= curxpos)
870
 
              {  
871
829
                canScrollLeft = false;
872
 
              }
873
830
              else
874
831
              {
875
832
                canScrollRight = true;
876
 
                ev_pos.setX(rmapxDev(rmapx(ev_pos.x()) - scrollSpeed));
 
833
                dx = -rmapxDev(scrollSpeed);
 
834
                ev_pos.setX(ev_pos.x() + dx);
877
835
                doHMove = true;
878
836
              }
879
837
            }    
880
 
            else
881
 
            {  
882
 
            }
883
838
          break; 
884
839
          default:
885
840
          break;   
886
841
        }
887
 
        int voff = rmapy(yOffset())+mapy(yorg);
888
 
        int curypos;
889
842
        switch(vscrollDir)
890
843
        {
891
844
          case VSCROLL_DOWN:
892
845
            if(canScrollDown)
893
846
            {
894
 
              curypos = ypos;
895
 
              voff += scrollSpeed;
896
 
              emit verticalScroll(voff);
 
847
              int curypos = ypos;
 
848
              emit verticalScroll(ypos + scrollSpeed);
897
849
              if(ypos <= curypos)
898
 
              {  
899
850
                canScrollDown = false;
900
 
              }
901
851
              else
902
852
              {
903
853
                canScrollUp = true;
904
 
                ev_pos.setY(rmapyDev(rmapy(ev_pos.y()) + scrollSpeed));
 
854
                dy = rmapyDev(scrollSpeed);
 
855
                ev_pos.setY(ev_pos.y() + dy);
905
856
                doVMove = true;
906
857
              }
907
858
            }    
908
 
            else
909
 
            {  
910
 
            }
911
859
          break;  
912
860
          case VSCROLL_UP:
913
861
            if(canScrollUp)
914
862
            {
915
 
              curypos = ypos;
916
 
              voff -= scrollSpeed;
917
 
              emit verticalScroll(voff);
 
863
              int curypos = ypos;
 
864
              emit verticalScroll(ypos - scrollSpeed);
918
865
              if(ypos >= curypos)
919
 
              {  
920
866
                canScrollUp = false;
921
 
              }
922
867
              else
923
868
              {
924
869
                canScrollDown = true;
925
 
                ev_pos.setY(rmapyDev(rmapy(ev_pos.y()) - scrollSpeed));
 
870
                dy = -rmapyDev(scrollSpeed);
 
871
                ev_pos.setY(ev_pos.y() + dy);
926
872
                doVMove = true;
927
873
              } 
928
874
            }   
929
 
            else
930
 
            {  
931
 
            }
932
875
          break;
933
876
          default:
934
877
          break;
965
908
                lasso = QRect(start.x(), start.y(), dist.x(), dist.y());
966
909
                redraw();
967
910
                break;
 
911
 
968
912
          case DRAG_NEW:
 
913
                if(newCItem)
 
914
                {
 
915
                  if((doHMove && !scrollDoResize) || doVMove)
 
916
                  {
 
917
                    int nx = newCItem->x();
 
918
                    int ny = newCItem->y();
 
919
                    if(doHMove && !scrollDoResize)
 
920
                      nx += dx;
 
921
                    if(nx < 0)
 
922
                      nx = 0;
 
923
                    if(doVMove)
 
924
                      ny += dy;
 
925
                    if(ny < 0)
 
926
                      ny = 0;
 
927
                    newCItem->move(QPoint(nx, ny));
 
928
                  }
 
929
                  if(scrollDoResize && doHMove)
 
930
                  {
 
931
                    int w = ev_pos.x() - newCItem->x();
 
932
                    if(w < 1)
 
933
                      w = 1;
 
934
                    newCItem->setWidth(w);
 
935
                  }
 
936
                  redraw();
 
937
                }
 
938
                break;
 
939
                
969
940
          case DRAG_RESIZE:
970
 
                if (dist.x()) {
971
 
                      if (dist.x() < 1)
972
 
                            curItem->setWidth(1);
973
 
                      else
974
 
                            curItem->setWidth(dist.x());
 
941
                if (doHMove) {
 
942
                      int w = ev_pos.x() - curItem->x();
 
943
                      if(w < 1)
 
944
                        w = 1;
 
945
                      curItem->setWidth(w);
975
946
                      redraw();
976
947
                      }
977
948
                break;
980
951
        }
981
952
        //printf("Canvas::scrollTimerDone starting scrollTimer: Currently active?%d\n", scrollTimer->isActive());
982
953
        
983
 
        // p3.3.43 Make sure to yield to other events (for up to 3 seconds), otherwise other events 
984
 
        //  take a long time to reach us, causing scrolling to take a painfully long time to stop.
985
 
        // FIXME: Didn't help at all.
986
 
        //qApp->processEvents();
987
 
        // No, try up to 100 ms for each yield.
988
 
        //qApp->processEvents(100);
989
 
        //
990
 
        //scrollTimer->start( 40, TRUE ); // X ms single-shot timer
991
 
        // OK, changing the timeout from 40 to 80 helped.
992
 
        //scrollTimer->start( 80, TRUE ); // X ms single-shot timer
 
954
        // Make sure to yield to other events, otherwise other events take a long time to reach us,
 
955
        //  causing scrolling to take a painfully long time to stop. Try up to 100 ms for each yield: 
 
956
        //qApp->processEvents(100);       // FIXME: Didn't help at all.
993
957
        scrollTimer->setSingleShot(true);
994
 
        scrollTimer->start(80);
 
958
        scrollTimer->start(80);           // OK, setting a timeout 80 helped.
995
959
      }
996
960
      else 
997
961
      {
998
962
          //printf("Canvas::scrollTimerDone !(drag != DRAG_OFF && doScroll) deleting scrollTimer\n");
999
 
          
1000
963
          delete scrollTimer;
1001
964
          scrollTimer=NULL;
1002
965
      }
1003
966
}
1004
967
 
1005
 
 
1006
968
//---------------------------------------------------------
1007
969
//   viewMouseMoveEvent
1008
970
//---------------------------------------------------------
1009
971
 
1010
972
void Canvas::viewMouseMoveEvent(QMouseEvent* event)
1011
973
      {
 
974
      if(ignore_mouse_move)
 
975
      {
 
976
        ignore_mouse_move = false;
 
977
        event->accept();
 
978
        return;
 
979
      }
 
980
      //fprintf(stderr, "xpos=%d xorg=%d xmag=%d event->x=%d ->gx:%d mapx(xorg)=%d rmapx0=%d xOffset=%d rmapx(xOffset()=%d\n",
 
981
      //                 xpos,   xorg,   xmag,   event->x(), event->globalX(), mapx(xorg), rmapx(0), xOffset(), rmapx(xOffset()));
 
982
      //fprintf(stderr, "ypos=%d yorg=%d ymag=%d event->y=%d ->gy:%d mapy(yorg)=%d rmapy0=%d yOffset=%d rmapy(yOffset()=%d\n",
 
983
      //                 ypos,   yorg,   ymag,   event->y(), event->globalY(), mapy(yorg), rmapy(0), yOffset(), rmapy(yOffset()));
 
984
 
 
985
      QRect  screen_rect    = QApplication::desktop()->screenGeometry();
 
986
      QPoint screen_center  = QPoint(screen_rect.width()/2, screen_rect.height()/2);
 
987
      QPoint glob_dist      = event->globalPos() - ev_global_pos;
 
988
      QPoint glob_zoom_dist = MusEGlobal::config.borderlessMouse ? (event->globalPos() - screen_center) : glob_dist;
 
989
      QPoint last_dist      = event->pos() - ev_pos;
1012
990
      
1013
 
      ev_pos  = event->pos();
1014
 
      QPoint dist = ev_pos - start;
1015
 
      int ax      = ABS(rmapx(dist.x()));
1016
 
      int ay      = ABS(rmapy(dist.y()));
1017
 
      bool moving = (ax >= 2) || (ay > 2);
 
991
      ev_pos     = event->pos();
 
992
      QPoint dist  = ev_pos - start;
 
993
      int ax       = ABS(rmapx(dist.x()));
 
994
      int ay       = ABS(rmapy(dist.y()));
 
995
      bool moving  = (ax >= 2) || (ay > 2);
 
996
      int modifiers = event->modifiers();
 
997
      bool ctrl  = modifiers & Qt::ControlModifier;
 
998
      bool shift = modifiers & Qt::ShiftModifier;
 
999
      bool meta  = modifiers & Qt::MetaModifier;
 
1000
      bool alt   = modifiers & Qt::AltModifier;
 
1001
      bool right_button = event->buttons() & Qt::RightButton;
1018
1002
 
1019
1003
      // set scrolling variables: doScroll, scrollRight
1020
 
      if (drag != DRAG_OFF) {
1021
 
            
1022
 
                
 
1004
      // No auto scroll in zoom mode or normal pan mode.
 
1005
      if (drag != DRAG_OFF && drag != DRAG_ZOOM && (drag != DRAG_PAN || !MusEGlobal::config.borderlessMouse)) {  
1023
1006
            int ex = rmapx(event->x())+mapx(0);
1024
 
            if(ex < 40 && canScrollLeft)
1025
 
              hscrollDir = HSCROLL_LEFT;
 
1007
            if(ex < 15 && (canScrollLeft || drag == DRAG_PAN))
 
1008
              hscrollDir = (drag == DRAG_PAN ? HSCROLL_RIGHT : HSCROLL_LEFT);
1026
1009
            else  
1027
 
            if(ex > (width() - 40))
 
1010
            if(ex > (width() - 15))
1028
1011
              switch(drag) 
1029
1012
              {
1030
1013
                case DRAG_NEW:
1038
1021
                case DRAG_MOVE:
1039
1022
                case DRAG_COPY:
1040
1023
                case DRAG_CLONE:
1041
 
                    hscrollDir = HSCROLL_RIGHT;
 
1024
                case DRAG_PAN:
 
1025
                    hscrollDir = (drag == DRAG_PAN ? HSCROLL_LEFT : HSCROLL_RIGHT);
1042
1026
                break;
1043
1027
                default:
1044
1028
                  if(canScrollRight)
1045
 
                    hscrollDir = HSCROLL_RIGHT;
 
1029
                    hscrollDir = (drag == DRAG_PAN ? HSCROLL_LEFT : HSCROLL_RIGHT);
1046
1030
                  else  
1047
1031
                    hscrollDir = HSCROLL_NONE;
1048
1032
                break;
1049
1033
              }
1050
1034
            else  
1051
1035
              hscrollDir = HSCROLL_NONE;
 
1036
            
1052
1037
            int ey = rmapy(event->y())+mapy(0);
1053
 
            if(ey < 15 && canScrollUp)
1054
 
              vscrollDir = VSCROLL_UP;
 
1038
            if(ey < 15 && (canScrollUp || drag == DRAG_PAN))
 
1039
              vscrollDir = (drag == DRAG_PAN ? VSCROLL_DOWN : VSCROLL_UP);
1055
1040
            else  
1056
 
            if(ey > (height() - 15) && canScrollDown)
1057
 
              vscrollDir = VSCROLL_DOWN;
 
1041
            if(ey > (height() - 15) && (canScrollDown || drag == DRAG_PAN))
 
1042
              vscrollDir = (drag == DRAG_PAN ? VSCROLL_UP : VSCROLL_DOWN);
1058
1043
            else  
1059
1044
              vscrollDir = VSCROLL_NONE;
 
1045
 
1060
1046
            if(hscrollDir != HSCROLL_NONE || vscrollDir != VSCROLL_NONE)
1061
1047
            {
1062
1048
              doScroll=true;
1064
1050
              {
1065
1051
                  scrollTimer= new QTimer(this);
1066
1052
                  connect( scrollTimer, SIGNAL(timeout()), SLOT(scrollTimerDone()) );
1067
 
                  //scrollTimer->start( 0, TRUE ); // single-shot timer
1068
1053
                  scrollTimer->setSingleShot(true); // single-shot timer
1069
1054
                  scrollTimer->start(0); 
1070
1055
              }
1090
1075
                  drag = DRAG_LASSO;
1091
1076
                  setCursor();
1092
1077
                  // proceed with DRAG_LASSO:
1093
 
 
1094
1078
            case DRAG_LASSO:
1095
1079
                  {
1096
1080
                  lasso = QRect(start.x(), start.y(), dist.x(), dist.y());
1097
 
 
1098
1081
                  // printf("xorg=%d xmag=%d event->x=%d, mapx(xorg)=%d rmapx0=%d xOffset=%d rmapx(xOffset()=%d\n",
1099
1082
                  //         xorg, xmag, event->x(),mapx(xorg), rmapx(0), xOffset(),rmapx(xOffset()));
1100
 
 
1101
1083
                  }
1102
1084
                  redraw();
1103
1085
                  break;
1149
1131
                  else
1150
1132
                        dt = MOVE_CLONE;
1151
1133
                  
1152
 
                  startMoving(ev_pos, dt);
 
1134
                  startMoving(ev_pos, dt, !(keyState & Qt::ShiftModifier));
1153
1135
                  break;
1154
1136
 
1155
1137
            case DRAG_MOVE:
1156
1138
            case DRAG_COPY:
1157
1139
            case DRAG_CLONE:
1158
 
      
1159
1140
                  if(!scrollTimer)
1160
 
                    moveItems(ev_pos, 0);
 
1141
                    moveItems(ev_pos, 0, !shift);
1161
1142
                  break;
1162
1143
 
1163
1144
            case DRAGX_MOVE:
1164
1145
            case DRAGX_COPY:
1165
1146
            case DRAGX_CLONE:
1166
1147
                  if(!scrollTimer)
1167
 
                    moveItems(ev_pos, 1);
 
1148
                    moveItems(ev_pos, 1, false);
1168
1149
                  break;
1169
1150
 
1170
1151
            case DRAGY_MOVE:
1171
1152
            case DRAGY_COPY:
1172
1153
            case DRAGY_CLONE:
1173
1154
                  if(!scrollTimer)
1174
 
                    moveItems(ev_pos, 2);
 
1155
                    moveItems(ev_pos, 2, false);
1175
1156
                  break;
1176
1157
 
1177
1158
            case DRAG_NEW:
 
1159
                  if(newCItem) {
 
1160
                    if (last_dist.x()) {
 
1161
                          if(((ctrl || right_button) && !meta && !alt) || !virt())  // Non-virt width is meaningless, such as drums.
 
1162
                          {
 
1163
                            int nx = ev_pos.x() - newCItem->width();  // Keep the cursor at the right edge.
 
1164
                            if(nx < 0)
 
1165
                              nx = 0;
 
1166
                            if(!shift)
 
1167
                            {
 
1168
                              nx = raster(QPoint(nx, 0)).x();  // 0 is dummy, we want only x
 
1169
                              if(nx < 0)
 
1170
                                nx = 0;
 
1171
                            }
 
1172
                            newCItem->move(QPoint(nx, newCItem->y()));
 
1173
                          }
 
1174
                          else
 
1175
                          {
 
1176
                            int w = ev_pos.x() - newCItem->x();
 
1177
                            if(w < 1)
 
1178
                              w = 1;
 
1179
                            newCItem->setWidth(w);
 
1180
                          }
 
1181
                          }
 
1182
                    if (last_dist.y()) {
 
1183
                          int x = newCItem->x();
 
1184
                          int y = ev_pos.y();
 
1185
                          int ny = pitch2y(y2pitch(y)) - yItemOffset();
 
1186
                          QPoint pt = QPoint(x, ny);
 
1187
                          newCItem->move(pt);
 
1188
                          newCItem->setHeight(y2height(y));
 
1189
                          itemMoved(newCItem, pt);
 
1190
                          }
 
1191
                    if (last_dist.x() || last_dist.y())
 
1192
                      redraw();
 
1193
                  }
 
1194
                  break;
 
1195
 
1178
1196
            case DRAG_RESIZE:
1179
 
                  if (dist.x()) {
1180
 
                        if (dist.x() < 1)
1181
 
                              curItem->setWidth(1);
1182
 
                        else
1183
 
                              curItem->setWidth(dist.x());
 
1197
                  if (last_dist.x()) {
 
1198
                        int w = ev_pos.x() - curItem->x();
 
1199
                        if(w < 1)
 
1200
                          w = 1;
 
1201
                        curItem->setWidth(w);
1184
1202
                        redraw();
1185
1203
                        }
1186
1204
                  break;
 
1205
                  
1187
1206
            case DRAG_DELETE:
1188
1207
                  deleteItem(ev_pos);
1189
1208
                  break;
1190
1209
 
 
1210
            case DRAG_PAN:
 
1211
                  {
 
1212
                    bool changed = false;
 
1213
                    if((!shift || (shift && ctrl)) && glob_zoom_dist.x() != 0 && (!doScroll || hscrollDir == HSCROLL_NONE))  // Don't interfere if auto-scrolling
 
1214
                    {
 
1215
                      emit horizontalScroll(xpos - glob_zoom_dist.x());
 
1216
                      changed = true;
 
1217
                    }
 
1218
                    if((!ctrl || (shift && ctrl)) && glob_zoom_dist.y() != 0 && (!doScroll || vscrollDir == VSCROLL_NONE))   // Don't interfere if auto-scrolling
 
1219
                    {
 
1220
                      emit verticalScroll(ypos - glob_zoom_dist.y());
 
1221
                      changed = true;
 
1222
                    }
 
1223
                    if(MusEGlobal::config.borderlessMouse && changed)
 
1224
                    {
 
1225
                      ignore_mouse_move = true;      // Avoid recursion.
 
1226
                      QCursor::setPos(screen_center);
 
1227
                    }
 
1228
                  }
 
1229
                  break;
 
1230
                  
 
1231
            case DRAG_ZOOM:
 
1232
                  if(glob_zoom_dist.x() != 0)   
 
1233
                      emit horizontalZoom(glob_zoom_dist.x(), global_start);
 
1234
                  //if(glob_zoom_dist.y() != 0)
 
1235
                  //    emit verticalZoom(glob_zoom_dist.y(), global_start);  // TODO
 
1236
                  if(MusEGlobal::config.borderlessMouse && (glob_zoom_dist.x() != 0 || glob_zoom_dist.y() != 0))
 
1237
                  {
 
1238
                    ignore_mouse_move = true;      // Avoid recursion.
 
1239
                    QCursor::setPos(screen_center);
 
1240
                  }
 
1241
                  break;
 
1242
                  
1191
1243
            case DRAG_OFF:
1192
1244
                  break;
1193
1245
            }
1194
 
                  
1195
 
      mouseMove(event);
 
1246
 
 
1247
      ev_global_pos = event->globalPos();
 
1248
 
 
1249
      if(drag != DRAG_ZOOM && (drag != DRAG_PAN || !MusEGlobal::config.borderlessMouse))
 
1250
        mouseMove(event);
1196
1251
      }
1197
1252
 
1198
1253
//---------------------------------------------------------
1200
1255
//---------------------------------------------------------
1201
1256
 
1202
1257
void Canvas::viewMouseReleaseEvent(QMouseEvent* event)
1203
 
      {
 
1258
{
1204
1259
      doScroll = false;
1205
1260
      canScrollLeft = true;
1206
1261
      canScrollRight = true;
1207
1262
      canScrollUp = true;
1208
1263
      canScrollDown = true;
1209
 
      if (event->buttons() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(event->button())) {
 
1264
      if (event->buttons() & (Qt::LeftButton|Qt::RightButton|Qt::MidButton) & ~(event->button())) 
1210
1265
            return;
1211
 
            }
1212
1266
 
1213
1267
      QPoint pos = event->pos();
1214
 
      bool ctrl = ((QInputEvent*)event)->modifiers() & Qt::ControlModifier;
1215
 
      bool shift = ((QInputEvent*)event)->modifiers() & Qt::ShiftModifier;
 
1268
      bool ctrl = event->modifiers() & Qt::ControlModifier;
 
1269
      bool shift = event->modifiers() & Qt::ShiftModifier;
1216
1270
      bool redrawFlag = false;
1217
1271
 
1218
1272
      switch (drag) {
1224
1278
                        curPartId = curPart->sn();
1225
1279
                        curPartChanged();
1226
1280
                        }
1227
 
 
1228
1281
                  if (!ctrl)
1229
1282
                        deselectAll();
1230
 
                        
1231
1283
                  if (!shift) { //Select or deselect only the clicked item
1232
1284
                      selectItem(curItem, !(ctrl && curItem->isSelected()));
1233
1285
                      }
1243
1295
                  itemReleased(curItem, curItem->pos());
1244
1296
                  break;
1245
1297
            case DRAG_COPY:
1246
 
                  endMoveItems(pos, MOVE_COPY, 0);
 
1298
                  endMoveItems(pos, MOVE_COPY, 0, !shift);
1247
1299
                  break;
1248
1300
            case DRAGX_COPY:
1249
 
                  endMoveItems(pos, MOVE_COPY, 1);
 
1301
                  endMoveItems(pos, MOVE_COPY, 1, false);
1250
1302
                  break;
1251
1303
            case DRAGY_COPY:
1252
 
                  endMoveItems(pos, MOVE_COPY, 2);
 
1304
                  endMoveItems(pos, MOVE_COPY, 2, false);
1253
1305
                  break;
1254
1306
            case DRAG_MOVE:
1255
 
                  endMoveItems(pos, MOVE_MOVE, 0);
 
1307
                  endMoveItems(pos, MOVE_MOVE, 0, !shift);
1256
1308
                  break;
1257
1309
            case DRAGX_MOVE:
1258
 
                  endMoveItems(pos, MOVE_MOVE, 1);
 
1310
                  endMoveItems(pos, MOVE_MOVE, 1, false);
1259
1311
                  break;
1260
1312
            case DRAGY_MOVE:
1261
 
                  endMoveItems(pos, MOVE_MOVE, 2);
 
1313
                  endMoveItems(pos, MOVE_MOVE, 2, false);
1262
1314
                  break;
1263
1315
            case DRAG_CLONE:
1264
 
                  endMoveItems(pos, MOVE_CLONE, 0);
 
1316
                  endMoveItems(pos, MOVE_CLONE, 0, !shift);
1265
1317
                  break;
1266
1318
            case DRAGX_CLONE:
1267
 
                  endMoveItems(pos, MOVE_CLONE, 1);
 
1319
                  endMoveItems(pos, MOVE_CLONE, 1, false);
1268
1320
                  break;
1269
1321
            case DRAGY_CLONE:
1270
 
                  endMoveItems(pos, MOVE_CLONE, 2);
 
1322
                  endMoveItems(pos, MOVE_CLONE, 2, false);
1271
1323
                  break;
1272
1324
            case DRAG_OFF:
1273
1325
                  break;
1274
1326
            case DRAG_RESIZE:
1275
 
                  resizeItem(curItem, false, ctrl);
 
1327
                  resizeItem(curItem, shift, ctrl);
1276
1328
                  break;
1277
1329
            case DRAG_NEW:
1278
 
                  newItem(curItem, false);
1279
 
                  redrawFlag = true;
 
1330
                  if(newCItem)
 
1331
                  {
 
1332
                    items.add(newCItem);
 
1333
                    curItem = newCItem;
 
1334
                    newCItem = NULL;
 
1335
                    itemReleased(curItem, curItem->pos());
 
1336
                    newItem(curItem, shift);
 
1337
                    redrawFlag = true;
 
1338
                  }
1280
1339
                  break;
1281
1340
            case DRAG_LASSO_START:
1282
1341
                  lasso.setRect(-1, -1, -1, -1);
1297
1356
 
1298
1357
            case DRAG_DELETE:
1299
1358
                  break;
 
1359
                  
 
1360
            case DRAG_PAN:
 
1361
                  if(MusEGlobal::config.borderlessMouse)
 
1362
                  {
 
1363
                    pos = global_start;
 
1364
                    ignore_mouse_move = true;      // Avoid recursion.
 
1365
                    QCursor::setPos(global_start);
 
1366
                  }
 
1367
                  break;
 
1368
                  
 
1369
            case DRAG_ZOOM:
 
1370
                  if(MusEGlobal::config.borderlessMouse)
 
1371
                  {
 
1372
                    pos = global_start;
 
1373
                    ignore_mouse_move = true;      // Avoid recursion.
 
1374
                    QCursor::setPos(global_start);
 
1375
                  }
 
1376
                  break;
1300
1377
            }
1301
1378
      //printf("Canvas::viewMouseReleaseEvent setting drag to DRAG_OFF\n");
 
1379
 
 
1380
      // Just in case it was somehow forgotten:
 
1381
      if(newCItem)
 
1382
      {
 
1383
        if(newCItem->event().empty() && newCItem->part()) // Was it a new part, with no event?
 
1384
          delete newCItem->part();
 
1385
        delete newCItem;
 
1386
        newCItem = NULL;
 
1387
      }
 
1388
      
 
1389
      if(drag == DRAG_ZOOM) // Update the small zoom drawing area
 
1390
      {
 
1391
        drag = DRAG_OFF;
 
1392
        QPoint pt = mapFromGlobal(global_start);
 
1393
        update(pt.x(), pt.y(), zoomIcon->width(), zoomIcon->height());
 
1394
      }
1302
1395
      
1303
1396
      drag = DRAG_OFF;
1304
1397
      if (redrawFlag)
1305
1398
            redraw();
1306
1399
      setCursor();
1307
1400
      mouseRelease(pos);
1308
 
      }
 
1401
}
1309
1402
 
1310
1403
//---------------------------------------------------------
1311
1404
//   selectLasso
1330
1423
                  int w = rmapxDev(box.width());
1331
1424
                  int h = rmapyDev(box.height());
1332
1425
                  QRect r(x, y, w, h);
1333
 
                  ///r.moveBy(i->second->pos().x(), i->second->pos().y());
1334
1426
                  r.translate(i->second->pos().x(), i->second->pos().y());
1335
1427
                  if (r.intersects(lasso)) {
1336
1428
                        selectItem(i->second, !(toggle && i->second->isSelected()));
1339
1431
                  }
1340
1432
            }
1341
1433
 
1342
 
 
1343
 
 
1344
1434
      if (n) {
1345
1435
            updateSelection();
1346
1436
            redraw();
1385
1475
                  int w = rmapxDev(box.width());
1386
1476
                  int h = rmapyDev(box.height());
1387
1477
                  QRect r(x, y, w, h);
1388
 
                  ///r.moveBy(i->second->pos().x(), i->second->pos().y());
1389
1478
                  r.translate(i->second->pos().x(), i->second->pos().y());
1390
1479
                  if (r.contains(p)) {
1391
1480
                        if (deleteItem(i->second)) {
1431
1520
            case DRAG_MOVE:
1432
1521
            case DRAG_COPY:
1433
1522
            case DRAG_CLONE:
1434
 
                  QWidget::setCursor(QCursor(Qt::SizeAllCursor));
 
1523
                  // Bug in KDE cursor theme? On some distros this cursor is actually another version of a closed hand! From 'net:
 
1524
                  // "It might be a problem in the distribution as Qt uses the cursor that is provided by X.org/xcursor extension with name "size_all".
 
1525
                  //  We fixed this issue by setting the KDE cursor theme to "System theme" "
 
1526
                  QWidget::setCursor(QCursor(Qt::SizeAllCursor));  
1435
1527
                  break;
1436
1528
 
1437
1529
            case DRAG_RESIZE:
1438
1530
                  QWidget::setCursor(QCursor(Qt::SizeHorCursor));
1439
1531
                  break;
1440
1532
 
 
1533
            case DRAG_PAN:
 
1534
                  if(MusEGlobal::config.borderlessMouse)
 
1535
                    QWidget::setCursor(QCursor(Qt::BlankCursor));  // Hide it.
 
1536
                  else
 
1537
                    QWidget::setCursor(QCursor(Qt::ClosedHandCursor));
 
1538
                  break;
 
1539
                  
 
1540
            case DRAG_ZOOM:
 
1541
                  if(MusEGlobal::config.borderlessMouse)
 
1542
                    QWidget::setCursor(QCursor(Qt::BlankCursor));  // Hide it.
 
1543
                  break;
 
1544
                  
1441
1545
            case DRAG_DELETE:
1442
1546
            case DRAG_COPY_START:
1443
1547
            case DRAG_CLONE_START:
1465
1569
                        case AutomationTool:
1466
1570
                              QWidget::setCursor(QCursor(Qt::PointingHandCursor));
1467
1571
                              break;
 
1572
                        case PanTool:
 
1573
                              QWidget::setCursor(QCursor(Qt::OpenHandCursor));
 
1574
                              break;
 
1575
                        case ZoomTool:
 
1576
                              QWidget::setCursor(QCursor(*zoomAtIcon, 0, 0));
 
1577
                              break;
1468
1578
                        default:
1469
1579
                              QWidget::setCursor(QCursor(Qt::ArrowCursor));
1470
1580
                              break;
1483
1593
      }
1484
1594
 
1485
1595
//---------------------------------------------------------
 
1596
//   keyRelease
 
1597
//---------------------------------------------------------
 
1598
 
 
1599
void Canvas::keyRelease(QKeyEvent* event)
 
1600
      {
 
1601
      event->ignore();
 
1602
      }
 
1603
 
 
1604
//---------------------------------------------------------
1486
1605
//   isSingleSelection
1487
1606
//---------------------------------------------------------
1488
1607
 
1507
1626
 
1508
1627
//---------------------------------------------------------
1509
1628
//   genCanvasPopup
 
1629
//   Add the list of available tools to a popup menu
 
1630
//   menu parameter can be NULL meaning create a menu here
1510
1631
//---------------------------------------------------------
1511
1632
 
1512
 
QMenu* Canvas::genCanvasPopup()
 
1633
QMenu* Canvas::genCanvasPopup(QMenu* menu)
1513
1634
      {
1514
1635
      if (canvasTools == 0)
1515
1636
            return 0;
1516
 
      QMenu* canvasPopup = new QMenu(this);
 
1637
      QMenu* r_menu = menu;
 
1638
      if(!r_menu)
 
1639
        r_menu = new QMenu(this);
1517
1640
      QAction* act0 = 0;
1518
1641
 
1519
 
      for (unsigned i = 0; i < 9; ++i) {
 
1642
      r_menu->addAction(new MenuTitleItem(tr("Tools:"), r_menu));
 
1643
      
 
1644
      for (unsigned i = 0; i < gNumberOfTools; ++i) {
1520
1645
            if ((canvasTools & (1 << i))==0)
1521
1646
                  continue;
1522
 
            QAction* act = canvasPopup->addAction(QIcon(**toolList[i].icon), tr(toolList[i].tip));
1523
 
            act->setData(1<<i); // ddskrjo
 
1647
            QAction* act = r_menu->addAction(QIcon(**toolList[i].icon), tr(toolList[i].tip));
 
1648
 
 
1649
            if (MusEGui::toolShortcuts.contains(1 << i)) {
 
1650
                act->setShortcut(MusEGui::shortcuts[MusEGui::toolShortcuts[1 << i]].key);
 
1651
            }
 
1652
            //
 
1653
            act->setData(TOOLS_ID_BASE + i);
 
1654
            act->setCheckable(true);
 
1655
            act->setChecked((1 << i) == _tool);
1524
1656
            if (!act0)
1525
1657
                  act0 = act;
1526
1658
            }
1527
 
      canvasPopup->setActiveAction(act0);
1528
 
      return canvasPopup;
 
1659
      if(!menu)  // Don't interefere with supplied menu's current item
 
1660
        r_menu->setActiveAction(act0);
 
1661
      return r_menu;
1529
1662
      }
1530
1663
 
1531
1664
//---------------------------------------------------------
1534
1667
 
1535
1668
void Canvas::canvasPopup(int n)
1536
1669
      {
1537
 
      setTool(n);
1538
 
      emit toolChanged(n);
 
1670
        if(n >= TOOLS_ID_BASE)
 
1671
        {
 
1672
          n -= TOOLS_ID_BASE;
 
1673
          int t = 1 << n;
 
1674
          setTool(t);
 
1675
          emit toolChanged(t);
 
1676
        }
1539
1677
      }
1540
1678
 
1541
1679
void Canvas::setCurrentPart(MusECore::Part* part)