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

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2004 Jarosław Staniek <staniek@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 <kexi_global.h>
0021 #include "kexiactionproxy.h"
0022 #include "kexiactionproxy_p.h"
0023 #include "KexiMainWindowIface.h"
0024 
0025 #include <KActionCollection>
0026 
0027 #include <QDebug>
0028 #include <QWidget>
0029 #include <QAction>
0030 
0031 KexiSharedActionConnector::KexiSharedActionConnector(KexiActionProxy* proxy, QObject *obj)
0032         : m_proxy(proxy)
0033         , m_object(obj)
0034 {
0035 }
0036 
0037 KexiSharedActionConnector::~KexiSharedActionConnector()
0038 {
0039 }
0040 
0041 void KexiSharedActionConnector::plugSharedAction(const QString& action_name, const char *slot)
0042 {
0043     m_proxy->plugSharedAction(action_name, m_object, slot);
0044 }
0045 
0046 //=======================
0047 
0048 class Q_DECL_HIDDEN KexiActionProxy::Private
0049 {
0050 public:
0051     Private() {}
0052 
0053     QMap<QString, QPair<KexiActionProxySignal*, bool>* > signalsMap;
0054 };
0055 
0056 
0057 KexiActionProxy::KexiActionProxy(QObject *receiver, KexiSharedActionHost *host)
0058         : m_host(host ? host : KexiSharedActionHost::defaultHost())
0059         , m_receiver(receiver)
0060         , m_actionProxyParent(0)
0061         , m_signal_parent(0)
0062         , m_focusedChild(0)
0063         , d(new Private)
0064 {
0065     m_signal_parent.setObjectName("signal_parent");
0066     //m_sharedActionChildren.setAutoDelete(false); //!< @todo port logic to KDE4
0067     //m_alternativeActions.setAutoDelete(true); //!< @todo port logic to KDE4
0068     m_host->plugActionProxy(this);
0069 }
0070 
0071 KexiActionProxy::~KexiActionProxy()
0072 {
0073     qDeleteAll(d->signalsMap);
0074     d->signalsMap.clear();
0075     //detach myself from every child
0076     foreach(KexiActionProxy *proxy, m_sharedActionChildren) {
0077         proxy->setActionProxyParent_internal(0);
0078     }
0079     //take me from parent
0080     if (m_actionProxyParent)
0081         m_actionProxyParent->takeActionProxyChild(this);
0082 
0083     m_host->takeActionProxyFor(m_receiver);
0084 
0085     delete d;
0086 }
0087 
0088 void KexiActionProxy::plugSharedAction(const QString& action_name, QObject* receiver, const char *slot)
0089 {
0090     if (action_name.isEmpty())// || !receiver || !slot)
0091         return;
0092     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.value(action_name);
0093     if (! p) {
0094         p = new QPair<KexiActionProxySignal*, bool>(new KexiActionProxySignal(&m_signal_parent), true);
0095         d->signalsMap.insert(action_name, p);
0096     }
0097     if (receiver && slot)
0098         QObject::connect(p->first, SIGNAL(invoke()), receiver, slot);
0099 }
0100 
0101 void KexiActionProxy::unplugSharedAction(const QString& action_name)
0102 {
0103     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.take(action_name);
0104     if (! p)
0105         return;
0106     delete p->first;
0107     delete p;
0108 }
0109 
0110 void KexiActionProxy::plugSharedAction(const QString& action_name, QWidget* w)
0111 {
0112     QAction *a = sharedAction(action_name);
0113     if (!a) {
0114         qWarning() << "NO SUCH ACTION:" << action_name;
0115         return;
0116     }
0117     w->addAction(a);
0118 }
0119 
0120 void KexiActionProxy::unplugSharedAction(const QString& action_name, QWidget* w)
0121 {
0122     QAction *a = sharedAction(action_name);
0123     if (!a) {
0124         qWarning() << "NO SUCH ACTION:" << action_name;
0125         return;
0126     }
0127     w->removeAction(a);
0128 }
0129 
0130 QAction * KexiActionProxy::plugSharedAction(const QString& action_name, const QString& alternativeText, QWidget* w)
0131 {
0132     QAction *a = sharedAction(action_name);
0133     if (!a) {
0134         qWarning() << "NO SUCH ACTION:" << action_name;
0135         return 0;
0136     }
0137     QString altName = a->objectName() + "_alt";
0138 
0139     QAction *ka = dynamic_cast<QAction*>(a);
0140     Q_ASSERT(ka);
0141     QAction *alt_act = new QAction(0);
0142     alt_act->setObjectName(altName);
0143     alt_act->setText(alternativeText);
0144     alt_act->setParent(ka->parent());
0145     alt_act->setIcon(ka->icon());
0146     alt_act->setShortcut(ka->shortcut());
0147 
0148     QObject::connect(alt_act, SIGNAL(triggered()), a, SLOT(trigger()));
0149     w->addAction(alt_act);
0150 
0151     //OK?
0152     m_host->updateActionAvailable(action_name, true, m_receiver);
0153 
0154     return alt_act;
0155 }
0156 
0157 bool KexiActionProxy::activateSharedAction(const QString& action_name, bool alsoCheckInChildren)
0158 {
0159     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.value(action_name);
0160     if (!p || !p->second) {
0161         //try in children...
0162         if (alsoCheckInChildren) {
0163             foreach(KexiActionProxy *proxy, m_sharedActionChildren) {
0164                 if (proxy->activateSharedAction(action_name, alsoCheckInChildren))
0165                     return true;
0166             }
0167         }
0168         return m_actionProxyParent ? m_actionProxyParent->activateSharedAction(action_name, false) : false; //last chance: parent
0169     }
0170     //activate in this proxy...
0171     p->first->activate();
0172     return true;
0173 }
0174 
0175 QAction* KexiActionProxy::sharedAction(const QString& action_name)
0176 {
0177     return m_host->mainWindow()->actionCollection()->action(action_name);
0178 }
0179 
0180 bool KexiActionProxy::isSupported(const QString& action_name) const
0181 {
0182     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.value(action_name);
0183     if (!p) {
0184         //not supported explicitly - try in children...
0185         if (m_focusedChild)
0186             return m_focusedChild->isSupported(action_name);
0187         foreach(KexiActionProxy *proxy, m_sharedActionChildren) {
0188             if (proxy->isSupported(action_name))
0189                 return true;
0190         }
0191         return false; //not suported
0192     }
0193     return p != 0;
0194 }
0195 
0196 bool KexiActionProxy::isAvailable(const QString& action_name, bool alsoCheckInChildren) const
0197 {
0198     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.value(action_name);
0199     if (!p) {
0200         //not supported explicitly - try in children...
0201         if (alsoCheckInChildren) {
0202             if (m_focusedChild)
0203                 return m_focusedChild->isAvailable(action_name, alsoCheckInChildren);
0204             foreach(KexiActionProxy *proxy, m_sharedActionChildren) {
0205                 if (proxy->isSupported(action_name))
0206                     return proxy->isAvailable(action_name, alsoCheckInChildren);
0207             }
0208         }
0209         return m_actionProxyParent ? m_actionProxyParent->isAvailable(action_name, false) : false; //last chance: parent
0210     }
0211     //supported explicitly:
0212     return p->second != 0;
0213 }
0214 
0215 void KexiActionProxy::setAvailable(const QString& action_name, bool set)
0216 {
0217     QPair<KexiActionProxySignal*, bool> *p = d->signalsMap.value(action_name);
0218     if (!p)
0219         return;
0220     p->second = set;
0221     m_host->updateActionAvailable(action_name, set, m_receiver);
0222 }
0223 
0224 void KexiActionProxy::addActionProxyChild(KexiActionProxy* child)
0225 {
0226     if (!child || child == this)
0227         return;
0228     child->setActionProxyParent_internal(this);
0229     m_sharedActionChildren.append(child);
0230 }
0231 
0232 void KexiActionProxy::takeActionProxyChild(KexiActionProxy* child)
0233 {
0234     //qDebug() << child;
0235     const int index = m_sharedActionChildren.indexOf(child);
0236     if (index != -1)
0237         m_sharedActionChildren.removeAt(index);
0238 }
0239 
0240 void KexiActionProxy::setActionProxyParent_internal(KexiActionProxy* parent)
0241 {
0242     m_actionProxyParent = parent;
0243 }
0244