Пример #1
0
QRect
WPiano::rect2qrect(const Rect &rect) const
{
	int l = time2x(rect.time_beg);
	int r = time2x(rect.time_end);
	int t = rect.level_end > levels(track()) ? 0 : level2y(rect.level_end);
	int b = rect.level_end > levels(track()) ? height() : level2y(rect.level_beg);
	return QRect(l, t, r-l, b-t);
}
Пример #2
0
void
WPiano::look_at_cursor(LookMode mode)
{
	QWidget *viewport_widget = qobject_cast<QWidget *>(parent());
	if (viewport_widget == NULL)
		return;
	QScrollArea *scroll = qobject_cast<QScrollArea *>(viewport_widget->parent());
	if (scroll == NULL)
		return;
	QScrollBar *hs = scroll->horizontalScrollBar();
	QScrollBar *vs = scroll->verticalScrollBar();

	bool pl = playing();
	QRect v = viewport();
	int x1, x2, y1, y2;
	x1 = time2x(cursorTime());
	x2 = pl ? x1 + 1 : time2x(cursorEndTime());
	y1 = level2y(cursor_level_ + 1);
	y2 = level2y(cursor_level_ - 1);

	switch (mode) {
	case PAGE:
		if (x1 < v.left())
			hs->setValue(scroll_snap(this, x2 - v.width(), true));
		if (x2 > v.right())
			hs->setValue(scroll_snap(this, x1 - 1));
		if (pl && y1 < v.top())
			vs->setValue(y2 - v.height() + level_height);
		if (pl && y2 > v.bottom())
			vs->setValue(y1 - level_height);
		break;
	case MINSCROLL:
		scroll->ensureVisible(x1, y1, level_height, level_height);
		scroll->ensureVisible(x2, y2, level_height, level_height);
		break;
	case CENTER:
		hs->setValue((x1 + x2 - v.width()) / 2);
		vs->setValue((y1 + y2 - v.height()) / 2);
		break;
	}
}
Пример #3
0
void QScope::addSpike(Spikeinfo const &si) {
//  int x = time2x(si.time+qss.sf->first());
  int x = time2x(si.time);
  QPainter qpai(this);
  qpai.setPen(aux_pen); qpai.setBrush(aux_pen.color());
  qpai.drawEllipse(x-2, coffset+(si.height>0?-1:1)*halfhei*7/8-2,4,4);
  if (nspikes>=spikes.size()) 
    spikes.push_back(si);
  else 
    spikes[nspikes] = si;
  nspikes++;
  forall(&QScope::addSpike,si);
}
Пример #4
0
QRect
WPiano::cursor_qrect() const
{
	if (playing())
		return QRect(time2x(cursor_time_), 0, 1, height());
	else {
		Rect rect(
			cursorTime(),
			cursorEndTime(),
			cursor_level_ - 1,
			cursor_level_ + 1
		);
		return rect2qrect(rect).adjusted(-3, -3, 3, 3);
	}
}
Пример #5
0
WPiano::WPiano(File *_file, vmd_track_t *_track, vmd_time_t time, Player *_player)
	:file_(_file),
	track_(_track),
	grid_size_(file()->division),
	mouse_captured_(false),
	cursor_time_(grid_snap_left(this, time)),
	cursor_size_(file()->division),
	cursor_level_(0),
	pivot_enabled_(false),
	selection_(NULL),
	player_(_player)
{
	int w = time2x(vmd_file_length(file()));
	int h = margin * 2 + level_height * levels(track());
	setMinimumSize(w, h);
	setPalette(PianoPalette());
	setFocusPolicy(Qt::StrongFocus);

	connect(file_, SIGNAL(acted()), this, SLOT(update()));
	connect(player_, SIGNAL(started()), this, SLOT(playStarted()));
	connect(player_, SIGNAL(finished()), this, SLOT(playStopped()));
	if (playing())
		playStarted();
}
Пример #6
0
void QScope::drawContents_box(QPainter *qp) {
  QGraph::drawContents(qp);
  if (guide_spacing) {
    // Let's draw zero line and guide lines
    qp->setPen(zero_pen);
    int yy = value2y(center);
    qp->drawLine(xoffset, yy, xoffset+wid-1, yy); 
    qp->setPen(guide_pen);
    int gs = guide_spacing;
    for (raw_t y=gs; y<extent; y+=gs) {
      int yy = value2y(center + y);
      qp->drawLine(xoffset, yy, xoffset+wid-1, yy);
      yy = value2y(center-y);
      qp->drawLine(xoffset, yy, xoffset+wid-1, yy);
    }
  }

  if (!qss.sf)
    return;
  
  if (qss.endtime>0) {
    // let's draw trace.
    // I *assume* that there are more data points than pixels, but even if
    //   this is not so, I think this should be OK. 
    qp->setPen(trace_pen);
    qp->setBrush(trace_pen.color());
    timeref_t starttime = (qss.endtime>qss.length)?(qss.endtime-qss.length):0;
    int tlength = qss.endtime-starttime;
    int twidth = wid * tlength/qss.length;
    int lastend;
    timeref_t time;
 
    if (controller || speedy!=AvgOnly) {
      // I am a satellite or not speedy
      // -- collect max line --
      lastend = 0;
      time = starttime;
      int x_end = 2*twidth-1;
      raw_t maxv=(*qss.sf)[time][qss.channel];
      for (int x=0; x<twidth; x++) {
	raw_t max=(*qss.sf)[time][qss.channel];
	int nextend = (x+1)*tlength/twidth;
	//	int n=nextend-lastend;
	for (; lastend<nextend; lastend++)
	  maxIs(max, (*qss.sf)[time++][qss.channel]);
	qpa->setPoint(x_end-x, x+xoffset, value2y(max));
	//if(qss.channel<126) 	qpa->setPoint(x_end-x, x+xoffset, value2y(max));
	//else			qpa->setPoint(x_end-x, x+xoffset, yoffset+(4095-max)*hei/4096);
	maxIs(maxv,max);
      }
      // -- collect min line --
      lastend=0; time = starttime;
      raw_t minv=(*qss.sf)[time][qss.channel];
      for (int x=0; x<twidth; x++) {
	raw_t min=(*qss.sf)[time][qss.channel];
	int nextend = (x+1)*tlength/twidth;
	//	int n=nextend-lastend;
	for (; lastend<nextend; lastend++)
	  minIs(min, (*qss.sf)[time++][qss.channel]);
	qpa->setPoint(x, x+xoffset, value2y(min));
	//if(qss.channel<126)	qpa->setPoint(x, x+xoffset, value2y(min));
	//else			qpa->setPoint(x, x+xoffset, yoffset+(4095-min)*hei/4096);
	minIs(minv,min);
      }
      // -- draw it --    // db  need to send qp for allgraphs also, use graphptrs offsets and apply to draw functions
      /*if (maxv-minv>4000)  // do not plot rail-to-rail noisy channels
	qp->drawLine(xoffset, value2y(center), xoffset+wid, value2y(center));
      else*/ if (speedy==MinMax) 
	qp->drawPolyline(*qpa,0,x_end*2);
      else
	qp->drawPolygon(*qpa,true,0,x_end*2);
    } else {
      // I am a speedy small QMultiGraph member
      // -- draw average line --
      lastend=0; time=starttime;
      for (int x=0; x<twidth; x++) {
	float sum=0;
	int nextend = (x+1)*tlength/twidth;
	int n=nextend-lastend;
	for (; lastend<nextend; lastend++)
	  sum += (*qss.sf)[time++][qss.channel];
	qpa->setPoint(x, x+xoffset, value2y(raw_t(sum/n)));
	//if(qss.channel<126)	qpa->setPoint(x, x+xoffset, value2y(raw_t(sum/n)));
	//else			qpa->setPoint(x, x+xoffset, yoffset+(4095-raw_t(sum/n))*hei/4096);
      }
      qp->drawPolyline(*qpa,0,twidth);
    }
    if (controller) {
      // draw more guide lines
      QFont f(qp->font());
      f.setPointSize(14);
      qp->setFont(f);
      qp->setPen(guide_pen);
      int timelines[4] = { 2, 10, 50, 250 };
      bool drawtl[4];
      int tlmax=0;
      for (int n=0; n<4; n++) {
	drawtl[n] = twidth * timelines[n]*FREQKHZ / tlength > 10;
	if (timelines[n]*FREQKHZ < tlength)
	  tlmax=n;
      }
      bool subtext = tlmax>0 && (twidth * timelines[tlmax-1]*FREQKHZ / tlength)>60;
      bool hundreds = tlmax>2;
      bool tens = tlmax>1;
      
      int uvlines[2] = { 10, 50 };
      bool drawuv[2];
      int uvmax=0;
      float uvpdig = uvpd();
      for (int n=0; n<2; n++) {
	drawuv[n] = halfhei * (uvlines[n]/uvpdig) / extent > 10;
	if (uvlines[n]/uvpdig < extent)
	  uvmax=n;
      }

      timeref_t t0 = qss.sf?qss.sf->first():0;
      timeref_t t = starttime - t0;
      t = timeref_t(t/(FREQKHZ*timelines[0])+.99999) * FREQKHZ*timelines[0];
      timeref_t t1 = starttime-t0+tlength;
      while (t<t1) {
	//	sdbx("Time: %.5f / starttime=%.5f t0=%.5f x=%i",t/25000.0,starttime/25000.0,t0/25000.0,time2x(t+t0));
	for (int n=0; n<4; n++) {
	  if (t % (FREQKHZ*timelines[n]) == 0) {
	    if (drawtl[n]) {
	      int x = time2x(t+t0);
	      qp->drawLine(x,0,x,10*(n+1));
	      qp->drawLine(x,hei,x,hei-10*(n+1));
	      if (n==tlmax) {
		qp->setPen(black_pen);
		char buf[100]; sprintf(buf,"%.3f",t/(1000.0*FREQKHZ));
		qp->drawText(x-40,hei-70,80,35,
			     Qt::AlignHCenter|Qt::AlignBottom,buf);
		qp->setPen(guide_pen);
	      } else if (subtext && n==tlmax-1 && t % (FREQKHZ*timelines[n+1]) != 0) {
		char buf[100];
		if (hundreds)
		  sprintf(buf,"%03i",int(t/FREQKHZ)%1000);
		else if (tens)
		  sprintf(buf,"%02i",int(t/FREQKHZ)%100);
		else
  		  sprintf(buf,"%01i",int(t/FREQKHZ)%10);
		qp->drawText(x-40,hei-70,80,35,
			     Qt::AlignHCenter|Qt::AlignBottom,buf);
	      }
	    }
	  } else {
	    break;
	  }
	}
	t+=FREQKHZ*timelines[0];
      }
      for (int uv=0; uv<uvpdig*extent; uv+=uvlines[0]) {
	for (int n=0; n<2; n++) {
	  if (uv%uvlines[n] == 0 && drawuv[n]) {
	    int y=coffset - int(uv/uvpdig * halfhei/extent);
	    qp->drawLine(0,y,10*(n+1),y);
	    qp->drawLine(wid,y,wid-10*(n+1),y);
	    if (n==uvmax) {
	      char buf[100]; sprintf(buf,"%i",uv);
	      qp->setPen(black_pen);
	      qp->drawText(wid-110,y-50,80,100,
			   Qt::AlignVCenter|Qt::AlignRight,buf);
	      qp->setPen(guide_pen);
	    } 
	    if (uv) {
	      y=coffset + int(uv/uvpdig * halfhei/extent);
	      qp->drawLine(0,y,10*(n+1),y);
	      qp->drawLine(wid,y,wid-10*(n+1),y);
	      if (n==uvmax) {
		char buf[100]; sprintf(buf,"%i",-uv);
		qp->setPen(black_pen);
		qp->drawText(wid-110,y-50,80,100,
			     Qt::AlignVCenter|Qt::AlignRight,buf);
		qp->setPen(guide_pen);
	      }
	    }
	  }
	}
      }
    }
  }
  qp->setPen(aux_pen); qp->setBrush(aux_pen.color());
  timeref_t t0 = qss.sf->first();
  for (unsigned int i=0; i<nspikes; i++) {
    Spikeinfo const &si = spikes[i];
    int x = time2x(si.time+t0);
    qp->drawEllipse(x-2, coffset+(si.height>0?-1:1)*halfhei*7/8-2,4,4);
  }
}
Пример #7
0
void
WPiano::paintEvent(QPaintEvent *ev)
{
	QPainter painter(this);
	QPen pen;
	vmd_time_t beg = x2time(ev->rect().left());
	vmd_time_t end = x2time(ev->rect().right());

	/* background */
	painter.setPen(Qt::NoPen);
	painter.setBrush(palette().base());
	painter.drawRect(0, 0, width(), level2y(levels(track())));
	painter.drawRect(0, level2y(0), width(), height() - level2y(0));
	for (int i = 0; i < (levels(track()) + 1) / 2; i++) {
		painter.setBrush(i % 2 == 0 ? palette().alternateBase() : palette().base());
		painter.drawRect(0, level2y(i*2+2), width(), level2y(i*2) - level2y(i*2+2));
	}

	/* selection */
	if (pivot_enabled_) {
		painter.setBrush(palette().highlight());
		painter.setPen(Qt::NoPen);

		Rect sel = selectionRect();
		sel.level_beg -= 1;
		painter.drawRect(rect2qrect(sel));
	}

	/* vertical grid */
	painter.setPen(QPen());
	vmd_file_measures(file(), beg, end + 1, draw_measure, &painter);

	/* horizontal grid */
	for (int i = 0; i < levels(track()); i++) {
		int style = level_style(track(), i);
		int y = level2y(i);
		if (style != LEVEL_NORMAL) {
			pen.setWidth(style == LEVEL_OCTAVE_LINE ? 2 : 0);
			painter.setPen(pen);
			painter.drawLine(0, y, width(), y);
		}
	}

	/* notes */
	vmd_track_for_range(track(), beg, end, draw_note, &painter);

	/* cursor */
	if (playing()) {
		painter.setPen(QPen());
		int x = time2x(cursor_time_);
		painter.drawLine(x, 0, x, height());
	} else {
		Qt::GlobalColor colors[2] = {
			Qt::black,
			cursorPitch() >= 0 ? Qt::red : Qt::lightGray
		};
		QRect r = cursor_qrect();
		for (int i = 0; i < 2; i++) {
			r.adjust(1, 1, -1, -1);
			painter.setPen(QColor(colors[i]));
			painter.setBrush(Qt::NoBrush);
			painter.drawRect(r);
		}
	}
}
Пример #8
0
void
WPiano::keyPressEvent(QKeyEvent *ev)
{
	int key = ev->key();
	int mod = ev->modifiers() & (Qt::CTRL | Qt::SHIFT);

#define SHIFT_SELECTS \
	do { \
		if (mod & Qt::SHIFT) { \
			capture_mouse(false); \
			set_pivot(); \
		} else \
			drop_pivot(); \
	} while(0)

	switch (key) {
	case Qt::Key_Escape:
		drop_pivot();
		capture_mouse(false);
		break;
	case Qt::Key_Home:
		SHIFT_SELECTS;
		setCursorTime(0);
		break;
	case Qt::Key_End:
		SHIFT_SELECTS;
		setCursorTime(grid_snap_right(this, vmd_track_length(track_)));
		break;
	case Qt::Key_Left:
		SHIFT_SELECTS;
		setCursorTime(grid_snap_left(this, cursor_time_ - 1));
		break;
	case Qt::Key_Right:
		SHIFT_SELECTS;
		setCursorTime(grid_snap_right(this, cursor_time_ + 1));
		break;
	case Qt::Key_Up:
		SHIFT_SELECTS;
		if (cursor_level_ < levels(track()))
			setCursorLevel(cursor_level_ + 1);
		break;
	case Qt::Key_Down:
		SHIFT_SELECTS;
		if (cursor_level_ > 0)
			setCursorLevel(cursor_level_ - 1);
		break;
	case Qt::Key_Space:
		drop_pivot();
		if (playing())
			player_->stop();
		else
			player_->play(file(), cursor_time_);
		break;
	case Qt::Key_QuoteLeft:
		{
			QString s = QInputDialog::getText(
				this,
				"vomid",
				mod & Qt::CTRL ? QString("Enter grid size:") : QString("Enter cursor size:")
			);
			QStringList sl = s.split("/");
			if (sl.size() != 2)
				break;
			int n = sl[0].toInt();
			int m = sl[1].toInt();
			if (n <= 0 && m <= 0)
				break;
			vmd_time_t size = file()->division * 4 * n / m;
			if (mod & Qt::CTRL)
				grid_size_ = size;
			else
				cursor_size_ = size;
		}
		break;
	case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4:
	case Qt::Key_5: case Qt::Key_6: case Qt::Key_7:
		{
			vmd_time_t size = file()->division * 4;
			for (int i = 0; i < key - Qt::Key_1; i++)
				size /= 2;
			if (mod & Qt::CTRL)
				grid_size_ = size;
			else
				cursor_size_ = size;
		}
		break;
	case Qt::Key_Enter:
	case Qt::Key_Return:
		drop_pivot();
		toggle_note();
		break;
	case Qt::Key_I:
		if (mod == Qt::CTRL) {
			vmd_note_t *note = noteAtCursor();
			if (note == NULL)
				break;
			QPoint pos(time2x(cursor_time_), level2y(cursor_level_));
			QString text = "Note: ";
			text += "channel = "; text += QString::number(note->channel->number);
			QToolTip::hideText();
			QToolTip::showText(mapToGlobal(pos), text);
		}
		break;
	case Qt::Key_C:
		if (mod == Qt::CTRL) {
			if (clipboard == NULL)
				clipboard = vmd_track_create(&clipboard_file, VMD_CHANMASK_ALL);

			Rect s = selectionRect();
			vmd_time_t base_time = s.time_beg;
			int base_pitch = level2pitch(track(), s.level_beg, true);

			clipboard_time_relative = s.time_end != VMD_MAX_TIME;
			clipboard_pitch_relative = s.level_end <= levels(track());
			vmd_track_clear(clipboard);
			for (vmd_note_t *i = selection(); i != NULL; i = i->next)
				vmd_copy_note(i, clipboard, -base_time, -base_pitch);
		}
		break;
	case Qt::Key_V:
		if (mod == Qt::CTRL) {
			vmd_time_t t = clipboard_time_relative ? cursorTime() : 0;
			vmd_pitch_t p = clipboard_pitch_relative ? cursorPitch() : 0;
			if (clipboard == NULL || p < 0)
				break;

			VMD_BST_FOREACH(vmd_bst_node_t *i, &clipboard->notes)
				vmd_copy_note(vmd_track_note(i), track(), t, p);
			file()->commit("Paste Notes");
			drop_pivot();
		}
		break;
	case Qt::Key_Delete:
		for (vmd_note_t *i = selection(); i != NULL; i = i->next)
			vmd_erase_note(i);
		file()->commit("Erase Notes");
		drop_pivot();
	case Qt::Key_T:
		if (mod == Qt::CTRL) {
			int dPitch = QInputDialog::getInt(
				this,
				"vomid",
				QString("Transpose (in semi-tones):")
			);
			if (dPitch == 0)
				break;
			for (vmd_note_t *i = selection(), *next; i != NULL; i = next) {
				next = i->next;
				vmd_copy_note(i, track(), 0, dPitch);
				vmd_erase_note(i);
			}
			file()->commit("Transpose");
		}
	default:
		return QWidget::keyPressEvent(ev);
	}
	look_at_cursor();
	update();
}