2
#include "trackviewcommands.h"
12
#include <kglobalsettings.h>
14
#include <kmessagebox.h>
16
#include <kpopupmenu.h>
18
#include <kxmlguiclient.h>
27
#include "trackprint.h"
30
#include <qcombobox.h>
31
#include <qcheckbox.h>
33
#include <stdlib.h> // required for declaration of abs()
35
// LVIFIX: note differences between "old" (in trackview.cpp) and "new" drawing code (in trackprint.cpp):
36
// - erase width around tab column numbers is "as tight as possible", while the cursor is a bit wider,
37
// which leads to minor reverse-video artefacts under the cursor
38
// - starting bars (very thick and thick one) not implemented
39
// - harmonics use a diamond instead of text in the new code
40
// - palm muting uses a small cross instead of text in the new code
42
// Define if both "old" and "new" drawing code must be used at the same time
43
// Undefine to use only the "new" drawing code
44
#undef USE_BOTH_OLD_AND_NEW
45
// #define USE_BOTH_OLD_AND_NEW
47
#ifdef USE_BOTH_OLD_AND_NEW
48
#define VERTSPACE 230 // between top of cell and first line
49
#define VERTLINE 10 // between horizontal tabulature lines
51
#define HORCELL 14 // horizontal size of tab numbers column
52
#define TIMESIGSIZE 14 // horizontal time sig size
53
#define ABBRLENGTH 25 // drum abbreviations horizontal size
55
#define BOTTOMDUR VERTSPACE+VERTLINE*(s+1)
58
#define NORMAL_FONT_FACTOR 0.8
59
#define TIME_SIG_FONT_FACTOR 1.4
60
#define SMALL_CAPTION_FONT_FACTOR 0.7
62
// definitions for the "new" drawing code layout
63
#define TOPSPTB 3 // top space tabbar in ysteptb units
64
#define BOTSPTB 3 // bottom space tabbar in ysteptb units
65
#define ADDSPST 1.5 // additional top space staff in ystepst units
66
#define TOPSPST 7.5 // top space staff in ystepst units
67
#define BOTSPST 1.5 // bottom space staff in ystepst units
68
#define NLINEST 5 // number of staff lines
70
TrackView::TrackView(TabSong *s, KXMLGUIClient *_XMLGUIClient, KCommandHistory *_cmdHist,
72
TSE3::MidiScheduler *_scheduler,
74
QWidget *parent, const char *name): QGridView(parent, name)
76
setFrameStyle(Panel | Sunken);
77
setBackgroundMode(PaletteBase);
81
setFocusPolicy(QWidget::StrongFocus);
83
xmlGUIClient = _XMLGUIClient;
87
setCurrentTrack(s->t.first());
89
normalFont = new QFont(KGlobalSettings::generalFont());
90
if (normalFont->pointSize() == -1) {
91
normalFont->setPixelSize((int) ((double) normalFont->pixelSize() * NORMAL_FONT_FACTOR));
93
normalFont->setPointSizeFloat(normalFont->pointSizeFloat() * NORMAL_FONT_FACTOR);
96
smallCaptionFont = new QFont(*normalFont);
97
if (smallCaptionFont->pointSize() == -1) {
98
smallCaptionFont->setPixelSize((int) ((double) smallCaptionFont->pixelSize() * SMALL_CAPTION_FONT_FACTOR));
100
smallCaptionFont->setPointSizeFloat(smallCaptionFont->pointSizeFloat() * SMALL_CAPTION_FONT_FACTOR);
103
timeSigFont = new QFont(*normalFont);
104
if (timeSigFont->pointSize() == -1) {
105
timeSigFont->setPixelSize((int) ((double) timeSigFont->pixelSize() * TIME_SIG_FONT_FACTOR));
107
timeSigFont->setPointSizeFloat(timeSigFont->pointSizeFloat() * TIME_SIG_FONT_FACTOR);
109
timeSigFont->setBold(TRUE);
118
scheduler = _scheduler;
121
playbackCursor = FALSE;
123
trp = new TrackPrint;
126
trp->pLnBl = QPen(Qt::black, lw);
127
trp->pLnWh = QPen(Qt::white, lw);
129
updateRows(); // depends on trp's font metrics
132
TrackView::~TrackView()
135
delete smallCaptionFont;
140
void TrackView::initFonts(QFont *f4, QFont *f5)
144
trp->initFonts(normalFont, smallCaptionFont, timeSigFont, fetaFont, fetaNrFont);
147
void TrackView::selectTrack(TabTrack *trk)
149
setCurrentTrack(trk);
154
void TrackView::selectBar(uint n)
156
if (n != (uint) curt->xb && n < curt->b.size()) {
157
curt->x = curt->b[n].start;
159
ensureCurrentVisible();
161
emit columnChanged();
166
void TrackView::setCurrentTrack(TabTrack *trk)
169
emit trackChanged(trk);
172
// Set new horizontal zoom level and update display accordingly
173
void TrackView::setZoomLevel(int newZoomLevel)
175
if (newZoomLevel > 0) {
176
zoomLevel = newZoomLevel;
182
void TrackView::zoomIn()
184
setZoomLevel(zoomLevel - 1);
187
void TrackView::zoomOut()
189
setZoomLevel(zoomLevel + 1);
192
// Set zoom level dialog
193
void TrackView::zoomLevelDialog()
198
void TrackView::updateRows()
200
int ch = (int) ((TOPSPTB + curt->string + BOTSPTB) * trp->ysteptb);
201
#ifdef USE_BOTH_OLD_AND_NEW
202
// note: cannot make row height dependent on viewscore without making too many
203
// changes to the "old" drawing code: use fixed height
204
ch += 3 * VERTLINE * 2 + VERTLINE * (curt->string - 1);
205
ch += (int) ((TOPSPST + NLINEST - 1 + BOTSPST) * trp->ystepst);
206
ch += (int) (ADDSPST * trp->ystepst);
208
if (viewscore && fetaFont) {
209
ch += (int) ((TOPSPST + NLINEST - 1 + BOTSPST) * trp->ystepst);
210
ch += (int) (ADDSPST * trp->ystepst);
213
setNumRows(curt->b.size());
214
setMinimumHeight(ch);
216
// cout << "TrackView::updateRows()"
218
// << " nr=" << curt->b.size()
222
void TrackView::repaintCellNumber(int n)
227
void TrackView::repaintCurrentCell()
229
repaintCellNumber(curt->xb);
233
void TrackView::repaintCurrentColumn()
235
//VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2
238
// if (rowYPos(curt->xb, &ycoord)) // GREYFIX - what was it all about?
240
// GREYFIX: some crazy things going here about what coordinate
241
// system to use. I'm totally screwed up trying to figure it out,
242
// until I do, just update whole cell.
244
// repaint(selxcoord, cellHeight() * curt->xb - contentsY(), HORCELL + 1, cellHeight());
246
repaintCell(curt->xb, 0);
247
// emit paneChanged();
250
// Checks is current bar is fully visible, and, if it's not, tries to
251
// do minimal scrolling to ensure the full visibility
252
void TrackView::ensureCurrentVisible()
254
/* int ch = cellHeight();
256
if ((curt->xb + 1) * ch > yOffset() + height())
257
setYOffset((curt->xb + 1) * ch - height());
258
else if (curt->xb * ch < yOffset())
259
setYOffset(curt->xb * ch);
261
ensureCellVisible(curt->xb, 0);
264
// Process a mouse press of fret "fret" in current column on string
265
// "num". Depending on given "button" mouse state flags, additional
266
// things may happen.
267
void TrackView::melodyEditorPress(int num, int fret, ButtonState button = NoButton)
269
if (button & LeftButton)
270
melodyEditorAction(num, fret, 0);
271
if (button & MidButton)
272
melodyEditorAction(num, fret, 1);
273
if (button & RightButton)
274
melodyEditorAction(num, fret, 2);
277
// Execute one of melody editors actions, as defined in
278
// globalMelodyEditorAction array
279
void TrackView::melodyEditorAction(int num, int fret, int action)
281
// GREYFIX: make it *one* undo transaction
282
switch (Settings::melodyEditorAction(action)) {
286
setFinger(num, fret);
288
case 3: // set 022 power chord
289
setFinger(num + 2, fret + 2);
290
case 2: // set 02 power chord
291
setFinger(num + 1, fret + 2);
292
setFinger(num, fret);
294
case 5: // set 0022 power chord
295
setFinger(num + 3, fret + 2);
296
setFinger(num + 2, fret + 2);
297
case 4: // set 00 power chord
298
setFinger(num + 1, fret);
299
setFinger(num, fret);
301
case 6: // delete note
302
setFinger(num, NULL_NOTE);
307
// Process a mouse release in melody editor. Depending on given
308
// "button" mouse state flags, additional things, such as proceeding
309
// to next column, may happen.
310
void TrackView::melodyEditorRelease(ButtonState button)
312
if (((button & LeftButton) && (Settings::melodyEditorAdvance(0))) ||
313
((button & MidButton) && (Settings::melodyEditorAdvance(1))) ||
314
((button & RightButton) && (Settings::melodyEditorAdvance(2)))) {
323
// Add tab number insertion command on current column, string "num",
324
// setting fret number "fret". Perform various checks, including
325
// no repeats for same insertion.
326
void TrackView::setFinger(int num, int fret)
328
if (num < 0 || num >= curt->string)
330
if (fret > curt->frets)
332
if (curt->c[curt->x].a[num] == fret)
336
cmdHist->addCommand(new InsertTabCommand(this, curt, fret));
337
repaintCurrentColumn();
338
emit columnChanged();
341
int TrackView::finger(int num)
343
return curt->c[curt->x].a[num];
346
void TrackView::setLength(int l)
349
if (curt->c[curt->x].l != l)
350
cmdHist->addCommand(new SetLengthCommand(this, curt, l));
353
void TrackView::linkPrev()
355
cmdHist->addCommand(new SetFlagCommand(this, curt, FLAG_ARC));
359
void TrackView::addHarmonic()
361
if (curt->c[curt->x].a[curt->y] >= 0)
362
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_HARMONIC));
366
void TrackView::addArtHarm()
368
if (curt->c[curt->x].a[curt->y] >= 0)
369
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_ARTHARM));
373
void TrackView::addLegato()
375
if (curt->c[curt->x].a[curt->y] >= 0)
376
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_LEGATO));
380
void TrackView::addSlide()
382
if (curt->c[curt->x].a[curt->y] >= 0)
383
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_SLIDE));
387
void TrackView::addLetRing()
389
if (curt->c[curt->x].a[curt->y] >= 0)
390
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_LETRING));
392
cmdHist->addCommand(new AddFXCommand(this, curt, EFFECT_STOPRING));
396
// Call the chord constructor dialog and may be parse something from it
397
void TrackView::insertChord()
407
for (int i = 0; i < curt->string; i++)
408
cs.setApp(i, curt->c[curt->x].a[i]);
410
// required to detect chord from tabulature
415
// set fingering right if frets > 5
416
for (i = 0; i < curt->string; i++)
418
cs.fng->setFingering(a);
421
for (i = 0; i < curt->string; i++)
423
cmdHist->addCommand(new InsertStrumCommand(this, curt, cs.scheme(), a));
429
// Call rhythm construction dialog and may be parse something from it
430
void TrackView::rhythmer()
433
Rhythmer r(scheduler);
439
cmdHist->addCommand(new InsertRhythm(this, curt, r.quantized));
444
// Determine horizontal offset between two columns - n and n+1
446
int TrackView::horizDelta(uint n)
448
#ifdef USE_BOTH_OLD_AND_NEW
449
int res = curt->c[n].fullDuration() * HORCELL / zoomLevel;
450
// if (res < HORCELL)
453
int res = trp->colWidth(n, curt); // LVIFIX: zoomLevel
458
#ifdef USE_BOTH_OLD_AND_NEW
459
void TrackView::drawLetRing(QPainter *p, int x, int y)
461
p->setPen(SolidLine);
462
p->drawLine(x, y, x - HORCELL / 3, y - VERTLINE / 3);
463
p->drawLine(x, y, x - HORCELL / 3, y + VERTLINE / 3);
468
void TrackView::paintCell(QPainter *p, int row, int /*col*/)
470
// cout << "TrackView::paintCell(row=" << row << ")" << endl;
472
uint bn = row; // Drawing only this bar
477
if (row >= int(curt->b.size())) {
478
kdDebug() << "Drawing the bar out of limits!" << endl;
483
// LVIFIX: initmetrics may be expensive but depends on p, init only once ?
485
// LVIFIX: do following calculations for the current bar only
487
curt->calcStepAltOct();
491
if (viewscore && fetaFont) {
493
trp->yposst = (int) ((TOPSPST + NLINEST - 1 + BOTSPST) * trp->ystepst);
494
trp->drawStLns(width());
498
trp->ypostb = trp->yposst
499
+ (int) ((TOPSPTB + curt->string - 0.5) * trp->ysteptb);
500
#ifdef USE_BOTH_OLD_AND_NEW
501
// force new tabbar position close to old one
502
trp->ypostb = (int) ((TOPSPST + NLINEST - 1) * trp->ystepst)
503
+ (int) (BOTSPST * trp->ystepst)
504
+ (int) ((TOPSPTB + curt->string) * trp->ysteptb);
506
trp->drawBarLns(width(), curt);
507
// trp->drawKey(row, curt); // LVIFIX: make (some more) room between key and time sig
510
bool flop = (row == 0);
511
(void) trp->drawKKsigTsig(row, curt, doDraw, fbol, flop);
512
trp->drawBar(row, curt, 0, selxcoord, selx2coord);
514
// connect tabbar and staff with vertical line at end of bar
515
if (viewscore && fetaFont) {
516
p->setPen(trp->pLnBl);
517
p->drawLine(trp->xpos - 1, trp->yposst, trp->xpos - 1, trp->ypostb);
520
// DEBUG: DRAW VARIOUS GUIDE BORDERS
522
// p->setBrush(NoBrush);
524
// p->drawRect(cellRect());
526
// p->drawRect(0, TOPSPTB * trp->ysteptb, cellWidth(), curt->string * trp->ysteptb);
530
p->setRasterOp(Qt::XorROP);
531
p->setBrush(KGlobalSettings::baseColor());
533
const int horcell = (int) (2.6 * trp->br8w);
534
const int vertline = trp->ysteptb;
535
const int vertspace = trp->ypostb;
537
if (playbackCursor) {
538
// Draw MIDI playback cursor
540
p->drawRect(selxcoord - horcell / 2, 0, horcell + 1, cellHeight());
544
// Draw selection between selxcoord and selx2coord (if it exists)
546
if ((selxcoord != -1) && (selx2coord != -1)) {
547
int x1 = KMIN(selxcoord, selx2coord);
548
int wid = abs(selx2coord - selxcoord) + horcell + 1;
549
p->drawRect(x1 - horcell / 2, 0, wid, cellHeight());
550
} else if ((selxcoord == -1) && (selx2coord != -1)) {
551
if (curt->x > curt->lastColumn(bn))
552
p->drawRect(selx2coord - horcell / 2, 0, cellWidth(), cellHeight());
554
p->drawRect(0, 0, selx2coord + horcell / 2 + 1, cellHeight());
555
} else if ((selxcoord != -1) && (selx2coord == -1)) {
556
if (curt->xsel > curt->lastColumn(bn))
557
p->drawRect(selxcoord - horcell / 2, 0, cellWidth(), cellHeight());
559
p->drawRect(0, 0, selxcoord + horcell / 2 + 1, cellHeight());
560
} else { // both are -1
561
int x1 = KMIN(curt->x, curt->xsel);
562
int x2 = KMAX(curt->x, curt->xsel);
563
if ((x1 < curt->b[bn].start) && (x2 > curt->lastColumn(bn)))
564
p->drawRect(0, 0, cellWidth(), cellHeight());
567
// Draw original cursor (still inverted)
568
if (selxcoord != -1) {
569
p->drawRect(selxcoord - horcell / 2,
570
vertspace + (0 - curt->y) * vertline - vertline / 2 - 2,
576
p->setRasterOp(Qt::CopyROP);
578
#ifdef USE_BOTH_OLD_AND_NEW
580
bool ringing[MAX_STRINGS];
581
int trpCnt = 0; // triplet count
582
int lastPalmMute = 0;
584
int s = curt->string - 1;
586
for (int i = 0; i <= s; i++) {
587
p->drawLine(0, VERTSPACE + (s - i) * VERTLINE,
588
width(), VERTSPACE + (s - i) * VERTLINE);
592
int xpos = 40, lastxpos = 20, xdelta;
596
// Starting bars - very thick and thick one
599
p->setBrush(SolidPattern);
600
p->drawRect(0, VERTSPACE, 5, VERTLINE * s);
601
p->drawRect(8, VERTSPACE, 2, VERTLINE * s);
606
if (curt->showBarSig(bn)) {
607
p->setFont(*timeSigFont);
608
tmp.setNum(curt->b[bn].time1);
609
p->drawText(20, VERTSPACE + VERTLINE * s / 4 - TIMESIGSIZE / 2,
610
TIMESIGSIZE, TIMESIGSIZE, AlignCenter, tmp);
611
tmp.setNum(curt->b[bn].time2);
612
p->drawText(20, VERTSPACE + VERTLINE * s * 3 / 4 - TIMESIGSIZE / 2,
613
TIMESIGSIZE, TIMESIGSIZE, AlignCenter, tmp);
616
p->setFont(*normalFont);
617
p->setBrush(KGlobalSettings::baseColor());
619
// Drum abbreviations markings
621
if (curt->trackMode() == TabTrack::DrumTab) {
623
for (int i = 0; i <= s; i++) {
624
p->drawRect(xpos, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2,
625
ABBRLENGTH, VERTLINE + 1);
626
p->drawText(xpos, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2,
627
ABBRLENGTH, VERTLINE, AlignCenter, drum_abbr[curt->tune[i]]);
629
xpos += ABBRLENGTH + 10; lastxpos += ABBRLENGTH + 10;
630
p->setPen(SolidLine);
633
for (int t = curt->b[bn].start; t <= curt->lastColumn(bn); t++) {
636
// - reset after third note of triplet
637
// - count notes while inside triplet
641
if (curt->c[t].flags & FLAG_TRIPLET) {
647
// Drawing duration marks
649
// Draw connection with previous, if applicable
650
if ((t > 0) && (t > curt->b[bn].start) && (curt->c[t - 1].l == curt->c[t].l))
651
xdelta = lastxpos + HORCELL / 2;
653
xdelta = xpos + HORCELL / 2 + HORDUR;
655
switch (curt->c[t].l) {
657
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + VERTLINE - 4,
658
xdelta, BOTTOMDUR + VERTLINE - 4);
660
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + VERTLINE - 2,
661
xdelta, BOTTOMDUR + VERTLINE - 2);
663
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + VERTLINE,
664
xdelta, BOTTOMDUR + VERTLINE);
665
case 120: { // 1/4 - a long vertical line, so we need to find the highest note
667
for (i = s; ((i >= 0) && (curt->c[t].a[i] == -1)); i--);
669
// If it's an empty measure at all - draw the vertical line from bottom
670
if (i < 0) i = s / 2;
672
p->drawLine(xpos + HORCELL / 2, VERTSPACE + VERTLINE * (s - i) + VERTLINE / 2,
673
xpos + HORCELL / 2, BOTTOMDUR + VERTLINE);
676
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + 3,
677
xpos + HORCELL / 2, BOTTOMDUR + VERTLINE);
683
if (curt->c[t].flags & FLAG_DOT)
684
p->drawRect(xpos + HORCELL / 2 + 3, BOTTOMDUR + 5, 2, 2);
686
// Draw triplet - GREYFIX: ugly code, needs to be fixed
687
// somehow... Ideally, triplets should be drawn in a second
688
// loop, after everything else would be done.
691
if (curt->c[t].flags & FLAG_TRIPLET) {
692
if ((curt->c.size() >= t + 1) && (t) &&
693
(curt->c[t - 1].flags & FLAG_TRIPLET) &&
694
(curt->c[t + 1].flags & FLAG_TRIPLET) &&
695
(curt->c[t - 1].l == curt->c[t].l) &&
696
(curt->c[t + 1].l == curt->c[t].l)) {
697
p->drawLine(lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5,
698
xpos * 2 - lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5);
699
p->drawLine(lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 2,
700
lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5);
701
p->drawLine(xpos * 2 - lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 2,
702
xpos * 2 - lastxpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5);
703
p->setFont(*smallCaptionFont);
704
p->drawText(xpos, BOTTOMDUR + VERTLINE + 7, HORCELL, VERTLINE, AlignHCenter | AlignTop, "3");
705
p->setFont(*normalFont);
707
if (!(((curt->c.size() >= t + 2) &&
708
(curt->c[t + 1].flags & FLAG_TRIPLET) &&
709
(curt->c[t + 2].flags & FLAG_TRIPLET) &&
710
(curt->c[t + 1].l == curt->c[t].l) &&
711
(curt->c[t + 2].l == curt->c[t].l)) ||
713
(curt->c[t - 1].flags & FLAG_TRIPLET) &&
714
(curt->c[t - 2].flags & FLAG_TRIPLET) &&
715
(curt->c[t - 1].l == curt->c[t].l) &&
716
(curt->c[t - 2].l == curt->c[t].l)))) {
717
p->setFont(*smallCaptionFont);
718
p->drawText(xpos, BOTTOMDUR + VERTLINE + 7, HORCELL, VERTLINE, AlignHCenter | AlignTop, "3");
719
p->setFont(*normalFont);
725
// Length of interval to next column - adjusted if dotted
726
// calculated here because it is required by triplet code
728
xdelta = horizDelta(t);
730
// Draw triplet - improved (? :-)) code
731
if ((trpCnt == 1) || (trpCnt == 2)) {
732
// draw horizontal line to next note
733
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5,
734
xpos + HORCELL / 2 + xdelta, BOTTOMDUR + VERTLINE + 5);
736
if ((trpCnt == 1) || (trpCnt == 3)) {
737
// draw vertical line
738
p->drawLine(xpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 2,
739
xpos + HORCELL / 2, BOTTOMDUR + VERTLINE + 5);
743
p->setFont(*smallCaptionFont);
744
p->drawText(xpos, BOTTOMDUR + VERTLINE + 7, HORCELL, VERTLINE, AlignHCenter | AlignTop, "3");
745
p->setFont(*normalFont);
748
// Draw arcs to backward note
750
if (curt->c[t].flags & FLAG_ARC)
751
p->drawArc(lastxpos + HORCELL / 2, BOTTOMDUR + 9,
752
xpos - lastxpos, 10, 0, -180 * 16);
756
if (curt->c[t].flags & FLAG_PM) {
757
if (lastPalmMute == 0) { // start drawing with "P.M."
758
p->setFont(*smallCaptionFont);
759
p->drawText(xpos, VERTSPACE / 2, VERTLINE * 2, VERTLINE,
760
AlignCenter, "P.M.");
761
p->setFont(*normalFont);
763
} else if (lastPalmMute == 1) {
764
p->drawLine(lastxpos + VERTLINE * 2, VERTSPACE / 2 + VERTLINE / 2,
765
xpos + HORCELL / 2, VERTSPACE / 2 + VERTLINE / 2);
768
p->drawLine(lastxpos + HORCELL / 2, VERTSPACE / 2 + VERTLINE / 2,
769
xpos + HORCELL / 2, VERTSPACE / 2 + VERTLINE / 2);
772
if (lastPalmMute == 2) {
773
p->drawLine(lastxpos + HORCELL / 2, VERTSPACE / 2 + VERTLINE / 2,
774
lastxpos + HORCELL / 2, VERTSPACE / 2 + VERTLINE);
779
// Draw the number column
782
for (int i = 0; i <= s; i++) {
783
if (curt->c[t].a[i] != -1) {
784
if (curt->c[t].a[i] == DEAD_NOTE)
787
tmp.setNum(curt->c[t].a[i]);
788
p->drawRect(xpos, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2,
790
p->drawText(xpos, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2,
791
HORCELL, VERTLINE, AlignCenter, tmp);
793
drawLetRing(p, xpos, VERTSPACE + (s - i) * VERTLINE);
797
if ((curt->c[t].a[i] == -1)
798
&& (curt->c[t].e[i] == EFFECT_STOPRING)) {
800
drawLetRing(p, xpos, VERTSPACE + (s - i) * VERTLINE);
812
// GREYFIX - use lastxpos, not xdelta
814
switch (curt->c[t].e[i]) {
815
case EFFECT_HARMONIC:
816
p->setFont(*smallCaptionFont);
817
p->drawText(xpos + VERTLINE + 2, VERTSPACE + (s - i) * VERTLINE - VERTLINE * 2 / 3,
818
HORCELL, VERTLINE, AlignCenter, "H");
819
p->setFont(*normalFont);
822
p->setFont(*smallCaptionFont);
823
p->drawText(xpos + VERTLINE + 2, VERTSPACE + (s - i) * VERTLINE - VERTLINE * 2 / 3,
824
HORCELL * 2, VERTLINE, AlignCenter, "AH");
825
p->setFont(*normalFont);
828
p->setPen(SolidLine);
829
p->drawArc(xpos + HORCELL, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2,
830
xdelta - HORCELL, 10, 0, 180 * 16);
831
if ((t < curt->c.size() - 1) && (curt->c[t + 1].a[i] >= 0)) {
832
p->setFont(*smallCaptionFont);
833
if (curt->c[t + 1].a[i] > curt->c[t].a[i]) {
834
p->drawText(xpos + xdelta / 2 - HORCELL / 2, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 3,
835
HORCELL * 2, VERTLINE, AlignCenter, "HO");
836
} else if (curt->c[t + 1].a[i] < curt->c[t].a[i]) {
837
p->drawText(xpos + xdelta / 2 - HORCELL / 2, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 3,
838
HORCELL * 2, VERTLINE, AlignCenter, "PO");
840
p->setFont(*normalFont);
845
p->setPen(SolidLine);
846
if ((t < curt->c.size() - 1) && (curt->c[t + 1].a[i] >= 0)) {
847
if (curt->c[t + 1].a[i] > curt->c[t].a[i]) {
848
p->drawLine(xpos + HORCELL + 2, VERTSPACE + (s - i) * VERTLINE + VERTLINE / 2 - 1,
849
xpos + xdelta, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2 + 1);
851
p->drawLine(xpos + HORCELL + 2, VERTSPACE + (s - i) * VERTLINE - VERTLINE / 2 + 1,
852
xpos + xdelta, VERTSPACE + (s - i) * VERTLINE + VERTLINE / 2 - 1);
863
p->setPen(SolidLine);
869
// Show notes still ringing at end of bar
870
for (int i = 0; i <= s; i++) {
872
drawLetRing(p, xpos - HORCELL / 3, VERTSPACE + (s - i) * VERTLINE);
877
// End bar with vertical line
878
p->setPen(SolidLine);
879
p->drawRect(xpos, VERTSPACE, 1, VERTLINE * s);
881
// Draw original cursor (still inverted)
882
p->setRasterOp(Qt::XorROP);
883
// p->setBrush(KGlobalSettings::highlightColor());
884
if (selxcoord != -1) {
885
p->drawRect(selxcoord, VERTSPACE + (s - curt->y) * VERTLINE - VERTLINE / 2 - 1,
886
HORCELL + 1, VERTLINE + 2);
889
// p->setBrush(KGlobalSettings::baseColor());
890
p->setRasterOp(Qt::CopyROP);
891
p->setBrush(SolidPattern);
892
#endif // USE_BOTH_OLD_AND_NEW
895
void TrackView::resizeEvent(QResizeEvent *e)
897
QGridView::resizeEvent(e); // GREYFIX ? Is it C++-correct?
898
setCellWidth(width() - 2 - QStyle::PM_ScrollBarExtent);
901
bool TrackView::moveFinger(int from, int dir)
903
int n0 = curt->c[curt->x].a[from];
912
if ((to < 0) || (to >= curt->string))
914
n = n0 + curt->tune[from] - curt->tune[to];
915
if ((n < 0) || (n > curt->frets))
917
} while (curt->c[curt->x].a[to] != -1);
919
cmdHist->addCommand(new MoveFingerCommand(this, curt, from, to, n));
920
emit columnChanged();
925
// LVIFIX: eventually KGuitar should support changing the key at the start
926
// of a new bar. For the time being, we don't: the key is the same for the
927
// whole track and is stored in the first bar
929
void TrackView::keySig()
931
int oldsig = curt->b[0].keysig;
932
if ((oldsig <= -8) || (8 <= oldsig)) {
933
// LVIFIX: report error ???
937
SetKeySig sks(oldsig);
940
curt->b[0].keysig = sks.keySignature();
948
void TrackView::timeSig()
950
SetTimeSig sts(curt->b[curt->xb].time1, curt->b[curt->xb].time2);
953
cmdHist->addCommand(new SetTimeSigCommand(this, curt, sts.toend->isChecked(),
954
sts.time1(), sts.time2()));
959
void TrackView::keyLeft()
969
void TrackView::keyRight()
979
void TrackView::keyLeftBar()
989
void TrackView::keyRightBar()
999
void TrackView::keyHome()
1009
void TrackView::keyEnd()
1019
void TrackView::keyCtrlHome()
1029
void TrackView::keyCtrlEnd()
1039
void TrackView::moveLeft()
1042
if (curt->b[curt->xb].start == curt->x) {
1044
repaintCurrentCell();
1046
ensureCurrentVisible();
1051
repaintCurrentCell();
1052
emit columnChanged();
1057
void TrackView::moveRight()
1059
if (((uint) (curt->x + 1)) == curt->c.size()) {
1060
cmdHist->addCommand(new AddColumnCommand(this, curt));
1061
emit columnChanged();
1063
if (curt->b.size() == (uint) curt->xb + 1)
1066
if (curt->b[curt->xb + 1].start == curt->x + 1) {
1068
repaintCurrentCell();
1070
ensureCurrentVisible();
1076
repaintCurrentCell();
1077
emit columnChanged();
1082
void TrackView::moveLeftBar()
1084
if (curt->x > curt->b[curt->xb].start) {
1092
void TrackView::moveRightBar()
1094
if (curt->x == curt->lastColumn(curt->xb)) {
1096
} else if (curt->x == curt->b[curt->xb].start) {
1104
void TrackView::moveHome()
1106
curt->x = curt->b[curt->xb].start;
1107
repaintCurrentCell();
1108
emit columnChanged();
1111
void TrackView::moveEnd()
1113
curt->x = curt->lastColumn(curt->xb);
1114
repaintCurrentCell();
1115
emit columnChanged();
1118
void TrackView::moveCtrlHome()
1122
ensureCurrentVisible();
1125
emit columnChanged();
1128
void TrackView::moveCtrlEnd()
1130
curt->x = curt->c.size() - 1;
1131
curt->xb = curt->b.size() - 1;
1132
ensureCurrentVisible();
1135
emit columnChanged();
1138
void TrackView::selectLeft()
1142
curt->xsel = curt->x;
1143
repaintCurrentCell();
1149
void TrackView::selectRight()
1153
curt->xsel = curt->x;
1154
repaintCurrentCell();
1160
void TrackView::moveUp()
1162
if (curt->y+1 < curt->string) {
1165
repaintCurrentCell();
1167
repaintCurrentColumn();
1172
void TrackView::transposeUp()
1174
if (curt->y+1 < curt->string)
1175
moveFinger(curt->y, 1);
1179
void TrackView::moveDown()
1184
repaintCurrentCell();
1186
repaintCurrentColumn();
1191
void TrackView::transposeDown()
1194
moveFinger(curt->y, -1);
1198
void TrackView::deadNote()
1200
cmdHist->addCommand(new SetFlagCommand(this, curt, DEAD_NOTE));
1201
emit columnChanged();
1205
void TrackView::deleteNote()
1207
if (curt->c[curt->x].a[curt->y] != -1) {
1208
cmdHist->addCommand(new DeleteNoteCommand(this, curt));
1209
emit columnChanged();
1214
void TrackView::deleteColumn()
1216
cmdHist->addCommand(new DeleteColumnCommand(this, curt));
1217
emit columnChanged();
1221
void TrackView::deleteColumn(QString name)
1223
cmdHist->addCommand(new DeleteColumnCommand(name, this, curt));
1224
emit columnChanged();
1227
void TrackView::insertColumn()
1229
cmdHist->addCommand(new InsertColumnCommand(this, curt));
1230
emit columnChanged();
1234
void TrackView::palmMute()
1236
cmdHist->addCommand(new SetFlagCommand(this, curt, FLAG_PM));
1240
void TrackView::dotNote()
1242
cmdHist->addCommand(new SetFlagCommand(this, curt, FLAG_DOT));
1246
void TrackView::tripletNote()
1248
cmdHist->addCommand(new SetFlagCommand(this, curt, FLAG_TRIPLET));
1252
void TrackView::keyPlus()
1254
if (curt->c[curt->x].l < 480)
1255
setLength(curt->c[curt->x].l * 2);
1259
void TrackView::keyMinus()
1261
if (curt->c[curt->x].l > 15)
1262
setLength(curt->c[curt->x].l / 2);
1266
void TrackView::arrangeTracks()
1268
cmdHist->clear(); // because columns will be changed
1269
curt->arrangeBars();
1275
emit columnChanged();
1278
void TrackView::insertTab(int num)
1282
if (curt->c[curt->x].flags & FLAG_ARC)
1283
curt->c[curt->x].flags -= FLAG_ARC;
1285
// Allow making two-digit fret numbers pressing two keys sequentally
1286
if ((lastnumber != -1) && (lastnumber * 10 + num <= curt->frets)) {
1287
totab = lastnumber * 10 + num;
1293
if ((totab <= curt->frets) && (curt->c[curt->x].a[curt->y] != totab))
1294
cmdHist->addCommand(new InsertTabCommand(this, curt, totab));
1295
emit columnChanged();
1298
void TrackView::arrangeBars()
1300
song->arrangeBars();
1302
emit columnChanged();
1306
void TrackView::mousePressEvent(QMouseEvent *e)
1310
// RightButton pressed
1311
if (e->button() == RightButton) {
1312
QWidget *tmpWidget = 0;
1313
tmpWidget = xmlGUIClient->factory()->container("trackviewpopup", xmlGUIClient);
1315
if (!tmpWidget || !tmpWidget->inherits("KPopupMenu")) {
1316
kdDebug() << "TrackView::mousePressEvent => wrong container widget" << endl;
1320
KPopupMenu *menu(static_cast<KPopupMenu*>(tmpWidget));
1321
menu->popup(QCursor::pos());
1324
// LeftButton pressed
1325
if (e->button() == LeftButton) {
1329
uint tabrow = rowAt(contentsY() + e->pos().y());
1331
// Clicks on non-existing rows are not allowed
1332
if (tabrow >= curt->b.size())
1335
clickpt.setX(contentsX() + e->pos().x());
1336
clickpt.setY(contentsY() + e->pos().y());
1338
int xpos = trp->getFirstColOffs(tabrow, curt);
1342
for (uint j=curt->b[tabrow].start;
1343
j < (tabrow < curt->b.size()-1 ? curt->b[tabrow+1].start : curt->c.size());
1346
// Length of interval to next column - adjusted if dotted
1347
xdelta = horizDelta(j);
1349
// Current column X area is half of the previous duration and
1350
// half of current duration
1352
if ((clickpt.x() >= (lastxpos + xpos) / 2) &&
1353
(clickpt.x() <= xpos + xdelta / 2)) {
1355
// We won't calculate xb from x as in updateXB(), but
1356
// would just use what we know.
1359
const int vertline = trp->ysteptb;
1360
const int vertspace = trp->ypostb; // LVIFIX: better name, this is not the vertical space but the lowest tab line's y coord
1361
curt->y = - ((int) (clickpt.y() - vertline / 2 - tabrow * cellHeight()) - vertspace) / vertline;
1365
if (curt->y>=curt->string)
1366
curt->y = curt->string-1;
1370
emit columnChanged();
1385
void TrackView::setX(int x)
1387
if (x < (int) curt->c.size()) {
1389
int oldxb = curt->xb;
1391
if (oldxb == curt->xb) {
1392
repaintCurrentCell();
1395
ensureCurrentVisible();
1397
emit columnChanged();
1402
void TrackView::setPlaybackCursor(bool pc)
1404
playbackCursor = pc;
1408
void TrackView::viewScore(bool on)
1410
// cout << "TrackView::viewScore(on=" << on << ")" << endl;