1 //////////////////////////////////////////////////////////////////////
2 //
3 // BeeBEEP Copyright (C) 2010-2021 Marco Mastroddi
4 //
5 // BeeBEEP is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published
7 // by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // BeeBEEP is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with BeeBEEP. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // Author: Marco Mastroddi <marco.mastroddi(AT)gmail.com>
19 //
20 // $Id: GuiMain.cpp 1476 2021-01-07 10:43:54Z mastroddi $
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "AudioManager.h"
25 #include "Core.h"
26 #include "BeeApplication.h"
27 #include "BeeUtils.h"
28 #include "ChatManager.h"
29 #include "EmoticonManager.h"
30 #include "FileDialog.h"
31 #include "FileShare.h"
32 #include "GuiAddUser.h"
33 #include "GuiAskPassword.h"
34 #include "GuiChat.h"
35 #include "GuiChatList.h"
36 #include "GuiCreateGroup.h"
37 #include "GuiCreateMessage.h"
38 #include "GuiConfig.h"
39 #include "GuiEditVCard.h"
40 #include "GuiFileSharing.h"
41 #include "GuiFloatingChat.h"
42 #include "GuiGroupList.h"
43 #include "GuiHome.h"
44 #include "GuiLanguage.h"
45 #include "GuiLog.h"
46 #include "GuiNetworkTest.h"
47 #include "GuiPluginManager.h"
48 #include "GuiRefusedChat.h"
49 #include "GuiSavedChat.h"
50 #include "GuiSavedChatList.h"
51 #include "GuiScreenShot.h"
52 #include "GuiNetwork.h"
53 #include "GuiShareBox.h"
54 #ifdef BEEBEEP_USE_SHAREDESKTOP
55 #include "GuiShareDesktop.h"
56 #include "ImageOptimizer.h"
57 #endif
58 #include "GuiShareLocal.h"
59 #include "GuiShareNetwork.h"
60 #include "GuiShortcut.h"
61 #include "GuiSystemTray.h"
62 #include "GuiFileTransfer.h"
63 #include "GuiUserList.h"
64 #include "GuiMain.h"
65 #include "GuiVCard.h"
66 #ifdef BEEBEEP_USE_WEBENGINE
67 #include "GuiWebView.h"
68 #endif
69 #include "GuiWizard.h"
70 #include "GuiWorkgroups.h"
71 #include "IconManager.h"
72 #include "NetworkManager.h"
73 #include "PluginManager.h"
74 #include "Protocol.h"
75 #include "MessageManager.h"
76 #include "Settings.h"
77 #include "ShortcutManager.h"
78 #include "SpellChecker.h"
79 #include "UserManager.h"
80 #ifdef BEEBEEP_USE_VOICE_CHAT
81 #include "VoicePlayer.h"
82 #include "GuiRecordVoiceMessageSettings.h"
83 #endif
84 #ifdef Q_OS_WIN
85 #include <Windows.h>
86 #endif
87
88
GuiMain(QWidget * parent)89 GuiMain::GuiMain( QWidget *parent )
90 : QMainWindow( parent ), m_floatingChats()
91 {
92 setObjectName( "GuiMainWindow" );
93 setWindowIcon( IconManager::instance().icon( "beebeep.png" ) );
94
95 // Create a status bar before the actions and the menu
96 (void) statusBar();
97
98 mp_tabMain = new QTabWidget( this );
99 mp_tabMain->setObjectName( "GuiTabMain" );
100 mp_tabMain->setTabPosition( QTabWidget::South );
101 setCentralWidget( mp_tabMain );
102
103 mp_fileSharing = Q_NULLPTR;
104 mp_screenShot = Q_NULLPTR;
105 mp_log = Q_NULLPTR;
106 mp_networkTest = Q_NULLPTR;
107 m_unreadActivities = 0;
108
109 mp_barMain = addToolBar( tr( "Show the main tool bar" ) );
110 mp_barMain->setObjectName( "GuiMainToolBar" );
111 mp_barMain->setIconSize( Settings::instance().mainBarIconSize() );
112 mp_barMain->toggleViewAction()->setVisible( false );
113
114 mp_trayIcon = new GuiSystemTray( this );
115
116 m_lastUserStatus = User::Online;
117 m_forceShutdown = false;
118 m_autoConnectOnInterfaceUp = false;
119 m_prevActivatedState = true;
120 m_coreIsConnecting = false;
121 m_changeTabToUserListOnFirstConnected = false;
122
123 m_useFusionStyle = false;
124
125 createActions();
126 createMainWidgets();
127 createMenus();
128 createToolAndMenuBars();
129 updadePluginMenu();
130
131 connect( mp_tabMain, SIGNAL( currentChanged( int ) ), this, SLOT( onMainTabChanged( int ) ) );
132
133 connect( beeCore, SIGNAL( connected() ), this, SLOT( onCoreConnected() ) );
134 connect( beeCore, SIGNAL( disconnected() ), this, SLOT( onCoreDisconnected() ) );
135 connect( beeCore, SIGNAL( newChatMessage( const Chat&, const ChatMessage& ) ), this, SLOT( onNewChatMessage( const Chat&, const ChatMessage& ) ) );
136 connect( beeCore, SIGNAL( fileDownloadRequest( const User&, const FileInfo& ) ), this, SLOT( downloadFile( const User&, const FileInfo& ) ) );
137 connect( beeCore, SIGNAL( folderDownloadRequest( const User&, const QString&, const QList<FileInfo>& ) ), this, SLOT( downloadFolder( const User&, const QString&, const QList<FileInfo>& ) ) );
138 connect( beeCore, SIGNAL( userChanged( const User& ) ), this, SLOT( onUserChanged( const User& ) ) );
139 connect( beeCore, SIGNAL( userRemoved( const User& ) ), this, SLOT( onUserRemoved( const User& ) ) );
140 connect( beeCore, SIGNAL( userIsWriting( const User&, VNumber ) ), this, SLOT( showWritingUser( const User&, VNumber ) ) );
141 connect( beeCore, SIGNAL( fileTransferProgress( VNumber, const User&, const FileInfo&, FileSizeType, qint64 ) ), this, SLOT( onFileTransferProgress( VNumber, const User&, const FileInfo&, FileSizeType, qint64 ) ) );
142 connect( beeCore, SIGNAL( fileTransferMessage( VNumber, const User&, const FileInfo&, const QString&, FileTransferPeer::TransferState ) ), this, SLOT( onFileTransferMessage( VNumber, const User&, const FileInfo&, const QString&, FileTransferPeer::TransferState ) ) );
143 connect( beeCore, SIGNAL( fileShareAvailable( const User& ) ), this, SLOT( showSharesForUser( const User& ) ) );
144 connect( beeCore, SIGNAL( chatChanged( const Chat& ) ), this, SLOT( onChatChanged( const Chat& ) ) );
145 connect( beeCore, SIGNAL( chatRemoved( const Chat& ) ), this, SLOT( onChatRemoved( const Chat& ) ) );
146 connect( beeCore, SIGNAL( savedChatListAvailable() ), this, SLOT( loadSavedChatsCompleted() ) );
147 connect( beeCore, SIGNAL( userConnectionStatusChanged( const User& ) ), this, SLOT( showConnectionStatusChanged( const User& ) ) );
148 connect( beeCore, SIGNAL( networkInterfaceIsDown() ), this, SLOT( onNetworkInterfaceDown() ) );
149 connect( beeCore, SIGNAL( networkInterfaceIsUp() ), this, SLOT( onNetworkInterfaceUp() ) );
150 connect( beeCore, SIGNAL( chatReadByUser( const Chat&, const User& ) ), this, SLOT( onChatReadByUser( const Chat&, const User& ) ) );
151 connect( beeCore, SIGNAL( localUserIsBuzzedBy( const User& ) ), this, SLOT( showBuzzFromUser( const User& ) ) );
152 connect( beeCore, SIGNAL( newSystemStatusMessage( const QString&, int ) ), this, SLOT( showMessage( const QString&, int ) ) );
153 connect( beeCore, SIGNAL( newsAvailable( const QString& ) ), this, SLOT( onNewsAvailable( const QString& ) ) );
154 connect( beeCore, SIGNAL( offlineMessageSentToUser( const User& ) ), this, SLOT( updateUser( const User& ) ) );
155 #ifdef BEEBEEP_USE_SHAREDESKTOP
156 connect( beeCore, SIGNAL( shareDesktopImageAvailable( const User&, const QImage&, const QString&, QRgb ) ), this, SLOT( onShareDesktopImageAvailable( const User&, const QImage&, const QString&, QRgb ) ) );
157 connect( beeCore, SIGNAL( shareDesktopUpdate( const User& ) ), this, SLOT( onShareDesktopUpdate( const User& ) ) );
158 #endif
159 #ifdef BEEBEEP_USE_MULTICAST_DNS
160 connect( beeCore, SIGNAL( multicastDnsChanged() ), this, SLOT( showDefaultServerPortInMenu() ) );
161 #endif
162 #ifdef BEEBEEP_USE_VOICE_CHAT
163 connect( beeCore->voicePlayer(), SIGNAL( openWithExternalPlayer( const QUrl&, VNumber ) ), this, SLOT( openUrlFromChat( const QUrl&, VNumber ) ) );
164 #endif
165
166 connect( mp_fileTransfer, SIGNAL( transferCanceled( VNumber ) ), beeCore, SLOT( cancelFileTransfer( VNumber ) ) );
167 connect( mp_fileTransfer, SIGNAL( transferPaused( VNumber ) ), beeCore, SLOT( pauseFileTransfer( VNumber ) ) );
168 connect( mp_fileTransfer, SIGNAL( openFileCompleted( const QUrl& ) ), this, SLOT( openUrl( const QUrl& ) ) );
169 connect( mp_fileTransfer, SIGNAL( resumeTransfer( VNumber, const FileInfo& ) ), this, SLOT( resumeFileTransfer( VNumber, const FileInfo& ) ) );
170
171 connect( mp_userList, SIGNAL( chatSelected( VNumber ) ), this, SLOT( showChat( VNumber ) ) );
172 connect( mp_userList, SIGNAL( userSelected( VNumber ) ), this, SLOT( checkUserSelected( VNumber ) ) );
173 connect( mp_userList, SIGNAL( showVCardRequest( VNumber ) ), this, SLOT( showVCard( VNumber ) ) );
174 connect( mp_userList, SIGNAL( sendFilesToChatRequest( VNumber, const QStringList& ) ), this, SLOT( sendFilesFromChat( VNumber, const QStringList& ) ) );
175
176 connect( mp_groupList, SIGNAL( openChatForGroupRequest( VNumber ) ), this, SLOT( showChat( VNumber ) ) );
177 connect( mp_groupList, SIGNAL( createGroupRequest() ), this, SLOT( createGroupChat() ) );
178 connect( mp_groupList, SIGNAL( editGroupRequest( VNumber ) ), this, SLOT( editGroupChat( VNumber ) ) );
179 connect( mp_groupList, SIGNAL( showVCardRequest( VNumber ) ), this, SLOT( showVCard( VNumber ) ) );
180
181 connect( mp_chatList, SIGNAL( chatSelected( VNumber ) ), this, SLOT( showChat( VNumber ) ) );
182 connect( mp_chatList, SIGNAL( chatToClear( VNumber ) ), this, SLOT( clearChat( VNumber ) ) );
183 connect( mp_chatList, SIGNAL( chatToEdit( VNumber ) ), this, SLOT( editGroupChat( VNumber ) ) );
184 connect( mp_chatList, SIGNAL( createNewChatRequest() ), this, SLOT( createGroupChat() ) );
185 connect( mp_chatList, SIGNAL( createNewMessageRequest() ), this, SLOT( createMessage() ) );
186 connect( mp_chatList, SIGNAL( hideEmptyChatsRequest() ), this, SLOT( onHideEmptyChatsRequest() ) );
187
188 connect( mp_trayIcon, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), this, SLOT( trayIconClicked( QSystemTrayIcon::ActivationReason ) ) );
189 connect( mp_trayIcon, SIGNAL( messageClicked() ), this, SLOT( trayMessageClicked() ) );
190
191 connect( mp_savedChatList, SIGNAL( savedChatSelected( const QString& ) ), this, SLOT( showSavedChatSelected( const QString& ) ) );
192 connect( mp_savedChatList, SIGNAL( savedChatRemoved( const QString& ) ), this, SLOT( removeSavedChat( const QString& ) ) );
193 connect( mp_savedChatList, SIGNAL( savedChatLinkRequest( const QString& ) ), this, SLOT( linkSavedChat( const QString& ) ) );
194
195 connect( statusBar(), SIGNAL( messageChanged( const QString& ) ), this, SLOT( onStatusBarMessageChanged( const QString& ) ) );
196
197 initShortcuts();
198 initGuiItems();
199 updateShortcuts();
200 }
201
initShortcuts()202 void GuiMain::initShortcuts()
203 {
204 mp_scMinimizeAllChats = new QShortcut( this );
205 mp_scMinimizeAllChats->setContext( Qt::ApplicationShortcut );
206 connect( mp_scMinimizeAllChats, SIGNAL( activated() ), this, SLOT( minimizeAllChats() ) );
207 #ifdef BEEBEEP_USE_QXT
208 mp_scShowAllChats = new QxtGlobalShortcut( this );
209 connect( mp_scShowAllChats, SIGNAL( activated() ), this, SLOT( showAllChats() ) );
210 #endif
211 mp_scShowNextUnreadMessage = new QShortcut( this );
212 mp_scShowNextUnreadMessage->setContext( Qt::ApplicationShortcut );
213 connect( mp_scShowNextUnreadMessage, SIGNAL( activated() ), this, SLOT( showNextChat() ) );
214 }
215
setupChatConnections(GuiChat * gui_chat)216 void GuiMain::setupChatConnections( GuiChat* gui_chat )
217 {
218 connect( gui_chat, SIGNAL( newMessage( VNumber, const QString& ) ), this, SLOT( sendMessage( VNumber, const QString& ) ) );
219 connect( gui_chat, SIGNAL( writing( VNumber ) ), beeCore, SLOT( sendWritingMessage( VNumber ) ) );
220 connect( gui_chat, SIGNAL( nextChat() ), this, SLOT( showNextChat() ) );
221 connect( gui_chat, SIGNAL( openUrl( const QUrl&, VNumber ) ), this, SLOT( openUrlFromChat( const QUrl&, VNumber ) ) );
222 connect( gui_chat, SIGNAL( sendFileFromChatRequest( VNumber, const QString& ) ), this, SLOT( sendFileFromChat( VNumber, const QString& ) ) );
223 connect( gui_chat, SIGNAL( sendFilesFromChatRequest( VNumber, const QStringList& ) ), this, SLOT( sendFilesFromChat( VNumber, const QStringList& ) ) );
224 connect( gui_chat, SIGNAL( editGroupRequest( VNumber ) ), this, SLOT( editGroupChat( VNumber ) ) );
225 connect( gui_chat, SIGNAL( chatToClear( VNumber ) ), this, SLOT( clearChat( VNumber ) ) );
226 connect( gui_chat, SIGNAL( clearSystemMessagesRequestFromChat( VNumber ) ), this, SLOT( clearSystemMessagesInChat( VNumber ) ) );
227 connect( gui_chat, SIGNAL( showChatMenuRequest() ), this, SLOT( showChatSettingsMenu() ) );
228 #ifdef BEEBEEP_USE_SHAREDESKTOP
229 connect( gui_chat, SIGNAL( shareDesktopToChatRequest( VNumber, bool ) ), this, SLOT( onShareDesktopRequestFromChat( VNumber, bool ) ) );
230 connect( gui_chat, SIGNAL( screenshotToChatRequest( VNumber ) ), this, SLOT( sendScreenshotToChat( VNumber ) ) );
231 #endif
232 }
233
checkWindowFlagsAndShow()234 void GuiMain::checkWindowFlagsAndShow()
235 {
236 if( !mp_trayIcon->isVisible() )
237 {
238 mp_trayIcon->show();
239 #ifdef Q_OS_LINUX
240 qApp->processEvents();
241 mp_trayIcon->hide();
242 qApp->processEvents();
243 mp_trayIcon->show();
244 #endif
245 }
246
247 if( mp_tabMain->currentWidget() != mp_home )
248 mp_tabMain->setCurrentWidget( mp_home );
249
250 if( !Settings::instance().enableMaximizeButton() )
251 setWindowFlags( windowFlags() & ~Qt::WindowMaximizeButtonHint );
252
253 Bee::setWindowStaysOnTop( this, Settings::instance().stayOnTop() );
254
255 if( !isVisible() )
256 show();
257
258 if( Settings::instance().resetGeometryAtStartup() || Settings::instance().guiGeometry().isEmpty() )
259 resetGeometryAndState();
260 else
261 restoreGeometryAndState();
262
263 checkViewActions();
264
265 #ifdef Q_OS_WIN
266 beeApp->setSessionNotificationForWindow( reinterpret_cast<HWND>( winId() ) );
267 #endif
268
269 if( Settings::instance().loadOnTrayAtStartup() && QSystemTrayIcon::isSystemTrayAvailable() )
270 {
271 QMetaObject::invokeMethod( this, "hideToTrayIcon", Qt::QueuedConnection );
272 return;
273 }
274
275 if( Settings::instance().showMinimizedAtStartup() )
276 QMetaObject::invokeMethod( this, "showMinimized", Qt::QueuedConnection );
277 }
278
showUp()279 void GuiMain::showUp()
280 {
281 Bee::showUp( this );
282 }
283
raiseOnTop()284 void GuiMain::raiseOnTop()
285 {
286 Bee::raiseOnTop( this );
287 }
288
updateWindowTitle()289 void GuiMain::updateWindowTitle()
290 {
291 setWindowTitle( QString( "%1 - %2" ).arg( Bee::userNameToShow( Settings::instance().localUser(), false ), Settings::instance().programName() ) );
292 }
293
RemoveMenuStringFromTooltip(const QString & s)294 static QString RemoveMenuStringFromTooltip( const QString& s )
295 {
296 return s.isEmpty() ? QString( "" ) : s.split( QString( "\n" ), QString::KeepEmptyParts ).first();
297 }
298
updateTabTitles()299 void GuiMain::updateTabTitles()
300 {
301 int tab_index = mp_tabMain->indexOf( mp_home );
302 int current_value = m_unreadActivities;
303 mp_tabMain->setTabText( tab_index, current_value > 0 ? QString::number( current_value ) : "" );
304 if( current_value > 0 )
305 mp_tabMain->setTabToolTip( tab_index, QString( "%1: %2 %3" ).arg( RemoveMenuStringFromTooltip( mp_home->mainToolTip() ) ).arg( current_value ).arg( tr( "news" ) ) );
306 else
307 mp_tabMain->setTabToolTip( tab_index, RemoveMenuStringFromTooltip( mp_home->mainToolTip() ) );
308
309 tab_index = mp_tabMain->indexOf( mp_userList );
310 current_value = beeCore->connectedUsers();
311 int other_value = UserManager::instance().userList().size();
312 mp_tabMain->setTabText( tab_index, current_value > 0 ? QString::number( current_value ) : (other_value > 0 ? QString::number( other_value ) : "" ) );
313 if( current_value > 0 )
314 mp_tabMain->setTabToolTip( tab_index, QString( "%1: %2 %3" ).arg( RemoveMenuStringFromTooltip( mp_userList->mainToolTip() ) ).arg( current_value ).arg( tr( "connected" ) ) );
315 else
316 mp_tabMain->setTabToolTip( tab_index, RemoveMenuStringFromTooltip( mp_userList->mainToolTip() ) );
317
318 tab_index = mp_tabMain->indexOf( mp_chatList );
319 current_value = ChatManager::instance().countNotEmptyChats( false );
320 mp_tabMain->setTabText( tab_index, current_value > 0 ? QString::number( current_value ) : "" );
321
322 tab_index = mp_tabMain->indexOf( mp_groupList );
323 current_value = ChatManager::instance().countGroupChats();
324 mp_tabMain->setTabText( tab_index, current_value > 0 ? QString::number( current_value ) : "" );
325
326 tab_index = mp_tabMain->indexOf( mp_savedChatList );
327 current_value = ChatManager::instance().constHistoryMap().size();
328 mp_tabMain->setTabText( tab_index, current_value > 0 ? QString::number( current_value ) : "" );
329 }
330
keyPressEvent(QKeyEvent * e)331 void GuiMain::keyPressEvent( QKeyEvent* e )
332 {
333 if( e->key() == Qt::Key_Escape )
334 {
335 if( Settings::instance().keyEscapeMinimizeInTray() )
336 QTimer::singleShot( 0, this, SLOT( hideToTrayIcon() ) );
337 else
338 QTimer::singleShot( 0, this, SLOT( showMinimized() ) );
339 e->accept();
340 return;
341 }
342
343 QMainWindow::keyPressEvent( e );
344 }
345
changeEvent(QEvent * e)346 void GuiMain::changeEvent( QEvent* e )
347 {
348 QMainWindow::changeEvent( e );
349 }
350
closeEvent(QCloseEvent * e)351 void GuiMain::closeEvent( QCloseEvent* e )
352 {
353 if( beeCore->isConnected() )
354 {
355 if( !m_forceShutdown )
356 {
357 if( Settings::instance().closeMinimizeInTray() && QSystemTrayIcon::isSystemTrayAvailable() )
358 {
359 QTimer::singleShot( 0, this, SLOT( hideToTrayIcon() ) );
360 e->ignore();
361 return;
362 }
363
364 if( Settings::instance().promptOnCloseEvent() )
365 {
366 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you want to quit %1?" ).arg( Settings::instance().programName() ),
367 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
368 {
369 e->ignore();
370 return;
371 }
372 }
373 }
374
375 beeCore->stop();
376 }
377
378 if( Settings::instance().saveGeometryOnExit() )
379 #if QT_VERSION == 0x050906
380 {
381 if( isVisible() )
382 {
383 Settings::instance().setGuiGeometry( saveGeometry() );
384 Settings::instance().save();
385 }
386 }
387 #else
388 saveGeometryAndState();
389 #endif
390
391 QSettings* sets = Settings::instance().objectSettings();
392 sets->deleteLater();
393
394 if( !m_forceShutdown )
395 {
396 if( !sets->isWritable() )
397 {
398 if( QMessageBox::warning( this, Settings::instance().programName(),
399 QString( "%1<br>%2<br>%3<br>%4<br>%5" ).arg( tr( "<b>Settings can not be saved</b>. Path:" ) )
400 .arg( sets->fileName() )
401 .arg( tr( "<b>is not writable</b> by user:" ) )
402 .arg( Settings::instance().localUser().accountName() )
403 .arg( tr( "Do you want to close anyway?" ) ),
404 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
405 {
406 e->ignore();
407 return;
408 }
409 }
410
411 if( Settings::instance().chatAutoSave() )
412 {
413 if( !MessageManager::instance().chatMessageCanBeSaved() )
414 {
415 if( QMessageBox::warning( this, Settings::instance().programName(),
416 QString( "%1<br>%2<br>%3<br>%4<br>%5" ).arg( tr( "<b>Chat messages can not be saved</b>. Path:" ) )
417 .arg( Settings::instance().savedChatsFilePath() )
418 .arg( tr( "<b>is not writable</b> by user:" ) )
419 .arg( Settings::instance().localUser().accountName() )
420 .arg( tr( "Do you want to close anyway?" ) ),
421 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
422 {
423 e->ignore();
424 return;
425 }
426 }
427 }
428 }
429
430 if( mp_fileSharing )
431 mp_fileSharing->close();
432
433 if( mp_screenShot )
434 mp_screenShot->close();
435
436 if( mp_networkTest )
437 mp_networkTest->close();
438
439 #ifdef BEEBEEP_USE_WEBENGINE
440 if( mp_webView )
441 mp_webView->close();
442 #endif
443
444 #ifdef BEEBEEP_USE_VOICE_CHAT
445 if( !beeCore->voicePlayer()->isStopped() )
446 beeCore->voicePlayer()->stop();
447 #endif
448
449 if( mp_log )
450 mp_log->close();
451
452 foreach( QWidget* w, qApp->allWidgets() )
453 {
454 GuiSavedChat* gsv = qobject_cast<GuiSavedChat*>( w );
455 if( gsv )
456 gsv->close();
457 }
458
459 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
460 fl_chat->close();
461
462 if( mp_menuMain && mp_menuMain->isVisible() )
463 mp_menuMain->close();
464 if( mp_menuSettings && mp_menuSettings->isVisible() )
465 mp_menuSettings->close();
466 if( mp_menuInfo && mp_menuInfo->isVisible() )
467 mp_menuInfo->close();
468 if( mp_menuStatus && mp_menuStatus->isVisible() )
469 mp_menuStatus->close();
470 if( mp_menuUsersSettings && mp_menuUsersSettings->isVisible() )
471 mp_menuUsersSettings->close();
472
473 mp_trayIcon->hide();
474
475 if( mp_dockFileTransfers->isFloating() && mp_dockFileTransfers->isVisible() )
476 mp_dockFileTransfers->hide();
477
478 #ifdef Q_OS_WIN
479 beeApp->resetSessionNotificationForWindow();
480 #endif
481 // quit now on last window closed
482 qApp->setQuitOnLastWindowClosed( true );
483
484 e->accept();
485 }
486
showNextChat()487 void GuiMain::showNextChat()
488 {
489 #ifdef BEEBEEP_DEBUG
490 qDebug() << "Show next chat in list with unread messages";
491 #endif
492 Chat c = ChatManager::instance().firstChatWithUnreadMessages();
493 if( c.isValid() )
494 {
495 showChat( c.id() );
496 GuiFloatingChat* fl_chat = floatingChat( c.id() );
497 if( fl_chat && !fl_chat->isActiveWindow() )
498 fl_chat->setFocusInChat();
499 }
500 else
501 showMessage( tr( "No new message available" ), 5000 );
502 }
503
forceShutdown()504 void GuiMain::forceShutdown()
505 {
506 qDebug() << "Shutdown...";
507 m_forceShutdown = true;
508 if( beeCore->isConnected() )
509 beeCore->stop();
510 close();
511 }
512
onWakeUpRequest()513 void GuiMain::onWakeUpRequest()
514 {
515 #ifdef BEEBEEP_DEBUG
516 qDebug() << "Main window wakes up from sleep";
517 #endif
518 initGuiItems();
519 }
520
onSleepRequest()521 void GuiMain::onSleepRequest()
522 {
523 #ifdef BEEBEEP_DEBUG
524 qDebug() << "Main window goes to sleep";
525 #endif
526 if( beeCore->isConnected() )
527 {
528 m_autoConnectOnInterfaceUp = true;
529 stopCore();
530 }
531 }
532
onCoreConnected()533 void GuiMain::onCoreConnected()
534 {
535 m_coreIsConnecting = false;
536 initGuiItems();
537 #ifdef BEEBEEP_USE_WEBENGINE
538 QTimer::singleShot( 0, mp_webView, SLOT( loadNews() ) );
539 #endif
540 }
541
onCoreDisconnected()542 void GuiMain::onCoreDisconnected()
543 {
544 if( m_coreIsConnecting )
545 m_coreIsConnecting = false;
546 initGuiItems();
547 }
548
startCore()549 void GuiMain::startCore()
550 {
551 if( beeCore->isConnected() || m_coreIsConnecting )
552 return;
553
554 mp_home->resetNews();
555 m_coreIsConnecting = true;
556
557 if( Settings::instance().askChangeUserAtStartup() )
558 {
559 if( !showWizard() )
560 {
561 m_coreIsConnecting = false;
562 return;
563 }
564 }
565
566 if( Settings::instance().firstTime() )
567 {
568 Settings::instance().setFirstTime( false );
569 Settings::instance().setAskChangeUserAtStartup( false );
570 }
571
572 if( Settings::instance().askPassword() )
573 {
574 if( !promptConnectionPassword() )
575 {
576 m_coreIsConnecting = false;
577 return;
578 }
579 }
580
581 if( beeCore->start() )
582 {
583 m_autoConnectOnInterfaceUp = true;
584 if( Settings::instance().showChatsOnConnection() )
585 {
586 mp_tabMain->setCurrentWidget( mp_chatList );
587 m_changeTabToUserListOnFirstConnected = false;
588 }
589 else if( Settings::instance().showUsersOnConnection() )
590 {
591 mp_tabMain->setCurrentWidget( mp_userList );
592 m_changeTabToUserListOnFirstConnected = false;
593 }
594 else
595 m_changeTabToUserListOnFirstConnected = true;
596 }
597 else
598 QMetaObject::invokeMethod( beeCore, "checkNetworkInterface", Qt::QueuedConnection );
599 }
600
promptConnectionPassword()601 bool GuiMain::promptConnectionPassword()
602 {
603 GuiAskPassword gap( this );
604 gap.setModal( true );
605 gap.loadData();
606 gap.show();
607 gap.setFixedSize( gap.size() );
608 if( gap.exec() == QDialog::Rejected )
609 return false;
610 mp_actPromptPassword->setChecked( Settings::instance().askPasswordAtStartup() );
611 if( beeCore->isConnected() )
612 showRestartConnectionAlertMessage();
613 return true;
614 }
615
disconnectFromNetwork()616 void GuiMain::disconnectFromNetwork()
617 {
618 m_autoConnectOnInterfaceUp = false;
619 stopCore();
620 }
621
stopCore()622 void GuiMain::stopCore()
623 {
624 if( isFileTransferInProgress() )
625 return;
626
627 if( mp_tabMain->currentWidget() != mp_home )
628 mp_tabMain->setCurrentWidget( mp_home );
629
630 #ifdef BEEBEEP_USE_SHAREDESKTOP
631 foreach( GuiShareDesktop* gsd, m_desktops )
632 gsd->close();
633 #endif
634
635 beeCore->stop();
636 }
637
restartCore()638 void GuiMain::restartCore()
639 {
640 if( !beeCore->isConnected() && !m_coreIsConnecting )
641 {
642 startCore();
643 return;
644 }
645
646 if( isFileTransferInProgress() )
647 return;
648
649 #ifdef BEEBEEP_USE_SHAREDESKTOP
650 foreach( GuiShareDesktop* gsd, m_desktops )
651 gsd->close();
652 #endif
653
654 mp_home->resetNews();
655 m_coreIsConnecting = true;
656 beeCore->restart();
657 }
658
isFileTransferInProgress()659 bool GuiMain::isFileTransferInProgress()
660 {
661 if( m_forceShutdown )
662 return false;
663
664 if( !NetworkManager::instance().isMainInterfaceUp() )
665 return false;
666
667 if( beeApp->isInSleepMode() )
668 return false;
669
670 if( beeCore->hasFileTransferInProgress() )
671 {
672 if( QMessageBox::warning( this, Settings::instance().programName(),
673 tr( "There are still files that have not been transferred and will be interrupted. Do you want to disconnect anyway?" ),
674 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
675 return true;
676 }
677 return false;
678 }
679
initGuiItems()680 void GuiMain::initGuiItems()
681 {
682 mp_userList->updateUsers();
683 mp_chatList->updateChats();
684 mp_groupList->updateGroups();
685 mp_savedChatList->updateSavedChats();
686 updateStatusIcon();
687 updateNewMessageAction();
688 checkViewActions();
689 }
690
checkViewActions()691 void GuiMain::checkViewActions()
692 {
693 bool is_connected = beeCore->isConnected();
694 int connected_users = beeCore->connectedUsers();
695 bool file_transfer_is_active = beeCore->isFileTransferActive();
696
697 mp_actConnect->setEnabled( !m_coreIsConnecting && !is_connected );
698 mp_actDisconnect->setEnabled( is_connected );
699 mp_actBroadcast->setEnabled( is_connected );
700 mp_actCreateMessage->setEnabled( is_connected && !Settings::instance().disableCreateMessage() );
701 mp_actCreateGroupChat->setEnabled( UserManager::instance().userList().size() > 1 );
702 mp_actViewFileTransfer->setEnabled( Settings::instance().enableFileTransfer() );
703 mp_actViewFileSharing->setEnabled( file_transfer_is_active && Settings::instance().enableFileSharing() && !Settings::instance().disableFileSharing() );
704 if( mp_menuFileTransferSettings->isEnabled() )
705 {
706 foreach( QAction* act, mp_menuFileTransferSettings->actions() )
707 {
708 if( act->data().toInt() == 12 )
709 continue;
710 act->setEnabled( Settings::instance().enableFileTransfer() );
711 }
712 }
713 mp_actEnableFileSharing->setEnabled( Settings::instance().enableFileTransfer() && !Settings::instance().disableFileSharing() );
714
715 #ifdef BEEBEEP_USE_VOICE_CHAT
716 mp_menuVoiceMessage->setEnabled( Settings::instance().enableFileTransfer() );
717 #endif
718
719 showDefaultServerPortInMenu();
720
721 if( !m_floatingChats.isEmpty() )
722 {
723 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
724 fl_chat->updateActions( is_connected, connected_users, file_transfer_is_active );
725 }
726
727 if( mp_fileSharing )
728 {
729 if( mp_actViewFileSharing->isEnabled() )
730 mp_fileSharing->checkViewActions();
731 else
732 mp_fileSharing->close();
733 }
734
735 updateWindowTitle();
736 updateTabTitles();
737 }
738
showAbout()739 void GuiMain::showAbout()
740 {
741 #ifdef Q_OS_MAC
742 QMessageBox::about( Q_NULLPTR, Settings::instance().programName(),
743 #else
744 QMessageBox::about( this, Settings::instance().programName(),
745 #endif
746 QString( "<b>%1</b> - Free Office Messenger<br><br>%2<br>%3 %4 %5<br><br>%6 %7<br>%8<br>" )
747 .arg( Settings::instance().programName() )
748 .arg( Settings::instance().isDevelopmentVersion() ? tr( "Development version") : tr( "Version" ) )
749 .arg( Settings::instance().version( true, true, true ) )
750 .arg( tr( "for" ) )
751 .arg( Settings::instance().operatingSystem( true ) )
752 .arg( tr( "developed by" ) )
753 .arg( QString( "<a href='%1'>Marco Mastroddi</a>" ).arg( Settings::instance().developerWebSite() ) )
754 .arg( QString( "e-mail: <a href='mailto://marco.mastroddi@gmail.com'>marco.mastroddi@gmail.com</a><br>web: <a href='%1'>www.beebeep.net</a>" ).arg( Settings::instance().officialWebSite() ) )
755 );
756 }
757
showLicense()758 void GuiMain::showLicense()
759 {
760 QString license_txt = QLatin1String(
761 "BeeBEEP Copyright (C) 2010-2021 Marco Mastroddi <br><br>"
762 "BeeBEEP is free software: you can redistribute it and/or modify "
763 "it under the terms of the GNU General Public License as published "
764 "by the Free Software Foundation, either version 3 of the License "
765 "or (at your option) any later version. <br><br>"
766 "BeeBEEP is distributed in the hope that it will be useful, "
767 "but WITHOUT ANY WARRANTY; without even the implied warranty "
768 "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. <br><br>"
769 "See the GNU General Public License for more details. <br><br>" );
770 #ifdef Q_OS_MAC
771 QMessageBox::about( Q_NULLPTR, Settings::instance().programName(), license_txt );
772 #else
773 QMessageBox::about( this, Settings::instance().programName(), license_txt );
774 #endif
775 }
776
showAboutQt()777 void GuiMain::showAboutQt()
778 {
779 #ifdef Q_OS_MAC
780 QMessageBox::aboutQt( Q_NULLPTR, Settings::instance().programName() );
781 #else
782 QMessageBox::aboutQt( this, Settings::instance().programName() );
783 #endif
784 }
785
createActions()786 void GuiMain::createActions()
787 {
788 mp_actConnect = new QAction( IconManager::instance().icon( "connection.png" ), tr( "Connect" ), this );
789 connect( mp_actConnect, SIGNAL( triggered() ), this, SLOT( startCore() ) );
790
791 mp_actDisconnect = new QAction( IconManager::instance().icon( "disconnection.png" ), tr( "Disconnect" ), this );
792 connect( mp_actDisconnect, SIGNAL( triggered() ), this, SLOT( disconnectFromNetwork() ) );
793
794 mp_actBroadcast = new QAction( IconManager::instance().icon( "broadcast.png" ), tr( "Search users" ), this );
795 connect( mp_actBroadcast, SIGNAL( triggered() ), this, SLOT( sendBroadcastMessage() ) );
796
797 mp_actConfigureNetwork = new QAction( IconManager::instance().icon( "network.png"), tr( "Configure network..."), this );
798 connect( mp_actConfigureNetwork, SIGNAL( triggered() ), this, SLOT( searchUsers() ) );
799
800 mp_actQuit = new QAction( IconManager::instance().icon( "quit.png" ), tr( "Quit" ), this );
801 mp_actQuit->setShortcuts( QKeySequence::Quit );
802 mp_actQuit->setMenuRole( QAction::QuitRole );
803 connect( mp_actQuit, SIGNAL( triggered() ), this, SLOT( forceShutdown() ) );
804
805 mp_actVCard = new QAction( IconManager::instance().icon( "profile-edit.png"), tr( "Edit your profile..." ), this );
806 connect( mp_actVCard, SIGNAL( triggered() ), this, SLOT( changeVCard() ) );
807
808 mp_actAbout = new QAction( IconManager::instance().icon( "beebeep.png" ), tr( "About %1..." ).arg( Settings::instance().programName() ), this );
809 mp_actAbout->setMenuRole( QAction::AboutRole );
810 connect( mp_actAbout, SIGNAL( triggered() ), this, SLOT( showAbout() ) );
811
812 mp_actCreateGroupChat = new QAction( IconManager::instance().icon( "group-create.png" ), tr( "Create new group chat" ), this );
813 connect( mp_actCreateGroupChat, SIGNAL( triggered() ), this, SLOT( createGroupChat() ) );
814
815 mp_actViewNewMessage = new QAction( IconManager::instance().icon( "beebeep-message.png" ), tr( "Show new message" ), this );
816 connect( mp_actViewNewMessage, SIGNAL( triggered() ), this, SLOT( showNextChat() ) );
817
818 mp_actViewFileSharing = new QAction( IconManager::instance().icon( "file-sharing.png" ), tr( "Show file sharing window" ), this );
819 connect( mp_actViewFileSharing, SIGNAL( triggered() ), this, SLOT( showFileSharingWindow() ) );
820
821 mp_actViewLog = new QAction( IconManager::instance().icon( "log.png" ), tr( "Show the %1 log" ).arg( Settings::instance().programName() )+QString("..."), this );
822 connect( mp_actViewLog, SIGNAL( triggered() ), this, SLOT( showLogWindow() ) );
823
824 mp_actViewScreenShot = new QAction( IconManager::instance().icon( "screenshot.png" ), tr( "Make a screenshot" ), this );
825 connect( mp_actViewScreenShot, SIGNAL( triggered() ), this, SLOT( showScreenShotWindow() ) );
826
827 mp_actCreateMessage = new QAction( IconManager::instance().icon( "message-create" ), tr( "Write a message" ), this );
828 connect( mp_actCreateMessage, SIGNAL( triggered() ), this, SLOT( createMessage() ) );
829 if( Settings::instance().disableCreateMessage() )
830 mp_actCreateMessage->setToolTip( tr( "The option has been disabled by your system administrator.") );
831
832 #ifdef BEEBEEP_USE_WEBENGINE
833 mp_actWebView = new QAction( IconManager::instance().icon( "network.png" ), tr( "News" ), this );
834 connect( mp_actWebView, SIGNAL( triggered() ), this, SLOT( showWebView() ) );
835 mp_actWebView->setDisabled( true );
836 #endif
837 }
838
createMenus()839 void GuiMain::createMenus()
840 {
841 /* Plugins Menu */
842 mp_menuPlugins = new QMenu( tr( "Plugins" ) + QString( "..." ), this );
843 mp_menuPlugins->setIcon( IconManager::instance().icon( "plugin.png" ) );
844
845 /* Main Menu */
846 mp_menuMain = new QMenu( tr( "Main" ), this );
847 mp_menuMain->addAction( mp_actConnect );
848 mp_menuMain->addAction( mp_actDisconnect );
849 mp_menuMain->addSeparator();
850 mp_menuMain->addAction( mp_actBroadcast );
851 mp_menuMain->addSeparator();
852 mp_menuMain->addAction( mp_actVCard );
853 mp_menuMain->addSeparator();
854 if( Settings::instance().resourceFolder() != Settings::instance().dataFolder() )
855 mp_menuMain->addAction( IconManager::instance().icon( "resource-folder.png" ), tr( "Open your resource folder" )+QString("..."), this, SLOT( openResourceFolder() ) );
856 mp_menuMain->addAction( IconManager::instance().icon( "data-folder.png" ), tr( "Open your data folder" )+QString("..."), this, SLOT( openDataFolder() ) );
857 mp_menuMain->addAction( IconManager::instance().icon( "download-folder.png" ), tr( "Open your download folder" )+QString("..."), this, SLOT( openDownloadFolder() ) );
858 mp_menuMain->addSeparator();
859 mp_menuMain->addAction( IconManager::instance().icon( "network-test.png" ), tr( "Test your network" )+QString("..."), this, SLOT( showNetworkTest() ) );
860 mp_menuMain->addSeparator();
861 mp_menuMain->addAction( mp_actViewLog );
862 #ifdef BEEBEEP_USE_WEBENGINE
863 mp_menuMain->addSeparator();
864 mp_menuMain->addAction( mp_actWebView );
865 #endif
866 mp_menuMain->addSeparator();
867 mp_menuMain->addMenu( mp_menuPlugins );
868 mp_menuMain->addSeparator();
869 mp_menuMain->addAction( mp_actQuit );
870
871 QAction* act;
872 /* Chat Menu */
873 mp_menuChat = new QMenu( tr( "Chat" ), this );
874
875 /* System Menu */
876 mp_menuSettings = new QMenu( tr( "Settings" ), this );
877 mp_menuInterfaceSettings = new QMenu( tr( "Interface" ), this );
878 mp_menuInterfaceSettings->setIcon( IconManager::instance().icon( "interface.png" ) );
879 mp_menuSettings->addMenu( mp_menuInterfaceSettings );
880 act = mp_menuInterfaceSettings->addAction( tr( "Use the dark theme" ), this, SLOT( settingsChanged() ) );
881 act->setCheckable( true );
882 act->setChecked( Settings::instance().useDarkStyle() );
883 act->setData( 77 );
884 #if QT_VERSION < 0x050000
885 act->setEnabled( false );
886 #endif
887 act = mp_menuInterfaceSettings->addAction( tr( "Reset minimum width for applied style" ), this, SLOT( settingsChanged() ) );
888 act->setCheckable( true );
889 act->setChecked( Settings::instance().resetMinimumWidthForStyle() );
890 act->setData( 103 );
891 mp_menuInterfaceSettings->addSeparator();
892 act = mp_menuInterfaceSettings->addAction( tr( "Escape key minimize to tray icon" ), this, SLOT( settingsChanged() ) );
893 act->setCheckable( true );
894 act->setChecked( Settings::instance().keyEscapeMinimizeInTray() );
895 act->setData( 29 );
896 act = mp_menuInterfaceSettings->addAction( tr( "Close button minimize to tray icon" ), this, SLOT( settingsChanged() ) );
897 act->setCheckable( true );
898 act->setChecked( Settings::instance().closeMinimizeInTray() );
899 act->setData( 11 );
900 #ifdef Q_OS_MAC
901 // Close button on MacOSX must quit the app
902 act->setDisabled( true );
903 #endif
904 act = mp_menuInterfaceSettings->addAction( tr( "Enable maximize button" ), this, SLOT( settingsChanged() ) );
905 act->setCheckable( true );
906 act->setChecked( Settings::instance().enableMaximizeButton() );
907 act->setData( 28 );
908 mp_menuInterfaceSettings->addSeparator();
909 mp_menuInterfaceSettings->addAction( IconManager::instance().icon( "shortcut.png" ), tr( "Shortcuts" ) + QString( "..." ), this, SLOT( editShortcuts() ) );
910 mp_menuInterfaceSettings->addAction( IconManager::instance().icon( "language.png" ), tr( "Select language" ) + QString( "..." ), this, SLOT( selectLanguage() ) );
911 mp_menuInterfaceSettings->addAction( IconManager::instance().icon( "theme.png" ), tr( "Select icon theme" ) + QString( "..." ), this, SLOT( selectIconSourcePath() ) );
912 mp_menuInterfaceSettings->addSeparator();
913 mp_menuInterfaceSettings->addAction( IconManager::instance().icon( "update.png" ), tr( "Restore the colors to the default ones" ), this, SLOT( resetAllColors() ) );
914 mp_menuInterfaceSettings->addAction( IconManager::instance().icon( "reset-window.png" ), tr( "Reset geometry of all windows" ), this, SLOT( askResetGeometryAndState() ) );
915
916 mp_menuStartupSettings = new QMenu( tr( "On start" ), this );
917 mp_menuStartupSettings->setIcon( IconManager::instance().icon( "settings-start.png" ) );
918 mp_menuSettings->addMenu( mp_menuStartupSettings );
919 act = mp_menuStartupSettings->addAction( tr( "Show minimized" ), this, SLOT( settingsChanged() ) );
920 act->setCheckable( true );
921 act->setChecked( Settings::instance().showMinimizedAtStartup() );
922 act->setData( 35 );
923 act = mp_menuStartupSettings->addAction( tr( "Show only on system tray" ), this, SLOT( settingsChanged() ) );
924 act->setCheckable( true );
925 act->setChecked( Settings::instance().loadOnTrayAtStartup() );
926 act->setData( 24 );
927 act = mp_menuStartupSettings->addAction( tr( "Reset window geometry" ), this, SLOT( settingsChanged() ) );
928 act->setCheckable( true );
929 act->setChecked( Settings::instance().resetGeometryAtStartup() );
930 act->setData( 26 );
931 act = mp_menuStartupSettings->addAction( tr( "Check for new version" ), this, SLOT( settingsChanged() ) );
932 act->setCheckable( true );
933 act->setChecked( Settings::instance().checkNewVersionAtStartup() );
934 act->setData( 43 );
935 mp_menuStartupSettings->addSeparator();
936 act = mp_menuStartupSettings->addAction( IconManager::instance().icon( "timer.png" ), tr( "Delay first connection" ) + QString( "..." ), this, SLOT( settingsChanged() ) );
937 act->setData( 65 );
938
939 mp_menuCloseSettings = new QMenu( tr( "On close" ), this );
940 mp_menuCloseSettings->setIcon( IconManager::instance().icon( "settings-close.png" ) );
941 mp_menuSettings->addMenu( mp_menuCloseSettings );
942 act = mp_menuCloseSettings->addAction( tr( "Prompt on quit when connected" ), this, SLOT( settingsChanged() ) );
943 act->setCheckable( true );
944 act->setChecked( Settings::instance().promptOnCloseEvent() );
945 act->setData( 36 );
946 act = mp_menuCloseSettings->addAction( tr( "Save window's geometry" ), this, SLOT( settingsChanged() ) );
947 act->setCheckable( true );
948 act->setChecked( Settings::instance().saveGeometryOnExit() );
949 act->setData( 68 );
950
951 mp_menuConnectionSettings = new QMenu( tr( "On connection" ), this );
952 mp_menuConnectionSettings->setIcon( IconManager::instance().icon( "connection.png" ) );
953 mp_menuSettings->addMenu( mp_menuConnectionSettings );
954 act = mp_menuConnectionSettings->addAction( tr( "Show the user list" ), this, SLOT( settingsChanged() ) );
955 act->setCheckable( true );
956 act->setChecked( Settings::instance().showUsersOnConnection() );
957 act->setData( 69 );
958 act = mp_menuConnectionSettings->addAction( tr( "Show the chat list" ), this, SLOT( settingsChanged() ) );
959 act->setCheckable( true );
960 act->setChecked( Settings::instance().showChatsOnConnection() );
961 act->setData( 79 );
962 mp_menuConnectionSettings->addSeparator();
963 act = mp_menuConnectionSettings->addAction( tr( "Prompts to change user" ), this, SLOT( settingsChanged() ) );
964 act->setCheckable( true );
965 act->setChecked( Settings::instance().askChangeUserAtStartup() );
966 act->setData( 45 );
967 mp_actPromptPassword = mp_menuConnectionSettings->addAction( tr( "Prompts to ask network password" ), this, SLOT( settingsChanged() ) );
968 mp_actPromptPassword->setCheckable( true );
969 mp_actPromptPassword->setChecked( Settings::instance().askPasswordAtStartup() );
970 mp_actPromptPassword->setData( 17 );
971
972 mp_menuNetworkStatus = new QMenu( tr( "Network" ), this );
973 mp_menuNetworkStatus->setIcon( IconManager::instance().icon( "network.png" ) );
974 mp_menuSettings->addMenu( mp_menuNetworkStatus );
975 mp_menuNetworkStatus->addAction( mp_actConfigureNetwork );
976 mp_menuNetworkStatus->addSeparator();
977 mp_actEditWorkgroups = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "workgroup.png" ), tr( "Your workgroups" ) + QString( "..." ), this, SLOT( showWorkgroups() ) );
978 mp_menuNetworkStatus->addSeparator();
979 mp_actHostAddress = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "network.png" ), QString( "ip" ) );
980 mp_actPortBroadcast = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "broadcast.png" ), QString( "udp1" ) );
981 mp_actMulticastGroupAddress = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "multicast-group.png" ), QString( "multicast" ) );
982 mp_actPortListener = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "default-chat-online.png" ), QString( "tcp1" ) );
983 mp_actPortFileTransfer = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "network-scan.png" ), QString( "tcp2" ) );
984 #ifdef BEEBEEP_USE_MULTICAST_DNS
985 mp_actMulticastDns = mp_menuNetworkStatus->addAction( IconManager::instance().icon( "mdns.png" ), QString( "mdns" ) );
986 #endif
987 mp_menuNetworkStatus->addSeparator();
988 mp_actEncryptedConnectionByDefault = mp_menuNetworkStatus->addAction( Settings::instance().disableConnectionSocketEncryption() ? IconManager::instance().icon( "encryption-disabled.png" ) : IconManager::instance().icon( "encryption-enabled.png" ), QString( "End-to-end encryption" ) );
989 mp_actCompressedDataByDefault = mp_menuNetworkStatus->addAction( Settings::instance().disableConnectionSocketDataCompression() ? IconManager::instance().icon( "folder.png" ) : IconManager::instance().icon( "file-compressed.png" ), QString( "Data compression" ) );
990
991 mp_menuUsersSettings = new QMenu( tr( "Users" ), this );
992 mp_menuUsersSettings->setIcon( IconManager::instance().icon( "user-list.png" ) );
993 mp_menuSettings->addMenu( mp_menuUsersSettings );
994
995 QMenu* menu_recognize_users = mp_menuUsersSettings->addMenu( tr( "Recognize users" ) + QString( "..." ) );
996 menu_recognize_users->setIcon( IconManager::instance().icon( "user-list.png" ) );
997 mp_actGroupRecognizeUsers = new QActionGroup( this );
998 mp_actGroupRecognizeUsers->setExclusive( true );
999 act = menu_recognize_users->addAction( tr( "By nickname" ) + QString( " (%1)" ).arg( tr( "default" ) ) );
1000 act->setCheckable( true );
1001 act->setChecked( Settings::instance().userRecognitionMethod() == Settings::RecognizeByNickname );
1002 act->setData( 59 );
1003 mp_actGroupRecognizeUsers->addAction( act );
1004 act = menu_recognize_users->addAction( tr( "By account name and domain name" ) );
1005 act->setCheckable( true );
1006 act->setChecked( Settings::instance().userRecognitionMethod() == Settings::RecognizeByAccountAndDomain );
1007 act->setData( 57 );
1008 mp_actGroupRecognizeUsers->addAction( act );
1009 act = menu_recognize_users->addAction( tr( "By account name" ) );
1010 act->setCheckable( true );
1011 act->setChecked( Settings::instance().userRecognitionMethod() == Settings::RecognizeByAccount );
1012 act->setData( 58 );
1013 mp_actGroupRecognizeUsers->addAction( act );
1014 menu_recognize_users->addSeparator();
1015 connect( mp_actGroupRecognizeUsers, SIGNAL( triggered( QAction* ) ), this, SLOT( settingsChanged( QAction* ) ) );
1016 mp_menuUsersSettings->addSeparator();
1017 mp_actAddUsers = mp_menuUsersSettings->addAction( IconManager::instance().icon( "user-add.png" ), tr( "Add users" ) + QString( "..." ), this, SLOT( showAddUser() ) );
1018 mp_menuUsersSettings->addSeparator();
1019 mp_actSaveUserList = mp_menuUsersSettings->addAction( tr( "Save users" ), this, SLOT( settingsChanged() ) );
1020 mp_actSaveUserList->setCheckable( true );
1021 mp_actSaveUserList->setChecked( Settings::instance().saveUserList() );
1022 mp_actSaveUserList->setData( 32 );
1023 mp_actSaveGroupList = mp_menuUsersSettings->addAction( tr( "Save groups" ), this, SLOT( settingsChanged() ) );
1024 mp_actSaveGroupList->setCheckable( true );
1025 mp_actSaveGroupList->setChecked( Settings::instance().saveGroupList() );
1026 mp_actSaveGroupList->setData( 2 );
1027 mp_menuUsersSettings->addSeparator();
1028 mp_actShowUserFullName = mp_menuUsersSettings->addAction( tr( "Show the name and surname of the users" ) , this, SLOT( settingsChanged() ) );
1029 mp_actShowUserFullName->setCheckable( true );
1030 mp_actShowUserFullName->setChecked( Settings::instance().useUserFullName() );
1031 mp_actShowUserFullName->setDisabled( true );
1032 mp_actShowUserFirstNameFirstInFullName = mp_menuUsersSettings->addAction( tr( "Show surname before firstname of the users" ) , this, SLOT( settingsChanged() ) );
1033 mp_actShowUserFirstNameFirstInFullName->setCheckable( true );
1034 mp_actShowUserFirstNameFirstInFullName->setChecked( !Settings::instance().useUserFirstNameFirstInFullName() );
1035 mp_actShowUserFirstNameFirstInFullName->setData( 102 );
1036 mp_menuUsersSettings->addSeparator();
1037 mp_actRemoveInactiveUsers = mp_menuUsersSettings->addAction( "", this, SLOT( settingsChanged() ) );
1038 mp_actRemoveInactiveUsers->setCheckable( true );
1039 mp_actRemoveInactiveUsers->setChecked( Settings::instance().removeInactiveUsers() );
1040 mp_actRemoveInactiveUsers->setData( 33 );
1041 setMaxInactivityDaysInAction( mp_actRemoveInactiveUsers );
1042 mp_menuChatSettings = new QMenu( tr( "Chat" ), this );
1043 mp_menuChatSettings->setIcon( IconManager::instance().icon( "chat.png" ) );
1044 mp_menuSettings->addMenu( mp_menuChatSettings );
1045 mp_menuChatSaveSettings = new QMenu( tr( "Save messages" ) + QString( "..." ), this );
1046 mp_menuChatSaveSettings->setIcon( IconManager::instance().icon( "save-as.png" ) );
1047 mp_menuChatSettings->addMenu( mp_menuChatSaveSettings );
1048 act = mp_menuChatSaveSettings->addAction( tr( "Enable message saving" ), this, SLOT( settingsChanged() ) );
1049 act->setCheckable( true );
1050 act->setChecked( Settings::instance().chatAutoSave() );
1051 act->setData( 18 );
1052 mp_menuChatSaveSettings->addSeparator();
1053 act = mp_menuChatSaveSettings->addAction( tr( "Save unsent messages" ), this, SLOT( settingsChanged() ) );
1054 act->setCheckable( true );
1055 act->setChecked( Settings::instance().chatSaveUnsentMessages() );
1056 act->setData( 81 );
1057 mp_actSaveFileTransferMessages = mp_menuChatSaveSettings->addAction( tr( "Save file transfer messages" ), this, SLOT( settingsChanged() ) );
1058 mp_actSaveFileTransferMessages->setCheckable( true );
1059 mp_actSaveFileTransferMessages->setChecked( Settings::instance().chatSaveFileTransfers() );
1060 mp_actSaveFileTransferMessages->setData( 82 );
1061 mp_actSaveSystemMessages = mp_menuChatSaveSettings->addAction( tr( "Save system messages" ), this, SLOT( settingsChanged() ) );
1062 mp_actSaveSystemMessages->setCheckable( true );
1063 mp_actSaveSystemMessages->setChecked( Settings::instance().chatSaveSystemMessages() );
1064 mp_actSaveSystemMessages->setData( 83 );
1065 mp_menuChatSettings->addSeparator();
1066 act = mp_menuChatSaveSettings->addAction( "", this, SLOT( settingsChanged() ) );
1067 act->setCheckable( true );
1068 act->setData( 84 );
1069 setChatMaxLinesToSaveInAction( act );
1070 mp_menuChatSaveSettings->addSeparator();
1071 act = mp_menuChatSaveSettings->addAction( "", this, SLOT( settingsChanged() ) );
1072 act->setCheckable( true );
1073 act->setData( 85 );
1074 setClearCacheAfterDaysInAction( act );
1075 mp_menuChatSettings->addSeparator();
1076 act = mp_menuChatSettings->addAction( tr( "Open chats in a single window" ), this, SLOT( settingsChanged() ) );
1077 act->setCheckable( true );
1078 act->setChecked( Settings::instance().showChatsInOneWindow() );
1079 act->setData( 7 );
1080 act = mp_menuChatSettings->addAction( tr( "Clear all read messages on closing window" ), this, SLOT( settingsChanged() ) );
1081 act->setCheckable( true );
1082 act->setChecked( Settings::instance().chatClearAllReadMessages() );
1083 act->setData( 47 );
1084 act = mp_menuChatSettings->addAction( tr( "Use high resolution emoticons" ), this, SLOT( settingsChanged() ) );
1085 act->setCheckable( true );
1086 act->setChecked( Settings::instance().useHiResEmoticons() );
1087 act->setData( 105 );
1088 #if QT_VERSION < 0x050000
1089 act->setEnabled( false );
1090 #endif
1091 act = mp_menuChatSettings->addAction( tr( "Use font emoticons" ), this, SLOT( settingsChanged() ) );
1092 act->setCheckable( true );
1093 act->setChecked( Settings::instance().useFontEmoticons() );
1094 act->setData( 31 );
1095 act = mp_menuChatSettings->addAction( tr( "Show chat toolbar" ), this, SLOT( settingsChanged() ) );
1096 act->setCheckable( true );
1097 act->setChecked( Settings::instance().showChatToolbar() );
1098 act->setData( 42 );
1099 mp_menuChatSettings->addSeparator();
1100 act = mp_menuChatSettings->addAction( tr( "Send offline messages also to chat with all users" ), this, SLOT( settingsChanged() ) );
1101 act->setCheckable( true );
1102 act->setChecked( Settings::instance().sendOfflineMessagesToDefaultChat() );
1103 act->setData( 66 );
1104 act = mp_menuChatSettings->addAction( "", this, SLOT( settingsChanged() ) );
1105 act->setCheckable( true );
1106 setChatMessagesToShowInAction( act );
1107 act->setData( 27 );
1108 act = mp_menuChatSettings->addAction( "", this, SLOT( settingsChanged() ) );
1109 act->setCheckable( true );
1110 act->setData( 71 );
1111 setChatInactiveWindowOpacityLevelInAction( act );
1112 mp_menuChatSettings->addSeparator();
1113 QMenu* menu_on_sending_message = mp_menuChatSettings->addMenu( tr( "On sending message" ) + QString( "..." ) );
1114 menu_on_sending_message->setIcon( IconManager::instance().icon( "send.png" ) );
1115 mp_actGroupOnSendingMessage = new QActionGroup( this );
1116 mp_actGroupOnSendingMessage->setExclusive( true );
1117 act = menu_on_sending_message->addAction( tr( "Do nothing" ) + QString( " (%1)" ).arg( tr( "default" ) ) );
1118 act->setCheckable( true );
1119 act->setChecked( Settings::instance().chatOnSendingMessage() == Settings::SkipOnSendingMessage );
1120 act->setData( 91 );
1121 mp_actGroupOnSendingMessage->addAction( act );
1122 act = menu_on_sending_message->addAction( tr( "Minimize chat window" ) );
1123 act->setCheckable( true );
1124 act->setChecked( Settings::instance().chatOnSendingMessage() == Settings::MinimizeChatOnSendingMessage );
1125 act->setData( 92 );
1126 mp_actGroupOnSendingMessage->addAction( act );
1127 act = menu_on_sending_message->addAction( tr( "Close chat window" ) );
1128 act->setCheckable( true );
1129 act->setChecked( Settings::instance().chatOnSendingMessage() == Settings::CloseChatOnSendingMessage );
1130 act->setData( 93 );
1131 mp_actGroupOnSendingMessage->addAction( act );
1132 connect( mp_actGroupOnSendingMessage, SIGNAL( triggered( QAction* ) ), this, SLOT( settingsChanged( QAction* ) ) );
1133 mp_menuChatSettings->addSeparator();
1134 mp_menuChatColorSettings = new QMenu( tr( "Colors" ) + QString( "..." ), this );
1135 mp_menuChatColorSettings->setIcon( IconManager::instance().icon( "colors.png" ) );
1136 mp_menuChatSettings->addMenu( mp_menuChatColorSettings );
1137 act = mp_menuChatColorSettings->addAction( IconManager::instance().icon( "background-color.png" ), tr( "Select chat background color" ), this, SLOT( settingsChanged() ) );
1138 act->setData( 72 );
1139 act = mp_menuChatColorSettings->addAction( IconManager::instance().icon( "font-color.png" ), tr( "Select chat default text color" ), this, SLOT( settingsChanged() ) );
1140 act->setData( 73 );
1141 act = mp_menuChatColorSettings->addAction( IconManager::instance().icon( "log.png" ), tr( "Select chat system text color" ), this, SLOT( settingsChanged() ) );
1142 act->setData( 74 );
1143 act = mp_menuChatColorSettings->addAction( IconManager::instance().icon( "quote-text.png" ), tr( "Select quote text color" ), this, SLOT( settingsChanged() ) );
1144 act->setData( 89 );
1145 act = mp_menuChatColorSettings->addAction( IconManager::instance().icon( "quote-background.png" ), tr( "Select quote background color" ), this, SLOT( settingsChanged() ) );
1146 act->setData( 90 );
1147 mp_actSelectEmoticonSourcePath = mp_menuChatSettings->addAction( IconManager::instance().icon( "emoticon.png" ), tr( "Select emoticon theme" ) + QString( "..." ), this, SLOT( selectEmoticonSourcePath() ) );
1148 mp_actSelectEmoticonSourcePath->setEnabled( !Settings::instance().useFontEmoticons() );
1149 mp_menuChatSettings->addAction( IconManager::instance().icon( "dictionary.png" ), tr( "Dictionary" ) + QString( "..." ), this, SLOT( selectDictionatyPath() ) );
1150 mp_menuChatSettings->addSeparator();
1151 mp_menuChatSettings->addAction( IconManager::instance().icon( "refused-chat.png" ), tr( "Blocked chats" ) + QString( "..." ), this, SLOT( showRefusedChats() ) );
1152
1153 mp_menuFileTransferSettings = new QMenu( tr( "File transfer" ), this );
1154 mp_menuFileTransferSettings->setIcon( IconManager::instance().icon( "file-transfer.png" ) );
1155 mp_menuFileTransferSettings->setDisabled( Settings::instance().disableFileTransfer() );
1156 mp_menuSettings->addMenu( mp_menuFileTransferSettings );
1157 act = mp_menuFileTransferSettings->addAction( tr( "Enable file transfer" ), this, SLOT( settingsChanged() ) );
1158 act->setCheckable( true );
1159 act->setChecked( Settings::instance().enableFileTransfer() );
1160 act->setData( 12 );
1161 mp_actEnableFileSharing = mp_menuFileTransferSettings->addAction( tr( "Enable file sharing" ), this, SLOT( settingsChanged() ) );
1162 mp_actEnableFileSharing->setCheckable( true );
1163 mp_actEnableFileSharing->setChecked( Settings::instance().enableFileSharing() );
1164 mp_actEnableFileSharing->setData( 5 );
1165 mp_actEnableFileSharing->setDisabled( Settings::instance().disableFileSharing() );
1166 mp_menuFileTransferSettings->addSeparator();
1167 mp_actConfirmDownload = mp_menuFileTransferSettings->addAction( tr( "Prompt before downloading file" ), this, SLOT( settingsChanged() ) );
1168 mp_actConfirmDownload->setCheckable( true );
1169 mp_actConfirmDownload->setChecked( Settings::instance().confirmOnDownloadFile() );
1170 mp_actConfirmDownload->setData( 30 );
1171 act = mp_menuFileTransferSettings->addAction( tr( "Always download files into the folder with the user's name" ), this, SLOT( settingsChanged() ) );
1172 act->setCheckable( true );
1173 act->setChecked( Settings::instance().downloadInUserFolder() );
1174 act->setData( 86 );
1175 mp_menuExistingFile = mp_menuFileTransferSettings->addMenu( tr( "If a file already exists" ) + QString( "..." ) );
1176 mp_actGroupExistingFile = new QActionGroup( this );
1177 mp_actGroupExistingFile->setExclusive( true );
1178 act = mp_menuExistingFile->addAction( tr( "Generate new file name" ) );
1179 act->setCheckable( true );
1180 act->setChecked( true );
1181 act->setData( (int)Settings::GenerateNewFileName );
1182 mp_actGroupExistingFile->addAction( act );
1183 act = mp_menuExistingFile->addAction( tr( "Skip" ) );
1184 act->setCheckable( true );
1185 act->setData( (int)Settings::SkipExistingFile );
1186 mp_actGroupExistingFile->addAction( act );
1187 act = mp_menuExistingFile->addAction( tr( "Overwrite" ) );
1188 act->setCheckable( true );
1189 act->setData( (int)Settings::OverwriteExistingFile );
1190 mp_actGroupExistingFile->addAction( act );
1191 act = mp_menuExistingFile->addAction( tr( "Overwrite older" ) );
1192 act->setCheckable( true );
1193 act->setData( (int)Settings::OverwriteOlderExistingFile );
1194 mp_actGroupExistingFile->addAction( act );
1195 foreach( QAction* act_to_select, mp_actGroupExistingFile->actions() )
1196 {
1197 if( act_to_select->data().toInt() == Settings::instance().onExistingFileAction() )
1198 {
1199 act_to_select->setChecked( true );
1200 break;
1201 }
1202 }
1203 connect( mp_actGroupExistingFile, SIGNAL( triggered( QAction* ) ), this, SLOT( onChangeSettingOnExistingFile( QAction* ) ) );
1204
1205 act = mp_menuFileTransferSettings->addAction( tr( "Keep the original modification date of the transferred file" ), this, SLOT( settingsChanged() ) );
1206 act->setCheckable( true );
1207 act->setChecked( Settings::instance().keepModificationDateOnFileTransferred() );
1208 act->setData( 101 );
1209 mp_actResumeFileTransfer = mp_menuFileTransferSettings->addAction( tr( "Resume file transfer" ) + QString( " (%1)" ).arg( tr( "when possible" ) ), this, SLOT( settingsChanged() ) );
1210 mp_actResumeFileTransfer->setCheckable( true );
1211 mp_actResumeFileTransfer->setChecked( Settings::instance().resumeFileTransfer() );
1212 mp_actResumeFileTransfer->setData( 97 );
1213 act = mp_menuFileTransferSettings->addAction( "", this, SLOT( settingsChanged() ) );
1214 act->setCheckable( true );
1215 act->setData( 100 );
1216 setClearPartiallyDownloadedFilesAfterDaysInAction( act );
1217 mp_menuFileTransferSettings->addSeparator();
1218 act = mp_menuFileTransferSettings->addAction( "", this, SLOT( settingsChanged() ) );
1219 act->setCheckable( true );
1220 setMaxQueuedDownloadsInAction( act );
1221 act->setData( 88 );
1222 act = mp_menuFileTransferSettings->addAction( tr( "Always shows the progress of file transfer" ), this, SLOT( settingsChanged() ) );
1223 act->setCheckable( true );
1224 act->setChecked( Settings::instance().alwaysShowFileTransferProgress() );
1225 act->setData( 78 );
1226 mp_menuFileTransferSettings->addSeparator();
1227 act = mp_menuFileTransferSettings->addAction( tr( "Use native file dialogs" ), this, SLOT( settingsChanged() ) );
1228 act->setCheckable( true );
1229 act->setChecked( Settings::instance().useNativeDialogs() );
1230 act->setData( 4 );
1231 mp_menuFileTransferSettings->addSeparator();
1232 mp_actSelectDownloadFolder = mp_menuFileTransferSettings->addAction( IconManager::instance().icon( "download-folder.png" ), tr( "Select download folder" ) + QString( "..." ), this, SLOT( selectDownloadDirectory() ) );
1233
1234 #ifdef BEEBEEP_USE_VOICE_CHAT
1235 mp_menuVoiceMessage = new QMenu( tr( "Voice message" ), this );
1236 mp_menuVoiceMessage->setIcon( IconManager::instance().icon( "microphone.png" ) );
1237 mp_menuVoiceMessage->setDisabled( Settings::instance().disableVoiceMessages() );
1238 mp_menuSettings->addMenu( mp_menuVoiceMessage );
1239 act = mp_menuVoiceMessage->addAction( IconManager::instance().icon( "audio-settings.png" ), tr( "Voice encoder" ) + QString( "..." ), this, SLOT( showVoiceEncoderSettings() ) );
1240 mp_menuVoiceMessage->addSeparator();
1241 act = mp_menuVoiceMessage->addAction( IconManager::instance().icon( "timer.png" ), tr( "Maximum duration" ) + QString( "..." ), this, SLOT( settingsChanged() ) );
1242 act->setData( 94 );
1243 mp_menuVoiceMessage->addSeparator();
1244 act = mp_menuVoiceMessage->addAction( tr( "Use the integrated voice message player" ) + QString( " (beta)" ), this, SLOT( settingsChanged() ) );
1245 act->setCheckable( true );
1246 act->setChecked( Settings::instance().useVoicePlayer() );
1247 act->setData( 95 );
1248 #endif
1249
1250 mp_menuNotificationSettings = new QMenu( tr( "Notifications" ), this );
1251 mp_menuNotificationSettings->setIcon( IconManager::instance().icon( "bell.png" ) );
1252 mp_menuSettings->addMenu( mp_menuNotificationSettings );
1253 mp_actBeepOnNewMessage = mp_menuNotificationSettings->addAction( tr( "Enable BEEP alert" ), this, SLOT( settingsChanged() ) );
1254 mp_actBeepOnNewMessage->setCheckable( true );
1255 mp_actBeepOnNewMessage->setChecked( Settings::instance().beepOnNewMessageArrived() );
1256 mp_actBeepOnNewMessage->setData( 34 );
1257 act = mp_menuNotificationSettings->addAction( tr( "Enable Buzz sound" ), this, SLOT( settingsChanged() ) );
1258 act->setCheckable( true );
1259 act->setChecked( Settings::instance().playBuzzSound() );
1260 act->setData( 56 );
1261 act = mp_menuNotificationSettings->addAction( tr( "Enable notifications also for chat with all users" ), this, SLOT( settingsChanged() ) );
1262 act->setCheckable( true );
1263 act->setChecked( Settings::instance().enableDefaultChatNotifications() );
1264 act->setData( 75 );
1265 act = mp_menuNotificationSettings->addAction( tr( "Enable BEEP alert also for active chat windows" ), this, SLOT( settingsChanged() ) );
1266 act->setCheckable( true );
1267 act->setChecked( Settings::instance().beepInActiveWindowAlso() );
1268 act->setData( 98 );
1269 act = mp_menuNotificationSettings->addAction( tr( "Disable BEEP alert if your status is busy" ), this, SLOT( settingsChanged() ) );
1270 act->setCheckable( true );
1271 act->setChecked( Settings::instance().disableBeepInUserStatusBusy() );
1272 act->setData( 96 );
1273 mp_menuNotificationSettings->addSeparator();
1274 act = mp_menuNotificationSettings->addAction( tr( "Raise main window on new message" ), this, SLOT( settingsChanged() ) );
1275 act->setCheckable( true );
1276 act->setChecked( Settings::instance().raiseMainWindowOnNewMessageArrived() );
1277 act->setData( 80 );
1278 act = mp_menuNotificationSettings->addAction( tr( "Always open chat on new message" ), this, SLOT( settingsChanged() ) );
1279 act->setCheckable( true );
1280 act->setChecked( Settings::instance().alwaysOpenChatOnNewMessageArrived() );
1281 act->setData( 70 );
1282 act = mp_menuNotificationSettings->addAction( tr( "Raise previously opened chat on new message" ), this, SLOT( settingsChanged() ) );
1283 act->setCheckable( true );
1284 act->setChecked( Settings::instance().raiseOnNewMessageArrived() );
1285 act->setData( 15 );
1286 mp_menuNotificationSettings->addSeparator();
1287 mp_menuTrayIconSettings = new QMenu( tr( "System tray icon" ), this );
1288 mp_menuTrayIconSettings->setIcon( IconManager::instance().icon( "settings-tray-icon.png" ) );
1289 mp_menuNotificationSettings->addMenu( mp_menuTrayIconSettings );
1290 act = mp_menuTrayIconSettings->addAction( tr( "Enable tray icon notifications" ), this, SLOT( settingsChanged() ) );
1291 act->setCheckable( true );
1292 act->setChecked( Settings::instance().showNotificationOnTray() );
1293 act->setData( 19 );
1294 act = mp_menuTrayIconSettings->addAction( tr( "Show only message notifications" ), this, SLOT( settingsChanged() ) );
1295 act->setCheckable( true );
1296 act->setChecked( Settings::instance().showOnlyMessageNotificationOnTray() );
1297 act->setData( 40 );
1298 act = mp_menuTrayIconSettings->addAction( tr( "Show chat message preview" ), this, SLOT( settingsChanged() ) );
1299 act->setCheckable( true );
1300 act->setChecked( Settings::instance().showChatMessageOnTray() );
1301 act->setData( 46 );
1302 act = mp_menuTrayIconSettings->addAction( tr( "Show file notifications" ), this, SLOT( settingsChanged() ) );
1303 act->setCheckable( true );
1304 act->setChecked( Settings::instance().showFileTransferCompletedOnTray() );
1305 act->setData( 48 );
1306 mp_menuNotificationSettings->addSeparator();
1307 mp_menuNotificationSettings->addAction( IconManager::instance().icon( "file-beep.png" ), tr( "Select beep file..." ), this, SLOT( selectBeepFile() ) );
1308 mp_menuNotificationSettings->addAction( IconManager::instance().icon( "play.png" ), tr( "Play beep" ), this, SLOT( testBeepFile() ) );
1309
1310 #ifdef BEEBEEP_USE_SHAREDESKTOP
1311 QMenu* menu_share_desktop = new QMenu( tr( "Desktop sharing" ), this );
1312 menu_share_desktop->setIcon( IconManager::instance().icon( "desktop-share.png" ) );
1313 menu_share_desktop->setDisabled( Settings::instance().disableDesktopSharing() );
1314 mp_menuSettings->addMenu( menu_share_desktop );
1315 act = menu_share_desktop->addAction( tr( "Enable desktop sharing" ), this, SLOT( settingsChanged() ) );
1316 act->setCheckable( true );
1317 act->setChecked( Settings::instance().enableShareDesktop() );
1318 act->setData( 60 );
1319 menu_share_desktop->addSeparator();
1320 act = menu_share_desktop->addAction( IconManager::instance().icon( "timer.png" ), tr( "Select screen capture interval" ) + QString( "..." ), this, SLOT( settingsChanged() ) );
1321 act->setData( 61 );
1322 act = menu_share_desktop->addAction( IconManager::instance().icon( "image-type.png" ), tr( "Select image type" ) + QString( "..." ), this, SLOT( settingsChanged() ) );
1323 act->setData( 62 );
1324 act = menu_share_desktop->addAction( IconManager::instance().icon( "image-quality.png" ), tr( "Select image quality" ) + QString( "..." ), this, SLOT( settingsChanged() ) );
1325 act->setData( 63 );
1326 menu_share_desktop->addSeparator();
1327 act = menu_share_desktop->addAction( tr( "Fit image to screen" ), this, SLOT( settingsChanged() ) );
1328 act->setCheckable( true );
1329 act->setChecked( Settings::instance().shareDesktopFitToScreen() );
1330 act->setData( 64 );
1331 #endif
1332
1333 mp_menuSettings->addSeparator();
1334 act = mp_menuSettings->addAction( tr( "Always stay on top" ), this, SLOT( settingsChanged() ) );
1335 act->setCheckable( true );
1336 act->setChecked( Settings::instance().stayOnTop() );
1337 act->setData( 14 );
1338 #ifdef Q_OS_WIN
1339 act = mp_menuSettings->addAction( tr( "Start %1 automatically" ).arg( Settings::instance().programName() ), this, SLOT( settingsChanged() ) );
1340 act->setCheckable( true );
1341 act->setChecked( Settings::instance().hasStartOnSystemBoot() );
1342 act->setData( 16 );
1343 #endif
1344 mp_actSaveWindowGeometry = mp_menuSettings->addAction( IconManager::instance().icon( "save-window.png" ), tr( "Save window's geometry" ), this, SLOT( askSaveGeometryAndState() ) );
1345 mp_actSaveWindowGeometry->setDisabled( Settings::instance().resetGeometryAtStartup() );
1346
1347 /* User List Menu */
1348 mp_menuUserList = new QMenu( tr( "Options" ), this );
1349 act = mp_menuUserList->addAction( tr( "Sort users in ascending order" ), this, SLOT( settingsChanged() ) );
1350 act->setCheckable( true );
1351 act->setChecked( Settings::instance().sortUsersAscending() );
1352 act->setData( 49 );
1353 QMenu* sorting_users_menu = mp_menuUserList->addMenu( tr( "Sorting mode" ) + QString( "..." ) );
1354 QActionGroup* sorting_users_action_group = new QActionGroup( this );
1355 sorting_users_action_group->setExclusive( true );
1356 act = sorting_users_menu->addAction( tr( "Default mode" ) );
1357 act->setCheckable( true );
1358 act->setChecked( Settings::instance().userSortingMode() < 1 || Settings::instance().userSortingMode() > 3 );
1359 act->setData( 50 );
1360 sorting_users_action_group->addAction( act );
1361 act = sorting_users_menu->addAction( tr( "By user name" ) );
1362 act->setCheckable( true );
1363 act->setChecked( Settings::instance().userSortingMode() == 1 );
1364 act->setData( 51 );
1365 sorting_users_action_group->addAction( act );
1366 act = sorting_users_menu->addAction( tr( "By user status" ) );
1367 act->setCheckable( true );
1368 act->setChecked( Settings::instance().userSortingMode() == 2 );
1369 act->setData( 52 );
1370 sorting_users_action_group->addAction( act );
1371 act = sorting_users_menu->addAction( tr( "By unread messages" ) );
1372 act->setCheckable( true );
1373 act->setChecked( Settings::instance().userSortingMode() == 3 );
1374 act->setData( 53 );
1375 sorting_users_action_group->addAction( act );
1376 connect( sorting_users_action_group, SIGNAL( triggered( QAction* ) ), this, SLOT( settingsChanged( QAction* ) ) );
1377 mp_menuUserList->addSeparator();
1378 mp_actShowOnlineUsersOnly = mp_menuUserList->addAction( tr( "Show online users only" ), this, SLOT( settingsChanged() ) );
1379 mp_actShowOnlineUsersOnly->setCheckable( true );
1380 mp_actShowOnlineUsersOnly->setChecked( Settings::instance().showOnlyOnlineUsers() );
1381 mp_actShowOnlineUsersOnly->setData( 6 );
1382 act = mp_menuUserList->addAction( tr( "Show users in their workgroups" ), this, SLOT( settingsChanged() ) );
1383 act->setCheckable( true );
1384 act->setChecked( Settings::instance().showUsersInWorkgroups() );
1385 act->setData( 87 );
1386 if( mp_actShowUserFullName->isChecked() )
1387 mp_menuUserList->addAction( mp_actShowUserFullName );
1388 mp_menuUserList->addAction( mp_actShowUserFirstNameFirstInFullName );
1389 mp_menuUserList->addSeparator();
1390 act = mp_menuUserList->addAction( tr( "Show the user's picture" ), this, SLOT( settingsChanged() ) );
1391 act->setCheckable( true );
1392 act->setChecked( Settings::instance().showUserPhoto() );
1393 act->setData( 21 );
1394 act = mp_menuUserList->addAction( tr( "Show the user's vCard on right click" ), this, SLOT( settingsChanged() ) );
1395 act->setCheckable( true );
1396 act->setChecked( Settings::instance().showVCardOnRightClick() );
1397 act->setData( 25 );
1398 act = mp_menuUserList->addAction( tr( "Show status color in background" ), this, SLOT( settingsChanged() ) );
1399 act->setCheckable( true );
1400 act->setChecked( Settings::instance().showUserStatusBackgroundColor() );
1401 act->setData( 38 );
1402 act = mp_menuUserList->addAction( tr( "Show the status description" ), this, SLOT( settingsChanged() ) );
1403 act->setCheckable( true );
1404 act->setChecked( Settings::instance().showUserStatusDescription() );
1405 act->setData( 37 );
1406 mp_menuUserList->addSeparator();
1407 mp_actEditAvatarIconSize = mp_menuUserList->addAction( IconManager::instance().icon( "icon-size.png" ), tr( "Change size of the user's picture" ), this, SLOT( changeAvatarSizeInList() ) );
1408 mp_userList->setMenuSettings( mp_menuUserList );
1409
1410 /* Status Menu */
1411 mp_menuStatus = new QMenu( tr( "Status" ), this );
1412 mp_menuStatus->setIcon( IconManager::instance().icon( "user-status.png" ) );
1413 for( int i = User::Online; i < User::NumStatus; i++ )
1414 {
1415 act = mp_menuStatus->addAction( QIcon( Bee::menuUserStatusIconFileName( i ) ), Bee::userStatusToString( i ), this, SLOT( statusSelected() ) );
1416 act->setData( i );
1417 act->setIconVisibleInMenu( true );
1418 }
1419 mp_menuStatus->addSeparator();
1420 mp_actSetAutoAway = mp_menuStatus->addAction( tr( "Set your status to away automatically" ), this, SLOT( settingsChanged() ) );
1421 mp_actSetAutoAway->setCheckable( true );
1422 mp_actSetAutoAway->setChecked( Settings::instance().autoUserAway() );
1423 mp_actSetAutoAway->setData( 20 );
1424 mp_menuStatus->addSeparator();
1425 mp_menuUserStatusList = new QMenu( tr( "Recently used" ), this );
1426 act = mp_menuStatus->addMenu( mp_menuUserStatusList );
1427 act->setIcon( IconManager::instance().icon( "recent.png" ) );
1428 loadUserStatusRecentlyUsed();
1429 mp_actChangeStatusDescription = mp_menuStatus->addAction( IconManager::instance().icon( "user-status.png" ), tr( "Change your status description..." ), this, SLOT( changeStatusDescription() ) );
1430 mp_menuStatus->addAction( IconManager::instance().icon( "clear.png" ), tr( "Clear all status descriptions" ), this, SLOT( clearRecentlyUsedUserStatus() ) );
1431 mp_menuStatus->addSeparator();
1432 mp_menuStatus->addAction( mp_actEditWorkgroups );
1433 mp_menuStatus->addSeparator();
1434 act = mp_menuStatus->addAction( QIcon( Bee::menuUserStatusIconFileName( User::Offline ) ), Bee::userStatusToString( User::Offline ), this, SLOT( statusSelected() ) );
1435 act->setData( User::Offline );
1436 act->setIconVisibleInMenu( true );
1437 act = mp_menuStatus->menuAction();
1438 connect( act, SIGNAL( triggered() ), this, SLOT( showLocalUserVCard() ) );
1439
1440 /* Context Menu for user list view */
1441 QMenu* context_menu_users = new QMenu( "Menu", this );
1442 if( mp_actShowUserFullName->isChecked() )
1443 context_menu_users->addAction( mp_actShowUserFullName );
1444 context_menu_users->addAction( mp_actShowUserFirstNameFirstInFullName );
1445 context_menu_users->addSeparator();
1446 context_menu_users->addAction( mp_actVCard );
1447 context_menu_users->addAction( mp_actChangeStatusDescription );
1448 context_menu_users->addSeparator();
1449 context_menu_users->addAction( mp_actSetAutoAway );
1450 context_menu_users->addSeparator();
1451 context_menu_users->addAction( mp_actConfigureNetwork );
1452 context_menu_users->addAction( mp_actAddUsers );
1453 context_menu_users->addSeparator();
1454 context_menu_users->addAction( mp_actEditAvatarIconSize );
1455 context_menu_users->addSeparator();
1456 context_menu_users->addAction( mp_actShowOnlineUsersOnly );
1457 mp_userList->setContextMenuUsers( context_menu_users );
1458
1459 /* Help Menu */
1460 mp_menuInfo = new QMenu( tr("?" ), this );
1461 mp_menuInfo->addAction( IconManager::instance().icon( "donate.png" ), tr( "Donate for %1" ).arg( Settings::instance().programName() ) + QString( "..." ), this, SLOT( openDonationPage() ) );
1462 mp_menuInfo->addSeparator();
1463 mp_menuInfo->addAction( mp_actAbout );
1464 mp_menuInfo->addAction( IconManager::instance().icon( "license.png" ), tr( "Show %1's license..." ).arg( Settings::instance().programName() ), this, SLOT( showLicense() ) );
1465 act = mp_menuInfo->addAction( IconManager::instance().icon( "qt.png" ), tr( "Qt Library..." ), this, SLOT( showAboutQt() ) );
1466 act->setMenuRole( QAction::AboutQtRole );
1467 mp_menuInfo->addSeparator();
1468 mp_menuInfo->addAction( IconManager::instance().icon( "beebeep.png" ), tr( "Open %1 official website..." ).arg( Settings::instance().programName() ), this, SLOT( openWebSite() ) );
1469 mp_menuInfo->addAction( IconManager::instance().icon( "update.png" ), tr( "Check for new version..." ), this, SLOT( checkNewVersion() ) );
1470 mp_menuInfo->addAction( IconManager::instance().icon( "plugin.png" ), tr( "Download plugins..." ), this, SLOT( openDownloadPluginPage() ) );
1471 mp_menuInfo->addSeparator();
1472 mp_menuInfo->addAction( IconManager::instance().icon( "info.png" ), tr( "Help online..." ), this, SLOT( openHelpPage() ) );
1473 mp_menuInfo->addAction( IconManager::instance().icon( "tip.png" ), tr( "Show tips..." ), this, SLOT( showTipOfTheDay() ) );
1474 mp_menuInfo->addAction( IconManager::instance().icon( "chat-small.png" ), tr( "Read FAQ..." ), this, SLOT( showFaq() ) );
1475 mp_menuInfo->addAction( IconManager::instance().icon( "fact.png" ), tr( "Discover the fact of the day..." ), this, SLOT( showFactOfTheDay() ) );
1476 mp_menuInfo->addSeparator();
1477 mp_menuInfo->addAction( IconManager::instance().icon( "star.png" ), tr( "Information about %1..." ).arg( "Marco Mastroddi" ), this, SLOT( openDeveloperWebSite() ) );
1478 #ifdef BEEBEEP_DEBUG
1479 mp_menuInfo->addSeparator();
1480 act = mp_menuInfo->addAction( tr( "Add +1 user to anonymous usage statistics" ), this, SLOT( settingsChanged() ) );
1481 act->setCheckable( true );
1482 act->setChecked( Settings::instance().postUsageStatistics() );
1483 act->setData( 44 );
1484 #endif
1485
1486 /* Tray icon menu */
1487 mp_menuTrayIcon = new QMenu( this );
1488 act = mp_menuTrayIcon->addAction( IconManager::instance().icon( "beebeep.png" ), tr( "Show" ), this, SLOT( showUp() ) );
1489 mp_menuTrayIcon->setDefaultAction( act );
1490 mp_menuTrayIcon->addSeparator();
1491 mp_menuTrayIcon->addAction( mp_menuStatus->menuAction() );
1492 mp_menuTrayIcon->addSeparator();
1493 mp_menuTrayIcon->addAction( mp_actViewNewMessage );
1494 mp_menuTrayIcon->addSeparator();
1495 mp_menuTrayIcon->addAction( IconManager::instance().icon( "quit.png" ), tr( "Quit" ), this, SLOT( forceShutdown() ) );
1496
1497 mp_trayIcon->setContextMenu( mp_menuTrayIcon );
1498 }
1499
createToolAndMenuBars()1500 void GuiMain::createToolAndMenuBars()
1501 {
1502 menuBar()->addMenu( mp_menuMain );
1503 if( Settings::instance().disableMenuSettings() )
1504 mp_menuSettings->setDisabled( true );
1505 menuBar()->addMenu( mp_menuSettings );
1506 menuBar()->addMenu( mp_menuInfo );
1507 QLabel *label_version = new QLabel( this );
1508 label_version->setTextFormat( Qt::RichText );
1509 label_version->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
1510 QString label_version_text = QString( " <b>%1%2</b> %3 " )
1511 .arg( Settings::instance().version( Settings::instance().isDevelopmentVersion(), false, false ) )
1512 .arg( Settings::instance().isDevelopmentVersion() ? QString( "-dev" ) : "" )
1513 .arg( IconManager::instance().toHtml( Settings::instance().operatingSystemIconPath(), "*", 12, 12 ) );
1514 label_version->setText( label_version_text );
1515 label_version->setToolTip( QString( "BeeBEEP %1 %2%3" ).arg( Settings::instance().version( true, true, true ), Settings::instance().operatingSystem( true ),
1516 Settings::instance().isDevelopmentVersion() ? QString( " (%1)" ).arg( tr("Development version") ) : "" ) );
1517 menuBar()->setCornerWidget( label_version );
1518
1519 mp_barMain->addAction( mp_menuStatus->menuAction() );
1520 mp_barMain->addAction( mp_actVCard );
1521 mp_barMain->addSeparator();
1522 mp_barMain->addAction( mp_actBroadcast );
1523 mp_barMain->addSeparator();
1524 mp_barMain->addAction( mp_actViewNewMessage );
1525 mp_barMain->addAction( mp_actCreateMessage );
1526 mp_barMain->addAction( mp_actCreateGroupChat );
1527 mp_barMain->addSeparator();
1528 mp_barMain->addAction( mp_actViewFileTransfer );
1529 mp_barMain->addAction( mp_actViewFileSharing );
1530 }
1531
createMainWidgets()1532 void GuiMain::createMainWidgets()
1533 {
1534 int tab_index;
1535 QString tooltip_right_button = tr( "Right click to open menu" );
1536
1537 mp_home = new GuiHome( this );
1538 connect( mp_home, SIGNAL( openUrlRequest( const QUrl& ) ), this, SLOT( openUrl( const QUrl& ) ) );
1539 connect( mp_home, SIGNAL( clearSystemMessagesRequest( VNumber ) ), this, SLOT( clearSystemMessagesInChat( VNumber ) ) );
1540 tab_index = mp_tabMain->addTab( mp_home, IconManager::instance().icon( "activities.png" ), "" );
1541 mp_tabMain->setTabToolTip( tab_index, tr( "Activities" ) );
1542 mp_home->setMainToolTip( QString( "%1\n(%2)" ).arg( mp_tabMain->tabToolTip( tab_index ), tooltip_right_button ) );
1543
1544 mp_userList = new GuiUserList( this );
1545 tab_index = mp_tabMain->addTab( mp_userList, IconManager::instance().icon( "user-list.png" ), "" );
1546 mp_tabMain->setTabToolTip( tab_index, tr( "Users" ) );
1547 mp_userList->setMainToolTip( QString( "%1\n(%2)" ).arg( mp_tabMain->tabToolTip( tab_index ), tooltip_right_button ) );
1548
1549 mp_chatList = new GuiChatList( this );
1550 tab_index = mp_tabMain->addTab( mp_chatList, IconManager::instance().icon( "chat-list.png" ), "" );
1551 mp_tabMain->setTabToolTip( tab_index, tr( "Chats" ) );
1552 mp_chatList->setMainToolTip( QString( "%1\n(%2)" ).arg( mp_tabMain->tabToolTip( tab_index ), tooltip_right_button ) );
1553
1554 mp_groupList = new GuiGroupList( this );
1555 tab_index = mp_tabMain->addTab( mp_groupList, IconManager::instance().icon( "group.png" ), "" );
1556 mp_tabMain->setTabToolTip( tab_index, tr( "Groups" ) );
1557 mp_groupList->setMainToolTip( QString( "%1\n(%2)" ).arg( mp_tabMain->tabToolTip( tab_index ), tooltip_right_button ) );
1558
1559 mp_savedChatList = new GuiSavedChatList( this );
1560 tab_index = mp_tabMain->addTab( mp_savedChatList, IconManager::instance().icon( "saved-chat-list.png" ), "" );
1561 mp_tabMain->setTabToolTip( tab_index, tr( "Saved chats" ) );
1562 mp_savedChatList->setMainToolTip( QString( "%1\n(%2)" ).arg( mp_tabMain->tabToolTip( tab_index ), tooltip_right_button ) );
1563
1564 #ifdef BEEBEEP_USE_WEBENGINE
1565 mp_webView = new GuiWebView();
1566 connect( mp_webView, SIGNAL( newsLoadFinished( bool ) ), this, SLOT( onNewsLoad( bool ) ) );
1567 #endif
1568
1569 mp_dockFileTransfers = new QDockWidget( tr( "File Transfers" ), this );
1570 mp_dockFileTransfers->setObjectName( "GuiFileTransferDock" );
1571 mp_fileTransfer = new GuiFileTransfer( this );
1572 mp_dockFileTransfers->setWidget( mp_fileTransfer );
1573 mp_dockFileTransfers->setAllowedAreas( Qt::AllDockWidgetAreas );
1574 addDockWidget( Qt::BottomDockWidgetArea, mp_dockFileTransfers );
1575 mp_actViewFileTransfer = mp_dockFileTransfers->toggleViewAction();
1576 mp_actViewFileTransfer->setIcon( IconManager::instance().icon( "file-transfer.png" ) );
1577 mp_actViewFileTransfer->setText( tr( "Show the file transfer panel" ) );
1578 mp_actViewFileTransfer->setData( 99 );
1579 mp_dockFileTransfers->hide();
1580 }
1581
startExternalApplicationFromActionData()1582 void GuiMain::startExternalApplicationFromActionData()
1583 {
1584 QAction* act = qobject_cast<QAction*>( sender() );
1585 if( !act )
1586 return;
1587
1588 QString application_path = act->data().toString();
1589 qDebug() << "Starting external application:" << qPrintable( application_path );
1590 if( !QDesktopServices::openUrl( QUrl::fromLocalFile( application_path ) ) )
1591 QMessageBox::information( qApp->activeWindow(), Settings::instance().programName(), tr( "Unable to open %1" ).arg( application_path ), tr( "Ok" ) );
1592 }
1593
settingsChanged()1594 void GuiMain::settingsChanged()
1595 {
1596 QAction* act = qobject_cast<QAction*>( sender() );
1597 if( act )
1598 settingsChanged( act );
1599 }
1600
settingsChanged(QAction * act)1601 void GuiMain::settingsChanged( QAction* act )
1602 {
1603 bool refresh_users = false;
1604 bool refresh_chat = false;
1605 int settings_data_id = act->data().toInt();
1606 bool ok = false;
1607
1608 #ifdef BEEBEEP_DEBUG
1609 if( act->isCheckable() )
1610 qDebug() << "Settings changed for action id" << settings_data_id << "to" << static_cast<int>(act->isChecked());
1611 #endif
1612
1613 switch( settings_data_id )
1614 {
1615 case 1:
1616 Settings::instance().setChatCompact( act->isChecked() );
1617 refresh_chat = true;
1618 break;
1619 case 2:
1620 Settings::instance().setSaveGroupList( act->isChecked() );
1621 break;
1622 case 3:
1623 Settings::instance().setChatShowMessageTimestamp( act->isChecked() );
1624 refresh_chat = true;
1625 break;
1626 case 4:
1627 Settings::instance().setUseNativeDialogs( act->isChecked() );
1628 break;
1629 case 5:
1630 setFileSharingEnabled( act->isChecked() );
1631 break;
1632 case 6:
1633 Settings::instance().setShowOnlyOnlineUsers( act->isChecked() );
1634 refresh_users = true;
1635 refresh_chat = true;
1636 break;
1637 case 7:
1638 {
1639 Settings::instance().setShowChatsInOneWindow( act->isChecked() );
1640 if( Settings::instance().showChatsInOneWindow() )
1641 {
1642 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
1643 fl_chat->close();
1644 }
1645 }
1646 break;
1647 case 8:
1648 Settings::instance().setChatUseHtmlTags( act->isChecked() );
1649 refresh_chat = true;
1650 break;
1651 case 9:
1652 Settings::instance().setChatUseClickableLinks( act->isChecked() );
1653 refresh_chat = true;
1654 break;
1655 case 10:
1656 Settings::instance().setShowEmoticons( act->isChecked() );
1657 refresh_chat = true;
1658 break;
1659 case 11:
1660 Settings::instance().setCloseMinimizeInTray( act->isChecked() );
1661 break;
1662 case 12:
1663 setFileTransferEnabled( act->isChecked() );
1664 break;
1665 case 13:
1666 Settings::instance().setShowMessagesGroupByUser( act->isChecked() );
1667 refresh_chat = true;
1668 break;
1669 case 14:
1670 {
1671 Settings::instance().setStayOnTop( act->isChecked() );
1672 Bee::setWindowStaysOnTop( this, act->isChecked() );
1673 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
1674 Bee::setWindowStaysOnTop( fl_chat, act->isChecked() );
1675 if( mp_fileSharing )
1676 Bee::setWindowStaysOnTop( mp_fileSharing, act->isChecked() );
1677 if( mp_log )
1678 Bee::setWindowStaysOnTop( mp_log, act->isChecked() );
1679 if( mp_screenShot )
1680 Bee::setWindowStaysOnTop( mp_screenShot, act->isChecked() );
1681 if( mp_networkTest )
1682 Bee::setWindowStaysOnTop( mp_networkTest, act->isChecked() );
1683 }
1684 break;
1685 case 15:
1686 Settings::instance().setRaiseOnNewMessageArrived( act->isChecked() );
1687 break;
1688 case 16:
1689 checkAutoStartOnBoot( act->isChecked() );
1690 break;
1691 case 17:
1692 {
1693 if( !act->isChecked() )
1694 {
1695 Settings::instance().setAskPasswordAtStartup( false );
1696 if( Settings::instance().askPassword() )
1697 {
1698 QMessageBox::information( this, Settings::instance().programName(), tr( "Please save the network password in the next dialog if you want to use password without prompt." ) );
1699 promptConnectionPassword();
1700 return;
1701 }
1702 }
1703 else
1704 Settings::instance().setAskPasswordAtStartup( true );
1705 }
1706 break;
1707 case 18:
1708 {
1709 Settings::instance().setChatAutoSave( act->isChecked() );
1710 if( !Settings::instance().chatAutoSave() && (Settings::instance().chatSaveFileTransfers() || !Settings::instance().chatSaveSystemMessages()) )
1711 {
1712 if( QMessageBox::warning( this, Settings::instance().programName(),
1713 tr( "There will be no saving of 'system' and 'file transfer' messages if this option is disabled." ),
1714 tr( "Ok" ), tr( "Cancel" ), QString(), 0, 1 ) )
1715 {
1716 Settings::instance().setChatSaveFileTransfers( false );
1717 Settings::instance().setChatSaveSystemMessages( false );
1718 mp_actSaveFileTransferMessages->setChecked( false );
1719 mp_actSaveSystemMessages->setChecked( false );
1720 }
1721 }
1722 }
1723 break;
1724 case 19:
1725 Settings::instance().setShowNotificationOnTray( act->isChecked() );
1726 break;
1727 case 20:
1728 {
1729 Settings::instance().setAutoUserAway( act->isChecked() );
1730 if( act->isChecked() )
1731 {
1732 int away_timeout = QInputDialog::getInt( this, Settings::instance().programName(),
1733 tr( "How many minutes of idle %1 can wait before changing status to away?" ).arg( Settings::instance().programName() ),
1734 Settings::instance().userAwayTimeout(), 1, 30, 1, &ok );
1735 if( ok && away_timeout > 0 )
1736 Settings::instance().setUserAwayTimeout( away_timeout );
1737
1738 if( beeApp )
1739 beeApp->setIdleTimeout( Settings::instance().userAwayTimeout() );
1740 }
1741 }
1742 break;
1743 case 21:
1744 Settings::instance().setShowUserPhoto( act->isChecked() );
1745 refresh_users = true;
1746 break;
1747 case 23:
1748 {
1749 Settings::instance().setChatFont( QApplication::font() );
1750 updateChatFont();
1751 }
1752 break;
1753 case 24:
1754 Settings::instance().setLoadOnTrayAtStartup( act->isChecked() );
1755 break;
1756 case 25:
1757 Settings::instance().setShowVCardOnRightClick( act->isChecked() );
1758 break;
1759 case 26:
1760 {
1761 Settings::instance().setResetGeometryAtStartup( act->isChecked() );
1762 mp_actSaveWindowGeometry->setDisabled( Settings::instance().resetGeometryAtStartup() );
1763 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
1764 fl_chat->setSaveGeometryDisabled( Settings::instance().resetGeometryAtStartup() );
1765 }
1766 break;
1767 case 27:
1768 {
1769 #if QT_VERSION >= 0x050000
1770 int num_messages = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
1771 #else
1772 int num_messages = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
1773 #endif
1774 tr( "Please select the maximum number of messages to be showed" ) + QString( "\n" )
1775 + tr( "(current: %1, default: %2, all: -1, none: 0)" )
1776 .arg( Settings::instance().chatMessagesToShow() )
1777 .arg( Settings::instance().defaultChatMessagesToShow() ),
1778 Settings::instance().chatMessagesToShow(),
1779 -1, 2000, 10, &ok );
1780 if( ok )
1781 {
1782 Settings::instance().setChatMessagesToShow( num_messages );
1783 refresh_chat = true;
1784 }
1785 setChatMessagesToShowInAction( act );
1786 }
1787 break;
1788 case 28:
1789 {
1790 Settings::instance().setEnableMaximizeButton( act->isChecked() );
1791 if( Settings::instance().enableMaximizeButton() )
1792 setWindowFlags( windowFlags() | Qt::WindowMaximizeButtonHint );
1793 else
1794 setWindowFlags( windowFlags() & ~Qt::WindowMaximizeButtonHint );
1795 if( !isVisible() )
1796 show();
1797 }
1798 break;
1799 case 29:
1800 Settings::instance().setKeyEscapeMinimizeInTray( act->isChecked() );
1801 break;
1802 case 30:
1803 Settings::instance().setConfirmOnDownloadFile( act->isChecked() );
1804 break;
1805 case 31:
1806 Settings::instance().setUseFontEmoticons( act->isChecked() );
1807 mp_actSelectEmoticonSourcePath->setEnabled( !act->isChecked() );
1808 updateEmoticons();
1809 refresh_chat = true;
1810 break;
1811 case 32:
1812 Settings::instance().setSaveUserList( act->isChecked() );
1813 mp_actRemoveInactiveUsers->setEnabled( act->isChecked() );
1814 break;
1815 case 33:
1816 {
1817 Settings::instance().setRemoveInactiveUsers( act->isChecked() );
1818 if( act->isChecked() )
1819 {
1820 #if QT_VERSION >= 0x050000
1821 int num_days = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
1822 #else
1823 int num_days = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
1824 #endif
1825 tr( "Please select the number of inactive days before user is removed" ),
1826 Settings::instance().maxDaysOfUserInactivity(),
1827 2, 365, 5, &ok );
1828 if( ok )
1829 {
1830 Settings::instance().setMaxDaysOfUserInactivity( num_days );
1831 setMaxInactivityDaysInAction( act );
1832 }
1833 }
1834 }
1835 break;
1836 case 34:
1837 Settings::instance().setBeepOnNewMessageArrived( act->isChecked() );
1838 break;
1839 case 35:
1840 Settings::instance().setShowMinimizedAtStartup( act->isChecked() );
1841 break;
1842 case 36:
1843 Settings::instance().setPromptOnCloseEvent( act->isChecked() );
1844 break;
1845 case 37:
1846 Settings::instance().setShowUserStatusDescription( act->isChecked() );
1847 refresh_users = true;
1848 break;
1849 case 38:
1850 Settings::instance().setShowUserStatusBackgroundColor( act->isChecked() );
1851 refresh_users = true;
1852 break;
1853 case 39:
1854 Settings::instance().setUseShortcuts( act->isChecked() );
1855 break;
1856 case 40:
1857 Settings::instance().setShowOnlyMessageNotificationOnTray( act->isChecked() );
1858 break;
1859 case 41:
1860 Settings::instance().setChatUseYourNameInsteadOfYou( act->isChecked() );
1861 refresh_chat = true;
1862 break;
1863 case 42:
1864 {
1865 Settings::instance().setShowChatToolbar( act->isChecked() );
1866 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
1867 fl_chat->setChatToolbarVisible( Settings::instance().showChatToolbar() );
1868 }
1869 break;
1870 case 43:
1871 Settings::instance().setCheckNewVersionAtStartup( act->isChecked() );
1872 break;
1873 case 44:
1874 Settings::instance().setPostUsageStatistics( act->isChecked() );
1875 break;
1876 case 45:
1877 Settings::instance().setAskChangeUserAtStartup( act->isChecked() );
1878 break;
1879 case 46:
1880 Settings::instance().setShowChatMessageOnTray( act->isChecked() );
1881 break;
1882 case 47:
1883 Settings::instance().setChatClearAllReadMessages( act->isChecked() );
1884 break;
1885 case 48:
1886 Settings::instance().setShowFileTransferCompletedOnTray( act->isChecked() );
1887 break;
1888 case 49:
1889 Settings::instance().setSortUsersAscending( act->isChecked() );
1890 refresh_users = true;
1891 break;
1892 case 50:
1893 Settings::instance().setUserSortingMode( 0 );
1894 refresh_users = true;
1895 break;
1896 case 51:
1897 Settings::instance().setUserSortingMode( 1 );
1898 refresh_users = true;
1899 break;
1900 case 52:
1901 Settings::instance().setUserSortingMode( 2 );
1902 refresh_users = true;
1903 break;
1904 case 53:
1905 Settings::instance().setUserSortingMode( 3 );
1906 refresh_users = true;
1907 break;
1908 case 54:
1909 Settings::instance().setShowPresetMessages( act->isChecked() );
1910 break;
1911 case 55:
1912 Settings::instance().setShowTextInModeRTL( act->isChecked() );
1913 refresh_chat = true;
1914 break;
1915 case 56:
1916 Settings::instance().setPlayBuzzSound( act->isChecked() );
1917 break;
1918 case 57:
1919 Settings::instance().setUserRecognitionMethod( Settings::RecognizeByAccountAndDomain );
1920 showRestartConnectionAlertMessage();
1921 break;
1922 case 58:
1923 Settings::instance().setUserRecognitionMethod( Settings::RecognizeByAccount );
1924 showRestartConnectionAlertMessage();
1925
1926 break;
1927 case 59:
1928 Settings::instance().setUserRecognitionMethod( Settings::RecognizeByNickname );
1929 showRestartConnectionAlertMessage();
1930 break;
1931 #ifdef BEEBEEP_USE_SHAREDESKTOP
1932 case 60:
1933 {
1934 Settings::instance().setEnableShareDesktop( act->isChecked() );
1935 if( !act->isChecked() )
1936 {
1937 if( beeCore->shareDesktopIsActive( ID_INVALID ) )
1938 beeCore->stopShareDesktop();
1939 }
1940 }
1941 break;
1942 case 61:
1943 {
1944 int capture_delay = QInputDialog::getInt( this, Settings::instance().programName(), act->text() + QString( " (ms)" ),
1945 Settings::instance().shareDesktopCaptureDelay(), 1100, 8000, 300, &ok );
1946 if( ok )
1947 Settings::instance().setShareDesktopCaptureDelay( capture_delay );
1948 }
1949 break;
1950 case 62:
1951 {
1952 QString image_type = QInputDialog::getItem( this, Settings::instance().programName(),
1953 act->text() + QString( "\n(%1)" ).arg( tr( "jpg for photo, png for presentation" ) ),
1954 ImageOptimizer::instance().imageTypes(),
1955 qMax( 0, ImageOptimizer::instance().imageTypes().indexOf( Settings::instance().shareDesktopImageType() ) ),
1956 false, &ok );
1957 if( ok )
1958 Settings::instance().setShareDesktopImageType( image_type );
1959 }
1960 break;
1961 case 63:
1962 {
1963 int image_quality = QInputDialog::getInt( this, Settings::instance().programName(),
1964 act->text() + QString( "\n(%1)" ).arg( tr( "-1 default, 10 low, 60 medium, 100 high" ) ),
1965 Settings::instance().shareDesktopImageQuality(), -1, 100, 10, &ok );
1966 if( ok )
1967 Settings::instance().setShareDesktopImageQuality( image_quality );
1968 }
1969 break;
1970 case 64:
1971 Settings::instance().setShareDesktopFitToScreen( act->isChecked() );
1972 break;
1973 #endif
1974 case 65:
1975 {
1976 int delay_connection = QInputDialog::getInt( this, Settings::instance().programName(),
1977 act->text() + QString( "\n(%1)" ).arg( tr( "milliseconds, 5000 default" ) ),
1978 Settings::instance().delayConnectionAtStartup(), 3000, 60000, 1000, &ok );
1979 if( ok )
1980 Settings::instance().setDelayConnectionAtStartup( delay_connection );
1981 }
1982 break;
1983 case 66:
1984 Settings::instance().setSendOfflineMessagesToDefaultChat( act->isChecked() );
1985 break;
1986 case 67:
1987 Settings::instance().setChatUseColoredUserNames( act->isChecked() );
1988 refresh_chat = true;
1989 break;
1990 case 68:
1991 Settings::instance().setSaveGeometryOnExit( act->isChecked() );
1992 break;
1993 case 69:
1994 Settings::instance().setShowUsersOnConnection( act->isChecked() );
1995 break;
1996 case 70:
1997 Settings::instance().setAlwaysOpenChatOnNewMessageArrived( act->isChecked() );
1998 break;
1999 case 71:
2000 {
2001 #if QT_VERSION >= 0x050000
2002 int opacity_level = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2003 #else
2004 int opacity_level = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2005 #endif
2006 tr( "Please select the opacity percentage of inactive chat window (default: %1%)" ).arg( Settings::instance().chatInactiveWindowDefaultOpacityLevel() ),
2007 Settings::instance().chatInactiveWindowOpacityLevel(),
2008 10, 100, 5, &ok );
2009 if( ok )
2010 Settings::instance().setChatInactiveWindowOpacityLevel( opacity_level );
2011 setChatInactiveWindowOpacityLevelInAction( act );
2012 }
2013 break;
2014 case 72:
2015 {
2016 QColor c = QColorDialog::getColor( QColor( Settings::instance().chatBackgroundColor() ), this );
2017 if( c.isValid() )
2018 {
2019 Settings::instance().setChatBackgroundColor( c.name() );
2020 updateChatColors();
2021 }
2022 }
2023 break;
2024 case 73:
2025 {
2026 QColor c = QColorDialog::getColor( QColor( Settings::instance().chatDefaultTextColor() ), this );
2027 if( c.isValid() )
2028 {
2029 Settings::instance().setChatDefaultTextColor( c.name() );
2030 updateChatColors();
2031 }
2032 }
2033 break;
2034 case 74:
2035 {
2036 QColor c = QColorDialog::getColor( QColor( Settings::instance().chatSystemTextColor() ), this );
2037 if( c.isValid() )
2038 {
2039 Settings::instance().setChatSystemTextColor( c.name() );
2040 updateChatColors();
2041 QMessageBox::information( this, Settings::instance().programName(), tr( "You must close and reopen the chat windows to see the changes applied." ), tr( "Ok" ) );
2042 }
2043 }
2044 break;
2045 case 75:
2046 Settings::instance().setEnableDefaultChatNotifications( act->isChecked() );
2047 break;
2048 case 76:
2049 Settings::instance().setUseMessageTimestampWithAP( act->isChecked() );
2050 refresh_chat = true;
2051 break;
2052 case 77:
2053 {
2054 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you really want to apply the new theme?" ), tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 0 )
2055 {
2056 Settings::instance().setUseDarkStyle( act->isChecked() );
2057 Settings::instance().resetAllColors();
2058 QTimer::singleShot( 0, this, SLOT( loadStyle() ) );
2059 }
2060 }
2061 break;
2062 case 78:
2063 Settings::instance().setalwaysShowFileTransferProgress( act->isChecked() );
2064 break;
2065 case 79:
2066 Settings::instance().setShowChatsOnConnection( act->isChecked() );
2067 break;
2068 case 80:
2069 Settings::instance().setRaiseMainWindowOnNewMessageArrived( act->isChecked() );
2070 break;
2071 case 81:
2072 {
2073 Settings::instance().setChatSaveUnsentMessages( act->isChecked() );
2074 if( Settings::instance().chatSaveUnsentMessages() && (!Settings::instance().saveUserList() || !Settings::instance().saveGroupList()) )
2075 {
2076 if( QMessageBox::question( this, Settings::instance().programName(),
2077 tr( "Saving unsent messages may fail if 'Save users' and 'Save groups' options are not enabled. Do you want to enable them?" ),
2078 tr( "Yes" ), tr( "No" ), QString(), 0, 1 ) == 0 )
2079 {
2080 Settings::instance().setSaveUserList( true );
2081 Settings::instance().setSaveGroupList( true );
2082 mp_actSaveUserList->setChecked( true );
2083 mp_actSaveGroupList->setChecked( true );
2084 }
2085 }
2086 }
2087 break;
2088 case 82:
2089 Settings::instance().setChatSaveFileTransfers( act->isChecked() );
2090 showCheckSaveChatMessages();
2091 break;
2092 case 83:
2093 Settings::instance().setChatSaveSystemMessages( act->isChecked() );
2094 showCheckSaveChatMessages();
2095 break;
2096 case 84:
2097 {
2098 #if QT_VERSION >= 0x050000
2099 int save_max_lines = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2100 #else
2101 int save_max_lines = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2102 #endif
2103 tr( "Please select the maximum number of lines to be saved in the chat (current: %1)." ).arg( Settings::instance().chatMaxLineSaved() ),
2104 Settings::instance().chatMaxLineSaved(),
2105 100, 50000, 100, &ok );
2106 if( ok )
2107 Settings::instance().setChatMaxLineSaved( save_max_lines );
2108 setChatMaxLinesToSaveInAction( act );
2109 }
2110 break;
2111 case 85:
2112 {
2113 #if QT_VERSION >= 0x050000
2114 int cc_days = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2115 #else
2116 int cc_days = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2117 #endif
2118 tr( "Please select the number of days that items (such as images) can remain cached." ) +
2119 QString( "\n(%1)" ).arg( tr( "current: %1, never clear: -1, always clear: 0" ).arg( Settings::instance().clearCacheAfterDays() ) ),
2120 Settings::instance().clearCacheAfterDays(), -1, 999, 10, &ok );
2121 if( ok )
2122 {
2123 Settings::instance().setClearCacheAfterDays( cc_days );
2124 setClearCacheAfterDaysInAction( act );
2125 }
2126 }
2127 break;
2128 case 86:
2129 Settings::instance().setDownloadInUserFolder( act->isChecked() );
2130 break;
2131 case 87:
2132 Settings::instance().setShowUsersInWorkgroups( act->isChecked() );
2133 refresh_users = true;
2134 break;
2135 case 88:
2136 {
2137 #if QT_VERSION >= 0x050000
2138 int max_files_in_queue = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2139 #else
2140 int max_files_in_queue = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2141 #endif
2142 tr( "Please select the maximum number of files you can queue up for the transfer (current: %1)." ).arg( Settings::instance().maxQueuedDownloads() ),
2143 Settings::instance().maxQueuedDownloads(),
2144 1, 9999, 10, &ok );
2145 if( ok )
2146 {
2147 Settings::instance().setMaxQueuedDownloads( max_files_in_queue);
2148 setMaxQueuedDownloadsInAction( act );
2149 }
2150 }
2151 break;
2152 case 89:
2153 {
2154 QColor c = QColorDialog::getColor( QColor( Settings::instance().chatQuoteTextColor() ), this );
2155 if( c.isValid() )
2156 {
2157 Settings::instance().setChatQuoteTextColor( c.name() );
2158 refresh_chat = true;
2159 }
2160 }
2161 break;
2162 case 90:
2163 {
2164 QColor c = QColorDialog::getColor( QColor( Settings::instance().chatQuoteBackgroundColor() ), this );
2165 if( c.isValid() )
2166 {
2167 Settings::instance().setChatQuoteBackgroundColor( c.name() );
2168 refresh_chat = true;
2169 }
2170 }
2171 break;
2172 case 91:
2173 {
2174 Settings::instance().setChatOnSendingMessage( Settings::SkipOnSendingMessage );
2175 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
2176 fl_chat->guiChat()->updateOnSendingMessage();
2177 }
2178 break;
2179 case 92:
2180 {
2181 Settings::instance().setChatOnSendingMessage( Settings::MinimizeChatOnSendingMessage );
2182 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
2183 fl_chat->guiChat()->updateOnSendingMessage();
2184 }
2185 break;
2186 case 93:
2187 {
2188 Settings::instance().setChatOnSendingMessage( Settings::CloseChatOnSendingMessage );
2189 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
2190 fl_chat->guiChat()->updateOnSendingMessage();
2191 }
2192 break;
2193 case 94:
2194 {
2195 #if QT_VERSION >= 0x050000
2196 int max_duration = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2197 #else
2198 int max_duration = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2199 #endif
2200 tr( "Please select the maximum duration (in seconds) that a voice message can have (current: %1)." ).arg( Settings::instance().voiceMessageMaxDuration() ),
2201 Settings::instance().voiceMessageMaxDuration(),
2202 10, 900, 10, &ok );
2203 if( ok )
2204 Settings::instance().setVoiceMessageMaxDuration( max_duration );
2205 }
2206 break;
2207 case 95:
2208 Settings::instance().setUseVoicePlayer( act->isChecked() );
2209 break;
2210 case 96:
2211 Settings::instance().setDisableBeepInUserStatusBusy( act->isChecked() );
2212 break;
2213 case 97:
2214 Settings::instance().setResumeFileTransfer( act->isChecked() );
2215 break;
2216 case 98:
2217 Settings::instance().setBeepInActiveWindowAlso( act->isChecked() );
2218 break;
2219 case 99:
2220 break;
2221 case 100:
2222 {
2223 #if QT_VERSION >= 0x050000
2224 int cc_days = QInputDialog::getInt( qApp->activeWindow(), Settings::instance().programName(),
2225 #else
2226 int cc_days = QInputDialog::getInteger( qApp->activeWindow(), Settings::instance().programName(),
2227 #endif
2228 tr( "Please select the number of days that partially downloaded files can remain cached." ) +
2229 QString( "\n(%1)" ).arg( tr( "current: %1, never clear: -1, always clear: 0" ).arg( Settings::instance().removePartiallyDownloadedFilesAfterDays() ) ),
2230 Settings::instance().removePartiallyDownloadedFilesAfterDays(), -1, 999, 10, &ok );
2231 if( ok )
2232 {
2233 Settings::instance().setRemovePartiallyDownloadedFilesAfterDays( cc_days );
2234 setClearPartiallyDownloadedFilesAfterDaysInAction( act );
2235 }
2236 }
2237 break;
2238 case 101:
2239 Settings::instance().setKeepModificationDateOnFileTransferred( act->isChecked() );
2240 break;
2241 case 102:
2242 Settings::instance().setUseUserFirstNameFirstInFullName( !act->isChecked() );
2243 break;
2244 case 103:
2245 Settings::instance().setResetMinimumWidthForStyle( act->isChecked() );
2246 setMinimumWidthForStyle();
2247 break;
2248 case 104:
2249 EmoticonManager::instance().clearRecentEmoticons();
2250 updateEmoticons();
2251 break;
2252 case 105:
2253 Settings::instance().setUseHiResEmoticons( act->isChecked() );
2254 updateEmoticons();
2255 break;
2256 case 106:
2257 EmoticonManager::instance().clearFavoriteEmoticons();
2258 updateEmoticons();
2259 break;
2260 default:
2261 qWarning() << "GuiMain::settingsChanged(): error in setting id" << act->data().toInt();
2262 }
2263
2264 if( refresh_users )
2265 mp_userList->updateUsers();
2266
2267 if( refresh_chat )
2268 {
2269 QApplication::setOverrideCursor( Qt::WaitCursor );
2270 QApplication::processEvents();
2271 mp_chatList->updateChats();
2272 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
2273 {
2274 Chat c = ChatManager::instance().chat( fl_chat->guiChat()->chatId() );
2275 if( c.isValid() )
2276 fl_chat->setChat( c );
2277 }
2278 QApplication::restoreOverrideCursor();
2279 }
2280
2281 if( settings_data_id > 0 && settings_data_id != 99 )
2282 {
2283 if( act->isCheckable() )
2284 {
2285 QApplication::processEvents(); // Menu is closing and status bar will be reset -> force events to display next messages
2286 if( act->isChecked() )
2287 showMessage( tr( "Option enabled." ), 3000 );
2288 else
2289 showMessage( tr( "Option disabled." ), 3000 );
2290 }
2291 Settings::instance().save();
2292 }
2293 }
2294
showCheckSaveChatMessages()2295 void GuiMain::showCheckSaveChatMessages()
2296 {
2297 if( !Settings::instance().chatAutoSave() && (Settings::instance().chatSaveFileTransfers() || !Settings::instance().chatSaveSystemMessages()) )
2298 {
2299 if( QMessageBox::warning( this, Settings::instance().programName(),
2300 tr( "There will be no saving of 'system' and 'file transfer' messages if this option is disabled." ),
2301 tr( "Ok" ), tr( "Cancel" ), QString(), 0, 1 ) )
2302 {
2303 Settings::instance().setChatSaveFileTransfers( false );
2304 Settings::instance().setChatSaveSystemMessages( false );
2305 mp_actSaveFileTransferMessages->setChecked( false );
2306 mp_actSaveSystemMessages->setChecked( false );
2307 }
2308 }
2309 }
2310
setChatMessagesToShowInAction(QAction * act)2311 void GuiMain::setChatMessagesToShowInAction( QAction* act )
2312 {
2313 act->setText( tr( "Show only last %1 messages" ).arg( Settings::instance().chatMessagesToShow() >= 0 ? Settings::instance().chatMessagesToShow() : 800 ) );
2314 act->setChecked( Settings::instance().chatMessagesToShow() >= 0 );
2315 }
2316
setMaxInactivityDaysInAction(QAction * act)2317 void GuiMain::setMaxInactivityDaysInAction( QAction* act )
2318 {
2319 act->setText( tr( "Remove users after %1 days of inactivity" ).arg( Settings::instance().maxDaysOfUserInactivity() ) );
2320 act->setEnabled( Settings::instance().saveUserList() );
2321 }
2322
setChatInactiveWindowOpacityLevelInAction(QAction * act)2323 void GuiMain::setChatInactiveWindowOpacityLevelInAction( QAction* act )
2324 {
2325 act->setChecked( Settings::instance().chatInactiveWindowOpacityLevel() < 100 );
2326 act->setText( tr( "Show inactive chat window with %1% opacity" ).arg( Settings::instance().chatInactiveWindowOpacityLevel() ) );
2327 }
2328
setChatMaxLinesToSaveInAction(QAction * act)2329 void GuiMain::setChatMaxLinesToSaveInAction( QAction* act )
2330 {
2331 act->setText( tr( "Save maximum %1 lines of chat" ).arg( Settings::instance().chatMaxLineSaved() ) );
2332 act->setEnabled( Settings::instance().chatAutoSave() );
2333 act->setChecked( Settings::instance().chatMaxLineSaved() > 0 );
2334 }
2335
setClearCacheAfterDaysInAction(QAction * act)2336 void GuiMain::setClearCacheAfterDaysInAction( QAction* act )
2337 {
2338 act->setText( tr( "Clean the cache from items older than %1 days" ).arg( Settings::instance().clearCacheAfterDays() >= 0 ? Settings::instance().clearCacheAfterDays() : 96 ) );
2339 act->setEnabled( Settings::instance().chatAutoSave() );
2340 act->setChecked( Settings::instance().clearCacheAfterDays() >= 0 );
2341 }
2342
setClearPartiallyDownloadedFilesAfterDaysInAction(QAction * act)2343 void GuiMain::setClearPartiallyDownloadedFilesAfterDaysInAction( QAction* act )
2344 {
2345 act->setText( tr( "Delete partially downloaded files after %1 days" ).arg( Settings::instance().removePartiallyDownloadedFilesAfterDays() >= 0 ? Settings::instance().removePartiallyDownloadedFilesAfterDays() : 5 ) );
2346 act->setChecked( Settings::instance().removePartiallyDownloadedFilesAfterDays() >= 0 );
2347 }
2348
setMaxQueuedDownloadsInAction(QAction * act)2349 void GuiMain::setMaxQueuedDownloadsInAction( QAction* act )
2350 {
2351 act->setText( tr( "Add up to %1 files to the transfer queue" ).arg( Settings::instance().maxQueuedDownloads() ) );
2352 act->setChecked( Settings::instance().maxQueuedDownloads() > 0 );
2353 }
2354
sendMessage(VNumber chat_id,const QString & msg)2355 void GuiMain::sendMessage( VNumber chat_id, const QString& msg )
2356 {
2357 #ifdef BEEBEEP_DEBUG
2358 int num_messages = beeCore->sendChatMessage( chat_id, msg, false );
2359 qDebug() << num_messages << "messages sent";
2360 #else
2361 beeCore->sendChatMessage( chat_id, msg, false );
2362 #endif
2363 mp_chatList->updateChat( ChatManager::instance().chat( chat_id ) ); // to sort the chats
2364 }
2365
showAlertForMessage(const Chat & c,const ChatMessage & cm)2366 void GuiMain::showAlertForMessage( const Chat& c, const ChatMessage& cm )
2367 {
2368 if( cm.isImportant() )
2369 {
2370 playBuzz();
2371 }
2372 else
2373 {
2374 if( Settings::instance().beepOnNewMessageArrived() &&
2375 !(Settings::instance().localUser().status() == User::Busy && Settings::instance().disableBeepInUserStatusBusy()) )
2376 {
2377 playBeep();
2378 }
2379 }
2380
2381 bool show_message_in_tray = true;
2382
2383 GuiFloatingChat* fl_chat = floatingChat( c.id() );
2384 if( fl_chat )
2385 {
2386 fl_chat->setMainIcon( true );
2387 QApplication::alert( fl_chat, 0 );
2388 if( Settings::instance().raiseOnNewMessageArrived() || cm.isImportant() )
2389 {
2390 fl_chat->raiseOnTop();
2391 show_message_in_tray = false;
2392 }
2393 }
2394
2395 if( Settings::instance().raiseMainWindowOnNewMessageArrived() )
2396 raiseOnTop();
2397
2398 if( show_message_in_tray )
2399 {
2400 User u = UserManager::instance().findUser( cm.userId() );
2401 QString msg;
2402 bool long_time_show = false;
2403
2404 if( u.isValid() )
2405 {
2406 if( Settings::instance().showChatMessageOnTray() )
2407 {
2408 QString txt = Bee::removeHtmlTags( cm.message() );
2409 if( txt.size() > Settings::instance().textSizeInChatMessagePreviewOnTray() )
2410 {
2411 txt.truncate( Settings::instance().textSizeInChatMessagePreviewOnTray() );
2412 txt.append( "..." );
2413 }
2414
2415 if( c.isDefault() )
2416 msg = QString( "%1 %2: %3" ).arg( u.name(), tr( "to all" ), txt );
2417 else if( c.isGroup() )
2418 msg = QString( "%1 %2 %3: %4" ).arg( u.name(), tr( "to" ), c.name(), txt );
2419 else
2420 msg = QString( "%1 %2: %4" ).arg( u.name(), tr( "to you" ), txt );
2421
2422 long_time_show = true;
2423 }
2424 else
2425 {
2426 QString pre_msg = tr( "New message from" );
2427 if( c.isDefault() )
2428 msg = QString( "%1 %2 %3" ).arg( pre_msg, u.name(), tr( "to all" ) );
2429 else if( c.isGroup() )
2430 msg = QString( "%1 %2 %3 %4" ).arg( pre_msg, u.name(), tr( "to" ), c.name() );
2431 else
2432 msg = QString( "%1 %2 %3" ).arg( pre_msg, u.name(), tr( "to you" ) );
2433 }
2434 }
2435 else
2436 msg = tr( "New message arrived" );
2437
2438 mp_trayIcon->showNewMessageArrived( c.id(), msg, long_time_show );
2439 }
2440 }
2441
onNewChatMessage(const Chat & c,const ChatMessage & cm)2442 void GuiMain::onNewChatMessage( const Chat& c, const ChatMessage& cm )
2443 {
2444 if( !c.isValid() )
2445 {
2446 qWarning() << "Invalid chat" << c.name() << "found in GuiMain::onNewChatMessage(...)";
2447 return;
2448 }
2449
2450 if( c.isDefault() )
2451 {
2452 if( mp_home->addSystemMessage( cm ) && mp_tabMain->currentWidget() != mp_home )
2453 {
2454 m_unreadActivities++;
2455 updateTabTitles();
2456 }
2457 }
2458
2459 bool floating_chat_created = false;
2460 bool alert_can_be_notified = false;
2461
2462 if( c.isDefault() )
2463 alert_can_be_notified = cm.alertCanBeSent() && Settings::instance().enableDefaultChatNotifications();
2464 else if( c.isGroup() )
2465 alert_can_be_notified = cm.alertCanBeSent() && !Settings::instance().isNotificationDisabledForGroup( c.privateId() );
2466 else
2467 alert_can_be_notified = cm.alertCanBeSent();
2468
2469 GuiFloatingChat* fl_chat = floatingChat( c.id() );
2470
2471 if( !fl_chat && Settings::instance().alwaysOpenChatOnNewMessageArrived() && alert_can_be_notified )
2472 {
2473 fl_chat = createFloatingChat( c );
2474 floating_chat_created = true;
2475 fl_chat->show();
2476 fl_chat->guiChat()->ensureLastMessageVisible();
2477 if( !Settings::instance().raiseOnNewMessageArrived() && !cm.isImportant() )
2478 fl_chat->showMinimized();
2479 }
2480
2481 if( fl_chat && !floating_chat_created )
2482 fl_chat->showChatMessage( c, cm );
2483
2484 if( fl_chat && fl_chat->isActiveWindow() )
2485 {
2486 if( alert_can_be_notified && (cm.isImportant() || Settings::instance().beepInActiveWindowAlso()) )
2487 playBeep();
2488 readAllMessagesInChat( c.id() );
2489 }
2490 else
2491 {
2492 if( alert_can_be_notified )
2493 showAlertForMessage( c, cm );
2494 }
2495 }
2496
updateUser(const User & u)2497 void GuiMain::updateUser( const User& u )
2498 {
2499 mp_userList->setUser( u, false );
2500 mp_chatList->updateUser( u );
2501 mp_groupList->updateUser( u );
2502 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
2503 fl_chat->updateUser( u );
2504 mp_fileTransfer->updateUser( u );
2505 }
2506
searchUsers()2507 void GuiMain::searchUsers()
2508 {
2509 GuiNetwork gn( this );
2510 gn.setModal( true );
2511 gn.loadSettings();
2512 gn.setSizeGripEnabled( true );
2513 gn.show();
2514
2515 if( gn.exec() != QDialog::Accepted )
2516 return;
2517
2518 if( gn.restartConnection() )
2519 {
2520 showRestartConnectionAlertMessage();
2521 return;
2522 }
2523
2524 if( !beeCore->isConnected() )
2525 return;
2526
2527 #ifdef BEEBEEP_USE_MULTICAST_DNS
2528 if( Settings::instance().useMulticastDns() )
2529 beeCore->startDnsMulticasting();
2530 else
2531 beeCore->stopDnsMulticasting();
2532 #endif
2533
2534 QMetaObject::invokeMethod( this, "sendBroadcastMessage", Qt::QueuedConnection );
2535 }
2536
showWritingUser(const User & u,VNumber chat_id)2537 void GuiMain::showWritingUser( const User& u, VNumber chat_id )
2538 {
2539 QString msg = tr( "%1 is writing..." ).arg( u.name() );
2540 GuiFloatingChat* fl_chat = floatingChat( chat_id );
2541 if( fl_chat )
2542 fl_chat->showStatusMessage( msg, Settings::instance().writingTimeout() );
2543 }
2544
setUserStatusSelected(int user_status)2545 void GuiMain::setUserStatusSelected( int user_status )
2546 {
2547 if( user_status == User::Offline )
2548 {
2549 if( beeCore->isConnected() )
2550 {
2551 if( !Settings::instance().promptOnCloseEvent() || QMessageBox::question( this, Settings::instance().programName(),
2552 tr( "Do you want to disconnect from %1 network?" ).arg( Settings::instance().programName() ),
2553 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 0 )
2554 {
2555 disconnectFromNetwork();
2556 return;
2557 }
2558 }
2559 updateStatusIcon();
2560 }
2561 else
2562 {
2563 if( beeCore->isConnected() )
2564 {
2565 beeCore->setLocalUserStatus( user_status );
2566 }
2567 else
2568 {
2569 Settings::instance().setLocalUserStatus( static_cast<User::Status>(user_status) );
2570 startCore();
2571 }
2572 }
2573 }
2574
statusSelected()2575 void GuiMain::statusSelected()
2576 {
2577 QAction* act = qobject_cast<QAction*>( sender() );
2578 if( !act )
2579 return;
2580
2581 int user_status = act->data().toInt();
2582 setUserStatusSelected( user_status );
2583 }
2584
updateStatusIcon()2585 void GuiMain::updateStatusIcon()
2586 {
2587 int status_type;
2588 if( !beeCore->isConnected() )
2589 status_type = User::Offline;
2590 else
2591 status_type = Settings::instance().localUser().status();
2592
2593 mp_menuStatus->setIcon( Bee::avatarForUser( Settings::instance().localUser(), Settings::instance().avatarIconSize(), true ) );
2594 QString tip = tr( "You are %1%2" ).arg( Bee::userStatusToString( status_type ) )
2595 .arg( (Settings::instance().localUser().statusDescription().isEmpty() ? QString( "" ) : QString( ": %1" ).arg( Settings::instance().localUser().statusDescription() ) ) );
2596 QAction* act = mp_menuStatus->menuAction();
2597 act->setToolTip( tip );
2598 act->setText( Bee::capitalizeFirstLetter( Bee::userStatusToString( status_type ), true ) );
2599 updateWindowTitle();
2600 }
2601
changeStatusDescription()2602 void GuiMain::changeStatusDescription()
2603 {
2604 bool ok = false;
2605 QString status_description = QInputDialog::getText( this, Settings::instance().programName(),
2606 tr( "Please insert the new status description" ), QLineEdit::Normal, Settings::instance().localUser().statusDescription(), &ok );
2607 if( !ok || status_description.isNull() )
2608 return;
2609 beeCore->setLocalUserStatusDescription( Settings::instance().localUser().status(), status_description, true );
2610 loadUserStatusRecentlyUsed();
2611 updateStatusIcon();
2612 updateLocalStatusMessage();
2613 }
2614
sendFileFromChat(VNumber chat_id,const QString & file_path)2615 void GuiMain::sendFileFromChat( VNumber chat_id, const QString& file_path )
2616 {
2617 Chat c = ChatManager::instance().chat( chat_id );
2618 if( !c.isValid() )
2619 return;
2620
2621 if( c.isDefault() && !Settings::instance().chatWithAllUsersIsEnabled() )
2622 return;
2623
2624 QStringList files_path_selected = checkFilePath( file_path );
2625 if( files_path_selected.isEmpty() )
2626 return;
2627
2628 beeCore->sendFilesFromChat( c.id(), files_path_selected );
2629 }
2630
sendFilesFromChat(VNumber chat_id,const QStringList & file_path_list)2631 void GuiMain::sendFilesFromChat( VNumber chat_id, const QStringList& file_path_list )
2632 {
2633 Chat c = ChatManager::instance().chat( chat_id );
2634 if( !c.isValid() )
2635 return;
2636
2637 if( c.isDefault() && !Settings::instance().chatWithAllUsersIsEnabled() )
2638 return;
2639
2640 if( file_path_list.isEmpty() )
2641 return;
2642
2643 beeCore->sendFilesFromChat( c.id(), file_path_list );
2644 }
2645
sendFile(VNumber user_id)2646 void GuiMain::sendFile( VNumber user_id )
2647 {
2648 User u = UserManager::instance().findUser( user_id );
2649 QStringList files_path_selected = checkFilePath( "" );
2650 if( files_path_selected.isEmpty() )
2651 return;
2652 Chat c = ChatManager::instance().privateChatForUser( user_id );
2653 if( !c.isValid() )
2654 qWarning() << "Unable to send files to user" << user_id << "without a private chat in GuiMain::sendFile(...)";
2655 beeCore->sendFilesFromChat( c.id(), files_path_selected );
2656 }
2657
checkFilePath(const QString & file_path)2658 QStringList GuiMain::checkFilePath( const QString& file_path )
2659 {
2660 QStringList files_path_selected;
2661 if( file_path.isEmpty() || !QFile::exists( file_path ) )
2662 {
2663 files_path_selected = FileDialog::getOpenFileNames( true, activeWindow(), tr( "%1 - Select a file" ).arg( Settings::instance().programName() ) + QString( " %1" ).arg( tr( "or more" ) ),
2664 Settings::instance().lastDirectorySelected() );
2665 if( files_path_selected.isEmpty() )
2666 return files_path_selected;
2667
2668 Settings::instance().setLastDirectorySelectedFromFile( files_path_selected.last() );
2669 }
2670 else
2671 {
2672 files_path_selected.append( file_path );
2673 }
2674
2675 return files_path_selected;
2676 }
2677
sendFile(const User & u,const QString & file_path,VNumber chat_id)2678 bool GuiMain::sendFile( const User& u, const QString& file_path, VNumber chat_id )
2679 {
2680 if( !Settings::instance().enableFileTransfer() )
2681 {
2682 QMessageBox::information( activeWindow(), Settings::instance().programName(), tr( "File transfer is not enabled." ) );
2683 return false;
2684 }
2685
2686 if( !beeCore->isConnected() )
2687 {
2688 QMessageBox::information( activeWindow(), Settings::instance().programName(), tr( "You are not connected." ) );
2689 return false;
2690 }
2691
2692 User user_selected;
2693
2694 if( !u.isValid() )
2695 {
2696 QStringList user_string_list;
2697 foreach( User u, UserManager::instance().userList().toList() )
2698 {
2699 if( u.isStatusConnected() )
2700 user_string_list.append( u.path() );
2701 }
2702
2703 if( user_string_list.isEmpty() )
2704 {
2705 QMessageBox::information( activeWindow(), Settings::instance().programName(), tr( "There is no user connected." ) );
2706 return false;
2707 }
2708
2709 bool ok = false;
2710 QString user_path = QInputDialog::getItem( activeWindow(), Settings::instance().programName(),
2711 tr( "Please select the user to whom you would like to send a file."),
2712 user_string_list, 0, false, &ok );
2713 if( !ok )
2714 return false;
2715
2716 user_selected = UserManager::instance().findUserByPath( user_path );
2717
2718 if( !user_selected.isValid() )
2719 {
2720 QMessageBox::warning( activeWindow(), Settings::instance().programName(), tr( "User not found." ) );
2721 return false;
2722 }
2723
2724 Chat c = ChatManager::instance().privateChatForUser( user_selected.id() );
2725 chat_id = c.id();
2726 }
2727 else
2728 user_selected = u;
2729
2730 return beeCore->sendFile( user_selected.id(), file_path, "", false, chat_id );
2731 }
2732
sendFile(const QString & file_path)2733 void GuiMain::sendFile( const QString& file_path )
2734 {
2735 sendFile( User(), file_path, ID_INVALID );
2736 }
2737
askToDownloadFile(const User & u,const FileInfo & fi,const QString & download_path,bool make_questions)2738 bool GuiMain::askToDownloadFile( const User& u, const FileInfo& fi, const QString& download_path, bool make_questions )
2739 {
2740 if( !Settings::instance().enableFileTransfer() )
2741 {
2742 QMessageBox::warning( activeWindow(), Settings::instance().programName(), tr( "File transfer is disabled. You cannot download %1." ).arg( fi.name() ) );
2743 return false;
2744 }
2745
2746 int msg_result = make_questions ? 0 : 1;
2747
2748 if( msg_result == 0 )
2749 {
2750 if( Settings::instance().confirmOnDownloadFile() )
2751 {
2752 if( isMinimized() || !isActiveWindow() )
2753 {
2754 if( Settings::instance().raiseMainWindowOnNewMessageArrived() )
2755 raiseOnTop();
2756 mp_actViewNewMessage->setEnabled( true );
2757 }
2758 QString msg = tr( "Do you want to download %1 (%2) from %3?" ).arg( fi.name(), Bee::bytesToString( fi.size() ), Bee::userNameToShow( u, false ) );
2759 msg_result = QMessageBox::question( this, Settings::instance().programName(), msg, tr( "No" ), tr( "Yes" ), tr( "Yes, and don't ask anymore" ), 0, 0 );
2760 }
2761 else
2762 msg_result = 1;
2763 }
2764
2765 if( msg_result == 2 )
2766 {
2767 qDebug() << "Prompt on download file disabled by user request";
2768 Settings::instance().setConfirmOnDownloadFile( false );
2769 mp_actConfirmDownload->setChecked( false );
2770 }
2771
2772 if( msg_result > 0 )
2773 {
2774 QFileInfo qfile_info( download_path, fi.name() );
2775 qDebug() << "You accept to download" << fi.name() << "from" << qPrintable( u.path() );
2776 if( qfile_info.exists() && Settings::instance().onExistingFileAction() == Settings::GenerateNewFileName )
2777 {
2778 QString file_name = Bee::uniqueFilePath( qfile_info.absoluteFilePath(), true );
2779 qDebug() << "File" << qfile_info.absoluteFilePath() << "exists. Save it with new path (auto):" << qPrintable( file_name );
2780 qfile_info = QFileInfo( file_name );
2781 }
2782 FileInfo file_info = fi;
2783 file_info.setPath( qfile_info.absoluteFilePath() );
2784 return beeCore->downloadFile( u.id(), file_info, make_questions );
2785 }
2786 else
2787 {
2788 qDebug() << "You refuse to download" << fi.name() << "from" << u.path();
2789 return false;
2790 }
2791 }
2792
downloadFile(const User & u,const FileInfo & fi)2793 void GuiMain::downloadFile( const User& u, const FileInfo& fi )
2794 {
2795 if( !askToDownloadFile( u, fi, Settings::instance().downloadDirectoryForUser( u ), true ) )
2796 beeCore->refuseToDownloadFile( u.id(), fi );
2797 }
2798
downloadSharedFiles(const QList<SharedFileInfo> & share_file_info_list)2799 void GuiMain::downloadSharedFiles( const QList<SharedFileInfo>& share_file_info_list )
2800 {
2801 if( share_file_info_list.isEmpty() )
2802 return;
2803
2804 QString download_folder;
2805 User u;
2806 int files_to_download = 0;
2807
2808 if( share_file_info_list.size() > Settings::instance().maxQueuedDownloads() )
2809 {
2810 if( QMessageBox::question( activeWindow(), Settings::instance().programName(),
2811 tr( "You cannot download all these files at once. Do you want to download the first %1 files of the list?" )
2812 .arg( Settings::instance().maxQueuedDownloads() ),
2813 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
2814 return;
2815 }
2816 else if( share_file_info_list.size() > 100 )
2817 {
2818 if( QMessageBox::question( activeWindow(), Settings::instance().programName(),
2819 tr( "Downloading %1 files is a hard duty. Maybe you have to wait a lot of minutes. Do yo want to continue?" ).arg( share_file_info_list.size() ),
2820 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
2821 return;
2822 }
2823
2824 foreach( SharedFileInfo sfi, share_file_info_list )
2825 {
2826 u = UserManager::instance().findUser( sfi.first );
2827 download_folder = Bee::convertToNativeFolderSeparator( QString( "%1/%2" ).arg( Settings::instance().downloadDirectoryForUser( u ), sfi.second.shareFolder() ) );
2828 if( !askToDownloadFile( u, sfi.second, download_folder, false ) )
2829 return;
2830 files_to_download++;
2831 if( files_to_download > Settings::instance().maxQueuedDownloads() )
2832 break;
2833 }
2834
2835 showMessage( tr( "Downloading %1 files" ).arg( files_to_download ), 5000 );
2836 }
2837
downloadSharedFile(VNumber user_id,VNumber file_id)2838 void GuiMain::downloadSharedFile( VNumber user_id, VNumber file_id )
2839 {
2840 User u = UserManager::instance().findUser( user_id );
2841 FileInfo file_info = FileShare::instance().networkFileInfo( user_id, file_id );
2842
2843 if( u.isStatusConnected() && file_info.isValid() )
2844 {
2845 askToDownloadFile( u, file_info, Settings::instance().downloadDirectoryForUser( u ), true );
2846 return;
2847 }
2848
2849 qWarning() << "Unable to download shared file" << file_id << "from user" << user_id;
2850 QString info_msg = tr( "File is not available for download." );
2851 if( u.isValid() && !u.isStatusConnected() )
2852 info_msg += QLatin1String( "\n" ) + tr( "%1 is not connected." ).arg( u.name() );
2853 info_msg += QLatin1String( "\n" ) + tr( "Please reload the list of shared files." );
2854
2855 if( QMessageBox::information( activeWindow(), Settings::instance().programName(), info_msg,
2856 tr( "Reload file list" ), tr( "Cancel" ), QString(), 1, 1 ) == 0 )
2857 {
2858 if( mp_fileSharing )
2859 mp_fileSharing->updateNetworkFileList();
2860 }
2861 }
2862
downloadFolder(const User & u,const QString & folder_name,const QList<FileInfo> & file_info_list)2863 void GuiMain::downloadFolder( const User& u, const QString& folder_name, const QList<FileInfo>& file_info_list )
2864 {
2865 if( !Settings::instance().enableFileTransfer() )
2866 {
2867 QMessageBox::warning( activeWindow(), Settings::instance().programName(), tr( "File transfer is disabled. You cannot download %1." ).arg( folder_name ) );
2868 return;
2869 }
2870
2871 if( file_info_list.isEmpty() )
2872 {
2873 qWarning() << "Unable to download folder" << folder_name << "from user" << qPrintable( u.path() ) << "with empty file list";
2874 return;
2875 }
2876
2877 int msg_result = Settings::instance().confirmOnDownloadFile() ? 0 : 1;
2878
2879 if( msg_result == 0 )
2880 {
2881 QString msg = tr( "Do you want to download folder %1 (%2 files) from %3?" ).arg( folder_name ).arg( file_info_list.size() ).arg( u.name() );
2882 msg_result = QMessageBox::question( activeWindow(), Settings::instance().programName(), msg, tr( "No" ), tr( "Yes" ), tr( "Yes, and don't ask anymore" ), 0, 0 );
2883 }
2884
2885 if( msg_result == 2 )
2886 {
2887 Settings::instance().setConfirmOnDownloadFile( false );
2888 mp_actConfirmDownload->setChecked( false );
2889 }
2890
2891 if( msg_result > 0 )
2892 {
2893 // Accepted
2894 qDebug() << "You accept to download folder" << folder_name << "from" << u.path();
2895 QString download_folder;
2896 int files_to_download = 0;
2897 foreach( FileInfo fi, file_info_list )
2898 {
2899 download_folder = Bee::convertToNativeFolderSeparator( QString( "%1/%2" ).arg( Settings::instance().downloadDirectoryForUser( u ), fi.shareFolder() ) );
2900 if( !askToDownloadFile( u, fi, download_folder, false ) )
2901 return;
2902
2903 files_to_download++;
2904
2905 if( files_to_download > Settings::instance().maxQueuedDownloads() )
2906 {
2907 qWarning() << "Unable to download all the" << file_info_list.size() << "files because max queued reached" << Settings::instance().maxQueuedDownloads();
2908 break;
2909 }
2910 }
2911 }
2912 else
2913 {
2914 qDebug() << "You refuse to download folder" << folder_name << "from" << u.path();
2915 beeCore->refuseToDownloadFolder( u.id(), folder_name, file_info_list.first().chatPrivateId() );
2916 }
2917 }
2918
selectDownloadDirectory()2919 void GuiMain::selectDownloadDirectory()
2920 {
2921 QString download_directory_path = FileDialog::getExistingDirectory( activeWindow(),
2922 tr( "%1 - Select the download folder" )
2923 .arg( Settings::instance().programName() ),
2924 Settings::instance().downloadDirectory() );
2925 if( download_directory_path.isEmpty() )
2926 return;
2927
2928 Settings::instance().setDownloadDirectory( download_directory_path );
2929 QMessageBox::information( this, Settings::instance().programName(),
2930 QString( "%1<br>%2%3%4" ).arg( tr( "The files will be downloaded to the folder:" ) )
2931 .arg( download_directory_path )
2932 .arg( Bee::nativeFolderSeparator() )
2933 .arg( Settings::instance().downloadInUserFolder() ? Bee::convertToNativeFolderSeparator( QString( "<user's name>" ) ) : "" ),
2934 tr( "Ok" ) );
2935 }
2936
showTipOfTheDay()2937 void GuiMain::showTipOfTheDay()
2938 {
2939 openWebUrl( Settings::instance().tipsWebSite() );
2940 }
2941
showFactOfTheDay()2942 void GuiMain::showFactOfTheDay()
2943 {
2944 openWebUrl( Settings::instance().factWebSite() );
2945 }
2946
showFaq()2947 void GuiMain::showFaq()
2948 {
2949 openWebUrl( Settings::instance().faqWebSite() );
2950 }
2951
showChat(VNumber chat_id)2952 void GuiMain::showChat( VNumber chat_id )
2953 {
2954 Chat c = ChatManager::instance().chat( chat_id );
2955 if( !c.isValid() )
2956 {
2957 qWarning() << "Invalid chat" << chat_id << "found in GuiMain::showChat(...)";
2958 return;
2959 }
2960
2961 GuiFloatingChat* fl_chat = createFloatingChat( c );
2962 if( !fl_chat )
2963 return;
2964
2965 fl_chat->show();
2966 fl_chat->showUp();
2967 fl_chat->setFocusInChat();
2968 }
2969
changeVCard()2970 void GuiMain::changeVCard()
2971 {
2972 GuiEditVCard gvc;
2973 gvc.setModal( true );
2974 gvc.setUser( Settings::instance().localUser() );
2975 gvc.setSizeGripEnabled( true );
2976 gvc.show();
2977 if( gvc.exec() == QDialog::Accepted )
2978 {
2979 beeCore->setLocalUserVCard( gvc.userColor(), gvc.vCard() );
2980 if( gvc.regenerateUserHash() )
2981 {
2982 beeCore->regenerateLocalUserHash();
2983 QMessageBox::information( this, Settings::instance().programName(), tr( "You must restart %1 to apply these changes." ).arg( Settings::instance().programName() ) );
2984 }
2985 }
2986 }
2987
showLocalUserVCard()2988 void GuiMain::showLocalUserVCard()
2989 {
2990 showVCard( ID_LOCAL_USER );
2991 }
2992
showVCard(VNumber user_id)2993 void GuiMain::showVCard( VNumber user_id )
2994 {
2995 User u = UserManager::instance().findUser( user_id );
2996 if( !u.isValid() )
2997 return;
2998
2999 GuiVCard* gvc = new GuiVCard( this );
3000 connect( gvc, SIGNAL( showChat( VNumber ) ), this, SLOT( showChat( VNumber ) ) );
3001 connect( gvc, SIGNAL( sendFile( VNumber ) ), this, SLOT( sendFile( VNumber ) ) );
3002 connect( gvc, SIGNAL( changeUserColor( VNumber, const QString& ) ), this, SLOT( changeUserColor( VNumber, const QString& ) ) );
3003 connect( gvc, SIGNAL( toggleFavorite( VNumber ) ), this, SLOT( toggleUserFavorite( VNumber ) ) );
3004 connect( gvc, SIGNAL( removeUser( VNumber ) ), this, SLOT( removeUserFromList( VNumber ) ) );
3005 connect( gvc, SIGNAL( buzzUser( VNumber ) ), this, SLOT( sendBuzzToUser( VNumber ) ) );
3006 gvc->setVCard( u, ChatManager::instance().privateChatForUser( u.id() ).id(), beeCore->isConnected() );
3007
3008 QPoint cursor_pos = QCursor::pos();
3009 QRect screen_rect = qApp->desktop()->availableGeometry( cursor_pos );
3010 int diff_margin = cursor_pos.x() + gvc->size().width() - screen_rect.width();
3011 if( diff_margin > 0 )
3012 cursor_pos.setX( cursor_pos.x() - gvc->size().width() - 16 );
3013 diff_margin = cursor_pos.y() + gvc->size().height() - screen_rect.height();
3014 if( diff_margin > 0 )
3015 cursor_pos.setY( cursor_pos.y() - gvc->size().height() + 24 );
3016 gvc->move( cursor_pos );
3017 gvc->show();
3018 gvc->adjustSize();
3019 gvc->setFixedSize( gvc->size() );
3020 }
3021
updadePluginMenu()3022 void GuiMain::updadePluginMenu()
3023 {
3024 mp_menuPlugins->clear();
3025 QAction* act;
3026 mp_menuPlugins->addAction( IconManager::instance().icon( "plugin.png" ), tr( "Plugin Manager..." ), this, SLOT( showPluginManager() ) );
3027
3028 QString help_data_ts = tr( "is a plugin developed by" );
3029 QString help_data_format = QString( "<p>%1 <b>%2</b> %3 <b>%4</b>.<br><i>%5</i></p><br>" );
3030
3031 mp_menuPlugins->addAction( mp_actViewScreenShot );
3032
3033 bool copymastro_available = false;
3034 QString copy_mastro_path = "";
3035 #ifdef Q_OS_WIN
3036 copy_mastro_path = QString( "%1\\%2" ).arg( Settings::instance().pluginPath(), QString( "CopyMastro.exe" ) );
3037 copymastro_available = QFile::exists( copy_mastro_path );
3038 if( !copymastro_available )
3039 {
3040 copy_mastro_path = QString( "C:\\Program Files (x86)\\CopyMastro\\CopyMastro.exe" );
3041 copymastro_available = QFile::exists( copy_mastro_path );
3042 }
3043 #endif
3044
3045 if( copymastro_available )
3046 {
3047 qDebug() << "CopyMastro is found:" << qPrintable( copy_mastro_path );
3048 act = mp_menuPlugins->addAction( IconManager::instance().icon( "CopyMastro.png" ), "CopyMastro", this, SLOT( startExternalApplicationFromActionData() ) );
3049 act->setToolTip( tr( "Start the new application to copy file and folders by Marco Mastroddi" ) );
3050 act->setData( copy_mastro_path );
3051 }
3052
3053 if( PluginManager::instance().textMarkers().size() > 0 )
3054 {
3055 mp_menuPlugins->addSeparator();
3056
3057 foreach( TextMarkerInterface* text_marker, PluginManager::instance().textMarkers() )
3058 {
3059 act = mp_menuPlugins->addAction( text_marker->name(), this, SLOT( showPluginHelp() ) );
3060
3061 act->setData( help_data_format
3062 .arg( IconManager::instance().toHtml( (text_marker->icon().isNull() ? "images/plugin.png" : text_marker->iconFileName()), "*P*" ),
3063 text_marker->name(), help_data_ts, text_marker->author(), text_marker->help() ) );
3064 act->setIcon( text_marker->icon() );
3065 act->setEnabled( text_marker->isEnabled() );
3066 }
3067 }
3068 }
3069
showPluginHelp()3070 void GuiMain::showPluginHelp()
3071 {
3072 QAction* act = qobject_cast<QAction*>(sender());
3073 if( !act )
3074 return;
3075
3076 QMessageBox::information( this, act->text(), act->data().toString() );
3077 }
3078
showPluginManager()3079 void GuiMain::showPluginManager()
3080 {
3081 GuiPluginManager gpm;
3082 gpm.setModal( true );
3083 gpm.setSizeGripEnabled( true );
3084 gpm.updatePlugins();
3085 gpm.show();
3086 gpm.exec();
3087 if( gpm.isChanged() )
3088 updadePluginMenu();
3089 }
3090
showWizard()3091 bool GuiMain::showWizard()
3092 {
3093 GuiWizard gw( this );
3094 gw.setModal( true );
3095 gw.loadSettings();
3096 gw.show();
3097 gw.setFixedSize( gw.size() );
3098 if( gw.exec() == QDialog::Accepted )
3099 {
3100 if( !beeCore->changeLocalUser( gw.userName() ) )
3101 {
3102 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Your name is not changed. Do you want to continue?" ),
3103 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
3104 {
3105 return false;
3106 }
3107 }
3108 return true;
3109 }
3110 else
3111 return false;
3112 }
3113
hideToTrayIcon()3114 void GuiMain::hideToTrayIcon()
3115 {
3116 Chat c = ChatManager::instance().firstChatWithUnreadMessages();
3117 if( c.isValid() )
3118 mp_trayIcon->setUnreadMessages( c.id(), c.unreadMessages() );
3119 else
3120 mp_trayIcon->setUnreadMessages( ID_INVALID, 0 );
3121 hide();
3122 }
3123
trayIconClicked(QSystemTrayIcon::ActivationReason ar)3124 void GuiMain::trayIconClicked( QSystemTrayIcon::ActivationReason ar )
3125 {
3126 #ifdef Q_OS_MAC
3127
3128 // In Mac that is the expected behavior, there is no distinction
3129 // between left and right buttons for the systray icons.
3130 // They will always show the context menu, that's the Mac behavior.
3131 Q_UNUSED( ar );
3132
3133 #else
3134
3135 // Other OS
3136
3137 if( ar == QSystemTrayIcon::Context )
3138 {
3139 #ifdef BEEBEEP_DEBUG
3140 qDebug() << "TrayIcon is activated with context click and menu is showed";
3141 #endif
3142 return;
3143 }
3144
3145 if( ar == QSystemTrayIcon::Trigger )
3146 {
3147 if( !isActiveWindow() || isMinimized() )
3148 {
3149 #ifdef BEEBEEP_DEBUG
3150 qDebug() << "TrayIcon is activated with trigger click and main window will be showed";
3151 #endif
3152 QTimer::singleShot( 0, this, SLOT( raiseOnTop() ) );
3153 }
3154 else
3155 {
3156 #ifdef BEEBEEP_DEBUG
3157 qDebug() << "TrayIcon is activated with trigger click and menu will be showed";
3158 #endif
3159 mp_menuTrayIcon->popup( QCursor::pos() );
3160 }
3161 }
3162 else
3163 {
3164 #ifdef BEEBEEP_DEBUG
3165 qDebug() << "TrayIcon is activated with unknown click";
3166 #endif
3167 if( !mp_menuTrayIcon->isVisible() )
3168 mp_menuTrayIcon->popup( QCursor::pos() );
3169 }
3170 #endif
3171 }
3172
trayMessageClicked()3173 void GuiMain::trayMessageClicked()
3174 {
3175 // QT 2019-06-27: Currently this signal is not sent on macOS.
3176 if( mp_trayIcon->chatId() != ID_INVALID && ChatManager::instance().chat( mp_trayIcon->chatId() ).isValid() )
3177 {
3178 VNumber chat_id = mp_trayIcon->chatId();
3179 showChat( chat_id );
3180 GuiFloatingChat* fl_chat = floatingChat( chat_id );
3181 if( fl_chat && !fl_chat->chatIsVisible() )
3182 QTimer::singleShot( 0, fl_chat, SLOT( raiseOnTop() ) );
3183 }
3184 else
3185 QTimer::singleShot( 0, this, SLOT( raiseOnTop() ) );
3186 }
3187
addToShare(const QString & share_path)3188 void GuiMain::addToShare( const QString& share_path )
3189 {
3190 beeCore->addPathToShare( share_path );
3191 }
3192
removeFromShare(const QString & share_path)3193 void GuiMain::removeFromShare( const QString& share_path )
3194 {
3195 beeCore->removePathFromShare( share_path );
3196 }
3197
openUrl(const QUrl & file_url)3198 void GuiMain::openUrl( const QUrl& file_url )
3199 {
3200 openUrlFromChat( file_url, ID_INVALID );
3201 }
3202
openUrlFromChat(const QUrl & file_url,VNumber chat_id)3203 void GuiMain::openUrlFromChat( const QUrl& file_url, VNumber chat_id )
3204 {
3205 #ifdef BEEBEEP_DEBUG
3206 qDebug() << "Opening url (not encoded):" << qPrintable( file_url.toString() );
3207 #endif
3208
3209 if( file_url.scheme() == QLatin1String( "beeshowsavedchat" ) )
3210 {
3211 QStringList sl_chat_id = file_url.toString().split( "#" );
3212 if( !sl_chat_id.isEmpty() )
3213 {
3214 bool chat_id_is_integer = false;
3215 VNumber chat_id = sl_chat_id.last().toULongLong( &chat_id_is_integer );
3216 if( chat_id_is_integer && chat_id > 0 )
3217 {
3218 QString chat_name = ChatManager::instance().chatName( chat_id );
3219 if( ChatManager::instance().chatHasSavedText( chat_name ) )
3220 showSavedChatSelected( chat_name );
3221 else
3222 QMessageBox::information( QApplication::activeWindow(), Settings::instance().programName(),
3223 tr( "There are no messages saved in the chat with %1." ).arg( chat_name ), tr( "Ok" ) );
3224 }
3225 else
3226 qWarning() << "Invalid chat id" << chat_id << "found parsing open history request in GuiMain::openUrl(...)";
3227 }
3228 }
3229 else if( file_url.scheme() == FileInfo::urlSchemeShowFileInFolder() )
3230 {
3231 QUrl adj_file_url = file_url;
3232 adj_file_url.setScheme( QLatin1String( "file" ) );
3233 if( !Bee::showFileInGraphicalShell( Bee::convertToNativeFolderSeparator( adj_file_url.toLocalFile() ) ) )
3234 {
3235 QFileInfo file_info_url( adj_file_url.toLocalFile() );
3236 adj_file_url = QUrl::fromLocalFile( Bee::convertToNativeFolderSeparator( file_info_url.absoluteDir().absolutePath() ) );
3237 openUrlFromChat( adj_file_url, chat_id );
3238 return;
3239 }
3240 }
3241 else if( file_url.scheme() == FileInfo::urlSchemeVoiceMessage() )
3242 {
3243 QUrl adj_file_url = file_url;
3244 adj_file_url.setScheme( QLatin1String( "file" ) );
3245 #ifdef BEEBEEP_USE_VOICE_CHAT
3246 if( Settings::instance().useVoicePlayer() )
3247 {
3248 GuiFloatingChat* fl_chat = floatingChat( chat_id );
3249 if( fl_chat )
3250 fl_chat->guiChat()->guiVoicePlayer()->setFilePath( Bee::convertToNativeFolderSeparator( adj_file_url.toLocalFile() ), chat_id );
3251 }
3252 else
3253 #endif
3254 openUrlFromChat( adj_file_url, chat_id );
3255 }
3256 #if QT_VERSION >= 0x040800
3257 else if( file_url.isLocalFile() )
3258 #else
3259 else if( file_url.scheme() == QLatin1String( "file" ) )
3260 #endif
3261 {
3262 QString file_path = Bee::convertToNativeFolderSeparator( file_url.toLocalFile() );
3263 if( file_path.isEmpty() )
3264 {
3265 qWarning() << "Unable to open an empty file path";
3266 return;
3267 }
3268
3269 QFileInfo fi( file_path );
3270 if( !fi.exists() )
3271 {
3272 QMessageBox::information( qApp->activeWindow(), Settings::instance().programName(),
3273 tr( "%1: no such file or directory." ).arg( file_path.isEmpty() ? file_url.toString() : file_path ), tr( "Ok" ) );
3274 return;
3275 }
3276
3277 #ifdef Q_OS_MAC
3278 bool is_exe_file = fi.isBundle();
3279 #else
3280 bool is_exe_file = fi.isExecutable() && !fi.isDir();
3281 #endif
3282 if( is_exe_file && QMessageBox::question( qApp->activeWindow(), Settings::instance().programName(),
3283 tr( "Do you want to open the file %1?" ).arg( file_path ),
3284 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
3285 return;
3286
3287 qDebug() << "Open file:" << file_path;
3288 if( !QDesktopServices::openUrl( QUrl::fromLocalFile( file_path ) ) )
3289 QMessageBox::information( qApp->activeWindow(), Settings::instance().programName(),
3290 tr( "Unable to open %1" ).arg( file_path.isEmpty() ? file_url.toString() : file_path ), tr( "Ok" ) );
3291 }
3292 else
3293 {
3294 QString url_txt = file_url.toString();
3295 qDebug() << "Open url:" << url_txt;
3296 if( !QDesktopServices::openUrl( file_url ) )
3297 qWarning() << "Unable to open link url:" << url_txt;
3298 }
3299 }
3300
selectBeepFile()3301 void GuiMain::selectBeepFile()
3302 {
3303 QString file_path = FileDialog::getOpenFileName( false, this, Settings::instance().programName(), Settings::instance().beepFilePath(), tr( "Sound files (*.wav)" ) );
3304 if( file_path.isNull() || file_path.isEmpty() )
3305 return;
3306
3307 Settings::instance().setBeepFilePath( file_path );
3308 qDebug() << "New sound file selected:" << qPrintable( file_path );
3309
3310 AudioManager::instance().clearBeep();
3311 AudioManager::instance().playBeep();
3312
3313 if( !Settings::instance().beepOnNewMessageArrived() )
3314 {
3315 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Sound is not enabled on a new message. Do you want to enable it?" ), tr( "Yes" ), tr( "No" ) ) == 0 )
3316 {
3317 Settings::instance().setBeepOnNewMessageArrived( true );
3318 mp_actBeepOnNewMessage->setChecked( true );
3319 }
3320 }
3321 }
3322
testBeepFile()3323 void GuiMain::testBeepFile()
3324 {
3325 QString s_default_beep = tr( "The default BEEP will be used" );
3326 if( !AudioManager::instance().isAudioDeviceAvailable() )
3327 {
3328 qWarning() << "Sound device is not available";
3329 QMessageBox::warning( this, Settings::instance().programName(), QString( "%1. %2." ).arg( tr( "Sound module is not working" ), s_default_beep ) );
3330 }
3331 else if( !QFile::exists( Settings::instance().beepFilePath() ) )
3332 {
3333 QString warn_text = QString( "%1\n%2. %3." ).arg( Settings::instance().beepFilePath() )
3334 .arg( tr( "Sound file not found" ) )
3335 .arg( s_default_beep );
3336 QMessageBox::warning( this, Settings::instance().programName(), warn_text );
3337 }
3338
3339 playBeep();
3340 }
3341
playBeep()3342 void GuiMain::playBeep()
3343 {
3344 AudioManager::instance().playBeep();
3345 }
3346
playBuzz()3347 void GuiMain::playBuzz()
3348 {
3349 AudioManager::instance().playBuzz();
3350 }
3351
createGroupChat()3352 void GuiMain::createGroupChat()
3353 {
3354 if( !Settings::instance().canAddMembersToGroup() )
3355 {
3356 QMessageBox::information( this, Settings::instance().programName(),
3357 tr( "You are not allowed create groups." ) + QString( " " ) + tr( "The option has been disabled by your system administrator." ),
3358 tr( "Ok" ) );
3359 return;
3360 }
3361
3362 GuiCreateGroup gcg;
3363 gcg.loadData();
3364 gcg.setModal( true );
3365 gcg.show();
3366 gcg.setFixedSize( gcg.size() );
3367 if( gcg.exec() != QDialog::Accepted )
3368 return;
3369
3370 if( gcg.leaveGroup() )
3371 return;
3372
3373 Group g = gcg.group();
3374
3375 Chat c = ChatManager::instance().findGroupChatByUsers( g.usersId() );
3376 if( c.isValid() )
3377 {
3378 if( QMessageBox::question( this, Settings::instance().programName(),
3379 QString( "%1\n%2" ).arg( tr( "There is a chat with the same members: %1." ).arg( c.name() ) )
3380 .arg( "How do you want to continue?" ),
3381 tr( "Create new group chat" ), tr( "Cancel" ), QString(), 1, 1 ) == 1 )
3382 {
3383 return;
3384 }
3385 }
3386
3387 c = beeCore->createGroupChat( Settings::instance().localUser(), g, true );
3388 if( c.isValid() )
3389 showChat( c.id() );
3390 }
3391
editGroupChat(VNumber chat_id)3392 void GuiMain::editGroupChat( VNumber chat_id )
3393 {
3394 Chat c = ChatManager::instance().chat( chat_id );
3395 if( !c.isValid() )
3396 return;
3397
3398 if( !Settings::instance().canAddMembersToGroup() && !Settings::instance().canRemoveMembersFromGroup() )
3399 {
3400 QMessageBox::information( this, Settings::instance().programName(),
3401 tr( "You are not allowed modify groups." ) + QString( " " ) + tr( "The option has been disabled by your system administrator." ),
3402 tr( "Ok" ) );
3403 return;
3404 }
3405
3406 GuiCreateGroup gcg( activeWindow() );
3407 gcg.init( c.group() );
3408 gcg.loadData();
3409 gcg.setModal( true );
3410 gcg.show();
3411 gcg.setFixedSize( gcg.size() );
3412 if( gcg.exec() == QDialog::Accepted )
3413 {
3414 if( gcg.leaveGroup() )
3415 removeChat( chat_id );
3416 else
3417 beeCore->changeGroupChat( Settings::instance().localUser(), gcg.group() );
3418 }
3419 }
3420
checkAutoStartOnBoot(bool add_service)3421 void GuiMain::checkAutoStartOnBoot( bool add_service )
3422 {
3423 if( add_service )
3424 {
3425 if( Settings::instance().addStartOnSystemBoot() )
3426 {
3427 QString alert_message = tr( "Now %1 will start on windows boot." ).arg( Settings::instance().programName() );
3428 #ifdef Q_OS_WIN
3429 if( QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8_1 )
3430 alert_message += QString( "\n%1" ).arg( "Note: you have to disable the alert window for unsigned software." );
3431 #endif
3432 QMessageBox::information( this, Settings::instance().programName(), alert_message );
3433 }
3434 else
3435 QMessageBox::warning( this, Settings::instance().programName(), tr( "Unable to add this key in the registry: permission denied." ) );
3436 }
3437 else
3438 {
3439 if( Settings::instance().removeStartOnSystemBoot() )
3440 QMessageBox::information( this, Settings::instance().programName(), tr( "%1 will not start on windows boot." ).arg( Settings::instance().programName() ) );
3441 else
3442 QMessageBox::warning( this, Settings::instance().programName(), tr( "Unable to add this key in the registry: permission denied." ) );
3443 }
3444 }
3445
loadSession()3446 void GuiMain::loadSession()
3447 {
3448 showMessage( tr( "Starting" ), 3000 );
3449 mp_tabMain->setCurrentWidget( mp_home );
3450 mp_home->loadSystemMessages();
3451 QTimer::singleShot( 100, beeCore, SLOT( buildSavedChatList() ) );
3452
3453 QTimer::singleShot( Settings::instance().delayConnectionAtStartup(), this, SLOT( startCore() ) );
3454 if( Settings::instance().delayConnectionAtStartup() > 5000 )
3455 qDebug() << "Delay first connection for" << Settings::instance().delayConnectionAtStartup() << "ms";
3456 }
3457
showSavedChatSelected(const QString & chat_name)3458 void GuiMain::showSavedChatSelected( const QString& chat_name )
3459 {
3460 if( chat_name.isEmpty() )
3461 return;
3462
3463 foreach( QWidget* w, qApp->allWidgets() )
3464 {
3465 GuiSavedChat* gsv = qobject_cast<GuiSavedChat*>( w );
3466 if( gsv && gsv->savedChatName() == chat_name )
3467 {
3468 gsv->raise();
3469 return;
3470 }
3471 }
3472
3473 GuiSavedChat* saved_chat = new GuiSavedChat( this );
3474 saved_chat->setAttribute( Qt::WA_DeleteOnClose, true );
3475 saved_chat->resize( qMin( (QApplication::desktop()->availableGeometry().width()-80), 680 ), 420 );
3476 connect( saved_chat, SIGNAL( deleteSavedChatRequest( const QString& ) ), this, SLOT( removeSavedChat( const QString& ) ) );
3477 connect( saved_chat, SIGNAL( openUrl( const QUrl& ) ), this, SLOT( openUrl( const QUrl& ) ) );
3478 saved_chat->showSavedChat( chat_name );
3479 saved_chat->show();
3480 }
3481
removeSavedChat(const QString & chat_name)3482 void GuiMain::removeSavedChat( const QString& chat_name )
3483 {
3484 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you want to delete saved chat with %1?" ).arg( chat_name ), tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 1 )
3485 return;
3486
3487 foreach( QWidget* w, qApp->allWidgets() )
3488 {
3489 GuiSavedChat* gsv = qobject_cast<GuiSavedChat*>( w );
3490 if( gsv && gsv->savedChatName() == chat_name )
3491 {
3492 gsv->close();
3493 break;
3494 }
3495 }
3496 beeCore->removeSavedChat( chat_name );
3497 mp_savedChatList->updateSavedChats();
3498 updateTabTitles();
3499 }
3500
linkSavedChat(const QString & chat_name)3501 void GuiMain::linkSavedChat( const QString& chat_name )
3502 {
3503 bool ok = false;
3504 QStringList chat_names_string_list = ChatManager::instance().chatNamesToStringList( true );
3505 chat_names_string_list.removeOne( chat_name );
3506
3507 QString chat_name_selected = QInputDialog::getItem( this, Settings::instance().programName(),
3508 tr( "Please select a chat you would like to link the saved text."),
3509 chat_names_string_list, 0, false, &ok );
3510 if( !ok )
3511 return;
3512
3513 bool add_to_existing_saved_text = false;
3514 if( ChatManager::instance().chatHasSavedText( chat_name_selected ) )
3515 {
3516 switch( QMessageBox::question( this, Settings::instance().programName(),
3517 tr( "The chat '%1' selected has already a saved text.<br>"
3518 "What do you want to do with the selected saved text?" ).arg( chat_name_selected ),
3519 tr( "Overwrite" ), tr( "Add in the head" ), tr( "Cancel" ), 2, 2 ) )
3520 {
3521 case 0:
3522 break;
3523 case 1:
3524 add_to_existing_saved_text = true;
3525 break;
3526 default:
3527 return;
3528 }
3529
3530 }
3531
3532 beeCore->linkSavedChat( chat_name, chat_name_selected, add_to_existing_saved_text );
3533 }
3534
openWebUrl(const QString & web_url)3535 bool GuiMain::openWebUrl( const QString& web_url )
3536 {
3537 QUrl url( web_url );
3538
3539 if( !QDesktopServices::openUrl( url ) )
3540 {
3541 QMessageBox::information( this, Settings::instance().programName(), tr( "Unable to open %1" ).arg( web_url ), tr( "Ok" ) );
3542 return false;
3543 }
3544 else
3545 return true;
3546 }
3547
checkNewVersion()3548 void GuiMain::checkNewVersion()
3549 {
3550 QString url_and_arguments = Settings::instance().checkVersionWebSite();
3551 openWebUrl( url_and_arguments );
3552 }
3553
openWebSite()3554 void GuiMain::openWebSite()
3555 {
3556 openWebUrl( Settings::instance().officialWebSite() );
3557 }
3558
openDownloadPluginPage()3559 void GuiMain::openDownloadPluginPage()
3560 {
3561 openWebUrl( Settings::instance().pluginWebSite() );
3562 }
3563
openDonationPage()3564 void GuiMain::openDonationPage()
3565 {
3566 openWebUrl( Settings::instance().donationWebSite() );
3567 }
3568
openHelpPage()3569 void GuiMain::openHelpPage()
3570 {
3571 openWebUrl( Settings::instance().helpWebSite() );
3572 }
3573
openDeveloperWebSite()3574 void GuiMain::openDeveloperWebSite()
3575 {
3576 openWebUrl( Settings::instance().developerWebSite() );
3577 }
3578
setInIdle()3579 void GuiMain::setInIdle()
3580 {
3581 if( !beeCore->isConnected() )
3582 return;
3583
3584 if( !Settings::instance().autoUserAway() )
3585 return;
3586
3587 if( Settings::instance().localUser().status() == User::Away )
3588 return;
3589
3590 m_lastUserStatus = Settings::instance().localUser().status();
3591 beeCore->setLocalUserStatus( User::Away );
3592 updateStatusIcon();
3593 }
3594
exitFromIdle()3595 void GuiMain::exitFromIdle()
3596 {
3597 if( !beeCore->isConnected() )
3598 return;
3599
3600 if( !Settings::instance().autoUserAway() )
3601 return;
3602
3603 if( Settings::instance().localUser().status() != User::Away )
3604 return;
3605
3606 beeCore->setLocalUserStatus( m_lastUserStatus );
3607 updateStatusIcon();
3608 }
3609
updateLocalStatusMessage()3610 void GuiMain::updateLocalStatusMessage()
3611 {
3612 showMessage( Settings::instance().localUser().statusDescription(), 0 );
3613 }
3614
onStatusBarMessageChanged(const QString & msg)3615 void GuiMain::onStatusBarMessageChanged( const QString& msg )
3616 {
3617 if( msg.isNull() && !Settings::instance().localUser().statusDescription().isEmpty() )
3618 QTimer::singleShot( 0, this, SLOT( updateLocalStatusMessage() ) );
3619 }
3620
showMessage(const QString & status_msg,int time_out)3621 void GuiMain::showMessage( const QString& status_msg, int time_out )
3622 {
3623 statusBar()->showMessage( status_msg, time_out );
3624 if( status_msg == Settings::instance().localUser().statusDescription() )
3625 statusBar()->setToolTip( tr( "Your status description" ) );
3626 else
3627 statusBar()->setToolTip( "" );
3628 }
3629
changeUserColor(VNumber user_id,const QString & user_color)3630 void GuiMain::changeUserColor( VNumber user_id, const QString& user_color )
3631 {
3632 QColor c = QColorDialog::getColor( QColor( user_color ), qApp->activeWindow() );
3633 if( c.isValid() )
3634 beeCore->changeUserColor( user_id, c.name() );
3635 }
3636
onUserChanged(const User & u)3637 void GuiMain::onUserChanged( const User& u )
3638 {
3639 mp_userList->setUser( u, true );
3640 mp_groupList->updateUser( u );
3641 mp_chatList->updateUser( u );
3642 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
3643 fl_chat->updateUser( u );
3644 checkViewActions();
3645 if( u.isLocal() )
3646 {
3647 updateStatusIcon();
3648 updateWindowTitle();
3649 }
3650 else
3651 {
3652 if( m_changeTabToUserListOnFirstConnected && u.isStatusConnected() && mp_tabMain->currentWidget() == mp_home )
3653 {
3654 m_changeTabToUserListOnFirstConnected = false;
3655 mp_tabMain->setCurrentWidget( mp_userList );
3656 }
3657 }
3658 #ifdef BEEBEEP_USE_SHAREDESKTOP
3659 foreach( GuiShareDesktop* gsd, m_desktops )
3660 gsd->onUserChanged( u );
3661 #endif
3662 }
3663
onUserRemoved(const User & u)3664 void GuiMain::onUserRemoved( const User& u )
3665 {
3666 showMessage( tr( "%1 removed" ).arg( u.name() ), 2000 );
3667 mp_userList->updateUsers();
3668 updateTabTitles();
3669 }
3670
onChatChanged(const Chat & c)3671 void GuiMain::onChatChanged( const Chat& c )
3672 {
3673 #ifdef BEEBEEP_DEBUG
3674 showMessage( tr( "%1 updated" ).arg( c.name() ), 2000 );
3675 #endif
3676 mp_userList->updateChat( c );
3677 mp_chatList->updateChat( c );
3678 mp_groupList->updateChat( c );
3679 GuiFloatingChat* fl_chat = floatingChat( c.id() );
3680 if( fl_chat )
3681 fl_chat->updateChat( c );
3682 mp_savedChatList->updateSavedChats();
3683 updateTabTitles();
3684 updateNewMessageAction();
3685 }
3686
onChatRemoved(const Chat & c)3687 void GuiMain::onChatRemoved( const Chat& c )
3688 {
3689 showMessage( tr( "%1 removed" ).arg( c.name() ), 2000 );
3690 GuiFloatingChat* fl_chat = floatingChat( c.id() );
3691 if( fl_chat )
3692 fl_chat->close();
3693 mp_chatList->updateChats();
3694 mp_groupList->updateGroups();
3695 mp_savedChatList->updateSavedChats();
3696 if( mp_trayIcon->chatId() == c.id() )
3697 mp_trayIcon->setUnreadMessages( c.id(), 0 );
3698 updateTabTitles();
3699 updateNewMessageAction();
3700 }
3701
checkAllChatMembersAreConnected(const QList<VNumber> & users_id)3702 bool GuiMain::checkAllChatMembersAreConnected( const QList<VNumber>& users_id )
3703 {
3704 if( !beeCore->areUsersConnected( users_id ) )
3705 {
3706 if( QMessageBox::question( activeWindow(), Settings::instance().programName(),
3707 tr( "All the members of this chat are not online. The changes may not be permanent. Do you wish to continue?" ),
3708 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
3709 return false;
3710 }
3711 return true;
3712 }
3713
clearChat(VNumber chat_id)3714 void GuiMain::clearChat( VNumber chat_id )
3715 {
3716 Chat c = ChatManager::instance().chat( chat_id );
3717 if( !c.isValid() )
3718 return;
3719 QString chat_name = c.isDefault() ? QObject::tr( "All users" ).toLower() : c.name();
3720 if( c.isEmpty() && !ChatManager::instance().chatHasSavedText( c.name() ) )
3721 {
3722 QMessageBox::information( activeWindow(), Settings::instance().programName(), tr( "Chat with %1 is empty." ).arg( chat_name ) );
3723 return;
3724 }
3725
3726 QString question_txt = tr( "Do you want to clear messages with %1?" ).arg( chat_name );
3727 QString button_2_text;
3728 if( ChatManager::instance().chatHasSavedText( c.name() ) )
3729 button_2_text = QString( " " ) + tr( "Yes and delete history" ) + QString( " " );
3730
3731 bool chat_cleared = false;
3732 switch( QMessageBox::information( activeWindow(), Settings::instance().programName(), question_txt, tr( "Yes" ), tr( "No" ), button_2_text, 1, 1 ) )
3733 {
3734 case 0:
3735 chat_cleared = beeCore->clearMessagesInChat( chat_id, false );
3736 break;
3737 case 2:
3738 chat_cleared = beeCore->clearMessagesInChat( chat_id, true );
3739 break;
3740 default:
3741 return;
3742 }
3743
3744 if( chat_cleared )
3745 {
3746 GuiFloatingChat* fl_chat = floatingChat( chat_id );
3747 if( fl_chat )
3748 {
3749 Chat c = ChatManager::instance().chat( chat_id );
3750 if( c.isValid() )
3751 fl_chat->setChat( c );
3752 }
3753
3754 if( chat_id == ID_DEFAULT_CHAT )
3755 mp_home->loadSystemMessages();
3756 }
3757 }
3758
clearSystemMessagesInChat(VNumber chat_id)3759 void GuiMain::clearSystemMessagesInChat( VNumber chat_id )
3760 {
3761 if( beeCore->clearSystemMessagesInChat( chat_id ) )
3762 {
3763 GuiFloatingChat* fl_chat = floatingChat( chat_id );
3764 if( fl_chat )
3765 {
3766 Chat c = ChatManager::instance().chat( chat_id );
3767 if( c.isValid() )
3768 fl_chat->setChat( c );
3769 }
3770
3771 if( chat_id == ID_DEFAULT_CHAT )
3772 mp_home->loadSystemMessages();
3773 }
3774 }
3775
removeChat(VNumber chat_id)3776 void GuiMain::removeChat( VNumber chat_id )
3777 {
3778 Chat c = ChatManager::instance().chat( chat_id );
3779 if( !c.isValid() )
3780 {
3781 qWarning() << "Invalid chat" << chat_id << "found in GuiMain::removeChat(...)";
3782 return;
3783 }
3784
3785 QString button_2_text;
3786 if( ChatManager::instance().chatHasSavedText( c.name() ) )
3787 button_2_text = QString( " " ) + tr( "Yes and delete history" ) + QString( " " );
3788 QString question_txt = tr( "Do you want to leave the chat with %1?" ).arg( c.name() );
3789 int answer_id = QMessageBox::question( activeWindow(), Settings::instance().programName(), question_txt, tr( "Yes" ), tr( "No" ), button_2_text, 1, 1 );
3790 if( answer_id == 1 )
3791 return;
3792
3793 if( !beeCore->removeChat( chat_id, answer_id == 0 ) )
3794 QMessageBox::warning( activeWindow(), Settings::instance().programName(), tr( "Unable to leave the chat with %1." ).arg( c.name() ) );
3795 }
3796
showSharesForUser(const User & u)3797 void GuiMain::showSharesForUser( const User& u )
3798 {
3799 if( mp_fileSharing )
3800 mp_fileSharing->showUserFileList( u );
3801 }
3802
selectLanguage()3803 void GuiMain::selectLanguage()
3804 {
3805 GuiLanguage gl;
3806 gl.setModal( true );
3807 gl.loadLanguages();
3808 gl.setSizeGripEnabled( true );
3809 gl.show();
3810
3811 if( gl.exec() == QDialog::Rejected )
3812 return;
3813
3814 QString old_language_path = Settings::instance().languageFilePath( Settings::instance().languagePath(), Settings::instance().language() );
3815 QString new_language_path = Settings::instance().languageFilePath( gl.folderSelected(), gl.languageSelected() );
3816
3817 if( old_language_path != new_language_path )
3818 {
3819 QString language_message;
3820 if( gl.languageSelected().isEmpty() )
3821 language_message = tr( "Default language is restored." );
3822 else
3823 language_message = tr( "New language '%1' is selected." ).arg( gl.languageSelected() );
3824
3825 QMessageBox::information( this, Settings::instance().programName(),
3826 QString( "%1<br>%2" ).arg( language_message ).arg( tr( "You must restart %1 to apply these changes." )
3827 .arg( Settings::instance().programName() ) ) );
3828
3829 Settings::instance().setLanguage( gl.languageSelected() );
3830 Settings::instance().setLanguagePath( gl.folderSelected() );
3831 }
3832 }
3833
showAddUser()3834 void GuiMain::showAddUser()
3835 {
3836 GuiAddUser gad;
3837 gad.loadUsers();
3838 gad.setModal( true );
3839 gad.setSizeGripEnabled( true );
3840 gad.show();
3841
3842 if( gad.exec() == QDialog::Accepted )
3843 {
3844 if( !Settings::instance().networkAddressList().isEmpty() )
3845 {
3846 beeCore->updateUsersAddedManually();
3847 QMetaObject::invokeMethod( this, "sendBroadcastMessage", Qt::QueuedConnection );
3848 }
3849 }
3850 }
3851
showChatSettingsMenu()3852 void GuiMain::showChatSettingsMenu()
3853 {
3854 mp_menuChat->clear();
3855 QAction* act = mp_menuChat->addAction( tr( "Use RTL mode to show text" ), this, SLOT( settingsChanged() ) );
3856 act->setCheckable( true );
3857 act->setChecked( Settings::instance().showTextInModeRTL() );
3858 act->setData( 55 );
3859 mp_menuChat->addSeparator();
3860 act = mp_menuChat->addAction( tr( "Show the chat in compact view mode" ), this, SLOT( settingsChanged() ) );
3861 act->setCheckable( true );
3862 act->setChecked( Settings::instance().chatCompact() );
3863 act->setData( 1 );
3864 act = mp_menuChat->addAction( tr( "Show the timestamp" ), this, SLOT( settingsChanged() ) );
3865 act->setCheckable( true );
3866 act->setChecked( Settings::instance().chatShowMessageTimestamp() );
3867 act->setData( 3 );
3868 act = mp_menuChat->addAction( tr( "Show the time with the AM/PM notation" ), this, SLOT( settingsChanged() ) );
3869 act->setCheckable( true );
3870 act->setChecked( Settings::instance().useMessageTimestampWithAP() );
3871 act->setData( 76 );
3872 act = mp_menuChat->addAction( tr( "Show messages grouped by user" ), this, SLOT( settingsChanged() ) );
3873 act->setCheckable( true );
3874 act->setChecked( Settings::instance().showMessagesGroupByUser() );
3875 act->setData( 13 );
3876 act = mp_menuChat->addAction( tr( "Show your name instead of 'You'" ), this, SLOT( settingsChanged() ) );
3877 act->setCheckable( true );
3878 act->setChecked( Settings::instance().chatUseYourNameInsteadOfYou() );
3879 act->setData( 41 );
3880 if( mp_actShowUserFullName->isChecked() )
3881 {
3882 mp_menuChat->addAction( mp_actShowUserFullName );
3883 mp_menuChat->addAction( mp_actShowUserFirstNameFirstInFullName );
3884 }
3885 act = mp_menuChat->addAction( tr( "Show username's color" ), this, SLOT( settingsChanged() ) );
3886 act->setCheckable( true );
3887 act->setChecked( Settings::instance().chatUseColoredUserNames() );
3888 act->setData( 67 );
3889 mp_menuChat->addSeparator();
3890 act = mp_menuChat->addAction( tr( "Show emoticons" ), this, SLOT( settingsChanged() ) );
3891 act->setCheckable( true );
3892 act->setChecked( Settings::instance().showEmoticons() );
3893 act->setData( 10 );
3894 act = mp_menuChat->addAction( tr( "Use HTML tags" ), this, SLOT( settingsChanged() ) );
3895 act->setCheckable( true );
3896 act->setChecked( Settings::instance().chatUseHtmlTags() );
3897 act->setData( 8 );
3898 act = mp_menuChat->addAction( tr( "Use clickable links" ), this, SLOT( settingsChanged() ) );
3899 act->setCheckable( true );
3900 act->setChecked( Settings::instance().chatUseClickableLinks() );
3901 act->setData( 9 );
3902 mp_menuChat->addSeparator();
3903 act = mp_menuChat->addAction( tr( "Clear recent emoticons" ), this, SLOT( settingsChanged() ) );
3904 act->setIcon( IconManager::instance().icon( "clear.png" ) );
3905 act->setData( 104 );
3906 act = mp_menuChat->addAction( tr( "Clear favorite emoticons" ), this, SLOT( settingsChanged() ) );
3907 act->setIcon( IconManager::instance().icon( "clear.png" ) );
3908 act->setData( 106 );
3909 act = mp_menuChat->addAction( tr( "Restore default font" ), this, SLOT( settingsChanged() ) );
3910 act->setIcon( IconManager::instance().icon( "font.png" ) );
3911 act->setData( 23 );
3912 mp_menuChat->exec( QCursor::pos() );
3913 }
3914
showDefaultServerPortInMenu()3915 void GuiMain::showDefaultServerPortInMenu()
3916 {
3917 QString host_address = tr( "offline" );
3918 QString broadcast_port = tr( "offline" );
3919 QString listener_port = tr( "offline" );
3920 QString file_transfer_port = tr( "offline" );
3921 #ifdef BEEBEEP_USE_MULTICAST_DNS
3922 QString multicast_dns = tr( "inactive" );
3923 #endif
3924 QString multicast_group = tr( "none" );
3925
3926 if( beeCore->isConnected() )
3927 {
3928 mp_menuNetworkStatus->setIcon( IconManager::instance().icon( "network-connected.png" ) );
3929 mp_actHostAddress->setIcon( IconManager::instance().icon( "network-connected.png" ) );
3930 mp_actHostAddress->setEnabled( true );
3931 mp_actPortBroadcast->setEnabled( true );
3932 mp_actPortListener->setEnabled( true );
3933 mp_actEncryptedConnectionByDefault->setEnabled( true );
3934 mp_actCompressedDataByDefault->setEnabled( true );
3935
3936 host_address = Settings::instance().localUser().networkAddress().hostAddress().toString();
3937 broadcast_port = QString::number( Settings::instance().defaultBroadcastPort() );
3938 listener_port = QString::number( Settings::instance().localUser().networkAddress().hostPort() );
3939
3940 QHostAddress multicast_host_address = beeCore->multicastGroupAddress();
3941 mp_actMulticastGroupAddress->setEnabled( !multicast_host_address.isNull() );
3942 if( !multicast_host_address.isNull() )
3943 multicast_group = multicast_host_address.toString();
3944
3945 if( Settings::instance().enableFileTransfer() )
3946 {
3947 file_transfer_port = QString::number( beeCore->fileTransferPort() );
3948 mp_actPortFileTransfer->setEnabled( true );
3949 if( mp_networkTest )
3950 mp_networkTest->updateSettings( QString::number( beeCore->fileTransferPort() ) );
3951 }
3952 else
3953 {
3954 file_transfer_port = tr( "disabled" );
3955 mp_actPortFileTransfer->setEnabled( false );
3956 if( mp_networkTest )
3957 mp_networkTest->updateSettings( file_transfer_port );
3958 }
3959
3960 #ifdef BEEBEEP_USE_MULTICAST_DNS
3961 if( beeCore->dnsMulticastingIsActive() )
3962 {
3963
3964 multicast_dns = tr( "active" );
3965 mp_actMulticastDns->setEnabled( true );
3966 }
3967 else
3968 mp_actMulticastDns->setEnabled( false );
3969 #endif
3970
3971
3972 }
3973 else
3974 {
3975 mp_menuNetworkStatus->setIcon( IconManager::instance().icon( "network-disconnected.png" ) );
3976 mp_actHostAddress->setIcon( IconManager::instance().icon( "network-disconnected.png" ) );
3977 mp_actHostAddress->setEnabled( false );
3978 mp_actPortBroadcast->setEnabled( false );
3979 mp_actMulticastGroupAddress->setEnabled( false );
3980 mp_actPortListener->setEnabled( false );
3981 mp_actPortFileTransfer->setEnabled( false );
3982 #ifdef BEEBEEP_USE_MULTICAST_DNS
3983 mp_actMulticastDns->setEnabled( false );
3984 #endif
3985 mp_actEncryptedConnectionByDefault->setEnabled( false );
3986 mp_actCompressedDataByDefault->setEnabled( false );
3987 }
3988
3989 mp_actHostAddress->setText( QString( "ip: %1 (%2)" ).arg( host_address ).arg( tr( "your IP address" ) ) );
3990 mp_actPortBroadcast->setText( QString( "udp: %1 (%2)" ).arg( broadcast_port ).arg( tr( "to search for users" ) ) );
3991 mp_actMulticastGroupAddress->setText( QString( "multicast: %1" ).arg( multicast_group ) );
3992 mp_actPortListener->setText( QString( "tcp1: %1 (%2)" ).arg( listener_port ).arg( tr( "chat messages" ) ) );
3993 mp_actPortFileTransfer->setText( QString( "tcp2: %1 (%2)" ).arg( file_transfer_port ).arg( tr( "file transfer" ) ) );
3994 #ifdef BEEBEEP_USE_MULTICAST_DNS
3995 mp_actMulticastDns->setText( QString( "mdns: %1" ).arg( multicast_dns ) );
3996 #endif
3997 if( Settings::instance().disableConnectionSocketEncryption() )
3998 {
3999 mp_actEncryptedConnectionByDefault->setIcon( IconManager::instance().icon( "warning.png" ) );
4000 mp_actEncryptedConnectionByDefault->setText( tr( "End-to-end encryption is disabled" ) );
4001 }
4002 else
4003 {
4004 mp_actEncryptedConnectionByDefault->setIcon( IconManager::instance().icon( "encryption-enabled.png" ) );
4005 mp_actEncryptedConnectionByDefault->setText( tr( "End-to-end encryption is enabled" ) );
4006 }
4007
4008 if( Settings::instance().disableConnectionSocketEncryption() )
4009 {
4010 mp_actCompressedDataByDefault->setIcon( IconManager::instance().icon( "folder.png" ) );
4011 mp_actCompressedDataByDefault->setText( tr( "Data compression is disabled" ) );
4012 }
4013 else
4014 {
4015 mp_actCompressedDataByDefault->setIcon( IconManager::instance().icon( "file-compressed.png" ) );
4016 mp_actCompressedDataByDefault->setText( tr( "Data compression is enabled" ) );
4017 }
4018 }
4019
sendBroadcastMessage()4020 void GuiMain::sendBroadcastMessage()
4021 {
4022 mp_actBroadcast->setDisabled( true );
4023 beeCore->sendBroadcastMessage();
4024 #ifdef BEEBEEP_USE_MULTICAST_DNS
4025 beeCore->sendDnsMulticastingMessage();
4026 #endif
4027 QTimer::singleShot( 61000, this, SLOT( enableBroadcastAction() ) );
4028 }
4029
enableBroadcastAction()4030 void GuiMain::enableBroadcastAction()
4031 {
4032 mp_actBroadcast->setEnabled( beeCore->isConnected() );
4033 }
4034
checkUserSelected(VNumber user_id)4035 void GuiMain::checkUserSelected( VNumber user_id )
4036 {
4037 User u = UserManager::instance().findUser( user_id );
4038 if( !u.isValid() )
4039 {
4040 qWarning() << "Invalid user id" << user_id << "found in check user selected";
4041 return;
4042 }
4043
4044 Chat c = ChatManager::instance().privateChatForUser( user_id );
4045 if( !c.isValid() )
4046 {
4047 beeCore->createPrivateChat( u );
4048 c = ChatManager::instance().privateChatForUser( user_id );
4049 if( !c.isValid() )
4050 {
4051 qWarning() << "Unable to create private chat for user" << user_id;
4052 return;
4053 }
4054 }
4055 showChat( c.id() );
4056 }
4057
showConnectionStatusChanged(const User & u)4058 void GuiMain::showConnectionStatusChanged( const User& u )
4059 {
4060 if( !beeCore->isConnected() )
4061 return;
4062
4063 if( Settings::instance().showOnlyMessageNotificationOnTray() )
4064 return;
4065
4066 QString msg;
4067 if( u.isStatusConnected() )
4068 msg = tr( "%1 is online" ).arg( u.name() );
4069 else
4070 msg = tr( "%1 is offline" ).arg( u.name() );
4071
4072 Chat c = ChatManager::instance().privateChatForUser( u.id() );
4073 if( c.isValid() && u.isStatusConnected() )
4074 mp_trayIcon->showUserStatusChanged( c.id(), msg );
4075 else
4076 mp_trayIcon->showUserStatusChanged( ID_DEFAULT_CHAT, msg );
4077 }
4078
changeAvatarSizeInList()4079 void GuiMain::changeAvatarSizeInList()
4080 {
4081 bool ok = false;
4082 int avatar_size = QInputDialog::getInt( this, Settings::instance().programName(), tr( "Please select the new size of the user picture" ),
4083 Settings::instance().avatarIconSize().height(), 16, 96, 4, &ok );
4084 if( !ok )
4085 return;
4086
4087 Settings::instance().setAvatarIconSize( QSize( avatar_size, avatar_size ) );
4088 mp_userList->updateUsers();
4089 mp_chatList->updateChats();
4090 mp_groupList->updateGroups();
4091 mp_savedChatList->updateSavedChats();
4092 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4093 {
4094 Chat c = ChatManager::instance().chat( fl_chat->guiChat()->chatId() );
4095 if( c.isValid() )
4096 fl_chat->updateChatMembers( c );
4097 }
4098 }
4099
toggleUserFavorite(VNumber user_id)4100 void GuiMain::toggleUserFavorite( VNumber user_id )
4101 {
4102 beeCore->toggleUserFavorite( user_id );
4103 }
4104
removeUserFromList(VNumber user_id)4105 void GuiMain::removeUserFromList( VNumber user_id )
4106 {
4107 QString question_txt = tr( "Do you want to delete user %1?" ).arg( UserManager::instance().findUser( user_id ).name() );
4108 if( QMessageBox::question( activeWindow(), Settings::instance().programName(), question_txt, tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
4109 return;
4110 beeCore->removeOfflineUser( user_id );
4111 }
4112
openResourceFolder()4113 void GuiMain::openResourceFolder()
4114 {
4115 QUrl folder_url = QUrl::fromLocalFile( Settings::instance().resourceFolder() );
4116 openUrl( folder_url );
4117 }
4118
openDataFolder()4119 void GuiMain::openDataFolder()
4120 {
4121 QUrl folder_url = QUrl::fromLocalFile( Settings::instance().dataFolder() );
4122 openUrl( folder_url );
4123 }
4124
openDownloadFolder()4125 void GuiMain::openDownloadFolder()
4126 {
4127 QUrl folder_url = QUrl::fromLocalFile( Settings::instance().downloadDirectory() );
4128 openUrl( folder_url );
4129 }
4130
floatingChat(VNumber chat_id) const4131 GuiFloatingChat* GuiMain::floatingChat( VNumber chat_id ) const
4132 {
4133 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4134 {
4135 if( fl_chat->guiChat()->chatId() == chat_id )
4136 return fl_chat;
4137 }
4138 return Q_NULLPTR;
4139 }
4140
removeFloatingChatFromList(VNumber chat_id)4141 void GuiMain::removeFloatingChatFromList( VNumber chat_id )
4142 {
4143 GuiFloatingChat* fl_chat = floatingChat( chat_id );
4144 if( !fl_chat )
4145 return;
4146
4147 if( mp_menuChat->isVisible() )
4148 mp_menuChat->close();
4149
4150 m_floatingChats.removeOne( fl_chat );
4151 fl_chat->deleteLater();
4152 #ifdef BEEBEEP_DEBUG
4153 qDebug() << "Floating chat" << chat_id << "closed and deleted";
4154 #endif
4155
4156 #ifdef BEEBEEP_USE_SHAREDESKTOP
4157 onShareDesktopRequestFromChat( chat_id, false );
4158 #endif
4159 }
4160
createFloatingChat(const Chat & c)4161 GuiFloatingChat* GuiMain::createFloatingChat( const Chat& c )
4162 {
4163 GuiFloatingChat* fl_chat = floatingChat( c.id() );
4164 if( fl_chat )
4165 return fl_chat;
4166
4167 if( Settings::instance().showChatsInOneWindow() && !m_floatingChats.isEmpty() )
4168 fl_chat = m_floatingChats.first();
4169
4170 if( !fl_chat )
4171 {
4172 fl_chat = new GuiFloatingChat;
4173 setupChatConnections( fl_chat->guiChat() );
4174 connect( fl_chat, SIGNAL( chatIsAboutToClose( VNumber ) ), this, SLOT( removeFloatingChatFromList( VNumber ) ) );
4175 connect( fl_chat, SIGNAL( readAllMessages( VNumber ) ), this, SLOT( readAllMessagesInChat( VNumber ) ) );
4176 connect( fl_chat, SIGNAL( showVCardRequest( VNumber ) ), this, SLOT( showVCard( VNumber ) ) );
4177 connect( fl_chat, SIGNAL( updateChatFontRequest() ), this, SLOT( updateChatFont() ) );
4178 connect( fl_chat, SIGNAL( updateChatColorsRequest() ), this, SLOT( updateChatColors() ) );
4179 #ifdef BEEBEEP_USE_VOICE_CHAT
4180 connect( fl_chat, SIGNAL( sendVoiceMessageRequest( VNumber, const QString&, qint64 ) ), this, SLOT( sendVoiceMessageToChat( VNumber, const QString&, qint64 ) ) );
4181 #endif
4182
4183 m_floatingChats.append( fl_chat );
4184 fl_chat->setWindowFlagsAndGeometry();
4185 fl_chat->setSaveGeometryDisabled( Settings::instance().resetGeometryAtStartup() );
4186 }
4187
4188 if( !fl_chat->setChat( c ) )
4189 {
4190 qWarning() << "Unable to create floating window for not existing chat" << c.id() << c.name();
4191 fl_chat->deleteLater();
4192 return Q_NULLPTR;
4193 }
4194
4195 return fl_chat;
4196 }
4197
activeWindow()4198 QWidget* GuiMain::activeWindow()
4199 {
4200 QWidget* active_window = QApplication::activeWindow();
4201 if( active_window )
4202 return active_window;
4203 else
4204 return qobject_cast<QWidget*>( this );
4205 }
4206
loadUserStatusRecentlyUsed()4207 void GuiMain::loadUserStatusRecentlyUsed()
4208 {
4209 if( !mp_menuUserStatusList->isEmpty() )
4210 mp_menuUserStatusList->clear();
4211
4212 QList<UserStatusRecord> user_status_list;
4213 foreach( QString s, Settings::instance().userStatusList() )
4214 {
4215 UserStatusRecord usr = Protocol::instance().loadUserStatusRecord( s );
4216 if( usr.isValid() )
4217 user_status_list.append( usr );
4218 }
4219
4220 if( user_status_list.size() < Settings::instance().maxUserStatusDescriptionInList() )
4221 {
4222 UserStatusRecord usr1;
4223 usr1.setStatus( User::Away );
4224 usr1.setStatusDescription( tr( "at lunch" ) );
4225 if( !user_status_list.contains( usr1 ) )
4226 user_status_list.append( usr1 );
4227 }
4228
4229 if( user_status_list.size() < Settings::instance().maxUserStatusDescriptionInList() )
4230 {
4231 UserStatusRecord usr2;
4232 usr2.setStatus( User::Busy );
4233 usr2.setStatusDescription( tr( "in a meeting" ) );
4234 if( !user_status_list.contains( usr2 ) )
4235 user_status_list.append( usr2 );
4236 }
4237
4238 qSort( user_status_list );
4239
4240 QAction* act;
4241 foreach( UserStatusRecord usr, user_status_list )
4242 {
4243 if( usr.isValid() )
4244 {
4245 act = mp_menuUserStatusList->addAction( Bee::userStatusIcon( usr.status() ), usr.statusDescription(), this, SLOT( recentlyUsedUserStatusSelected() ) );
4246 act->setData( Protocol::instance().saveUserStatusRecord( usr ) );
4247 }
4248 }
4249 }
4250
recentlyUsedUserStatusSelected()4251 void GuiMain::recentlyUsedUserStatusSelected()
4252 {
4253 QAction* act = qobject_cast<QAction*>( sender() );
4254 if( !act )
4255 return;
4256
4257 UserStatusRecord usr = Protocol::instance().loadUserStatusRecord( act->data().toString() );
4258 if( usr.isValid() )
4259 {
4260 beeCore->setLocalUserStatusDescription( usr.status(), usr.statusDescription(), false );
4261 setUserStatusSelected( usr.status() );
4262 loadUserStatusRecentlyUsed();
4263 updateLocalStatusMessage();
4264 }
4265 }
4266
clearRecentlyUsedUserStatus()4267 void GuiMain::clearRecentlyUsedUserStatus()
4268 {
4269 if( QMessageBox::question( this, Settings::instance().programName(),
4270 tr( "Do you want to clear all saved status descriptions?" ),
4271 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
4272 return;
4273
4274 qDebug() << "User status description list is cleared";
4275 QStringList sl = Settings::instance().userStatusList();
4276 sl.clear();
4277 Settings::instance().setUserStatusList( sl );
4278 loadUserStatusRecentlyUsed();
4279 }
4280
loadSavedChatsCompleted()4281 void GuiMain::loadSavedChatsCompleted()
4282 {
4283 mp_chatList->updateChats();
4284 mp_savedChatList->updateSavedChats();
4285 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4286 fl_chat->setChat( ChatManager::instance().chat( fl_chat->guiChat()->chatId() ) );
4287 updateTabTitles();
4288 }
4289
editShortcuts()4290 void GuiMain::editShortcuts()
4291 {
4292 GuiShortcut gs;
4293 gs.setModal( true );
4294 gs.loadShortcuts();
4295 gs.setSizeGripEnabled( true );
4296 gs.show();
4297
4298 if( gs.exec() == QDialog::Rejected )
4299 return;
4300
4301 Settings::instance().setShortcuts( ShortcutManager::instance().saveToStringList() );
4302 Settings::instance().save();
4303 updateShortcuts();
4304 }
4305
updateShortcuts()4306 void GuiMain::updateShortcuts()
4307 {
4308 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4309 fl_chat->guiChat()->updateShortcuts();
4310
4311 QKeySequence ks = ShortcutManager::instance().shortcut( ShortcutManager::ShowFileTransfers );
4312 if( !ks.isEmpty() && Settings::instance().useShortcuts() )
4313 mp_actViewFileTransfer->setShortcut( ks );
4314 else
4315 mp_actViewFileTransfer->setShortcut( QKeySequence() );
4316
4317 ks = ShortcutManager::instance().shortcut( ShortcutManager::MinimizeAllChats );
4318 if( !ks.isEmpty() )
4319 {
4320 mp_scMinimizeAllChats->setKey( ks );
4321 mp_scMinimizeAllChats->setEnabled( Settings::instance().useShortcuts() );
4322 }
4323 else
4324 mp_scMinimizeAllChats->setEnabled( false );
4325
4326 #ifdef BEEBEEP_USE_QXT
4327 ks = ShortcutManager::instance().shortcut( ShortcutManager::ShowAllChats );
4328 if( !ks.isEmpty() && Settings::instance().useShortcuts() )
4329 {
4330 mp_scShowAllChats->setShortcut( ks );
4331 mp_scShowAllChats->setEnabled( true );
4332 }
4333 else
4334 {
4335 mp_scShowAllChats->unsetShortcut();
4336 mp_scShowAllChats->setEnabled( false );
4337 }
4338 #endif
4339 ks = ShortcutManager::instance().shortcut( ShortcutManager::ShowNextUnreadMessage );
4340 if( !ks.isEmpty() )
4341 {
4342 mp_scShowNextUnreadMessage->setKey( ks );
4343 mp_scShowNextUnreadMessage->setEnabled( Settings::instance().useShortcuts() );
4344 }
4345 else
4346 mp_scShowNextUnreadMessage->setEnabled( false );
4347
4348 ks = ShortcutManager::instance().shortcut( ShortcutManager::Broadcast );
4349 if( !ks.isEmpty() && Settings::instance().useShortcuts() )
4350 mp_actBroadcast->setShortcut( ks );
4351 else
4352 mp_actBroadcast->setShortcut( QKeySequence() );
4353
4354 }
4355
minimizeAllChats()4356 void GuiMain::minimizeAllChats()
4357 {
4358 QWidget* w = qApp->activeWindow();
4359
4360 bool last_active_window_exists = w == this ? true : false;
4361
4362 if( !m_floatingChats.isEmpty() )
4363 {
4364 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4365 {
4366 if( !fl_chat->isMinimized() )
4367 fl_chat->showMinimized();
4368 if( fl_chat == mp_lastActiveWindow )
4369 last_active_window_exists = true;
4370 }
4371 }
4372
4373 if( !isMinimized() )
4374 showMinimized();
4375
4376 if( last_active_window_exists )
4377 mp_lastActiveWindow = w;
4378 }
4379
showAllChats()4380 void GuiMain::showAllChats()
4381 {
4382 bool last_active_window_exists = false;
4383
4384 if( !m_floatingChats.isEmpty() )
4385 {
4386 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4387 {
4388 if( fl_chat->isMinimized() )
4389 fl_chat->showNormal();
4390 else
4391 fl_chat->show();
4392 fl_chat->raiseOnTop();
4393
4394 if( fl_chat == mp_lastActiveWindow )
4395 last_active_window_exists = true;
4396 }
4397 }
4398
4399 if( isMinimized() )
4400 showNormal();
4401 else
4402 show();
4403 raiseOnTop();
4404
4405 if( this == mp_lastActiveWindow )
4406 last_active_window_exists = true;
4407
4408 if( last_active_window_exists )
4409 {
4410 mp_lastActiveWindow->raise();
4411 qApp->setActiveWindow( mp_lastActiveWindow );
4412 }
4413 }
4414
selectDictionatyPath()4415 void GuiMain::selectDictionatyPath()
4416 {
4417 QString dictionary_path = FileDialog::getOpenFileName( false, this, tr( "Select your dictionary path" ), Settings::instance().dictionaryPath(), QString( "*.dic" ) );
4418
4419 if( dictionary_path.isEmpty() )
4420 return;
4421
4422 Settings::instance().setDictionaryPath( dictionary_path );
4423 #ifdef BEEBEEP_USE_HUNSPELL
4424 if( SpellChecker::instance().setDictionary( dictionary_path ) )
4425 QMessageBox::information( this, Settings::instance().programName(), tr( "Dictionary selected: %1" ).arg( dictionary_path ) );
4426 else
4427 QMessageBox::warning( this, Settings::instance().programName(), tr( "Unable to set dictionary: %1" ).arg( dictionary_path ) );
4428 #endif
4429 Settings::instance().setUseSpellChecker( true );
4430 Settings::instance().setUseWordCompleter( true );
4431
4432 // update spellchecker and wordcompleter actions
4433 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4434 fl_chat->guiChat()->updateActionsOnFocusChanged();
4435 }
4436
onNetworkInterfaceDown()4437 void GuiMain::onNetworkInterfaceDown()
4438 {
4439 if( beeCore->isConnected() )
4440 {
4441 m_autoConnectOnInterfaceUp = true;
4442 QMetaObject::invokeMethod( this, "stopCore", Qt::QueuedConnection );
4443 }
4444 else
4445 m_autoConnectOnInterfaceUp = false;
4446 }
4447
onNetworkInterfaceUp()4448 void GuiMain::onNetworkInterfaceUp()
4449 {
4450 if( m_autoConnectOnInterfaceUp )
4451 QMetaObject::invokeMethod( this, "startCore", Qt::QueuedConnection );
4452 }
4453
onTickEvent(int ticks)4454 void GuiMain::onTickEvent( int ticks )
4455 {
4456 int chat_tab_index = mp_tabMain->indexOf( mp_chatList );
4457 if( mp_actViewNewMessage->isEnabled() )
4458 {
4459 QIcon new_message_blinking_icon = IconManager::instance().icon( "beebeep-message.png" );
4460 mp_actViewNewMessage->setIcon( ticks % 2 == 0 ? new_message_blinking_icon : Bee::convertToGrayScale( new_message_blinking_icon, Settings::instance().mainBarIconSize() ) );
4461 mp_tabMain->setTabIcon( chat_tab_index, ticks % 2 == 0 ? new_message_blinking_icon : IconManager::instance().icon( "chat-list.png" ) );
4462 setWindowIcon( ticks % 2 == 0 ? new_message_blinking_icon : IconManager::instance().icon( "beebeep.png" ) );
4463 }
4464
4465 mp_trayIcon->onTickEvent( ticks );
4466 mp_chatList->onTickEvent( ticks );
4467 mp_userList->onTickEvent( ticks );
4468 mp_groupList->onTickEvent( ticks );
4469 mp_fileTransfer->onTickEvent( ticks );
4470 if( mp_fileSharing )
4471 mp_fileSharing->onTickEvent( ticks );
4472 if( mp_networkTest )
4473 mp_networkTest->onTickEvent( ticks );
4474
4475 if( beeCore->hasFileTransferInProgress() )
4476 mp_actViewFileTransfer->setIcon( ticks % 2 == 0 ? IconManager::instance().icon( "file-transfer-progress.png" ) : IconManager::instance().icon( "file-transfer.png" ) );
4477
4478 if( ticks % 2 == 0 && mp_actViewNewMessage->isEnabled() )
4479 {
4480 Chat c = ChatManager::instance().firstChatWithUnreadMessages();
4481 GuiFloatingChat* fl_chat = floatingChat( c.id() );
4482 if( !fl_chat )
4483 QApplication::alert( this, 1000 );
4484 showMessage( tr( "You have new message" ), 1000 );
4485 }
4486
4487 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4488 fl_chat->onTickEvent( ticks );
4489
4490 #ifdef BEEBEEP_USE_SHAREDESKTOP
4491 foreach( GuiShareDesktop* gsd, m_desktops )
4492 gsd->onTickEvent( ticks );
4493 #endif
4494
4495 if( beeApp->isInSleepMode() )
4496 return;
4497
4498 if( !m_coreIsConnecting )
4499 {
4500 if( Bee::isTimeToCheck( ticks, Settings::instance().tickIntervalCheckIdle() ) )
4501 {
4502 if( beeApp->idleTimeout() > 0 )
4503 QMetaObject::invokeMethod( beeApp, "checkIdle", Qt::QueuedConnection );
4504 }
4505
4506 beeCore->onTickEvent( ticks );
4507 }
4508 }
4509
onChatReadByUser(const Chat & c,const User & u)4510 void GuiMain::onChatReadByUser( const Chat& c, const User& u )
4511 {
4512 GuiFloatingChat* fl_chat = floatingChat( c.id() );
4513 if( fl_chat )
4514 fl_chat->setChatReadByUser( c, u );
4515 }
4516
readAllMessagesInChat(VNumber chat_id)4517 void GuiMain::readAllMessagesInChat( VNumber chat_id )
4518 {
4519 beeCore->readAllMessagesInChat( chat_id );
4520 }
4521
saveSession(QSessionManager &)4522 void GuiMain::saveSession( QSessionManager& )
4523 {
4524 qDebug() << "Session manager ask to save and close session";
4525 forceShutdown();
4526 }
4527
updateEmoticons()4528 void GuiMain::updateEmoticons()
4529 {
4530 if( m_floatingChats.isEmpty() )
4531 return;
4532
4533 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
4534 fl_chat->updateEmoticons();
4535 }
4536
updateNewMessageAction()4537 void GuiMain::updateNewMessageAction()
4538 {
4539 Chat c = ChatManager::instance().firstChatWithUnreadMessages();
4540 mp_trayIcon->setNextChatToRead( c );
4541 mp_actViewNewMessage->setEnabled( c.isValid() );
4542 int chat_tab_index = mp_tabMain->indexOf( mp_chatList );
4543 if( mp_actViewNewMessage->isEnabled() )
4544 {
4545 mp_actViewNewMessage->setStatusTip( tr( "You have new message" ) );
4546 mp_tabMain->setTabIcon( chat_tab_index, IconManager::instance().icon( "beebeep-message.png" ) );
4547 setWindowIcon( IconManager::instance().icon( "beebeep-message.png" ) );
4548 }
4549 else
4550 {
4551 mp_actViewNewMessage->setStatusTip( "" );
4552 mp_tabMain->setTabIcon( chat_tab_index, IconManager::instance().icon( "chat-list.png" ) );
4553 setWindowIcon( IconManager::instance().icon( "beebeep.png" ) );
4554 }
4555 }
4556
saveGeometryAndState()4557 void GuiMain::saveGeometryAndState()
4558 {
4559 if( isVisible() )
4560 {
4561 Settings::instance().setGuiGeometry( saveGeometry() );
4562 Settings::instance().setGuiState( saveState() );
4563 Settings::instance().save();
4564 }
4565 }
4566
askSaveGeometryAndState()4567 void GuiMain::askSaveGeometryAndState()
4568 {
4569 if( isVisible() )
4570 {
4571 QByteArray ba_state = saveState();
4572 #if QT_VERSION == 0x050906
4573 int default_button = mp_dockFileTransfers->isVisible() ? 0 : 1;
4574 int ret_code = QMessageBox::warning( this, Settings::instance().programName(),
4575 tr( "Qt libraries have a bug on saving the window's state." ) + QString( " " ) +
4576 tr( "If you have layout problem please save only geometry." ),
4577 tr( "Save all" ), tr( "Save only geometry" ), tr( "Cancel" ), default_button, 2 );
4578 switch( ret_code )
4579 {
4580 case 0:
4581 break;
4582 case 1:
4583 ba_state = QByteArray();
4584 break;
4585 default:
4586 return;
4587 }
4588 #endif
4589 Settings::instance().setGuiGeometry( saveGeometry() );
4590 Settings::instance().setGuiState( ba_state );
4591 Settings::instance().save();
4592 if( ba_state.isEmpty() )
4593 showMessage( tr( "Window geometry saved" ), 3000 );
4594 else
4595 showMessage( tr( "Window geometry and state saved" ), 3000 );
4596 }
4597 }
4598
restoreGeometryAndState()4599 void GuiMain::restoreGeometryAndState()
4600 {
4601 restoreGeometry( Settings::instance().guiGeometry() );
4602 if( !Settings::instance().guiState().isEmpty() )
4603 restoreState( Settings::instance().guiState() );
4604 }
4605
resetGeometryAndState()4606 void GuiMain::resetGeometryAndState()
4607 {
4608 if( mp_dockFileTransfers->isVisible() )
4609 mp_dockFileTransfers->hide();
4610 resize( qMax( width(), 280 ), qMin( 520, qMax( QApplication::desktop()->availableGeometry().height() - 120, 460 ) ) );
4611
4612 #ifdef Q_OS_WIN
4613 move( QApplication::desktop()->availableGeometry().width() - frameGeometry().width(),
4614 QApplication::desktop()->availableGeometry().height() - frameGeometry().height() );
4615 #elif defined BEEBEEP_FOR_RASPBERRY_PI
4616 move( QApplication::desktop()->availableGeometry().width() - frameGeometry().width(), 70 );
4617 #elif defined Q_OS_MAC
4618 #if QT_VERSION >= 0x050900
4619 move( QApplication::desktop()->availableGeometry().width() - frameGeometry().width(), 0 );
4620 #else
4621 move( QApplication::desktop()->availableGeometry().width() - frameGeometry().width() - 20, 0 );
4622 #endif
4623 #else
4624 move( QApplication::desktop()->availableGeometry().width() - frameGeometry().width(), 0 );
4625 #endif
4626
4627 if( !Settings::instance().guiGeometry().isEmpty() )
4628 Settings::instance().setGuiGeometry( QByteArray() );
4629 if( !Settings::instance().guiState().isEmpty() )
4630 Settings::instance().setGuiState( QByteArray() );
4631 }
4632
askResetGeometryAndState()4633 void GuiMain::askResetGeometryAndState()
4634 {
4635 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you really want to reset window's geometry?" ), tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 0 )
4636 {
4637 resetGeometryAndState();
4638 setMinimumWidthForStyle();
4639 if( !Settings::instance().floatingChatGeometry().isEmpty() )
4640 Settings::instance().setFloatingChatGeometry( QByteArray() );
4641 if( !Settings::instance().floatingChatState().isEmpty() )
4642 Settings::instance().setFloatingChatState( QByteArray() );
4643 if( !Settings::instance().floatingChatSplitterState().isEmpty() )
4644 Settings::instance().setFloatingChatSplitterState( QByteArray() );
4645 if( !Settings::instance().createMessageGeometry().isEmpty() )
4646 Settings::instance().setCreateMessageGeometry( QByteArray() );
4647 if( !Settings::instance().fileSharingGeometry().isEmpty() )
4648 Settings::instance().setFileSharingGeometry( QByteArray() );
4649 Settings::instance().setShowEmoticonMenu( false );
4650 Settings::instance().save();
4651 showMessage( tr( "Geometry of all windows has been reset" ), 3000 );
4652 }
4653 }
4654
onChangeSettingOnExistingFile(QAction * act)4655 void GuiMain::onChangeSettingOnExistingFile( QAction* act )
4656 {
4657 if( !act )
4658 return;
4659
4660 Settings::instance().setOnExistingFileAction( act->data().toInt() );
4661 Settings::instance().save();
4662 }
4663
onFileTransferProgress(VNumber peer_id,const User & u,const FileInfo & fi,FileSizeType bytes,qint64 elapsed_time)4664 void GuiMain::onFileTransferProgress( VNumber peer_id, const User& u, const FileInfo& fi, FileSizeType bytes, qint64 elapsed_time )
4665 {
4666 mp_fileTransfer->setProgress( peer_id, u, fi, bytes, elapsed_time );
4667 if( Settings::instance().alwaysShowFileTransferProgress() )
4668 {
4669 if( !mp_dockFileTransfers->isVisible() )
4670 {
4671 mp_dockFileTransfers->show();
4672 raiseOnTop();
4673 }
4674 }
4675 }
4676
onFileTransferMessage(VNumber peer_id,const User & u,const FileInfo & fi,const QString & msg,FileTransferPeer::TransferState ft_state)4677 void GuiMain::onFileTransferMessage( VNumber peer_id, const User& u, const FileInfo& fi, const QString& msg, FileTransferPeer::TransferState ft_state )
4678 {
4679 mp_fileTransfer->setMessage( peer_id, u, fi, msg, ft_state );
4680 if( Settings::instance().alwaysShowFileTransferProgress() )
4681 {
4682 if( !mp_dockFileTransfers->isVisible() )
4683 {
4684 mp_dockFileTransfers->show();
4685 raiseOnTop();
4686 }
4687 }
4688
4689 if( ft_state == FileTransferPeer::Completed )
4690 {
4691 if( !fi.isInShareBox() && fi.isDownload() )
4692 {
4693 Chat c = ChatManager::instance().findChatByPrivateId( fi.chatPrivateId(), false, u.id() );
4694 if( !c.isValid() )
4695 {
4696 qWarning() << "Unable to find chat by private id" << qPrintable( fi.chatPrivateId() ) << "for user" << qPrintable( u.name() ) << "in onFileTransferCompleted(...)";
4697 return;
4698 }
4699
4700 if( Settings::instance().showFileTransferCompletedOnTray() )
4701 mp_trayIcon->showNewFileArrived( c.id(), tr( "New file from %1" ).arg( u.name() ), false );
4702
4703 GuiFloatingChat* fl_chat = floatingChat( c.id() );
4704 if( fl_chat && fl_chat->isActiveWindow() )
4705 return;
4706 onChatChanged( c );
4707 }
4708 }
4709 }
4710
sendBuzzToUser(VNumber user_id)4711 void GuiMain::sendBuzzToUser( VNumber user_id )
4712 {
4713 if( beeCore->isConnected() )
4714 beeCore->sendBuzzToUser( user_id );
4715 }
4716
showBuzzFromUser(const User & u)4717 void GuiMain::showBuzzFromUser( const User& u )
4718 {
4719 if( Settings::instance().playBuzzSound() )
4720 playBuzz();
4721
4722 Chat c = ChatManager::instance().privateChatForUser( u.id() );
4723 if( c.isValid() )
4724 mp_trayIcon->showNewMessageArrived( c.id(), tr( "%1 is buzzing you!" ).arg( u.name() ), true );
4725 }
4726
showFileSharingWindow()4727 void GuiMain::showFileSharingWindow()
4728 {
4729 if( Settings::instance().disableFileSharing() )
4730 return;
4731
4732 if( !mp_fileSharing )
4733 {
4734 mp_fileSharing = new GuiFileSharing( Q_NULLPTR );
4735 mp_fileSharing->setAttribute( Qt::WA_DeleteOnClose, true );
4736 Bee::setWindowStaysOnTop( mp_fileSharing, Settings::instance().stayOnTop() );
4737 mp_fileSharing->resize( qMin( (QApplication::desktop()->availableGeometry().width()-20), 760 ), 460 );
4738 mp_fileSharing->updateLocalFileList();
4739 connect( mp_fileSharing, SIGNAL( destroyed() ), this, SLOT( onFileSharingWindowClosed() ) );
4740 connect( mp_fileSharing, SIGNAL( openUrlRequest( const QUrl& ) ), this, SLOT( openUrl( const QUrl& ) ) );
4741 connect( mp_fileSharing, SIGNAL( sendFileRequest( const QString& ) ), this, SLOT( sendFile( const QString& ) ) );
4742 connect( mp_fileSharing, SIGNAL( downloadSharedFileRequest( VNumber, VNumber ) ), this, SLOT( downloadSharedFile( VNumber, VNumber ) ) );
4743 connect( mp_fileSharing, SIGNAL( downloadSharedFilesRequest( const QList<SharedFileInfo>& ) ), this, SLOT( downloadSharedFiles( QList<SharedFileInfo> ) ) );
4744 connect( beeCore, SIGNAL( userChanged( const User& ) ), mp_fileSharing, SLOT( onUserChanged( const User& ) ) );
4745 }
4746 mp_fileSharing->showUp();
4747 }
4748
onFileSharingWindowClosed()4749 void GuiMain::onFileSharingWindowClosed()
4750 {
4751 if( mp_fileSharing )
4752 mp_fileSharing = Q_NULLPTR;
4753 }
4754
showScreenShotWindow()4755 void GuiMain::showScreenShotWindow()
4756 {
4757 if( !mp_screenShot )
4758 {
4759 mp_screenShot = new GuiScreenShot;
4760 mp_screenShot->setAttribute( Qt::WA_DeleteOnClose, true );
4761 Bee::setWindowStaysOnTop( mp_screenShot, Settings::instance().stayOnTop() );
4762 mp_screenShot->resize( 620, 460 );
4763 connect( mp_screenShot, SIGNAL( screenShotToSend( const QString& ) ), this, SLOT( sendFile( const QString& ) ) );
4764 connect( mp_screenShot, SIGNAL( destroyed() ), this, SLOT( onScreenShotWindowClosed() ) );
4765 }
4766 mp_screenShot->showUp();
4767 }
4768
onScreenShotWindowClosed()4769 void GuiMain::onScreenShotWindowClosed()
4770 {
4771 if( mp_screenShot )
4772 mp_screenShot = Q_NULLPTR;
4773 }
4774
showLogWindow()4775 void GuiMain::showLogWindow()
4776 {
4777 if( !mp_log )
4778 {
4779 mp_log = new GuiLog;
4780 Bee::setWindowStaysOnTop( mp_log, Settings::instance().stayOnTop() );
4781 mp_log->resize( qMin( (QApplication::desktop()->availableGeometry().width()-20), 760 ), 460 );
4782 connect( mp_log, SIGNAL( destroyed() ), this, SLOT( onLogWindowClosed() ) );
4783 }
4784 mp_log->showUp();
4785 }
4786
onLogWindowClosed()4787 void GuiMain::onLogWindowClosed()
4788 {
4789 if( mp_log )
4790 mp_log = Q_NULLPTR;
4791 }
4792
onMainTabChanged(int tab_index)4793 void GuiMain::onMainTabChanged( int tab_index )
4794 {
4795 if( mp_tabMain->widget( tab_index ) == mp_home )
4796 {
4797 m_unreadActivities = 0;
4798 updateTabTitles();
4799 }
4800
4801 if( m_changeTabToUserListOnFirstConnected )
4802 m_changeTabToUserListOnFirstConnected = false;
4803 }
4804
setFileTransferEnabled(bool enable)4805 void GuiMain::setFileTransferEnabled( bool enable )
4806 {
4807 if( Settings::instance().disableFileTransfer() )
4808 return;
4809
4810 Settings::instance().setEnableFileTransfer( enable );
4811 if( !enable )
4812 {
4813 Settings::instance().setEnableFileSharing( false );
4814 Settings::instance().setUseShareBox( false );
4815 mp_actEnableFileSharing->setChecked( false );
4816 beeCore->stopFileTransferServer();
4817 QMetaObject::invokeMethod( beeCore, "buildLocalShareList", Qt::QueuedConnection );
4818 }
4819 else
4820 {
4821 if( !Bee::folderIsWriteable( Settings::instance().downloadDirectory(), false ) )
4822 {
4823 QMessageBox::warning( this, Settings::instance().programName(), tr( "The download folder does not exists or is not writable. Please select a new one." ), tr( "Ok" ) );
4824 selectDownloadDirectory();
4825 }
4826 beeCore->startFileTransferServer();
4827 }
4828 checkViewActions();
4829 }
4830
setFileSharingEnabled(bool enable)4831 void GuiMain::setFileSharingEnabled( bool enable )
4832 {
4833 if( Settings::instance().disableFileTransfer() || Settings::instance().disableFileSharing() )
4834 return;
4835
4836 Settings::instance().setEnableFileSharing( enable );
4837 QMetaObject::invokeMethod( beeCore, "buildLocalShareList", Qt::QueuedConnection );
4838 checkViewActions();
4839 if( !enable )
4840 {
4841 if( mp_fileSharing )
4842 mp_fileSharing->close();
4843 }
4844 }
4845
showWorkgroups()4846 void GuiMain::showWorkgroups()
4847 {
4848 GuiWorkgroups gw;
4849 gw.loadWorkgroups();
4850 gw.setModal( true );
4851 gw.setSizeGripEnabled( true );
4852 gw.show();
4853 if( gw.exec() != QDialog::Accepted )
4854 return;
4855
4856 if( Settings::instance().acceptConnectionsOnlyFromWorkgroups() && !Settings::instance().localUser().workgroups().isEmpty() )
4857 qDebug() << "You have selected to accept connections only from these workgroups:" << qPrintable( Settings::instance().localUser().workgroups().join( ", " ) );
4858
4859 if( gw.restartConnection() )
4860 showRestartConnectionAlertMessage();
4861 }
4862
showRefusedChats()4863 void GuiMain::showRefusedChats()
4864 {
4865 GuiRefusedChat grc;
4866 int previous_refused_chats = grc.loadRefusedChats();
4867 grc.setModal( true );
4868 grc.setSizeGripEnabled( true );
4869 grc.show();
4870 if( grc.exec() == QDialog::Accepted )
4871 {
4872 showMessage( tr( "%1 blocked chats" ).arg( Settings::instance().refusedChats().size() ), 5000 );
4873 if( previous_refused_chats != ChatManager::instance().refusedChats().size() )
4874 showRestartConnectionAlertMessage();
4875 }
4876 }
4877
selectIconSourcePath()4878 void GuiMain::selectIconSourcePath()
4879 {
4880 int ret_code = 1;
4881 if( Settings::instance().iconSourcePath().isEmpty() )
4882 {
4883 ret_code = QMessageBox::information( this, Settings::instance().programName(),
4884 tr( "You are using the default icons." ),
4885 tr( "Select the icon folder" ), tr( "Cancel" ), QString(), 1, 1 );
4886 }
4887 else
4888 {
4889 ret_code = QMessageBox::information( this, Settings::instance().programName(),
4890 tr( "You are using custom icons in folder %1." ).arg( Settings::instance().iconSourcePath() ),
4891 tr( "Select the icon folder" ), tr( "Cancel" ), tr( "Restore default icons" ), 1, 1 );
4892 }
4893
4894 if( ret_code == 1 )
4895 return;
4896
4897 QString icon_source_path = "";
4898 if( ret_code == 0 )
4899 {
4900 icon_source_path = QFileDialog::getExistingDirectory( this, tr( "Select the icon folder" ),
4901 Settings::instance().iconSourcePath().isEmpty() ? Settings::instance().resourceFolder() : Settings::instance().iconSourcePath() );
4902 if( icon_source_path.isEmpty() )
4903 return;
4904
4905 icon_source_path = Bee::convertToNativeFolderSeparator( icon_source_path );
4906 }
4907
4908 if( icon_source_path != Settings::instance().iconSourcePath() )
4909 {
4910 showRestartApplicationAlertMessage();
4911 Settings::instance().setIconSourcePath( icon_source_path );
4912 }
4913 }
4914
selectEmoticonSourcePath()4915 void GuiMain::selectEmoticonSourcePath()
4916 {
4917 int ret_code = 1;
4918 if( Settings::instance().emoticonSourcePath().isEmpty() )
4919 {
4920 ret_code = QMessageBox::information( this, Settings::instance().programName(),
4921 tr( "You are using the default emoticons." ),
4922 tr( "Select the emoticon folder" ), tr( "Cancel" ), QString(), 1, 1 );
4923 }
4924 else
4925 {
4926 ret_code = QMessageBox::information( this, Settings::instance().programName(),
4927 tr( "You are using custom emoticons in folder %1." ).arg( Settings::instance().emoticonSourcePath() ),
4928 tr( "Select the emoticon folder" ), tr( "Cancel" ), tr( "Restore default emoticons" ), 1, 1 );
4929 }
4930
4931 if( ret_code == 1 )
4932 return;
4933
4934 QString emoticon_source_path = "";
4935 if( ret_code == 0 )
4936 {
4937 emoticon_source_path = QFileDialog::getExistingDirectory( this, tr( "Select the emoticon folder" ),
4938 Settings::instance().emoticonSourcePath().isEmpty() ? Settings::instance().resourceFolder() : Settings::instance().emoticonSourcePath() );
4939 if( emoticon_source_path.isEmpty() )
4940 return;
4941
4942 emoticon_source_path = Bee::convertToNativeFolderSeparator( emoticon_source_path );
4943 }
4944
4945 if( emoticon_source_path != Settings::instance().emoticonSourcePath() )
4946 {
4947 Settings::instance().setEmoticonSourcePath( emoticon_source_path );
4948 updateEmoticons();
4949 }
4950 }
4951
showRestartConnectionAlertMessage()4952 void GuiMain::showRestartConnectionAlertMessage()
4953 {
4954 if( QMessageBox::information( this, Settings::instance().programName(), tr( "You have to restart your connection to apply changes." ),
4955 tr( "Restart connection now" ), tr( "Restart later manually" ), QString(), 0, 1 ) == 0 )
4956 {
4957 QTimer::singleShot( 0, this, SLOT( restartCore() ) );
4958 }
4959 }
4960
showRestartApplicationAlertMessage()4961 void GuiMain::showRestartApplicationAlertMessage()
4962 {
4963 QMessageBox::information( this, Settings::instance().programName(), tr( "You must restart %1 to apply these changes." ).arg( Settings::instance().programName() ), tr( "Ok" ) );
4964 }
4965
onNewsAvailable(const QString & news)4966 void GuiMain::onNewsAvailable( const QString& news )
4967 {
4968 #ifdef BEEBEEP_DEBUG
4969 qDebug() << "News from the website available:" << qPrintable( news );
4970 #endif
4971 mp_home->setNews( news );
4972 }
4973
createMessage()4974 void GuiMain::createMessage()
4975 {
4976 if( Settings::instance().disableCreateMessage() )
4977 {
4978 QMessageBox::information( this, Settings::instance().programName(),
4979 tr( "You are not allowed create new message." ) + QString( " " ) + tr( "The option has been disabled by your system administrator." ),
4980 tr( "Ok" ) );
4981 return;
4982 }
4983 GuiCreateMessage gcm;
4984 gcm.setModal( true );
4985 gcm.setSizeGripEnabled( true );
4986 gcm.show();
4987 if( gcm.exec() == QDialog::Accepted )
4988 {
4989 if( !gcm.toChatIdList().isEmpty() )
4990 {
4991 int max_chat_to_open = 6;
4992 int num_chat_opened = 0;
4993 foreach( VNumber chat_id, gcm.toChatIdList() )
4994 {
4995 beeCore->sendChatMessage( chat_id, gcm.message(), gcm.messageIsImportant() );
4996 mp_chatList->updateChat( ChatManager::instance().chat( chat_id ) ); // to sort the chats
4997 if( gcm.openChat() && num_chat_opened < max_chat_to_open )
4998 {
4999 showChat( chat_id );
5000 num_chat_opened++;
5001 }
5002 }
5003 updateTabTitles();
5004 }
5005 }
5006 }
5007
updateChatFont()5008 void GuiMain::updateChatFont()
5009 {
5010 if( m_floatingChats.isEmpty() )
5011 return;
5012
5013 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
5014 fl_chat->guiChat()->setChatFont( Settings::instance().chatFont() );
5015 }
5016
updateChatColors()5017 void GuiMain::updateChatColors()
5018 {
5019 if( m_floatingChats.isEmpty() )
5020 return;
5021
5022 foreach( GuiFloatingChat* fl_chat, m_floatingChats )
5023 {
5024 if( fl_chat->guiChat()->chatId() != ID_DEFAULT_CHAT )
5025 fl_chat->guiChat()->updateChatColors();
5026 }
5027 }
5028
resetAllColors()5029 void GuiMain::resetAllColors()
5030 {
5031 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you really want to restore the colors to the default ones?" ), tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) == 0 )
5032 {
5033 Settings::instance().resetAllColors();
5034 Settings::instance().save();
5035 loadStyle();
5036 }
5037 }
5038
onHideEmptyChatsRequest()5039 void GuiMain::onHideEmptyChatsRequest()
5040 {
5041 Settings::instance().setHideEmptyChatsInList( !Settings::instance().hideEmptyChatsInList() );
5042 mp_chatList->updateChats();
5043 }
5044
onApplicationFocusChanged(QWidget * old,QWidget * now)5045 void GuiMain::onApplicationFocusChanged( QWidget* old, QWidget* now )
5046 {
5047 if( old == Q_NULLPTR && isAncestorOf( now ) )
5048 {
5049 #ifdef BEEBEEP_DEBUG
5050 qDebug() << "Main window has grabbed focus";
5051 #endif
5052 m_prevActivatedState = true;
5053 return;
5054 }
5055
5056 if( isAncestorOf( old ) && now == Q_NULLPTR )
5057 {
5058 #ifdef BEEBEEP_DEBUG
5059 qDebug() << "Main window has lost focus";
5060 #endif
5061 m_prevActivatedState = false;
5062 return;
5063 }
5064
5065 bool current_state = isActiveWindow();
5066 if( current_state != m_prevActivatedState )
5067 {
5068 m_prevActivatedState = current_state;
5069 #ifdef BEEBEEP_DEBUG
5070 if( current_state )
5071 qDebug() << "Main window has grabbed focus (active)";
5072 else
5073 qDebug() << "Main window has lost focus (active)";
5074 #endif
5075 }
5076 }
5077
5078 #ifdef BEEBEEP_USE_WEBENGINE
showWebView()5079 void GuiMain::showWebView()
5080 {
5081 mp_webView->show();
5082 }
5083
onNewsLoad(bool ok)5084 void GuiMain::onNewsLoad( bool ok )
5085 {
5086 mp_actWebView->setEnabled( ok );
5087 }
5088 #endif
5089
5090 #ifdef BEEBEEP_USE_SHAREDESKTOP
onShareDesktopImageAvailable(const User & u,const QImage & img,const QString & image_type,QRgb diff_color)5091 void GuiMain::onShareDesktopImageAvailable( const User& u, const QImage& img, const QString& image_type, QRgb diff_color )
5092 {
5093 foreach( GuiShareDesktop* gsd, m_desktops )
5094 {
5095 if( gsd->userId() == u.id() )
5096 {
5097 if( img.isNull() )
5098 gsd->close();
5099 else
5100 gsd->updateImage( img, image_type, diff_color );
5101 return;
5102 }
5103 }
5104
5105 if( img.isNull() )
5106 return;
5107
5108 int desktop_h = qApp->desktop()->availableGeometry().height() - 50;
5109 int desktop_w = qApp->desktop()->availableGeometry().width() - 80;
5110 int frame_w = frameGeometry().width() - geometry().width();
5111 int frame_h = frameGeometry().height() - geometry().height();
5112 int max_img_w = img.width()+ frame_w;
5113 int max_img_h = img.height()+ frame_h;
5114
5115 GuiShareDesktop* new_gui = new GuiShareDesktop;
5116 connect( new_gui, SIGNAL( shareDesktopClosed( VNumber ) ), this, SLOT( onShareDesktopCloseEvent( VNumber ) ) );
5117 connect( new_gui, SIGNAL( shareDesktopDeleteRequest( VNumber ) ), this, SLOT( onShareDesktopDeleteRequest( VNumber ) ) );
5118 new_gui->setUser( u );
5119 new_gui->setGeometry( 10, 40, qMin( max_img_w, qMax( 640, desktop_w ) ), qMin( max_img_h, qMax( 480, desktop_h ) ) );
5120 new_gui->setMaximumSize( max_img_w, max_img_h );
5121 new_gui->show();
5122 new_gui->updateImage( img, image_type, diff_color );
5123
5124 m_desktops.append( new_gui );
5125 }
5126
onShareDesktopCloseEvent(VNumber user_id)5127 void GuiMain::onShareDesktopCloseEvent( VNumber user_id )
5128 {
5129 #ifdef BEEBEEP_DEBUG
5130 qDebug() << "You close the desktop shared viewer for user" << user_id;
5131 #endif
5132 beeCore->refuseToViewShareDesktop( ID_LOCAL_USER, user_id );
5133 }
5134
onShareDesktopDeleteRequest(VNumber user_id)5135 void GuiMain::onShareDesktopDeleteRequest( VNumber user_id )
5136 {
5137 QList<GuiShareDesktop*>::iterator it = m_desktops.begin();
5138 while( it != m_desktops.end() )
5139 {
5140 if( (*it)->userId() == user_id )
5141 {
5142 #ifdef BEEBEEP_DEBUG
5143 qDebug() << "Delete GuiShareDesktop for user" << user_id;
5144 #endif
5145 (*it)->disconnect();
5146 (*it)->deleteLater();
5147 m_desktops.erase( it );
5148 return;
5149 }
5150 }
5151 }
5152
onShareDesktopRequestFromChat(VNumber chat_id,bool enable_desktop_sharing)5153 void GuiMain::onShareDesktopRequestFromChat( VNumber chat_id, bool enable_desktop_sharing )
5154 {
5155 if( chat_id == ID_DEFAULT_CHAT )
5156 return;
5157
5158 if( beeCore->shareDesktopIsActive( ID_INVALID ) == enable_desktop_sharing )
5159 return;
5160
5161 Chat c = ChatManager::instance().chat( chat_id );
5162 if( !c.isValid() )
5163 {
5164 qWarning() << "Invalid chat" << chat_id << "found in GuiMain::onShareDesktopRequestFromChat(...)";
5165 return;
5166 }
5167
5168 if( enable_desktop_sharing )
5169 {
5170 if( QMessageBox::question( activeWindow(), Settings::instance().programName(),
5171 tr( "Do you really want to share your desktop with %1?" ).arg( c.name() ),
5172 tr( "Yes" ), tr( "No" ), QString(), 0, 1 ) == 1 )
5173 return;
5174
5175 foreach( VNumber user_id, c.usersId() )
5176 {
5177 if( user_id != ID_LOCAL_USER )
5178 beeCore->startShareDesktop( user_id );
5179 }
5180 }
5181 else
5182 {
5183 foreach( VNumber user_id, c.usersId() )
5184 {
5185 if( user_id != ID_LOCAL_USER )
5186 beeCore->stopShareDesktop( user_id );
5187 }
5188 }
5189 }
5190
onShareDesktopUpdate(const User & u)5191 void GuiMain::onShareDesktopUpdate( const User& u )
5192 {
5193 bool core_is_connected = beeCore->isConnected();
5194 int connected_users = beeCore->connectedUsers();
5195 bool file_transfer_is_active = beeCore->isFileTransferActive();
5196 QList<Chat> chat_list = ChatManager::instance().chatsWithUser( u.id() );
5197 foreach( Chat c, chat_list )
5198 {
5199 GuiFloatingChat* fl_chat = floatingChat( c.id() );
5200 if( fl_chat )
5201 fl_chat->guiChat()->updateActions( c, core_is_connected, connected_users, file_transfer_is_active );
5202 }
5203 }
5204
sendScreenshotToChat(VNumber chat_id)5205 void GuiMain::sendScreenshotToChat( VNumber chat_id )
5206 {
5207 QMetaObject::invokeMethod( beeCore, "sendScreenshotToChat", Qt::QueuedConnection, Q_ARG(VNumber, chat_id) );
5208 GuiFloatingChat* fl_chat = floatingChat( chat_id );
5209 if( fl_chat && fl_chat->isMinimized() )
5210 QTimer::singleShot( 200, fl_chat, SLOT( showNormal() ) );
5211 }
5212 #endif
5213
showNetworkTest()5214 void GuiMain::showNetworkTest()
5215 {
5216 if( !mp_networkTest )
5217 {
5218 mp_networkTest = new GuiNetworkTest( this );
5219 mp_networkTest->updateSettings( Settings::instance().enableFileTransfer() ? QString::number( beeCore->fileTransferPort() ) : tr( "disabled" ) );
5220 connect( mp_networkTest, SIGNAL( destroyed() ), this, SLOT( onScreenShotWindowClosed() ) );
5221 }
5222 mp_networkTest->showUp();
5223 }
5224
onNetworkTestWindowClosed()5225 void GuiMain::onNetworkTestWindowClosed()
5226 {
5227 if( mp_networkTest )
5228 mp_networkTest = Q_NULLPTR;
5229 }
5230
setMinimumWidthForStyle()5231 void GuiMain::setMinimumWidthForStyle()
5232 {
5233 if( Settings::instance().resetMinimumWidthForStyle() )
5234 {
5235 int old_w = width();
5236 int wasted_w = 20;
5237 #if defined( Q_OS_MAC )
5238 int icon_wasted_w = m_useFusionStyle ? 4 : 8;
5239 int min_w = qMax( 300, mp_barMain->actions().size() * (mp_barMain->iconSize().width() + icon_wasted_w) + wasted_w );
5240 #elif defined( Q_OS_UNIX )
5241 int min_w = qMax( 320, mp_barMain->actions().size() * (mp_barMain->iconSize().width()+4) + wasted_w );
5242 #elif defined( Q_OS_WIN )
5243 int min_w = qMax( 320, mp_barMain->actions().size() * (mp_barMain->iconSize().width()+2) + wasted_w );
5244 #else
5245 int min_w = qMax( 320, mp_barMain->actions().size() * (mp_barMain->iconSize().width()+2) + wasted_w );
5246 #endif
5247 setMinimumWidth( min_w );
5248 if( min_w > old_w )
5249 {
5250 int new_pos_x = qMax( 1, pos().x() - (min_w - old_w) );
5251 move( new_pos_x, pos().y() );
5252 }
5253 }
5254 else
5255 setMinimumWidth( 90 );
5256 }
5257
loadStyle()5258 void GuiMain::loadStyle()
5259 {
5260 QStyle* p_style = QStyleFactory::create( "Fusion" );
5261 if( p_style )
5262 {
5263 beeApp->setStyle( p_style );
5264 m_useFusionStyle = true;
5265 }
5266 else
5267 {
5268 beeApp->resetStyle();
5269 m_useFusionStyle = false;
5270 }
5271
5272 if( Settings::instance().useDarkStyle() )
5273 {
5274 qDebug() << "Stylesheet:" << (m_useFusionStyle ? "Fusion" : "System Default") << "Dark";
5275 beeApp->setPalette( Bee::darkPalette() );
5276 }
5277 else
5278 {
5279 qDebug() << "Stylesheet:" << (m_useFusionStyle ? "Fusion" : "System Default" );
5280 beeApp->resetPalette();
5281 }
5282
5283 setMinimumWidthForStyle();
5284
5285 mp_home->updateBackground();
5286 mp_userList->updateBackground();
5287 mp_chatList->updateBackground();
5288 mp_groupList->updateBackground();
5289 mp_savedChatList->updateBackground();
5290 updateChatColors();
5291 updateEmoticons();
5292 }
5293
5294 #ifdef BEEBEEP_USE_VOICE_CHAT
sendVoiceMessageToChat(VNumber chat_id,const QString & file_path,qint64 message_duration)5295 void GuiMain::sendVoiceMessageToChat( VNumber chat_id, const QString& file_path, qint64 message_duration )
5296 {
5297 beeCore->sendVoiceMessageToChat( chat_id, file_path, message_duration );
5298 }
5299
showVoiceEncoderSettings()5300 void GuiMain::showVoiceEncoderSettings()
5301 {
5302 GuiRecordVoiceMessageSettings grvm( this );
5303 grvm.setModal( true );
5304 grvm.init();
5305 grvm.loadSettings();
5306 grvm.show();
5307 if( grvm.exec() == QDialog::Accepted )
5308 {
5309 Settings::instance().save();
5310 AudioManager::instance().checkDefaultAudioDevice();
5311 }
5312 }
5313 #endif
5314
resumeFileTransfer(VNumber user_id,const FileInfo & file_info)5315 void GuiMain::resumeFileTransfer( VNumber user_id, const FileInfo& file_info )
5316 {
5317 beeCore->resumeFileTransfer( user_id, file_info );
5318 }
5319