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

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0004    Copyright (C) 2004-2014 Jarosław Staniek <staniek@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "form_p.h"
0023 #include "formIO.h"
0024 
0025 #include <KPropertyListData>
0026 
0027 #include <KLocalizedString>
0028 
0029 #include <QStyleOption>
0030 
0031 using namespace KFormDesigner;
0032 
0033 DesignModeStyle::DesignModeStyle(const QString &baseStyleName)
0034     : QProxyStyle(baseStyleName)
0035 {
0036 }
0037 
0038 void DesignModeStyle::drawControl(ControlElement element, const QStyleOption *option,
0039                                   QPainter *p, const QWidget *w) const
0040 {
0041     QStyleOption *so = alterOption(element, option);
0042     QProxyStyle::drawControl(element, so ? so : option, p, w);
0043     delete so;
0044 }
0045 
0046 //! Used in alterOption()
0047 template <class StyleOptionClass>
0048 static StyleOptionClass *cloneStyleOption(const QStyleOption *option)
0049 {
0050     const StyleOptionClass *o = qstyleoption_cast<const StyleOptionClass*>(option);
0051     return o ? new StyleOptionClass(*o) : new StyleOptionClass();
0052 }
0053 
0054 QStyleOption* DesignModeStyle::alterOption(ControlElement element, const QStyleOption *option) const
0055 {
0056     Q_UNUSED(element)
0057     if (!option)
0058         return 0;
0059     QStyleOption* res = 0;
0060     switch (option->type) {
0061     case QStyleOption::SO_Button:
0062         res = cloneStyleOption<QStyleOptionButton>(option);
0063         break;
0064     case QStyleOption::SO_ComboBox:
0065         res = cloneStyleOption<QStyleOptionComboBox>(option);
0066         break;
0067     case QStyleOption::SO_Complex:
0068         res = cloneStyleOption<QStyleOptionComplex>(option);
0069         break;
0070     case QStyleOption::SO_DockWidget:
0071         res = cloneStyleOption<QStyleOptionDockWidget>(option);
0072         break;
0073     case QStyleOption::SO_FocusRect:
0074         res = cloneStyleOption<QStyleOptionFocusRect>(option);
0075         break;
0076     case QStyleOption::SO_Frame:
0077         res = cloneStyleOption<QStyleOptionFrame>(option);
0078         break;
0079     case QStyleOption::SO_GraphicsItem:
0080         res = cloneStyleOption<QStyleOptionGraphicsItem>(option);
0081         break;
0082     case QStyleOption::SO_GroupBox:
0083         res = cloneStyleOption<QStyleOptionGroupBox>(option);
0084         break;
0085     case QStyleOption::SO_Header:
0086         res = cloneStyleOption<QStyleOptionHeader>(option);
0087         break;
0088     case QStyleOption::SO_MenuItem:
0089         res = cloneStyleOption<QStyleOptionMenuItem>(option);
0090         break;
0091     case QStyleOption::SO_ProgressBar:
0092         res = cloneStyleOption<QStyleOptionProgressBar>(option);
0093         break;
0094     case QStyleOption::SO_RubberBand:
0095         res = cloneStyleOption<QStyleOptionRubberBand>(option);
0096         break;
0097     case QStyleOption::SO_SizeGrip:
0098         res = cloneStyleOption<QStyleOptionSizeGrip>(option);
0099         break;
0100     case QStyleOption::SO_Slider:
0101         res = cloneStyleOption<QStyleOptionSlider>(option);
0102         break;
0103     case QStyleOption::SO_SpinBox:
0104         res = cloneStyleOption<QStyleOptionSpinBox>(option);
0105         break;
0106     case QStyleOption::SO_Tab:
0107         res = cloneStyleOption<QStyleOptionTab>(option);
0108         break;
0109     case QStyleOption::SO_TabBarBase:
0110         res = cloneStyleOption<QStyleOptionTabBarBase>(option);
0111         break;
0112     case QStyleOption::SO_TabWidgetFrame:
0113         res = cloneStyleOption<QStyleOptionTabWidgetFrame>(option);
0114         break;
0115     case QStyleOption::SO_TitleBar:
0116         res = cloneStyleOption<QStyleOptionTitleBar>(option);
0117         break;
0118     case QStyleOption::SO_ToolBar:
0119         res = cloneStyleOption<QStyleOptionToolBar>(option);
0120         break;
0121     case QStyleOption::SO_ToolBox:
0122         res = cloneStyleOption<QStyleOptionToolBox>(option);
0123         break;
0124     case QStyleOption::SO_ToolButton:
0125         res = cloneStyleOption<QStyleOptionToolButton>(option);
0126         break;
0127     case QStyleOption::SO_ViewItem:
0128         res = cloneStyleOption<QStyleOptionViewItem>(option);
0129         break;
0130     default:
0131         return 0;
0132     }
0133 
0134     const QStyle::State statesToRemove( QStyle::State_MouseOver | State_HasFocus );
0135     res->state |= statesToRemove;
0136     res->state ^= statesToRemove;
0137     return res;
0138 }
0139 
0140 //--------------
0141 
0142 FormPrivate::FormPrivate(Form *form, WidgetLibrary *_library, Form::Mode _mode,
0143                          KActionCollection &col, KFormDesigner::ActionGroup &group)
0144     : mode(_mode)
0145     , state(Form::WidgetSelecting)
0146     , internalCollection(static_cast<QObject *>(nullptr))
0147     , collection(&col)
0148     , widgetActionGroup(&group)
0149 #ifdef KEXI_PIXMAP_COLLECTIONS_SUPPORT
0150     , pixcollection(nullptr)
0151 #endif
0152     , formWidget(nullptr)
0153     , formatVersion(KFormDesigner::version())
0154     , originalFormatVersion(KFormDesigner::version())
0155 #ifdef KFD_SIGSLOTS
0156     , mouseTrackers(nullptr)
0157     , connection(nullptr)
0158 #endif
0159     , library(_library)
0160     , q(form)
0161 {
0162     toplevel = 0;
0163     topTree = 0;
0164     widget = 0;
0165     modified = false;
0166     interactive = true;
0167     autoTabstops = true;
0168     isRedoing = false;
0169 //! @todo get the default from globals...
0170     snapToGrid = true;
0171     gridSize = 10;
0172 #ifdef KFD_SIGSLOTS
0173     connBuffer = new ConnectionBuffer();
0174 #endif
0175     lastCommand = 0;
0176     lastCommandGroup = 0;
0177     isUndoing = false;
0178     slotPropertyChangedEnabled = true;
0179     slotPropertyChanged_addCommandEnabled = true;
0180     insideAddPropertyCommand = false;
0181     initPropertiesDescription();
0182     designModeStyle = 0;
0183     idOfPropertyCommand = 0;
0184     selectWidgetEnabled = true;
0185     pixmapsStoredInline = false;
0186     QObject::connect(&propertySet, SIGNAL(propertyChanged(KPropertySet &, KProperty &)), q,
0187                      SLOT(slotPropertyChanged(KPropertySet &, KProperty &)));
0188     QObject::connect(&propertySet, SIGNAL(propertyReset(KPropertySet &, KProperty &)), q,
0189                      SLOT(slotPropertyReset(KPropertySet &, KProperty &)));
0190 }
0191 
0192 FormPrivate::~FormPrivate()
0193 {
0194     delete topTree;
0195 #ifdef KFD_SIGSLOTS
0196     delete connBuffer;
0197     connBuffer = 0;
0198 #endif
0199 }
0200 
0201 QString FormPrivate::propertyCaption(const QByteArray &name)
0202 {
0203     return propCaption.value(name);
0204 }
0205 
0206 QString FormPrivate::valueCaption(const QByteArray &name)
0207 {
0208     return propValCaption.value(name);
0209 }
0210 
0211 void FormPrivate::addPropertyCaption(const QByteArray &property, const QString &caption)
0212 {
0213     if (!propCaption.contains(property))
0214         propCaption.insert(property, caption);
0215 }
0216 
0217 void FormPrivate::addValueCaption(const QByteArray &value, const QString &caption)
0218 {
0219     if (!propValCaption.contains(value))
0220         propValCaption.insert(value, caption);
0221 }
0222 
0223 void FormPrivate::setColorProperty(KProperty& p,
0224                                    QPalette::ColorRole (QWidget::*roleMethod)() const,
0225                                    const QVariant& value)
0226 {
0227     bool nullColor = value.isNull() || !value.value<QColor>().isValid();
0228     foreach(QWidget* widget, selected) {
0229         ObjectTreeItem *titem = q->objectTree()->lookup(widget->objectName());
0230         QColor color;
0231         if (nullColor && roleMethod == &QWidget::backgroundRole) {
0232             color = widget->parentWidget()->palette().color((widget->*roleMethod)());
0233         }
0234         else {
0235             color = value.value<QColor>();
0236         }
0237         if (titem && p.isModified())
0238             titem->addModifiedProperty(p.name(), color);
0239         QPalette widgetPalette(widget->palette());
0240         QColor oldColor(widgetPalette.color((widget->*roleMethod)()));
0241         widgetPalette.setColor((widget->*roleMethod)(), color);
0242         widget->setPalette(widgetPalette);
0243         if (!isRedoing && !isUndoing) {
0244             q->addPropertyCommand(widget->objectName().toLatin1(),
0245                 oldColor, color, p.name(), Form::DontExecuteCommand);
0246         }
0247         if (roleMethod == &QWidget::backgroundRole) {
0248             widget->setAutoFillBackground(!nullColor);
0249             if (nullColor) { // make background inherited
0250                 widget->setBackgroundRole(QPalette::NoRole);
0251             }
0252         }
0253     }
0254 }
0255 
0256 void FormPrivate::enableAction(const char *name, bool enable)
0257 {
0258     QAction *a = collection->action(QLatin1String(name));
0259     if (a) {
0260         a->setEnabled(enable);
0261     }
0262 }
0263 
0264 ////////////////////////////////////////// i18n related functions ////////
0265 
0266 void FormPrivate::initPropertiesDescription()
0267 {
0268 //! \todo perhaps a few of them shouldn't be translated within KFD mode,
0269 //!       to be more Qt Designer friendly?
0270     propCaption["name"] = xi18n("Name"); // for backward compatibility with Qt 3
0271     propCaption["objectName"] = xi18n("Name");
0272     propCaption["caption"] = xi18n("Caption");
0273     propCaption["windowTitle"] = xi18n("Window title");
0274     propCaption["text"] = xi18n("Text");
0275     propCaption["paletteBackgroundPixmap"] = xi18n("Background Pixmap");
0276     propCaption["enabled"] = xi18nc("Property: enabled widget", "Enabled");
0277     propCaption["geometry"] = xi18n("Geometry");
0278     propCaption["sizePolicy"] = xi18n("Size Policy");
0279     propCaption["minimumSize"] = xi18n("Minimum Size");
0280     propCaption["maximumSize"] = xi18n("Maximum Size");
0281     propCaption["font"] = xi18n("Font");
0282     propCaption["cursor"] = xi18n("Cursor");
0283     propCaption["paletteForegroundColor"] = xi18n("Foreground Color");
0284     propCaption["paletteBackgroundColor"] = xi18n("Background Color");
0285     propCaption["autoFillBackground"] = xi18n("Fill Background");
0286     propCaption["focusPolicy"] = xi18n("Focus Policy");
0287     propCaption["margin"] = xi18n("Margin");
0288     propCaption["readOnly"] = xi18n("Read Only");
0289     propCaption["styleSheet"] = xi18n("Style Sheet");
0290     propCaption["toolTip"] = xi18nc("Widget's Tooltip", "Tooltip");
0291     propCaption["whatsThis"] = xi18nc("Widget's Whats This", "What's This");
0292     propCaption["iconSize"] = xi18n("Icon Size");
0293 
0294     //any QFrame
0295     propCaption["frame"] = xi18n("Frame");
0296     propCaption["lineWidth"] = xi18n("Frame Width");
0297     propCaption["midLineWidth"] = xi18n("Mid Frame Width");
0298     propCaption["frameShape"] = xi18n("Frame Shape");
0299     propCaption["frameShadow"] = xi18n("Frame Shadow");
0300     //any QScrollBar
0301     propCaption["vScrollBarMode"] = xi18n("Vertical Scrollbar");
0302     propCaption["hScrollBarMode"] = xi18n("Horizontal Scrollbar");
0303 
0304     propValCaption["NoBackground"] = xi18n("No Background");
0305     propValCaption["PaletteForeground"] = xi18n("Palette Foreground");
0306     propValCaption["AutoText"] = xi18nc("Auto (HINT: for AutoText)", "Auto");
0307 
0308     propValCaption["AlignAuto"] = xi18nc("Auto (HINT: for Align)", "Auto");
0309     propValCaption["AlignBaseline"] = xi18nc("Baseline (HINT: for Align)", "Baseline");
0310     propValCaption["AlignLeft"] = xi18nc("Left (HINT: for Align)", "Left");
0311     propValCaption["AlignLeading"] = xi18nc("Left (HINT: for Align)", "Left");
0312     propValCaption["AlignRight"] = xi18nc("Right (HINT: for Align)", "Right");
0313     propValCaption["AlignTrailing"] = xi18nc("Right (HINT: for Align)", "Right");
0314     propValCaption["AlignHCenter"] = xi18nc("Center (HINT: for Align)", "Center");
0315     propValCaption["AlignJustify"] = xi18nc("Justify (HINT: for Align)", "Justify");
0316     propValCaption["AlignVCenter"] = xi18nc("Center (HINT: for Align)", "Center");
0317     propValCaption["AlignTop"] = xi18nc("Top (HINT: for Align)", "Top");
0318     propValCaption["AlignBottom"] = xi18nc("Bottom (HINT: for Align)", "Bottom");
0319 
0320     propValCaption["NoFrame"] = xi18nc("No Frame (HINT: for Frame Shape)", "No Frame");
0321     propValCaption["Box"] = xi18nc("Box (HINT: for Frame Shape)", "Box");
0322     propValCaption["Panel"] = xi18nc("Panel (HINT: for Frame Shape)", "Panel");
0323     propValCaption["WinPanel"] = xi18nc("Windows Panel (HINT: for Frame Shape)", "Windows Panel");
0324     propValCaption["HLine"] = xi18nc("Horiz. Line (HINT: for Frame Shape)", "Horiz. Line");
0325     propValCaption["VLine"] = xi18nc("Vertical Line (HINT: for Frame Shape)", "Vertical Line");
0326     propValCaption["StyledPanel"] = xi18nc("Styled (HINT: for Frame Shape)", "Styled");
0327     propValCaption["PopupPanel"] = xi18nc("Popup (HINT: for Frame Shape)", "Popup");
0328     propValCaption["MenuBarPanel"] = xi18nc("Menu Bar (HINT: for Frame Shape)", "Menu Bar");
0329     propValCaption["ToolBarPanel"] = xi18nc("Toolbar (HINT: for Frame Shape)", "Toolbar");
0330     propValCaption["LineEditPanel"] = xi18nc("Text Box (HINT: for Frame Shape)", "Text Box");
0331     propValCaption["TabWidgetPanel"] = xi18nc("Tab Widget (HINT: for Frame Shape)", "Tab Widget");
0332     propValCaption["GroupBoxPanel"] = xi18nc("Group Box (HINT: for Frame Shape)", "Group Box");
0333 
0334     propValCaption["Plain"] = xi18nc("Plain (HINT: for Frame Shadow)", "Plain");
0335     propValCaption["Raised"] = xi18nc("Raised (HINT: for Frame Shadow)", "Raised");
0336     propValCaption["Sunken"] = xi18nc("Sunken (HINT: for Frame Shadow)", "Sunken");
0337     propValCaption["MShadow"] = xi18nc("for Frame Shadow", "Internal");
0338 
0339     propValCaption["NoFocus"] = xi18nc("No Focus (HINT: for Focus)", "No Focus");
0340     propValCaption["TabFocus"] = xi18nc("Tab (HINT: for Focus)", "Tab");
0341     propValCaption["ClickFocus"] = xi18nc("Click (HINT: for Focus)", "Click");
0342     propValCaption["StrongFocus"] = xi18nc("Tab/Click (HINT: for Focus)", "Tab/Click");
0343     propValCaption["WheelFocus"] = xi18nc("Tab/Click/MouseWheel (HINT: for Focus)", "Tab/Click/Mouse Wheel");
0344 
0345     propValCaption["Auto"] = xi18n("Auto");
0346     propValCaption["AlwaysOff"] = xi18n("Always Off");
0347     propValCaption["AlwaysOn"] = xi18n("Always On");
0348 
0349     //orientation
0350     propValCaption["Horizontal"] = xi18n("Horizontal");
0351     propValCaption["Vertical"] = xi18n("Vertical");
0352 
0353     //layout direction
0354     propValCaption["LeftToRight"] = xi18n("Left to Right");
0355     propValCaption["RightToLeft"] = xi18n("Right to Left");
0356 }
0357 
0358 KPropertyListData* FormPrivate::createValueList(WidgetInfo *winfo, const QStringList &list)
0359 {
0360     QStringList names;
0361     foreach (const QString& name, list) {
0362         QString n(propValCaption.value(name.toLatin1()));
0363         if (n.isEmpty()) { //try within factory and (maybe) parent factory
0364             if (winfo) {
0365                 n = q->library()->propertyDescForValue(winfo, name.toLatin1());
0366             }
0367             if (n.isEmpty()) {
0368                 names.append(name);   //untranslated
0369             }
0370             else {
0371                 names.append(n);
0372             }
0373         } else {
0374             names.append(n);
0375         }
0376     }
0377     return new KPropertyListData(list, names);
0378 }