File indexing completed on 2024-05-12 16:36:01
0001 /* This file is part of the KDE project 0002 Copyright 2011 Marijn Kruisselbrink <mkruisselbrink@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "ActionOptionWidget.h" 0021 0022 // Qt 0023 #include <QDomElement> 0024 #include <QHBoxLayout> 0025 #include <QToolButton> 0026 #include <QWidgetAction> 0027 0028 #include <QStyle> 0029 0030 // KF5 0031 #include <KLocalizedString> 0032 0033 // Calligra 0034 #include <KoFontComboBox.h> 0035 0036 // Calligra Sheets 0037 #include "CellToolBase.h" 0038 0039 using namespace Calligra::Sheets; 0040 0041 class GroupFlowLayout : public QLayout 0042 { 0043 public: 0044 GroupFlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); 0045 GroupFlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); 0046 ~GroupFlowLayout() override; 0047 0048 void addItem(QLayoutItem *item) override; 0049 int horizontalSpacing() const; 0050 int verticalSpacing() const; 0051 Qt::Orientations expandingDirections() const override; 0052 bool hasHeightForWidth() const override; 0053 int heightForWidth(int) const override; 0054 int count() const override; 0055 QLayoutItem *itemAt(int index) const override; 0056 QSize minimumSize() const override; 0057 void setGeometry(const QRect &rect) override; 0058 QSize sizeHint() const override; 0059 QLayoutItem *takeAt(int index) override; 0060 0061 private: 0062 int doLayout(const QRect &rect, bool testOnly) const; 0063 int smartSpacing(QStyle::PixelMetric pm) const; 0064 0065 QList<QLayoutItem *> itemList; 0066 int m_hSpace; 0067 int m_vSpace; 0068 }; 0069 0070 ActionOptionWidget::ActionOptionWidget(CellToolBase* cellTool, const QDomElement& e, QWidget *parent) : 0071 QWidget(parent) 0072 { 0073 QString name = e.attribute("name"); 0074 setObjectName(name); 0075 setWindowTitle(i18n(name.toLatin1())); 0076 0077 QLayout* layout = new GroupFlowLayout(this);//QBoxLayout(QBoxLayout::TopToBottom, this); 0078 0079 for (QDomElement group = e.firstChildElement("group"); !group.isNull(); group = group.nextSiblingElement("group")) { 0080 QHBoxLayout *groupLayout = new QHBoxLayout(); 0081 layout->addItem(groupLayout); 0082 0083 // In each group there are a number of actions that will be layouted together. 0084 for (QDomElement action = group.firstChildElement("action"); !action.isNull(); action = action.nextSiblingElement("action")) { 0085 QString actionName = action.attribute("name"); 0086 QAction* a = cellTool->action(actionName); 0087 if (!a) { 0088 warnSheets << "unknown action" << actionName << "in CellToolOptionWidgets.xml"; 0089 continue; 0090 } 0091 QWidgetAction* wa = qobject_cast<QWidgetAction *>(a); 0092 QWidget* w = wa ? wa->requestWidget(this) : 0; 0093 if (w && qobject_cast<KoFontComboBox*>(w)) { 0094 w->setMinimumWidth(w->minimumWidth() / 2); 0095 } 0096 if (!w) { 0097 QToolButton* b = new QToolButton(this); 0098 b->setFocusPolicy(Qt::NoFocus); 0099 b->setDefaultAction(a); 0100 w = b; 0101 } 0102 0103 if (w) { 0104 groupLayout->addWidget(w); 0105 } 0106 } 0107 } 0108 0109 // The following widget activates a special feature in the 0110 // ToolOptionsDocker that makes the components of the widget align 0111 // to the top if there is extra space. 0112 QWidget *specialSpacer = new QWidget(this); 0113 specialSpacer->setObjectName("SpecialSpacer"); 0114 layout->addWidget(specialSpacer); 0115 } 0116 0117 GroupFlowLayout::GroupFlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) 0118 : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) 0119 { 0120 setContentsMargins(margin, margin, margin, margin); 0121 } 0122 0123 GroupFlowLayout::GroupFlowLayout(int margin, int hSpacing, int vSpacing) 0124 : m_hSpace(hSpacing), m_vSpace(vSpacing) 0125 { 0126 setContentsMargins(margin, margin, margin, margin); 0127 } 0128 0129 GroupFlowLayout::~GroupFlowLayout() 0130 { 0131 QLayoutItem *item; 0132 while ((item = takeAt(0))) 0133 delete item; 0134 } 0135 0136 void GroupFlowLayout::addItem(QLayoutItem *item) 0137 { 0138 itemList.append(item); 0139 } 0140 0141 int GroupFlowLayout::horizontalSpacing() const 0142 { 0143 if (m_hSpace >= 0) { 0144 return m_hSpace; 0145 } else { 0146 return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); 0147 } 0148 } 0149 0150 int GroupFlowLayout::verticalSpacing() const 0151 { 0152 if (m_vSpace >= 0) { 0153 return m_vSpace; 0154 } else { 0155 return smartSpacing(QStyle::PM_LayoutVerticalSpacing); 0156 } 0157 } 0158 0159 int GroupFlowLayout::count() const 0160 { 0161 return itemList.size(); 0162 } 0163 0164 QLayoutItem *GroupFlowLayout::itemAt(int index) const 0165 { 0166 return itemList.value(index); 0167 } 0168 0169 QLayoutItem *GroupFlowLayout::takeAt(int index) 0170 { 0171 if (index >= 0 && index < itemList.size()) 0172 return itemList.takeAt(index); 0173 else 0174 return 0; 0175 } 0176 0177 Qt::Orientations GroupFlowLayout::expandingDirections() const 0178 { 0179 return 0; 0180 } 0181 0182 bool GroupFlowLayout::hasHeightForWidth() const 0183 { 0184 return true; 0185 } 0186 0187 int GroupFlowLayout::heightForWidth(int width) const 0188 { 0189 int height = doLayout(QRect(0, 0, width, 0), true); 0190 return height; 0191 } 0192 0193 void GroupFlowLayout::setGeometry(const QRect &rect) 0194 { 0195 QLayout::setGeometry(rect); 0196 doLayout(rect, false); 0197 } 0198 0199 QSize GroupFlowLayout::sizeHint() const 0200 { 0201 return minimumSize(); 0202 } 0203 0204 QSize GroupFlowLayout::minimumSize() const 0205 { 0206 QSize size; 0207 QLayoutItem *item; 0208 foreach (item, itemList) 0209 size = size.expandedTo(item->minimumSize()); 0210 0211 size += QSize(2*margin(), 2*margin()); 0212 return size; 0213 } 0214 0215 int GroupFlowLayout::doLayout(const QRect &rect, bool testOnly) const 0216 { 0217 int left, top, right, bottom; 0218 getContentsMargins(&left, &top, &right, &bottom); 0219 QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); 0220 int x = effectiveRect.x(); 0221 int y = effectiveRect.y(); 0222 int lineHeight = 0; 0223 0224 QLayoutItem *item; 0225 foreach (item, itemList) { 0226 QWidget *wid = item->widget(); 0227 int spaceX = horizontalSpacing(); 0228 if (wid && spaceX == -1) 0229 spaceX = wid->style()->layoutSpacing( 0230 QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); 0231 if (spaceX == -1) spaceX = 5; 0232 int spaceY = verticalSpacing(); 0233 if (wid && spaceY == -1) 0234 spaceY = wid->style()->layoutSpacing( 0235 QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical); 0236 if (spaceY == -1) spaceX = 5; 0237 int nextX = x + item->sizeHint().width() + spaceX; 0238 if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { 0239 x = effectiveRect.x(); 0240 y = y + lineHeight + spaceY; 0241 nextX = x + item->sizeHint().width() + spaceX; 0242 lineHeight = 0; 0243 } 0244 0245 if (!testOnly) { 0246 QSize s = item->sizeHint(); 0247 if (nextX - spaceX > effectiveRect.right()) { 0248 QSize minSize = item->minimumSize(); 0249 int neededW = effectiveRect.right() - x; 0250 s.setWidth(qMax(neededW, minSize.width())); 0251 } 0252 item->setGeometry(QRect(QPoint(x, y), s)); 0253 } 0254 0255 x = nextX; 0256 lineHeight = qMax(lineHeight, item->sizeHint().height()); 0257 } 0258 return y + lineHeight - rect.y() + bottom; 0259 } 0260 0261 int GroupFlowLayout::smartSpacing(QStyle::PixelMetric pm) const 0262 { 0263 QObject *parent = this->parent(); 0264 if (!parent) { 0265 return -1; 0266 } else if (parent->isWidgetType()) { 0267 QWidget *pw = static_cast<QWidget *>(parent); 0268 return pw->style()->pixelMetric(pm, 0, pw); 0269 } else { 0270 return static_cast<QLayout *>(parent)->spacing(); 0271 } 0272 }