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