You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
12 KiB
363 lines
12 KiB
/***************************************************************************
|
|
* Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
***************************************************************************/
|
|
#include "device_group.h"
|
|
|
|
#if !defined(NO_KDE)
|
|
# include <tqpainter.h>
|
|
# include <kglobal.h>
|
|
|
|
TQColor Device::statusColor(Status status)
|
|
{
|
|
switch (status.type()) {
|
|
case Status::Future: return TQt::blue;
|
|
case Status::InProduction: return TQt::green;
|
|
case Status::Mature:
|
|
case Status::NotRecommended: return TQColor("orange");
|
|
case Status::EOL: return TQt::red;
|
|
case Status::Unknown:
|
|
case Status::Nb_Types: break;
|
|
}
|
|
return TQt::black;
|
|
}
|
|
|
|
TQString coloredString(const TQString &text, TQColor color)
|
|
{
|
|
return TQString("<font color=\"") + color.name() + "\">" + text + "</font>";
|
|
}
|
|
|
|
TQString supportedString(bool supported)
|
|
{
|
|
return coloredString(supported ? i18n("Supported") : i18n("Unsupported"),
|
|
supported ? TQt::green : TQt::red);
|
|
}
|
|
|
|
class Tick {
|
|
public:
|
|
Tick() {}
|
|
Tick(double value, double oValue) {
|
|
s = KGlobal::locale()->formatNumber(value, 1);
|
|
min = oValue;
|
|
}
|
|
TQString s;
|
|
double min;
|
|
};
|
|
|
|
class TickMap : public TQMap<double, Tick>
|
|
{
|
|
public:
|
|
TickMap() {}
|
|
void add(double value, double oValue) {
|
|
insert(value, Tick(value, oValue), false);
|
|
(*this)[value].min = TQMIN((*this)[value].min, oValue);
|
|
}
|
|
};
|
|
|
|
TQPixmap drawGraph(const TQValueVector<Device::RangeBox> &boxes)
|
|
{
|
|
const uint w = 300, h = 200;
|
|
TQPixmap pixmap(w, h);
|
|
pixmap.fill(TQt::white);
|
|
TQPainter p(&pixmap);
|
|
TQFontMetrics f(p.font());
|
|
TickMap xTicks, yTicks;
|
|
xTicks.add(0.0, 0.0);
|
|
yTicks.add(0.0, 0.0);
|
|
for (uint i=0; i<boxes.count(); i++) {
|
|
// qDebug("box #%i: %f=[%f %f] %f=[%f %f]", i, boxes[i].start.x, boxes[i].start.yMin,
|
|
// boxes[i].start.yMax, boxes[i].end.x, boxes[i].end.yMin, boxes[i].end.yMax);
|
|
xTicks.add(boxes[i].start.x, boxes[i].start.yMin);
|
|
xTicks.add(boxes[i].start.x, boxes[i].start.yMax);
|
|
xTicks.add(boxes[i].end.x, boxes[i].end.yMin);
|
|
xTicks.add(boxes[i].end.x, boxes[i].end.yMax);
|
|
yTicks.add(boxes[i].start.yMin, boxes[i].start.x);
|
|
yTicks.add(boxes[i].start.yMax, boxes[i].start.x);
|
|
yTicks.add(boxes[i].end.yMin, boxes[i].end.x);
|
|
yTicks.add(boxes[i].end.yMax, boxes[i].end.x);
|
|
}
|
|
double xMax = 0.0, yMax = 0.0;
|
|
int xStart = 0;
|
|
int yStart = h-1 - f.lineSpacing();
|
|
TickMap::const_iterator it = xTicks.begin();
|
|
for (; it!=xTicks.end(); ++it) {
|
|
xStart = TQMAX(xStart, f.width(it.data().s));
|
|
xMax = TQMAX(xMax, it.key());
|
|
}
|
|
for (it = yTicks.begin(); it!=yTicks.end(); ++it)
|
|
yMax = TQMAX(yMax, it.key());
|
|
int xEnd = w-1 - f.width(xTicks[xMax].s)/2;
|
|
TQRect rect = f.boundingRect(yTicks[yMax].s);
|
|
int yEnd = rect.height()/2;
|
|
|
|
// draw boxes
|
|
p.setPen(TQt::lightGray);
|
|
p.setBrush(TQt::lightGray);
|
|
for (uint i=0; i<boxes.count(); i++) {
|
|
double ax = double(xEnd - xStart)/xMax;
|
|
double ay = double(yEnd - yStart)/yMax;
|
|
TQPointArray pa(4);
|
|
pa.setPoint(0, tqRound(ax*boxes[i].start.x), tqRound(ay*boxes[i].start.yMin));
|
|
pa.setPoint(1, tqRound(ax*boxes[i].end.x), tqRound(ay*boxes[i].end.yMin));
|
|
pa.setPoint(2, tqRound(ax*boxes[i].end.x), tqRound(ay*boxes[i].end.yMax));
|
|
pa.setPoint(3, tqRound(ax*boxes[i].start.x), tqRound(ay*boxes[i].start.yMax));
|
|
pa.translate(xStart, yStart);
|
|
p.drawPolygon(pa);
|
|
}
|
|
|
|
// draw axis
|
|
p.setPen(TQt::black);
|
|
p.drawLine(xStart, yStart, w-1, yStart);
|
|
p.drawLine(xStart, yStart, xStart, 0);
|
|
|
|
// draw ticks and lines
|
|
p.setPen(TQt::DotLine);
|
|
for (it = yTicks.begin(); it!=yTicks.end(); ++it) {
|
|
int y1 = yStart + tqRound(it.key()*(yEnd-yStart)/yMax);
|
|
TQRect rect = f.boundingRect(it.data().s);
|
|
p.drawText(xStart/2-rect.width()/2 , y1+rect.height()/2, it.data().s);
|
|
int xmin = xStart + tqRound(it.data().min*(xEnd-xStart)/xMax);
|
|
p.drawLine(xStart, y1, xmin, y1);
|
|
}
|
|
for (it = xTicks.begin(); it!=xTicks.end(); ++it) {
|
|
int x1 = xStart + tqRound(it.key()*(xEnd-xStart)/xMax);
|
|
TQRect rect = f.boundingRect(it.data().s);
|
|
p.drawText(x1-rect.width()/2, h-1, it.data().s);
|
|
int ymin = yStart + tqRound(it.data().min*(yEnd-yStart)/yMax);
|
|
p.drawLine(x1, yStart, x1, ymin);
|
|
}
|
|
|
|
return pixmap;
|
|
}
|
|
|
|
TQPixmap Device::vddGraph(const TQString &xLabel, const TQString &yLabel,
|
|
const TQValueVector<Device::RangeBox> &boxes)
|
|
{
|
|
uint sp = 10;
|
|
TQPixmap graph = drawGraph(boxes);
|
|
TQPainter p;
|
|
TQFontMetrics f(p.font());
|
|
TQPixmap pixmap(graph.width() + sp + f.width(xLabel), graph.height() + sp + f.lineSpacing());
|
|
pixmap.fill(TQt::white);
|
|
copyBlt(&pixmap, 0, f.lineSpacing() + sp, &graph, 0, 0, graph.width(), graph.height());
|
|
p.begin(&pixmap);
|
|
p.setPen(TQt::black);
|
|
p.drawText(0, f.lineSpacing(), yLabel);
|
|
p.drawText(pixmap.width()-1-f.width(xLabel), pixmap.height()-1, xLabel);
|
|
return pixmap;
|
|
}
|
|
|
|
const Device::Package *Device::barPackage(const char *name, const Device::Data &data)
|
|
{
|
|
for (uint i=0; i<data.packages().count(); i++)
|
|
for (uint k=0; k<data.packages()[i].types.count(); k++)
|
|
if ( Package::TYPE_DATA[data.packages()[i].types[k]].name==name ) return &data.packages()[i];
|
|
return 0;
|
|
}
|
|
|
|
TQPixmap Device::pinsGraph(const Device::Package &package)
|
|
{
|
|
TQPixmap pixmap;
|
|
TQPainter p;
|
|
TQFontMetrics fm(p.font());
|
|
uint nb = package.pins.count();
|
|
const int hspacing = 3, wspacing = 3, wmark = 10, wpin = 4;
|
|
int theight = fm.ascent() + (fm.ascent()%2==0 ? 1 : 0);
|
|
int height = hspacing + (nb/2)*(hspacing + theight);
|
|
int wnumber = fm.width("1");
|
|
wnumber = TQMAX(wnumber, fm.width(TQString::number(nb/2)));
|
|
wnumber = TQMAX(wnumber, fm.width(TQString::number(nb/2+1)));
|
|
wnumber = TQMAX(wnumber, fm.width(TQString::number(nb)));
|
|
int bwidth = 4*wspacing + 2*wnumber + wmark;
|
|
int lwidth = 0, rwidth = 0;
|
|
for (uint k=0; k<nb/2; k++) {
|
|
lwidth = TQMAX(lwidth, fm.width(package.pins[k]));
|
|
rwidth = TQMAX(rwidth, fm.width(package.pins[nb-k-1]));
|
|
}
|
|
int bx = lwidth + wspacing + wpin;
|
|
int width = bx + bwidth + wpin + wspacing + rwidth;
|
|
pixmap.resize(width, height);
|
|
pixmap.fill(TQt::white);
|
|
p.begin(&pixmap);
|
|
p.setPen(TQPen(TQt::black, 2));
|
|
p.drawRect(bx, 1, bwidth, height-1);
|
|
p.drawArc(bx+wspacing+wnumber+wspacing, -wmark/2+2, wmark, wmark, 0, -180*16);
|
|
for (uint k=0; k<nb/2; k++) {
|
|
int h = hspacing + theight/2 + k*(hspacing + theight);
|
|
p.drawLine(bx-wpin-1, h, bx, h);
|
|
p.drawLine(bx+bwidth, h, bx+bwidth+wpin, h);
|
|
h += theight/2;
|
|
TQString label = package.pins[k];
|
|
p.drawText(bx-wpin-wspacing-fm.width(label), h, label);
|
|
p.drawText(bx+bwidth+wpin+wspacing, h, package.pins[nb-k-1]);
|
|
uint pin = (k+1);
|
|
if ( pin==1 || pin==(nb/2) ) {
|
|
p.drawText(bx+wspacing, h, TQString::number(pin));
|
|
label = TQString::number(nb-k);
|
|
p.drawText(bx+bwidth-wspacing-fm.width(label), h, label);
|
|
}
|
|
}
|
|
p.end();
|
|
return pixmap;
|
|
}
|
|
|
|
TQString Device::htmlInfo(const Device::Data &data, const TQString &deviceHref, const TQString &documentHtml)
|
|
{
|
|
TQString doc;
|
|
|
|
// title
|
|
doc += "<h1>";
|
|
bool first = true;
|
|
FOR_EACH(Special, special) {
|
|
for (uint k=0; k<data.frequencyRanges().count(); k++) {
|
|
if ( data.frequencyRanges()[k].special!=special ) continue;
|
|
if (first) first = false;
|
|
else doc += " / ";
|
|
doc += data.fname(special);
|
|
break;
|
|
}
|
|
}
|
|
doc += "</h1>";
|
|
|
|
doc += "<table>";
|
|
TQString status = coloredString(data.status().label(), statusColor(data.status()));
|
|
doc += htmlTableRow(i18n("Status"), status);
|
|
if ( data.alternatives().count() ) {
|
|
TQString s;
|
|
for (uint i=0; i<data.alternatives().count(); i++) {
|
|
if ( i!=0 ) s += ", ";
|
|
if ( deviceHref.isEmpty() ) s += data.alternatives()[i].upper();
|
|
else {
|
|
TQString href = deviceHref.tqarg(data.alternatives()[i].upper());
|
|
s += TQString("<a href=\"%1\">%2</a>").tqarg(href).tqarg(data.alternatives()[i].upper());
|
|
}
|
|
}
|
|
doc += htmlTableRow(i18n("Alternatives"), s);
|
|
}
|
|
doc += documentHtml;
|
|
doc += "</table>";
|
|
|
|
doc += "<hr />";
|
|
doc += "<table>";
|
|
doc += data.group().informationHtml(data);
|
|
TQString s;
|
|
for (uint i=0; i<data.packages().count(); i++)
|
|
for (uint k=0; k<data.packages()[i].types.count(); k++)
|
|
s += i18n(Package::TYPE_DATA[data.packages()[i].types[k]].label) + TQString("[%1] ").tqarg(data.packages()[i].pins.count());
|
|
doc += htmlTableRow(i18n("Packaging"), s);
|
|
doc += "</table>";
|
|
|
|
return doc;
|
|
}
|
|
|
|
TQString Device::htmlPinDiagrams(const Device::Data &data, const TQString &imagePrefix, TQMimeSourceFactory *msf)
|
|
{
|
|
TQString doc;
|
|
// pins
|
|
const Package *package = 0;
|
|
for (uint i=0; Package::TYPE_DATA[i].name; i++) {
|
|
if ( Package::TYPE_DATA[i].tqshape!=Package::Bar ) continue;
|
|
package = barPackage(Package::TYPE_DATA[i].name, data);
|
|
if (package) break;
|
|
}
|
|
if (package) {
|
|
TQPixmap pix = pinsGraph(*package);
|
|
doc += "<table cellpadding=\"3\"><tr bgcolor=\"gray\"><th align=\"center\">";
|
|
for (uint k=0; k<package->types.count(); k++) {
|
|
if ( k!=0 ) doc += " ";
|
|
doc += i18n(Package::TYPE_DATA[package->types[k]].label);
|
|
doc += "(" + TQString::number(package->pins.count()) + ")";
|
|
}
|
|
doc += "</th></tr><tr><td align=\"center\">";
|
|
TQString label = data.name() + "_pins_graph.png";
|
|
doc += "<img src=\"" + imagePrefix + label + "\" />";
|
|
if (msf) msf->setPixmap(label, pix);
|
|
doc += "</td></tr></table>";
|
|
}
|
|
return doc;
|
|
}
|
|
|
|
TQString Device::htmlVoltageFrequencyGraphs(const Device::Data &data, const TQString &imagePrefix, TQMimeSourceFactory *msf)
|
|
{
|
|
TQString doc;
|
|
FOR_EACH(Special, special) {
|
|
for (uint k=0; k<data.frequencyRanges().count(); k++) {
|
|
const Device::FrequencyRange &fr = data.frequencyRanges()[k];
|
|
if ( fr.special!=special ) continue;
|
|
doc += "<h3>" + data.fname(special) + " - " + i18n("Temperature range: ") + fr.operatingCondition.label() + "</h3>";
|
|
TQString label = data.name() + "_" + data.fname(special) + "_"
|
|
+ fr.operatingCondition.key() + ".png";
|
|
doc += "<img src=\"" + imagePrefix + label + "\" />";
|
|
if (msf) msf->setPixmap(label, Device::vddGraph(i18n("F (MHz)"), i18n("Vdd (V)"), fr.vdds));
|
|
}
|
|
}
|
|
return doc;
|
|
}
|
|
|
|
TQPixmap Device::memoryGraph(const TQValueList<MemoryGraphData> &r)
|
|
{
|
|
TQValueList<MemoryGraphData> ranges = r;
|
|
TQPixmap pixmap;
|
|
TQPainter p;
|
|
TQFontMetrics fm(p.font());
|
|
// order
|
|
qHeapSort(ranges);
|
|
// add empty ranges
|
|
TQValueList<MemoryGraphData>::iterator it;
|
|
for (it=ranges.begin(); it!=ranges.end(); ) {
|
|
TQValueList<MemoryGraphData>::iterator prev = it;
|
|
++it;
|
|
if ( it==ranges.end() ) break;
|
|
if ( (*prev).endAddress+1==(*it).startAddress ) continue;
|
|
MemoryGraphData data;
|
|
data.startAddress = (*prev).endAddress + 1;
|
|
data.endAddress = (*it).startAddress-1;
|
|
ranges.insert(it, data);
|
|
}
|
|
// compute widths and total height
|
|
int theight = fm.ascent() + (fm.ascent()%2==0 ? 1 : 0);
|
|
int hspacing = 5;
|
|
int height = 1;
|
|
int w1 = 0, w2 = 0;
|
|
for (it=ranges.begin(); it!=ranges.end(); ++it) {
|
|
w1 = TQMAX(w1, fm.width((*it).start));
|
|
w1 = TQMAX(w1, fm.width((*it).end));
|
|
w2 = TQMAX(w2, fm.width((*it).label));
|
|
(*it).height = 2*hspacing + theight;
|
|
if ( (*it).startAddress!=(*it).endAddress ) (*it).height += 2*theight;
|
|
height += (*it).height;
|
|
}
|
|
int wspacing = 4;
|
|
int width = wspacing + w1 + wspacing + wspacing + w2;
|
|
pixmap.resize(width, height);
|
|
pixmap.fill(TQt::white);
|
|
p.begin(&pixmap);
|
|
int h = 0;
|
|
// draw ranges
|
|
for (it=ranges.begin(); it!=ranges.end(); ++it) {
|
|
p.setPen(TQPen(TQt::black, 1, TQt::DotLine));
|
|
p.drawLine(0,h, width-1,h);
|
|
p.setPen(TQPen(TQt::black, 1));
|
|
p.setBrush((*it).label.isEmpty() ? TQt::gray : TQt::white);
|
|
p.drawRect(0,h, wspacing+w1+wspacing,(*it).height+1);
|
|
int hmid = h+(*it).height/2+theight/2;
|
|
p.drawText(wspacing+w1+wspacing+wspacing,hmid, (*it).label);
|
|
if ( (*it).startAddress==(*it).endAddress ) p.drawText(wspacing,hmid, (*it).start);
|
|
else {
|
|
p.drawText(wspacing,h+theight, (*it).start);
|
|
p.drawText(wspacing,h+(*it).height-3, (*it).end);
|
|
}
|
|
h += (*it).height;
|
|
p.setPen(TQPen(TQt::black, 1, TQt::DotLine));
|
|
p.drawLine(0,h, width-1,h);
|
|
}
|
|
p.end();
|
|
return pixmap;
|
|
}
|
|
|
|
#endif
|