1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 	begin                : Jan 2005
9 	copyright            : (C) 2005 by Craig Bradney
10 	email                : cbradney@zip.com.au
11  ***************************************************************************/
12 
13 /***************************************************************************
14  *                                                                         *
15  *   This program is free software; you can redistribute it and/or modify  *
16  *   it under the terms of the GNU General Public License as published by  *
17  *   the Free Software Foundation; either version 2 of the License, or     *
18  *   (at your option) any later version.                                   *
19  *                                                                         *
20  ***************************************************************************/
21 
22 #include <QDebug>
23 #include <QObject>
24 #include <QMetaObject>
25 #include <QMenu>
26 #include <QList>
27 #include "scmenu.h"
28 #include "scraction.h"
29 #include "util_debug.h"
30 #include "iconmanager.h"
31 
32 
ScrPopupMenu(QWidget * parent,const QString & pMenuName,const QString & pMenuText,const QString & parentName,bool pCheckable)33 ScrPopupMenu::ScrPopupMenu ( QWidget * parent, const QString& pMenuName, const QString& pMenuText, const QString& parentName, bool pCheckable ) : QObject(parent)
34 {
35 	parentMenuName=parentName;
36 	parentMenuID=-1;
37 	menuText=pMenuText;
38 	menuName=pMenuName;
39 	menuBarID=-1;
40 	menuItemList.clear();
41 	localPopupMenu=new QMenu(parent);//, name);
42 //	localPopupMenu->setCheckable(pCheckable);
43 	enabled=true;
44 	checkable = pCheckable;
45 }
46 
~ScrPopupMenu()47 ScrPopupMenu::~ScrPopupMenu()
48 {
49 	delete localPopupMenu;
50 }
51 
getMenuText()52 QString ScrPopupMenu::getMenuText()
53 {
54 	return menuText;
55 }
56 
setText(const QString & pMenuText)57 void ScrPopupMenu::setText(const QString& pMenuText)
58 {
59 	menuText=pMenuText;
60 	localPopupMenu->menuAction()->setText(menuText);
61 }
62 
getMenuIcon()63 QIcon ScrPopupMenu::getMenuIcon()
64 {
65 	return menuIcon;
66 }
67 
setMenuIcon(const QIcon & pMenuIcon)68 void ScrPopupMenu::setMenuIcon(const QIcon& pMenuIcon)
69 {
70 	menuIcon=pMenuIcon;
71 }
72 
getMenuName()73 QString ScrPopupMenu::getMenuName()
74 {
75 	return menuName;
76 }
77 
getParentMenuName()78 QString ScrPopupMenu::getParentMenuName()
79 {
80 	return parentMenuName;
81 }
82 
83 // void ScrPopupMenu::setMenuBarID(int id)
84 // {
85 // 	menuBarID=id;
86 // }
87 //
88 // int ScrPopupMenu::getMenuBarID()
89 // {
90 // 	return menuBarID;
91 // }
92 
getLocalPopupMenu()93 QMenu *ScrPopupMenu::getLocalPopupMenu()
94 {
95 	return localPopupMenu;
96 }
97 
hasSubMenu(ScrPopupMenu * subMenu)98 bool ScrPopupMenu::hasSubMenu(ScrPopupMenu* subMenu)
99 {
100 	return menuItemList.contains(QPointer<QObject>(subMenu));
101 }
102 
103 // void ScrPopupMenu::setParentMenuID(int id)
104 // {
105 // 	parentMenuID=id;
106 // }
107 //
108 //
109 // const int ScrPopupMenu::getParentMenuID()
110 // {
111 // 	return parentMenuID;
112 // }
113 
insertSubMenu(ScrPopupMenu * newSubMenu)114 bool ScrPopupMenu::insertSubMenu(ScrPopupMenu* newSubMenu)
115 {
116 	if (newSubMenu)
117 	{
118 		menuItemList.append(newSubMenu);
119 // 		localPopupMenu->insertItem(newSubMenu->getMenuIcon(), newSubMenu->getMenuText(), newSubMenu->getLocalPopupMenu());
120 		QAction *m=localPopupMenu->addMenu(newSubMenu->getLocalPopupMenu());
121 		if (m)
122 			m->setText(newSubMenu->getMenuText());
123 		return true;
124 	}
125 	return false;
126 }
127 
removeSubMenu(ScrPopupMenu * subMenu)128 bool ScrPopupMenu::removeSubMenu(ScrPopupMenu* subMenu)
129 {
130 	if (menuItemList.removeAll(subMenu))
131 	{
132 		repopulateLocalMenu();
133 		return true;
134 	}
135 	return false;
136 }
137 
insertMenuItem(ScrAction * newMenuAction)138 bool ScrPopupMenu::insertMenuItem(ScrAction *newMenuAction)
139 {
140 	if (newMenuAction)
141 	{
142 
143 #ifdef Q_OS_MAC
144 		bool menuListHasNoIcons = true;
145 		// look for ScrAction or ScrPopupMenu from the end of the list
146 //		QList< QPointer<QObject> >::Iterator it = menuItemList.end();
147 		int s=menuItemList.size()-1;
148 		for (int i=s; i>=0; --i) {
149 			QObject* menuItem = menuItemList[i];
150 			QString menuItemListClassName = menuItemList[i]->metaObject()->className();
151 			if (menuItemListClassName == "ScrAction")
152 			{
153 				ScrAction * act = qobject_cast<ScrAction *>(menuItem);
154 				if (act!=nullptr)
155 					menuListHasNoIcons = act->icon().isNull();
156 				break;
157 			}
158 			if (menuItemListClassName == "ScrPopupMenu")
159 			{
160 				ScrPopupMenu * men = qobject_cast<ScrPopupMenu *>(menuItem);
161 				if (men!=nullptr)
162 					menuListHasNoIcons = men->getMenuIcon().isNull();
163 				break;
164 			}
165 		}
166 		if (newMenuAction->icon().isNull() && ! menuListHasNoIcons)
167 			newMenuAction->setIcon(IconManager::instance().loadIcon("noicon.png"));
168 #endif
169 
170 		menuItemList.append(newMenuAction);
171 		localPopupMenu->addAction(newMenuAction);
172 		return true;
173 	}
174 	return false;
175 }
176 
177 /* Qt4
178 bool ScrPopupMenu::insertMenuItem(QWidget *widget)
179 {
180 	if (widget)
181 	{
182 		ScrAction *widgetAction = new ScrAction( nullptr, "widget_action" );
183 		menuItemList.append(widgetAction);
184 		localPopupMenu->insertItem(widget);
185 		return true;
186 	}
187 	else
188 		return false;
189 }
190 */
191 
insertMenuItemAfter(ScrAction * newMenuAction,ScrAction * afterMenuAction)192 bool ScrPopupMenu::insertMenuItemAfter(ScrAction *newMenuAction, ScrAction *afterMenuAction)
193 {
194 	//Allow duplicate menu items ???
195 	//if (menuItemList.findRef(newMenuAction)!=-1)
196 	//	return false;
197 
198 #ifdef Q_OS_MAC
199 	if (newMenuAction && afterMenuAction)
200 		if (newMenuAction->icon().isNull() && ! (afterMenuAction->icon().isNull()))
201 			newMenuAction->setIcon(IconManager::instance().loadIcon("noicon.png"));
202 #endif
203 
204 	int pos=menuItemList.indexOf(QPointer<QObject>(afterMenuAction));
205 	menuItemList.insert(++pos, QPointer<QObject>(newMenuAction));
206 	/*
207 	if (index==-1)
208 		return false;
209 	int newIndex=++index;
210 	bool insSuccess=menuItemList.insert(newIndex, newMenuAction);
211 
212 	if (!insSuccess)
213 		return false;
214 	*/
215 	return repopulateLocalMenu();
216 }
217 
removeMenuItem(ScrAction * menuAction)218 bool ScrPopupMenu::removeMenuItem(ScrAction *menuAction)
219 {
220 	if (menuItemList.removeAll(menuAction))
221 	{
222 		repopulateLocalMenu();
223 		return true;
224 	}
225 	return false;
226 }
227 /*
228 bool ScrPopupMenu::insertMenuItemAfter(ScrAction *newMenuAction, const QString afterMenuName)
229 {
230 	bool retVal=true;
231 	bool found=false;
232 	QPtrListIterator<QObject> menuItemListIt(menuItemList);
233 	QObject *object;
234 	while ( (object = menuItemListIt.current()) != 0  )
235 	{
236 		QString menuItemListClassName=object->className();
237 		int index=-1;
238 		//index=menuItemListIt.at();
239 		if (index=-1)
240 		{
241 			retVal=false;
242 			break;
243 		}
244 		if (menuItemListClassName=="ScrAction")
245 		{
246 			qDebug("ScrAction found");
247 			if(QString(object->name())==QString("separator_action"))
248 				bool blah=true;//localPopupMenu->insertSeparator();
249 			else
250 			{
251 				//Grab the action from the list, break and call the other after insert function
252 
253 				int newIndex=++index;
254 				bool insSuccess=menuItemList.insert(newIndex, newMenuAction);
255 				if (!insSuccess)
256 					return false;
257 
258 			}
259 		}
260 	}
261 	if (!found)
262 		return false;
263 	if (retVal==false)
264 		return false;
265 
266 	return repopulateLocalMenu();
267 }
268 */
269 
270 //CB TODO Does NOT handle rebuilding with widgets
repopulateLocalMenu()271 bool ScrPopupMenu::repopulateLocalMenu()
272 {
273 	localPopupMenu->clear();
274 	QList< QPointer<QObject> >::Iterator menuItemListIt = menuItemList.begin();
275 	while (menuItemListIt!=menuItemList.end())
276 	{
277 		QObject *listObj=(*menuItemListIt);
278 		if (listObj==nullptr)
279 		{
280 			QList< QPointer<QObject> >::Iterator menuItemListItToDelete = menuItemListIt;
281 			++menuItemListIt;
282 			menuItemList.removeAll(*menuItemListItToDelete);
283 			continue;
284 		}
285 
286 		QString menuItemListClassName=listObj->metaObject()->className();
287 		if (menuItemListClassName=="ScrAction")
288 		{
289 			ScrAction * act = qobject_cast<ScrAction *>(listObj);
290 			if (act!=nullptr)
291 				localPopupMenu->addAction(act);
292 		}
293 		else
294 		{
295 			if (menuItemListClassName=="ScrPopupMenu")
296 			{
297 				ScrPopupMenu * men = qobject_cast<ScrPopupMenu *>(listObj);
298 				if (men!=nullptr)
299 				{
300 					//qDebug()<<men->localPopupMenu->title()<<men->localPopupMenu->;
301 // 					localPopupMenu->insertItem(men->getMenuIcon(), men->getMenuText(), men->getLocalPopupMenu());
302 					QAction *m=localPopupMenu->addMenu(men->getLocalPopupMenu());
303 					if (m)
304 						m->setText(men->getMenuText());
305 				}
306 			}
307 			else
308 				sDebug(QString("Alien found: %1").arg((*menuItemListIt)->metaObject()->className()));
309 		}
310 		++menuItemListIt;
311 	}
312 	return true;
313 }
314 
generateEntryList(QStringList * actNames)315 bool ScrPopupMenu::generateEntryList(QStringList *actNames)
316 {
317 	QList< QPointer<QObject> >::Iterator menuItemListIt = menuItemList.begin();
318 	while (menuItemListIt!=menuItemList.end())
319 	{
320 		QObject *listObj=(*menuItemListIt);
321 		if (listObj==nullptr)
322 		{
323 			QList< QPointer<QObject> >::Iterator menuItemListItToDelete = menuItemListIt;
324 			++menuItemListIt;
325 			menuItemList.removeAll(*menuItemListItToDelete);
326 			continue;
327 		}
328 
329 		QString menuItemListClassName=listObj->metaObject()->className();
330 		if (menuItemListClassName=="ScrAction")
331 		{
332 			auto *sca=qobject_cast<ScrAction *>(listObj);
333 			if (sca!=nullptr)
334 				actNames->append(sca->objectName());
335 		}
336 		else
337 			if (menuItemListClassName=="ScrPopupMenu")
338 			{
339 				auto *scp=qobject_cast<ScrPopupMenu *>(listObj);
340 				if (scp!=nullptr)
341 					scp->generateEntryList(actNames);
342 			}
343 		++menuItemListIt;
344 	}
345 	return true;
346 
347 }
348 
clear()349 bool ScrPopupMenu::clear()
350 {
351 	menuItemList.clear(); //CB TODO leaking separators here ?
352 	localPopupMenu->clear();
353 	return true;
354 }
355 
insertMenuSeparator()356 bool ScrPopupMenu::insertMenuSeparator()
357 {
358 	ScrAction *sepAction = new ScrAction( nullptr );
359 	sepAction->setSeparator(true);
360 	menuItemList.append(sepAction);
361 	localPopupMenu->addSeparator();
362 	return true;
363 }
364 
setEnabled(bool menuEnabled)365 void ScrPopupMenu::setEnabled(bool menuEnabled)
366 {
367 	enabled=menuEnabled;
368 	localPopupMenu->setEnabled(enabled);
369 }
370 
setParentMenuName(const QString & newParentMenuName)371 void ScrPopupMenu::setParentMenuName(const QString& newParentMenuName)
372 {
373 	if (!parentMenuName.isEmpty())
374 		parentMenuName=newParentMenuName;
375 }
376