Пример #1
0
// shape functions
QRectF Node::outline_rect() const
{
    QFontMetricsF metrics = qApp->fontMetrics();
    QRectF outline_rect = metrics.boundingRect(text);
    outline_rect.adjust(-iWidthPadding, -iHeightPadding, iWidthPadding, iHeightPadding);
    outline_rect.translate(-outline_rect.center());
    return outline_rect;
}
Пример #2
0
QRectF QNodeItem::outlineRect() const
{
    const int Padding = 6;
    QFontMetricsF metrics = qApp->font();
    QRectF rect = metrics.boundingRect(text);
    rect.adjust(-Padding, -Padding, +Padding, +Padding);
    rect.translate(-rect.center());
    return rect;
}
Пример #3
0
QRectF usecaseclass::outlineRect() const
{
    const int Padding = 60;
    QFontMetricsF metrics = qApp->font();
    QRectF rect = metrics.boundingRect(myText);
    rect.adjust(-Padding, -Padding, +Padding, +Padding);
    rect.translate(-rect.center());
    return rect;
}
void tst_QQuickTextMetrics::functionsWithArguments()
{
    QFETCH(QString, text);
    QFETCH(Qt::TextElideMode, mode);
    QFETCH(qreal, width);

    QQuickTextMetrics metrics;
    // Ensures that the values actually change.
    metrics.setText(text + "extra");
    metrics.setElideWidth(width + 1);
    switch (mode) {
        case Qt::ElideNone: metrics.setElide(Qt::ElideMiddle); break;
        case Qt::ElideLeft: metrics.setElide(Qt::ElideRight); break;
        case Qt::ElideMiddle: metrics.setElide(Qt::ElideNone); break;
        case Qt::ElideRight: metrics.setElide(Qt::ElideLeft); break;
    }

    QSignalSpy textSpy(&metrics, SIGNAL(textChanged()));
    QSignalSpy metricsSpy(&metrics, SIGNAL(metricsChanged()));
    metrics.setText(text);
    QCOMPARE(textSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 1);

    QSignalSpy elideSpy(&metrics, SIGNAL(elideChanged()));
    metrics.setElide(mode);
    QCOMPARE(elideSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 2);

    QSignalSpy elideWidthSpy(&metrics, SIGNAL(elideWidthChanged()));
    metrics.setElideWidth(width);
    QCOMPARE(elideWidthSpy.count(), 1);
    QCOMPARE(metricsSpy.count(), 3);

    QFontMetricsF expected = QFontMetricsF(QFont());

    QCOMPARE(metrics.elidedText(), expected.elidedText(text, mode, width, 0));
    QCOMPARE(metrics.advanceWidth(), expected.width(text));
    QCOMPARE(metrics.boundingRect(), expected.boundingRect(text));
    QCOMPARE(metrics.width(), expected.boundingRect(text).width());
    QCOMPARE(metrics.height(), expected.boundingRect(text).height());
    QCOMPARE(metrics.tightBoundingRect(), expected.tightBoundingRect(text));
}
Пример #5
0
void VerticalViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	QRectF rect = boundingRect();

	QString symboldir = QString("%1/images").arg(ConfigParser::getInstance().envMapDir());
	QDir dir(symboldir);
	if (!dir.exists()) return;

	QPen pen(Qt::black);
	painter->setPen(pen);

	QFont font(qApp->font());
	font.setPointSize(9);
	font.setBold(true);
	painter->setFont(font);

	QFontMetricsF metrics = qApp->font();
	QRectF fontRect;
	int maxData = 0;
	if (mode == 0) {
		maxData = getMaxAlt() * 25;	// feet
	}else {
		maxData = getMaxAlt();
	}

	qDebug() << maxData;

	if (mode == 0) {			// Altitude

		// 고도의 max 값을 구한다.
		if (maxData < 6) {
			painter->drawText(QPoint(20,  20), "Altitude");
			painter->drawText(QPoint(20,  40), " (Feet)");
			painter->drawText(QPoint(20, 100), "       6");
			painter->drawText(QPoint(20, 190), "       5");
			painter->drawText(QPoint(20, 280), "       4");
			painter->drawText(QPoint(20, 370), "       3");
			painter->drawText(QPoint(20, 460), "       2");
			painter->drawText(QPoint(20, 550), "       1");
		}else {

			int size = (int)(maxData / 6);
			QString t1 = QString("%1").arg(QString("%1").arg(size),     -8, ' ');
			QString t2 = QString("%1").arg(QString("%1").arg(size * 2), -8, ' ');
			QString t3 = QString("%1").arg(QString("%1").arg(size * 3), -8, ' ');
			QString t4 = QString("%1").arg(QString("%1").arg(size * 4), -8, ' ');
			QString t5 = QString("%1").arg(QString("%1").arg(size * 5), -8, ' ');
			QString t6 = QString("%1").arg(QString("%1").arg(maxData), -8, ' ');

			painter->drawText(QPoint(20,  20), "Altitude");
			painter->drawText(QPoint(20,  40), " (Feet)");
			painter->drawText(QPoint(20, 100), t6);
			painter->drawText(QPoint(20, 190), t5);
			painter->drawText(QPoint(20, 280), t4);
			painter->drawText(QPoint(20, 370), t3);
			painter->drawText(QPoint(20, 460), t2);
			painter->drawText(QPoint(20, 550), t1);
		}
		fontRect = metrics.boundingRect("Altitude  ");

	}else if(mode == 1) {	// Speed
		if (maxData < 6) {
			painter->drawText(QPoint(20,  20), "   Speed");
			painter->drawText(QPoint(20,  40), "   (NM) ");
			painter->drawText(QPoint(20, 100), "       6");
			painter->drawText(QPoint(20, 190), "       5");
			painter->drawText(QPoint(20, 280), "       4");
			painter->drawText(QPoint(20, 370), "       3");
			painter->drawText(QPoint(20, 460), "       2");
			painter->drawText(QPoint(20, 550), "       1");
		}else {
			int size = (int)(maxData / 6);
			QString t1 = QString("%1").arg(QString("%1").arg(size),     -8, ' ');
			QString t2 = QString("%1").arg(QString("%1").arg(size * 2), -8, ' ');
			QString t3 = QString("%1").arg(QString("%1").arg(size * 3), -8, ' ');
			QString t4 = QString("%1").arg(QString("%1").arg(size * 4), -8, ' ');
			QString t5 = QString("%1").arg(QString("%1").arg(size * 5), -8, ' ');
			QString t6 = QString("%1").arg(QString("%1").arg(maxData), -8, ' ');

			painter->drawText(QPoint(20,  20), "   Speed");
			painter->drawText(QPoint(20,  40), "   (NM) ");
			painter->drawText(QPoint(20, 100), t6);
			painter->drawText(QPoint(20, 190), t5);
			painter->drawText(QPoint(20, 280), t4);
			painter->drawText(QPoint(20, 370), t3);
			painter->drawText(QPoint(20, 460), t2);
			painter->drawText(QPoint(20, 550), t1);
		}
		fontRect = metrics.boundingRect("Speed     ");
	}
	// 가로 / 세로 라인
	painter->drawLine(QPoint(fontRect.width()+cap, 20),  QPoint(fontRect.width()+cap, 640));
	painter->drawLine(QPoint(fontRect.width()+cap, 640), QPoint(widthDef+fontRect.width()+cap, 640));

	// 고도 라인
	pen.setStyle(Qt::DotLine);
	painter->setPen(pen);
	painter->drawLine(QPoint(fontRect.width()+cap, 100),QPoint(widthDef+fontRect.width()+cap, 100));
	painter->drawLine(QPoint(fontRect.width()+cap, 190),QPoint(widthDef+fontRect.width()+cap, 190));
	painter->drawLine(QPoint(fontRect.width()+cap, 280),QPoint(widthDef+fontRect.width()+cap, 280));
	painter->drawLine(QPoint(fontRect.width()+cap, 370),QPoint(widthDef+fontRect.width()+cap, 370));
	painter->drawLine(QPoint(fontRect.width()+cap, 460),QPoint(widthDef+fontRect.width()+cap, 460));
	painter->drawLine(QPoint(fontRect.width()+cap, 550),QPoint(widthDef+fontRect.width()+cap, 550));

	// Time 추출 - 타임 라인
	int timeCount = timeList.size();
	int lineWidth = (int)((widthDef-100)/timeCount);		// time pixel per line width
	int secWidth  = (int)(lineWidth/plus);						// 1 second per pixel
	int printWidth = lineWidth;

	//qDebug() << timeCount;
	for (int i=0; i<timeCount; i++) {
		// Time line 출력
		painter->drawLine(QPoint(fontRect.width()+cap+printWidth, 20),  QPoint(fontRect.width()+cap+printWidth, 640));
		painter->drawText(QPoint(fontRect.width()+printWidth, 640+15), timeList[i].toString("hh:mm:ss"));

		printWidth += lineWidth;
	}

	//qDebug() << "secWidth : " << secWidth << ", lineWidth : " << lineWidth;

	// 고도에 따른 트랙 출력
	QTime minTime = timeList.at(0);

	// 데이터 블록은 서로 겹쳐 보일 수 있으로 출력시 +- 80 으로 해서 지그재그로 보일 수 있도록 한다.
	int dataBlock = 80;
	int idx       = 0;

	for (int i=0; i<model.size(); i++) {
		// TrackDataModel
		//qDebug() << "dataModel size : " << model[i].dataModel.size();
		for (int j=0; j<model[i].dataModel.size(); j++) {
			//qDebug() << model[i].dataModel[j].occur_dt;

			if (mode == 0) {		// altitude
				if (model[i].dataModel[j].alt == 0) continue;		   // alt = 0 에 대해서 처리하지 않는다.
			}else if(mode == 1) {	// speed
				if (model[i].dataModel[j].spd == 0) continue;			// spd = 0 에 대해서 처리하지 않는다.
			}
			idx++;

			QString occur_dt = model[i].dataModel[j].occur_dt;		// datetime
			QString tm = occur_dt.right(8);
			QTime t = QTime::fromString(tm, "hh:mm:ss");
			int sec = minTime.secsTo(t);

			int secPixel = sec * secWidth;

			//qDebug() << "sec : " << sec << ", secPixel : " << secPixel;
			QString fullname;
			if (model[i].dataModel[j].psr == "0" && model[i].dataModel[j].ssr == "1") {       // PSR only
				fullname = QString("%1%2%3").arg(symboldir).arg(QDir::separator()).arg("psr_only.xpm");
			}else if (model[i].dataModel[j].psr == "1" && model[i].dataModel[j].ssr == "0") { // SSR only
				fullname = QString("%1%2%3").arg(symboldir).arg(QDir::separator()).arg("ssr_only.xpm");
			}else if(model[i].dataModel[j].cst == "1") {									// Coasting
				fullname = QString("%1%2%3").arg(symboldir).arg(QDir::separator()).arg("coasting_only.xpm");
			}else {
				fullname = QString("%1%2%3").arg(symboldir).arg(QDir::separator()).arg(model[i].symbol);
			}

			//QString fullname = QString("%1%2%3").arg(symboldir).arg(QDir::separator()).arg(model[i].symbol);
			QPixmap icon2;
			icon2.load(fullname);
			QPixmap icon = icon2.scaled(QSize(10, 10));

			QPixmap batang(QSize(icon.width()+1, icon.height()+1));
			batang.fill(QColor(0, 0, 0));

			QPainter pp(&batang);
			pp.drawPixmap(0, 0, icon);

			// 고도
			int alt = 0;

			if (mode == 0) {			// Altitude
				alt = model[i].dataModel[j].alt;				// unit = FL
				alt = alt * 25;	// 1FL = 25 ft
			}else if(mode == 1) {	// Speed
				alt = (int)model[i].dataModel[j].spd;		// unit = NM
			}

			int fixel = 0;

			if (mode == 0) {			// Altitude
				// max 고도에서 640을 나눈 값을 곱한다.
				double s = 544.0 / maxData;
				// 1ft = 0.018 fixel
				fixel = (int)(s * alt);	// 고도 대 픽셀 위치

				qDebug() << "s : " << s << ", fixel : " << fixel;
			}else if(mode == 1) {	// Speed
				double s = 544.0 / maxData;
				fixel = (int)(s * alt);	   // 속도 대 픽셀 위치
			}

			painter->drawPixmap(QPoint(fontRect.width()+18+lineWidth+secPixel, 640 - fixel), batang);

			// Altitude와 Speed가 같다면 계속적으로 데이터 블럭을 표현할 필요가 없다.
			if (model[i].dataModel[j].alt == model[i].dataModel[j].prev_alt
					&& model[i].dataModel[j].spd == model[i].dataModel[j].prev_spd) {
				continue;
			}

			// 데이터 블럭 출력 옵션에 따라서 출력한다.
			if (rptOption->blockCount > 0) {
				if ((j+1) != 1) {		// first data
					//qDebug() << "blockCount : " << rptOption->blockCount;
					//qDebug() << "myNumber   : " << (j+1);
					//qDebug() << "cal        : " << ((j+1) / rptOption->blockCount);
					if ((j+1) % rptOption->blockCount != 0) {
						continue;
					}
				}
			}

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			// Data block define
			QPen pen(Qt::black);
			QColor textColor = Qt::black;
			painter->setPen(pen);
			if (idx%2) {
				dataBlock = -40;
			}else {
				dataBlock = +80;
			}


			QString msg = "";
			//////////////////////////////////////////////////////////////
			// 경보 상태가 있다면...

			//////////////////////////////////////////////////////////////
			int found = 0;
			int tmpHeight = 15;
			if (rptOption->trackNumber && model[i].dataModel[j].type == 0) {	// track data
				msg += QString("%1").arg(model[i].trackNo);
			}else {
				msg += "     ";
			}
			if (rptOption->ssr && model[i].dataModel[j].type == 0) {		// ReportOption check
				msg += QString("/%1").arg(model[i].ssr)+"\n";
			}else {
				msg += "    \n";
			}
			tmpHeight += 15;

			// 하강, 상승
			QString climb;
			if (model[i].dataModel[j].climb > 0) {		// 상승
				climb = "^";
			}else if(model[i].dataModel[j].climb == 0) {  // 수평비행
				climb = "-";
			}else {
				climb = "V";
			}
			QString cfl;
			if (model[i].dataModel[j].cfl == 0) {
				cfl = "";
			}else {
				cfl = QString("%1").arg(model[i].dataModel[j].cfl);
			}
			// 고도 | 상승,하강 | 배정고도 | 속도
			found = 0;
			QString tmp = "";
			if (rptOption->modec) {
				msg += QString("%1 %2 ").arg(model[i].dataModel[j].alt).arg(climb);
				found = 1;
			}else {
				msg += "    ";
			}
			if (rptOption->assignedFL && model[i].dataModel[j].type == 0) {
				msg += QString( "%1 ").arg(cfl);
				found = 1;
			}else {
				msg += "   ";
			}
			if (rptOption->velocity) {
				msg += QString(" /%1 \n").arg((int)model[i].dataModel[j].spd);
				found = 1;
			}else {
				msg += " /  \n";
			}
			tmpHeight += 15;
			QString callsign = model[i].callsign;
			if (callsign != "" && rptOption->callsing) {
				msg += callsign  + "/ ";  // + QString(" %1").arg(airplane->getTrackData().wt_type);
			}

	//		// 기종과 목적 공항
	//		if (!airplane->getTrackData().actp.trimmed().isEmpty() && airplane->getTrackData().type == 0) {
	//			if (airplane->getReportOption()->trackNumber || callsign != "" && airplane->getReportOption()->callsing || found == 1) {
	//				msg += "\n";
	//			}
	//			msg += QString("%1     %2").arg(airplane->getTrackData().actp).arg(airplane->getTrackData().arr_ad);
	//			found = 2;
	//			tmpHeight += 15;
	//		}


			tmpHeight += 5;

			QRectF rect(
							QPointF(fontRect.width()+18+lineWidth+secPixel - 45, 640 - fixel - 50+dataBlock),
							QSizeF(100, tmpHeight));

			painter->drawRect(rect);
			painter->setPen(textColor);
			painter->drawText(rect, Qt::AlignCenter, msg);

			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			// Line
			int dim1 = 5;
			int dim2 = -10;
			painter->setPen(pen);

			if (idx%2) {
				painter->drawLine(QLineF(QPointF(fontRect.width()+18+lineWidth+secPixel+dim1,  640 - fixel - 50+dataBlock + 50),
						QPointF(fontRect.width()+18+lineWidth+secPixel+dim1, 640 - fixel - dim2)));
			}else {
				painter->drawLine(QLineF(QPointF(fontRect.width()+18+lineWidth+secPixel+dim1,  640 - fixel - 50+dataBlock ),
						QPointF(fontRect.width()+18+lineWidth+secPixel+dim1, 640 - fixel - dim2)));
			}
		}
	}

}
Пример #6
0
void TextObject::prepareLineInfos() const
{
	const TextSymbol* text_symbol = reinterpret_cast<const TextSymbol*>(symbol);
	
	double scaling = text_symbol->calculateInternalScaling();
	QFontMetricsF metrics = text_symbol->getFontMetrics();
	double line_spacing = text_symbol->getLineSpacing() * metrics.lineSpacing();
	double paragraph_spacing = scaling * text_symbol->getParagraphSpacing() + (text_symbol->hasLineBelow() ? (scaling * (text_symbol->getLineBelowDistance() + text_symbol->getLineBelowWidth())) : 0);
	double ascent = metrics.ascent();
	
	bool word_wrap = ! hasSingleAnchor();
	double box_width  = word_wrap ? (scaling * getBoxWidth())  : 0.0;
	double box_height = word_wrap ? (scaling * getBoxHeight()) : 0.0;
	
	int text_end = text.length();
	const QLatin1Char line_break('\n');
	const QLatin1Char part_break('\t');
	const QLatin1Char word_break(' ');
	
	line_infos.clear();
	
	// Initialize offsets
	
	double line_x = 0.0;
	if (h_align == TextObject::AlignLeft)
		line_x -= 0.5 * box_width;
	else if (h_align == TextObject::AlignRight)
		line_x += 0.5 * box_width;

	double line_y = 0.0;
	if (v_align == TextObject::AlignTop || v_align == TextObject::AlignBaseline)
		line_y += -0.5 * box_height;
	if (v_align != TextObject::AlignBaseline)
		line_y += ascent;
	
	// Determine lines and parts
	
	//double next_line_x_offset = 0; // to keep indentation after word wrap in a line with tabs
	int num_paragraphs = 0;
	int line_num = 0;
	int line_start = 0;
	while (line_start <= text_end) 
	{
		// Initialize input line
		double line_width = 0.0;
		int line_end = text.indexOf(line_break, line_start);
		if (line_end == -1)
			line_end = text_end;
		bool paragraph_end = true;
		
		std::vector<TextObjectPartInfo> part_infos;
		
		int part_start = line_start;
		double part_x = line_x;
		
		while (part_start <= line_end)
		{
			// Initialize part (sequence of letters terminated by tab or line break)
			int part_end = text.indexOf(part_break, part_start);
			if (part_end == -1)
				part_end = line_end;
			else if (part_end > line_end)
				part_end = line_end;
			
			if (part_start > 0 && text[part_start - 1] == part_break)
				part_x = line_x + text_symbol->getNextTab(part_x - line_x);
			
			QString part = text.mid(part_start, part_end - part_start);
			double part_width = metrics.boundingRect(part).width();
			
			if (word_wrap)
			{
				// shrink overflowing part to maximum possible size
				while (part_x + part_width - line_x > box_width)
				{
					// find latest possible break
					int new_part_end =  text.lastIndexOf(word_break, part_end - 1);
					if (new_part_end <= part_start)
					{
						// part won't fit
						if (part_start > line_start)
						{
							// don't put another part on this line
							part_end = part_start - 1;
							paragraph_end = false;
						}
						break;
					}
					
					paragraph_end = false;
					
					// Shrink the part and the line
					part_end = new_part_end;
					part = text.mid(part_start, part_end - part_start);
					part_width = metrics.width(part);
					line_end = part_end;
				}
			}
			if (part_end < part_start)
				break;
			
			// Add the current part
			part_infos.push_back( { part, part_start, part_end, part_x, metrics.width(part), metrics } );
			
			// Advance to next part position
			part_start = part_end + 1;
			part_x += part_width;
		}
		
		TextObjectPartInfo& last_part_info = part_infos.back();
		line_end   = last_part_info.end_index;
		line_width = last_part_info.part_x + last_part_info.width - line_x;
		
		// Jump over whitespace after the end of the line and check if it contains a newline character to determine if it is a paragraph end
		int next_line_start = line_end + 1;
		/*while (next_line_start < text.size() && (text[next_line_start] == line_break || text[next_line_start] == part_break || text[next_line_start] == word_break))
		{
			if (text[next_line_start - 1] == line_break)
			{
				paragraph_end = true;
				break;
			}
			++next_line_start;
		}*/
		
		line_infos.push_back( { line_start, line_end, paragraph_end, line_x, line_y, line_width, metrics.ascent(), metrics.descent(), part_infos } );
		
		// Advance to next line
		line_y += line_spacing;
		if (paragraph_end)
		{
			line_y += paragraph_spacing;
			num_paragraphs++;
		}
		line_num++;
		line_start = next_line_start;
	}
	
	// Update the line and part offset for every other alignment than top-left or baseline-left
	
	double delta_y = 0.0;
	if (v_align == TextObject::AlignBottom || v_align == TextObject::AlignVCenter)
	{
		int num_lines = getNumLines();
		double height = ascent + (num_lines - 1) * line_spacing + (num_paragraphs - 1) * paragraph_spacing;
		
		if (v_align == TextObject::AlignVCenter)
			delta_y = -0.5 * height;
		else if (v_align == TextObject::AlignBottom)
			delta_y = -height + 0.5 * box_height;
	}
	
	if (delta_y != 0.0 || h_align != TextObject::AlignLeft)
	{
		int num_lines = getNumLines();
		for (int i = 0; i < num_lines; i++)
		{
			TextObjectLineInfo* line_info = &line_infos[i];
			
			double delta_x = 0.0;
			if (h_align == TextObject::AlignHCenter)
				delta_x = -0.5 * line_info->width;
			else if (h_align == TextObject::AlignRight)
				delta_x -= line_info->width;
			
			line_info->line_x += delta_x;
			line_info->line_y += delta_y;
			
			int num_parts = line_info->part_infos.size();
			for (int j = 0; j < num_parts; j++)
			{
				line_info->part_infos.at(j).part_x += delta_x;
			}
		}
	}
}