/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * widget.cc * * Fri Jul 4 12:31:17 CEST 2008 * Copyright 2008 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of Pracro. * * Pracro 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. * * Pracro 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 Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "widget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgetwrapper.h" #include "propertieseditor.h" Widget::Widget(QDomNode node) : QWidget() { elem = node.cloneNode(true).toElement(); iscontainer = false; if(elem.hasAttribute("layout")) { setAcceptDrops(true); dragObject = NULL; iscontainer = true; widget = new QFrame(); if(elem.attribute("layout") == "vbox") { orientation = Qt::Vertical; setLayout(new QVBoxLayout()); } else { orientation = Qt::Horizontal; setLayout(new QHBoxLayout()); } } else { setAcceptDrops(false); if(elem.hasAttribute("name")) { if(elem.attribute("name") == "combo") widget = new QComboBox(); else if(elem.attribute("name") == "label") widget = new QLabel(); else if(elem.attribute("name") == "button") widget = new QPushButton(); else if(elem.attribute("name") == "checkbox") widget = new QCheckBox(); else if(elem.attribute("name") == "lineedit") widget = new QLineEdit(); else if(elem.attribute("name") == "textedit") widget = new QTextEdit(); else widget = new QLabel(); } else { widget = new QFrame(); } setLayout(new QHBoxLayout()); } setSizePolicy(widget->sizePolicy()); if(widget->minimumSizeHint().isValid()) setMinimumSize(widget->minimumSizeHint()); // Iterate and call setValue on all attributes QDomNamedNodeMap map = elem.attributes(); for(size_t i = 0; i < map.length(); i++) { QDomAttr attr = map.item(i).toAttr(); QString name = attr.name(); QString value = attr.value(); setValue(name, value); } } void Widget::paintEvent(QPaintEvent *) { if(widget->minimumSizeHint().isValid()) setMinimumSize(widget->minimumSizeHint()); widget->resize(width(), height()); QPixmap pixmap = QPixmap::grabWidget(widget, 0, 0); QPainter p(this); int y = (height() - pixmap.height()) / 2; p.drawPixmap(0, y, pixmap); if(iscontainer) { p.setPen(Qt::blue); p.drawRect(0, 0, width()-1, height()-1); p.setPen(QColor(150,150,200)); if(orientation == Qt::Vertical) { p.drawLine(4, 2, 2, 4); p.drawLine(4, 2, 6, 4); p.drawLine(4, 2, 4, 12); p.drawLine(4, 12, 2, 10); p.drawLine(4, 12, 6, 10); } else { p.drawLine(2, 4, 4, 2); p.drawLine(2, 4, 4, 6); p.drawLine(2, 4 ,12, 4); p.drawLine(12, 4, 10, 2); p.drawLine(12, 4, 10, 6); } } else { p.setPen(QColor(128, 128, 128, 128)); p.drawText(width() / 2 - 20, height() / 2 + 5, elem.attribute("name", "Widget")); } } void Widget::setValue(QString name, QString value) { if(iscontainer == false && elem.hasAttribute("name")) { if(elem.attribute("name") == "combo") { QComboBox *combo = ((QComboBox*)widget); if(name == "value") { while(combo->count()) combo->removeItem(0); combo->addItem(value); combo->setCurrentIndex(0); } repaint(); } else if(elem.attribute("name") == "label") { QLabel *label = ((QLabel*)widget); if(name == "caption") label->setText(value); repaint(); } else if(elem.attribute("name") == "button") { QPushButton *button = ((QPushButton*)widget); if(name == "caption") button->setText(value); repaint(); } else if(elem.attribute("name") == "checkbox") { QCheckBox *checkbox = ((QCheckBox*)widget); if(name == "caption") checkbox->setText(value); if(name == "value") checkbox->setChecked(value == "true"); repaint(); } else if(elem.attribute("name") == "lineedit") { QLineEdit *lineedit = ((QLineEdit*)widget); if(name == "value") lineedit->setText(value); repaint(); } else if(elem.attribute("name") == "textedit") { QTextEdit *textedit = ((QTextEdit*)widget); if(name == "value") textedit->setPlainText(value); repaint(); } else { ((QLabel*)widget)->setText("Unknown attribute " + name + ", set to " + value); } } elem.attributeNode(name).setValue(value); } void Widget::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { dragStartPosition = event->pos(); // Show properties if(!propertieseditor) propertieseditor = new PropertiesEditor(); propertieseditor->setProperties(this); propertieseditor->show(); } } void Widget::mouseMoveEvent(QMouseEvent *event) { if (!(event->buttons() & Qt::LeftButton)) return; if((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance()) return; if(parentWidget()) { QDrag *drag = new QDrag(this); widget->resize(width(), height()); drag->setPixmap(QPixmap::grabWidget(widget, 0, 0)); QMimeData *mimedata = new QMimeData(); mimedata->setData("pracro/widget", wrapWidget(this)); drag->setMimeData(mimedata); parentWidget()->layout()->removeWidget(this); setVisible(false); drag->exec(); } } void Widget::dragEnterEvent(QDragEnterEvent *event) { if(!iscontainer) return; if(event->mimeData()->hasFormat("pracro/widget")) { event->acceptProposedAction(); if(dragObject) delete dragObject; QFrame *frame = new QFrame(); QPalette pal; pal.setColor(QPalette::Foreground, Qt::red); frame->setPalette(pal); if(orientation == Qt::Horizontal) { frame->setFixedWidth(1); } else { frame->setFixedHeight(1); } frame->setFrameStyle(QFrame::Box | QFrame::Plain); frame->setContentsMargins(1,1,0,0); dragObject = frame; QWidget *w = findWidget(event->pos()); if(w) { int idx = ((QBoxLayout*)layout())->indexOf(w); ((QBoxLayout*)layout())->insertWidget(idx, dragObject); } else { layout()->addWidget(dragObject); } } } void Widget::dragLeaveEvent(QDragLeaveEvent *) { if(!iscontainer) return; if(dragObject) delete dragObject; dragObject = NULL; } void Widget::dragMoveEvent(QDragMoveEvent *event) { if(!iscontainer) return; if(event->mimeData()->hasFormat("pracro/widget")) { event->acceptProposedAction(); layout()->removeWidget(dragObject); QWidget *w = findWidget(event->pos()); if(w == dragObject) return; if(w) { int idx = ((QBoxLayout*)layout())->indexOf(w); ((QBoxLayout*)layout())->insertWidget(idx, dragObject); } else { layout()->addWidget(dragObject); } } } void Widget::dropEvent(QDropEvent *event) { if(!iscontainer) return; if(event->mimeData()->hasFormat("pracro/widget")) { int idx = layout()->indexOf(dragObject); /* QString type = event->mimeData()->data("pracro/widget").data(); QWidget *widget; if(type == "horizontal") widget = new Widget(Qt::Horizontal); else if(type == "vertical") widget = new Widget(Qt::Vertical); else widget = new Widget(type); */ QWidget *widget = unwrapWidget(event->mimeData()->data("pracro/widget")); ((QBoxLayout*)layout())->insertWidget(idx, widget); delete dragObject; dragObject = NULL; event->acceptProposedAction(); widget->setVisible(true); widget->show(); } } QWidget *Widget::findWidget(QPoint pos) { QPoint newpos = pos; QWidget *w = childAt(newpos); float angle = 0.0; float dist = 0.0; while((!w || QString(w->metaObject()->className()) == "QFrame") && layout()->count()) { angle += M_PI / 4; dist += 1; newpos = pos + QPoint(sin(angle) * dist, cos(angle) * dist); if(newpos.x() > height() && newpos.y() > width() && newpos.y() < 0 && newpos.x() < 0) { break; } // printf("%d, %d\n", newpos.x(), newpos.y()); w = childAt(newpos); } // printf("Done {%p %s}\n", w, w!=NULL?w->metaObject()->className():"(null)"); if(w) { int idx = layout()->indexOf(w); // printf("\r%d > %d", pos.y() - w->pos().y(), w->height() / 2); fflush(stdout); if(orientation == Qt::Horizontal) { if(pos.x() - w->pos().x() > w->width() / 2) idx++; } else { if(pos.y() - w->pos().y() > w->height() / 2) idx++; } // if(idx < layout()->count()) idx = layout()->count() - 1; if(idx >= 0 && idx < layout()->count()) w = layout()->itemAt(idx)->widget(); else w = NULL; } return w; } QString Widget::toXml(QString tabs) { QString xml; xml = tabs + "<" + elem.attribute("name"); QDomNamedNodeMap map = elem.attributes(); for(size_t i = 0; i < map.length(); i++) { QDomAttr attr = map.item(i).toAttr(); xml += " " + attr.name() + "=\"" + attr.value() + "\""; } if(iscontainer) { xml += ">\n"; for(int i = 0; i < layout()->count(); i++) { Widget *child = (Widget*)layout()->itemAt(i)->widget(); xml += child->toXml(" " + tabs); } xml += tabs + "\n"; } else { xml += "/>\n"; } return xml; }