/*************************************************************************** kmess.cpp - description ------------------- begin : Sun Jan 5 15:18:36 CST 2003 copyright : (C) 2003 by Mike K. Bennett email : mkb137b@hotmail.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kmess.h" #include "emoticon.h" // workarround for mingw-g++ compiler bug "extraneous `char' ignored" #include "emoticontheme.h" // #include "emoticonmanager.h" // #include "chat/chat.h" #include "chat/chatmaster.h" #include "contact/contact.h" #include "contact/group.h" #include "contact/msnstatus.h" #include "dialogs/addcontactdialog.h" #include "dialogs/awaymessagedialog.h" #include "dialogs/chathistorydialog.h" #include "dialogs/contactaddeduserdialog.h" #include "dialogs/listexportdialog.h" #include "dialogs/transferwindow.h" #include "model/contactlist.h" #include "network/msnnotificationconnection.h" #include "notification/notificationmanager.h" #include "notification/chatnotification.h" #include "notification/contactstatusnotification.h" #include "notification/newemailnotification.h" #include "notification/systemtraywidget.h" #include "settings/accountsettingsdialog.h" #include "utils/idletimer.h" #include "utils/kmessconfig.h" #include "utils/kmessdbus.h" #include "utils/kmessshared.h" #include "utils/nowlisteningclient.h" #include "utils/richtextparser.h" #include "account.h" #include "accountsmanager.h" #include "accountaction.h" #include "currentaccount.h" #include "emoticonmanager.h" #include "initialview.h" #include "kmessdebug.h" #include "kmessinterface.h" #include "kmessview.h" #include <QDir> #include <QNetworkProxy> #include <KActionMenu> #include <KConfig> #include <KGlobal> #include <KInputDialog> #include <KLocale> #include <KMessageBox> #include <KMenu> #include <KProtocolManager> #include <KSelectAction> #include <KStandardDirs> #include <KStatusBar> #include <KToggleAction> #ifdef KMESSTEST #include "dialogs/networkwindow.h" #endif // The constructor KMess::KMess( QWidget *parent ) : KMessInterface( parent ), chatMaster_(0), chatNotification_(0), contactStatusNotification_(0), newEmailNotification_(0), idleTimer_(0), initialized_(false), initialView_(0), nowListeningClient_(0), msnNotificationConnection_(0), view_(0) { } // The destructor KMess::~KMess() { #ifdef KMESSDEBUG_KMESS kDebug() << "shutting down KMess..."; #endif /* * The destructor is called after closeEvent(), * when KMess is quit by the user. * * If the KDE session ends, the destructor won't be called. * only saveProperties() will be called, and the execution ends. */ // Saving properties manually. saveProperties(); // Delete all chat windows if(chatMaster_ != 0) { chatMaster_->disconnected(); chatMaster_->deleteLater(); chatMaster_ = 0; } // Disconnect main connection so views can clean up/save properties. if(msnNotificationConnection_->isConnected()) { // Make sure KMess::disconnected() does attempt to update // the user interface when we're trying to kill it disconnect(msnNotificationConnection_, SIGNAL(disconnected()), this, SLOT(disconnected()) ); // This also destroys all contacts msnNotificationConnection_->closeConnection(); } // Delete other created objects delete idleTimer_; delete chatNotification_; delete contactStatusNotification_; delete notificationManager_; delete newEmailNotification_; delete nowListeningClient_; delete msnNotificationConnection_; AccountsManager::destroy(); CurrentAccount::destroy(); TransferWindow::destroy(); KMessConfig::destroy(); #ifdef KMESS_NETWORK_WINDOW NetworkWindow::destroy(); #endif #ifdef KMESSDEBUG_KMESS kDebug() << "DESTROYED."; #endif } // Add the account to the GUI void KMess::slotAccountAdded(Account *account) { // Check if the account is already present in the menus if( connectMenuItems_.contains( account ) ) { return; } AccountAction *accountAction; // Make the action for the "Connect..." menu accountAction = new AccountAction( account, this ); connectActionMenu_->addAction( accountAction ); connectMenuItems_[ account ] = accountAction; connect( accountAction, SIGNAL( activated(Account*) ), this, SLOT ( connectWithAccount(Account*) ) ); // If the initial login window is visible, add the new account there if it's not a guestAccount if( initialView_ && ! account->isGuestAccount()) { initialView_->addAccount( account ); } } // "Add a new contact" was selected from the menu. void KMess::addNewContact() { #ifdef KMESSTEST KMESS_ASSERT( msnNotificationConnection_ != 0 ); #endif QStringList groupsId; QString newHandle; // Launch a modal dialog to get the new contact handle and, optionally, group new AddContactDialog( newHandle, groupsId, this ); // Do nothing if the user has clicked cancel if( newHandle.isEmpty() ) { return; } #ifdef KMESSDEBUG_KMESS kDebug() << "Adding " << newHandle << "to groups: " << groupsId; #endif // Check if the contact is already in contact list Contact *contact = currentAccount_->getContactList()->getContactByHandle( newHandle ); if( contact != 0 ) { // If the contact is already in friendly list, stop the process if( contact->isFriend() ) { QMessageBox::information( this, i18n( "Contact Information" ), i18n( "<html>The contact <b>%1</b> is already in your contact list.</html>", newHandle ) ); return; } else { // The user is adding one deleted contact msnNotificationConnection_->addExistingContact( newHandle, groupsId ); return; } } // Ask the server to add the contact msnNotificationConnection_->addNewContact( newHandle, groupsId ); } // "Add a new group" was selected from the menu. void KMess::addNewGroup() { #ifdef KMESSTEST KMESS_ASSERT( msnNotificationConnection_ != 0 ); #endif #ifdef KMESSDEBUG_KMESS kDebug(); #endif QString newGroupName; bool okPressed = false; // Set a default group name newGroupName = i18n( "New Group" ); // Launch a dialog to get a new group name newGroupName = KInputDialog::getText(i18nc( "Dialog box title", "Add a Group" ), i18n( "Enter a name for the new group:" ), newGroupName, &okPressed, this); if(okPressed) { // Check if the group already exists. Group *group = currentAccount_->getContactList()->getGroupByName( newGroupName ); if( group != 0 ) { return; } // Ask the server to add the group msnNotificationConnection_->addGroup( newGroupName ); } } // The application is closing, after queryClose() was approved void KMess::applicationClosing() { // Prepare closing, KMessInterface::queryClose() accepted the close request. // After this method returns, KApplication::aboutToQuit() also kicks in, handled by KMessApplication. if( chatMaster_ != 0 ) { #ifdef KMESSDEBUG_KMESS kDebug() << "destroying chat master"; #endif // Close the chat windows earlier, so logs are saved. chatMaster_->deleteLater(); chatMaster_ = 0; } } // An account's settings have been changed void KMess::slotAccountChanged( Account *account, QString oldHandle, QString oldFriendlyName ) { QString newHandle( account->getHandle() ); #ifdef KMESSDEBUG_KMESS kDebug() << "Saving UI settings for" << newHandle; #endif if ( msnNotificationConnection_ != 0 ) { // While we're saving stuff, also save the contact list settings msnNotificationConnection_->saveProperties(); bool isCurrentAccount = ( oldHandle == currentAccount_->getHandle() ); bool isConnectedCurrentAccount = ( isCurrentAccount && msnNotificationConnection_->isConnected() ); // If the account matches the current account and the friendly name was changed, ask the server to change it if( isConnectedCurrentAccount && account->isVerified() && account->getFriendlyName( STRING_ORIGINAL ) != oldFriendlyName ) { msnNotificationConnection_->changeFriendlyName( account->getFriendlyName( STRING_ORIGINAL ) ); } } // Change the account name in the UI when it's been changed if( oldHandle == newHandle ) { return; } // Update it in the initial view's list of accounts if( initialView_ ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Updating initial view"; #endif // Notify the initial view when the account handle has changed. initialView_->changedAccount( oldHandle, newHandle ); } // Update the menu items connectMenuItems_ [ account ]->updateText(); } // A view pictures mode has been selected from the menu. void KMess::changedListPictureSize( int mode ) { int newMode = 0; switch( mode ) { case 0: break; case 1: newMode = 32; break; case 2: newMode = 40; break; case 3: newMode = 48; break; default: break; } currentAccount_->setListPictureSize( newMode ); } // A status was selected from the menu. void KMess::changeStatus( QAction *action ) { QString awayMessage; Status newStatus = (Status) action->data().toInt(); // The user has set Away with Auto Reply, let it choose the message if( newStatus == STATUS_AWAY_AUTOREPLY ) { awayMessage = currentAccount_->getAutoreplyMessage(); // Create and show the away message dialog AwayMessageDialog *awayMessageDialog = new AwayMessageDialog( this ); bool useAutoreply = awayMessageDialog->useMessage( awayMessage ); if( ! useAutoreply ) { awayMessage.clear(); } delete awayMessageDialog; } // The user wants to disconnect if( newStatus == STATUS_OFFLINE ) { disconnectClicked(); return; } changeStatus( newStatus, awayMessage ); } // We should change status to this right away (can be called by changeStatus() or by other code) void KMess::changeStatus( Status newStatus, QString autoReplyMessage ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Selected status:" << MsnStatus::getCode( newStatus ); #endif // Is the status is set manually, idle is forced. isIdleForced_ = true; // Set or unset the auto reply message if( autoReplyMessage.isEmpty() ) { currentAccount_->setAutoreply( false ); } else { currentAccount_->setAutoreplyMessage( autoReplyMessage ); currentAccount_->setAutoreply( true ); } // Change status msnNotificationConnection_->changeStatus( newStatus ); } // The current now listening settings have changed. void KMess::changedNowListeningSettings() { // Enable now listening if current account is online and likes to enable now listening. Status status = currentAccount_->getStatus(); // Enable only if not offline or invisible bool isOnline = ( status != STATUS_OFFLINE && status != STATUS_INVISIBLE ); nowListeningClient_->setEnabled( currentAccount_->getShowNowListening() && isOnline ); #ifdef KMESSDEBUG_KMESS kDebug() << "Now listening setting is now" << ( currentAccount_->getShowNowListening() ? "enabled" : "disabled") << endl; #endif } // The currently playing song was changed. void KMess::changedSong( const QString &artist, const QString &album, const QString &track, bool playing ) { if( msnNotificationConnection_->isConnected() ) { if( ! playing ) { // Update notification connection and KMessView. msnNotificationConnection_->removeCurrentMedia(); } else { // Update notification connection. QStringList arguments; arguments << track << artist << album << "" << ""; msnNotificationConnection_->changeCurrentMedia( "", "Music", true, "{0} - {1}", arguments ); } // Update KMessView if( view_ ) { view_->changedSong( artist, album, track, playing ); } } } // The status was changed void KMess::changedStatus( Account *account ) { Status newStatus; if( account != 0 ) { newStatus = account->getInitialStatus(); } else if ( currentAccount_ != 0 ) { newStatus = currentAccount_->getStatus(); } else { kWarning() << "Changed status dropdown without an account set!"; return; } #ifdef KMESSDEBUG_KMESS kDebug() << "Changed status to" << MsnStatus::getCode( newStatus ) << "Autoreply is" << currentAccount_->getAutoreply() << endl; #endif // Make sure the drop down list matches the user's status QList<KAction*> menuActions( status_->findChildren<KAction*>() ); foreach( KAction *action, menuActions ) { if( (Status) action->data().toInt() == newStatus ) { action->setEnabled( false ); } else { action->setEnabled( true ); } } } // A view mode has been selected from the menu. void KMess::changeViewMode(int mode) { #ifdef KMESSTEST KMESS_ASSERT( ( mode >= 0 ) || ( mode <= 2 ) ); #endif CurrentAccount::instance()->setContactListDisplayMode( (Account::ContactListDisplayMode) mode ); } // Show a "Contact added you" dialog void KMess::showContactAddedUserDialog( const QString handle ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Contact" << handle << "added user, showing dialog."; #endif // Show a dialog and let the user choose whether to add, allow, or block the contact. ContactAddedUserDialog *dialog = new ContactAddedUserDialog( handle , handle ); connect( dialog, SIGNAL( userChoice(const QString&,const QStringList&,const int) ), this, SLOT ( slotContactAddedUserDialogChoice(const QString&,const QStringList&,const int) ) ); dialog->show(); } // Show the context-sensitive menu item void KMess::showContextMenu() { if( KMESS_NULL( view_ ) ) return; if( KMESS_NULL( connectActionMenu_ ) ) return; if( KMESS_NULL( contextMenuAction_ ) ) return; // HACK: Get where the triggered action is located, by asking a menu QRect actionPos( connectActionMenu_->menu()->actionGeometry( contextMenuAction_ ) ); view_->showContextMenu( actionPos.bottomRight() ); // Approximate to a side of the action, can't really do more } void KMess::showListExportDialog() { ListExportDialog *listExportDialog = new ListExportDialog(); listExportDialog->show(); } #ifdef KMESS_NETWORK_WINDOW // Opens the network window void KMess::showNetworkWindow() { NetworkWindow::instance()->show(); } #endif // Show a dialog before removing the contact void KMess::showRemoveContactDialog(QString handle) { QString message( i18n( "<qt>Are you sure you want to remove the contact <b>%1</b> from your contact list?</qt>", handle ) ); int result = KMessageBox::warningYesNoCancel( this, message, i18n( "Remove Contact" ) , KGuiItem(i18n("Remove"), "edit-delete") // Yes , KGuiItem(i18n("Remove and Block"), "list-remove") // No , KStandardGuiItem::cancel() , QString() , KMessageBox::Dangerous ); switch( result ) { // User has pressed "Remove and block" case KMessageBox::No : msnNotificationConnection_->removeContact( handle, true ); break; // User has pressed "Remove only" case KMessageBox::Yes : msnNotificationConnection_->removeContact( handle, false ); break; // User has canceled the action, no nothing case KMessageBox::Cancel : default: break; } } // Show a dialog before removing the group void KMess::showRemoveGroupDialog(QString groupId) { const ContactList *list = currentAccount_->getContactList(); Group *group = list->getGroupById( groupId ); // If the group was not found, bail out if(group == 0) { kDebug() << "Couldn't find a matching group."; return; } // If the group was not empty, bail also out. We would receive an error from the server, otherwise if( ! list->isGroupEmpty( groupId ) ) { // TODO Allow the user to choose between: 1) delete or delete+block all contacts in the group; // 2) remove all contacts from the group; 3) cancel the operation. KMessageBox::error( this, i18nc( "dialog text", "The group <b>%1</b> is not empty! First remove all contacts from it, then try again!", group->getName() ), i18nc( "dialog title", "Group Removal" ) ); return; } // Prompt to remove QString message( i18nc( "dialog text", "<qt>Are you sure you want to remove the group <b>%1</b> from your contact list?</qt>", group->getName() ) ); int result = KMessageBox::warningContinueCancel( this, message, i18nc( "dialog title", "Group Removal" ), KGuiItem( i18nc( "dialog button", "Remove" ), "edit-delete" ), KStandardGuiItem::cancel(), QString(), KMessageBox::Dangerous ); if(result == KMessageBox::Continue) { msnNotificationConnection_->removeGroup(groupId); } } // Show a "Rename group" dialog void KMess::showRenameGroupDialog( QString groupId ) { Group *group = currentAccount_->getContactList()->getGroupById(groupId); // If the group was found if ( group == 0 ) { kDebug() << "Couldn't find a matching group."; return; } // If the group is not a special group... if( group->isSpecialGroup() ) { // Show a message that it can't be deleted KMessageBox::error( 0, i18n("This is a special group, which cannot be changed.") ); return; } else { bool okPressed = false; // Otherwise, get the new group name.. const QString& currentName( group->getName() ); // Launch a dialog to get a new group name const QString& newGroupName( KInputDialog::getText(i18n( "Rename Group" ), i18n( "Enter a new name for this group:" ), currentName, &okPressed, this ) ); if( okPressed && currentName != newGroupName ) { // Request that the group be renamed msnNotificationConnection_->renameGroup(groupId, newGroupName); } } } // Show the chat history dialog and, if requested, that of a specific contact void KMess::showChatHistory( const QString &handle ) { ChatHistoryDialog *dialog = new ChatHistoryDialog( this ); dialog->setContact( handle ); dialog->show(); } // Opens the transfer manager void KMess::showTransferWindow() { TransferWindow *transferWindow = TransferWindow::getInstance(); transferWindow->show(); } // Autologin with the first account that has autologin enabled // This method is also called when restoring the session void KMess::checkAutologin(QString handle) { Account *loginAccount = 0; // If no handle was given, find the default account to connect with. if ( handle.isEmpty() ) { #ifdef KMESSDEBUG_KMESS kDebug() << "No handle was given, find an account that uses autologin."; #endif const QList<Account*> accountsList = AccountsManager::instance()->getAccounts(); foreach( Account *account, accountsList ) { // We are searching for a saved account with the autologin flag on if( account->isGuestAccount() || ! account->getUseAutologin() ) { continue; } loginAccount = account; break; } } else { #ifdef KMESSDEBUG_KMESS kDebug() << "finding account: " << handle << "."; #endif loginAccount = AccountsManager::instance()->getAccountByHandle(handle); } bool doAutoLogin = ( loginAccount != 0 ); // Wait for the user password if needed AccountsManager::instance()->readPasswords( doAutoLogin ); if( doAutoLogin ) { if( loginAccount->getPassword().isEmpty() ) { KMessageBox::error( this, i18nc( "dialog text", "<p>Cannot login automatically with account <b>%1</b>:<br/>" "you must first save the account password!</p>", loginAccount->getHandle() ), i18nc( "dialog title", "Autologin Failed" ) ); return; } // Set the login info in the initial view and connect // Using the reconnect() method here instead of startConnecting() // so KMess waits until the network is back up. // Also connect immediately if possible. initialView_->reconnect( loginAccount->getHandle(), true ); // FIXME for 2.1: when using --autologin, don't display ".. to reconnect" but "to connect". } } // A connection has been made with the notification server. void KMess::connected() { // Enable/disable the menus enableMenus( true ); // Set up the toggle and view mode tools to match the account settings showAllowedAction_ ->setChecked( currentAccount_->getShowAllowedContacts() ); showOfflineAction_ ->setChecked( currentAccount_->getShowOfflineContacts() ); showRemovedAction_ ->setChecked( currentAccount_->getShowRemovedContacts() ); showEmptyAction_ ->setChecked( currentAccount_->getShowEmptyGroups () ); showHistoryBoxAction_->setChecked( currentAccount_->getShowHistoryBox () ); // Set the pictures mode int newMode = 0; switch( currentAccount_->getListPictureSize() ) { case 0: break; case 32: newMode = 1; break; case 40: newMode = 2; break; case 48: newMode = 3; break; default: break; } listPictureSize_->setCurrentItem( newMode ); // Set the list's groups and contacts display mode viewMode_->setCurrentItem( currentAccount_->getContactListDisplayMode() ); // Check the 'Show search bar' option if the user has left it open the last login showSearchAction_->setChecked( currentAccount_->getShowSearchBar() ); // Show the connected message statusMessage( i18n("Connected"), false ); // The connection was successful, this means the supplied // email and password were correct: save the settings now if( ! currentAccount_->getSavePassword() ) { // we reset the password here if it shouldn't be saved (so accountsmanager removes it) #ifdef KMESSDEBUG_KMESS kDebug() << "Resetting password in currentAccount because it shouldn't be saved."; #endif currentAccount_->setPassword( "" ); } saveProperties(); // Notify ChatMaster we're connected chatMaster_->connected(); // Enable showing the settings for this account now that we are connected showSettingsAction_->setEnabled( true ); // Load and show the contact list switchViewToContactList(); // Set the caption setCaptionToUser(); // Show the status bar (if it's enabled) now that we're connected showStatusBar(); } // Connect to the server with the given account void KMess::connectWithAccount(Account *account) { if(KMESS_NULL(account)) return; #ifdef KMESSDEBUG_KMESS kDebug() << "Connecting account:" << account->getHandle(); #endif startConnection( account ); } // Connect to the server with the given account, possibly temporary or new. void KMess::connectWithAccount(QString handle, QString password, bool rememberAccount, bool rememberPassword, bool autologin, Status initialStatus ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Connecting with handle " << handle; #endif // Try to find an existing account Account *account = AccountsManager::instance()->getAccountByHandle(handle); if( account != 0 ) { // Found an existing account. // The user may enter a new password at the login dialog. // When the login succeeds, save the new temporary password as new account password. account->setTemporaryPassword( password ); account->setSavePassword( rememberPassword ); account->setInitialStatus( initialStatus ); if( rememberAccount && rememberPassword && autologin ) { // Mark this account as the auto-login one const QList<Account*> accountsList = AccountsManager::instance()->getAccounts(); foreach( Account *accountItem, accountsList ) { // We are searching for a saved account with the autologin flag on if( accountItem->getUseAutologin() ) { accountItem->setUseAutologin( false ); } } account->setUseAutologin( true ); } startConnection( account ); return; } // No account found, create a new account. account = new Account(); account->setLoginInformation( handle, handle, QString() ); account->setTemporaryPassword( password ); account->setGuestAccount( ! rememberAccount ); account->setSavePassword( rememberPassword ); account->setInitialStatus( initialStatus ); AccountsManager::instance()->addAccount( account ); if( rememberAccount && rememberPassword && autologin ) { // Mark this account as the auto-login one const QList<Account*> accountsList = AccountsManager::instance()->getAccounts(); foreach( Account *accountItem, accountsList ) { // We are searching for a saved account with the autologin flag on if( accountItem->getUseAutologin() ) { accountItem->setUseAutologin( false ); } } account->setUseAutologin( true ); } // Connect it startConnection( account ); } // The user wants to reconnect void KMess::reconnect() { #ifdef KMESSDEBUG kDebug() << "Reconnecting"; #endif connectWithAccount( currentAccount_ ); } // Create the program's default directories in .kde/share/apps/ bool KMess::createDirectories() { #ifdef KMESSDEBUG_KMESS kDebug() << "Creating default directories."; #endif KStandardDirs *dirs = KGlobal::dirs(); QString localKdeDir; QDir appsDir, kmessDir; localKdeDir = dirs->localkdedir(); #ifdef KMESSDEBUG_KMESS kDebug() << "Local KDE dir is " << localKdeDir << "."; #endif appsDir.setPath( localKdeDir + "/share/apps" ); if ( appsDir.exists() ) { kmessDir.setPath( appsDir.absolutePath() + "/kmess" ); #ifdef KMESSDEBUG_KMESS kDebug() << "kmess dir should be at " << kmessDir.absolutePath() << "."; #endif if ( !kmessDir.exists() ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Creating kmess dir."; #endif appsDir.mkdir( kmessDir.absolutePath() ); } } #ifdef KMESSDEBUG_KMESS else { kDebug() << "" << appsDir.absolutePath() << " doesn't exist!"; } #endif #ifdef KMESSTEST KMESS_ASSERT( kmessDir.exists() ); #endif return true; } // "Add new account" has been selected from the menu. void KMess::createNewAccount() { AccountsManager::instance()->showAccountSettings(); } // Delete the given account from the UI void KMess::slotAccountDeleted( Account *account ) { AccountAction *accountAction; if( KMESS_NULL(account) ) return; // Remove it from the initial screen's list if( initialView_ ) { initialView_->deleteAccount( account ); } // Remove from connect menu. accountAction = connectMenuItems_[ account ]; if( ! KMESS_NULL(accountAction) ) { connectActionMenu_->removeAction( accountAction ); delete connectMenuItems_.take( account ); } } // The user was presented the "contact added user" dialog and has made a choice void KMess::slotContactAddedUserDialogChoice( const QString &handle, const QStringList &groupIds, const int code ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Contact" << handle << "added user, who has choosen option:" << code << "Group list:" << groupIds; #endif switch( (ContactAddedUserDialog::ReturnCode) code ) { case ContactAddedUserDialog::ADD: // Add the contact to the allowed and friends lists msnNotificationConnection_->addNewContact( handle, groupIds ); break; case ContactAddedUserDialog::ALLOW: // Add the contact to the allowed list msnNotificationConnection_->allowContact( handle ); break; case ContactAddedUserDialog::BLOCK: // Add the contact to the blocked list. msnNotificationConnection_->blockContact( handle ); break; } } /** * @brief Update the UI when the network connection status changes * * This method receives KDE's Solid network connection status changes, and updates the view's widgets * to reflect it. * * @param newStatus The new status of the network connection */ 01053 void KMess::slotConnectionStatusChanged( Solid::Networking::Status newStatus ) { #ifdef KMESSDEBUG_KMESSINTERFACE kDebug() << "Solid status changed to " << newStatus; #endif // If Solid is unable to retrieve the status, assume we're connected bool isNetConnected = ( newStatus == Solid::Networking::Connected || newStatus == Solid::Networking::Unknown ); // Do not disable the connection menu if we're connected already if( isConnected() ) { // Do update the status message if the network is down if( newStatus == Solid::Networking::Unconnected ) { // TODO: this slightly interferes with the "Pings lost..." message, and doesn't recover directly if solid indicates so. statusMessage( i18n("Connection could be down..."), false ); } return; } // Update the menu connectActionMenu_->setEnabled( isNetConnected ); } // Disconnect was selected from the menu. void KMess::disconnectClicked() { #ifdef KMESSTEST KMESS_ASSERT( msnNotificationConnection_ != 0 ); #endif #ifdef KMESSDEBUG_KMESSINTERFACE kDebug() << "Disconnecting."; #endif msnNotificationConnection_->closeConnection(); } // The program is not connected (initially) or no longer connected (after a disconnect) to the notification server. void KMess::disconnected() { #ifdef KMESSTEST KMESS_ASSERT( chatMaster_ != 0 ); #endif #ifdef KMESSDEBUG_KMESS kDebug() << "Disconnected."; #endif // this method is also called when initializing the GUI, avoid mangling the settings at that point. if( initialized_ ) { // ContactList is saved by the MsnNotificationConnection already. // A nice alternative would be currentAccount_->disconnected() saving the list, // however CurrentAccount has a const reference to the list // because MsnNotificationConnection maintains the list instead. // Save the account. If it is not found, it's the initial disconnect call. Account *account = AccountsManager::instance()->getAccountByHandle( currentAccount_->getHandle() ); if( account ) { if( account->isDeleted() ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Account" << account->getHandle() << "was deleted, removing menu items."; #endif slotAccountDeleted( account ); } else { #ifdef KMESSDEBUG_KMESS kDebug() << "Saving the CurrentAccount."; #endif // Transfer account settings account->copyAccount( currentAccount_ ); } } } // Update the GUI disconnect_->setEnabled( false ); enableMenus(false); statusMessage( i18nc( "Status bar message", "Disconnected"), true ); showSearchAction_->setChecked( false ); showSettingsAction_->setEnabled( false ); // Hide the status bar now that we're not connected if( showStatusBar_->isChecked() ) { statusBar()->hide(); } // Inform the chat master that we're disconnected chatMaster_->disconnected(); // Update the current account currentAccount_->setStatus( STATUS_OFFLINE ); currentAccount_->setAutoreply( false ); #ifdef KMESSDEBUG_KMESS kDebug() << "Swap views."; #endif // Show the screen where to insert login details to log back in switchViewToInitialScreen(); #ifdef KMESSDEBUG_KMESS kDebug() << "Blank the caption."; #endif // Set the caption setCaption( QString::null ); } // Initialize the class bool KMess::initialize() { if ( initialized_ ) { kDebug() << "Already initialized."; return false; } #ifdef KMESSDEBUG_KMESS kDebug() << "initializing main class."; #endif // Initialize the Rich Text parser engine RichTextParser::initialize(); // Create current account instance currentAccount_ = CurrentAccount::instance(); if ( currentAccount_ == 0 ) { kDebug() << "Couldn't get a pointer to the instance of the current account."; return false; } if ( !KMessInterface::initialize() ) { kDebug() << "Couldn't initialize ancestor."; return false; } if ( !initMsnNotificationConnection() ) { kDebug() << "Couldn't initialize the MsnNotificationConnection class."; return false; } if ( !initIdleTimer() ) { kDebug() << "Couldn't initialize the IdleTimer class."; return false; } if ( !initChatMaster() ) { kDebug() << "Couldn't initialize the Chat master."; return false; } if ( !initNotifications() ) { kDebug() << "Couldn't initialize the notifications."; return false; } if ( !initNowListening() ) { kDebug() << "Couldn't initialize the now listening support."; return false; } if ( !initEmoticonManager() ) { kDebug() << "Couldn't initialize the emoticon manager."; return false; } if ( !initProxy() ) { kDebug() << "Couldn't initialize the proxy support."; return false; } if ( !createDirectories() ) { kDebug() << "Couldn't create local KDE directories."; return false; } // Use Solid to find out whether we're connected or not, and disable the Connect menu if we are not connect( Solid::Networking::notifier(), SIGNAL( statusChanged(Solid::Networking::Status) ), this, SLOT ( slotConnectionStatusChanged(Solid::Networking::Status) ) ); slotConnectionStatusChanged( Solid::Networking::status() ); // Connect current account signals for Now Listening connect( currentAccount_, SIGNAL( accountInvisible() ), this, SLOT ( changedNowListeningSettings() )); connect( currentAccount_, SIGNAL( accountOffline() ), this, SLOT ( changedNowListeningSettings() )); connect( currentAccount_, SIGNAL( accountOnline() ), this, SLOT ( changedNowListeningSettings() )); // Connect current account connect( currentAccount_, SIGNAL( changedFriendlyName() ), this, SLOT ( setCaptionToUser() )); connect( currentAccount_, SIGNAL( changedNowListeningSettings() ), this, SLOT ( changedNowListeningSettings() )); connect( currentAccount_, SIGNAL( changedStatus() ), this, SLOT ( changedStatus() )); connect( currentAccount_, SIGNAL( changedMsnObject() ), msnNotificationConnection_, SLOT( changedMsnObject() )); connect( currentAccount_, SIGNAL( changedEmoticonSettings() ), EmoticonManager::instance(),SLOT(slotChangedEmoticonSettings() ) ); // Connect the account management signals AccountsManager *accountsManager = AccountsManager::instance(); connect( accountsManager, SIGNAL( accountAdded(Account*) ), this, SLOT ( slotAccountAdded(Account*) ) ); connect( accountsManager, SIGNAL( accountChanged(Account*,QString,QString) ), this, SLOT ( slotAccountChanged(Account*,QString,QString) ) ); connect( accountsManager, SIGNAL( accountDeleted(Account*) ), this, SLOT ( slotAccountDeleted(Account*) ) ); // Fill up the account lists in the UI const QList<Account*> list( accountsManager->getAccounts() ); foreach( Account *account, list ) { slotAccountAdded( account ); } // Connect the action to show the connected account settings connect( showSettingsAction_, SIGNAL( triggered(bool) ), this, SLOT ( showSettingsForCurrentAccount() ) ); // Read the accounts and properties readProperties(); // Start disconnected. // Added debug here because this has a potential to cause problems.. // It would be better if each class got things right from it's construtor or initialize method. #ifdef KMESSDEBUG_KMESS kDebug() << "faking disconnect signal."; #endif disconnected(); // Setting up DBus dbus_ = new KMessDBus( this ); // All done, mark as initialized #ifdef KMESSDEBUG_KMESS kDebug() << "main class is initialized."; #endif initialized_ = true; return true; } // Initialize the chat master bool KMess::initChatMaster() { #ifdef KMESSTEST KMESS_ASSERT( chatMaster_ == 0 ); #endif if ( msnNotificationConnection_ == 0 ) { kDebug() << "The notification connection must be initialized before the chat master."; return false; } chatMaster_ = new ChatMaster( this ); if ( chatMaster_ == 0 ) { kDebug() << "Couldn't create the chat master."; return false; } if ( !chatMaster_->initialize() ) { kDebug() << "Couldn't initialize the chat master."; return false; } // Make the chat master's connections connect( chatMaster_, SIGNAL( requestSwitchboard(QString,ChatInformation::ConnectionType) ), msnNotificationConnection_, SLOT ( requestSwitchboard(QString,ChatInformation::ConnectionType) )); connect( chatMaster_, SIGNAL( blockContact(QString) ), msnNotificationConnection_, SLOT ( blockContact(QString) ) ); connect( chatMaster_, SIGNAL( unblockContact(QString) ), msnNotificationConnection_, SLOT ( unblockContact(QString) ) ); connect( chatMaster_, SIGNAL( addContact(QString) ), msnNotificationConnection_, SLOT ( addNewContact(QString) ) ); connect( chatMaster_, SIGNAL( removeContact(QString,bool) ), msnNotificationConnection_, SLOT ( removeContact(QString,bool) ) ); connect( chatMaster_, SIGNAL( allowContact(QString) ), msnNotificationConnection_, SLOT ( allowContact(QString) ) ); connect( msnNotificationConnection_, SIGNAL( startSwitchboard(const ChatInformation&) ), chatMaster_, SLOT ( startSwitchboard(const ChatInformation&) ) ); connect( msnNotificationConnection_, SIGNAL( offlineMessage(const ChatMessage&) ), chatMaster_, SLOT ( showSpecialMessage(const ChatMessage&) )); connect( msnNotificationConnection_, SIGNAL( pingSent() ), chatMaster_, SLOT ( timedUpdate() )); connect( chatMaster_, SIGNAL( reconnect() ), this, SLOT ( reconnect() )); #ifdef KMESSTEST KMESS_ASSERT( chatMaster_ != 0 ); #endif return true; } // Initialize the emoticon manager bool KMess::initEmoticonManager() { if ( msnNotificationConnection_ == 0 ) { kDebug() << "MsnNotificationConnection must be initialized before EmoticonManager"; return false; } EmoticonManager *manager = EmoticonManager::instance(); connect( msnNotificationConnection_, SIGNAL( connected() ), manager, SLOT ( connected() ) ); connect( msnNotificationConnection_, SIGNAL( disconnected() ), manager, SLOT ( disconnected() ) ); return true; } // Initialize the idle timer bool KMess::initIdleTimer() { #ifdef KMESSTEST KMESS_ASSERT( idleTimer_ == 0 ); #endif idleTimer_ = new IdleTimer(); if ( idleTimer_ == 0 ) { kDebug() << "Couldn't create the idle timer."; return false; } // Connect the timer to signal when the user is away. connect( idleTimer_, SIGNAL( timeout() ), this, SLOT ( userIsIdle() ) ); connect( idleTimer_, SIGNAL( activity() ), this, SLOT ( userIsNotIdle() ) ); #ifdef KMESSTEST KMESS_ASSERT( idleTimer_ != 0 ); #endif return true; } // Initialize the MSN notification connection bool KMess::initMsnNotificationConnection() { bool initialized; msnNotificationConnection_ = new MsnNotificationConnection(); initialized = msnNotificationConnection_->initialize(); if ( !initialized ) { kDebug() << "Couldn't initialize MsnNotificationConnection."; return false; } // Connect the signals connect( msnNotificationConnection_, SIGNAL( connected() ), // Connected to msn this, SLOT ( connected() ) ); connect( msnNotificationConnection_, SIGNAL( disconnected() ), // Disconnected from msn this, SLOT ( disconnected() ) ); connect( msnNotificationConnection_, SIGNAL( contactAddedUser(const QString) ), // Contact added user this, SLOT ( showContactAddedUserDialog(const QString) ) ); connect( msnNotificationConnection_, SIGNAL( statusMessage(QString,bool) ), // Display a status message this, SLOT ( statusMessage(QString,bool) ) ); return true; } // Initialize notification objects bool KMess::initNotifications() { #ifdef KMESSTEST KMESS_ASSERT( currentAccount_ != 0 ); KMESS_ASSERT( systemTrayWidget_ != 0 ); KMESS_ASSERT( msnNotificationConnection_ != 0 ); KMESS_ASSERT( chatNotification_ == 0 ); KMESS_ASSERT( contactStatusNotification_ == 0 ); KMESS_ASSERT( newEmailNotification_ == 0 ); #endif const ContactList *contactList; if ( systemTrayWidget_ == 0 ) { kDebug() << "The system tray widget must be initialized before the notifications!"; return false; } if ( msnNotificationConnection_ == 0 ) { kDebug() << "The notification connection must be initialized before the notifications!"; return false; } // Add check whether the 'eventsrc' file can be found. // The warning is a bit obtruisive, but should help to user to fix the problem. if( KGlobal::dirs()->findResource( "data", "kmess/kmess.notifyrc" ).isNull() ) { QString dirs( KGlobal::dirs()->findDirs( "data", QString() ).join("/kmess<br>") ); if( ! dirs.isEmpty() ) { dirs = "<br>" + dirs + "/kmess"; dirs = dirs.replace( "//kmess", "/kmess" ); // possibly added by /kmess suffix. dirs = i18nc( "Paragraph to be added to the text of a message dialog box, but only when KDE gives a list of " "folders where to search for an application file", "<p>KMess has searched for it in the following folders:<br>%1</p>", dirs ); } // Always show warning at the console. kWarning() << "Sounds and notifications will not be available, the file 'kmess/kmess.notifyrc' could not be found."; // Show the message in the GUI as well. // Allow to user to choose "don't show this message again", in case he/she doesn't know how to fix it. KMessageBox::information( this, i18nc( "Text for a message dialog box; %1 is an explanation about the list of folders " "where the file was searched for, which is only shown if any folders are found", "<html><p>KMess will not be able to play sounds nor show notifications.</p>" "<p>The required file 'kmess.notifyrc' could not be found in any application folder.</p>" "%1" "<p>Please verify your installation.</p>" "</html>", dirs ), i18nc( "Message box title", "Error With Notifications" ), "eventsrcNotFound" ); } contactList = currentAccount_->getContactList(); notificationManager_ = NotificationManager::instance(); notificationManager_->setTrayObject( systemTrayWidget_ ); // Create the notifiers chatNotification_ = new ChatNotification ( notificationManager_ ); contactStatusNotification_ = new ContactStatusNotification( notificationManager_ ); newEmailNotification_ = new NewEmailNotification ( notificationManager_ ); // Connect the chat messages notification signals connect( chatMaster_, SIGNAL( newChatMessage(const ChatMessage&, Chat*) ), chatNotification_, SLOT ( notify(const ChatMessage&, Chat*) ) ); connect( chatNotification_, SIGNAL( raiseChat(Chat*,bool) ), chatMaster_, SLOT ( raiseChat(Chat*,bool) ) ); // Connect the status change notification signals connect( contactList, SIGNAL( contactOnline(Contact*,bool) ), contactStatusNotification_, SLOT ( notify(Contact*,bool) ) ); connect( contactList, SIGNAL( contactOffline(Contact*,bool) ), contactStatusNotification_, SLOT ( notify(Contact*,bool) ) ); connect( contactList, SIGNAL( contactChangedStatus(Contact*,bool) ), contactStatusNotification_, SLOT ( notify(Contact*,bool) ) ); // Connect the "Email notification" signals connect( msnNotificationConnection_, SIGNAL( newEmail(QString, QString, bool, QString, QString, QString) ), newEmailNotification_, SLOT ( notify(QString, QString, bool, QString, QString, QString) ) ); // Connect the "Chat request" signals connect( contactStatusNotification_, SIGNAL( startChat(QString) ), chatMaster_, SLOT ( requestChat(QString) ) ); #ifdef KMESSTEST KMESS_ASSERT( chatNotification_ != 0 ); KMESS_ASSERT( contactStatusNotification_ != 0 ); KMESS_ASSERT( newEmailNotification_ != 0 ); #endif return true; } // Initialize the now listening support. bool KMess::initNowListening() { if ( msnNotificationConnection_ == 0 ) { kDebug() << "The notification connection must be initialized before the now listening support!"; return false; } // Create and connect client. nowListeningClient_ = new NowListeningClient(); connect( nowListeningClient_, SIGNAL( changedSong( const QString&, const QString&, const QString&, bool ) ), this, SLOT ( changedSong( const QString&, const QString&, const QString&, bool ) )); return true; } // Initialize the proxy support. bool KMess::initProxy() { // NOTE: Due to the fact that KDE proxy settings do not have a signal to notify proxy // config changes, KMess will need to be restarted if the user changes them. // No proxy, done already! if( ! KProtocolManager::useProxy() ) { #ifdef KMESSDEBUG_KMESS kDebug() << "No proxy support is needed (kde's proxy is turned off)."; #endif return true; } QString proxyAddress( KProtocolManager::proxyForUrl( KUrl( "https://www.kmess.org/" ) ) ); // No need to use the proxy for HTTPS traffic if( proxyAddress.isEmpty() || proxyAddress == "DIRECT" ) { #ifdef KMESSDEBUG_KMESS kDebug() << "No proxy support is needed (no proxy is needed for HTTPS traffic)."; #endif return true; } #ifdef KMESSDEBUG_KMESS kDebug() << "Proxy URL:" << proxyAddress; #endif KUrl proxyUrl( proxyAddress ); QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy; // Configure the proxy if( proxyUrl.protocol() == "socks" ) { proxyType = QNetworkProxy::Socks5Proxy; } else { proxyType = QNetworkProxy::HttpProxy; } // Set the default proxy for the whole application QNetworkProxy appProxy( proxyType, proxyUrl.host(), (quint16) proxyUrl.port(), proxyUrl.user(), proxyUrl.pass() ); QNetworkProxy::setApplicationProxy( appProxy ); return true; } // Check if the connection to the server is active bool KMess::isConnected() { if( KMESS_NULL(msnNotificationConnection_) ) { return false; } return msnNotificationConnection_->isConnected(); } // Load the application's global state void KMess::readGlobalProperties( KConfig *sessionConfig ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Loading current state..."; #endif KConfigGroup settings( sessionConfig->group( "state" ) ); // If the list window was visible, show it again setVisible( settings.readEntry( "isVisible", false ) ); // If an account was connected, try connecting it again QString connectedAccount( settings.readEntry( "connectedAccount", QString() ) ); // Delete the setting, if needed it'll be added again on session close settings.deleteEntry( "connectedAccount" ); checkAutologin( connectedAccount ); } // Save the application's global state void KMess::saveGlobalProperties( KConfig *sessionConfig ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Saving current state..."; #endif KConfigGroup settings( sessionConfig->group( "state" ) ); QString connectedAccount; if( isConnected() ) { connectedAccount = currentAccount_->getHandle(); } settings.writeEntry( "isVisible", isVisible() ); settings.writeEntry( "connectedAccount", connectedAccount ); } // Read in account and other properties void KMess::readProperties( const KConfigGroup &config ) { #ifdef KMESSDEBUG_KMESS kDebug() << "Reading properties"; #endif KConfigGroup group; // Choose the config group if it was not given if( &config == 0 ) { group = KMessConfig::instance()->getGlobalConfig( "General" ); } else { group = config; } KMessInterface::readProperties( group ); } // Save account and other properties void KMess::saveProperties( KConfigGroup &config ) { KConfigGroup group; // Choose the config group if it was not given if( &config == 0 ) { group = KMessConfig::instance()->getGlobalConfig( "General" ); } else { group = config; } // Save the UI configuration KMessInterface::saveProperties( group ); #ifdef KMESSDEBUG_KMESS kDebug() << "saving properties"; #endif // Have all the accounts save their properties const QList<Account*> accountsList = AccountsManager::instance()->getAccounts(); foreach( Account *account, accountsList ) { // Avoid saving guest accounts if( account->isGuestAccount() || account->isDeleted() ) { continue; } // If the account is the current account... if ( account->getHandle() == currentAccount_->getHandle() ) { // Move the settings from the current account to the account #ifdef KMESSDEBUG_KMESS kDebug() << "copying settings from CurrentAccount to the Account object."; #endif account->copyAccount( currentAccount_ ); } // Save properties of accounts account->saveProperties(); } // Save the accounts' passwords (blocking, or KMess may quit before it's done) AccountsManager::instance()->savePasswords( true ); // Write data now! group.sync(); } // Set the caption void KMess::setCaptionToUser() { // On start, use the default caption if( currentAccount_ == 0 ) { setCaption( QString() ); return; } // Get the friendly name, but avoid newlines which cause problems to the titlebar layout QString friendlyName( currentAccount_->getFriendlyName().replace( "\n", " " ) ); // Set a standard caption if there is no friendly name yet (ie. first connection) if( friendlyName.isEmpty() ) { setCaption( QString() ); return; } // Set the caption setPlainCaption( i18nc( "Main window caption: switched order to easily distinguish it from chats", "KMess - %1", friendlyName ) ); } // Show the settings dialog for a given account void KMess::showSettingsForAccount( Account *account ) { AccountsManager::instance()->showAccountSettings( account ); } // Show the settings dialog for the current account. void KMess::showSettingsForCurrentAccount() { // Use the Account object so it's consistent with the other AccountAction events. Account *accountData = AccountsManager::instance()->getAccountByHandle( CurrentAccount::instance()->getHandle() ); if( KMESS_NULL(accountData) ) return; showSettingsForAccount( accountData ); } // Show the user's MSN profile. void KMess::showUserProfile() { if( currentAccount_ == 0 ) { return; } const QString url( currentAccount_->getUrlInformation().value( "PROFILE" ) ); KMessShared::openBrowser( KUrl( url ) ); } // Initiate a connection to the server. Use connectWithAccount() to connect, not this method. void KMess::startConnection( Account *account ) { if( KMESS_NULL(account) ) return; // First disconnect, to unregister all contacts if( msnNotificationConnection_->isConnected() ) { msnNotificationConnection_->closeConnection(); } // Update the initial view with account details and start the connection if everything is ok if( ! initialView_->startConnecting( account->getHandle(), false /* emitConnectionSignal */ ) ) { show(); return; } // Update the main view's controls to match this account's details. changedStatus( account ); // Copy the account to the current account #ifdef KMESSDEBUG_KMESS kDebug() << "copying data of account" << account->getHandle() << "to the CurrentAccount object."; #endif currentAccount_->copyAccount( account ); // Allow users to cancel the login attempt disconnect_->setEnabled( true ); // Set UI state of any open chat tabs to "Connecting" chatMaster_->connecting(); // Connect to the server msnNotificationConnection_->openConnection(); } // Switch the view to the contact list void KMess::switchViewToContactList() { // Clean up views beforehand. // Whatever was the previous centralWidget will be deleted below. We mark // any objects that still exist here, for deletion, and set them to zero. // See also ::switchViewToInitialScreen if( view_ ) { view_->deleteLater(); view_ = 0; } if( initialView_ ) { initialView_->deleteLater(); initialView_ = 0; } #ifdef KMESSTEST KMESS_ASSERT( msnNotificationConnection_ != 0 ); #endif // Create and initialize the view's widgets view_ = new KMessView( this ); view_->initialize( msnNotificationConnection_->getContactListModel() ); // Connect other signals to msnNotificationConnection connect( msnNotificationConnection_, SIGNAL( disconnected() ), // The connection was closed view_, SLOT (slotDisconnected() ) ); connect( view_, SIGNAL( addContact(QString) ), // Add a contact msnNotificationConnection_, SLOT (addExistingContact(QString) ) ); connect( view_, SIGNAL( allowContact(QString) ), // Allow the contact msnNotificationConnection_, SLOT ( allowContact(QString) ) ); connect( view_, SIGNAL( blockContact(QString) ), // Block the contact msnNotificationConnection_, SLOT ( blockContact(QString) ) ); connect( view_, SIGNAL( changeFriendlyName(QString) ), // Change the friendly name msnNotificationConnection_, SLOT ( changeFriendlyName(QString) ) ); connect( view_, SIGNAL( changePersonalMessage(QString) ), // Change the personal message. msnNotificationConnection_, SLOT ( changePersonalMessage(QString) ) ); connect( view_, SIGNAL( copyContact(QString, QString) ), msnNotificationConnection_, SLOT ( addContactToGroup(QString, QString) ) ); connect( view_, SIGNAL( moveContact(QString, QString, QString) ), // Move the contact msnNotificationConnection_, SLOT ( moveContact(QString, QString, QString) ) ); connect( view_, SIGNAL( showSettings() ), // Show settings this, SLOT ( showSettingsForCurrentAccount() ) ); connect( view_, SIGNAL(requestChat( QString ) ), // Start a chat chatMaster_, SLOT (requestChat( QString ) ) ); connect( view_, SIGNAL( removeContact(QString) ), // Remove the contact this, SLOT ( showRemoveContactDialog(QString) ) ); connect( view_, SIGNAL( removeContactFromGroup(QString, QString) ), msnNotificationConnection_, SLOT ( removeContactFromGroup(QString, QString) ) ); connect( view_, SIGNAL( removeGroup(QString) ), // Remove the group this, SLOT ( showRemoveGroupDialog(QString) ) ); connect( view_, SIGNAL( renameGroup(QString) ), // Rename the group this, SLOT ( showRenameGroupDialog(QString) ) ); connect( view_, SIGNAL( selectionChanged(const QItemSelection&) ), // The selection has changed this, SLOT (updateContextMenu(const QItemSelection&) ) ); connect( view_, SIGNAL( unblockContact(QString) ), // Unblock the contact msnNotificationConnection_, SLOT ( unblockContact(QString) ) ); // this is horrible. i'm glad CurrentAccount is gone in 2.1! Account *realAccount = AccountsManager::instance()->getAccountByHandle( currentAccount_->getHandle() ); connect( realAccount, SIGNAL( changedEmoticonSettings() ), view_, SLOT( slotUpdateUserStatus() ) ); // Set it as the application's main widget setCentralWidget( view_ ); } // Switch the view to the initial login screen void KMess::switchViewToInitialScreen() { // Just use the same initialView_ if it's already there if( initialView_ ) { initialView_->reset(); return; } // Clean up view_ if it exists if( view_ ) { view_->deleteLater(); view_ = 0; } // Create and set up the new widget initialView_ = new InitialView( this ); // Connect it so it triggers the login process connect( initialView_, SIGNAL( connectWithAccount(QString,QString,bool,bool,bool,Status) ), this, SLOT ( connectWithAccount(QString,QString,bool,bool,bool,Status) ) ); connect( initialView_, SIGNAL( disconnectClicked() ), this, SLOT ( disconnectClicked() ) ); // Show settings connect( initialView_, SIGNAL( showSettings(Account*) ), this, SLOT ( showSettingsForAccount(Account*) ) ); connect( msnNotificationConnection_, SIGNAL( reconnect(QString) ), initialView_, SLOT ( reconnect(QString) ) ); connect( msnNotificationConnection_, SIGNAL( statusMessage(QString,bool) ), initialView_, SLOT ( statusMessage(QString) ) ); // Set it as the window's main widget setCentralWidget( initialView_ ); } // The "show allowed contacts" menu item has been toggled. void KMess::toggleShowAllowed(bool show) { currentAccount_->setShowAllowedContacts( show ); } // The "show empty groups" menu item has been toggled. void KMess::toggleShowEmpty( bool show ) { currentAccount_->setShowEmptyGroups( show ); } // The "show history box" menu item has been toggled. void KMess::toggleShowHistoryBox(bool show) { if( view_ != 0 ) { view_->toggleShowHistoryBox( show ); } } // The "show search in contact list" menu item has been toggled. void KMess::toggleShowSearchFrame(bool show) { if( view_ != 0 ) { view_->toggleShowSearchFrame( show ); } } // The "show offline contacts" menu item has been toggled. void KMess::toggleShowOffline(bool show) { currentAccount_->setShowOfflineContacts( show ); } // The "show removed contacts" menu item has been toggled. void KMess::toggleShowRemoved(bool show) { currentAccount_->setShowRemovedContacts( show ); } // Show the context-sensitive menu item void KMess::updateContextMenu( const QItemSelection &selection ) { contextMenuAction_->setEnabled( ! selection.indexes().isEmpty() ); } // The user has gone idle void KMess::userIsIdle() { #ifdef KMESSDEBUG_IDLETIMER kDebug(); #endif if ( ( currentAccount_ != 0 ) && ( msnNotificationConnection_ != 0 ) ) { #ifdef KMESSDEBUG_IDLETIMER kDebug() << "Current status is " << currentAccount_->getStatus() << "."; #endif // Only change the state if the user is currently set as online if ( currentAccount_->getStatus() == STATUS_ONLINE ) { #ifdef KMESSDEBUG_IDLETIMER kDebug() << "Change status to Idle."; #endif // Request a status change to Idle msnNotificationConnection_->changeStatus( STATUS_IDLE ); isIdleForced_ = false; } } } // The user is no longer idle void KMess::userIsNotIdle() { #ifdef KMESSDEBUG_IDLETIMER kDebug(); #endif if ( ( currentAccount_ != 0 ) && ( msnNotificationConnection_ != 0 ) ) { #ifdef KMESSDEBUG_IDLETIMER kDebug() << "User is no longer idle, current status is " << currentAccount_->getStatus(); #endif // Only change the state if the user is currently set as idle AND the idle status was not forced by the user if ( currentAccount_->getStatus() == STATUS_IDLE && ! isIdleForced_ ) { #ifdef KMESSDEBUG_IDLETIMER kDebug() << "Change status to Online"; #endif // Request a status change to Online msnNotificationConnection_->changeStatus( STATUS_ONLINE ); } } #ifdef KMESSDEBUG_IDLETIMER kDebug() << "Done userIsNotIdle()."; #endif } // return NS Connection // HACK: Remove after 2.0-final. MsnNotificationConnection *KMess::getNsConnection() { return msnNotificationConnection_; } #include "kmess.moc"