void LegendItem::paint(QPainter *painter) { if (!isVisible()) { return; } RelationList legendItems; if (_auto) { legendItems = plot()->renderItem(PlotRenderItem::Cartesian)->relationList(); } else { legendItems = _relations; } int count = legendItems.count(); if (count <= 0) { // no legend or box if there are no legend items return; } QFont font(_font); font.setPointSizeF(view()->scaledFontSize(_fontScale, *painter->device())); painter->setFont(font); // generate string list of relation names QStringList names; bool allAuto = true; bool sameX = true; bool sameYUnits = true; LabelInfo label_info = legendItems.at(0)->xLabelInfo(); QString yUnits = legendItems.at(0)->yLabelInfo().units; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); if (relation->descriptiveNameIsManual()) { allAuto = false; } if (relation->xLabelInfo() != label_info) { sameX = false; } // sameYUnits is false if any non empty units are defined differently. if (yUnits.isEmpty()) { yUnits = relation->yLabelInfo().units; } else if (relation->yLabelInfo().units != yUnits) { if (!relation->yLabelInfo().units.isEmpty()) { sameYUnits = false; } } } if (!allAuto) { for (int i = 0; i<count; i++) { names.append(legendItems.at(i)->descriptiveName()); } } else { for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QString label = relation->titleInfo().singleRenderItemLabel(); if (label.isEmpty()) { label_info = relation->yLabelInfo(); QString y_label = label_info.name; if (!sameYUnits) { if (!label_info.units.isEmpty()) { y_label = tr("%1 \\[%2\\]", "axis labels. %1 is quantity, %2 is units. eg Time [s]. '[' must be escaped.").arg(y_label).arg(label_info.units); } } if (!y_label.isEmpty()) { LabelInfo xlabel_info = relation->xLabelInfo(); if (!sameX) { label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); } else if (xlabel_info.quantity.isEmpty()) { label = y_label; } else if (xlabel_info.quantity != xlabel_info.name) { label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); } else { label = y_label; } } else { label = relation->descriptiveName(); } } int i_dup = names.indexOf(label); if (i_dup<0) { names.append(label); } else { RelationPtr dup_relation = legendItems.at(i_dup); if (!dup_relation->yLabelInfo().file.isEmpty()) { names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().escapedFile() + ')'); } if (!relation->yLabelInfo().file.isEmpty()) { names.append(label + " (" + relation->yLabelInfo().escapedFile() + ')'); } } } } QSize legendSize(0, 0); QSize titleSize(0,0); Label::Parsed *parsed = Label::parse(_title); int pad = painter->fontMetrics().ascent()/4; Label::RenderContext rc(painter->font(), painter); Label::renderLabel(rc, parsed->chunk, false, false); if (!_title.isEmpty()) { titleSize.setWidth(rc.x+3*pad); titleSize.setHeight(painter->fontMetrics().height()+pad); } QList<QSize> sizes; int max_w = 0; int max_h = 0; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QSize size; painter->save(); size = paintRelation(names.at(i), relation, painter, false); painter->restore(); sizes.append(size); max_w = qMax(max_w, size.width()); max_h = qMax(max_h, size.height()); } // determine number of rows and number of columns int n_rows = 0; int n_cols = 0; if (_verticalDisplay) { int h=titleSize.height(); for (int i = 0; i<count; i++) { h+=sizes.at(i).height(); } int max_legend_height = _plotItem->plotRect().height()*0.6+1; n_cols = qMin(count, h / max_legend_height + 1); n_rows = count / n_cols; while (n_rows*n_cols<count) { n_rows++; } } else { int w = 0; for (int i = 0; i<count; i++) { w+=sizes.at(i).width(); } int max_legend_width = _plotItem->plotRect().width()*0.8+1; n_rows = qMin(count, w / max_legend_width+1); n_cols = count/n_rows; while (n_rows*n_cols<count) { n_cols++; } } // determine the dimensions of each column QList<QSize> col_sizes; for (int i=0; i<n_cols; i++) { col_sizes.append(QSize(0,0)); } for (int i = 0; i<count; i++) { int col = i/n_rows; col_sizes[col].rheight()+= sizes.at(i).height(); col_sizes[col].setWidth(qMax(sizes.at(i).width(), col_sizes.at(col).width())); } // determine the dimensions of the legend int w = 0; int h = 0; for (int col = 0; col < n_cols; col++) { w += col_sizes.at(col).width(); h = qMax(h, col_sizes.at(col).height()); } legendSize.setHeight(h + titleSize.height()); legendSize.setWidth(qMax(titleSize.width(), w)); setViewRect(rect().x(), rect().y(), legendSize.width()+pad, legendSize.height()+pad); // Now paint everything painter->drawRect(rect()); int x=rect().x(); int y=rect().y(); if (!_title.isEmpty()) { rc.y = rect().y() + titleSize.height()-pad; rc.x = qMax(rect().x()+pad, rect().x() + legendSize.width()/2 - titleSize.width()/2); Label::renderLabel(rc, parsed->chunk, false, true); y+= titleSize.height(); } legendSize.setWidth(0); legendSize.setHeight(0); for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); painter->save(); painter->translate(x,y); paintRelation(names.at(i), relation, painter, true); painter->restore(); int col = i/n_rows; int row = i%n_rows; if (row == n_rows-1) { // end of a column x += col_sizes.at(col).width(); y = rect().y() + titleSize.height(); } else { y += sizes.at(i).height(); } } delete parsed; }
void LegendItem::paint(QPainter *painter) { if (!isVisible()) { return; } RelationList legendItems; if (_auto) { legendItems = plot()->renderItem(PlotRenderItem::Cartesian)->relationList(); } else { legendItems = _relations; } int count = legendItems.count(); if (count <= 0) { // no legend or box if there are no legend items return; } QList<DrawnLegendItem> legendPixmaps; QSize legendSize(0, 0); QFont font(_font); font.setPointSizeF(view()->viewScaledFontSize(_fontScale)); // generate string list of relation names QStringList names; bool allAuto = true; bool sameX = true; bool sameYUnits = true; LabelInfo label_info = legendItems.at(0)->xLabelInfo(); QString yUnits = legendItems.at(0)->yLabelInfo().units; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); if (relation->descriptiveNameIsManual()) { allAuto = false; } if (relation->xLabelInfo() != label_info) { sameX = false; } // sameYUnits is false if any non empty units are defined differently. if (yUnits.isEmpty()) { yUnits = relation->yLabelInfo().units; } else if (relation->yLabelInfo().units != yUnits) { if (!relation->yLabelInfo().units.isEmpty()) { sameYUnits = false; } } } if (!allAuto) { for (int i = 0; i<count; i++) { names.append(legendItems.at(i)->descriptiveName()); } } else { for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QString label = relation->titleInfo().singleRenderItemLabel(); if (label.isEmpty()) { label_info = relation->yLabelInfo(); QString y_label = label_info.name; if (!sameYUnits) { if (!label_info.units.isEmpty()) { y_label = i18n("%1 \\[%2\\]").arg(y_label).arg(label_info.units); } } if (!y_label.isEmpty()) { LabelInfo xlabel_info = relation->xLabelInfo(); if (!sameX) { label = i18n("%1 vs %2").arg(y_label).arg(xlabel_info.name); } else if (xlabel_info.quantity.isEmpty()) { label = y_label; } else if (xlabel_info.quantity != xlabel_info.name) { label = i18n("%1 vs %2").arg(y_label).arg(xlabel_info.name); } else { label = y_label; } } else { label = relation->descriptiveName(); } } int i_dup = names.indexOf(label); if (i_dup<0) { names.append(label); } else { RelationPtr dup_relation = legendItems.at(i_dup); if (!dup_relation->yLabelInfo().file.isEmpty()) { names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().file + ')'); } if (!relation->yLabelInfo().file.isEmpty()) { names.append(label + " (" + relation->yLabelInfo().file + ')'); } } } } for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); DrawnLegendItem item; item.pixmap = QPixmap(LEGENDITEMMAXWIDTH, LEGENDITEMMAXHEIGHT); item.size = paintRelation(names.at(i), relation, &item.pixmap, font); if (_verticalDisplay) { legendSize.setWidth(qMax(legendSize.width(), item.size.width())); legendSize.setHeight(legendSize.height() + item.size.height()); } else { legendSize.setHeight(qMax(legendSize.height(), item.size.height())); legendSize.setWidth(legendSize.width() + item.size.width()); } legendPixmaps.append(item); } int x = rect().left(); int y = rect().top(); painter->save(); if (!_title.isEmpty()) { // Paint the title Label::Parsed *parsed = Label::parse(_title); if (parsed) { painter->save(); QPixmap pixmap(400, 100); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); Label::RenderContext rc(font, &pixmapPainter); QFontMetrics fm(font); rc.y = fm.ascent(); Label::renderLabel(rc, parsed->chunk, false); int startPoint = qMax(0, (legendSize.width() / 2) - (rc.x / 2)); int paddingValue = fm.height() / 4; setViewRect(viewRect().x(), viewRect().y(), qMax(rc.x, legendSize.width()), rc.y + legendSize.height() + paddingValue * 3); painter->drawRect(rect()); painter->drawPixmap(QPoint(x + startPoint, y + paddingValue), pixmap, QRect(0, 0, rc.x, fm.height())); painter->restore(); y += fm.height() + (paddingValue *2); delete parsed; parsed = 0; } } else { // No Title setViewRect(viewRect().x(), viewRect().y(), legendSize.width(), legendSize.height()); painter->drawRect(rect()); } foreach(const DrawnLegendItem &item, legendPixmaps) { painter->drawPixmap(QPoint(x, y), item.pixmap, QRect(0, 0, item.size.width(), item.size.height())); if (_verticalDisplay) { y += item.size.height(); } else { x += item.size.width(); } }