File indexing completed on 2024-05-12 16:39:41
0001 /* This file is part of the KDE project 0002 Copyright (C) 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 "kexisharedactionhost.h" 0021 #include "kexisharedactionhost_p.h" 0022 #include "kexiactionproxy.h" 0023 #include "KexiWindow.h" 0024 #include "KexiMainWindowIface.h" 0025 0026 #include <kexiutils/utils.h> 0027 #include <kexi_global.h> 0028 0029 #include <KGuiItem> 0030 #include <KToggleAction> 0031 #include <KActionMenu> 0032 #include <KActionCollection> 0033 0034 #include <QApplication> 0035 #include <QIcon> 0036 #include <QDebug> 0037 0038 KexiSharedActionHostPrivate::KexiSharedActionHostPrivate(KexiSharedActionHost *h) 0039 : QObject() 0040 , actionMapper(this) 0041 , host(h) 0042 { 0043 setObjectName("KexiSharedActionHostPrivate"); 0044 connect(&actionMapper, SIGNAL(mapped(QString)), this, SLOT(slotAction(QString))); 0045 } 0046 0047 KexiSharedActionHostPrivate::~KexiSharedActionHostPrivate() 0048 { 0049 qDeleteAll(volatileActions); 0050 volatileActions.clear(); 0051 } 0052 0053 void KexiSharedActionHostPrivate::slotAction(const QString& act_id) 0054 { 0055 QWidget *w = host->focusWindow(); 0056 KexiActionProxy *proxy = w ? actionProxies.value(w) : 0; 0057 0058 if (!proxy || !proxy->activateSharedAction(act_id.toLatin1())) { 0059 //also try to find previous enabler 0060 w = enablers.contains(act_id) ? enablers.value(act_id) : 0; 0061 if (!w) 0062 return; 0063 proxy = actionProxies.value(w); 0064 if (!proxy) 0065 return; 0066 proxy->activateSharedAction(act_id.toLatin1()); 0067 } 0068 } 0069 0070 //-------------------------------------------------- 0071 0072 //! dummy host to avoid crashes 0073 Q_GLOBAL_STATIC_WITH_ARGS(KexiSharedActionHost, KexiSharedActionHost_dummy, (0)) 0074 0075 //! default host 0076 KexiSharedActionHost* KexiSharedActionHost_defaultHost = 0; 0077 0078 KexiSharedActionHost* KexiSharedActionHost::defaultHost() 0079 { 0080 if (!KexiSharedActionHost_defaultHost) 0081 return KexiSharedActionHost_dummy; 0082 return KexiSharedActionHost_defaultHost; 0083 } 0084 0085 void KexiSharedActionHost::setAsDefaultHost() 0086 { 0087 KexiSharedActionHost_defaultHost = this; 0088 } 0089 0090 //-------------------------------------------------- 0091 0092 KexiSharedActionHost::KexiSharedActionHost(KexiMainWindowIface* mainWin) 0093 : d(new KexiSharedActionHostPrivate(this)) 0094 { 0095 d->mainWin = mainWin; 0096 } 0097 0098 KexiSharedActionHost::~KexiSharedActionHost() 0099 { 0100 if (KexiSharedActionHost_defaultHost == this) { 0101 KexiSharedActionHost_defaultHost = 0; 0102 } 0103 delete d; 0104 d = 0; //! to let takeActionProxyFor() know that we are almost dead :) 0105 } 0106 0107 void KexiSharedActionHost::setActionAvailable(const QString& action_name, bool avail) 0108 { 0109 QAction *act = d->mainWin->actionCollection()->action(action_name); 0110 if (act) { 0111 act->setEnabled(avail); 0112 } 0113 } 0114 0115 void KexiSharedActionHost::updateActionAvailable(const QString& action_name, bool avail, QObject *obj) 0116 { 0117 if (!d) 0118 return; //sanity 0119 QWidget *fw = d->mainWin->focusWidget(); 0120 while (fw && obj != fw) 0121 fw = fw->parentWidget(); 0122 if (!fw) 0123 return; 0124 0125 setActionAvailable(action_name, avail); 0126 if (avail) { 0127 d->enablers.insert(action_name, fw); 0128 } else { 0129 d->enablers.take(action_name); 0130 } 0131 } 0132 0133 void KexiSharedActionHost::plugActionProxy(KexiActionProxy *proxy) 0134 { 0135 d->actionProxies.insert(proxy->receiver(), proxy); 0136 } 0137 0138 KexiMainWindowIface* KexiSharedActionHost::mainWindow() const 0139 { 0140 return d->mainWin; 0141 } 0142 0143 void KexiSharedActionHost::invalidateSharedActions(QObject *o) 0144 { 0145 if (!d) 0146 return; 0147 0148 KexiActionProxy *p = o ? d->actionProxies.value(o) : 0; 0149 foreach(QAction * a, d->sharedActions) { 0150 const bool avail = p && p->isAvailable(a->objectName()); 0151 KexiVolatileActionData *va = d->volatileActions.value(a); 0152 if (va != 0) { 0153 if (p && p->isSupported(a->objectName())) { 0154 QList<QAction *> actions_list; 0155 actions_list.append(a); 0156 if (!va->plugged) { 0157 va->plugged = true; 0158 } 0159 } else { 0160 if (va->plugged) { 0161 va->plugged = false; 0162 } 0163 } 0164 } 0165 a->setEnabled(avail); 0166 //qDebug() << "Action " << a->name() << (avail ? " enabled." : " disabled."); 0167 } 0168 } 0169 0170 KexiActionProxy* KexiSharedActionHost::actionProxyFor(QObject *o) const 0171 { 0172 return d->actionProxies.value(o); 0173 } 0174 0175 KexiActionProxy* KexiSharedActionHost::takeActionProxyFor(QObject *o) 0176 { 0177 if (d) 0178 return d->actionProxies.take(o); 0179 return 0; 0180 } 0181 0182 QWidget* KexiSharedActionHost::findWindow(QWidget * /*w*/) 0183 { 0184 return 0; 0185 } 0186 0187 QWidget* KexiSharedActionHost::focusWindow() 0188 { 0189 QWidget *aw = QApplication::activeWindow(); 0190 if (!aw) 0191 aw = dynamic_cast<QWidget*>(d->mainWin); 0192 QWidget *fw = aw->focusWidget(); 0193 return findWindow(fw); 0194 } 0195 0196 QAction * KexiSharedActionHost::createSharedActionInternal(QAction *action) 0197 { 0198 QObject::connect(action, SIGNAL(triggered()), &d->actionMapper, SLOT(map())); 0199 d->actionMapper.setMapping(action, action->objectName()); 0200 d->sharedActions.append(action); 0201 return action; 0202 } 0203 0204 QList<QAction *> KexiSharedActionHost::sharedActions() const 0205 { 0206 return d->sharedActions; 0207 } 0208 0209 QAction * KexiSharedActionHost::createSharedAction(const QString &text, const QString &iconName, 0210 const QKeySequence &cut, const char *name, KActionCollection* col, const char *subclassName) 0211 { 0212 if (!col) 0213 col = d->mainWin->actionCollection(); 0214 0215 if (subclassName == 0) { 0216 QAction *action = new QAction(QIcon::fromTheme(iconName), text, col); 0217 action->setObjectName(name); 0218 action->setShortcut(cut); 0219 col->addAction(name, action); 0220 return createSharedActionInternal(action); 0221 } else if (qstricmp(subclassName, "KToggleAction") == 0) { 0222 KToggleAction *action = new KToggleAction(QIcon::fromTheme(iconName), text, col); 0223 action->setObjectName(name); 0224 action->setShortcut(cut); 0225 col->addAction(name, action); 0226 return createSharedActionInternal(action); 0227 } else if (qstricmp(subclassName, "KActionMenu") == 0) { 0228 KActionMenu *action = new KActionMenu(QIcon::fromTheme(iconName), text, col); 0229 action->setObjectName(name); 0230 action->setShortcut(cut); 0231 col->addAction(name, action); 0232 return createSharedActionInternal(action); 0233 } 0234 //! @todo more QAction subclasses 0235 return 0; 0236 } 0237 0238 QAction * KexiSharedActionHost::createSharedAction(KStandardAction::StandardAction id, 0239 const char *name, KActionCollection* col) 0240 { 0241 if (!col) 0242 col = d->mainWin->actionCollection(); 0243 0244 QAction * action = KStandardAction::create(id, 0/*receiver*/, 0/*slot*/, col); 0245 if (name) { 0246 action->setObjectName(name); 0247 } 0248 (void)createSharedActionInternal(action); 0249 return action; 0250 } 0251 0252 QAction * KexiSharedActionHost::createSharedAction(const KGuiItem& guiItem, const QKeySequence &cut, 0253 const char *name, KActionCollection* col) 0254 { 0255 if (!col) 0256 col = d->mainWin->actionCollection(); 0257 QAction * action = new QAction(guiItem.icon(), guiItem.text(), col); 0258 action->setObjectName(name); 0259 action->setShortcut(cut); 0260 action->setEnabled(guiItem.isEnabled()); 0261 //! @todo how to update enable/disable? is it needed anyway? 0262 action->setToolTip(guiItem.toolTip()); 0263 action->setWhatsThis(guiItem.whatsThis()); 0264 return createSharedActionInternal(action); 0265 } 0266 0267 void KexiSharedActionHost::setActionVolatile(QAction *a, bool set) 0268 { 0269 if (!set) { 0270 d->volatileActions.remove(a); 0271 delete a; 0272 return; 0273 } 0274 if (d->volatileActions.value(a)) 0275 return; 0276 d->volatileActions.insert(a, new KexiVolatileActionData()); 0277 }