From 37986e00a38cb23e62caad0951cc63f3bf4df862 Mon Sep 17 00:00:00 2001 From: thunder2 Date: Fri, 30 Mar 2012 23:02:52 +0000 Subject: [PATCH] Added three new toasters - private chat, group chat and chat lobby. Fixed some utf8 issues in toasters and feeds. Fixed german language. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5065 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/retroshare/rsnotify.h | 14 +- libretroshare/src/services/p3chatservice.cc | 17 +- libretroshare/src/services/p3msgservice.cc | 9 +- retroshare-gui/src/RetroShare.pro | 9 + retroshare-gui/src/gui/ChatLobbyWidget.cpp | 4 +- retroshare-gui/src/gui/FriendsDialog.cpp | 26 ++ retroshare-gui/src/gui/FriendsDialog.h | 2 + retroshare-gui/src/gui/FriendsDialog.ui | 2 +- retroshare-gui/src/gui/MainWindow.cpp | 68 +++++- retroshare-gui/src/gui/MainWindow.h | 1 + .../src/gui/chat/ChatLobbyDialog.cpp | 2 + retroshare-gui/src/gui/chat/ChatWidget.cpp | 11 +- retroshare-gui/src/gui/chat/ChatWidget.h | 2 + retroshare-gui/src/gui/chat/ChatWidget.ui | 6 - retroshare-gui/src/gui/feeds/ChatMsgItem.cpp | 2 +- retroshare-gui/src/gui/notifyqt.cpp | 65 +++-- .../src/gui/settings/NotifyPage.cpp | 9 + retroshare-gui/src/gui/settings/NotifyPage.ui | 23 +- .../src/gui/toaster/ChatLobbyToaster.cpp | 62 +++++ .../src/gui/toaster/ChatLobbyToaster.h | 49 ++++ .../src/gui/toaster/ChatLobbyToaster.ui | 208 ++++++++++++++++ .../src/gui/toaster/ChatToaster.cpp | 49 ++++ retroshare-gui/src/gui/toaster/ChatToaster.h | 49 ++++ retroshare-gui/src/gui/toaster/ChatToaster.ui | 207 ++++++++++++++++ .../src/gui/toaster/GroupChatToaster.cpp | 48 ++++ .../src/gui/toaster/GroupChatToaster.h | 47 ++++ .../src/gui/toaster/GroupChatToaster.ui | 216 +++++++++++++++++ .../src/gui/toaster/MessageToaster.cpp | 6 +- .../src/gui/toaster/MessageToaster.h | 2 +- .../src/gui/toaster/OnlineToaster.cpp | 14 +- .../src/gui/toaster/OnlineToaster.h | 2 +- .../src/gui/toaster/OnlineToaster.ui | 55 ++--- retroshare-gui/src/lang/retroshare_de.qm | Bin 414839 -> 415252 bytes retroshare-gui/src/lang/retroshare_de.ts | 227 +++++++++++------- retroshare-gui/src/util/EventReceiver.cpp | 61 +---- 35 files changed, 1335 insertions(+), 239 deletions(-) create mode 100644 retroshare-gui/src/gui/toaster/ChatLobbyToaster.cpp create mode 100644 retroshare-gui/src/gui/toaster/ChatLobbyToaster.h create mode 100644 retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui create mode 100644 retroshare-gui/src/gui/toaster/ChatToaster.cpp create mode 100644 retroshare-gui/src/gui/toaster/ChatToaster.h create mode 100644 retroshare-gui/src/gui/toaster/ChatToaster.ui create mode 100644 retroshare-gui/src/gui/toaster/GroupChatToaster.cpp create mode 100644 retroshare-gui/src/gui/toaster/GroupChatToaster.h create mode 100644 retroshare-gui/src/gui/toaster/GroupChatToaster.ui diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h index aabd86245..ee65ff2af 100644 --- a/libretroshare/src/retroshare/rsnotify.h +++ b/libretroshare/src/retroshare/rsnotify.h @@ -38,14 +38,16 @@ extern RsNotify *rsNotify; const uint32_t RS_SYS_ERROR = 0x0001; const uint32_t RS_SYS_WARNING = 0x0002; -const uint32_t RS_SYS_INFO = 0x0004; +const uint32_t RS_SYS_INFO = 0x0004; -const uint32_t RS_POPUP_MSG = 0x0001; -//const uint32_t RS_POPUP_CHAT = 0x0002; -//const uint32_t RS_POPUP_CALL = 0x0004; -const uint32_t RS_POPUP_CONNECT = 0x0008; +const uint32_t RS_POPUP_MSG = 0x0001; +const uint32_t RS_POPUP_CHAT = 0x0002; +//const uint32_t RS_POPUP_CALL = 0x0004; +const uint32_t RS_POPUP_CONNECT = 0x0008; const uint32_t RS_SYSTRAY_GROUP_MSG = 0x0010; -const uint32_t RS_POPUP_DOWNLOAD = 0x0020; +const uint32_t RS_POPUP_DOWNLOAD = 0x0020; +const uint32_t RS_POPUP_GROUPCHAT = 0x0040; +const uint32_t RS_POPUP_CHATLOBBY = 0x0080; /* CHAT flags are here - so they are in the same place as * other Notify flags... not used by libretroshare though diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index 6ce8ef8e9..e9fcbd59d 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -25,6 +25,7 @@ #include "util/rsdir.h" #include "util/rsrandom.h" +#include "util/rsstring.h" #include "retroshare/rsiface.h" #include "retroshare/rspeers.h" #include "pqi/pqibin.h" @@ -848,6 +849,8 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci) bool privateChanged = false; time_t now = time(NULL); + std::string name; + uint32_t popupChatFlag = RS_POPUP_CHAT; // check if it's a lobby msg, in which case we replace the peer id by the lobby's virtual peer id. // @@ -878,7 +881,9 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci) // std::string virtual_peer_id ; getVirtualPeerId(cli->lobby_id,virtual_peer_id) ; - cli->PeerId(virtual_peer_id) ; + cli->PeerId(virtual_peer_id) ; + name = cli->nick; + popupChatFlag = RS_POPUP_CHATLOBBY; } else { @@ -927,10 +932,14 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci) ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; } - if ((ci->chatFlags & RS_CHAT_FLAG_PRIVATE) == 0) { + std::string message; + librs::util::ConvertUtf16ToUtf8(ci->message, message); + if (ci->chatFlags & RS_CHAT_FLAG_PRIVATE) { + /* notify private chat message */ + getPqiNotify()->AddPopupMessage(popupChatFlag, ci->PeerId(), name, message); + } else { /* notify public chat message */ - std::string message; - message.assign(ci->message.begin(), ci->message.end()); + getPqiNotify()->AddPopupMessage(RS_POPUP_GROUPCHAT, ci->PeerId(), "", message); getPqiNotify()->AddFeedItem(RS_FEED_ITEM_CHAT_NEW, ci->PeerId(), message, ""); } diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index 879c462a7..a0b3cf0e8 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -35,6 +35,7 @@ #include "util/rsdebug.h" #include "util/rsdir.h" +#include "util/rsstring.h" #include #include @@ -150,10 +151,10 @@ void p3MsgService::processMsg(RsMsgItem *mi) pqiNotify *notify = getPqiNotify(); if (notify) { - std::string message , title; - notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId(), - title.assign(mi->subject.begin(), mi->subject.end()), - message.assign(mi->message.begin(),mi->message.end())); + std::string title, message; + librs::util::ConvertUtf16ToUtf8(mi->subject, title); + librs::util::ConvertUtf16ToUtf8(mi->message, message); + notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId(), title, message); std::ostringstream out; out << mi->msgId; diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index 7fd4f9f08..d4776d01c 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -331,6 +331,9 @@ HEADERS += rshare.h \ gui/toaster/MessageToaster.h \ gui/toaster/OnlineToaster.h \ gui/toaster/DownloadToaster.h \ + gui/toaster/ChatToaster.h \ + gui/toaster/GroupChatToaster.h \ + gui/toaster/ChatLobbyToaster.h \ gui/common/vmessagebox.h \ gui/common/RsUrlHandler.h \ gui/common/RsCollectionFile.h \ @@ -461,6 +464,9 @@ FORMS += gui/StartDialog.ui \ gui/toaster/MessageToaster.ui \ gui/toaster/OnlineToaster.ui \ gui/toaster/DownloadToaster.ui \ + gui/toaster/ChatToaster.ui \ + gui/toaster/GroupChatToaster.ui \ + gui/toaster/ChatLobbyToaster.ui \ gui/advsearch/AdvancedSearchDialog.ui \ gui/advsearch/expressionwidget.ui \ gui/NewsFeed.ui \ @@ -633,6 +639,9 @@ SOURCES += main.cpp \ gui/toaster/MessageToaster.cpp \ gui/toaster/DownloadToaster.cpp \ gui/toaster/OnlineToaster.cpp \ + gui/toaster/ChatToaster.cpp \ + gui/toaster/GroupChatToaster.cpp \ + gui/toaster/ChatLobbyToaster.cpp \ gui/advsearch/advancedsearchdialog.cpp \ gui/advsearch/expressionwidget.cpp \ gui/advsearch/guiexprelement.cpp \ diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index 859d6a22d..9bc4dd95f 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -126,8 +126,8 @@ static void updateItem(QTreeWidgetItem *item, ChatLobbyId id, const std::string if(topic.empty()) { - item->setText(COLUMN_TOPIC, QObject::tr("[No topic provided]")); - item->setData(COLUMN_TOPIC, ROLE_SORT, QObject::tr("[No topic provided]")); + item->setText(COLUMN_TOPIC, qApp->translate("ChatLobbyWidget", "[No topic provided]")); + item->setData(COLUMN_TOPIC, ROLE_SORT, qApp->translate("ChatLobbyWidget", "[No topic provided]")); } else { diff --git a/retroshare-gui/src/gui/FriendsDialog.cpp b/retroshare-gui/src/gui/FriendsDialog.cpp index b2cf51bbf..cb230f79e 100644 --- a/retroshare-gui/src/gui/FriendsDialog.cpp +++ b/retroshare-gui/src/gui/FriendsDialog.cpp @@ -847,3 +847,29 @@ void FriendsDialog::recommendFriends() { return instance ? instance->ui.tabWidget : NULL; } + +/*static*/ bool FriendsDialog::isGroupChatActive() +{ + FriendsDialog *friendsDialog = dynamic_cast(MainWindow::getPage(MainWindow::Friends)); + if (!friendsDialog) { + return false; + } + + if (friendsDialog->ui.tabWidget->currentWidget() == friendsDialog->ui.groupChatTab) { + return true; + } + + return false; +} + +/*static*/ void FriendsDialog::groupChatActivate() +{ + FriendsDialog *friendsDialog = dynamic_cast(MainWindow::getPage(MainWindow::Friends)); + if (!friendsDialog) { + return; + } + + MainWindow::showWindow(MainWindow::Friends); + friendsDialog->ui.tabWidget->setCurrentWidget(friendsDialog->ui.groupChatTab); + friendsDialog->ui.lineEdit->setFocus(); +} diff --git a/retroshare-gui/src/gui/FriendsDialog.h b/retroshare-gui/src/gui/FriendsDialog.h index 5a1695520..ab6fcef5f 100644 --- a/retroshare-gui/src/gui/FriendsDialog.h +++ b/retroshare-gui/src/gui/FriendsDialog.h @@ -47,6 +47,8 @@ public: virtual void updateDisplay() ; // overloaded from RsAutoUpdatePage static ChatTabWidget *getTabWidget(); + static bool isGroupChatActive(); + static void groupChatActivate(); public slots: diff --git a/retroshare-gui/src/gui/FriendsDialog.ui b/retroshare-gui/src/gui/FriendsDialog.ui index dc3f02c16..bff4130e0 100644 --- a/retroshare-gui/src/gui/FriendsDialog.ui +++ b/retroshare-gui/src/gui/FriendsDialog.ui @@ -817,7 +817,7 @@ p, li { white-space: pre-wrap; } true - + Group Chat diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 9179fe51f..ced4d280f 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -947,6 +947,72 @@ void MainWindow::addAction(QAction *action, const char *slot) connect(action, SIGNAL(triggered()), this, slot); } +#ifdef WINDOWS_SYS +//void SetForegroundWindowInternal(HWND hWnd) +//{ +// if (!::IsWindow(hWnd)) return; + +// // relation time of SetForegroundWindow lock +// DWORD lockTimeOut = 0; +// HWND hCurrWnd = ::GetForegroundWindow(); +// DWORD dwThisTID = ::GetCurrentThreadId(), +// dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0); + +// // we need to bypass some limitations from Microsoft :) +// if (dwThisTID != dwCurrTID) { +// ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE); + +// ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0); +// ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); + +// ::AllowSetForegroundWindow(ASFW_ANY); +// } + +// ::SetForegroundWindow(hWnd); + +// if(dwThisTID != dwCurrTID) { +// ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); +// ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE); +// } +//} + +void SetForegroundWindowInternal(HWND hWnd) +{ + if (!::IsWindow(hWnd)) return; + + BYTE keyState[256] = {0}; + // to unlock SetForegroundWindow we need to imitate Alt pressing + if (::GetKeyboardState((LPBYTE)&keyState)) { + if(!(keyState[VK_MENU] & 0x80)) { + ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0); + } + } + + ::SetForegroundWindow(hWnd); + + if (::GetKeyboardState((LPBYTE)&keyState)) { + if(!(keyState[VK_MENU] & 0x80)) { + ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + } + } +} +#endif + +/*static*/ void MainWindow::raiseWindow() +{ + if (_instance == NULL) { + return; + } + + /* Show the dialog. */ + _instance->show(); + _instance->raise(); + +#ifdef WINDOWS_SYS + SetForegroundWindowInternal(_instance->winId()); +#endif +} + /** Shows the MainWindow with focus set to the given page. */ /*static*/ void MainWindow::showWindow(Page page) { @@ -955,7 +1021,7 @@ void MainWindow::addAction(QAction *action, const char *slot) } /* Show the dialog. */ - _instance->show(); + raiseWindow(); /* Set the focus to the specified page. */ activatePage (page); } diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index 6fba1ab72..b3c5622eb 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -93,6 +93,7 @@ public: /** Destructor. */ ~MainWindow(); + static void raiseWindow(); /** Shows the MainWindow dialog with focus set to the given page. */ static void showWindow(Page page); /** Set focus to the given page. */ diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index dfb45aa4c..978eff885 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -27,6 +27,7 @@ #include "ChatTabWidget.h" #include "gui/settings/rsharesettings.h" #include "gui/settings/RsharePeerSettings.h" +#include "gui/MainWindow.h" #include "gui/FriendsDialog.h" #include @@ -219,6 +220,7 @@ bool ChatLobbyDialog::canClose() void ChatLobbyDialog::showDialog(uint chatflags) { if (chatflags & RS_CHAT_FOCUS) { + MainWindow::showWindow(MainWindow::Friends); ChatTabWidget *tabWidget = FriendsDialog::getTabWidget(); if (tabWidget) { tabWidget->setCurrentWidget(this); diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index a09d78f26..15753ac20 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -331,7 +331,7 @@ void ChatWidget::addChatMsg(bool incoming, const QString &name, const QDateTime if (incoming && chatType == TYPE_NORMAL) { emit newMessage(this); - if (!isVisible() || (window() && (!window()->isActiveWindow() || window()->isMinimized()))) { + if (!isActive()) { newMessages = true; } @@ -339,6 +339,15 @@ void ChatWidget::addChatMsg(bool incoming, const QString &name, const QDateTime } } +bool ChatWidget::isActive() +{ + if (!isVisible() || (window() && (!window()->isActiveWindow() || window()->isMinimized()))) { + return false; + } + + return true; +} + void ChatWidget::pasteLink() { std::cerr << "In paste link" << std::endl; diff --git a/retroshare-gui/src/gui/chat/ChatWidget.h b/retroshare-gui/src/gui/chat/ChatWidget.h index c802ff2ea..6289bf096 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.h +++ b/retroshare-gui/src/gui/chat/ChatWidget.h @@ -75,6 +75,8 @@ public: void addChatButton(QPushButton *button) ; + bool isActive(); + private slots: void clearChatHistory(); void deleteChatHistory(); diff --git a/retroshare-gui/src/gui/chat/ChatWidget.ui b/retroshare-gui/src/gui/chat/ChatWidget.ui index e06f34f2d..9546a296e 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.ui +++ b/retroshare-gui/src/gui/chat/ChatWidget.ui @@ -36,12 +36,6 @@ - - - 0 - 0 - - Arial diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp index 495e1dc8a..316579cc9 100644 --- a/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp @@ -146,7 +146,7 @@ void ChatMsgItem::insertChat(const std::string &message) QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss"); timestampLabel->setText(timestamp); - QString formatMsg = QString::fromStdString(message); + QString formatMsg = QString::fromUtf8(message.c_str()); unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS; diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp index ceb64b30e..ca9cd5215 100644 --- a/retroshare-gui/src/gui/notifyqt.cpp +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -27,12 +27,6 @@ #include "notifyqt.h" #include -#include -#include -#include -#ifdef TURTLE_HOPPING -#include -#endif #include "RsAutoUpdatePage.h" @@ -41,8 +35,14 @@ #include "toaster/OnlineToaster.h" #include "toaster/MessageToaster.h" #include "toaster/DownloadToaster.h" +#include "toaster/ChatToaster.h" +#include "toaster/GroupChatToaster.h" +#include "toaster/ChatLobbyToaster.h" #endif // MINIMAL_RSGUI +#include "chat/ChatDialog.h" +#include "chat/ChatWidget.h" +#include "FriendsDialog.h" #include "gui/settings/rsharesettings.h" #include "SoundManager.h" @@ -468,21 +468,12 @@ void NotifyQt::UpdateGUI() /* You can set timeToShow, timeToLive and timeToHide or can leave the standard */ Toaster *toaster = NULL; - /* id the name */ - QString name; - - if (type == RS_POPUP_DOWNLOAD) { - /* id = file hash */ - } else { - name = QString::fromUtf8(rsPeers->getPeerName(id).c_str()); - } - switch(type) { case RS_POPUP_MSG: if (popupflags & RS_POPUP_MSG) { - toaster = new Toaster(new MessageToaster(name, QString::fromUtf8(title.c_str()), QString::fromStdString(msg))); + toaster = new Toaster(new MessageToaster(id, QString::fromUtf8(title.c_str()), QString::fromUtf8(msg.c_str()))); } break; case RS_POPUP_CONNECT: @@ -490,15 +481,55 @@ void NotifyQt::UpdateGUI() if (popupflags & RS_POPUP_CONNECT) { - toaster = new Toaster(new OnlineToaster(id, name)); + toaster = new Toaster(new OnlineToaster(id)); } break; case RS_POPUP_DOWNLOAD: if (popupflags & RS_POPUP_DOWNLOAD) { + /* id = file hash */ toaster = new Toaster(new DownloadToaster(id, QString::fromUtf8(title.c_str()))); } break; + case RS_POPUP_CHAT: + if (popupflags & RS_POPUP_CHAT) + { + ChatDialog *chatDialog = ChatDialog::getChat(id, 0); + ChatWidget *chatWidget; + if (chatDialog && (chatWidget = chatDialog->getChatWidget()) && chatWidget->isActive()) { + // do not show when active + break; + } + toaster = new Toaster(new ChatToaster(id, QString::fromUtf8(msg.c_str()))); + } + break; + case RS_POPUP_GROUPCHAT: + if (popupflags & RS_POPUP_GROUPCHAT) + { + MainWindow *mainWindow = MainWindow::getInstance(); + if (mainWindow && mainWindow->isActiveWindow() && !mainWindow->isMinimized()) { + if (MainWindow::getActivatePage() == MainWindow::Friends) { + if (FriendsDialog::isGroupChatActive()) { + // do not show when active + break; + } + } + } + toaster = new Toaster(new GroupChatToaster(id, QString::fromUtf8(msg.c_str()))); + } + break; + case RS_POPUP_CHATLOBBY: + if (popupflags & RS_POPUP_CHATLOBBY) + { + ChatDialog *chatDialog = ChatDialog::getChat(id, 0); + ChatWidget *chatWidget; + if (chatDialog && (chatWidget = chatDialog->getChatWidget()) && chatWidget->isActive()) { + // do not show when active + break; + } + toaster = new Toaster(new ChatLobbyToaster(id, QString::fromUtf8(title.c_str()), QString::fromUtf8(msg.c_str()))); + } + break; } if (toaster) { diff --git a/retroshare-gui/src/gui/settings/NotifyPage.cpp b/retroshare-gui/src/gui/settings/NotifyPage.cpp index b7f72ecec..67916b9c9 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.cpp +++ b/retroshare-gui/src/gui/settings/NotifyPage.cpp @@ -69,6 +69,12 @@ NotifyPage::save(QString &/*errmsg*/) notifyflags |= RS_POPUP_MSG; if (ui.popup_DownloadFinished->isChecked()) notifyflags |= RS_POPUP_DOWNLOAD; + if (ui.popup_PrivateChat->isChecked()) + notifyflags |= RS_POPUP_CHAT; + if (ui.popup_GroupChat->isChecked()) + notifyflags |= RS_POPUP_GROUPCHAT; + if (ui.popup_ChatLobby->isChecked()) + notifyflags |= RS_POPUP_CHATLOBBY; if (ui.notify_Peers->isChecked()) newsflags |= RS_FEED_TYPE_PEER; @@ -151,6 +157,9 @@ void NotifyPage::load() ui.popup_Connect->setChecked(notifyflags & RS_POPUP_CONNECT); ui.popup_NewMsg->setChecked(notifyflags & RS_POPUP_MSG); ui.popup_DownloadFinished->setChecked(notifyflags & RS_POPUP_DOWNLOAD); + ui.popup_PrivateChat->setChecked(notifyflags & RS_POPUP_CHAT); + ui.popup_GroupChat->setChecked(notifyflags & RS_POPUP_GROUPCHAT); + ui.popup_ChatLobby->setChecked(notifyflags & RS_POPUP_CHATLOBBY); ui.notify_Peers->setChecked(newsflags & RS_FEED_TYPE_PEER); ui.notify_Channels->setChecked(newsflags & RS_FEED_TYPE_CHAN); diff --git a/retroshare-gui/src/gui/settings/NotifyPage.ui b/retroshare-gui/src/gui/settings/NotifyPage.ui index ce20a639f..b3daac04f 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.ui +++ b/retroshare-gui/src/gui/settings/NotifyPage.ui @@ -593,7 +593,7 @@ - Private Message + Private Chat @@ -715,6 +715,27 @@ + + + + Private Chat + + + + + + + Group Chat + + + + + + + Chat Lobby + + + diff --git a/retroshare-gui/src/gui/toaster/ChatLobbyToaster.cpp b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.cpp new file mode 100644 index 000000000..5d90c4e7b --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.cpp @@ -0,0 +1,62 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ChatLobbyToaster.h" +#include "gui/chat/ChatDialog.h" +#include "gui/chat/HandleRichText.h" + +#include + +ChatLobbyToaster::ChatLobbyToaster(const std::string &peerId, const QString &name, const QString &message) : QWidget(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + this->peerId = peerId; + + connect(ui.chatButton, SIGNAL(clicked()), SLOT(chatButtonSlot())); + connect(ui.closeButton, SIGNAL(clicked()), SLOT(hide())); + + /* set informations */ + ui.messageLabel->setText(RsHtml::formatText(message, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + QString lobbyName = name; + + std::list linfos; + rsMsgs->getChatLobbyList(linfos); + + ChatLobbyId lobbyId; + if (rsMsgs->isLobbyId(peerId, lobbyId)) { + for (std::list::const_iterator it(linfos.begin()); it != linfos.end(); ++it) { + if ((*it).lobby_id == lobbyId) { + lobbyName += "@" + QString::fromUtf8((*it).lobby_name.c_str()); + break; + } + } + } + ui.nameLabel->setText(lobbyName); +} + +void ChatLobbyToaster::chatButtonSlot() +{ + ChatDialog::chatFriend(peerId); + hide(); +} diff --git a/retroshare-gui/src/gui/toaster/ChatLobbyToaster.h b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.h new file mode 100644 index 000000000..06295a35c --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.h @@ -0,0 +1,49 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef CHATLOBBYTOASTER_H +#define CHATLOBBYTOASTER_H + +#include "ui_ChatLobbyToaster.h" + +/** + * Shows a toaster when a chat is incoming. + * + * + */ +class ChatLobbyToaster : public QWidget +{ + Q_OBJECT + +public: + ChatLobbyToaster(const std::string &peerId, const QString &name, const QString &message); + +private slots: + void chatButtonSlot(); + +private: + std::string peerId; + + /** Qt Designer generated object */ + Ui::ChatLobbyToaster ui; +}; + +#endif //CHATLOBBYTOASTER_H diff --git a/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui new file mode 100644 index 000000000..1a6b20281 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatLobbyToaster.ui @@ -0,0 +1,208 @@ + + + ChatLobbyToaster + + + + 0 + 0 + 300 + 100 + + + + + 300 + 100 + + + + + 300 + 100 + + + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + + 18 + 18 + + + + + 18 + 18 + + + + + :/images/closenormal.png:/images/closenormal.png + + + true + + + + + + + + 9 + 75 + true + + + + Name + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + :/images/rstray3.png + + + true + + + + + + + Qt::Horizontal + + + + + + + + + 4 + + + 4 + + + 0 + + + + + + + + Show Chat Lobby + + + + + + + + 220 + 47 + + + + true + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + QFrame::Panel + + + QFrame::Sunken + + + :/images/user/agt_forum64.png + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/toaster/ChatToaster.cpp b/retroshare-gui/src/gui/toaster/ChatToaster.cpp new file mode 100644 index 000000000..205162983 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatToaster.cpp @@ -0,0 +1,49 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ChatToaster.h" +#include "gui/chat/ChatDialog.h" +#include "gui/chat/HandleRichText.h" + +#include + +ChatToaster::ChatToaster(const std::string &peerId, const QString &message) : QWidget(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + this->peerId = peerId; + + connect(ui.chatButton, SIGNAL(clicked()), SLOT(chatButtonSlot())); + connect(ui.closeButton, SIGNAL(clicked()), SLOT(hide())); + + /* set informations */ + ui.messageLabel->setText(RsHtml::formatText(message, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + ui.nameLabel->setText(QString::fromUtf8(rsPeers->getPeerName(peerId).c_str())); + ui.avatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); + ui.avatarWidget->setId(peerId, false); +} + +void ChatToaster::chatButtonSlot() +{ + ChatDialog::chatFriend(peerId); + hide(); +} diff --git a/retroshare-gui/src/gui/toaster/ChatToaster.h b/retroshare-gui/src/gui/toaster/ChatToaster.h new file mode 100644 index 000000000..15a4f5047 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatToaster.h @@ -0,0 +1,49 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef CHATTOASTER_H +#define CHATTOASTER_H + +#include "ui_ChatToaster.h" + +/** + * Shows a toaster when a chat is incoming. + * + * + */ +class ChatToaster : public QWidget +{ + Q_OBJECT + +public: + ChatToaster(const std::string &peerId, const QString &message); + +private slots: + void chatButtonSlot(); + +private: + std::string peerId; + + /** Qt Designer generated object */ + Ui::ChatToaster ui; +}; + +#endif //CHATTOASTER_H diff --git a/retroshare-gui/src/gui/toaster/ChatToaster.ui b/retroshare-gui/src/gui/toaster/ChatToaster.ui new file mode 100644 index 000000000..8735e9d3e --- /dev/null +++ b/retroshare-gui/src/gui/toaster/ChatToaster.ui @@ -0,0 +1,207 @@ + + + ChatToaster + + + + 0 + 0 + 300 + 102 + + + + + 300 + 100 + + + + + 300 + 102 + + + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + + 18 + 18 + + + + + 18 + 18 + + + + + :/images/closenormal.png:/images/closenormal.png + + + true + + + + + + + Qt::Horizontal + + + + + + + + 9 + 75 + true + + + + Name + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + :/images/rstray3.png + + + true + + + + + + + + + 4 + + + 4 + + + 0 + + + + + + + + Show Chat + + + + + + + + 220 + 47 + + + + true + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + + + + + + AvatarWidget + QWidget +
gui/common/AvatarWidget.h
+ 1 +
+
+ + + + +
diff --git a/retroshare-gui/src/gui/toaster/GroupChatToaster.cpp b/retroshare-gui/src/gui/toaster/GroupChatToaster.cpp new file mode 100644 index 000000000..bb4faf233 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/GroupChatToaster.cpp @@ -0,0 +1,48 @@ +/* + * RetroShare + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GroupChatToaster.h" +#include "gui/FriendsDialog.h" +#include "gui/chat/HandleRichText.h" + +#include + +GroupChatToaster::GroupChatToaster(const std::string &peerId, const QString &message) : QWidget(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + this->peerId = peerId; + + connect(ui.chatButton, SIGNAL(clicked()), SLOT(chatButtonSlot())); + connect(ui.closeButton, SIGNAL(clicked()), SLOT(hide())); + + /* set informations */ + ui.messageLabel->setText(RsHtml::formatText(message, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + ui.nameLabel->setText(QString::fromUtf8(rsPeers->getPeerName(peerId).c_str())); + ui.avatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); + ui.avatarWidget->setDefaultAvatar(":/images/user/personal64.png"); + ui.avatarWidget->setId(peerId, false); +} + +void GroupChatToaster::chatButtonSlot() +{ + FriendsDialog::groupChatActivate(); + hide(); +} diff --git a/retroshare-gui/src/gui/toaster/GroupChatToaster.h b/retroshare-gui/src/gui/toaster/GroupChatToaster.h new file mode 100644 index 000000000..1ac8562e9 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/GroupChatToaster.h @@ -0,0 +1,47 @@ +/* + * RetroShare + * Copyright (C) 2012 RetroShare Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GROUPCHATTOASTER_H +#define GROUPCHATTOASTER_H + +#include "ui_GroupChatToaster.h" + +/** + * Shows a toaster when friend is GroupChat . + * + * + */ +class GroupChatToaster : public QWidget +{ + Q_OBJECT + +public: + GroupChatToaster(const std::string &peerId, const QString &message); + +private slots: + void chatButtonSlot(); + +private: + std::string peerId; + + /** Qt Designer generated object */ + Ui::GroupChatToaster ui; +}; + +#endif //GROUPCHATTOASTER_H diff --git a/retroshare-gui/src/gui/toaster/GroupChatToaster.ui b/retroshare-gui/src/gui/toaster/GroupChatToaster.ui new file mode 100644 index 000000000..28a89de33 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/GroupChatToaster.ui @@ -0,0 +1,216 @@ + + + GroupChatToaster + + + + 0 + 0 + 300 + 100 + + + + + 300 + 100 + + + + + 300 + 100 + + + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + + 18 + 18 + + + + + 18 + 18 + + + + + :/images/closenormal.png:/images/closenormal.png + + + true + + + + + + + + 9 + 75 + true + + + + Name + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + :/images/rstray3.png + + + true + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + 4 + + + 4 + + + 0 + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + + 220 + 47 + + + + true + + + + + + + + + + Show Group Chat + + + + + + + + + + + + + AvatarWidget + QWidget +
gui/common/AvatarWidget.h
+ 1 +
+
+ + closeButton + + + + + +
diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.cpp b/retroshare-gui/src/gui/toaster/MessageToaster.cpp index 54115d235..10728336e 100644 --- a/retroshare-gui/src/gui/toaster/MessageToaster.cpp +++ b/retroshare-gui/src/gui/toaster/MessageToaster.cpp @@ -20,7 +20,9 @@ #include "MessageToaster.h" #include "../MainWindow.h" -MessageToaster::MessageToaster(const QString &name, const QString &title, const QString &message) : QWidget(NULL) +#include + +MessageToaster::MessageToaster(const std::string &peerId, const QString &title, const QString &message) : QWidget(NULL) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); @@ -35,7 +37,7 @@ MessageToaster::MessageToaster(const QString &name, const QString &title, const ui.subjectline->setToolTip(title); ui.contentBrowser->setText(message); ui.contentBrowser->setToolTip(message); - ui.lblTitle->setText(ui.lblTitle->text() + " " + name); + ui.lblTitle->setText(ui.lblTitle->text() + " " + QString::fromUtf8(rsPeers->getPeerName(peerId).c_str())); } void MessageToaster::openmessageClicked() diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.h b/retroshare-gui/src/gui/toaster/MessageToaster.h index 05eb108d9..6c8c59fb4 100644 --- a/retroshare-gui/src/gui/toaster/MessageToaster.h +++ b/retroshare-gui/src/gui/toaster/MessageToaster.h @@ -33,7 +33,7 @@ class MessageToaster : public QWidget Q_OBJECT public: - MessageToaster(const QString &name, const QString &title, const QString &message); + MessageToaster(const std::string &peerId, const QString &title, const QString &message); private slots: void openmessageClicked(); diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.cpp b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp index 1f4fe7060..652dc87a4 100644 --- a/retroshare-gui/src/gui/toaster/OnlineToaster.cpp +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp @@ -18,12 +18,12 @@ */ #include "OnlineToaster.h" -#include "gui/settings/rsharesettings.h" #include "gui/chat/ChatDialog.h" #include "util/WidgetBackgroundImage.h" -#include "gui/common/AvatarDefs.h" -OnlineToaster::OnlineToaster(const std::string &peerId, const QString &name) : QWidget(NULL) +#include + +OnlineToaster::OnlineToaster(const std::string &peerId) : QWidget(NULL) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); @@ -35,11 +35,9 @@ OnlineToaster::OnlineToaster(const std::string &peerId, const QString &name) : Q connect(ui.closeButton, SIGNAL(clicked()), SLOT(hide())); /* set informations */ - ui.messageLabel->setText(name); - - QPixmap avatar; - AvatarDefs::getAvatarFromSslId(peerId, avatar, ":/images/user/personal64.png"); - ui.pixmaplabel->setPixmap(avatar); + ui.messageLabel->setText(QString::fromUtf8(rsPeers->getPeerName(peerId).c_str())); + ui.avatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); + ui.avatarWidget->setId(peerId, false); WidgetBackgroundImage::setBackgroundImage(ui.windowFrame, ":images/toaster/backgroundtoaster.png", WidgetBackgroundImage::AdjustNone); } diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.h b/retroshare-gui/src/gui/toaster/OnlineToaster.h index e21c6b998..1a282854e 100644 --- a/retroshare-gui/src/gui/toaster/OnlineToaster.h +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.h @@ -32,7 +32,7 @@ class OnlineToaster : public QWidget Q_OBJECT public: - OnlineToaster(const std::string &peerId, const QString &name); + OnlineToaster(const std::string &peerId); private slots: void chatButtonSlot(); diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.ui b/retroshare-gui/src/gui/toaster/OnlineToaster.ui index 3ce8576c5..c1b6ae985 100644 --- a/retroshare-gui/src/gui/toaster/OnlineToaster.ui +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.ui @@ -162,37 +162,6 @@
- - - - - 70 - 70 - - - - - 70 - 70 - - - - QLabel#pixmaplabel{ -border: 2px solid #238; -border-radius: 4px;} - - - - - - - :/images/user/personal64.png - - - Qt::AlignCenter - - - @@ -222,6 +191,22 @@ border-radius: 4px;} + + + + + 70 + 70 + + + + + 70 + 70 + + + + @@ -242,6 +227,14 @@ border-radius: 4px;}
+ + + AvatarWidget + QWidget +
gui/common/AvatarWidget.h
+ 1 +
+
closeButton diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm index 7fa1a3a11710f954b3d1dad65f8066aa61dd8900..19312c2876c6ef0a6d5f96048be33d0e2afc708b 100644 GIT binary patch delta 19313 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 delta 19081 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�b1W#_{AL?DI8IvFo0_P92x=C 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 diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts index f9e056293..ea59fb46d 100644 --- a/retroshare-gui/src/lang/retroshare_de.ts +++ b/retroshare-gui/src/lang/retroshare_de.ts @@ -233,7 +233,7 @@ p, li { white-space: pre-wrap; } AvatarWidget - + Click to change your avatar Klick zum Ändern deines Avatars @@ -241,7 +241,7 @@ p, li { white-space: pre-wrap; } BandwidthGraph - + Since: Seit: @@ -361,7 +361,7 @@ p, li { white-space: pre-wrap; } OK - + Close Schliessen @@ -696,7 +696,7 @@ p, li { white-space: pre-wrap; } CertificatePage - + Certificate files Zertifikat-Dateien @@ -795,7 +795,7 @@ p, li { white-space: pre-wrap; } - + Expand Erweitern @@ -830,12 +830,17 @@ p, li { white-space: pre-wrap; } Kopiere RetroShare Link - + Channel Feed Kanal - + + Files + Dateien + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. Warnung! Du hast weniger als %1 Stunden und %2 Minuten bevor die Datei gelöscht wird. Denke daran, sie zu speichern. @@ -937,7 +942,7 @@ p, li { white-space: pre-wrap; } OK - + Close Schliessen @@ -1112,7 +1117,7 @@ Bitte wähle einen zum chatten aus. ChatLobbyDialog - + Welcome to lobby %1 Willkommen in der Lobby %1 @@ -1153,7 +1158,7 @@ Bitte wähle einen zum chatten aus. Lobby abbestellen - + Hide Participants Telnehmer ausblenden @@ -1164,11 +1169,19 @@ Bitte wähle einen zum chatten aus. - + Change nick name Ändere Spitznamen + + ChatLobbyToaster + + + Show Chat Lobby + Zeige Chat Lobbie + + ChatLobbyWidget @@ -1230,7 +1243,13 @@ p, li { white-space: pre-wrap; } Abonnieren - + + + [No topic provided] + [Kein Thema angegeben] + + + Invitation to chat lobby Einladung zur Chat Lobby @@ -1279,7 +1298,7 @@ p, li { white-space: pre-wrap; } Abbrechen - + Quick Message Schnelle Nachrricht @@ -1487,6 +1506,14 @@ p, li { white-space: pre-wrap; } Kompakter Stil für den Verlauf + + ChatToaster + + + Show Chat + Zeige Chat + + ChatWidget @@ -1593,7 +1620,7 @@ p, li { white-space: pre-wrap; } Schriftart auf den Standard setzen - + Paste RetroShare Link RetroShare Link einfügen @@ -1983,7 +2010,7 @@ und meinen GPG Schlüssel nicht unterzeichnet ConnectFriendWizard - + Certificate Load Failed Das Zertifikat konnte nicht geladen werden @@ -3144,7 +3171,7 @@ p, li { white-space: pre-wrap; } DHTStatus - + DHT DHT @@ -3718,7 +3745,7 @@ Das ist nützlich, wenn Du eine externe Festplatte freigibst und die Datei nicht EmailPage - + Invite Friends by Email Lade Freunde per Email ein @@ -3775,7 +3802,7 @@ Bis bald in RetroShare! ExampleDialog - + Vote Up Daumen hoch @@ -4106,7 +4133,7 @@ p, li { white-space: pre-wrap; } FlatStyle_RDM - + Friends Directories Dateien von Freunden @@ -4263,7 +4290,7 @@ p, li { white-space: pre-wrap; } OK - + Apply and Close Annehmen und Schliessen @@ -5126,12 +5153,12 @@ p, li { white-space: pre-wrap; } Wähle oder ändere dein Avatar Bild - + Edit Personal message Statusnachricht ändern - + Group Chat Gruppenchat @@ -5181,18 +5208,16 @@ p, li { white-space: pre-wrap; } Nachrichtenverlauf leeren - - + Add Friend Freund hinzufügen - ... - ... + ... - + Create new Profile Erstelle neues Profil @@ -5255,15 +5280,13 @@ p, li { white-space: pre-wrap; } Nachrichtenverlauf speichern - - + Create new Chat lobby Neue Chat Lobby erstellen - - + Friend Recommendations Freundempfehlungen @@ -5298,8 +5321,7 @@ p, li { white-space: pre-wrap; } Status ausblenden - - + Add a new Group Neue Gruppe hinzufügen @@ -5327,7 +5349,7 @@ p, li { white-space: pre-wrap; } Löscht den gespeicherten und angezeigten Chat Verlauf - + Chat lobbies Chat Lobbies @@ -5506,7 +5528,7 @@ p, li { white-space: pre-wrap; } GamesDialog - + Cancel Game Spiel abbrechen @@ -6284,7 +6306,7 @@ p, li { white-space: pre-wrap; } Dein Freund hat RetroShare installiert und möchte, daß du es auch versuchst. - + forums and channels, all of which are as secure as the file-sharing. Foren, Kanäle, von denen alle ebenso sicher sind wie das Tauschen von Dateien. @@ -6399,6 +6421,14 @@ p, li { white-space: pre-wrap; } Klicke und ziehe die Knoten umher, Zoome mit dem Mausrad or den Tasten '+' und '-' + + GroupChatToaster + + + Show Group Chat + Zeige Gruppenchat + + GroupDefs @@ -7027,7 +7057,7 @@ p, li { white-space: pre-wrap; } IntroPage - + &Make friend with selected friends of my friends &Füge ausgewählte Freunde Deiner Freunde hinzu @@ -7069,7 +7099,7 @@ Die folgenden Wege sind möglich: MainWindow - + Network Netzwerk @@ -7167,7 +7197,7 @@ Die folgenden Wege sind möglich: %1 Freunde verbunden - + It seems to be an old RetroShare link. Please use copy instead. Es scheint ein alter RetroShare Link zu sein. Bitte kopiere den Link stattdessen. @@ -7177,23 +7207,23 @@ Die folgenden Wege sind möglich: Link ist fehlerhaft. - + %1 friend connected %1 Freund verbunden - + Internal Error Interener Fehler - + Options Optionen - + Hide Verbergen @@ -7203,7 +7233,7 @@ Die folgenden Wege sind möglich: Zeigen - + RetroShare @@ -7345,7 +7375,7 @@ Die folgenden Wege sind möglich: - + Do you really want to exit RetroShare ? Möchtest du RetroShare wirklich beenden? @@ -7355,7 +7385,7 @@ Die folgenden Wege sind möglich: Wirklich beenden? - + Low disk space warning Wenig Festplatenspeicher @@ -7988,7 +8018,7 @@ Möchtest du die Nachricht speichern ? Betreff - + Sub: Betreff: @@ -9235,12 +9265,11 @@ p, li { white-space: pre-wrap; } Systray Icon - Private Message - Private Nachricht + Private Nachricht - + Message Nachricht @@ -9285,7 +9314,17 @@ p, li { white-space: pre-wrap; } Neue Nachricht - + + Group Chat + Gruppenchat + + + + Chat Lobby + Chat Lobbie + + + Position Position @@ -9300,7 +9339,9 @@ p, li { white-space: pre-wrap; } Abstand Y - + + + Private Chat Privater Chat @@ -9330,12 +9371,12 @@ p, li { white-space: pre-wrap; } Zeige Systemabschnitts-Nachricht an - + Add feeds at end Feeds am Ende anfügen - + Top Left Oben Links @@ -9363,7 +9404,7 @@ p, li { white-space: pre-wrap; } NotifyQt - + GPG key passphrase GPG Schlüssel Passwort @@ -9396,7 +9437,7 @@ p, li { white-space: pre-wrap; } OnlineToaster - + Friend Online Freund Online @@ -9419,7 +9460,7 @@ p, li { white-space: pre-wrap; } - + Expand Erweitern @@ -9489,7 +9530,7 @@ p, li { white-space: pre-wrap; } Abbrechen - + Friend Connected Freund verbunden @@ -9527,7 +9568,7 @@ p, li { white-space: pre-wrap; } Unbekannter Nachbar - + Hide Verbergen @@ -9540,12 +9581,12 @@ p, li { white-space: pre-wrap; } PeerStatus - + Friends: 0/0 Freunde: 0/0 - + Online Friends/Total Friends Freunde online / Freunde total @@ -9558,7 +9599,7 @@ p, li { white-space: pre-wrap; } PhotoDialog - + Insert Show Lists @@ -10215,7 +10256,7 @@ Do you want to send them a Message instead ProfileEdit - + Remove Profile Entry Profil-Eintrag entfernen @@ -10314,7 +10355,7 @@ Do you want to send them a Message instead ProfileView - + Clear Photo Photo entfernen @@ -10431,7 +10472,7 @@ p, li { white-space: pre-wrap; } Copy Certificate - + Kopiere Zertifikat @@ -10616,7 +10657,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Adressliste</span></p></body></html> - + RetroShare RetroShare @@ -11028,12 +11069,6 @@ Reported error is: %2 Die Kollektion %1 konnte nicht geöffnet werden. Fehlermeldung: %2 - - - - [No topic provided] - - QuickStartWizard @@ -11383,19 +11418,27 @@ p, li { white-space: pre-wrap; } RatesStatus - + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) - - <strong>Down:</strong> - <strong>Runter:</strong> + + Down + Runter + Up + Hoch + + + <strong>Down:</strong> + <strong>Runter:</strong> + + <strong>Up:</strong> - <strong>Hoch:</strong> + <strong>Hoch:</strong> @@ -11667,7 +11710,7 @@ p, li { white-space: pre-wrap; } RsidPage - + RetroShare ID RetroShare ID @@ -11734,7 +11777,7 @@ p, li { white-space: pre-wrap; } - + Download Herunterladen @@ -11776,7 +11819,7 @@ p, li { white-space: pre-wrap; } Ordner - + New RetroShare Link(s) Neu(e) RetroShare Link(s) @@ -11831,7 +11874,7 @@ p, li { white-space: pre-wrap; } Such ID - + Download Notice Download @@ -11988,8 +12031,8 @@ p, li { white-space: pre-wrap; } SecurityItem - - + + Expand Erweitern @@ -12079,12 +12122,12 @@ p, li { white-space: pre-wrap; } Nachricht schreiben - + Connect Attempt Verbindungsversuch - + Not Yet Friends Noch keine Freunde @@ -12094,7 +12137,7 @@ p, li { white-space: pre-wrap; } Unbekannter (eingehender) Verbindungsversuch - + Unknown (Outgoing) Connect Attempt Unbekannter (ausgehender) Verbindungsversuch @@ -12114,7 +12157,7 @@ p, li { white-space: pre-wrap; } Unbekannter Nachbar - + Hide Verbergen @@ -13723,7 +13766,7 @@ p, li { white-space: pre-wrap; } TextPage - + Use text representation of the PGP certificates. Verwende diesen Text als PGP Zertifikat. @@ -13748,7 +13791,7 @@ p, li { white-space: pre-wrap; } Bitte füge das PGP-Zertifikat von Ihre Freunde in das Feld unten ein - + Clean certificate Bereinige Zertifikat @@ -13798,7 +13841,7 @@ p, li { white-space: pre-wrap; } - + Text certificate Text-Zertifikat @@ -13813,7 +13856,7 @@ p, li { white-space: pre-wrap; } Starte das Standard-Emailprogramm - + Connect Friend Help Verbindungshilfe @@ -14467,7 +14510,7 @@ Try to be patient! TurtleRouterDialog - + Search requests Suchanfragen diff --git a/retroshare-gui/src/util/EventReceiver.cpp b/retroshare-gui/src/util/EventReceiver.cpp index f1b06c8af..9a7b5af00 100644 --- a/retroshare-gui/src/util/EventReceiver.cpp +++ b/retroshare-gui/src/util/EventReceiver.cpp @@ -163,70 +163,11 @@ bool EventReceiver::winEvent(MSG* message, long* result) } #endif -#ifdef WINDOWS_SYS -//void SetForegroundWindowInternal(HWND hWnd) -//{ -// if (!::IsWindow(hWnd)) return; - -// // relation time of SetForegroundWindow lock -// DWORD lockTimeOut = 0; -// HWND hCurrWnd = ::GetForegroundWindow(); -// DWORD dwThisTID = ::GetCurrentThreadId(), -// dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0); - -// // we need to bypass some limitations from Microsoft :) -// if (dwThisTID != dwCurrTID) { -// ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE); - -// ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0); -// ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); - -// ::AllowSetForegroundWindow(ASFW_ANY); -// } - -// ::SetForegroundWindow(hWnd); - -// if(dwThisTID != dwCurrTID) { -// ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); -// ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE); -// } -//} - -void SetForegroundWindowInternal(HWND hWnd) -{ - if (!::IsWindow(hWnd)) return; - - BYTE keyState[256] = {0}; - // to unlock SetForegroundWindow we need to imitate Alt pressing - if (::GetKeyboardState((LPBYTE)&keyState)) { - if(!(keyState[VK_MENU] & 0x80)) { - ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0); - } - } - - ::SetForegroundWindow(hWnd); - - if (::GetKeyboardState((LPBYTE)&keyState)) { - if(!(keyState[VK_MENU] & 0x80)) { - ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); - } - } -} -#endif - void EventReceiver::received(const QString &url) { RetroShareLink link(url); if (link.valid()) { - MainWindow *window = MainWindow::getInstance(); - if (window) { - window->show(); - window->raise(); - -#ifdef WINDOWS_SYS - SetForegroundWindowInternal(window->winId()); -#endif - } + MainWindow::raiseWindow(); emit linkReceived(link.toUrl()); }