1 | /* |
2 | kopetewindow.cpp - Kopete Main Window |
3 | |
4 | Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org> |
5 | Copyright (c) 2001-2002 by Stefan Gehn <metz AT gehn.net> |
6 | Copyright (c) 2002-2003 by Martijn Klingens <klingens@kde.org> |
7 | Copyright (c) 2002-2009 by Olivier Goffart <ogoffart at kde.org> |
8 | Copyright (c) 2005-2006 by Will Stephenson <wstephenson@kde.org> |
9 | Copyright (c) 2008 by Roman Jarosz <kedgedev@centrum.cz> |
10 | |
11 | Kopete (c) 2002-2008 by the Kopete developers <kopete-devel@kde.org> |
12 | |
13 | ************************************************************************* |
14 | * * |
15 | * This program is free software; you can redistribute it and/or modify * |
16 | * it under the terms of the GNU General Public License as published by * |
17 | * the Free Software Foundation; either version 2 of the License, or * |
18 | * (at your option) any later version. * |
19 | * * |
20 | ************************************************************************* |
21 | */ |
22 | |
23 | #include "kopetewindow.h" |
24 | |
25 | #include <QCursor> |
26 | #include <QLayout> |
27 | |
28 | #include <QTimer> |
29 | #include <QPixmap> |
30 | #include <QCloseEvent> |
31 | #include <QMouseEvent> |
32 | #include <QEvent> |
33 | #include <QLabel> |
34 | #include <QShowEvent> |
35 | #include <QLineEdit> |
36 | #include <QSignalMapper> |
37 | #include <QTextEdit> |
38 | |
39 | #include <khbox.h> |
40 | #include <kvbox.h> |
41 | #include <kaction.h> |
42 | #include <kactionmenu.h> |
43 | #include <kactioncollection.h> |
44 | #include <ktoggleaction.h> |
45 | #include <kconfig.h> |
46 | #include <kdebug.h> |
47 | #include <kglobalaccel.h> |
48 | #include <klocale.h> |
49 | #include <kicon.h> |
50 | #include <kiconloader.h> |
51 | #include <kmessagebox.h> |
52 | #include <knotifyconfigwidget.h> |
53 | #include <kmenu.h> |
54 | #include <kshortcutsdialog.h> |
55 | #include <kedittoolbar.h> |
56 | #include <kmenubar.h> |
57 | #include <kstatusbar.h> |
58 | #include <kwindowsystem.h> |
59 | #include <kdeversion.h> |
60 | #include <kinputdialog.h> |
61 | #include <kplugininfo.h> |
62 | #include <ksqueezedtextlabel.h> |
63 | #include <kstringhandler.h> |
64 | #include <kurl.h> |
65 | #include <kxmlguifactory.h> |
66 | #include <ktoolbar.h> |
67 | #include <kdialog.h> |
68 | #include <kstandardaction.h> |
69 | #include <solid/networking.h> |
70 | #include <kstatusbarofflineindicator.h> |
71 | #include <kfilterproxysearchline.h> |
72 | |
73 | #include "addcontactpage.h" |
74 | #include "addressbooklinkwidget.h" |
75 | #include "ui_groupkabcselectorwidget.h" |
76 | #include "kabcexport.h" |
77 | #include "kopeteappearancesettings.h" |
78 | #include "kopeteapplication.h" |
79 | #include "kopeteaccount.h" |
80 | #include "kopeteaccountmanager.h" |
81 | #include "kopeteaccountstatusbaricon.h" |
82 | #include "kopeteidentitystatusbaricon.h" |
83 | #include "kopetebehaviorsettings.h" |
84 | #include "kopetecontact.h" |
85 | #include "kopetecontactlist.h" |
86 | #include "kopetegroup.h" |
87 | #include "kopeteidentity.h" |
88 | #include "kopeteidentitymanager.h" |
89 | #include "kopetelistviewsearchline.h" |
90 | #include "kopetechatsessionmanager.h" |
91 | #include "kopetepluginmanager.h" |
92 | #include "kopeteprotocol.h" |
93 | #include "kopetestdaction.h" |
94 | #include "kopeteuiglobal.h" |
95 | #include "systemtray.h" |
96 | #include "kopeteonlinestatusmanager.h" |
97 | #include "identitystatuswidget.h" |
98 | #include "kopetestatusmanager.h" |
99 | #include "kopetestatusrootaction.h" |
100 | #include "kopetestatuseditaction.h" |
101 | #include "kopeteemoticons.h" |
102 | #include "kopeteinfoeventmanager.h" |
103 | #include "infoeventwidget.h" |
104 | #include "contactlisttreemodel.h" |
105 | #include "contactlistplainmodel.h" |
106 | #include "contactlistproxymodel.h" |
107 | #include "kopeteitemdelegate.h" |
108 | #include "kopetemetacontact.h" |
109 | #include "kopetecontactlistview.h" |
110 | #include "kopetestatusitems.h" |
111 | |
112 | |
113 | //BEGIN GlobalStatusMessageIconLabel |
114 | GlobalStatusMessageIconLabel::GlobalStatusMessageIconLabel ( QWidget *parent ) |
115 | : QLabel ( parent ) |
116 | { |
117 | setCursor ( QCursor ( Qt::PointingHandCursor ) ); |
118 | setFixedSize ( 16, 16 ); |
119 | setPixmap ( SmallIcon ( "im-status-message-edit" ) ); |
120 | setToolTip ( i18n ( "Global status message" ) ); |
121 | } |
122 | |
123 | void GlobalStatusMessageIconLabel::mouseReleaseEvent ( QMouseEvent *event ) |
124 | { |
125 | if ( event->button() == Qt::LeftButton || event->button() == Qt::RightButton ) |
126 | { |
127 | emit iconClicked ( event->globalPos() ); |
128 | event->accept(); |
129 | } |
130 | } |
131 | //END GlobalStatusMessageIconLabel |
132 | |
133 | //BEGIN InfoEventIconLabel |
134 | InfoEventIconLabel::InfoEventIconLabel( QWidget *parent ) |
135 | : QLabel( parent ) |
136 | { |
137 | setCursor( QCursor( Qt::PointingHandCursor ) ); |
138 | setFixedSize( 16, 16 ); |
139 | setPixmap( SmallIcon( "flag-black" ) ); |
140 | setToolTip( i18n( "Service messages" ) ); |
141 | |
142 | connect( Kopete::InfoEventManager::self(), SIGNAL(changed()), this, SLOT(updateIcon()) ); |
143 | } |
144 | |
145 | void InfoEventIconLabel::mouseReleaseEvent( QMouseEvent *event ) |
146 | { |
147 | if ( event->button() == Qt::LeftButton || event->button() == Qt::RightButton ) |
148 | { |
149 | emit clicked(); |
150 | event->accept(); |
151 | } |
152 | } |
153 | |
154 | void InfoEventIconLabel::updateIcon() |
155 | { |
156 | if ( Kopete::InfoEventManager::self()->eventCount() > 0 ) |
157 | setPixmap( SmallIcon( "flag-green" ) ); |
158 | else { |
159 | setPixmap( SmallIcon( "flag-black" ) ); |
160 | emit clicked(); |
161 | } |
162 | } |
163 | //END InfoEventIconLabel |
164 | |
165 | class KopeteWindow::Private |
166 | { |
167 | public: |
168 | Private() |
169 | : contactlist ( 0 ), model(0), proxyModel(0), identitywidget ( 0 ), infoEventWidget ( 0 ), actionAddContact ( 0 ), actionDisconnect ( 0 ), |
170 | actionExportContacts ( 0 ), actionStatusMenu ( 0 ), actionDockMenu ( 0 ), actionSetAway ( 0 ), |
171 | actionSetBusy ( 0 ), actionSetAvailable ( 0 ), actionSetInvisible ( 0 ), actionPrefs ( 0 ), |
172 | actionQuit ( 0 ), actionSave ( 0 ), menubarAction ( 0 ), statusbarAction ( 0 ), |
173 | actionShowOfflineUsers ( 0 ), actionShowEmptyGroups ( 0 ), docked ( 0 ), deskRight ( 0 ), |
174 | statusBarWidget ( 0 ), tray ( 0 ), hidden ( false ), autoHide ( false ), |
175 | autoHideTimeout ( 0 ), autoHideTimer ( 0 ), addContactMapper ( 0 ), |
176 | showIdentityIcons( Kopete::AppearanceSettings::self()->showIdentityIcons() ), |
177 | globalStatusMessage ( 0 ) |
178 | {} |
179 | |
180 | ~Private() |
181 | {} |
182 | |
183 | KopeteContactListView *contactlist; |
184 | Kopete::UI::ContactListModel* model; |
185 | Kopete::UI::ContactListProxyModel* proxyModel; |
186 | |
187 | IdentityStatusWidget *identitywidget; |
188 | InfoEventWidget *infoEventWidget; |
189 | |
190 | // Some Actions |
191 | KActionMenu *actionAddContact; |
192 | |
193 | KAction *actionDisconnect; |
194 | KAction *actionExportContacts; |
195 | |
196 | KActionMenu *; |
197 | KActionMenu *; |
198 | KAction *actionSetAway; |
199 | KAction *actionSetBusy; |
200 | KAction *actionSetAvailable; |
201 | KAction *actionSetInvisible; |
202 | |
203 | |
204 | KAction *actionPrefs; |
205 | KAction *actionQuit; |
206 | KAction *actionSave; |
207 | KToggleAction *; |
208 | KToggleAction *statusbarAction; |
209 | KToggleAction *actionShowAllOfflineEmpty; |
210 | KToggleAction *actionShowOfflineUsers; |
211 | KToggleAction *actionShowEmptyGroups; |
212 | |
213 | int docked; |
214 | int deskRight; |
215 | QPoint position; |
216 | KHBox *statusBarWidget; |
217 | KopeteSystemTray *tray; |
218 | bool appDestroyed; |
219 | bool hidden; |
220 | bool autoHide; |
221 | unsigned int autoHideTimeout; |
222 | QTimer *autoHideTimer; |
223 | QTimer *autoResizeTimer; |
224 | QSignalMapper *addContactMapper; |
225 | |
226 | bool showIdentityIcons; |
227 | QHash<const Kopete::Identity*, KopeteIdentityStatusBarIcon*> identityStatusBarIcons; |
228 | QHash<const Kopete::Account*, KopeteAccountStatusBarIcon*> accountStatusBarIcons; |
229 | KSqueezedTextLabel *globalStatusMessage; |
230 | }; |
231 | |
232 | /* KMainWindow is very broken from our point of view - it deref()'s the app |
233 | * when the last visible KMainWindow is destroyed. But when our main window is |
234 | * hidden when it's in the tray,closing the last chatwindow would cause the app |
235 | * to quit. - Richard |
236 | * |
237 | * Fortunately KMainWindow checks queryExit before deref()ing the Kapplication. |
238 | * KopeteWindow reimplements queryExit() and only returns true if it is shutting down |
239 | * (either because the user quit Kopete, or the session manager did). |
240 | * |
241 | * KopeteWindow and ChatWindows are closed by session management. |
242 | * App shutdown is not performed by the KopeteWindow but by KopeteApplication: |
243 | * 1) user quit - KopeteWindow::slotQuit() was called, calls KopeteApplication::quitKopete(), |
244 | * which closes all chatwindows and the KopeteWindow. The last window to close |
245 | * shuts down the PluginManager in queryExit(). When the PluginManager has completed its |
246 | * shutdown, the app is finally deref()ed, and the contact list and accountmanager |
247 | * are saved. |
248 | * and calling KApplication::quit() |
249 | * 2) session - KopeteWindow and all chatwindows are closed by KApplication session management. |
250 | * quit Then the shutdown proceeds as above. |
251 | * |
252 | * queryClose() is honoured so groupchats and chats receiving recent messages can interrupt |
253 | * (session) quit. |
254 | */ |
255 | |
256 | KopeteWindow::KopeteWindow ( QWidget *parent ) |
257 | : KXmlGuiWindow ( parent ), d ( new Private ) |
258 | { |
259 | d->appDestroyed = false; |
260 | connect ( kapp, SIGNAL (destroyed()), this, SLOT (slotAppDestroyed()) ); |
261 | setAttribute ( Qt::WA_DeleteOnClose, false ); |
262 | setAttribute ( Qt::WA_QuitOnClose, false ); |
263 | // Applications should ensure that their StatusBar exists before calling createGUI() |
264 | // so that the StatusBar is always correctly positioned when KDE is configured to use |
265 | // a MacOS-style MenuBar. |
266 | // This fixes a "statusbar drawn over the top of the toolbar" bug |
267 | // e.g. it can happen when you switch desktops on Kopete startup |
268 | d->statusBarWidget = new KHBox ( statusBar() ); |
269 | d->statusBarWidget->setMargin ( 2 ); |
270 | d->statusBarWidget->setSpacing ( 1 ); |
271 | window()->setAttribute( Qt::WA_AlwaysShowToolTips ); |
272 | statusBar()->addPermanentWidget ( d->statusBarWidget, 0 ); |
273 | QWidget *statusBarMessage = new QWidget ( statusBar() ); |
274 | QHBoxLayout *statusBarMessageLayout = new QHBoxLayout ( statusBarMessage ); |
275 | statusBarMessageLayout->setMargin ( 2 ); |
276 | |
277 | KStatusBarOfflineIndicator * indicator = new KStatusBarOfflineIndicator ( this ); |
278 | statusBar()->addPermanentWidget ( indicator, 0 ); |
279 | |
280 | GlobalStatusMessageIconLabel *label = new GlobalStatusMessageIconLabel ( statusBarMessage ); |
281 | connect ( label, SIGNAL (iconClicked(QPoint)), |
282 | this, SLOT (slotGlobalStatusMessageIconClicked(QPoint)) ); |
283 | statusBarMessageLayout->addWidget ( label ); |
284 | statusBarMessageLayout->addSpacing ( 1 ); |
285 | |
286 | InfoEventIconLabel *infoLabel = new InfoEventIconLabel ( statusBarMessage ); |
287 | connect ( infoLabel, SIGNAL(clicked()), this, SLOT(slotInfoIconClicked()) ); |
288 | statusBarMessageLayout->addWidget ( infoLabel ); |
289 | statusBarMessageLayout->addSpacing ( 1 ); |
290 | connect( Kopete::InfoEventManager::self(), SIGNAL(eventAdded(Kopete::InfoEvent*)), this, SLOT(slotNewInfoEvent()) ); |
291 | |
292 | d->globalStatusMessage = new KSqueezedTextLabel ( statusBarMessage ); |
293 | connect ( Kopete::StatusManager::self(), SIGNAL (globalStatusChanged()), |
294 | this, SLOT (globalStatusChanged()) ); |
295 | statusBarMessageLayout->addWidget ( d->globalStatusMessage ); |
296 | statusBar()->addWidget ( statusBarMessage, 1 ); |
297 | |
298 | d->autoHideTimer = new QTimer ( this ); |
299 | d->autoResizeTimer = new QTimer ( this ); |
300 | d->autoResizeTimer->setSingleShot ( true ); |
301 | |
302 | // -------------------------------------------------------------------------------- |
303 | initView(); |
304 | initActions(); |
305 | d->contactlist->initActions ( actionCollection() ); |
306 | initSystray(); |
307 | // -------------------------------------------------------------------------------- |
308 | |
309 | // Trap all loaded plugins, so we can add their status bar icons accordingly , also used to add XMLGUIClient |
310 | connect ( Kopete::PluginManager::self(), SIGNAL (pluginLoaded(Kopete::Plugin*)), |
311 | this, SLOT (slotPluginLoaded(Kopete::Plugin*)) ); |
312 | connect ( Kopete::PluginManager::self(), SIGNAL (allPluginsLoaded()), |
313 | this, SLOT (slotAllPluginsLoaded()) ); |
314 | |
315 | // Connect all identity signals |
316 | connect ( Kopete::IdentityManager::self(), SIGNAL (identityRegistered(Kopete::Identity*)), |
317 | this, SLOT (slotIdentityRegistered(Kopete::Identity*)) ); |
318 | connect ( Kopete::IdentityManager::self(), SIGNAL (identityUnregistered(const Kopete::Identity*)), |
319 | this, SLOT (slotIdentityUnregistered(const Kopete::Identity*)) ); |
320 | |
321 | connect ( d->autoHideTimer, SIGNAL (timeout()), this, SLOT (slotAutoHide()) ); |
322 | connect ( d->contactlist, SIGNAL(visibleContentHeightChanged()), this, SLOT (slotStartAutoResizeTimer()) ); |
323 | connect ( d->autoResizeTimer, SIGNAL (timeout()), this, SLOT (slotUpdateSize()) ); |
324 | connect ( Kopete::AppearanceSettings::self(), SIGNAL (contactListAppearanceChanged()), |
325 | this, SLOT (slotContactListAppearanceChanged()) ); |
326 | createGUI ( QLatin1String ( "kopeteui.rc" ) ); |
327 | |
328 | // call this _after_ createGUI(), otherwise menubar is not set up correctly |
329 | loadOptions(); |
330 | |
331 | // If some plugins are already loaded, merge the GUI |
332 | Kopete::PluginList plugins = Kopete::PluginManager::self()->loadedPlugins(); |
333 | foreach ( Kopete::Plugin *plug, plugins ) |
334 | slotPluginLoaded ( plug ); |
335 | |
336 | // If some identity already registered, build the status icon |
337 | Kopete::Identity::List identityList = Kopete::IdentityManager::self()->identities(); |
338 | foreach ( Kopete::Identity *i, identityList ) |
339 | slotIdentityRegistered ( i ); |
340 | |
341 | //install an event filter for the quick search toolbar so we can |
342 | //catch the hide events |
343 | toolBar ( "quickSearchBar" )->installEventFilter ( this ); |
344 | } |
345 | |
346 | void KopeteWindow::slotAppDestroyed() |
347 | { |
348 | d->appDestroyed = true; |
349 | } |
350 | |
351 | void KopeteWindow::initView() |
352 | { |
353 | QWidget *w = new QWidget ( this ); |
354 | QVBoxLayout *l = new QVBoxLayout ( w ); |
355 | d->contactlist = new KopeteContactListView ( w ); |
356 | |
357 | if ( Kopete::AppearanceSettings::self()->groupContactByGroup() ) |
358 | d->model = new Kopete::UI::ContactListTreeModel( this ); |
359 | else |
360 | d->model = new Kopete::UI::ContactListPlainModel( this ); |
361 | |
362 | d->model->init(); |
363 | d->proxyModel = new Kopete::UI::ContactListProxyModel( this ); |
364 | d->proxyModel->setSourceModel( d->model ); |
365 | d->contactlist->setModel( d->proxyModel ); |
366 | l->addWidget ( d->contactlist ); |
367 | l->setSpacing ( 0 ); |
368 | l->setContentsMargins ( 0,0,0,0 ); |
369 | d->identitywidget = new IdentityStatusWidget ( 0, w ); |
370 | d->identitywidget->setSizePolicy ( QSizePolicy ( QSizePolicy::Preferred, QSizePolicy::Minimum ) ); |
371 | d->identitywidget->setVisible ( false ); |
372 | l->addWidget ( d->identitywidget ); |
373 | d->infoEventWidget = new InfoEventWidget ( w ); |
374 | d->infoEventWidget->setSizePolicy ( QSizePolicy ( QSizePolicy::Preferred, QSizePolicy::Minimum ) ); |
375 | d->infoEventWidget->setVisible ( false ); |
376 | connect ( d->infoEventWidget, SIGNAL(showRequest()), this, SLOT(slotShowInfoEventWidget()) ); |
377 | l->addWidget ( d->infoEventWidget ); |
378 | |
379 | setCentralWidget ( w ); |
380 | d->contactlist->setFocus(); |
381 | } |
382 | |
383 | void KopeteWindow::initActions() |
384 | { |
385 | // this action menu contains one action per account and is updated when accounts are registered/unregistered |
386 | d->actionAddContact = new KActionMenu ( KIcon ( "list-add-user" ), i18n ( "&Add Contact" ), this ); |
387 | d->actionAddContact->setIconText ( i18n ( "Add" ) ); |
388 | actionCollection()->addAction ( "AddContact" , d->actionAddContact ); |
389 | d->actionAddContact->setDelayed ( false ); |
390 | // this signal mapper is needed to call slotAddContact with the correct arguments |
391 | d->addContactMapper = new QSignalMapper ( this ); |
392 | connect ( d->addContactMapper, SIGNAL (mapped(QString)), |
393 | this, SLOT (slotAddContactDialogInternal(QString)) ); |
394 | |
395 | d->actionDisconnect = new KAction ( KIcon ( "user-offline" ), i18n ( "Offline" ), this ); |
396 | actionCollection()->addAction ( "DisconnectAll" , d->actionDisconnect ); |
397 | connect ( d->actionDisconnect, SIGNAL (triggered(bool)), this, SLOT (slotDisconnectAll()) ); |
398 | d->actionDisconnect->setEnabled ( false ); |
399 | |
400 | d->actionExportContacts = new KAction ( i18n ( "&Export Contacts..." ), this ); |
401 | d->actionExportContacts->setIcon ( KIcon ( "document-export" ) ); |
402 | actionCollection()->addAction ( "ExportContacts" , d->actionExportContacts ); |
403 | connect ( d->actionExportContacts, SIGNAL (triggered(bool)), this, SLOT (showExportDialog()) ); |
404 | |
405 | d->actionSetAway = new KAction ( KIcon ( "user-identity" , 0, QStringList() << QString() << "user-away" ), i18n ( "&Away" ), this ); |
406 | actionCollection()->addAction ( "SetAwayAll" , d->actionSetAway ); |
407 | connect ( d->actionSetAway, SIGNAL (triggered(bool)), this, SLOT (slotGlobalAway()) ); |
408 | |
409 | d->actionSetBusy = new KAction ( KIcon ( "user-identity" , 0, QStringList() << QString() << "user-busy" ), i18n ( "&Busy" ), this ); |
410 | actionCollection()->addAction ( "SetBusyAll" , d->actionSetBusy ); |
411 | connect ( d->actionSetBusy, SIGNAL (triggered(bool)), this, SLOT (slotGlobalBusy()) ); |
412 | |
413 | |
414 | d->actionSetInvisible = new KAction ( KIcon ( "user-identity" , 0, QStringList() << QString() << "user-invisible" ), i18n ( "&Invisible" ), this ); |
415 | actionCollection()->addAction ( "SetInvisibleAll" , d->actionSetInvisible ); |
416 | connect ( d->actionSetInvisible, SIGNAL (triggered(bool)), this, SLOT (slotSetInvisibleAll()) ); |
417 | |
418 | d->actionSetAvailable = new KAction ( KIcon ( "user-identity" , 0, QStringList() << QString() << "user-online" ), i18n ( "&Online" ), this ); |
419 | actionCollection()->addAction ( "SetAvailableAll" , d->actionSetAvailable ); |
420 | connect ( d->actionSetAvailable, SIGNAL (triggered(bool)), this, SLOT (slotGlobalAvailable()) ); |
421 | |
422 | d->actionStatusMenu = new KActionMenu ( KIcon ( "user-identity" , 0, QStringList() << QString() << "user-online" ), i18n ( "&Set Status" ), this ); |
423 | d->actionStatusMenu->setIconText ( i18n ( "Status" ) ); |
424 | actionCollection()->addAction ( "Status" , d->actionStatusMenu ); |
425 | d->actionStatusMenu->setDelayed ( false ); |
426 | |
427 | // Will be automatically deleted when the actionStatusMenu is deleted. |
428 | Kopete::StatusRootAction* statusAction = new Kopete::StatusRootAction ( d->actionStatusMenu ); |
429 | |
430 | connect ( statusAction, SIGNAL (changeStatus(uint,Kopete::StatusMessage)), |
431 | this, SLOT (setOnlineStatus(uint,Kopete::StatusMessage)) ); |
432 | connect ( statusAction, SIGNAL (updateMessage(Kopete::StatusRootAction*)), |
433 | this, SLOT (updateStatusMenuMessage(Kopete::StatusRootAction*)) ); |
434 | connect ( statusAction, SIGNAL (changeMessage(Kopete::StatusMessage)), |
435 | this, SLOT (setStatusMessage(Kopete::StatusMessage)) ); |
436 | |
437 | d->actionPrefs = KopeteStdAction::preferences ( actionCollection(), "settings_prefs" ); |
438 | |
439 | KStandardAction::quit ( this, SLOT (slotQuit()), actionCollection() ); |
440 | |
441 | setStandardToolBarMenuEnabled ( true ); |
442 | d->menubarAction = KStandardAction::showMenubar ( menuBar(), SLOT (setVisible(bool)), actionCollection() ); |
443 | actionCollection()->addAction ( "settings_showmenubar" , d->menubarAction ); |
444 | d->statusbarAction = KStandardAction::showStatusbar ( statusBar(), SLOT (setVisible(bool)), actionCollection() ); |
445 | actionCollection()->addAction ( "settings_showstatusbar" , d->statusbarAction ); |
446 | |
447 | KAction* act = KStandardAction::keyBindings ( guiFactory(), SLOT (configureShortcuts()), actionCollection() ); |
448 | actionCollection()->addAction ( "settings_keys" , act ); |
449 | |
450 | KAction *configureGlobalShortcutsAction = new KAction ( KIcon ( "configure-shortcuts" ), i18n ( "Configure &Global Shortcuts..." ), this ); |
451 | configureGlobalShortcutsAction->setMenuRole( QAction::NoRole ); //OS X: prevent Qt heuristics to move action to app menu->"Preferences" |
452 | actionCollection()->addAction ( "settings_global" , configureGlobalShortcutsAction ); |
453 | connect ( configureGlobalShortcutsAction, SIGNAL (triggered(bool)), this, SLOT (slotConfGlobalKeys()) ); |
454 | |
455 | KStandardAction::configureToolbars ( this, SLOT (slotConfToolbar()), actionCollection() ); |
456 | act = KStandardAction::configureNotifications ( this, SLOT (slotConfNotifications()), actionCollection() ); |
457 | actionCollection()->addAction ( "settings_notifications" , act ); |
458 | |
459 | d->actionShowAllOfflineEmpty = new KToggleAction ( KIcon ( "view-user-offline-kopete" ), i18n ( "Show &All" ), this ); |
460 | actionCollection()->addAction ( "settings_show_all_offline_empty" , d->actionShowAllOfflineEmpty ); |
461 | d->actionShowAllOfflineEmpty->setShortcut ( KShortcut ( Qt::CTRL + Qt::Key_U ) ); |
462 | connect ( d->actionShowAllOfflineEmpty, SIGNAL (triggered(bool)), this, SLOT (slotToggleShowAllOfflineEmpty(bool)) ); |
463 | |
464 | d->actionShowOfflineUsers = new KToggleAction ( KIcon ( "view-user-offline-kopete" ), i18n ( "Show Offline &Users" ), this ); |
465 | actionCollection()->addAction ( "settings_show_offliners" , d->actionShowOfflineUsers ); |
466 | connect ( d->actionShowOfflineUsers, SIGNAL (triggered(bool)), this, SLOT (slotToggleShowOfflineUsers()) ); |
467 | |
468 | d->actionShowEmptyGroups = new KToggleAction ( KIcon ( "folder-grey" ), i18n ( "Show Empty &Groups" ), this ); |
469 | actionCollection()->addAction ( "settings_show_empty_groups" , d->actionShowEmptyGroups ); |
470 | d->actionShowEmptyGroups->setShortcut ( KShortcut ( Qt::CTRL + Qt::Key_G ) ); |
471 | connect ( d->actionShowEmptyGroups, SIGNAL (triggered(bool)), this, SLOT (slotToggleShowEmptyGroups()) ); |
472 | |
473 | /* The following are highly misleading together with the checkbox, consider removing them - ahartmetz |
474 | d->actionShowAllOfflineEmpty->setCheckedState ( KGuiItem ( i18n ( "Hide O&ffline" ) ) ); |
475 | d->actionShowOfflineUsers->setCheckedState ( KGuiItem ( i18n ( "Hide Offline &Users" ) ) ); |
476 | d->actionShowEmptyGroups->setCheckedState ( KGuiItem ( i18n ( "Hide Empty &Groups" ) ) ); |
477 | */ |
478 | |
479 | KFilterProxySearchLine* searchLine = new KFilterProxySearchLine ( this ); |
480 | searchLine->setProxy( d->proxyModel ); |
481 | KAction *quickSearch = new KAction ( i18n ( "Quick Search Bar" ), this ); |
482 | actionCollection()->addAction ( "quicksearch_bar" , quickSearch ); |
483 | quickSearch->setDefaultWidget ( searchLine ); |
484 | |
485 | // sync actions, config and prefs-dialog |
486 | connect ( Kopete::AppearanceSettings::self(), SIGNAL (configChanged()), this, SLOT (slotConfigChanged()) ); |
487 | slotConfigChanged(); |
488 | |
489 | // Global actions |
490 | KAction *globalReadMessage = new KAction ( i18n ( "Read Message" ), this ); |
491 | actionCollection()->addAction ( "ReadMessage" , globalReadMessage ); |
492 | connect ( globalReadMessage, SIGNAL (triggered(bool)), Kopete::ChatSessionManager::self(), SLOT (slotReadMessage()) ); |
493 | globalReadMessage->setGlobalShortcut ( KShortcut ( Qt::CTRL + Qt::SHIFT + Qt::Key_I ) ); |
494 | globalReadMessage->setWhatsThis ( i18n ( "Read the next pending message" ) ); |
495 | |
496 | KAction *globalShowContactList = new KAction ( i18n ( "Show/Hide Contact List" ), this ); |
497 | actionCollection()->addAction ( "ShowContactList" , globalShowContactList ); |
498 | connect ( globalShowContactList, SIGNAL (triggered(bool)), this, SLOT (slotShowHide()) ); |
499 | globalShowContactList->setGlobalShortcut ( KShortcut ( Qt::CTRL + Qt::ALT + Qt::Key_T ) ); |
500 | globalShowContactList->setWhatsThis ( i18n ( "Show or hide the contact list" ) ); |
501 | |
502 | KAction *globalSetAway = new KAction ( i18n ( "Set Away/Back" ), this ); |
503 | actionCollection()->addAction ( "Set_Away_Back" , globalSetAway ); |
504 | connect ( globalSetAway, SIGNAL (triggered(bool)), this, SLOT (slotToggleAway()) ); |
505 | globalSetAway->setGlobalShortcut ( KShortcut ( Qt::CTRL + Qt::SHIFT + Qt::Key_W ) ); |
506 | } |
507 | |
508 | void KopeteWindow::slotShowHide() |
509 | { |
510 | if ( isActiveWindow() ) |
511 | { |
512 | d->autoHideTimer->stop(); //no timeouts if active |
513 | hide(); |
514 | } |
515 | else |
516 | { |
517 | show(); |
518 | #ifdef Q_WS_X11 |
519 | if ( !KWindowSystem::windowInfo ( winId(),NET::WMDesktop ).onAllDesktops() ) |
520 | KWindowSystem::setOnDesktop ( winId(), KWindowSystem::currentDesktop() ); |
521 | #endif |
522 | raise(); |
523 | KWindowSystem::forceActiveWindow( winId() ); |
524 | } |
525 | } |
526 | |
527 | void KopeteWindow::slotToggleAway() |
528 | { |
529 | kDebug ( 14000 ); |
530 | Kopete::StatusManager * statusManager = Kopete::StatusManager::self(); |
531 | const Kopete::Status::StatusItem * item = 0; |
532 | bool away = Kopete::StatusManager::self()->globalAway(); |
533 | |
534 | foreach (const Kopete::Status::StatusItem *i, statusManager->getRootGroup()->childList()) { |
535 | if (i->title() == QLatin1String("Online" ) && away ) { |
536 | item = i; |
537 | break; |
538 | } else if (i->title() == QLatin1String("Away" ) && !away) { |
539 | item = i; |
540 | break; |
541 | } |
542 | } |
543 | |
544 | const Kopete::Status::Status * status = qobject_cast<const Kopete::Status::Status*>(item); |
545 | if (status) { |
546 | statusManager->setGlobalStatusMessage(Kopete::StatusMessage(status->title(), status->message())); |
547 | } |
548 | |
549 | if ( away ) |
550 | slotGlobalAvailable(); |
551 | else |
552 | slotGlobalAway(); |
553 | } |
554 | |
555 | void KopeteWindow::initSystray() |
556 | { |
557 | if ( Kopete::BehaviorSettings::self()->showSystemTray() ) { |
558 | d->tray = KopeteSystemTray::systemTray ( this ); |
559 | |
560 | QObject::connect ( d->tray, SIGNAL (aboutToShowMenu(KMenu*)), |
561 | this, SLOT (slotTrayAboutToShowMenu(KMenu*)) ); |
562 | // :FIXME: The signal quitSelected does not exist on KopeteSystemTray |
563 | // QObject::connect ( d->tray, SIGNAL (quitSelected()), this, SLOT (slotQuit()) ); |
564 | } |
565 | } |
566 | |
567 | KopeteWindow::~KopeteWindow() |
568 | { |
569 | delete d; |
570 | } |
571 | |
572 | bool KopeteWindow::eventFilter ( QObject* target, QEvent* event ) |
573 | { |
574 | KToolBar *toolBar = dynamic_cast<KToolBar*> ( target ); |
575 | QAction *resetAction = actionCollection()->action ( "quicksearch_reset" ); |
576 | |
577 | if ( toolBar && resetAction && resetAction->associatedWidgets().contains ( toolBar ) ) |
578 | { |
579 | |
580 | if ( event->type() == QEvent::Hide ) |
581 | { |
582 | resetAction->trigger(); |
583 | return true; |
584 | } |
585 | return KXmlGuiWindow::eventFilter ( target, event ); |
586 | } |
587 | |
588 | return KXmlGuiWindow::eventFilter ( target, event ); |
589 | } |
590 | |
591 | void KopeteWindow::loadOptions() |
592 | { |
593 | KSharedConfig::Ptr config = KGlobal::config(); |
594 | |
595 | toolBar ( "mainToolBar" )->applySettings ( config->group ( "ToolBar Settings" ) ); |
596 | toolBar ( "quickSearchBar" )->applySettings ( config->group ( "QuickSearchBar Settings" ) ); |
597 | |
598 | applyMainWindowSettings ( config->group ( "General Options" ) ); |
599 | KConfigGroup cg ( config, "General Options" ); |
600 | QPoint pos = cg.readEntry ( "Position" , QPoint(-1, -1) ); |
601 | if ( pos.x() != -1 || pos.y() != -1 ) |
602 | move ( pos ); |
603 | |
604 | QSize size = cg.readEntry ( "Geometry" , QSize() ); |
605 | if ( size.isEmpty() ) // Default size |
606 | resize ( QSize ( 272, 400 ) ); |
607 | else |
608 | resize ( size ); |
609 | |
610 | d->autoHide = Kopete::AppearanceSettings::self()->contactListAutoHide(); |
611 | d->autoHideTimeout = Kopete::AppearanceSettings::self()->contactListAutoHideTimeout(); |
612 | |
613 | |
614 | QString tmp = cg.readEntry ( "WindowState" , "Shown" ); |
615 | if ( tmp == "Minimized" && Kopete::BehaviorSettings::self()->showSystemTray() ) |
616 | { |
617 | showMinimized(); |
618 | } |
619 | else if ( tmp == "Hidden" && Kopete::BehaviorSettings::self()->showSystemTray() ) |
620 | { |
621 | hide(); |
622 | } |
623 | else if ( !Kopete::BehaviorSettings::self()->startDocked() || !Kopete::BehaviorSettings::self()->showSystemTray() ) |
624 | show(); |
625 | |
626 | d->menubarAction->setChecked ( !menuBar()->isHidden() ); |
627 | d->statusbarAction->setChecked ( !statusBar()->isHidden() ); |
628 | } |
629 | |
630 | void KopeteWindow::saveOptions() |
631 | { |
632 | KConfigGroup mainToolbarGroup ( KGlobal::config(), "ToolBar Settings" ); |
633 | toolBar ( "mainToolBar" )->saveSettings ( mainToolbarGroup ); |
634 | KConfigGroup qsbGroup ( KGlobal::config(), "QuickSearchBar Settings" ); |
635 | toolBar ( "quickSearchBar" )->saveSettings ( qsbGroup ); |
636 | |
637 | KConfigGroup cg ( KGlobal::config(), "General Options" ); |
638 | saveMainWindowSettings ( cg ); |
639 | |
640 | cg.writeEntry ( "Position" , pos() ); |
641 | cg.writeEntry ( "Geometry" , size() ); |
642 | |
643 | if ( isMinimized() ) |
644 | { |
645 | cg.writeEntry ( "WindowState" , "Minimized" ); |
646 | } |
647 | else if ( isHidden() ) |
648 | { |
649 | cg.writeEntry ( "WindowState" , "Hidden" ); |
650 | } |
651 | else |
652 | { |
653 | cg.writeEntry ( "WindowState" , "Shown" ); |
654 | } |
655 | |
656 | Kopete::Identity *identity = d->identitywidget->identity(); |
657 | if ( identity ) |
658 | cg.writeEntry ( "ShownIdentityId" , identity->id() ); |
659 | else |
660 | cg.writeEntry ( "ShownIdentityId" , QString() ); |
661 | |
662 | cg.sync(); |
663 | } |
664 | |
665 | void KopeteWindow::slotToggleShowAllOfflineEmpty ( bool toggled ) |
666 | { |
667 | d->actionShowOfflineUsers->setChecked ( toggled ); |
668 | d->actionShowEmptyGroups->setChecked ( toggled ); |
669 | Kopete::AppearanceSettings::self()->setShowOfflineUsers ( toggled ); |
670 | Kopete::AppearanceSettings::self()->setShowEmptyGroups ( toggled ); |
671 | Kopete::AppearanceSettings::self()->writeConfig(); |
672 | } |
673 | |
674 | void KopeteWindow::slotToggleShowOfflineUsers() |
675 | { |
676 | Kopete::AppearanceSettings::self()->setShowOfflineUsers ( d->actionShowOfflineUsers->isChecked() ); |
677 | Kopete::AppearanceSettings::self()->writeConfig(); |
678 | } |
679 | |
680 | void KopeteWindow::slotToggleShowEmptyGroups() |
681 | { |
682 | Kopete::AppearanceSettings::self()->setShowEmptyGroups ( d->actionShowEmptyGroups->isChecked() ); |
683 | Kopete::AppearanceSettings::self()->writeConfig(); |
684 | } |
685 | |
686 | static bool compareOnlineStatus(const Kopete::Account *a, const Kopete::Account *b); |
687 | static bool invertedCompareOnlineStatus(const Kopete::Account *a, const Kopete::Account *b); |
688 | |
689 | void KopeteWindow::slotConfigChanged() |
690 | { |
691 | bool groupContactByGroupModel = qobject_cast<Kopete::UI::ContactListTreeModel*>( d->model ); |
692 | if ( groupContactByGroupModel != Kopete::AppearanceSettings::self()->groupContactByGroup() ) |
693 | { |
694 | Kopete::UI::ContactListModel* oldModel = d->model; |
695 | if ( Kopete::AppearanceSettings::self()->groupContactByGroup() ) |
696 | d->model = new Kopete::UI::ContactListTreeModel( this ); |
697 | else |
698 | d->model = new Kopete::UI::ContactListPlainModel( this ); |
699 | |
700 | d->model->init(); |
701 | d->proxyModel->setSourceModel( d->model ); |
702 | oldModel->deleteLater(); |
703 | } |
704 | |
705 | if ( isHidden() && !Kopete::BehaviorSettings::self()->showSystemTray() ) // user disabled systray while kopete is hidden, show it! |
706 | show(); |
707 | |
708 | d->actionShowAllOfflineEmpty->setChecked ( Kopete::AppearanceSettings::self()->showOfflineUsers() && Kopete::AppearanceSettings::self()->showEmptyGroups() ); |
709 | d->actionShowOfflineUsers->setChecked ( Kopete::AppearanceSettings::self()->showOfflineUsers() ); |
710 | d->actionShowEmptyGroups->setChecked ( Kopete::AppearanceSettings::self()->showEmptyGroups() ); |
711 | |
712 | if ( d->showIdentityIcons != Kopete::AppearanceSettings::self()->showIdentityIcons() ) |
713 | { |
714 | // Delete status bar icons |
715 | if ( d->showIdentityIcons ) |
716 | { |
717 | if ( d->identitywidget->isVisible() ) |
718 | { |
719 | d->identitywidget->setIdentity( 0 ); |
720 | d->identitywidget->setVisible( false ); |
721 | } |
722 | |
723 | qDeleteAll( d->identityStatusBarIcons ); |
724 | d->identityStatusBarIcons.clear(); |
725 | } |
726 | else |
727 | { |
728 | qDeleteAll( d->accountStatusBarIcons ); |
729 | d->accountStatusBarIcons.clear(); |
730 | } |
731 | |
732 | // Add new status bar icons |
733 | d->showIdentityIcons = Kopete::AppearanceSettings::self()->showIdentityIcons(); |
734 | if ( d->showIdentityIcons ) |
735 | { |
736 | Kopete::Identity::List identityList = Kopete::IdentityManager::self()->identities(); |
737 | foreach ( Kopete::Identity *identity, identityList ) |
738 | { |
739 | KopeteIdentityStatusBarIcon *sbIcon = new KopeteIdentityStatusBarIcon ( identity, d->statusBarWidget ); |
740 | connect ( sbIcon, SIGNAL(leftClicked(Kopete::Identity*,QPoint)), this, |
741 | SLOT(slotIdentityStatusIconLeftClicked(Kopete::Identity*,QPoint)) ); |
742 | |
743 | d->identityStatusBarIcons.insert ( identity, sbIcon ); |
744 | slotIdentityStatusIconChanged ( identity ); |
745 | slotIdentityToolTipChanged ( identity ); |
746 | } |
747 | } |
748 | else |
749 | { |
750 | QList<Kopete::Account *> accountList = Kopete::AccountManager::self()->accounts(); |
751 | qSort(accountList.begin(), accountList.end(), invertedCompareOnlineStatus); |
752 | foreach ( Kopete::Account *account, accountList ) |
753 | { |
754 | KopeteAccountStatusBarIcon *sbIcon = new KopeteAccountStatusBarIcon ( account, d->statusBarWidget ); |
755 | d->accountStatusBarIcons.insert ( account, sbIcon ); |
756 | } |
757 | } |
758 | } |
759 | } |
760 | |
761 | void KopeteWindow::slotContactListAppearanceChanged() |
762 | { |
763 | d->autoHide = Kopete::AppearanceSettings::self()->contactListAutoHide(); |
764 | d->autoHideTimeout = Kopete::AppearanceSettings::self()->contactListAutoHideTimeout(); |
765 | |
766 | startAutoHideTimer(); |
767 | } |
768 | |
769 | void KopeteWindow::slotConfNotifications() |
770 | { |
771 | KNotifyConfigWidget::configure ( this ); |
772 | } |
773 | |
774 | void KopeteWindow::slotConfGlobalKeys() |
775 | { |
776 | KShortcutsDialog::configure ( actionCollection() ); |
777 | } |
778 | |
779 | void KopeteWindow::slotConfToolbar() |
780 | { |
781 | KConfigGroup cg ( KGlobal::config(), "General Options" ); |
782 | saveMainWindowSettings ( cg ); |
783 | KEditToolBar *dlg = new KEditToolBar ( factory() ); |
784 | connect ( dlg, SIGNAL (newToolBarConfig()), this, SLOT (slotUpdateToolbar()) ); |
785 | connect ( dlg, SIGNAL (finished()) , dlg, SLOT (deleteLater()) ); |
786 | dlg->show(); |
787 | } |
788 | |
789 | void KopeteWindow::slotUpdateToolbar() |
790 | { |
791 | applyMainWindowSettings ( KGlobal::config()->group ( "General Options" ) ); |
792 | } |
793 | |
794 | void KopeteWindow::slotGlobalAway() |
795 | { |
796 | Kopete::AccountManager::self()->setOnlineStatus ( Kopete::OnlineStatusManager::Away, |
797 | Kopete::StatusManager::self()->globalStatusMessage() ); |
798 | } |
799 | |
800 | void KopeteWindow::slotGlobalBusy() |
801 | { |
802 | Kopete::AccountManager::self()->setOnlineStatus ( Kopete::OnlineStatusManager::Busy, |
803 | Kopete::StatusManager::self()->globalStatusMessage() ); |
804 | } |
805 | |
806 | void KopeteWindow::slotGlobalAvailable() |
807 | { |
808 | Kopete::AccountManager::self()->setOnlineStatus ( Kopete::OnlineStatusManager::Online, |
809 | Kopete::StatusManager::self()->globalStatusMessage() ); |
810 | } |
811 | |
812 | void KopeteWindow::slotSetInvisibleAll() |
813 | { |
814 | Kopete::AccountManager::self()->setOnlineStatus ( Kopete::OnlineStatusManager::Invisible, |
815 | Kopete::StatusManager::self()->globalStatusMessage() ); |
816 | } |
817 | |
818 | void KopeteWindow::slotDisconnectAll() |
819 | { |
820 | Kopete::AccountManager::self()->setOnlineStatus ( Kopete::OnlineStatusManager::Offline, |
821 | Kopete::StatusManager::self()->globalStatusMessage() ); |
822 | } |
823 | |
824 | bool KopeteWindow::queryClose() |
825 | { |
826 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
827 | if ( app->sessionSaving() || app->isShuttingDown() ) { |
828 | // we are shutting down, don't show any message |
829 | return true; |
830 | } |
831 | |
832 | Kopete::PluginList list = Kopete::PluginManager::self()->loadedPlugins(); |
833 | foreach ( Kopete::Plugin *plugin, list ) { |
834 | bool shown = false; |
835 | QMetaObject::invokeMethod(plugin, "showCloseWindowMessage" , Qt::DirectConnection, Q_RETURN_ARG(bool, shown)); |
836 | if ( shown ) { |
837 | // A message box has just been shown. Stop now, we do not want |
838 | // to spam the user with multiple message boxes. |
839 | return true; |
840 | } |
841 | } |
842 | |
843 | if ( Kopete::BehaviorSettings::self()->showSystemTray() |
844 | && !isHidden() ) |
845 | // I would make this a KMessageBox::queuedMessageBox but there doesn't seem to be don'tShowAgain support for those |
846 | KMessageBox::information ( this, |
847 | i18n ( "<qt>Closing the main window will keep Kopete running in the " |
848 | "system tray. Use 'Quit' from the 'File' menu to quit the application.</qt>" ), |
849 | i18n ( "Docking in System Tray" ), "hideOnCloseInfo" ); |
850 | // else // we are shutting down either user initiated or session management |
851 | // Kopete::PluginManager::self()->shutdown(); |
852 | |
853 | return true; |
854 | } |
855 | |
856 | bool KopeteWindow::shouldExitOnClose() const |
857 | { |
858 | Kopete::PluginList list = Kopete::PluginManager::self()->loadedPlugins(); |
859 | foreach ( Kopete::Plugin *plugin, list ) { |
860 | bool ok = true; |
861 | QMetaObject::invokeMethod(plugin, "shouldExitOnClose" , Qt::DirectConnection, Q_RETURN_ARG(bool, ok)); |
862 | if ( !ok ) { |
863 | kDebug ( 14000 ) << "plugin" << plugin->displayName() << "does not want to exit" ; |
864 | return false; |
865 | } |
866 | } |
867 | // If all plugins are OK, consider ourself OK only if there is no tray icon |
868 | return !Kopete::BehaviorSettings::self()->showSystemTray(); |
869 | } |
870 | |
871 | bool KopeteWindow::queryExit() |
872 | { |
873 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
874 | if ( app->sessionSaving() |
875 | || app->isShuttingDown() /* only set if KopeteApplication::quitKopete() or |
876 | KopeteApplication::commitData() called */ |
877 | || shouldExitOnClose() |
878 | || isHidden() ) |
879 | { |
880 | saveOptions(); |
881 | kDebug ( 14000 ) << " shutting down plugin manager" ; |
882 | Kopete::PluginList list = Kopete::PluginManager::self()->loadedPlugins(); |
883 | foreach ( Kopete::Plugin *plugin, list ) { |
884 | guiFactory()->removeClient(plugin); |
885 | } |
886 | Kopete::PluginManager::self()->shutdown(); |
887 | return true; |
888 | } |
889 | else |
890 | return false; |
891 | } |
892 | |
893 | void KopeteWindow::closeEvent ( QCloseEvent *e ) |
894 | { |
895 | // if we are not ok to exit on close and we are not shutting down then just do what needs to be done if a |
896 | // window is closed. |
897 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
898 | if ( !shouldExitOnClose() && !app->isShuttingDown() && !app->sessionSaving() ) { |
899 | // BEGIN of code borrowed from KMainWindow::closeEvent |
900 | // Save settings if auto-save is enabled, and settings have changed |
901 | if ( settingsDirty() && autoSaveSettings() ) |
902 | saveAutoSaveSettings(); |
903 | |
904 | if ( queryClose() ) { |
905 | e->accept(); |
906 | } |
907 | // END of code borrowed from KMainWindow::closeEvent |
908 | kDebug ( 14000 ) << "just closing because we have a system tray icon" ; |
909 | } |
910 | else |
911 | { |
912 | kDebug ( 14000 ) << "delegating to KXmlGuiWindow::closeEvent()" ; |
913 | KXmlGuiWindow::closeEvent ( e ); |
914 | } |
915 | } |
916 | |
917 | void KopeteWindow::slotQuit() |
918 | { |
919 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
920 | app->quitKopete(); |
921 | |
922 | if ( d->tray && app->isShuttingDown() ) |
923 | { |
924 | d->tray->deleteLater(); |
925 | d->tray = 0; |
926 | } |
927 | } |
928 | |
929 | void KopeteWindow::slotPluginLoaded ( Kopete::Plugin * p ) |
930 | { |
931 | guiFactory()->addClient ( p ); |
932 | } |
933 | |
934 | void KopeteWindow::slotAllPluginsLoaded() |
935 | { |
936 | // actionConnect->setEnabled(true); |
937 | d->actionDisconnect->setEnabled ( true ); |
938 | |
939 | KConfigGroup cg( KGlobal::config(), "General Options" ); |
940 | |
941 | // If some account already loaded, build the status icon |
942 | QList<Kopete::Account *> accountList = Kopete::AccountManager::self()->accounts(); |
943 | qSort(accountList.begin(), accountList.end(), invertedCompareOnlineStatus); |
944 | foreach ( Kopete::Account *a, accountList ) |
945 | slotAccountRegistered ( a ); |
946 | |
947 | //Connect the appropriate account signals |
948 | /* Please note that I tried to put this in the slotAllPluginsLoaded() function |
949 | * but it seemed to break the account icons in the statusbar --Matt */ |
950 | connect ( Kopete::AccountManager::self(), SIGNAL (accountRegistered(Kopete::Account*)), |
951 | this, SLOT (slotAccountRegistered(Kopete::Account*)) ); |
952 | connect ( Kopete::AccountManager::self(), SIGNAL (accountUnregistered(const Kopete::Account*)), |
953 | this, SLOT (slotAccountUnregistered(const Kopete::Account*)) ); |
954 | |
955 | if ( d->showIdentityIcons ) |
956 | { |
957 | QString identityId = cg.readEntry( "ShownIdentityId" , Kopete::IdentityManager::self()->defaultIdentity()->id() ); |
958 | if ( !identityId.isEmpty() ) |
959 | { |
960 | Kopete::Identity* identity = Kopete::IdentityManager::self()->findIdentity( identityId ); |
961 | if ( identity ) |
962 | slotIdentityStatusIconLeftClicked( identity, QPoint() ); |
963 | } |
964 | } |
965 | } |
966 | |
967 | void KopeteWindow::slotIdentityRegistered ( Kopete::Identity *identity ) |
968 | { |
969 | if ( !identity ) |
970 | return; |
971 | |
972 | connect ( identity, SIGNAL(onlineStatusChanged(Kopete::Identity*)), |
973 | this, SLOT(slotIdentityStatusIconChanged(Kopete::Identity*)) ); |
974 | connect ( identity, SIGNAL(identityChanged(Kopete::Identity*)), |
975 | this, SLOT(slotIdentityStatusIconChanged(Kopete::Identity*)) ); |
976 | connect ( identity, SIGNAL(toolTipChanged(Kopete::Identity*)), |
977 | this, SLOT(slotIdentityToolTipChanged(Kopete::Identity*)) ); |
978 | |
979 | if ( d->showIdentityIcons ) |
980 | { |
981 | KopeteIdentityStatusBarIcon *sbIcon = new KopeteIdentityStatusBarIcon ( identity, d->statusBarWidget ); |
982 | connect ( sbIcon, SIGNAL (leftClicked(Kopete::Identity*,QPoint)), |
983 | SLOT (slotIdentityStatusIconLeftClicked(Kopete::Identity*,QPoint)) ); |
984 | |
985 | d->identityStatusBarIcons.insert ( identity, sbIcon ); |
986 | } |
987 | |
988 | slotIdentityStatusIconChanged ( identity ); |
989 | slotIdentityToolTipChanged( identity ); |
990 | } |
991 | |
992 | void KopeteWindow::slotIdentityUnregistered ( const Kopete::Identity *identity ) |
993 | { |
994 | kDebug ( 14000 ) ; |
995 | |
996 | if ( d->showIdentityIcons ) |
997 | { |
998 | KopeteIdentityStatusBarIcon *sbIcon = d->identityStatusBarIcons.value ( identity, 0 ); |
999 | if ( sbIcon ) |
1000 | { |
1001 | d->identityStatusBarIcons.remove ( identity ); |
1002 | delete sbIcon; |
1003 | } |
1004 | } |
1005 | |
1006 | makeTrayToolTip(); |
1007 | |
1008 | } |
1009 | |
1010 | void KopeteWindow::slotIdentityToolTipChanged ( Kopete::Identity *identity ) |
1011 | { |
1012 | if ( d->appDestroyed ) |
1013 | return; |
1014 | |
1015 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
1016 | if ( app->sessionSaving() || app->isShuttingDown() ) |
1017 | return; |
1018 | |
1019 | // Adds tooltip for each status icon, useful in case you have many accounts |
1020 | // over one protocol |
1021 | KopeteIdentityStatusBarIcon *i = d->identityStatusBarIcons.value ( identity, 0 ); |
1022 | if ( i ) |
1023 | i->setToolTip ( identity->toolTip() ); |
1024 | |
1025 | makeTrayToolTip(); |
1026 | } |
1027 | |
1028 | void KopeteWindow::slotIdentityStatusIconChanged ( Kopete::Identity *identity ) |
1029 | { |
1030 | kDebug ( 14000 ) << identity->property ( Kopete::Global::Properties::self()->statusMessage() ).value(); |
1031 | // update the global status label if the change doesn't |
1032 | // QString newAwayMessage = contact->property( Kopete::Global::Properties::self()->awayMessage() ).value().toString(); |
1033 | // if ( status.status() != Kopete::OnlineStatus::Connecting ) |
1034 | // { |
1035 | // QString globalMessage = m_globalStatusMessage->text(); |
1036 | // if ( newAwayMessage != globalMessage ) |
1037 | // m_globalStatusMessage->setText( ""i18n("status message to show when different accounts have different status messages", "(multiple)" ); |
1038 | // } |
1039 | // kDebug(14000) << "Icons: '" << |
1040 | // status.overlayIcons() << "'" << endl; |
1041 | |
1042 | if ( d->appDestroyed ) |
1043 | return; |
1044 | |
1045 | KopeteApplication *app = static_cast<KopeteApplication *> ( kapp ); |
1046 | if ( app->sessionSaving() || app->isShuttingDown() ) |
1047 | return; |
1048 | |
1049 | if ( identity->onlineStatus() != Kopete::OnlineStatus::Connecting ) |
1050 | { |
1051 | // FIXME: It's not global status so don't save it |
1052 | //Kopete::StatusManager::self()->setGlobalStatusMessage( identity->property( Kopete::Global::Properties::self()->statusMessage() ).value().toString() ); |
1053 | } |
1054 | |
1055 | KopeteIdentityStatusBarIcon *i = d->identityStatusBarIcons.value ( identity, 0 ); |
1056 | if ( !i ) |
1057 | return; |
1058 | |
1059 | QPixmap pm; |
1060 | switch ( identity->onlineStatus() ) { |
1061 | case Kopete::OnlineStatus::Offline: |
1062 | case Kopete::OnlineStatus::Connecting: |
1063 | pm = SmallIcon ( "user-identity" , 0, KIconLoader::DefaultState, |
1064 | QStringList() << QString() << "user-offline" ); |
1065 | break; |
1066 | case Kopete::OnlineStatus::Invisible: |
1067 | pm = SmallIcon ( "user-identity" , 0, KIconLoader::DefaultState, |
1068 | QStringList() << QString() << "user-invisible" ); |
1069 | break; |
1070 | case Kopete::OnlineStatus::Away: |
1071 | pm = SmallIcon ( "user-identity" , 0, KIconLoader::DefaultState, |
1072 | QStringList() << QString() << "user-away" ); |
1073 | break; |
1074 | case Kopete::OnlineStatus::Busy: |
1075 | pm = SmallIcon ( "user-identity" , 0, KIconLoader::DefaultState, |
1076 | QStringList() << QString() << "user-busy" ); |
1077 | break; |
1078 | case Kopete::OnlineStatus::Online: |
1079 | pm = SmallIcon ( "user-identity" , 0, KIconLoader::DefaultState, |
1080 | QStringList() << QString() << "user-online" ); |
1081 | break; |
1082 | case Kopete::OnlineStatus::Unknown: |
1083 | pm = SmallIcon ( "user-identity" ); |
1084 | break; |
1085 | } |
1086 | |
1087 | // No Pixmap found, fallback to Unknown |
1088 | if ( pm.isNull() ) |
1089 | i->setPixmap ( SmallIcon ( "user-identity" ) ); |
1090 | else |
1091 | i->setPixmap ( pm ); |
1092 | } |
1093 | |
1094 | static bool compareOnlineStatus(const Kopete::Account *a, const Kopete::Account *b) |
1095 | { |
1096 | int c = 0; |
1097 | |
1098 | if (a->identity() && b->identity()) { |
1099 | c = QString::localeAwareCompare(a->identity()->label(), b->identity()->label()); |
1100 | } |
1101 | |
1102 | if (c == 0) { |
1103 | c = a->myself()->onlineStatus().status() - b->myself()->onlineStatus().status(); |
1104 | |
1105 | if (c == 0) { |
1106 | return (QString::localeAwareCompare(a->protocol()->displayName(), b->protocol()->displayName()) < 0); |
1107 | } |
1108 | return (c > 0); |
1109 | } |
1110 | return (c < 0); |
1111 | } |
1112 | |
1113 | static bool invertedCompareOnlineStatus(const Kopete::Account *a, const Kopete::Account *b) |
1114 | { |
1115 | return !compareOnlineStatus(a, b); |
1116 | } |
1117 | |
1118 | void KopeteWindow::makeTrayToolTip() |
1119 | { |
1120 | //FIXME: maybe use identities here? |
1121 | //the tool-tip of the systemtray. |
1122 | if ( d->tray ) |
1123 | { |
1124 | QString tt = QLatin1String ( "<qt>" ); |
1125 | QList<Kopete::Account *> accountList = Kopete::AccountManager::self()->accounts(); |
1126 | qSort(accountList.begin(), accountList.end(), compareOnlineStatus); |
1127 | foreach ( Kopete::Account *a, accountList ) |
1128 | { |
1129 | Kopete::Contact *self = a->myself(); |
1130 | /*tt += i18nc ( "Account tooltip information: <nobr>ICON <b>PROTOCOL:</b> NAME (<i>STATUS</i>)</nobr><br />", |
1131 | "<nobr><img src=\"kopete-account-icon:%3:%4\" /> <b>%1:</b> %2 (<i>%5</i>)</nobr><br />", |
1132 | a->protocol()->displayName(), a->accountLabel(), QString ( QUrl::toPercentEncoding ( a->protocol()->pluginId() ) ), |
1133 | QString ( QUrl::toPercentEncoding ( a->accountId() ) ), self->onlineStatus().description() );*/ |
1134 | tt += i18nc ( "Account tooltip information: <nobr>ICON <b>PROTOCOL:</b> NAME (<i>STATUS</i>)</nobr><br />" , |
1135 | "<nobr><img src=\"%3\" width=\"16\" height=\"16\" /> <b>%1:</b> %2 (<i>%4</i>)</nobr><br />" , |
1136 | a->protocol()->displayName(), a->accountLabel(), |
1137 | a->accountIconPath(KIconLoader::Small), self->onlineStatus().description() ); |
1138 | } |
1139 | tt += QLatin1String ( "</qt>" ); |
1140 | d->tray->setToolTip ( "kopete" , i18n("Kopete" ), tt ); |
1141 | } |
1142 | } |
1143 | |
1144 | void KopeteWindow::slotIdentityStatusIconLeftClicked ( Kopete::Identity *identity, const QPoint &p ) |
1145 | { |
1146 | Q_UNUSED ( p ) |
1147 | if ( d->identitywidget->isVisible() && d->identitywidget->identity() == identity ) |
1148 | { |
1149 | d->identitywidget->setIdentity ( 0 ); |
1150 | d->identitywidget->setVisible ( false ); |
1151 | return; |
1152 | } |
1153 | |
1154 | if ( d->infoEventWidget->isVisible() ) |
1155 | d->infoEventWidget->setVisible ( false ); |
1156 | |
1157 | d->identitywidget->setIdentity ( identity ); |
1158 | d->identitywidget->setVisible ( true ); |
1159 | } |
1160 | |
1161 | void KopeteWindow::slotShowInfoEventWidget() |
1162 | { |
1163 | if ( d->identitywidget->isVisible() ) |
1164 | { |
1165 | d->identitywidget->setIdentity( 0 ); |
1166 | d->identitywidget->setVisible( false ); |
1167 | } |
1168 | |
1169 | if ( !d->infoEventWidget->isVisible() ) |
1170 | d->infoEventWidget->setVisible( true ); |
1171 | |
1172 | if ( !isActiveWindow() ) |
1173 | slotShowHide(); |
1174 | } |
1175 | |
1176 | void KopeteWindow::slotInfoIconClicked() |
1177 | { |
1178 | if ( d->infoEventWidget->isVisible() ) |
1179 | { |
1180 | d->infoEventWidget->setVisible( false ); |
1181 | } |
1182 | else |
1183 | { |
1184 | if ( d->identitywidget->isVisible() ) |
1185 | { |
1186 | d->identitywidget->setIdentity( 0 ); |
1187 | d->identitywidget->setVisible( false ); |
1188 | } |
1189 | d->infoEventWidget->setVisible( true ); |
1190 | } |
1191 | } |
1192 | |
1193 | void KopeteWindow::slotAccountRegistered ( Kopete::Account *account ) |
1194 | { |
1195 | |
1196 | //enable the connect all toolbar button |
1197 | // actionConnect->setEnabled(true); |
1198 | d->actionDisconnect->setEnabled ( true ); |
1199 | |
1200 | // add an item for this account to the add contact actionmenu |
1201 | QString s = QString ( "actionAdd%1Contact" ).arg ( account->accountId() ); |
1202 | KAction *action = new KAction ( KIcon ( account->accountIcon() ), account->accountLabel(), this ); |
1203 | actionCollection()->addAction ( s, action ); |
1204 | connect ( action, SIGNAL (triggered(bool)), d->addContactMapper, SLOT (map()) ); |
1205 | connect ( account, SIGNAL(colorChanged(QColor)), this, SLOT(slotAccountColorChanged()) ); |
1206 | |
1207 | d->addContactMapper->setMapping ( action, account->protocol()->pluginId() + QChar ( 0xE000 ) + account->accountId() ); |
1208 | d->actionAddContact->addAction ( action ); |
1209 | |
1210 | if ( !d->showIdentityIcons ) |
1211 | { |
1212 | KopeteAccountStatusBarIcon *sbIcon = new KopeteAccountStatusBarIcon ( account, d->statusBarWidget ); |
1213 | d->accountStatusBarIcons.insert ( account, sbIcon ); |
1214 | } |
1215 | } |
1216 | |
1217 | void KopeteWindow::slotAccountColorChanged() |
1218 | { |
1219 | Kopete::Account* account = qobject_cast<Kopete::Account*>(sender()); |
1220 | Q_ASSERT(account); |
1221 | |
1222 | // update add contact actionmenu |
1223 | QString s = QString( "actionAdd%1Contact" ).arg( account->accountId() ); |
1224 | QAction *action = actionCollection()->action ( s ); |
1225 | if ( action ) |
1226 | action->setIcon( KIcon( account->accountIcon() ) ); |
1227 | } |
1228 | |
1229 | void KopeteWindow::slotAccountUnregistered ( const Kopete::Account *account ) |
1230 | { |
1231 | QList<Kopete::Account *> accounts = Kopete::AccountManager::self()->accounts(); |
1232 | if ( accounts.isEmpty() ) |
1233 | { |
1234 | // actionConnect->setEnabled(false); |
1235 | d->actionDisconnect->setEnabled ( false ); |
1236 | } |
1237 | |
1238 | disconnect ( account, SIGNAL(colorChanged(QColor)), this, SLOT(slotAccountColorChanged()) ); |
1239 | |
1240 | // update add contact actionmenu |
1241 | QString s = QString ( "actionAdd%1Contact" ).arg ( account->accountId() ); |
1242 | QAction *action = actionCollection()->action ( s ); |
1243 | if ( action ) |
1244 | { |
1245 | kDebug ( 14000 ) << " found KAction " << action << " with name: " << action->objectName(); |
1246 | d->addContactMapper->removeMappings ( action ); |
1247 | d->actionAddContact->removeAction ( action ); |
1248 | } |
1249 | |
1250 | if ( !d->showIdentityIcons ) |
1251 | { |
1252 | KopeteAccountStatusBarIcon *sbIcon = d->accountStatusBarIcons.value ( account, 0 ); |
1253 | if ( sbIcon ) |
1254 | { |
1255 | d->accountStatusBarIcons.remove ( account ); |
1256 | delete sbIcon; |
1257 | } |
1258 | } |
1259 | } |
1260 | |
1261 | void KopeteWindow:: ( KMenu * ) |
1262 | { |
1263 | KActionCollection *actionCollection = d->tray->actionCollection(); |
1264 | |
1265 | popup->clear(); |
1266 | popup->addTitle ( qApp->windowIcon(), KGlobal::caption() ); |
1267 | |
1268 | QList<Kopete::Account *> accountList = Kopete::AccountManager::self()->accounts(); |
1269 | qSort(accountList.begin(), accountList.end(), invertedCompareOnlineStatus); |
1270 | foreach ( Kopete::Account *account, accountList ) |
1271 | { |
1272 | KActionMenu * = new KActionMenu ( account->accountId(), account ); |
1273 | menu->setIcon( account->myself()->onlineStatus().iconFor( account ) ); |
1274 | |
1275 | if ( !account->hasCustomStatusMenu() ) |
1276 | Kopete::StatusRootAction::createAccountStatusActions ( account, menu ); |
1277 | |
1278 | account->fillActionMenu ( menu ); |
1279 | popup->addAction ( menu ); |
1280 | |
1281 | connect ( popup , SIGNAL (aboutToHide()) , menu , SLOT (deleteLater()) ); |
1282 | } |
1283 | |
1284 | popup->addSeparator(); |
1285 | popup->addAction ( d->actionStatusMenu ); |
1286 | popup->addSeparator(); |
1287 | popup->addAction ( d->actionPrefs ); |
1288 | popup->addAction ( d->actionAddContact ); |
1289 | popup->addSeparator(); |
1290 | popup->addAction ( actionCollection->action ( "minimizeRestore" ) ); |
1291 | popup->addAction ( actionCollection->action ( KStandardAction::name ( KStandardAction::Quit ) ) ); |
1292 | } |
1293 | |
1294 | void KopeteWindow::showExportDialog() |
1295 | { |
1296 | KabcExportWizard* wizard = new KabcExportWizard ( this ); |
1297 | wizard->setObjectName ( QLatin1String ( "export_contact_dialog" ) ); |
1298 | wizard->show(); |
1299 | } |
1300 | |
1301 | void KopeteWindow::leaveEvent ( QEvent * ) |
1302 | { |
1303 | startAutoHideTimer(); |
1304 | } |
1305 | |
1306 | void KopeteWindow::showEvent ( QShowEvent * ) |
1307 | { |
1308 | startAutoHideTimer(); |
1309 | slotStartAutoResizeTimer(); |
1310 | } |
1311 | |
1312 | void KopeteWindow::hideEvent ( QHideEvent * ) |
1313 | { |
1314 | d->autoResizeTimer->stop(); |
1315 | } |
1316 | |
1317 | void KopeteWindow::slotAutoHide() |
1318 | { |
1319 | if ( this->geometry().contains ( QCursor::pos() ) == false ) |
1320 | { |
1321 | /* The autohide-timer doesn't need to emit |
1322 | * timeouts when the window is hidden already. */ |
1323 | d->autoHideTimer->stop(); |
1324 | hide(); |
1325 | } |
1326 | } |
1327 | |
1328 | void KopeteWindow::startAutoHideTimer() |
1329 | { |
1330 | if ( d->autoHideTimeout > 0 && d->autoHide == true && isVisible() && Kopete::BehaviorSettings::self()->showSystemTray() ) |
1331 | d->autoHideTimer->start ( d->autoHideTimeout * 1000 ); |
1332 | } |
1333 | |
1334 | void KopeteWindow::slotStartAutoResizeTimer() |
1335 | { |
1336 | if ( Kopete::AppearanceSettings::contactListAutoResize() == true ) |
1337 | if ( ! d->autoResizeTimer->isActive() ) |
1338 | d->autoResizeTimer->start ( 1000 ); |
1339 | } |
1340 | |
1341 | void KopeteWindow::setOnlineStatus( uint category, const Kopete::StatusMessage& statusMessage ) |
1342 | { |
1343 | Kopete::AccountManager::self()->setOnlineStatus( category, statusMessage, 0, true ); |
1344 | } |
1345 | |
1346 | void KopeteWindow::setStatusMessage ( const Kopete::StatusMessage& statusMessage ) |
1347 | { |
1348 | Kopete::StatusManager::self()->setGlobalStatusMessage ( statusMessage ); |
1349 | } |
1350 | |
1351 | void KopeteWindow::globalStatusChanged() |
1352 | { |
1353 | QString statusTitle = Kopete::StatusManager::self()->globalStatusMessage().title(); |
1354 | QString statusMessage = Kopete::StatusManager::self()->globalStatusMessage().message(); |
1355 | d->globalStatusMessage->setText( statusTitle ); |
1356 | |
1357 | QString toolTip; |
1358 | toolTip += i18nc("@label:textbox formatted status title" , "<b>Status Title:</b> %1" , |
1359 | Kopete::Emoticons::parseEmoticons( Kopete::Message::escape(statusTitle) ) ); |
1360 | |
1361 | toolTip += i18nc("@label:textbox formatted status message" , "<br /><b>Status Message:</b> %1" , |
1362 | Kopete::Emoticons::parseEmoticons( Kopete::Message::escape(statusMessage) ) ); |
1363 | |
1364 | d->globalStatusMessage->setToolTip( toolTip ); |
1365 | } |
1366 | |
1367 | void KopeteWindow::slotGlobalStatusMessageIconClicked ( const QPoint &position ) |
1368 | { |
1369 | KMenu * = new KMenu ( this ); |
1370 | |
1371 | menu->addTitle ( i18n ( "Status Message" ) ); |
1372 | |
1373 | Kopete::UI::StatusEditAction* statusEditAction = new Kopete::UI::StatusEditAction ( this ); |
1374 | statusEditAction->setStatusMessage ( Kopete::StatusManager::self()->globalStatusMessage() ); |
1375 | connect ( statusEditAction, SIGNAL (statusChanged(Kopete::StatusMessage)), |
1376 | this, SLOT (setStatusMessage(Kopete::StatusMessage)) ); |
1377 | |
1378 | menu->addAction ( statusEditAction ); |
1379 | menu->exec ( position ); |
1380 | |
1381 | statusEditAction->deleteLater(); |
1382 | delete menu; |
1383 | } |
1384 | |
1385 | void KopeteWindow::slotAddContactDialogInternal ( const QString & accountIdentifier ) |
1386 | { |
1387 | QString protocolId = accountIdentifier.section ( QChar ( 0xE000 ), 0, 0 ); |
1388 | QString accountId = accountIdentifier.section ( QChar ( 0xE000 ), 1, 1 ); |
1389 | Kopete::Account *account = Kopete::AccountManager::self()->findAccount ( protocolId, accountId ); |
1390 | showAddContactDialog ( account ); |
1391 | } |
1392 | |
1393 | void KopeteWindow:: ( Kopete::StatusRootAction *statusRootAction ) |
1394 | { |
1395 | statusRootAction->setCurrentMessage ( Kopete::StatusManager::self()->globalStatusMessage() ); |
1396 | } |
1397 | |
1398 | void KopeteWindow::showAddContactDialog ( Kopete::Account * account ) |
1399 | { |
1400 | if ( !account ) { |
1401 | kDebug ( 14000 ) << "no account given" ; |
1402 | return; |
1403 | } |
1404 | |
1405 | KDialog *addDialog = new KDialog ( this ); |
1406 | addDialog->setCaption ( i18n ( "Add Contact" ) ); |
1407 | addDialog->setButtons ( KDialog::Ok | KDialog::Cancel ); |
1408 | addDialog->setDefaultButton ( KDialog::Ok ); |
1409 | addDialog->showButtonSeparator ( true ); |
1410 | |
1411 | KVBox * mainWid = new KVBox ( addDialog ); |
1412 | |
1413 | AddContactPage *addContactPage = |
1414 | account->protocol()->createAddContactWidget ( mainWid, account ); |
1415 | |
1416 | QWidget* groupKABC = new QWidget ( mainWid ); |
1417 | groupKABC->setObjectName ( "groupkabcwidget" ); |
1418 | Ui::GroupKABCSelectorWidget ui_groupKABC; |
1419 | ui_groupKABC.setupUi ( groupKABC ); |
1420 | |
1421 | // Populate the groups list |
1422 | Kopete::GroupList groups=Kopete::ContactList::self()->groups(); |
1423 | QHash<QString, Kopete::Group*> groupItems; |
1424 | |
1425 | // Add top level group |
1426 | groupItems.insert ( Kopete::Group::topLevel()->displayName(), Kopete::Group::topLevel() ); |
1427 | ui_groupKABC.groupCombo->addItem ( Kopete::Group::topLevel()->displayName() ); |
1428 | |
1429 | foreach ( Kopete::Group *group, groups ) |
1430 | { |
1431 | if ( group->type() != Kopete::Group::Normal ) |
1432 | continue; |
1433 | QString groupname = group->displayName(); |
1434 | if ( !groupname.isEmpty() ) |
1435 | { |
1436 | groupItems.insert ( groupname, group ); |
1437 | ui_groupKABC.groupCombo->addItem ( groupname ); |
1438 | } |
1439 | } |
1440 | |
1441 | if ( !addContactPage ) |
1442 | { |
1443 | kDebug ( 14000 ) << |
1444 | "Error while creating addcontactpage" << endl; |
1445 | } |
1446 | else |
1447 | { |
1448 | addDialog->setMainWidget ( mainWid ); |
1449 | if ( addDialog->exec() == QDialog::Accepted ) |
1450 | { |
1451 | if ( addContactPage->validateData() ) |
1452 | { |
1453 | Kopete::MetaContact * metacontact = new Kopete::MetaContact(); |
1454 | metacontact->addToGroup ( groupItems[ ui_groupKABC.groupCombo->currentText() ] ); |
1455 | metacontact->setKabcId ( ui_groupKABC.widAddresseeLink->uid() ); |
1456 | if ( addContactPage->apply ( account, metacontact ) ) |
1457 | { |
1458 | Kopete::ContactList::self()->addMetaContact ( metacontact ); |
1459 | } |
1460 | else |
1461 | { |
1462 | delete metacontact; |
1463 | } |
1464 | } |
1465 | } |
1466 | } |
1467 | addDialog->deleteLater(); |
1468 | } |
1469 | |
1470 | void KopeteWindow::slotUpdateSize() |
1471 | { |
1472 | /* resize with rules: |
1473 | - never will be taller than maxTall |
1474 | - never shorter than minTall |
1475 | - never will resize if contactlist is empty |
1476 | - never will resize if cursor is in window |
1477 | */ |
1478 | |
1479 | if ( this->geometry().contains ( QCursor::pos() ) == true ) |
1480 | { |
1481 | return; // don't do anything if cursor is inside window |
1482 | } |
1483 | const int amountWindowBiggerThanContactList = 200; |
1484 | const QRect workArea = KWindowSystem::workArea(); |
1485 | const int minHeight = 400; |
1486 | QRect newGeometry = geometry(); |
1487 | const QRect oldGeometry = geometry(); |
1488 | const int topFrameWidth = - ( frameGeometry().top() - oldGeometry.top() ); |
1489 | const int bottomFrameWidth = frameGeometry().bottom() - oldGeometry.bottom(); |
1490 | |
1491 | // desired height is height of full contents of contact list tree, as well as |
1492 | // some buffer for other elements in the main window |
1493 | int height = d->contactlist->visibleContentHeight(); |
1494 | newGeometry.setHeight ( height + amountWindowBiggerThanContactList ); |
1495 | |
1496 | if ( height ) { |
1497 | // if new size is too big or too small, bring inside limits |
1498 | if ( newGeometry.height() > workArea.height() ) |
1499 | newGeometry.setHeight ( workArea.height() - topFrameWidth - bottomFrameWidth ); |
1500 | else if ( newGeometry.height() < minHeight ) |
1501 | newGeometry.setHeight ( minHeight ); |
1502 | |
1503 | // set position of new geometry rectangle to same position as the old one |
1504 | if ( Kopete::AppearanceSettings::contactListResizeAnchor() == |
1505 | Kopete::AppearanceSettings::EnumContactListResizeAnchor::Top ) |
1506 | newGeometry.moveTop ( oldGeometry.top() ); |
1507 | else |
1508 | newGeometry.moveBottom ( oldGeometry.bottom() ); |
1509 | |
1510 | // if the window + its frame is out of the work area, bring it just inside |
1511 | if ( ( newGeometry.top() - topFrameWidth ) < workArea.top() ) |
1512 | newGeometry.moveTop ( workArea.top() + topFrameWidth ); |
1513 | |
1514 | else if ( ( newGeometry.bottom() + bottomFrameWidth ) > workArea.bottom() ) |
1515 | newGeometry.moveBottom ( workArea.bottom() - bottomFrameWidth ); |
1516 | |
1517 | // do it! |
1518 | setGeometry ( newGeometry ); |
1519 | } |
1520 | } |
1521 | |
1522 | |
1523 | void KopeteWindow::slotNewInfoEvent() |
1524 | { |
1525 | if ( !d->infoEventWidget->isVisible() ) |
1526 | { |
1527 | if ( d->identitywidget->isVisible() ) |
1528 | { |
1529 | d->identitywidget->setIdentity( 0 ); |
1530 | d->identitywidget->setVisible( false ); |
1531 | } |
1532 | d->infoEventWidget->setVisible( true ); |
1533 | } |
1534 | } |
1535 | |
1536 | #include "kopetewindow.moc" |
1537 | // vim: set noet ts=4 sts=4 sw=4: |
1538 | |