// Copyright (C) 2008 Lukas Lalinsky // // 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. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include #include #include #include "databasetable.h" #include "databasetableproperties.h" #include "diagramdocument.h" #include "column.h" #include "columnlist.h" #include "boxsidehub.h" DatabaseTable::DatabaseTable(DiagramItem *parent) : DiagramObject(parent) { setFlag(ItemIsMovable); setFlag(ItemIsSelectable); setHub(new BoxSideHub(this)); m_color = Qt::white; m_columnList = new ColumnList(this); connect(m_columnList, SIGNAL(columnInserted(int)), this, SLOT(updateLayout())); connect(m_columnList, SIGNAL(columnRemoved(int)), this, SLOT(updateLayout())); connect(m_columnList, SIGNAL(columnChanged(int)), this, SLOT(updateLayout())); } QRectF DatabaseTable::boundingRect() const { return m_outerRect; } QList DatabaseTable::primaryKeys() const { QList result; foreach (Column *column, m_columnList->columns()) if (column->isPrimaryKey()) result.append(column); return result; } void DatabaseTable::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); QFont font = scene()->font(); QFont boldFont = font; boldFont.setBold(true); QFont boldFontWithUnderline = boldFont; boldFontWithUnderline.setUnderline(true); QPen pen(QPen(QColor(0, 0, 0))); pen.setJoinStyle(Qt::MiterJoin); pen.setWidth(1); QPen borderPen(pen); borderPen.setWidthF(1.3); if (!document()->isPrinting() && isSelected()) { borderPen.setColor(QColor(0, 96, 255)); } painter->setPen(pen); painter->setFont(font); painter->fillRect(m_outerRect, color()); // Draw the table name painter->fillRect(m_nameBgRect, QColor(205, 205, 205)); painter->drawLine(m_nameBgRect.bottomLeft(), m_nameBgRect.bottomRight()); painter->drawText(m_namePos, m_name); painter->drawLine( QPointF(m_leftSideWidth, m_nameBgRect.bottom()), QPointF(m_leftSideWidth, m_outerRect.bottom())); // Draw the table name QPointF colPos = m_firstColPos; QPointF leftSizePos = colPos - QPointF(m_leftSideWidth, 0); int i = 0; foreach (Column *column, m_columnList->columns()) { bool isBold = column->isRequired(); painter->setFont(isBold ? (column->isPrimaryKey() ? boldFontWithUnderline : boldFont) : font); painter->drawText(colPos, column->name()); if (!m_columnLabels[i].isEmpty()) { painter->setFont(isBold ? boldFont : font); painter->drawText(leftSizePos, m_columnLabels[i]); } colPos += m_colPosIncrement; leftSizePos += m_colPosIncrement; ++i; } // Draw the outside border painter->setPen(borderPen); painter->drawRect(m_outerRect); } void DatabaseTable::setName(const QString &name) { m_name = name; updateLayout(); emit propertyChanged("name", name); } void DatabaseTable::setColor(const QColor &color) { m_color = color; updateLayout(); emit propertyChanged("color", color); } void DatabaseTable::setInitialName(int counter) { setName(counter > 1 ? QString("table_%1").arg(counter) : "table"); } QVariant DatabaseTable::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemSceneHasChanged) { updateLayout(); } if (change == ItemPositionChange) { DiagramDocument *model = qobject_cast(scene()); if (model) { emit model->itemMoved(this); } } if (change == ItemPositionHasChanged) { DiagramDocument *model = qobject_cast(scene()); if (model) emit model->itemHasMoved(this); } return QGraphicsItem::itemChange(change, value); } void DatabaseTable::updateLayout() { if (!scene()) return; prepareGeometryChange(); document()->updatePositions(this); QFont font = scene()->font(); QFontMetricsF fontMetrics(font); QFont boldFont = font; boldFont.setBold(true); QFontMetricsF boldFontMetrics(boldFont); qreal spaceWidth = fontMetrics.width(' '); qreal nameWidth = fontMetrics.width(m_name); qreal height = fontMetrics.height(); m_leftSideWidth = fontMetrics.width("PK"); qreal width = nameWidth + spaceWidth * 2; qreal maxColumnWidth = 0; m_columnLabels.clear(); foreach (Column *column, m_columnList->columns()) { qreal columnWidth = column->isRequired() ? boldFontMetrics.width(column->name()) : fontMetrics.width(column->name()); maxColumnWidth = qMax(maxColumnWidth, columnWidth); qreal columnLeftSideWidth = 0; QStringList label; if (column->isPrimaryKey()) { label << "PK"; } if (column->isForeignKey()) { label << "FK"; } QString labelStr = label.join(","); m_columnLabels << labelStr; if (column->isRequired()) { columnLeftSideWidth = boldFontMetrics.width(labelStr); } else { columnLeftSideWidth = fontMetrics.width(labelStr); } m_leftSideWidth = qMax(m_leftSideWidth, columnLeftSideWidth); } m_leftSideWidth += spaceWidth * 2; width = qMax(nameWidth + spaceWidth * 4, m_leftSideWidth + maxColumnWidth + spaceWidth * 2); qreal nameHeight = height + spaceWidth; m_outerRect = QRectF(0, 0, width, nameHeight + qMax(0.66, qreal(m_columnList->columnCount())) * fontMetrics.lineSpacing() - fontMetrics.leading() + fontMetrics.descent()); m_nameBgRect = QRectF(0, 0, width, nameHeight); m_namePos = QPointF((width - nameWidth) / 2, fontMetrics.ascent() + spaceWidth / 2); m_firstColPos = QPointF(m_leftSideWidth + spaceWidth * 1 - 1, nameHeight + fontMetrics.ascent() + 2); m_colPosIncrement = QPointF(0, fontMetrics.lineSpacing()); update(); } #include "domutils.h" void DatabaseTable::loadFromXml(QDomElement element, DiagramDocument *document) { DiagramItem::loadFromXml(element, document); QDomElement tableElement = element.firstChildElement("table"); if (!tableElement.isNull()) { setName(readStringElement(tableElement, "name")); QColor color(readStringElement(tableElement, "color")); setColor(color.isValid() ? color : Qt::white); QDomElement columnListElement = tableElement.firstChildElement("column-list"); QDomElement columnElement = columnListElement.firstChildElement("column"); while (!columnElement.isNull()) { Column *column = new Column(); column->setName(readStringElement(columnElement, "name")); column->setDataType(readStringElement(columnElement, "data-type")); column->setRequired(readBoolElement(columnElement, "required")); column->setPrimaryKey(readBoolElement(columnElement, "primary-key")); column->setNotes(readStringElement(columnElement, "notes")); columnList()->appendColumn(column); columnElement = columnElement.nextSiblingElement("column"); } } } void DatabaseTable::saveToXml(QDomDocument doc, QDomElement element) { DiagramItem::saveToXml(doc, element); QDomElement tableElement = doc.createElement("table"); element.appendChild(tableElement); appendStringElement(doc, tableElement, "name", name()); appendStringElement(doc, tableElement, "color", color().name()); QDomElement columnListElement = doc.createElement("column-list"); tableElement.appendChild(columnListElement); foreach (Column *column, columnList()->columns()) { QDomElement columnElement = doc.createElement("column"); columnListElement.appendChild(columnElement); appendStringElement(doc, columnElement, "name", column->name()); appendStringElement(doc, columnElement, "data-type", column->dataType()); appendBoolElement(doc, columnElement, "required", column->isRequired()); appendBoolElement(doc, columnElement, "primary-key", column->isPrimaryKey()); appendStringElement(doc, columnElement, "notes", column->notes()); } } DiagramItemProperties * DatabaseTable::createPropertiesEditor(QWidget *parent) { return new DatabaseTableProperties(parent); }