Warning, file /office/calligra/libs/widgets/KoToolBox.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  * Copyright (c) 2005-2009 Thomas Zander <zander@kde.org>
0003  * Copyright (c) 2009 Peter Simonsson <peter.simonsson@gmail.com>
0004  * Copyright (c) 2010 Cyrille Berger <cberger@cberger.net>
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 "KoToolBox_p.h"
0023 #include "KoToolBoxLayout_p.h"
0024 #include "KoToolBoxButton_p.h"
0025 
0026 #include <QButtonGroup>
0027 #include <QToolButton>
0028 #include <QStyleOptionFrameV3>
0029 #include <QPainter>
0030 #include <QHash>
0031 #include <QApplication>
0032 #include <QStyle>
0033 #include <QTimer>
0034 #include <QMenu>
0035 #include <QAction>
0036 
0037 #include <klocalizedstring.h>
0038 #include <WidgetsDebug.h>
0039 #include <kconfiggroup.h>
0040 #include <ksharedconfig.h>
0041 
0042 #include <KoCanvasController.h>
0043 #include <KoShapeLayer.h>
0044 
0045 #define BUTTON_MARGIN 10
0046 
0047 static int buttonSize(int screen)
0048 {
0049     QRect rc = qApp->desktop()->screenGeometry(screen);
0050     if (rc.width() <= 1024) {
0051         return 12;
0052     }
0053     else if (rc.width() <= 1377) {
0054         return 14;
0055     }
0056     else  if (rc.width() <= 1920 ) {
0057         return 16;
0058     }
0059     else {
0060         return 22;
0061     }
0062 }
0063 
0064 class KoToolBox::Private
0065 {
0066 public:
0067     Private()
0068         : layout(0)
0069         , buttonGroup(0)
0070         , floating(false)
0071         , contextSize(0)
0072     {
0073     }
0074 
0075     void addSection(Section *section, const QString &name);
0076 
0077     QList<QToolButton*> buttons;
0078     QMap<QString, Section*> sections;
0079     KoToolBoxLayout *layout;
0080     QButtonGroup *buttonGroup;
0081     QHash<QToolButton*, QString> visibilityCodes;
0082     bool floating;
0083     QMap<QAction*,int> contextIconSizes;
0084     QMenu* contextSize;
0085     Qt::Orientation orientation;
0086 };
0087 
0088 void KoToolBox::Private::addSection(Section *section, const QString &name)
0089 {
0090     section->setName(name);
0091     layout->addSection(section);
0092     sections.insert(name, section);
0093 }
0094 
0095 KoToolBox::KoToolBox()
0096     : d(new Private)
0097 {
0098     d->layout = new KoToolBoxLayout(this);
0099     // add defaults
0100     d->addSection(new Section(this), "main");
0101     d->addSection(new Section(this), "dynamic");
0102 
0103     d->buttonGroup = new QButtonGroup(this);
0104     setLayout(d->layout);
0105     foreach(KoToolAction *toolAction, KoToolManager::instance()->toolActionList()) {
0106         addButton(toolAction);
0107     }
0108 
0109     // Update visibility of buttons
0110     setButtonsVisible(QList<QString>());
0111 
0112     connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)),
0113             this, SLOT(setActiveTool(KoCanvasController*,int)));
0114     connect(KoToolManager::instance(), SIGNAL(currentLayerChanged(const KoCanvasController*,const KoShapeLayer*)),
0115             this, SLOT(setCurrentLayer(const KoCanvasController*,const KoShapeLayer*)));
0116     connect(KoToolManager::instance(), SIGNAL(toolCodesSelected(QList<QString>)), this, SLOT(setButtonsVisible(QList<QString>)));
0117     connect(KoToolManager::instance(),
0118             SIGNAL(addedTool(KoToolAction*,KoCanvasController*)),
0119             this, SLOT(toolAdded(KoToolAction*,KoCanvasController*)));
0120 
0121 }
0122 
0123 KoToolBox::~KoToolBox()
0124 {
0125     delete d;
0126 }
0127 
0128 void KoToolBox::addButton(KoToolAction *toolAction)
0129 {
0130     KoToolBoxButton *button = new KoToolBoxButton(toolAction, this);
0131 
0132     d->buttons << button;
0133 
0134     int toolbuttonSize = buttonSize(qApp->desktop()->screenNumber(this));
0135     KConfigGroup cfg =  KSharedConfig::openConfig()->group("KoToolBox");
0136     int iconSize = cfg.readEntry("iconSize", toolbuttonSize);
0137     button->setIconSize(QSize(iconSize, iconSize));
0138     foreach (Section *section, d->sections)  {
0139         section->setButtonSize(QSize(iconSize + BUTTON_MARGIN, iconSize + BUTTON_MARGIN));
0140     }
0141 
0142     QString sectionToBeAddedTo;
0143     const QString section = toolAction->section();
0144     if (section.contains(qApp->applicationName())) {
0145         sectionToBeAddedTo = "main";
0146     } else if (section.contains("main")) {
0147         sectionToBeAddedTo = "main";
0148     }  else if (section.contains("dynamic")) {
0149         sectionToBeAddedTo = "dynamic";
0150     } else {
0151         sectionToBeAddedTo = section;
0152     }
0153 
0154     Section *sectionWidget = d->sections.value(sectionToBeAddedTo);
0155     if (sectionWidget == 0) {
0156         sectionWidget = new Section(this);
0157         d->addSection(sectionWidget, sectionToBeAddedTo);
0158     }
0159     sectionWidget->addButton(button, toolAction->priority());
0160 
0161     d->buttonGroup->addButton(button, toolAction->buttonGroupId());
0162 
0163     d->visibilityCodes.insert(button, toolAction->visibilityCode());
0164 }
0165 
0166 void KoToolBox::setActiveTool(KoCanvasController *canvas, int id)
0167 {
0168     Q_UNUSED(canvas);
0169 
0170     QAbstractButton *button = d->buttonGroup->button(id);
0171     if (button) {
0172         button->setChecked(true);
0173         (qobject_cast<KoToolBoxButton*>(button))->setHighlightColor();
0174     }
0175     else {
0176         warnWidgets << "KoToolBox::setActiveTool(" << id << "): no such button found";
0177     }
0178 }
0179 
0180 void KoToolBox::setButtonsVisible(const QList<QString> &codes)
0181 {
0182     foreach(QToolButton *button, d->visibilityCodes.keys()) {
0183         QString code = d->visibilityCodes.value(button);
0184 
0185         if (code.startsWith(QLatin1String("flake/"))) {
0186             continue;
0187         }
0188 
0189         if (code.endsWith( QLatin1String( "/always"))) {
0190             button->setVisible(true);
0191             button->setEnabled( true );
0192         }
0193         else if (code.isEmpty()) {
0194             button->setVisible(true);
0195             button->setEnabled( codes.count() != 0 );
0196         }
0197         else {
0198             button->setVisible( codes.contains(code) );
0199         }
0200     }
0201     layout()->invalidate();
0202     update();
0203 }
0204 
0205 void KoToolBox::setCurrentLayer(const KoCanvasController *canvas, const KoShapeLayer *layer)
0206 {
0207     Q_UNUSED(canvas);
0208     const bool enabled = layer == nullptr || (layer->isEditable() && layer->isVisible());
0209     foreach (QToolButton *button, d->visibilityCodes.keys()) {
0210         if (d->visibilityCodes[button].endsWith( QLatin1String( "/always") ) ) {
0211             continue;
0212         }
0213         button->setEnabled(enabled);
0214     }
0215 }
0216 
0217 void KoToolBox::paintEvent(QPaintEvent *)
0218 {
0219     QPainter painter(this);
0220 
0221     const QList<Section*> sections = d->sections.values();
0222     QList<Section*>::const_iterator iterator = sections.begin();
0223     int halfSpacing = layout()->spacing();
0224     if (halfSpacing > 0) {
0225         halfSpacing /= 2;
0226     }
0227     while(iterator != sections.end()) {
0228         Section *section = *iterator;
0229         QStyleOption styleoption;
0230         styleoption.palette = palette();
0231 
0232         if (section->separators() & Section::SeparatorTop) {
0233             int y = section->y() - halfSpacing;
0234             styleoption.state = QStyle::State_None;
0235             styleoption.rect = QRect(section->x(), y-1, section->width(), 2);
0236 
0237             style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &styleoption, &painter);
0238         }
0239 
0240         if (section->separators() & Section::SeparatorLeft) {
0241             int x = section->x() - halfSpacing;
0242             styleoption.state = QStyle::State_Horizontal;
0243             styleoption.rect = QRect(x-1, section->y(), 2, section->height());
0244 
0245             style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &styleoption, &painter);
0246         }
0247 
0248         ++iterator;
0249     }
0250 
0251     painter.end();
0252 }
0253 
0254 void KoToolBox::setOrientation(Qt::Orientation orientation)
0255 {
0256     d->orientation = orientation;
0257     d->layout->setOrientation(orientation);
0258     QTimer::singleShot(0, this, SLOT(update()));
0259     foreach(Section* section, d->sections) {
0260         section->setOrientation(orientation);
0261     }
0262 }
0263 
0264 void KoToolBox::setFloating(bool v)
0265 {
0266     d->floating = v;
0267 }
0268 
0269 void KoToolBox::toolAdded(KoToolAction *toolAction, KoCanvasController *canvas)
0270 {
0271     Q_UNUSED(canvas);
0272     addButton(toolAction);
0273     setButtonsVisible(QList<QString>());
0274 
0275 }
0276 
0277 void KoToolBox::slotContextIconSize()
0278 {
0279     QAction* action = qobject_cast<QAction*>(sender());
0280     if (action && d->contextIconSizes.contains(action)) {
0281         const int iconSize = d->contextIconSizes.value(action);
0282 
0283         KConfigGroup cfg =  KSharedConfig::openConfig()->group("KoToolBox");
0284         cfg.writeEntry("iconSize", iconSize);
0285 
0286         foreach(QToolButton *button, d->buttons) {
0287             button->setIconSize(QSize(iconSize, iconSize));
0288         }
0289 
0290         foreach(Section *section, d->sections) {
0291             section->setButtonSize(QSize(iconSize + BUTTON_MARGIN, iconSize + BUTTON_MARGIN));
0292         }
0293 
0294     }
0295 }
0296 
0297 void KoToolBox::contextMenuEvent(QContextMenuEvent *event)
0298 {
0299 
0300     int toolbuttonSize = buttonSize(qApp->desktop()->screenNumber(this));
0301 
0302     if (!d->contextSize) {
0303 
0304         d->contextSize = new QMenu(i18n("Icon Size"), this);
0305         d->contextIconSizes.insert(d->contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"),
0306                                                           this, SLOT(slotContextIconSize())),
0307                                    toolbuttonSize);
0308 
0309         QList<int> sizes;
0310         sizes << 12 << 14 << 16 << 22 << 32 << 48 << 64; //<< 96 << 128 << 192 << 256;
0311         foreach(int i, sizes) {
0312             d->contextIconSizes.insert(d->contextSize->addAction(i18n("%1x%2", i, i), this, SLOT(slotContextIconSize())), i);
0313         }
0314 
0315         QActionGroup *sizeGroup = new QActionGroup(d->contextSize);
0316         foreach (QAction *action, d->contextSize->actions()) {
0317             action->setActionGroup(sizeGroup);
0318             action->setCheckable(true);
0319         }
0320     }
0321     KConfigGroup cfg =  KSharedConfig::openConfig()->group("KoToolBox");
0322     toolbuttonSize = cfg.readEntry("iconSize", toolbuttonSize);
0323 
0324     QMapIterator< QAction*, int > it = d->contextIconSizes;
0325     while (it.hasNext()) {
0326         it.next();
0327         if (it.value() == toolbuttonSize) {
0328             it.key()->setChecked(true);
0329             break;
0330         }
0331     }
0332 
0333     d->contextSize->exec(event->globalPos());
0334 }
0335 KoToolBoxLayout *KoToolBox::toolBoxLayout() const
0336 {
0337     return d->layout;
0338 }
0339 
0340 #include "moc_KoToolBoxScrollArea_p.cpp"