1 /*
2  * %kadu copyright begin%
3  * Copyright 2009, 2010, 2011 Piotr Galiszewski (piotr.galiszewski@kadu.im)
4  * Copyright 2009, 2010, 2012 Wojciech Treter (juzefwt@gmail.com)
5  * Copyright 2010, 2011 Piotr Dąbrowski (ultr@ultr.pl)
6  * Copyright 2009 Michał Podsiadlik (michal@kadu.net)
7  * Copyright 2009 Bartłomiej Zimoń (uzi18@o2.pl)
8  * Copyright 2010 Radosław Szymczyszyn (lavrin@gmail.com)
9  * Copyright 2010, 2011, 2012, 2013, 2014 Bartosz Brachaczek (b.brachaczek@gmail.com)
10  * Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015 Rafał Przemysław Malinowski (rafal.przemyslaw.malinowski@gmail.com)
11  * Copyright 2009 Longer (longer89@gmail.com)
12  * %kadu copyright end%
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include <QtCore/QLocale>
29 #include <QtGui/QClipboard>
30 #include <QtWidgets/QApplication>
31 #include <QtWidgets/QInputDialog>
32 #include <QtWidgets/QMenu>
33 
34 #include "accounts/account-manager.h"
35 #include "accounts/account.h"
36 #include "buddies/buddy-manager.h"
37 #include "configuration/configuration.h"
38 #include "configuration/deprecated-configuration-api.h"
39 #include "contacts/contact.h"
40 #include "core/application.h"
41 #include "core/injected-factory.h"
42 #include "core/myself.h"
43 #include "gui/actions/action.h"
44 #include "gui/actions/actions.h"
45 #include "gui/actions/change-status-action.h"
46 #include "gui/actions/chat/add-conference-action.h"
47 #include "gui/actions/chat/add-room-chat-action.h"
48 #include "gui/actions/default-proxy-action.h"
49 #include "gui/actions/delete-talkable-action.h"
50 #include "gui/actions/edit-talkable-action.h"
51 #include "gui/actions/recent-chats-action.h"
52 #include "gui/actions/talkable-tree-view/collapse-action.h"
53 #include "gui/actions/talkable-tree-view/expand-action.h"
54 #include "gui/menu/menu-inventory.h"
55 #include "gui/status-icon.h"
56 #include "gui/widgets/buddy-info-panel.h"
57 #include "gui/widgets/chat-widget/chat-widget-actions.h"
58 #include "gui/widgets/chat-widget/chat-widget-manager.h"
59 #include "gui/widgets/dialog/merge-buddies-dialog-widget.h"
60 #include "gui/widgets/status-menu.h"
61 #include "gui/widgets/talkable-delegate-configuration.h"
62 #include "gui/widgets/talkable-tree-view.h"
63 #include "gui/windows/add-buddy-window.h"
64 #include "gui/windows/buddy-delete-window.h"
65 #include "gui/windows/kadu-dialog.h"
66 #include "gui/windows/kadu-window-service.h"
67 #include "gui/windows/kadu-window.h"
68 #include "gui/windows/group-edit-window.h"
69 #include "gui/windows/main-configuration-window-service.h"
70 #include "gui/windows/message-dialog.h"
71 #include "gui/windows/multilogon-window-service.h"
72 #include "gui/windows/search-window.h"
73 #include "gui/windows/your-accounts-window-service.h"
74 #include "icons/kadu-icon.h"
75 #include "misc/misc.h"
76 #include "model/roles.h"
77 #include "os/generic/url-opener.h"
78 #include "parser/parser.h"
79 #include "protocols/protocol.h"
80 #include "status/status-container-manager.h"
81 #include "talkable/filter/blocked-talkable-filter.h"
82 #include "talkable/filter/hide-offline-talkable-filter.h"
83 #include "talkable/filter/hide-offline-without-description-talkable-filter.h"
84 #include "talkable/filter/hide-without-description-talkable-filter.h"
85 #include "talkable/model/talkable-model.h"
86 #include "talkable/model/talkable-proxy-model.h"
87 #include "url-handlers/url-handler-manager.h"
88 
89 #include "about.h"
90 #include "debug.h"
91 
92 #include "kadu-window-actions.h"
93 
hideNoMultilogonAccounts(AccountManager * accountManager,Action * action)94 void hideNoMultilogonAccounts(AccountManager *accountManager, Action *action)
95 {
96 	auto hasMultilogonAccount = false;
97 	for (auto const &account : accountManager->items())
98 		if (account.protocolHandler() && account.protocolHandler()->multilogonService())
99 		{
100 			hasMultilogonAccount = true;
101 			break;
102 		}
103 
104 	action->setVisible(hasMultilogonAccount);
105 }
106 
hideNoSearchServiceAccounts(AccountManager * accountManager,Action * action)107 void hideNoSearchServiceAccounts(AccountManager *accountManager, Action *action)
108 {
109 	auto hasSearchServiceAccount = false;
110 	for (auto const &account : accountManager->items())
111 		if (account.protocolHandler() && account.protocolHandler()->searchService())
112 		{
113 			hasSearchServiceAccount = true;
114 			break;
115 		}
116 
117 	action->setVisible(hasSearchServiceAccount);
118 }
119 
disableNoSearchService(Action * action)120 void disableNoSearchService(Action *action)
121 {
122 	const Contact &contact = action->context()->contacts().toContact();
123 	action->setEnabled(contact
124 			&& contact.contactAccount().protocolHandler()
125 			&& contact.contactAccount().protocolHandler()->searchService());
126 }
127 
disableNoContact(Action * action)128 void disableNoContact(Action *action)
129 {
130 	action->setEnabled(action->context()->contacts().toContact());
131 }
132 
disableNoDescription(Action * action)133 void disableNoDescription(Action *action)
134 {
135 	action->setEnabled(!action->context()->contacts().toContact().currentStatus().description().isEmpty());
136 }
137 
disableNoDescriptionUrl(UrlHandlerManager * urlHandlerManager,Action * action)138 void disableNoDescriptionUrl(UrlHandlerManager *urlHandlerManager, Action *action)
139 {
140 	action->setEnabled(action->context()->contacts().toContact().currentStatus().description().indexOf(urlHandlerManager->urlRegExp()) >= 0);
141 }
142 
disableNoEMail(UrlHandlerManager * urlHandlerManager,Action * action)143 void disableNoEMail(UrlHandlerManager *urlHandlerManager, Action *action)
144 {
145 	const Buddy &buddy = action->context()->buddies().toBuddy();
146 	bool hasMail = !buddy.email().isEmpty() && buddy.email().indexOf(urlHandlerManager->mailRegExp()) == 0;
147 
148 	action->setEnabled(hasMail);
149 }
150 
disableIfContactSelected(Myself * myself,Action * action)151 void disableIfContactSelected(Myself *myself, Action *action)
152 {
153 	if (!action || action->context())
154 		return;
155 
156 	action->setEnabled(!action->context()->roles().contains(ContactRole) && !action->context()->buddies().isEmpty());
157 
158 	if (action->context()->buddies().contains(myself->buddy()))
159 		action->setEnabled(false);
160 	else
161 		action->setEnabled(true);
162 }
163 
disableMerge(Myself * myself,Action * action)164 void disableMerge(Myself *myself, Action *action)
165 {
166 	if (action->context()->buddies().isAnyTemporary())
167 	{
168 		action->setEnabled(false);
169 		return;
170 	}
171 
172 	if (action->context()->buddies().contains(myself->buddy()))
173 		action->setEnabled(false);
174 	else
175 		action->setEnabled(true);
176 
177 	if (1 != action->context()->buddies().size())
178 		action->setEnabled(false);
179 }
180 
KaduWindowActions(QObject * parent)181 KaduWindowActions::KaduWindowActions(QObject *parent) : QObject(parent)
182 {
183 }
184 
~KaduWindowActions()185 KaduWindowActions::~KaduWindowActions()
186 {
187 }
188 
setAccountManager(AccountManager * accountManager)189 void KaduWindowActions::setAccountManager(AccountManager *accountManager)
190 {
191 	m_accountManager = accountManager;
192 }
193 
setActions(Actions * actions)194 void KaduWindowActions::setActions(Actions *actions)
195 {
196 	m_actions = actions;
197 }
198 
setApplication(Application * application)199 void KaduWindowActions::setApplication(Application *application)
200 {
201 	m_application = application;
202 }
203 
setChatWidgetActions(ChatWidgetActions * chatWidgetActions)204 void KaduWindowActions::setChatWidgetActions(ChatWidgetActions *chatWidgetActions)
205 {
206 	m_chatWidgetActions = chatWidgetActions;
207 }
208 
setConfiguration(Configuration * configuration)209 void KaduWindowActions::setConfiguration(Configuration *configuration)
210 {
211 	m_configuration = configuration;
212 }
213 
setInjectedFactory(InjectedFactory * injectedFactory)214 void KaduWindowActions::setInjectedFactory(InjectedFactory *injectedFactory)
215 {
216 	m_injectedFactory = injectedFactory;
217 }
218 
setKaduWindowService(KaduWindowService * kaduWindowService)219 void KaduWindowActions::setKaduWindowService(KaduWindowService *kaduWindowService)
220 {
221 	m_kaduWindowService = kaduWindowService;
222 }
223 
setMainConfigurationWindowService(MainConfigurationWindowService * mainConfigurationWindowService)224 void KaduWindowActions::setMainConfigurationWindowService(MainConfigurationWindowService *mainConfigurationWindowService)
225 {
226 	m_mainConfigurationWindowService = mainConfigurationWindowService;
227 }
228 
setMenuInventory(MenuInventory * menuInventory)229 void KaduWindowActions::setMenuInventory(MenuInventory *menuInventory)
230 {
231 	m_menuInventory = menuInventory;
232 }
233 
setMultilogonWindowService(MultilogonWindowService * multilogonWindowService)234 void KaduWindowActions::setMultilogonWindowService(MultilogonWindowService *multilogonWindowService)
235 {
236 	m_multilogonWindowService = multilogonWindowService;
237 }
238 
setMyself(Myself * myself)239 void KaduWindowActions::setMyself(Myself *myself)
240 {
241 	m_myself = myself;
242 }
243 
setParser(Parser * parser)244 void KaduWindowActions::setParser(Parser *parser)
245 {
246 	m_parser = parser;
247 }
248 
setUrlHandlerManager(UrlHandlerManager * urlHandlerManager)249 void KaduWindowActions::setUrlHandlerManager(UrlHandlerManager *urlHandlerManager)
250 {
251 	m_urlHandlerManager = urlHandlerManager;
252 }
253 
setUrlOpener(UrlOpener * urlOpener)254 void KaduWindowActions::setUrlOpener(UrlOpener *urlOpener)
255 {
256 	m_urlOpener = urlOpener;
257 }
258 
setYourAccountsWindowService(YourAccountsWindowService * yourAccountsWindowService)259 void KaduWindowActions::setYourAccountsWindowService(YourAccountsWindowService *yourAccountsWindowService)
260 {
261 	m_yourAccountsWindowService = yourAccountsWindowService;
262 }
263 
init()264 void KaduWindowActions::init()
265 {
266 	m_actions->blockSignals();
267 
268 	ShowConfigurationWindow = m_injectedFactory->makeInjected<ActionDescription>(this,
269 		ActionDescription::TypeGlobal, "configurationAction",
270 		this, SLOT(configurationActionActivated(QAction *, bool)),
271 		KaduIcon("preferences-other"), tr("Preferences")
272 	);
273 	ShowConfigurationWindow->setShortcut("kadu_configure", Qt::ApplicationShortcut);
274 
275 	ShowYourAccounts = m_injectedFactory->makeInjected<ActionDescription>(this,
276 		ActionDescription::TypeMainMenu, "yourAccountsAction",
277 		this, SLOT(yourAccountsActionActivated(QAction *, bool)),
278 		KaduIcon("x-office-address-book"), tr("Your Accounts")
279 	);
280 
281 	RecentChats = m_injectedFactory->makeInjected<RecentChatsAction>(this);
282 	m_actions->insert(RecentChats);
283 
284 	ShowMultilogons = m_injectedFactory->makeInjected<ActionDescription>(this,
285 		ActionDescription::TypeMainMenu, "showMultilogonsAction",
286 		this, SLOT(showMultilogonsActionActivated(QAction *, bool)),
287 		KaduIcon("kadu_icons/multilogon"), tr("Multilogons"), false,
288 		[this](Action *action){ return hideNoMultilogonAccounts(m_accountManager, action); }
289 	);
290 	connect(ShowMultilogons, SIGNAL(actionCreated(Action *)), this, SLOT(showMultilogonsActionCreated(Action *)));
291 
292 	ExitKadu = m_injectedFactory->makeInjected<ActionDescription>(this,
293 		ActionDescription::TypeMainMenu, "exitKaduAction",
294 		this, SLOT(exitKaduActionActivated(QAction *, bool)),
295 		KaduIcon("application-exit"), tr("&Quit")
296 	);
297 	ExitKadu->setShortcut("kadu_exit", Qt::ApplicationShortcut);
298 
299 	AddUser = m_injectedFactory->makeInjected<ActionDescription>(this,
300 		ActionDescription::TypeGlobal, "addUserAction",
301 		this, SLOT(addUserActionActivated(QAction *, bool)),
302 		KaduIcon("contact-new"), tr("Add Buddy...")
303 	);
304 	AddUser->setShortcut("kadu_adduser", Qt::ApplicationShortcut);
305 
306 	AddConference = m_injectedFactory->makeInjected<AddConferenceAction>(this);
307 	m_actions->insert(AddConference);
308 
309 	AddRoomChat = m_injectedFactory->makeInjected<AddRoomChatAction>(this);
310 	m_actions->insert(AddRoomChat);
311 
312 	AddGroup = m_injectedFactory->makeInjected<ActionDescription>(this,
313 		ActionDescription::TypeGlobal, "addGroupAction",
314 		this, SLOT(addGroupActionActivated(QAction *, bool)),
315 		KaduIcon("group-new"), tr("Add Group...")
316 	);
317 
318 	OpenSearch = m_injectedFactory->makeInjected<ActionDescription>(this,
319 		ActionDescription::TypeGlobal, "openSearchAction",
320 		this, SLOT(openSearchActionActivated(QAction *, bool)),
321 		KaduIcon("edit-find"), tr("Search for Buddy..."), false,
322 		[this](Action *action){ return hideNoSearchServiceAccounts(m_accountManager, action); }
323 	);
324 	connect(OpenSearch, SIGNAL(actionCreated(Action*)), this, SLOT(openSearchActionCreated(Action*)));
325 
326 	Forum = m_injectedFactory->makeInjected<ActionDescription>(this,
327 		ActionDescription::TypeMainMenu, "forumAction",
328 		this, SLOT(forumActionActivated(QAction *, bool)),
329 		KaduIcon{}, tr("Forum")
330 	);
331 
332 	Bugs = m_injectedFactory->makeInjected<ActionDescription>(this,
333 		ActionDescription::TypeMainMenu, "bugsAction",
334 		this, SLOT(bugsActionActivated(QAction *, bool)),
335 		KaduIcon("kadu_icons/report-a-bug"), tr("Report a Bug")
336 	);
337 
338 	GetInvolved = m_injectedFactory->makeInjected<ActionDescription>(this,
339 		ActionDescription::TypeMainMenu, "getInvolvedAction",
340 		this, SLOT(getInvolvedActionActivated(QAction *, bool)),
341 		KaduIcon("kadu_icons/get-involved"), tr("Get Involved")
342 	);
343 
344 	Translate = m_injectedFactory->makeInjected<ActionDescription>(this,
345 		ActionDescription::TypeMainMenu, "translateAction",
346 		this, SLOT(translateActionActivated(QAction *, bool)),
347 		KaduIcon("kadu_icons/translate-kadu"), tr("Translate Kadu")
348 	);
349 
350 	About = m_injectedFactory->makeInjected<ActionDescription>(this,
351 		ActionDescription::TypeMainMenu, "aboutAction",
352 		this, SLOT(aboutActionActivated(QAction *, bool)),
353 		KaduIcon("kadu_icons/about-kadu"), tr("A&bout Kadu")
354 	);
355 
356 	ShowInfoPanel = m_injectedFactory->makeInjected<ActionDescription>(this,
357 		ActionDescription::TypeMainMenu, "showInfoPanelAction",
358 		this, SLOT(showInfoPanelActionActivated(QAction *, bool)),
359 		KaduIcon("kadu_icons/show-information-panel"), tr("Show Information Panel"), true
360 	);
361 	connect(ShowInfoPanel, SIGNAL(actionCreated(Action *)), this, SLOT(showInfoPanelActionCreated(Action *)));
362 
363 	ShowBlockedBuddies = m_injectedFactory->makeInjected<ActionDescription>(this,
364 		ActionDescription::TypeMainMenu, "showIgnoredAction",
365 		this, SLOT(showBlockedActionActivated(QAction *, bool)),
366 		KaduIcon("kadu_icons/show-blocked-buddies"), tr("Show Blocked Buddies"), true
367 	);
368 	connect(ShowBlockedBuddies, SIGNAL(actionCreated(Action *)), this, SLOT(showBlockedActionCreated(Action *)));
369 
370 	ShowMyself = m_injectedFactory->makeInjected<ActionDescription>(this,
371 		ActionDescription::TypeMainMenu, "showMyselfAction",
372 		this, SLOT(showMyselfActionActivated(QAction *, bool)),
373 		KaduIcon(), tr("Show Myself Buddy"), true
374 	);
375 	connect(ShowMyself, SIGNAL(actionCreated(Action *)), this, SLOT(showMyselfActionCreated(Action *)));
376 
377 	auto expandAction = m_injectedFactory->makeInjected<ExpandAction>(this);
378 	m_actions->insert(expandAction);
379 
380 	auto collapseAction = m_injectedFactory->makeInjected<CollapseAction>(this);
381 	m_actions->insert(collapseAction);
382 
383 	m_menuInventory
384 		->menu("buddy-list")
385 		->addAction(expandAction, KaduMenu::SectionActionsGui, 2);
386 	m_menuInventory
387 		->menu("buddy-list")
388 		->addAction(collapseAction, KaduMenu::SectionActionsGui, 1);
389 
390 	CopyDescription = m_injectedFactory->makeInjected<ActionDescription>(this,
391 		ActionDescription::TypeUser, "copyDescriptionAction",
392 		this, SLOT(copyDescriptionActionActivated(QAction *, bool)),
393 		KaduIcon("edit-copy"), tr("Copy Description"), false,
394 		disableNoDescription
395 	);
396 	m_menuInventory
397 		->menu("buddy-list")
398 		->addAction(CopyDescription, KaduMenu::SectionActions, 10);
399 
400 	CopyPersonalInfo = m_injectedFactory->makeInjected<ActionDescription>(this,
401 		ActionDescription::TypeUser, "copyPersonalInfoAction",
402 		this, SLOT(copyPersonalInfoActionActivated(QAction *, bool)),
403 		KaduIcon("kadu_icons/copy-personal-info"), tr("Copy Personal Info")
404 	);
405 	m_menuInventory
406 		->menu("buddy-list")
407 		->addAction(CopyPersonalInfo, KaduMenu::SectionActions, 20);
408 
409 	OpenDescriptionLink = m_injectedFactory->makeInjected<ActionDescription>(this,
410 		ActionDescription::TypeUser, "openDescriptionLinkAction",
411 		this, SLOT(openDescriptionLinkActionActivated(QAction *, bool)),
412 		KaduIcon("go-jump"), tr("Open Description Link in Browser"), false,
413 		[this](Action *action){ return disableNoDescriptionUrl(m_urlHandlerManager, action); }
414 	);
415 	m_menuInventory
416 		->menu("buddy-list")
417 		->addAction(OpenDescriptionLink, KaduMenu::SectionActions, 30);
418 
419 	WriteEmail = m_injectedFactory->makeInjected<ActionDescription>(this,
420 		ActionDescription::TypeUser, "writeEmailAction",
421 		this, SLOT(writeEmailActionActivated(QAction *, bool)),
422 		KaduIcon("mail-message-new"), tr("Send E-Mail"), false,
423 		[this](Action *action){ return disableNoEMail(m_urlHandlerManager, action); }
424 	);
425 	connect(WriteEmail, SIGNAL(actionCreated(Action *)), this, SLOT(writeEmailActionCreated(Action *)));
426 
427 	m_menuInventory
428 		->menu("buddy-list")
429 		->addAction(WriteEmail, KaduMenu::SectionSend, 200);
430 
431 	LookupUserInfo = m_injectedFactory->makeInjected<ActionDescription>(this,
432 		ActionDescription::TypeUser, "lookupUserInfoAction",
433 		this, SLOT(lookupInDirectoryActionActivated(QAction *, bool)),
434 		KaduIcon("edit-find"), tr("Search in Directory"), false,
435 		disableNoSearchService
436 	);
437 
438 	InactiveUsers = m_injectedFactory->makeInjected<ActionDescription>(this,
439 		ActionDescription::TypeUserList, "inactiveUsersAction",
440 		this, SLOT(inactiveUsersActionActivated(QAction *, bool)),
441 		KaduIcon("kadu_icons/show-offline-buddies"), tr("Show Offline Buddies"),
442 		true
443 	);
444 	connect(InactiveUsers, SIGNAL(actionCreated(Action *)), this, SLOT(inactiveUsersActionCreated(Action *)));
445 	InactiveUsers->setShortcut("kadu_showoffline");
446 
447 	DescriptionUsers = m_injectedFactory->makeInjected<ActionDescription>(this,
448 		ActionDescription::TypeUserList, "descriptionUsersAction",
449 		this, SLOT(descriptionUsersActionActivated(QAction *, bool)),
450 		KaduIcon("kadu_icons/only-show-with-description"), tr("Only Show Buddies with Description"),
451 		true
452 	);
453 	connect(DescriptionUsers, SIGNAL(actionCreated(Action *)), this, SLOT(descriptionUsersActionCreated(Action *)));
454 	DescriptionUsers->setShortcut("kadu_showonlydesc");
455 
456 	ShowDescriptions = m_injectedFactory->makeInjected<ActionDescription>(this,
457 		ActionDescription::TypeUserList, "descriptionsAction",
458 		this, SLOT(showDescriptionsActionActivated(QAction *, bool)),
459 		KaduIcon("kadu_icons/show-descriptions"), tr("Show Descriptions"),
460 		true
461 	);
462 	connect(ShowDescriptions, SIGNAL(actionCreated(Action *)), this, SLOT(showDescriptionsActionCreated(Action *)));
463 
464 	OnlineAndDescriptionUsers = m_injectedFactory->makeInjected<ActionDescription>(this,
465 		ActionDescription::TypeUserList, "onlineAndDescriptionUsersAction",
466 		this, SLOT(onlineAndDescUsersActionActivated(QAction *, bool)),
467 		KaduIcon("kadu_icons/only-show-online-and-with-description"), tr("Only Show Online Buddies and Buddies with Description"),
468 		true
469 	);
470 	connect(OnlineAndDescriptionUsers, SIGNAL(actionCreated(Action *)), this, SLOT(onlineAndDescUsersActionCreated(Action *)));
471 
472 	EditTalkable = m_injectedFactory->makeInjected<EditTalkableAction>(this);
473 	m_actions->insert(EditTalkable);
474 
475 	m_menuInventory
476 		->menu("buddy-list")
477 		->addAction(EditTalkable, KaduMenu::SectionView);
478 
479 	MergeContact = m_injectedFactory->makeInjected<ActionDescription>(this,
480 		ActionDescription::TypeUser, "mergeContactAction",
481 		this, SLOT(mergeContactActionActivated(QAction *, bool)),
482 		KaduIcon("kadu_icons/merge-buddies"), tr("Merge Buddies..."), false,
483 		[this](Action *action){ return disableMerge(m_myself, action); }
484 	);
485 
486 	m_menuInventory
487 		->menu("buddy-list")
488 		->addAction(MergeContact, KaduMenu::SectionManagement, 100);
489 
490 	m_menuInventory
491 		->menu("buddy-list")
492 		->addAction(m_chatWidgetActions->blockUser(), KaduMenu::SectionManagement, 500);
493 
494 	DeleteTalkable = m_injectedFactory->makeInjected<DeleteTalkableAction>(this);
495 	m_actions->insert(DeleteTalkable);
496 
497 	m_menuInventory
498 		->menu("buddy-list")
499 		->addAction(DeleteTalkable, KaduMenu::SectionManagement, 1000);
500 
501 	// The last ActionDescription will send actionLoaded() signal.
502 	// TODO It will not reflect all action types (see MainWindow::actionLoadedOrUnloaded() method)
503 	// but will work good since KaduActions is created very early. Of course we still need a better mechanism for that.
504 	m_actions->unblockSignals();
505 
506 	ChangeStatus = m_injectedFactory->makeInjected<ChangeStatusAction>(this);
507 	m_actions->insert(ChangeStatus);
508 
509 	DefaultProxy = m_injectedFactory->makeInjected<DefaultProxyAction>(this);
510 	m_actions->insert(DefaultProxy);
511 }
512 
showMultilogonsActionCreated(Action * action)513 void KaduWindowActions::showMultilogonsActionCreated(Action *action)
514 {
515 	connect(m_accountManager, SIGNAL(accountRegistered(Account)), action, SLOT(checkState()));
516 	connect(m_accountManager, SIGNAL(accountUnregistered(Account)), action, SLOT(checkState()));
517 }
518 
openSearchActionCreated(Action * action)519 void KaduWindowActions::openSearchActionCreated(Action *action)
520 {
521 	connect(m_accountManager, SIGNAL(accountRegistered(Account)), action, SLOT(checkState()));
522 	connect(m_accountManager, SIGNAL(accountUnregistered(Account)), action, SLOT(checkState()));
523 }
524 
inactiveUsersActionCreated(Action * action)525 void KaduWindowActions::inactiveUsersActionCreated(Action *action)
526 {
527 	MainWindow *window = qobject_cast<MainWindow *>(action->parentWidget());
528 	if (!window)
529 		return;
530 	if (!window->talkableProxyModel())
531 		return;
532 
533 	bool enabled = m_configuration->deprecatedApi()->readBoolEntry("General", "ShowOffline");
534 	auto filter = m_injectedFactory->makeInjected<HideOfflineTalkableFilter>(action);
535 	filter->setEnabled(!enabled);
536 
537 	action->setData(QVariant::fromValue(filter));
538 	action->setChecked(enabled);
539 
540 	window->talkableProxyModel()->addFilter(filter);
541 }
542 
descriptionUsersActionCreated(Action * action)543 void KaduWindowActions::descriptionUsersActionCreated(Action *action)
544 {
545 	MainWindow *window = qobject_cast<MainWindow *>(action->parentWidget());
546 	if (!window)
547 		return;
548 	if (!window->talkableProxyModel())
549 		return;
550 
551 	bool enabled = !m_configuration->deprecatedApi()->readBoolEntry("General", "ShowWithoutDescription");
552 	auto filter = m_injectedFactory->makeInjected<HideWithoutDescriptionTalkableFilter>(action);
553 	filter->setEnabled(enabled);
554 
555 	action->setData(QVariant::fromValue(filter));
556 	action->setChecked(enabled);
557 
558 	window->talkableProxyModel()->addFilter(filter);
559 }
560 
showDescriptionsActionCreated(Action * action)561 void KaduWindowActions::showDescriptionsActionCreated(Action *action)
562 {
563 	bool enabled = m_configuration->deprecatedApi()->readBoolEntry("Look", "ShowDesc");
564 	action->setChecked(enabled);
565 }
566 
onlineAndDescUsersActionCreated(Action * action)567 void KaduWindowActions::onlineAndDescUsersActionCreated(Action *action)
568 {
569 	MainWindow *window = qobject_cast<MainWindow *>(action->parentWidget());
570 	if (!window)
571 		return;
572 	if (!window->talkableProxyModel())
573 		return;
574 
575 	bool enabled = m_configuration->deprecatedApi()->readBoolEntry("General", "ShowOnlineAndDescription");
576 	auto filter = m_injectedFactory->makeInjected<HideOfflineWithoutDescriptionTalkableFilter>(action);
577 	filter->setEnabled(enabled);
578 
579 	action->setData(QVariant::fromValue(filter));
580 	action->setChecked(enabled);
581 
582 	window->talkableProxyModel()->addFilter(filter);
583 }
584 
showInfoPanelActionCreated(Action * action)585 void KaduWindowActions::showInfoPanelActionCreated(Action *action)
586 {
587 	action->setChecked(m_configuration->deprecatedApi()->readBoolEntry("Look", "ShowInfoPanel"));
588 }
589 
showBlockedActionCreated(Action * action)590 void KaduWindowActions::showBlockedActionCreated(Action *action)
591 {
592 	MainWindow *window = qobject_cast<MainWindow *>(action->parentWidget());
593 	if (!window)
594 		return;
595 	if (!window->talkableProxyModel())
596 		return;
597 
598 	bool enabled = m_configuration->deprecatedApi()->readBoolEntry("General", "ShowBlocked");
599 	BlockedTalkableFilter *blockedTalkableFilter = new BlockedTalkableFilter(action);
600 	blockedTalkableFilter->setEnabled(!enabled);
601 
602 	action->setData(QVariant::fromValue(blockedTalkableFilter));
603 	action->setChecked(enabled);
604 
605 	window->talkableProxyModel()->addFilter(blockedTalkableFilter);
606 }
607 
showMyselfActionCreated(Action * action)608 void KaduWindowActions::showMyselfActionCreated(Action *action)
609 {
610 	MainWindow *window = qobject_cast<MainWindow *>(action->parentWidget());
611 	if (!window)
612 		return;
613 	if (!window->talkableProxyModel())
614 		return;
615 
616 	auto enabled = m_configuration->deprecatedApi()->readBoolEntry("General", "ShowMyself", false);
617 	auto model = qobject_cast<TalkableModel *>(window->talkableProxyModel()->sourceModel());
618 	if (model)
619 	{
620 		model->setIncludeMyself(enabled);
621 		action->setChecked(enabled);
622 	}
623 }
624 
writeEmailActionCreated(Action * action)625 void KaduWindowActions::writeEmailActionCreated(Action *action)
626 {
627 	const Buddy &buddy = action->context()->buddies().toBuddy();
628 	if (buddy)
629 		connect(buddy, SIGNAL(updated()), action, SLOT(checkState()));
630 }
631 
configurationActionActivated(QAction * sender,bool toggled)632 void KaduWindowActions::configurationActionActivated(QAction *sender, bool toggled)
633 {
634 	Q_UNUSED(sender)
635 	Q_UNUSED(toggled)
636 
637 	m_mainConfigurationWindowService->show();
638 }
639 
yourAccountsActionActivated(QAction * sender,bool toggled)640 void KaduWindowActions::yourAccountsActionActivated(QAction *sender, bool toggled)
641 {
642 	Q_UNUSED(sender)
643 	Q_UNUSED(toggled)
644 
645 	m_yourAccountsWindowService->show();
646 }
647 
showMultilogonsActionActivated(QAction * sender,bool toggled)648 void KaduWindowActions::showMultilogonsActionActivated(QAction *sender, bool toggled)
649 {
650 	Q_UNUSED(sender)
651 	Q_UNUSED(toggled)
652 
653 	m_multilogonWindowService->show();
654 }
655 
exitKaduActionActivated(QAction * sender,bool toggled)656 void KaduWindowActions::exitKaduActionActivated(QAction *sender, bool toggled)
657 {
658 	Q_UNUSED(sender)
659 	Q_UNUSED(toggled)
660 
661 	kdebugf();
662 
663 	m_application->quit();
664 }
665 
addUserActionActivated(QAction * sender,bool toggled)666 void KaduWindowActions::addUserActionActivated(QAction *sender, bool toggled)
667 {
668 	Q_UNUSED(toggled)
669 
670 	kdebugf();
671 
672 	Action *action = qobject_cast<Action *>(sender);
673 	if (!action)
674 		return;
675 
676 	const Buddy &buddy = action->context()->buddies().toBuddy();
677 
678 	if (buddy.isAnonymous())
679 		(m_injectedFactory->makeInjected<AddBuddyWindow>(action->parentWidget(), buddy, true))->show();
680 	else
681 		(m_injectedFactory->makeInjected<AddBuddyWindow>(action->parentWidget()))->show();
682 
683 	kdebugf2();
684 }
685 
mergeContactActionActivated(QAction * sender,bool toggled)686 void KaduWindowActions::mergeContactActionActivated(QAction *sender, bool toggled)
687 {
688 	Q_UNUSED(toggled)
689 
690 	kdebugf();
691 
692 	Action *action = qobject_cast<Action *>(sender);
693 	if (!action)
694 		return;
695 
696 	const Buddy &buddy = action->context()->buddies().toBuddy();
697 	if (!buddy)
698 		return;
699 
700 	MergeBuddiesDialogWidget *mergeWidget = m_injectedFactory->makeInjected<MergeBuddiesDialogWidget>(buddy,
701 			tr("Choose which buddy would you like to merge with <i>%1</i>")
702 			.arg(buddy.display()), sender->parentWidget());
703 	KaduDialog *window = new KaduDialog(mergeWidget, sender->parentWidget());
704 	window->setAcceptButtonText(tr("Merge"));
705 	window->exec();
706 
707 	kdebugf2();
708 }
709 
addGroupActionActivated(QAction * sender,bool toggled)710 void KaduWindowActions::addGroupActionActivated(QAction *sender, bool toggled)
711 {
712 	Q_UNUSED(toggled)
713 
714 	auto window = m_injectedFactory->makeInjected<GroupEditWindow>(Group::null, sender->parentWidget());
715 	window->show();
716 }
717 
openSearchActionActivated(QAction * sender,bool toggled)718 void KaduWindowActions::openSearchActionActivated(QAction *sender, bool toggled)
719 {
720 	Q_UNUSED(toggled)
721 
722 	(m_injectedFactory->makeInjected<SearchWindow>(sender->parentWidget()))->show();
723 }
724 
forumActionActivated(QAction * sender,bool toggled)725 void KaduWindowActions::forumActionActivated(QAction *sender, bool toggled)
726 {
727 	Q_UNUSED(sender)
728 	Q_UNUSED(toggled)
729 
730 	if (m_configuration->deprecatedApi()->readEntry("General", "Language") == "pl")
731 		m_urlOpener->openUrl("http://www.kadu.im/forum/");
732 	else
733 		m_urlOpener->openUrl("http://www.kadu.im/forum/viewforum.php?f=12");
734 }
735 
bugsActionActivated(QAction * sender,bool toggled)736 void KaduWindowActions::bugsActionActivated(QAction *sender, bool toggled)
737 {
738 	Q_UNUSED(sender)
739 	Q_UNUSED(toggled)
740 
741 	if (m_configuration->deprecatedApi()->readEntry("General", "Language") == "pl")
742 		m_urlOpener->openUrl("http://www.kadu.im/w/B%C5%82%C4%99dy");
743 	else
744 		m_urlOpener->openUrl("http://www.kadu.im/w/English:Bugs");
745 }
746 
getInvolvedActionActivated(QAction * sender,bool toggled)747 void KaduWindowActions::getInvolvedActionActivated(QAction *sender, bool toggled)
748 {
749 	Q_UNUSED(sender)
750 	Q_UNUSED(toggled)
751 
752 	if (m_configuration->deprecatedApi()->readEntry("General", "Language") == "pl")
753 		m_urlOpener->openUrl("http://www.kadu.im/w/Do%C5%82%C4%85cz");
754 	else
755 		m_urlOpener->openUrl("http://www.kadu.im/w/English:GetInvolved");
756 }
757 
aboutActionActivated(QAction * sender,bool toggled)758 void KaduWindowActions::aboutActionActivated(QAction *sender, bool toggled)
759 {
760 	Q_UNUSED(sender)
761 	Q_UNUSED(toggled)
762 
763 	m_injectedFactory->makeInjected<::About>(m_kaduWindowService->kaduWindow())->show();
764 }
765 
translateActionActivated(QAction * sender,bool toggled)766 void KaduWindowActions::translateActionActivated(QAction *sender, bool toggled)
767 {
768 	Q_UNUSED(sender)
769 	Q_UNUSED(toggled)
770 
771 	m_urlOpener->openUrl("http://www.transifex.net/projects/p/kadu/");
772 }
773 
showInfoPanelActionActivated(QAction * sender,bool toggled)774 void KaduWindowActions::showInfoPanelActionActivated(QAction *sender, bool toggled)
775 {
776 	Q_UNUSED(sender)
777 	Q_UNUSED(toggled)
778 
779 	m_kaduWindowService->kaduWindow()->infoPanel()->setVisible(toggled);
780 
781 	m_configuration->deprecatedApi()->writeEntry("Look", "ShowInfoPanel", toggled);
782 }
783 
showBlockedActionActivated(QAction * sender,bool toggled)784 void KaduWindowActions::showBlockedActionActivated(QAction *sender, bool toggled)
785 {
786 	QVariant v = sender->data();
787 	if (v.canConvert<BlockedTalkableFilter *>())
788 	{
789 		BlockedTalkableFilter *blockedTalkableFilter = v.value<BlockedTalkableFilter *>();
790 		blockedTalkableFilter->setEnabled(!toggled);
791 		m_configuration->deprecatedApi()->writeEntry("General", "ShowBlocked", toggled);
792 	}
793 }
794 
showMyselfActionActivated(QAction * sender,bool toggled)795 void KaduWindowActions::showMyselfActionActivated(QAction *sender, bool toggled)
796 {
797 	auto window = qobject_cast<MainWindow *>(sender->parentWidget());
798 	if (!window)
799 		return;
800 	if (!window->talkableProxyModel())
801 		return;
802 
803 	auto model = qobject_cast<TalkableModel *>(window->talkableProxyModel()->sourceModel());
804 	if (model)
805 	{
806 		model->setIncludeMyself(toggled);
807 		m_configuration->deprecatedApi()->writeEntry("General", "ShowMyself", toggled);
808 	}
809 }
810 
writeEmailActionActivated(QAction * sender,bool toggled)811 void KaduWindowActions::writeEmailActionActivated(QAction *sender, bool toggled)
812 {
813 	Q_UNUSED(toggled)
814 
815 	kdebugf();
816 
817 	Action *action = qobject_cast<Action *>(sender);
818 	if (!action)
819 		return;
820 
821 	const Buddy &buddy = action->context()->buddies().toBuddy();
822 	if (!buddy)
823 		return;
824 
825 	if (!buddy.email().isEmpty())
826 		m_urlOpener->openEmail(buddy.email().toUtf8());
827 
828 	kdebugf2();
829 }
830 
copyDescriptionActionActivated(QAction * sender,bool toggled)831 void KaduWindowActions::copyDescriptionActionActivated(QAction *sender, bool toggled)
832 {
833 	Q_UNUSED(toggled)
834 
835 	kdebugf();
836 
837 	Action *action = qobject_cast<Action *>(sender);
838 	if (!action)
839 		return;
840 
841 	const Contact &contact = action->context()->contacts().toContact();
842 	if (!contact)
843 		return;
844 
845 	const QString &description = contact.currentStatus().description();
846 	if (description.isEmpty())
847 		return;
848 
849 	QApplication::clipboard()->setText(description, QClipboard::Selection);
850 	QApplication::clipboard()->setText(description, QClipboard::Clipboard);
851 
852 	kdebugf2();
853 }
854 
openDescriptionLinkActionActivated(QAction * sender,bool toggled)855 void KaduWindowActions::openDescriptionLinkActionActivated(QAction *sender, bool toggled)
856 {
857 	Q_UNUSED(toggled)
858 
859 	kdebugf();
860 
861 	Action *action = qobject_cast<Action *>(sender);
862 	if (!action)
863 		return;
864 
865 	const Contact &contact = action->context()->contacts().toContact();
866 	if (!contact)
867 		return;
868 
869 	const QString &description = contact.currentStatus().description();
870 	if (description.isEmpty())
871 		return;
872 
873 	QRegExp url = m_urlHandlerManager->urlRegExp();
874 	int idx_start = url.indexIn(description);
875 	if (idx_start >= 0)
876 		m_urlOpener->openUrl(description.mid(idx_start, url.matchedLength()).toUtf8());
877 
878 	kdebugf2();
879 }
880 
copyPersonalInfoActionActivated(QAction * sender,bool toggled)881 void KaduWindowActions::copyPersonalInfoActionActivated(QAction *sender, bool toggled)
882 {
883 	Q_UNUSED(toggled)
884 
885 	kdebugf();
886 
887 	Action *action = qobject_cast<Action *>(sender);
888 	if (!action)
889 		return;
890 
891 	ContactSet contacts = action->context()->contacts();
892 
893 	QStringList infoList;
894 	QString defaultSyntax = m_parser->escape(tr("Contact:")) + " %a[ (%u)]\n["
895 			+ m_parser->escape(tr("First name:")) + " %f\n]["
896 			+ m_parser->escape(tr("Last name:")) + " %r\n]["
897 			+ m_parser->escape(tr("Mobile:")) + " %m\n]";
898 	QString copyPersonalDataSyntax = m_configuration->deprecatedApi()->readEntry("General", "CopyPersonalDataSyntax", defaultSyntax);
899 	foreach (Contact contact, contacts)
900 		infoList.append(m_parser->parse(copyPersonalDataSyntax, Talkable(contact), ParserEscape::NoEscape));
901 
902 	QString info = infoList.join("\n");
903 	if (info.isEmpty())
904 		return;
905 
906 	QApplication::clipboard()->setText(info, QClipboard::Selection);
907 	QApplication::clipboard()->setText(info, QClipboard::Clipboard);
908 
909 	kdebugf2();
910 }
911 
lookupInDirectoryActionActivated(QAction * sender,bool toggled)912 void KaduWindowActions::lookupInDirectoryActionActivated(QAction *sender, bool toggled)
913 {
914 	Q_UNUSED(toggled)
915 
916 	kdebugf();
917 
918 	Action *action = qobject_cast<Action *>(sender);
919 	if (!action)
920 		return;
921 
922 	const Buddy &buddy = action->context()->buddies().toBuddy();
923 	if (!buddy)
924 	{
925 		(m_injectedFactory->makeInjected<SearchWindow>(m_kaduWindowService->kaduWindow()))->show();
926 		return;
927 	}
928 
929 	auto sd = m_injectedFactory->makeInjected<SearchWindow>(m_kaduWindowService->kaduWindow(), buddy);
930 	sd->show();
931 	sd->firstSearch();
932 
933 	kdebugf2();
934 }
935 
inactiveUsersActionActivated(QAction * sender,bool toggled)936 void KaduWindowActions::inactiveUsersActionActivated(QAction *sender, bool toggled)
937 {
938 	QVariant v = sender->data();
939 	if (v.canConvert<HideOfflineTalkableFilter *>())
940 	{
941 		HideOfflineTalkableFilter *filter = v.value<HideOfflineTalkableFilter *>();
942 		filter->setEnabled(!toggled);
943 		m_configuration->deprecatedApi()->writeEntry("General", "ShowOffline", toggled);
944 	}
945 }
946 
descriptionUsersActionActivated(QAction * sender,bool toggled)947 void KaduWindowActions::descriptionUsersActionActivated(QAction *sender, bool toggled)
948 {
949 	QVariant v = sender->data();
950 	if (v.canConvert<HideWithoutDescriptionTalkableFilter *>())
951 	{
952 		auto filter = v.value<HideWithoutDescriptionTalkableFilter *>();
953 		filter->setEnabled(toggled);
954 	}
955 }
956 
showDescriptionsActionActivated(QAction * sender,bool toggled)957 void KaduWindowActions::showDescriptionsActionActivated(QAction *sender, bool toggled)
958 {
959 	Q_UNUSED(sender)
960 
961 	m_configuration->deprecatedApi()->writeEntry("Look", "ShowDesc", toggled);
962 	ConfigurationAwareObject::notifyAll();
963 }
964 
onlineAndDescUsersActionActivated(QAction * sender,bool toggled)965 void KaduWindowActions::onlineAndDescUsersActionActivated(QAction *sender, bool toggled)
966 {
967 	m_configuration->deprecatedApi()->writeEntry("General", "ShowOnlineAndDescription", toggled);
968 
969 	QVariant v = sender->data();
970 	if (v.canConvert<HideOfflineWithoutDescriptionTalkableFilter *>())
971 	{
972 		auto filter = v.value<HideOfflineWithoutDescriptionTalkableFilter *>();
973 		filter->setEnabled(toggled);
974 	}
975 }
976 
configurationUpdated()977 void KaduWindowActions::configurationUpdated()
978 {
979 	ActionContext *context = m_kaduWindowService->kaduWindow()->actionContext();
980 
981 	if (ShowInfoPanel->action(context)->isChecked() != m_configuration->deprecatedApi()->readBoolEntry("Look", "ShowInfoPanel"))
982 		ShowInfoPanel->action(context)->trigger();
983 
984 	if (InactiveUsers->action(context)->isChecked() != m_configuration->deprecatedApi()->readBoolEntry("General", "ShowOffline"))
985 		InactiveUsers->action(context)->trigger();
986 
987 	if (ShowBlockedBuddies->action(context)->isChecked() != m_configuration->deprecatedApi()->readBoolEntry("General", "ShowBlocked"))
988 		ShowBlockedBuddies->action(context)->trigger();
989 
990 	if (ShowMyself->action(context)->isChecked() != m_configuration->deprecatedApi()->readBoolEntry("General", "ShowMyself"))
991 		ShowMyself->action(context)->trigger();
992 }
993 
994 #include "moc_kadu-window-actions.cpp"
995