File indexing completed on 2024-05-12 16:39:51

0001 /* This file is part of the KDE project
0002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0003    Copyright (C) 2007-2009 Jarosław Staniek <staniek@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include <QApplication>
0022 #include <QClipboard>
0023 #include <QDomDocument>
0024 #include <QMimeData>
0025 #include <QPen>
0026 #include <QPainter>
0027 #include <QDebug>
0028 
0029 #include <kexiutils/utils.h>
0030 
0031 #include "form.h"
0032 #include "formIO.h"
0033 #include "objecttree.h"
0034 #include "utils.h"
0035 
0036 using namespace KFormDesigner;
0037 
0038 void
0039 KFormDesigner::removeChildrenFromList(QWidgetList &list)
0040 {
0041     QSet<QWidget*> toRemove;
0042     foreach (QWidget *w, list) {
0043         // If any widget in the list is a child of this widget, we remove it from the list
0044         foreach (QWidget *widg, list) {
0045             if ((w != widg) && (w->findChild<QWidget*>(widg->objectName()))) {
0046                 qDebug() << "Removing the widget " << widg->objectName()
0047                     << "which is a child of " << w->objectName();
0048                 toRemove.insert(widg);
0049             }
0050         }
0051     }
0052     QSet<QWidget*> all(list.toSet());
0053     all.subtract(toRemove);
0054     list = all.toList();
0055 }
0056 
0057 void
0058 KFormDesigner::setRecursiveCursor(QWidget *w, Form *form)
0059 {
0060     ObjectTreeItem *tree = form->objectTree()->lookup(w->objectName());
0061     if (tree && ((tree->modifiedProperties()->contains("cursor")) || !tree->children()->isEmpty())
0062             && !w->inherits("QLineEdit") && !w->inherits("QTextEdit"))
0063     {
0064         //fix weird behaviour
0065         return; // if the user has set a cursor for this widget or this is a container, don't change it
0066     }
0067 
0068     w->setCursor(Qt::ArrowCursor);
0069 
0070     const QList<QWidget*> list(w->findChildren<QWidget*>());
0071     foreach(QWidget *widget, list) {
0072         widget->setCursor(Qt::ArrowCursor);
0073     }
0074 }
0075 
0076 QSize
0077 KFormDesigner::getSizeFromChildren(QWidget *w, const char *inheritClass)
0078 {
0079     int tmpw = 0, tmph = 0;
0080     const QList<QWidget*> list(w->findChildren<QWidget*>());
0081     foreach(QWidget *widget, list) {
0082         if (widget->inherits(inheritClass)) {
0083             tmpw = qMax(tmpw, widget->geometry().right());
0084             tmph = qMax(tmph, widget->geometry().bottom());
0085         }
0086     }
0087     return QSize(tmpw, tmph) + QSize(10, 10);
0088 }
0089 
0090 // -----------------
0091 
0092 class HorizontalWidgetList::LessThan
0093 {
0094 public:
0095     explicit LessThan(QWidget *topLevelWidget)
0096      : m_topLevelWidget(topLevelWidget)
0097     {
0098     }
0099     bool operator()(QWidget *w1, QWidget *w2) {
0100         return w1->mapTo(m_topLevelWidget, QPoint(0, 0)).x()
0101              - w2->mapTo(m_topLevelWidget, QPoint(0, 0)).x();
0102     }
0103     QWidget *m_topLevelWidget;
0104 };
0105 
0106 HorizontalWidgetList::HorizontalWidgetList(QWidget *topLevelWidget)
0107         : CustomSortableWidgetList()
0108         , m_lessThan(new LessThan(topLevelWidget))
0109 {
0110 }
0111 
0112 HorizontalWidgetList::HorizontalWidgetList(const HorizontalWidgetList& list)
0113     : CustomSortableWidgetList(list)
0114     , m_lessThan(new LessThan(list.m_lessThan->m_topLevelWidget))
0115 {
0116 }
0117 
0118 
0119 HorizontalWidgetList::~HorizontalWidgetList()
0120 {
0121     delete m_lessThan;
0122 }
0123 
0124 void HorizontalWidgetList::sort()
0125 {
0126     std::sort(begin(), end(), *m_lessThan);
0127 }
0128 
0129 // -----------------
0130 
0131 class VerticalWidgetList::LessThan
0132 {
0133 public:
0134     explicit LessThan(QWidget *topLevelWidget)
0135      : m_topLevelWidget(topLevelWidget)
0136     {
0137     }
0138     bool operator()(QWidget *w1, QWidget *w2)
0139     {
0140         int y1, y2;
0141         QObject *page1 = 0;
0142         TabWidget *tw1 = KFormDesigner::findParent<KFormDesigner::TabWidget>(
0143             w1, "KFormDesigner::TabWidget", page1);
0144         if (tw1) // special case
0145             y1 = w1->mapTo(m_topLevelWidget, QPoint(0, 0)).y() + tw1->tabBarHeight() - 2 - 2;
0146         else
0147             y1 = w1->mapTo(m_topLevelWidget, QPoint(0, 0)).y();
0148 
0149         QObject *page2 = 0;
0150         TabWidget *tw2 = KFormDesigner::findParent<KFormDesigner::TabWidget>(
0151             w2, "KFormDesigner::TabWidget", page2);
0152         if (tw1 && tw2 && tw1 == tw2 && page1 != page2) {
0153             // this sorts widgets by tabs there're put in
0154             return tw1->indexOf(static_cast<QWidget*>(page1)) < tw2->indexOf(static_cast<QWidget*>(page2));
0155         }
0156 
0157         if (tw2) // special case
0158             y2 = w2->mapTo(m_topLevelWidget, QPoint(0, 0)).y() + tw2->tabBarHeight() - 2 - 2;
0159         else
0160             y2 = w2->mapTo(m_topLevelWidget, QPoint(0, 0)).y();
0161 
0162         qDebug() << w1->objectName() << ": " << y1 << " "
0163             << " | " << w2->objectName() << ": " << y2;
0164 
0165 
0166         //qDebug() << w1->name() << ": " << w1->mapTo(m_topLevelWidget, QPoint(0,0)) << " " << w1->y()
0167         //<< " | " << w2->name() << ":" /*<< w2->mapFrom(m_topLevelWidget, QPoint(0,w2->y()))*/ << " " << w2->y();
0168         return y1 < y2;
0169     }
0170     QWidget *m_topLevelWidget;
0171 };
0172 
0173 VerticalWidgetList::VerticalWidgetList(QWidget *topLevelWidget)
0174         : CustomSortableWidgetList()
0175         , m_lessThan(new LessThan(topLevelWidget))
0176 {
0177 }
0178 
0179 VerticalWidgetList::VerticalWidgetList(const VerticalWidgetList& list)
0180     : CustomSortableWidgetList(list)
0181     , m_lessThan(new LessThan(list.m_lessThan->m_topLevelWidget))
0182 {
0183 }
0184 
0185 VerticalWidgetList::~VerticalWidgetList()
0186 {
0187     delete m_lessThan;
0188 }
0189 
0190 void VerticalWidgetList::sort()
0191 {
0192     std::sort(begin(), end(), *m_lessThan);
0193 }
0194 
0195 // ----
0196 
0197 QMimeData *KFormDesigner::deepCopyOfMimeData(const QMimeData *data)
0198 {
0199     QMimeData *newData = new QMimeData();
0200     foreach(const QString& format, data->formats()) {
0201         newData->setData(format, data->data(format));
0202     }
0203     return newData;
0204 }
0205 
0206 void KFormDesigner::copyToClipboard(const QString& xml)
0207 {
0208     //qDebug() << xml;
0209     QMimeData *data = new QMimeData();
0210     data->setText(xml);
0211     data->setData(KFormDesigner::mimeType(), xml.toUtf8());
0212     QClipboard *cb = QApplication::clipboard();
0213     cb->setMimeData(data);
0214 }
0215 
0216 void KFormDesigner::widgetsToXML(QDomDocument& doc,
0217     QHash<QByteArray, QByteArray>& containers,
0218     QHash<QByteArray, QByteArray>& parents,
0219     const Form& form, const QWidgetList &list)
0220 {
0221     containers.clear();
0222     parents.clear();
0223     doc = QDomDocument("UI");
0224     doc.appendChild(doc.createElement("UI"));
0225     QDomElement parent = doc.firstChildElement("UI");
0226 
0227     QWidgetList topLevelList(list);
0228     KFormDesigner::removeChildrenFromList(topLevelList);
0229 
0230     foreach (QWidget *w, topLevelList) {
0231         ObjectTreeItem *item = form.objectTree()->lookup(w->objectName());
0232         if (!item)
0233             return;
0234         Container *c = form.parentContainer(item->widget());
0235         if (!c)
0236             return;
0237 
0238         // We need to store both parentContainer and parentWidget as they may be different (eg for TabWidget page)
0239         containers.insert(
0240             item->name().toLatin1(),
0241             c->widget()->objectName().toLatin1()
0242         );
0243         parents.insert(
0244             item->name().toLatin1(),
0245             item->parent()->name().toLatin1()
0246         );
0247         FormIO::saveWidget(item, parent, doc);
0248 #ifdef KFD_SIGSLOTS
0249         form.connectionBuffer()->saveAllConnectionsForWidget(
0250             item->widget()->objectName(), doc);
0251 #endif
0252     }
0253 
0254     FormIO::cleanClipboard(parent);
0255 }
0256 
0257 //-----------------------------
0258 
0259 class Q_DECL_HIDDEN ActionGroup::Private {
0260     public:
0261         Private() {}
0262         QHash<QString, QAction*> actions;
0263 };
0264 
0265 ActionGroup::ActionGroup( QObject * parent )
0266     : QActionGroup(parent)
0267     , d( new Private )
0268 {
0269 }
0270 
0271 ActionGroup::~ActionGroup()
0272 {
0273     delete d;
0274 }
0275 
0276 void ActionGroup::addAction(QAction* action)
0277 {
0278     QActionGroup::addAction(action);
0279     d->actions.insert(action->objectName(), action);
0280 }
0281 
0282 QAction *ActionGroup::action(const QString& name) const
0283 {
0284     return d->actions.value(name);
0285 }
0286 
0287 //-----------------------------
0288 
0289 int KFormDesigner::alignValueToGrid(int value, int gridSize)
0290 {
0291     if ((value % gridSize * 2) < gridSize)
0292         return value / gridSize * gridSize;
0293     return (value / gridSize + 1) * gridSize;
0294 }
0295 
0296 //-----------------------------
0297 
0298 void KFormDesigner::paintWidgetFrame(QPainter& p, const QRect& geometry)
0299 {
0300     QColor c1(Qt::white);
0301     c1.setAlpha(100);
0302     QColor c2(Qt::black);
0303     c2.setAlpha(100);
0304     QRect r(geometry);
0305     r.setWidth(r.width()-1);
0306     r.setHeight(r.height()-1);
0307     QPen pen1(c1, 1, Qt::DashLine);
0308     QPen pen2(c2, 1, Qt::DashLine);
0309     p.setPen(pen1);
0310     p.drawRect(r);
0311     p.setPen(pen2);
0312     p.drawRect(r);
0313 }
0314