Warning, file /network/ktp-contact-list/main-widget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of ktp-contact-list 0003 * 0004 * Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk> 0005 * @Author George Goldberg <george.goldberg@collabora.co.uk> 0006 * Copyright (C) 2011 Keith Rusler <xzekecomax@gmail.com> 0007 * Copyright (C) 2011-2013 Martin Klapetek <martin.klapetek@gmail.com> 0008 * Copyright (C) 2012-2012 David Edmundson <kde@davidedmundson.co.uk> 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Lesser General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2.1 of the License, or (at your option) any later version. 0014 * 0015 * This library is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 * Lesser General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Lesser General Public 0021 * License along with this library; if not, write to the Free Software 0022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0023 */ 0024 0025 #include "main-widget.h" 0026 #include "ktp-contactlist-debug.h" 0027 0028 #include <QSortFilterProxyModel> 0029 #include <QPainter> 0030 #include <QMenu> 0031 #include <QToolButton> 0032 #include <QtCore/QWeakPointer> 0033 #include <QWidgetAction> 0034 #include <QCloseEvent> 0035 #include <QDialog> 0036 #include <QMenu> 0037 #include <QMenuBar> 0038 #include <QDebug> 0039 0040 #include <TelepathyQt/PendingChannelRequest> 0041 #include <TelepathyQt/PendingContacts> 0042 #include <TelepathyQt/ContactManager> 0043 #include <TelepathyQt/PendingReady> 0044 #include <TelepathyQt/TextChannel> 0045 0046 #include <KTp/actions.h> 0047 #include <KTp/contact-factory.h> 0048 #include <KTp/types.h> 0049 #include <KTp/global-presence.h> 0050 #include <KTp/Widgets/add-contact-dialog.h> 0051 #include <KTp/Widgets/join-chat-room-dialog.h> 0052 #include <KTp/Widgets/start-chat-dialog.h> 0053 0054 #include <KIO/Job> 0055 #include <KMessageBox> 0056 #include <KProtocolInfo> 0057 #include <ksettings/Dialog> 0058 #include <KSharedConfig> 0059 #include <KStandardShortcut> 0060 #include <KNotification> 0061 #include <KToolInvocation> 0062 #include <KStandardAction> 0063 #include <KHelpMenu> 0064 #include <KAboutData> 0065 #include <KWindowSystem> 0066 #include <KLocalizedString> 0067 0068 #ifdef HAVE_KPEOPLE 0069 // #include <kpeople/widgets/mergedialog.h> //Disable for now, re-enable when kpeople re-enables it 0070 #include <KPeople/PersonsModel> 0071 #endif 0072 0073 #include "ui_main-widget.h" 0074 #include "tooltips/tooltipmanager.h" 0075 #include "context-menu.h" 0076 #include "filter-bar.h" 0077 0078 bool kde_tp_filter_contacts_by_publication_status(const Tp::ContactPtr &contact) 0079 { 0080 return contact->publishState() == Tp::Contact::PresenceStateAsk; 0081 } 0082 0083 MainWidget::MainWidget(QWidget *parent) 0084 : KMainWindow(parent), 0085 m_globalMenu(NULL), 0086 m_settingsDialog(NULL), 0087 m_joinChatRoom(NULL), 0088 m_makeCall(NULL), 0089 m_mergeContacts(NULL), 0090 m_contactListTypeGroup(NULL), 0091 m_blockedFilterGroup(NULL), 0092 m_quitAction(NULL) 0093 { 0094 setupUi(this); 0095 0096 m_filterBar->hide(); 0097 setAutoSaveSettings(); 0098 setupTelepathy(); 0099 0100 KSharedConfigPtr config = KSharedConfig::openConfig(); 0101 KConfigGroup guiConfigGroup(config, "GUI"); 0102 setupActions(guiConfigGroup); 0103 setupToolBar(); 0104 setupGlobalMenu(); 0105 0106 // Restore window geometry, global/by-account presence, search widget state 0107 restoreGeometry(guiConfigGroup.readEntry("window_geometry", QByteArray())); 0108 toggleSearchWidget(guiConfigGroup.readEntry("pin_filterbar", true)); 0109 m_presenceChooser->show(); 0110 0111 m_contextMenu = new ContextMenu(m_contactsListView); 0112 new ToolTipManager(m_contactsListView); 0113 0114 m_messageWidget->setWordWrap(true); 0115 m_messageWidget->setCloseButtonVisible(true); 0116 m_messageWidget->hide(); 0117 0118 connect(m_contactsListView, SIGNAL(customContextMenuRequested(QPoint)), 0119 this, SLOT(onCustomContextMenuRequested(QPoint))); 0120 connect(m_contactsListView->contactsModel(), SIGNAL(modelInitialized(bool)), 0121 this, SLOT(onModelInitialized(bool))); 0122 0123 connect(m_showOfflineAction, SIGNAL(toggled(bool)), 0124 m_contactsListView, SLOT(toggleOfflineContacts(bool))); 0125 connect(m_sortByPresenceAction, SIGNAL(activeChanged(bool)), 0126 m_contactsListView, SLOT(toggleSortByPresence(bool))); 0127 connect(m_metacontactToggleAction, SIGNAL(triggered(bool)), 0128 this, SLOT(onMetacontactToggleTriggered())); 0129 0130 connect(m_filterBar, SIGNAL(filterChanged(QString)), 0131 m_contactsListView, SLOT(setFilterString(QString))); 0132 connect(m_filterBar, SIGNAL(closeRequest()), 0133 m_filterBar, SLOT(hide())); 0134 connect(m_filterBar, SIGNAL(closeRequest()), 0135 m_searchContactAction, SLOT(trigger())); 0136 0137 connect(m_contactsListView, SIGNAL(genericOperationFinished(Tp::PendingOperation*)), 0138 this, SLOT(onGenericOperationFinished(Tp::PendingOperation*))); 0139 0140 connect(m_contactsListView, SIGNAL(actionStarted()), 0141 this, SLOT(clearSearch())); 0142 0143 connect(m_contactsListView, SIGNAL(contactSelectionChanged()), 0144 this, SLOT(onContactSelectionChanged())); 0145 0146 0147 bool showOffline = guiConfigGroup.readEntry("show_offline", false); 0148 m_showOfflineAction->setChecked(showOffline); 0149 m_showOfflineAction->setActive(showOffline); 0150 0151 bool sortByPresence = guiConfigGroup.readEntry("sort_by_presence", true); 0152 m_sortByPresenceAction->setActive(sortByPresence); 0153 0154 bool useGroups = guiConfigGroup.readEntry("use_groups", true); 0155 m_contactsListView->toggleGroups(useGroups); 0156 m_contactsListView->toggleOfflineContacts(showOffline); 0157 m_contactsListView->toggleSortByPresence(sortByPresence); 0158 } 0159 0160 MainWidget::~MainWidget() 0161 { 0162 //save the state of the filter bar, pinned or not 0163 KSharedConfigPtr config = KSharedConfig::openConfig(); 0164 KConfigGroup configGroup(config, "GUI"); 0165 configGroup.writeEntry("pin_filterbar", m_searchContactAction->isChecked()); 0166 configGroup.writeEntry("use_groups", m_groupContactsActionGroup->actions().first()->isChecked()); 0167 configGroup.writeEntry("show_offline", m_showOfflineAction->isChecked()); 0168 configGroup.writeEntry("sort_by_presence", m_sortByPresenceAction->isActive()); 0169 configGroup.config()->sync(); 0170 } 0171 0172 void MainWidget::onAccountManagerReady(Tp::PendingOperation* op) 0173 { 0174 if (op && op->isError()) { 0175 qCDebug(KTP_CONTACTLIST_MODULE) << op->errorName(); 0176 qCDebug(KTP_CONTACTLIST_MODULE) << op->errorMessage(); 0177 0178 KMessageBox::error(this, 0179 i18n("Something unexpected happened to the core part of your Instant Messaging system " 0180 "and it couldn't be initialized. Try restarting the Contact List."), 0181 i18n("IM system failed to initialize")); 0182 return; 0183 } 0184 0185 m_presenceChooser->globalPresence()->setAccountManager(m_accountManager); 0186 m_contactsListView->setAccountManager(m_accountManager); 0187 m_contextMenu->setAccountManager(m_accountManager); 0188 } 0189 0190 void MainWidget::showMessageToUser(const QString& text, const MainWidget::SystemMessageType type) 0191 { 0192 //The pointer is automatically deleted when the event is closed 0193 KNotification *notification; 0194 if (type == MainWidget::SystemMessageError) { 0195 notification = new KNotification("telepathyError", this); 0196 } else { 0197 notification = new KNotification("telepathyInfo", this); 0198 } 0199 0200 notification->setComponentName("ktelepathy"); 0201 0202 notification->setText(text); 0203 notification->sendEvent(); 0204 } 0205 0206 void MainWidget::onAddContactRequest() 0207 { 0208 if (m_accountManager->isReady()) { 0209 KTp::AddContactDialog *dialog = new KTp::AddContactDialog(m_accountManager, this); 0210 dialog->setAttribute(Qt::WA_DeleteOnClose); 0211 dialog->show(); 0212 } 0213 } 0214 0215 void MainWidget::onStartChatRequest() 0216 { 0217 if (m_accountManager->isReady()) { 0218 KTp::StartChatDialog *dialog = new KTp::StartChatDialog(m_accountManager, this); 0219 dialog->setAttribute(Qt::WA_DeleteOnClose); 0220 dialog->show(); 0221 } 0222 } 0223 0224 0225 void MainWidget::onCustomContextMenuRequested(const QPoint &pos) 0226 { 0227 QModelIndex index = m_contactsListView->indexAt(pos); 0228 0229 if (!index.isValid()) { 0230 return; 0231 } 0232 0233 KTp::RowType type = (KTp::RowType)index.data(KTp::RowTypeRole).toInt(); 0234 0235 QMenu *menu = 0; 0236 0237 if (type == KTp::ContactRowType || type == KTp::PersonRowType) { 0238 menu = m_contextMenu->contactContextMenu(index); 0239 } else if (type == KTp::GroupRowType) { 0240 menu = m_contextMenu->groupContextMenu(index); 0241 } 0242 0243 if (menu) { 0244 menu->exec(QCursor::pos()); 0245 menu->deleteLater(); 0246 } 0247 } 0248 0249 void MainWidget::onGenericOperationFinished(Tp::PendingOperation* operation) 0250 { 0251 if (operation->isError()) { 0252 QString errorMsg(operation->errorName() + ": " + operation->errorMessage()); 0253 showMessageToUser(errorMsg, SystemMessageError); 0254 } 0255 } 0256 0257 void MainWidget::onJoinChatRoomRequested() 0258 { 0259 if (m_accountManager->isReady()) { 0260 KTp::JoinChatRoomDialog *dialog = new KTp::JoinChatRoomDialog(m_accountManager); 0261 dialog->setAttribute(Qt::WA_DeleteOnClose); 0262 0263 dialog->show(); 0264 } 0265 } 0266 0267 void MainWidget::onMakeCallRequested() 0268 { 0269 KToolInvocation::kdeinitExec(QLatin1String("ktp-dialout-ui")); 0270 } 0271 0272 void MainWidget::onMergeContactsDialogRequested() 0273 { 0274 /* 0275 #ifdef HAVE_KPEOPLE 0276 KPeople::MergeDialog* mergeDialog = new KPeople::MergeDialog(this); 0277 //create a new model that queries all the data otherwise we will only show IM contacts 0278 KPeople::PersonsModel* model = new KPeople::PersonsModel(mergeDialog); 0279 mergeDialog->setPersonsModel(model); 0280 model->startQuery(KPeople::PersonsModelFeature::allFeatures()); 0281 mergeDialog->show(); 0282 mergeDialog->setAttribute(Qt::WA_DeleteOnClose); 0283 #endif 0284 */ 0285 } 0286 0287 void MainWidget::closeEvent(QCloseEvent* e) 0288 { 0289 KSharedConfigPtr config = KSharedConfig::openConfig(); 0290 KConfigGroup generalConfigGroup(config, "General"); 0291 KConfigGroup notifyConigGroup(config, "Notification Messages"); 0292 KConfigGroup guiConfigGroup(config, "GUI"); 0293 0294 if (qApp->closingDown()) { 0295 //the standard KMessageBox control saves "true" if you select the checkbox, therefore the reversed var name 0296 bool dontCheckForPlasmoid = notifyConigGroup.readEntry("dont_check_for_plasmoid", false); 0297 bool onlineAccounts = !m_presenceChooser->globalPresence()->onlineAccounts()->accounts().isEmpty(); 0298 0299 if (onlineAccounts && !dontCheckForPlasmoid) { 0300 if (!isPresencePlasmoidPresent()) { 0301 switch (KMessageBox::warningYesNoCancel(this, 0302 i18n("You do not have any other presence controls active (a Presence widget for example).\n" 0303 "Do you want to stay online or would you rather go offline?"), 0304 i18n("No Other Presence Controls Found"), 0305 KGuiItem(i18n("Stay Online"), QIcon::fromTheme("user-online")), 0306 KGuiItem(i18n("Go Offline"), QIcon::fromTheme("user-offline")), 0307 KStandardGuiItem::cancel(), 0308 QString("dont_check_for_plasmoid"))) { 0309 0310 case KMessageBox::No: 0311 generalConfigGroup.writeEntry("go_offline_when_closing", true); 0312 m_presenceChooser->globalPresence()->setPresence(KTp::Presence::offline(), KTp::GlobalPresence::Session); 0313 break; 0314 case KMessageBox::Cancel: 0315 default: 0316 e->ignore(); 0317 return; 0318 } 0319 } 0320 } else if (onlineAccounts && dontCheckForPlasmoid) { 0321 bool shouldGoOffline = generalConfigGroup.readEntry("go_offline_when_closing", false); 0322 if (shouldGoOffline) { 0323 m_presenceChooser->globalPresence()->setPresence(KTp::Presence::offline(), KTp::GlobalPresence::Session); 0324 } 0325 } 0326 0327 generalConfigGroup.config()->sync(); 0328 } 0329 0330 // Save window geometry 0331 guiConfigGroup.writeEntry("window_geometry", saveGeometry()); 0332 guiConfigGroup.config()->sync(); 0333 0334 KMainWindow::closeEvent(e); 0335 } 0336 0337 bool MainWidget::isPresencePlasmoidPresent() const 0338 { 0339 QDBusReply<bool> serviceRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Telepathy.PresenceApplet"); 0340 0341 if (serviceRegistered.isValid() && serviceRegistered.value()) { 0342 return true; 0343 } else { 0344 return false; 0345 } 0346 } 0347 0348 void MainWidget::toggleSearchWidget(bool show) 0349 { 0350 m_searchContactAction->setChecked(show); 0351 if(show) { 0352 m_filterBar->show(); 0353 } else { 0354 m_contactsListView->setFilterString(QString()); 0355 m_filterBar->clear(); 0356 m_filterBar->hide(); 0357 } 0358 } 0359 0360 void MainWidget::clearSearch() 0361 { 0362 m_filterBar->clear(); 0363 } 0364 0365 void MainWidget::setupGlobalMenu() 0366 { 0367 // Since our menu is hidden, its shortcuts do not work. 0368 // Here's a workarond: we must assign global menu's unique 0369 // items to main window. Since it's always active when an 0370 // application is active, shortcuts now will work properly. 0371 0372 m_globalMenu = new QMenuBar(this); 0373 m_globalMenu->setVisible(false); 0374 0375 QMenu *contacts = new QMenu(i18n("Contacts"), m_globalMenu); 0376 contacts->addAction(m_addContactAction); 0377 contacts->addAction(m_joinChatRoom); 0378 if (!QStandardPaths::findExecutable("ktp-dialout-ui").isEmpty()) { 0379 contacts->addAction(m_makeCall); 0380 } 0381 //temporarily disable until funcationality is restored in libkpeople 0382 if (KTp::kpeopleEnabled()) { 0383 // contacts->addAction(m_mergeContacts); 0384 } 0385 contacts->addAction(m_settingsDialog); 0386 contacts->addSeparator(); 0387 contacts->addAction(m_quitAction); 0388 this->addAction(m_quitAction); // Shortcuts workaround. 0389 m_globalMenu->addMenu(contacts); 0390 0391 QMenu *view = new QMenu(i18n("View"), m_globalMenu); 0392 view->addAction(m_showOfflineAction); 0393 view->addAction(m_sortByPresenceAction); 0394 view->addSeparator(); 0395 QMenu *view_contactListTypeMenu = new QMenu(i18n("Contact List Type"), view); 0396 view_contactListTypeMenu->addActions(m_contactListTypeGroup->actions()); 0397 view->addMenu(view_contactListTypeMenu); 0398 QMenu *view_blockedFilterMenu = new QMenu(i18n("Shown Contacts"), view); 0399 view_blockedFilterMenu->addActions(m_blockedFilterGroup->actions()); 0400 view->addMenu(view_blockedFilterMenu); 0401 QMenu *view_showGroupedMenu = new QMenu(i18n("Contact Grouping"), view); 0402 view_showGroupedMenu->addActions(m_groupContactsActionGroup->actions()); 0403 view->addMenu(view_showGroupedMenu); 0404 m_globalMenu->addMenu(view); 0405 KHelpMenu *helpMenu = new KHelpMenu(this, KAboutData::applicationData()); 0406 m_globalMenu->addMenu(helpMenu->menu()); 0407 } 0408 0409 void MainWidget::setupToolBar() 0410 { 0411 m_toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); 0412 if (KTp::kpeopleEnabled()) { 0413 m_toolBar->addAction(m_metacontactToggleAction); 0414 } 0415 m_toolBar->addAction(m_addContactAction); 0416 m_toolBar->addAction(m_searchContactAction); 0417 m_toolBar->addAction(m_showOfflineAction); 0418 m_toolBar->addAction(m_sortByPresenceAction); 0419 m_toolBar->addSeparator(); 0420 m_toolBar->addAction(m_startChatAction); 0421 m_toolBar->addAction(m_joinChatRoom); 0422 0423 QWidget *toolBarSpacer = new QWidget(this); 0424 toolBarSpacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); 0425 m_toolBar->addWidget(toolBarSpacer); 0426 0427 QToolButton *settingsButton = new QToolButton(this); 0428 settingsButton->setIcon(QIcon::fromTheme("configure")); 0429 settingsButton->setPopupMode(QToolButton::InstantPopup); 0430 0431 QMenu *settingsButtonMenu = new QMenu(settingsButton); 0432 settingsButtonMenu->addAction(m_settingsDialog); 0433 0434 QActionGroup *delegateTypeGroup = new QActionGroup(this); 0435 delegateTypeGroup->setExclusive(true); 0436 0437 QMenu *setDelegateTypeMenu = new QMenu(settingsButtonMenu); 0438 setDelegateTypeMenu->setTitle(i18n("Contact List Type")); 0439 setDelegateTypeMenu->addActions(m_contactListTypeGroup->actions()); 0440 settingsButtonMenu->addMenu(setDelegateTypeMenu); 0441 0442 QMenu *setBlockedFilterMenu = new QMenu(settingsButtonMenu); 0443 setBlockedFilterMenu->setTitle(i18n("Shown Contacts")); 0444 setBlockedFilterMenu->addActions(m_blockedFilterGroup->actions()); 0445 settingsButtonMenu->addMenu(setBlockedFilterMenu); 0446 0447 QMenu *showGroupedMenu = new QMenu(settingsButton); 0448 showGroupedMenu->setTitle(i18n("Contact Grouping")); 0449 showGroupedMenu->addActions(m_groupContactsActionGroup->actions()); 0450 settingsButtonMenu->addMenu(showGroupedMenu); 0451 0452 if (!QStandardPaths::findExecutable("ktp-dialout-ui").isEmpty()) { 0453 settingsButtonMenu->addAction(m_makeCall); 0454 } 0455 0456 if (KTp::kpeopleEnabled()) { 0457 // settingsButtonMenu->addAction(m_mergeContacts); 0458 } 0459 0460 settingsButtonMenu->addSeparator(); 0461 0462 KHelpMenu *helpMenu = new KHelpMenu(this, KAboutData::applicationData()); 0463 settingsButtonMenu->addMenu(helpMenu->menu()); 0464 0465 settingsButton->setMenu(settingsButtonMenu); 0466 0467 m_toolBar->addWidget(settingsButton); 0468 } 0469 0470 void MainWidget::setupTelepathy() 0471 { 0472 Tp::registerTypes(); 0473 0474 if (KTp::kpeopleEnabled()) { 0475 m_accountManager = KTp::accountManager(); 0476 } else { 0477 0478 Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(), 0479 Tp::Features() << Tp::Account::FeatureCore 0480 << Tp::Account::FeatureAvatar 0481 << Tp::Account::FeatureCapabilities 0482 << Tp::Account::FeatureProtocolInfo 0483 << Tp::Account::FeatureProfile); 0484 0485 Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(QDBusConnection::sessionBus(), 0486 Tp::Features() << Tp::Connection::FeatureCore 0487 << Tp::Connection::FeatureSelfContact); 0488 0489 Tp::ContactFactoryPtr contactFactory = KTp::ContactFactory::create(Tp::Features() << Tp::Contact::FeatureAlias 0490 << Tp::Contact::FeatureAvatarToken 0491 << Tp::Contact::FeatureAvatarData 0492 << Tp::Contact::FeatureSimplePresence 0493 << Tp::Contact::FeatureCapabilities 0494 << Tp::Contact::FeatureClientTypes); 0495 0496 Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus()); 0497 0498 m_accountManager = Tp::AccountManager::create(QDBusConnection::sessionBus(), 0499 accountFactory, 0500 connectionFactory, 0501 channelFactory, 0502 contactFactory); 0503 } 0504 0505 connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)), 0506 this, SLOT(onAccountManagerReady(Tp::PendingOperation*))); 0507 } 0508 0509 QAction *MainWidget::createAction(const QString &text, QObject *signalReceiver, const char *slot, const QIcon &icon = QIcon()) 0510 { 0511 QAction *action = new QAction(icon, text, this); 0512 action->setToolTip(text); 0513 connect(action, SIGNAL(triggered(bool)), signalReceiver, slot); 0514 return action; 0515 } 0516 0517 QAction *MainWidget::createAction(const QString& text, QObject *signalReceiver, const char* slot, bool isChecked, const QIcon &icon = QIcon()) 0518 { 0519 QAction *action = createAction(text, signalReceiver, slot, icon); 0520 action->setCheckable(true); 0521 action->setChecked(isChecked); 0522 return action; 0523 } 0524 0525 void MainWidget::setupActions(const KConfigGroup& guiConfigGroup) 0526 { 0527 m_settingsDialog = KStandardAction::preferences(m_contactsListView, SLOT(showSettingsKCM()),this); 0528 m_settingsDialog->setText(i18n("Instant Messaging Settings...")); // We set text manually since standard name is too long 0529 0530 m_quitAction = KStandardAction::quit(this, SLOT(close()), this); 0531 m_quitAction->setMenuRole(QAction::QuitRole); 0532 0533 m_joinChatRoom = createAction(i18n("Join Chat Room..."), this, SLOT(onJoinChatRoomRequested())); 0534 m_joinChatRoom->setIcon(QIcon::fromTheme("im-irc")); 0535 m_makeCall = createAction(i18n("Make a Call..."), this, SLOT(onMakeCallRequested())); 0536 m_mergeContacts = createAction(i18n("Merge Contacts..."), this, SLOT(onMergeContactsDialogRequested())); 0537 m_addContactAction = createAction(i18n("Add New Contacts..."), this, SLOT(onAddContactRequest()), QIcon::fromTheme("list-add-user")); 0538 m_searchContactAction = createAction(i18n("Find Contact"), this, SLOT(toggleSearchWidget(bool)), 0539 guiConfigGroup.readEntry("pin_filterbar", true), QIcon::fromTheme("edit-find")); 0540 m_searchContactAction->setShortcuts(KStandardShortcut::find()); 0541 m_startChatAction = createAction(i18n("Start a Chat..."), this, SLOT(onStartChatRequest()), QIcon::fromTheme("telepathy-kde")); 0542 0543 // Dual actions 0544 m_metacontactToggleAction = new KDualAction(i18n("Split Selected Contacts"), 0545 i18n("Merge Selected Contacts"), 0546 this); 0547 m_metacontactToggleAction->setActiveIcon(QIcon::fromTheme("user-group-new")); 0548 m_metacontactToggleAction->setInactiveIcon(QIcon::fromTheme("user-group-delete")); 0549 m_metacontactToggleAction->setActive(true); 0550 m_metacontactToggleAction->setDisabled(true); 0551 m_metacontactToggleAction->setAutoToggle(false); 0552 0553 m_groupContactsActionGroup = new QActionGroup(this); 0554 m_groupContactsActionGroup->setExclusive(true); 0555 m_groupContactsActionGroup->addAction(createAction(i18n("Show Contacts by Groups"), m_contactsListView, SLOT(showGrouped()), 0556 guiConfigGroup.readEntry("use_groups", true))); 0557 QString useGroupsDisabledText; 0558 if (KTp::kpeopleEnabled()) { 0559 useGroupsDisabledText = i18n("Do Not Group"); 0560 } 0561 else { 0562 useGroupsDisabledText = i18n("Show Contacts by Accounts"); 0563 } 0564 m_groupContactsActionGroup->addAction(createAction(useGroupsDisabledText, m_contactsListView, SLOT(showUngrouped()), 0565 ! guiConfigGroup.readEntry("use_groups", true))); 0566 0567 m_showOfflineAction = new KDualAction(i18n("Show Offline Contacts"), 0568 i18n("Hide Offline Contacts"), 0569 this); 0570 m_showOfflineAction->setActiveIcon(QIcon::fromTheme("show-offline")); 0571 m_showOfflineAction->setInactiveIcon(QIcon::fromTheme("show-offline")); 0572 m_showOfflineAction->setCheckable(true); 0573 m_showOfflineAction->setChecked(false); 0574 m_showOfflineAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); 0575 0576 m_sortByPresenceAction = new KDualAction(i18n("Sort by Presence"), 0577 i18n("Sort by Name"), 0578 this); 0579 m_sortByPresenceAction->setActiveIcon(QIcon::fromTheme("sort-presence")); 0580 m_sortByPresenceAction->setInactiveIcon(QIcon::fromTheme("sort-name")); 0581 0582 // Setup contact list appearance 0583 m_contactListTypeGroup = new QActionGroup(this); 0584 m_contactListTypeGroup->setExclusive(true); 0585 m_contactListTypeGroup->addAction(createAction(i18n("Use Full List"), m_contactsListView, SLOT(onSwitchToFullView()), 0586 guiConfigGroup.readEntry("selected_delegate", "normal") == QLatin1String("full"))); 0587 m_contactListTypeGroup->addAction(createAction(i18n("Use Normal List"), m_contactsListView, SLOT(onSwitchToCompactView()), 0588 guiConfigGroup.readEntry("selected_delegate", "normal") == QLatin1String("normal") 0589 || guiConfigGroup.readEntry("selected_delegate", "normal") == QLatin1String("compact"))); //needed for backwards compatibility 0590 0591 m_contactListTypeGroup->addAction(createAction(i18n("Use Minimalistic List"), m_contactsListView, SLOT(onSwitchToMiniView()), 0592 guiConfigGroup.readEntry("selected_delegate", "normal") == QLatin1String("mini"))); 0593 0594 // Setup blocked contacts filtering 0595 QString shownContacts = guiConfigGroup.readEntry("shown_contacts", "unblocked"); 0596 m_blockedFilterGroup = new QActionGroup(this); 0597 m_blockedFilterGroup->setExclusive(true); 0598 m_blockedFilterGroup->addAction(createAction(i18n("Show All Contacts"), m_contactsListView, SLOT(onShowAllContacts()), 0599 shownContacts == QLatin1String("all"))); 0600 m_blockedFilterGroup->addAction(createAction(i18n("Show Unblocked Contacts"), m_contactsListView, SLOT(onShowUnblockedContacts()), 0601 shownContacts == QLatin1String("unblocked"))); 0602 m_blockedFilterGroup->addAction(createAction(i18n("Show Blocked Contacts"), m_contactsListView, SLOT(onShowBlockedContacts()), 0603 shownContacts == QLatin1String("blocked"))); 0604 } 0605 0606 void MainWidget::toggleWindowVisibility() 0607 { 0608 if (isActiveWindow()) { 0609 close(); 0610 } else { 0611 KWindowSystem::forceActiveWindow(this->effectiveWinId()); 0612 } 0613 } 0614 0615 void MainWidget::onContactSelectionChanged() 0616 { 0617 QModelIndexList selection = m_contactsListView->selectionModel()->selectedIndexes(); 0618 if (selection.size() == 0) { 0619 //if nothing is selected, disable the button 0620 m_metacontactToggleAction->setActive(true); 0621 m_metacontactToggleAction->setDisabled(true); 0622 return; 0623 } else if (selection.size() == 1) { 0624 QModelIndex index = selection.first(); 0625 if (index.data(KTp::RowTypeRole).toInt() == KTp::PersonRowType || 0626 (index.parent().isValid() && index.parent().data(KTp::RowTypeRole).toInt() == KTp::PersonRowType)) { 0627 //if a person is selected or a subcontact is selected, switch to unlink action and enable 0628 m_metacontactToggleAction->setActive(false); 0629 m_metacontactToggleAction->setEnabled(true); 0630 return; 0631 } 0632 } else if (selection.size() > 1) { 0633 bool invalid = false; 0634 //we cannot merge child contact of a person with anything else 0635 Q_FOREACH (const QModelIndex &index, selection) { 0636 if (index.parent().isValid() && index.parent().data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0637 invalid = true; 0638 break; 0639 } 0640 } 0641 0642 if (!invalid) { 0643 m_metacontactToggleAction->setActive(true); 0644 m_metacontactToggleAction->setEnabled(true); 0645 return; 0646 } 0647 } 0648 0649 m_metacontactToggleAction->setActive(true); 0650 m_metacontactToggleAction->setDisabled(true); 0651 } 0652 0653 void MainWidget::onMetacontactToggleTriggered() 0654 { 0655 #ifdef HAVE_KPEOPLE 0656 const QModelIndexList selection = m_contactsListView->selectionModel()->selectedIndexes(); 0657 0658 Q_ASSERT(!selection.isEmpty()); 0659 if (m_metacontactToggleAction->isActive()) { 0660 //we're merging contacts 0661 bool invalid = false; 0662 QModelIndex person; 0663 QStringList uris; 0664 0665 Q_FOREACH (const QModelIndex &index, selection) { 0666 if (index.parent().isValid() 0667 && index.parent().data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0668 //we can merge only standalone contacts, not a contact that's already part of a person 0669 invalid = true; 0670 qCDebug(KTP_CONTACTLIST_MODULE) << "Found selected subcontact, aborting"; 0671 break; 0672 } 0673 0674 //the selection can have at most one person, so if we encounter second person 0675 //we break and do nothing 0676 if (index.data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0677 if (person.isValid()) { 0678 invalid = true; 0679 qCDebug(KTP_CONTACTLIST_MODULE) << "Found second person, aborting"; 0680 break; 0681 } else { 0682 qCDebug(KTP_CONTACTLIST_MODULE) << "Found a person, adding"; 0683 person = index; 0684 } 0685 } 0686 0687 //if we're dealing with contact that's a child of selected person 0688 //(we should never get here) 0689 if (index.parent().isValid() && index.parent() == person) { 0690 invalid = true; 0691 qCDebug(KTP_CONTACTLIST_MODULE) << "Found subcontact of selected person, aborting"; 0692 break; 0693 } 0694 0695 uris << index.data(KTp::PersonIdRole).toString(); 0696 } 0697 0698 if (!invalid) { 0699 KPeople::mergeContacts(uris); 0700 } 0701 } else { 0702 //we're removing contacts from person 0703 QStringList contacts; 0704 const QModelIndex &index = selection.first(); 0705 QString uri; 0706 0707 if (index.parent().isValid() && index.parent().data(KTp::RowTypeRole).toInt() == KTp::PersonRowType) { 0708 uri = index.data(KTp::ContactUriRole).toString(); 0709 } else { 0710 uri = index.data(KTp::PersonIdRole).toString(); 0711 } 0712 KPeople::unmergeContact(uri); 0713 } 0714 #endif 0715 } 0716 0717 void MainWidget::onModelInitialized(bool success) 0718 { 0719 if (!success) { 0720 m_messageWidget->setMessageType(KMessageWidget::Warning); 0721 m_messageWidget->setText(i18n("Some data sources failed to initialize properly, your contact list might be incomplete.")); 0722 m_messageWidget->animatedShow(); 0723 } 0724 0725 m_contactsListView->contactsModel()->setTrackUnreadMessages(true); 0726 }