#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeWidgetItem>
#include <QToolButton>
#include <QGraphicsScene>
#include <QAbstractGraphicsShapeItem>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QTableWidgetItem>
namespace Ui {
class MainWindow;
}
class ParamList : public QMap <QString, QString>
{
public:
int number (QString key, int default_value = 0);
};
class ColorButton : public QToolButton
{
private :
QString name;
QColor color;
public :
ColorButton (QString s);
protected:
void mousePressEvent(QMouseEvent *event);
};
class Common : private QObject
{
Q_OBJECT
public :
ParamList params;
};
class Rectangle : public QGraphicsRectItem, public Common
{
protected:
void dragEnterEvent (QGraphicsSceneDragDropEvent *event);
void dropEvent (QGraphicsSceneDragDropEvent *event);
public:
Rectangle ();
};
class Ellipse : public QGraphicsEllipseItem, public Common
{
protected:
void dragEnterEvent (QGraphicsSceneDragDropEvent *event);
void dropEvent (QGraphicsSceneDragDropEvent *event);
public:
Ellipse ();
};
class TreeNode : public QTreeWidgetItem
{
public:
Common * common;
QAbstractGraphicsShapeItem * shape;
TreeNode () : common (NULL), shape (NULL) { }
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void readFile(QString fileName);
Rectangle * createRectangle (TreeNode * node,
QGraphicsItem * target,
ParamList param);
Ellipse * createEllipse (TreeNode * node,
QGraphicsItem * target,
ParamList param);
void modifyShape (QGraphicsItem * target,
QAbstractGraphicsShapeItem * shape,
ParamList param);
private slots:
void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
void on_tableWidget_itemChanged(QTableWidgetItem *item);
private:
Ui::MainWindow * ui;
QGraphicsScene * scene;
Common * current_element;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QXmlStreamReader>
#include <QXmlStreamAttribute>
#include <QDrag>
#include <QMimeData>
#include <QIcon>
#include <QGraphicsSceneDragDropEvent>
int ParamList::number(QString key, int default_value)
{
QString s = this->value (key);
bool ok;
int n = s.toInt (&ok);
if (!ok)
n = default_value;
return n;
}
/* Color Button */
ColorButton::ColorButton(QString s)
: name (s), color (QColor (s))
{
setText (s);
setToolTip (s);
QPixmap p (24, 24);
p.fill (QColor (0, 0, 0, 0));
QPainter m (&p);
m.setPen (color);
m.setBrush (color);
m.drawEllipse (2, 2, 20, 20);
QIcon icon (p);
setIcon (icon);
}
void ColorButton::mousePressEvent(QMouseEvent *event)
{
QDrag * drag = new QDrag (this);
QMimeData * data = new QMimeData ();
data->setText (name);
data->setColorData (color);
drag->setMimeData(data);
QPixmap p = this->icon().pixmap(12, 12);
drag->setPixmap(p);
drag->start(Qt::CopyAction | Qt::MoveAction);
};
/* Rectangle */
void Rectangle::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
}
void Rectangle::dropEvent(QGraphicsSceneDragDropEvent *event)
{
const QMimeData * data = event->mimeData();
if (data->hasColor())
{
QColor c = data->colorData().value <QColor> ();
if (event->proposedAction() == Qt::MoveAction) /* shift */
setPen (c);
else
setBrush (c);
}
}
Rectangle::Rectangle()
{
setAcceptDrops(true);
}
/* Ellipse */
void Ellipse::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
}
void Ellipse::dropEvent(QGraphicsSceneDragDropEvent *event)
{
const QMimeData * data = event->mimeData();
if (data->hasColor())
{
QColor c = data->colorData().value <QColor> ();
if (event->proposedAction() == Qt::MoveAction) /* shift */
setPen (c);
else
setBrush (c);
}
}
Ellipse::Ellipse()
{
setAcceptDrops(true);
}
/* MainWindow */
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
current_element (NULL)
{
ui->setupUi(this);
QList <QString> names;
names << "red" << "blue" << "green" << "yellow" << "orange";
for (auto name : names)
{
ColorButton * b = new ColorButton (name);
ui->mainToolBar->addWidget (b);
}
scene = new QGraphicsScene;
ui->graphicsView->setScene (scene);
// scene->addLine (0, 0, 100, 100, QColor ("blue"));
scene->setSceneRect (0, 0, 1024, 800);
readFile ("../xml/data.xml");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readFile (QString fileName)
{
QFile file (fileName);
if (file.open (QFile::ReadOnly | QFile::Text ))
{
QTreeWidgetItem * branch =
ui->treeWidget->invisibleRootItem();
QGraphicsItem * target = NULL;
QXmlStreamReader reader (&file);
while (! reader.atEnd())
{
if (reader.isStartElement())
{
QString s = reader.name().toString();
TreeNode * item = new TreeNode;
item->setText (0, s);
item->setForeground (0, QColor ("blue"));
branch->addChild (item);
branch = item;
ParamList list;
// for (QXmlStreamAttribute a : reader.attributes())
for (auto a : reader.attributes())
{
QString t = a.name().toString();
QString v = a.value().toString();
/*
auto node = new QTreeWidgetItem;
node->setText (0, t + " = " + v);
node->setForeground (0, QColor ("green"));
item->addChild (node);
*/
// list.insert(t, v);
list [t] = v;
}
if (s == "rectangle")
target = createRectangle (item, target, list);
else if (s == "ellipse")
target = createEllipse (item, target, list);
}
else if (reader.isCharacters())
{
QString s = reader.text().toString().simplified();
if (s != "")
{
QTreeWidgetItem * item = new QTreeWidgetItem;
item->setText (0, s);
item->setForeground (0, QColor ("orange"));
branch->addChild (item);
}
}
else if (reader.isEndElement())
{
branch = branch->parent();
QString s = reader.name().toString();
if (s == "rectangle" || s == "ellipse")
target = target->parentItem ();
}
reader.readNext();
}
ui->treeWidget->expandAll();
}
}
Rectangle * MainWindow::createRectangle
(TreeNode * node,
QGraphicsItem * target,
ParamList list)
{
Rectangle * shape = new Rectangle;
shape->params = list;
node->common = shape;
node->shape = shape;
int w = list.number ("w", 100);
int h = list.number ("h", 40);
shape->setRect (0, 0, w, h);
modifyShape (target, shape, list);
return shape;
}
Ellipse * MainWindow::createEllipse
(TreeNode * node,
QGraphicsItem * target,
ParamList list)
{
Ellipse * shape = new Ellipse;
shape->params = list;
node->common = shape;
node->shape = shape;
int w = list.number ("w", 10);
int h = list.number ("h", 10);
shape->setRect (0, 0, w, h);
modifyShape (target, shape, list);
return shape;
}
void MainWindow::modifyShape (QGraphicsItem * target,
QAbstractGraphicsShapeItem * shape,
ParamList list)
{
int x = list.number ("x", 20);
int y = list.number ("y", 20);
shape->setPos (x, y);
QString pen = list ["pen"];
if (pen != "")
shape->setPen (QColor (pen));
QString brush = list ["brush"];
if (brush != "")
shape->setBrush (QColor (brush));
shape->setFlag (QGraphicsItem::ItemIsMovable);
shape->setFlag (QGraphicsItem::ItemIsSelectable);
if (target == NULL)
scene->addItem (shape);
else
shape->setParentItem (target);
}
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
TreeNode * node = dynamic_cast <TreeNode*> (item);
if (node != NULL && node->common != NULL )
{
current_element = NULL;
ui->statusBar->showMessage ("click");
ui->tableWidget->clear ();
ui->tableWidget->setColumnCount (2);
int cnt = 0;
QMapIterator <QString, QString> iter (node->common->params);
while (iter.hasNext())
{
iter.next();
QString name = iter.key ();
QString value = iter.value ();
ui->tableWidget->setRowCount(cnt+1);
QTableWidgetItem * field = new QTableWidgetItem;
field->setText (name);
ui->tableWidget->setItem (cnt, 0, field);
field = new QTableWidgetItem;
field->setText (value);
ui->tableWidget->setItem (cnt, 1, field);
if (name == "pen" or name == "brush")
field->setData(Qt::DecorationRole, QColor (value));
field->setData(Qt::UserRole, name);
cnt ++;
}
current_element = node->common;
}
}
int conv (QString s, int default_value)
{
bool ok;
int n = s.toInt (&ok);
if (!ok)
n = default_value;
return n;
}
void MainWindow::on_tableWidget_itemChanged(QTableWidgetItem *item)
{
QString name = item->data (Qt::UserRole).toString ();
QString value = item->text ();
if (name != "" && current_element != NULL)
{
ui->statusBar->showMessage ("update " + name + " = " + value);
Common * common = current_element;
QAbstractGraphicsShapeItem * shape =
dynamic_cast <QAbstractGraphicsShapeItem *> (common);
if (name == "pen" && shape != NULL)
shape->setPen (QColor (value));
if (name == "brush" && shape != NULL)
shape->setBrush (QColor (value));
if (name == "pen" || name == "brush")
item->setData(Qt::DecorationRole, QColor (value));
if (name == "x")
shape->setX (conv (value, 0));
if (name == "y")
shape->setY (conv (value, 0));
if (name == "w" || name == "h")
{
Rectangle * r = dynamic_cast <Rectangle*> (shape);
Ellipse * e = dynamic_cast <Ellipse*> (shape);
QRectF size;
if (r != NULL) size = r->rect();
if (e != NULL) size = e->rect();
int v = conv (value, 20);
if (name == "w")
size.setWidth (v);
else
size.setHeight (v);
if (r != NULL) r->setRect (size);
if (e != NULL) e->setRect (size);
}
common->params[name] = value;
}
}