diff options
author | Tobias Markmann <tm@ayena.de> | 2018-03-20 13:12:10 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2018-03-20 14:48:04 (GMT) |
commit | f2c2c7d035029fb9615b42c18ccea83e8e705b10 (patch) | |
tree | 2f56fb77de0f366528395f21732d418f016f63b5 /Swift | |
parent | 44581c5285d13c0ec715b35ddc79177e5ebeef39 (diff) | |
parent | 5ba3f18ad8efa040d49f36d83ec2e7891a9add9f (diff) | |
download | swift-f2c2c7d035029fb9615b42c18ccea83e8e705b10.zip swift-f2c2c7d035029fb9615b42c18ccea83e8e705b10.tar.bz2 |
Merge branch 'swift-4.x'swift-5.0alpha2
* swift-4.x: (44 commits)
Test-Information:
Builds on macOS 10.13.3 with clang trunk.
Change-Id: If50381f103b0ad18d038b920d3d43537642141cb
Diffstat (limited to 'Swift')
38 files changed, 1210 insertions, 485 deletions
diff --git a/Swift/ChangeLog.md b/Swift/ChangeLog.md index 32b5711..a00f41c 100644 --- a/Swift/ChangeLog.md +++ b/Swift/ChangeLog.md @@ -1,3 +1,45 @@ +4.0 (2018-03-20) +---------------- +- New chat theme including a new font +- Support for message carbons (XEP-0280) +- Enabled trellis mode as a default feature, allowing several tiled chats windows to be shown at once +- Redesigned keyword highlighting +- Improve date formatting +- Fix Last Message Correction in multi client scenarios +- Fix UI layout issue for translations that require right-to-left (RTL) layout +- Fix UX issues in trellis mode +- Improvements to font size handling in the chat theme +- Fix display of default avatar on Windows +- Support for automatic software updates on macOS +- macOS releases are now code-signed +- Support for unicode emojis on macOS +- Add AppImage for Linux 64-bit as a supported platform +- Improved spell checker support on Linux +- And assorted smaller features and usability enhancements + +4.0-rc6 ( 2018-03-07 ) +---------------------- +- Small usability fixes in Carbons ( XEP-0280 ) handling and Windows installer +- Fix crashes related to room invitations, layout changes, and vCard handling +- And smaller bug fixes + +4.0-rc5 ( 2018-01-09 ) +---------------------- +- Fix crash during sleep on macOS + +4.0-rc4 ( 2018-01-04 ) +---------------------- +- Remove conflicting shortcut +- Debian packaging fixes + +4.0-rc3 ( 2017-11-28 ) +---------------------- +- Fix crash in emoticon dialog +- Fix Windows MSI installer when updating from earlier Swift version +- Update translations ( Dutch, German ) +- Add AppImage for Linux 64-bit as a supported platform +- And smaller bug fixes + 4.0-rc2 ( 2017-05-22 ) ---------------------- - Fix regression in chat window titles for chat rooms @@ -10,7 +52,7 @@ - Fix Last Message Correction in multi client scenarios - Fix display of default avatar on Windows - Support for automatic software updates on macOS -- Redesigned keyword highlighing +- Redesigned keyword highlighting - Support for unicode emojis on macOS - Improvements to font size handling in the chat theme - Fix UX issues in trellis mode @@ -117,4 +159,4 @@ Yoann Blein, Catalin Badea, Pavol Babincak, Mateusz Piekos, Alexey Melnikov and 1.0 ( 2011-04-18 ) ------------------ -- Initial release.
\ No newline at end of file +- Initial release. diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 7fb9c59..5f5f41d 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -86,7 +86,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available); startMessage += "."; chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(startMessage), ChatWindow::DefaultDirection); - chatWindow_->onContinuationsBroken.connect([this, startMessage]() { chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(startMessage), ChatWindow::DefaultDirection); }); + continuationsBrokenConnection_ = chatWindow_->onContinuationsBroken.connect([this, startMessage]() { chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(startMessage), ChatWindow::DefaultDirection); }); chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_)); chatWindow_->onFileTransferStart.connect(boost::bind(&ChatController::handleFileTransferStart, this, _1, _2)); @@ -320,6 +320,7 @@ void ChatController::handleIncomingOwnMessage(std::shared_ptr<Message> message) if (!message->getBody().get_value_or("").empty()) { postSendMessage(message->getBody().get_value_or(""), message); handleStanzaAcked(message); + onActivity(message->getBody().get_value_or("")); } } @@ -585,8 +586,20 @@ JID ChatController::messageCorrectionJID(const JID& fromJID) { } ChatWindow* ChatController::detachChatWindow() { - chatWindow_->onUserTyping.disconnect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); + continuationsBrokenConnection_.disconnect(); + chatWindow_->onClosed.disconnect(boost::bind(&ChatController::handleWindowClosed, this)); + chatWindow_->onInviteToChat.disconnect(boost::bind(&ChatController::handleInviteToChat, this, _1)); + chatWindow_->onUnblockUserRequest.disconnect(boost::bind(&ChatController::handleUnblockUserRequest, this)); + chatWindow_->onBlockUserRequest.disconnect(boost::bind(&ChatController::handleBlockUserRequest, this)); + chatWindow_->onWhiteboardWindowShow.disconnect(boost::bind(&ChatController::handleWhiteboardWindowShow, this)); + chatWindow_->onWhiteboardSessionCancel.disconnect(boost::bind(&ChatController::handleWhiteboardSessionCancel, this)); + chatWindow_->onWhiteboardSessionAccept.disconnect(boost::bind(&ChatController::handleWhiteboardSessionAccept, this)); + chatWindow_->onSendFileRequest.disconnect(boost::bind(&ChatController::handleSendFileRequest, this, _1)); + chatWindow_->onFileTransferCancel.disconnect(boost::bind(&ChatController::handleFileTransferCancel, this, _1)); + chatWindow_->onFileTransferAccept.disconnect(boost::bind(&ChatController::handleFileTransferAccept, this, _1, _2)); + chatWindow_->onFileTransferStart.disconnect(boost::bind(&ChatController::handleFileTransferStart, this, _1, _2)); chatWindow_->onUserCancelsTyping.disconnect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_)); + chatWindow_->onUserTyping.disconnect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); return ChatControllerBase::detachChatWindow(); } diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h index c65eb9c..72acc27 100644 --- a/Swift/Controllers/Chat/ChatController.h +++ b/Swift/Controllers/Chat/ChatController.h @@ -111,6 +111,7 @@ namespace Swift { boost::signals2::scoped_connection blockingOnStateChangedConnection_; boost::signals2::scoped_connection blockingOnItemAddedConnection_; boost::signals2::scoped_connection blockingOnItemRemovedConnection_; + boost::signals2::scoped_connection continuationsBrokenConnection_; boost::optional<ChatWindow::AlertID> deliveryReceiptAlert_; boost::optional<ChatWindow::AlertID> blockedContactAlert_; diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index f514346..b1854d8 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -58,6 +58,9 @@ void ChatControllerBase::handleContinuationsBroken() { } ChatWindow* ChatControllerBase::detachChatWindow() { + chatWindow_->onContinuationsBroken.disconnect(boost::bind(&ChatControllerBase::handleContinuationsBroken, this)); + chatWindow_->onSendMessageRequest.disconnect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2)); + chatWindow_->onAllMessagesRead.disconnect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); ChatWindow* chatWindow = chatWindow_; chatWindow_ = nullptr; return chatWindow; diff --git a/Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h b/Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h new file mode 100644 index 0000000..1e053b2 --- /dev/null +++ b/Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <boost/version.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/archive/text_oarchive.hpp> +#include <boost/bind.hpp> +#include <boost/serialization/map.hpp> +#include <boost/serialization/optional.hpp> +#include <boost/serialization/split_free.hpp> +#include <boost/serialization/string.hpp> +#include <boost/serialization/vector.hpp> + +#include <Swift/Controllers/UIInterfaces/ChatListWindow.h> + +BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 3) +namespace Swift { + const boost::archive::library_version_type BoostArchiveSkipVersion(15); +} + +namespace boost { + namespace serialization { + template<class Archive> void save(Archive& ar, const Swift::JID& jid, const unsigned int /*version*/) { + std::string jidStr = jid.toString(); + ar << jidStr; + } + + template<class Archive> void load(Archive& ar, Swift::JID& jid, const unsigned int /*version*/) { + std::string stringJID; + ar >> stringJID; + jid = Swift::JID(stringJID); + } + + template<class Archive> inline void serialize(Archive& ar, Swift::JID& t, const unsigned int file_version) { + split_free(ar, t, file_version); + } + + template<class Archive> void serialize(Archive& ar, Swift::ChatListWindow::Chat& chat, const unsigned int version) { + auto archiveLibraryVersion = boost::archive::BOOST_ARCHIVE_VERSION(); + int archiveVersion = 0; + archive::text_oarchive* outputStream = dynamic_cast<archive::text_oarchive*>(&ar); + if (outputStream) { + archiveVersion = outputStream->get_library_version(); + } + archive::text_iarchive* inputStream = dynamic_cast<archive::text_iarchive*>(&ar); + if (inputStream) { + archiveVersion = inputStream->get_library_version(); + //Due to https://svn.boost.org/trac10/ticket/13050 the password field may fail to load and crash the client. Therefore we skip loading the values from previous versions. + if (archiveLibraryVersion == Swift::BoostArchiveSkipVersion && archiveLibraryVersion > archiveVersion) { + return; + } + } + ar & chat.jid; + ar & chat.chatName; + ar & chat.activity; + ar & chat.isMUC; + ar & chat.nick; + ar & chat.impromptuJIDs; + if (version > 0) { + if (outputStream && archiveLibraryVersion == Swift::BoostArchiveSkipVersion) { + //The bug does not affect the case boost::optional doesn't have a value. Therefore we store always that value, to avoid problem on future launches of the client. + boost::optional<std::string> empty; + ar & empty; + } + else { + ar & chat.password; + } + } + if (version > 1) { + ar & chat.inviteesNames; + } + } + } +} diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index dd74f6a..81892fc 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -9,14 +9,7 @@ #include <memory> #include <boost/algorithm/string.hpp> -#include <boost/archive/text_iarchive.hpp> -#include <boost/archive/text_oarchive.hpp> #include <boost/bind.hpp> -#include <boost/serialization/map.hpp> -#include <boost/serialization/optional.hpp> -#include <boost/serialization/split_free.hpp> -#include <boost/serialization/string.hpp> -#include <boost/serialization/vector.hpp> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Base/Log.h> @@ -43,6 +36,7 @@ #include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h> #include <Swift/Controllers/Chat/ChatController.h> #include <Swift/Controllers/Chat/ChatControllerBase.h> +#include <Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h> #include <Swift/Controllers/Chat/ChatMessageParser.h> #include <Swift/Controllers/Chat/MUCController.h> #include <Swift/Controllers/Chat/MUCSearchController.h> @@ -67,42 +61,6 @@ #include <Swift/Controllers/WhiteboardManager.h> #include <Swift/Controllers/XMPPEvents/EventController.h> -BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 2) - -namespace boost { -namespace serialization { - template<class Archive> void save(Archive& ar, const Swift::JID& jid, const unsigned int /*version*/) { - std::string jidStr = jid.toString(); - ar << jidStr; - } - - template<class Archive> void load(Archive& ar, Swift::JID& jid, const unsigned int /*version*/) { - std::string stringJID; - ar >> stringJID; - jid = Swift::JID(stringJID); - } - - template<class Archive> inline void serialize(Archive& ar, Swift::JID& t, const unsigned int file_version){ - split_free(ar, t, file_version); - } - - template<class Archive> void serialize(Archive& ar, Swift::ChatListWindow::Chat& chat, const unsigned int version) { - ar & chat.jid; - ar & chat.chatName; - ar & chat.activity; - ar & chat.isMUC; - ar & chat.nick; - ar & chat.impromptuJIDs; - if (version > 0) { - ar & chat.password; - } - if (version > 1) { - ar & chat.inviteesNames; - } - } -} -} - namespace Swift { typedef std::pair<JID, ChatController*> JIDChatControllerPair; @@ -206,6 +164,7 @@ ChatsManager::~ChatsManager() { roster_->onRosterCleared.disconnect(boost::bind(&ChatsManager::handleRosterCleared, this)); ftOverview_->onNewFileTransferController.disconnect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1)); delete joinMUCWindow_; + SWIFT_LOG(debug) << "Destroying ChatsManager, containing " << chatControllers_.size() << " chats and " << mucControllers_.size() << " MUCs" << std::endl; for (JIDChatControllerPair controllerPair : chatControllers_) { delete controllerPair.second; } @@ -341,7 +300,7 @@ void ChatsManager::loadRecents() { SWIFT_LOG(debug) << "Failed to load recents: " << e.what() << std::endl; return; } - + recentChats.erase(std::remove(recentChats.begin(), recentChats.end(), ChatListWindow::Chat()), recentChats.end()); for (auto chat : recentChats) { chat.statusType = StatusShow::None; chat = updateChatStatusAndAvatarHelper(chat); @@ -372,11 +331,13 @@ void ChatsManager::handleBookmarksReady() { } void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) { - std::map<JID, MUCController*>::iterator it = mucControllers_.find(bookmark.getRoom()); - if (it == mucControllers_.end() && bookmark.getAutojoin()) { - handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false, false ); + if (bookmark.getRoom().isBare() && !bookmark.getRoom().getNode().empty()) { + std::map<JID, MUCController*>::iterator it = mucControllers_.find(bookmark.getRoom()); + if (it == mucControllers_.end() && bookmark.getAutojoin()) { + handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false, false ); + } + chatListWindow_->addMUCBookmark(bookmark); } - chatListWindow_->addMUCBookmark(bookmark); } void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) { diff --git a/Swift/Controllers/Chat/UnitTest/ChatListWindowChatTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatListWindowChatTest.cpp new file mode 100644 index 0000000..9561e2b --- /dev/null +++ b/Swift/Controllers/Chat/UnitTest/ChatListWindowChatTest.cpp @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <memory> +#include <string> +#include <vector> + +#include <boost/algorithm/string.hpp> +#include <boost/version.hpp> + +#include <gtest/gtest.h> + +#include <Swiften/Base/ByteArray.h> +#include <Swiften/StringCodecs/Base64.h> + +#include <Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h> +#include <Swift/Controllers/UIInterfaces/ChatListWindow.h> + +using namespace Swift; + +class ChatListWindowChatTest : public ::testing::Test { +protected: + virtual void SetUp() {} + virtual void TearDown() {} + + void testOptionalPasswordValue(const boost::optional<std::string>& value1, const std::string& value2) { + auto archiveLibraryVersion = boost::archive::BOOST_ARCHIVE_VERSION(); + if (archiveLibraryVersion != Swift::BoostArchiveSkipVersion) { + EXPECT_EQ(value1.get_value_or(""), value2); + } + else { + EXPECT_EQ(value1.get_value_or(""), ""); + } + } + + std::string chatsSerialise(const std::vector<ChatListWindow::Chat>& chats) { + std::stringstream serializeStream; + boost::archive::text_oarchive oa(serializeStream); + oa & chats; + std::string serializedStr = Base64::encode(createByteArray(serializeStream.str())); + return serializedStr; + } + + std::vector<ChatListWindow::Chat> chatsDeserialise(const std::string& b64chats) { + ByteArray debase64 = Base64::decode(b64chats); + std::vector<ChatListWindow::Chat> recentChats; + std::stringstream deserializeStream(std::string(reinterpret_cast<const char*>(vecptr(debase64)), debase64.size())); + try { + boost::archive::text_iarchive ia(deserializeStream); + ia >> recentChats; + } + catch (const boost::archive::archive_exception& e) { + EXPECT_TRUE(false) << "Archive Version:" << boost::archive::BOOST_ARCHIVE_VERSION() << " " << e.what() << std::endl; + recentChats.clear(); + return recentChats; + } + recentChats.erase(std::remove(recentChats.begin(), recentChats.end(), ChatListWindow::Chat()), recentChats.end()); + return recentChats; + } +}; + +TEST_F(ChatListWindowChatTest, testNormalSerialization) { + ChatListWindow::Chat chat1("swift@rooms.swift.im", "swift@rooms.swift.im", "Some text 0", 0, StatusShow::None, "", false, false, "Nick Name"); + ChatListWindow::Chat chat2("testuser1@domain.com", "swift@rooms2.swift.im", "Some text 1", 0, StatusShow::None, "", false, false, "Nick Name", std::string("pass")); + ChatListWindow::Chat chat3("testuser2@domain.com", "room 2", "Some text 2", 0, StatusShow::None, "", true, false, "Nick Name"); + ChatListWindow::Chat chat4("testuser3@domain.com", "room 3", "Some text 2", 0, StatusShow::None, "", true, false, "Nick Name", std::string("pass")); + + std::map<std::string, JID> impromptuJIDs; + impromptuJIDs["testuser1@domain.com"] = "testuser1@domain.com"; + impromptuJIDs["testuser2@domain.com"] = "testuser2@domain.com"; + std::map<JID, std::string> inviteesNames; + inviteesNames["user1@domain.com"] = "user1@domain.com"; + + chat3.impromptuJIDs = impromptuJIDs; + chat3.inviteesNames = inviteesNames; + chat4.impromptuJIDs = impromptuJIDs; + chat4.inviteesNames = inviteesNames; + + std::vector<ChatListWindow::Chat> chats; + chats.push_back(chat1); + chats.push_back(chat2); + chats.push_back(chat3); + chats.push_back(chat4); + + auto base64 = chatsSerialise(chats); + ASSERT_TRUE(base64.size() > 0); + auto restoredChats = chatsDeserialise(base64); + ASSERT_EQ(restoredChats.size(), 4); + + EXPECT_FALSE(restoredChats[0].isMUC); + EXPECT_EQ(restoredChats[0].jid, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].chatName, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].activity, "Some text 0"); + EXPECT_EQ(restoredChats[0].nick, "Nick Name"); + EXPECT_EQ(restoredChats[0].impromptuJIDs.size(), 0); + testOptionalPasswordValue(restoredChats[0].password, ""); + EXPECT_EQ(restoredChats[0].inviteesNames.size(), 0); + + EXPECT_FALSE(restoredChats[1].isMUC); + EXPECT_EQ(restoredChats[1].jid, "testuser1@domain.com"); + EXPECT_EQ(restoredChats[1].chatName, "swift@rooms2.swift.im"); + EXPECT_EQ(restoredChats[1].activity, "Some text 1"); + EXPECT_EQ(restoredChats[1].nick, "Nick Name"); + EXPECT_EQ(restoredChats[1].impromptuJIDs.size(), 0); + testOptionalPasswordValue(restoredChats[1].password, "pass"); + EXPECT_EQ(restoredChats[1].inviteesNames.size(), 0); + + EXPECT_TRUE(restoredChats[2].isMUC); + EXPECT_EQ(restoredChats[2].jid, "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].chatName, "room 2"); + EXPECT_EQ(restoredChats[2].activity, "Some text 2"); + EXPECT_EQ(restoredChats[2].nick, "Nick Name"); + ASSERT_EQ(restoredChats[2].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + testOptionalPasswordValue(restoredChats[2].password, ""); + ASSERT_EQ(restoredChats[2].inviteesNames.size(), 1); + EXPECT_EQ(restoredChats[2].inviteesNames["user1@domain.com"], "user1@domain.com"); + + EXPECT_TRUE(restoredChats[3].isMUC); + EXPECT_EQ(restoredChats[3].jid, "testuser3@domain.com"); + EXPECT_EQ(restoredChats[3].chatName, "room 3"); + EXPECT_EQ(restoredChats[3].activity, "Some text 2"); + EXPECT_EQ(restoredChats[3].nick, "Nick Name"); + ASSERT_EQ(restoredChats[3].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + testOptionalPasswordValue(restoredChats[3].password, "pass"); + ASSERT_EQ(restoredChats[3].inviteesNames.size(), 1); + EXPECT_EQ(restoredChats[3].inviteesNames["user1@domain.com"], "user1@domain.com"); +} + +TEST_F(ChatListWindowChatTest, testVersionsSerialization) { + auto archiveLibraryVersion = boost::archive::BOOST_ARCHIVE_VERSION(); + /* + The following strings are base64 serialised vectors with these Swift::ChatListWindow::Chat elements: + + Chat1: Jid = "swift@rooms.swift.im", ChatName = "swift@rooms.swift.im", Activity = "Some text 0", isMUC = false, nick="Nick Name" + Chat2: Jid = "testuser1@domain.com", ChatName = "swift@rooms2.swift.im", Activity = "Some text 1", isMUC = false, nick="Nick Name", password = "pass" + Chat3: Jid = "testuser2@domain.com", ChatName = "room2", Activity = "Some text 2", isMUC = true, nick="Nick Name", impromptuJIDs, inviteesNames + Chat4: Jid = "testuser3@domain.com", ChatName = "room3", Activity = "Some text 2", isMUC = true, nick="Nick Name", impromptuJIDs, password = "pass", inviteesNames + + impromptuJIDs = {("testuser1@domain.com","testuser1@domain.com"), ("testuser2@domain.com", "testuser2@domain.com")} + inviteesNames = {("user1@domain.com","user1@domain.com")} + */ + std::string serializedChats_BoostArchiveV10_ClassVersion_0 = "MjIgc2VyaWFsaXphdGlvbjo6YXJjaGl2ZSAxMCAwIDAgNCAwIDAgMCAwIDAgMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMTEgU29tZSB0ZXh0IDAgMCA5IE5pY2sgTmFtZSAwIDAgMCAwIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIxIHN3aWZ0QHJvb21zMi5zd2lmdC5pbSAxMSBTb21lIHRleHQgMSAwIDkgTmljayBOYW1lIDAgMCAyMCB0ZXN0dXNlcjJAZG9tYWluLmNvbSA2IHJvb20gMiAxMSBTb21lIHRleHQgMiAxIDkgTmljayBOYW1lIDIgMCAwIDAgMjAgdGVzdHVzZXIxQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIxQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIyQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIyQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIzQGRvbWFpbi5jb20gNiByb29tIDMgMTEgU29tZSB0ZXh0IDIgMSA5IE5pY2sgTmFtZSAyIDAgMjAgdGVzdHVzZXIxQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIxQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIyQGRvbWFpbi5jb20gMjAgdGVzdHVzZXIyQGRvbWFpbi5jb20="; + { + auto restoredChats = chatsDeserialise(serializedChats_BoostArchiveV10_ClassVersion_0); + if (archiveLibraryVersion == Swift::BoostArchiveSkipVersion) { + ASSERT_EQ(restoredChats.size(), 0); + } + else { + ASSERT_EQ(restoredChats.size(), 4); + + EXPECT_FALSE(restoredChats[0].isMUC); + EXPECT_EQ(restoredChats[0].jid, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].chatName, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].activity, "Some text 0"); + EXPECT_EQ(restoredChats[0].nick, "Nick Name"); + EXPECT_EQ(restoredChats[0].impromptuJIDs.size(), 0); + + EXPECT_FALSE(restoredChats[1].isMUC); + EXPECT_EQ(restoredChats[1].jid, "testuser1@domain.com"); + EXPECT_EQ(restoredChats[1].chatName, "swift@rooms2.swift.im"); + EXPECT_EQ(restoredChats[1].activity, "Some text 1"); + EXPECT_EQ(restoredChats[1].nick, "Nick Name"); + EXPECT_EQ(restoredChats[1].impromptuJIDs.size(), 0); + + EXPECT_TRUE(restoredChats[2].isMUC); + EXPECT_EQ(restoredChats[2].jid, "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].chatName, "room 2"); + EXPECT_EQ(restoredChats[2].activity, "Some text 2"); + EXPECT_EQ(restoredChats[2].nick, "Nick Name"); + ASSERT_EQ(restoredChats[2].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + + EXPECT_TRUE(restoredChats[3].isMUC); + EXPECT_EQ(restoredChats[3].jid, "testuser3@domain.com"); + EXPECT_EQ(restoredChats[3].chatName, "room 3"); + EXPECT_EQ(restoredChats[3].activity, "Some text 2"); + EXPECT_EQ(restoredChats[3].nick, "Nick Name"); + ASSERT_EQ(restoredChats[3].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + } + } + + std::string serializedChats_BoostArchiveV10_ClassVersion_1 = "MjIgc2VyaWFsaXphdGlvbjo6YXJjaGl2ZSAxMCAwIDAgNCAxIDAgMSAwIDAgMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMTEgU29tZSB0ZXh0IDAgMCA5IE5pY2sgTmFtZSAwIDAgMCAwIDAgMCAwIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIxIHN3aWZ0QHJvb21zMi5zd2lmdC5pbSAxMSBTb21lIHRleHQgMSAwIDkgTmljayBOYW1lIDAgMCAxIDAgNCBwYXNzIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDYgcm9vbSAyIDExIFNvbWUgdGV4dCAyIDEgOSBOaWNrIE5hbWUgMiAwIDAgMCAyMCB0ZXN0dXNlcjFAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjFAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjJAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjJAZG9tYWluLmNvbSAwIDIwIHRlc3R1c2VyM0Bkb21haW4uY29tIDYgcm9vbSAzIDExIFNvbWUgdGV4dCAyIDEgOSBOaWNrIE5hbWUgMiAwIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDEgMCA0IHBhc3M="; + { + auto restoredChats = chatsDeserialise(serializedChats_BoostArchiveV10_ClassVersion_1); + if (archiveLibraryVersion == Swift::BoostArchiveSkipVersion) { + ASSERT_EQ(restoredChats.size(), 0); + } + else { + ASSERT_EQ(restoredChats.size(), 4); + + EXPECT_FALSE(restoredChats[0].isMUC); + EXPECT_EQ(restoredChats[0].jid, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].chatName, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].activity, "Some text 0"); + EXPECT_EQ(restoredChats[0].nick, "Nick Name"); + EXPECT_EQ(restoredChats[0].impromptuJIDs.size(), 0); + EXPECT_EQ(restoredChats[0].password.get_value_or(""), ""); + + EXPECT_FALSE(restoredChats[1].isMUC); + EXPECT_EQ(restoredChats[1].jid, "testuser1@domain.com"); + EXPECT_EQ(restoredChats[1].chatName, "swift@rooms2.swift.im"); + EXPECT_EQ(restoredChats[1].activity, "Some text 1"); + EXPECT_EQ(restoredChats[1].nick, "Nick Name"); + EXPECT_EQ(restoredChats[1].impromptuJIDs.size(), 0); + EXPECT_EQ(restoredChats[1].password.get_value_or(""), "pass"); + + EXPECT_TRUE(restoredChats[2].isMUC); + EXPECT_EQ(restoredChats[2].jid, "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].chatName, "room 2"); + EXPECT_EQ(restoredChats[2].activity, "Some text 2"); + EXPECT_EQ(restoredChats[2].nick, "Nick Name"); + ASSERT_EQ(restoredChats[2].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].password.get_value_or(""), ""); + + EXPECT_TRUE(restoredChats[3].isMUC); + EXPECT_EQ(restoredChats[3].jid, "testuser3@domain.com"); + EXPECT_EQ(restoredChats[3].chatName, "room 3"); + EXPECT_EQ(restoredChats[3].activity, "Some text 2"); + EXPECT_EQ(restoredChats[3].nick, "Nick Name"); + ASSERT_EQ(restoredChats[3].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + EXPECT_EQ(restoredChats[3].password.get_value_or(""), "pass"); + } + } + + std::string serializedChats_BoostArchiveV10_ClassVersion_2 = "MjIgc2VyaWFsaXphdGlvbjo6YXJjaGl2ZSAxMCAwIDAgNCAyIDAgMiAwIDAgMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMjAgc3dpZnRAcm9vbXMuc3dpZnQuaW0gMTEgU29tZSB0ZXh0IDAgMCA5IE5pY2sgTmFtZSAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMjAgdGVzdHVzZXIxQGRvbWFpbi5jb20gMjEgc3dpZnRAcm9vbXMyLnN3aWZ0LmltIDExIFNvbWUgdGV4dCAxIDAgOSBOaWNrIE5hbWUgMCAwIDEgMCA0IHBhc3MgMCAwIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDYgcm9vbSAyIDExIFNvbWUgdGV4dCAyIDEgOSBOaWNrIE5hbWUgMiAwIDAgMCAyMCB0ZXN0dXNlcjFAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjFAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjJAZG9tYWluLmNvbSAyMCB0ZXN0dXNlcjJAZG9tYWluLmNvbSAwIDEgMCAwIDAgMTYgdXNlcjFAZG9tYWluLmNvbSAxNiB1c2VyMUBkb21haW4uY29tIDIwIHRlc3R1c2VyM0Bkb21haW4uY29tIDYgcm9vbSAzIDExIFNvbWUgdGV4dCAyIDEgOSBOaWNrIE5hbWUgMiAwIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIwIHRlc3R1c2VyMUBkb21haW4uY29tIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDIwIHRlc3R1c2VyMkBkb21haW4uY29tIDEgMCA0IHBhc3MgMSAwIDE2IHVzZXIxQGRvbWFpbi5jb20gMTYgdXNlcjFAZG9tYWluLmNvbQ=="; + { + auto restoredChats = chatsDeserialise(serializedChats_BoostArchiveV10_ClassVersion_2); + if (archiveLibraryVersion == Swift::BoostArchiveSkipVersion) { + ASSERT_EQ(restoredChats.size(), 0); + } + else { + ASSERT_EQ(restoredChats.size(), 4); + + EXPECT_FALSE(restoredChats[0].isMUC); + EXPECT_EQ(restoredChats[0].jid, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].chatName, "swift@rooms.swift.im"); + EXPECT_EQ(restoredChats[0].activity, "Some text 0"); + EXPECT_EQ(restoredChats[0].nick, "Nick Name"); + EXPECT_EQ(restoredChats[0].impromptuJIDs.size(), 0); + EXPECT_EQ(restoredChats[0].password.get_value_or(""), ""); + EXPECT_EQ(restoredChats[0].inviteesNames.size(), 0); + + EXPECT_FALSE(restoredChats[1].isMUC); + EXPECT_EQ(restoredChats[1].jid, "testuser1@domain.com"); + EXPECT_EQ(restoredChats[1].chatName, "swift@rooms2.swift.im"); + EXPECT_EQ(restoredChats[1].activity, "Some text 1"); + EXPECT_EQ(restoredChats[1].nick, "Nick Name"); + EXPECT_EQ(restoredChats[1].impromptuJIDs.size(), 0); + EXPECT_EQ(restoredChats[1].password.get_value_or(""), "pass"); + EXPECT_EQ(restoredChats[1].inviteesNames.size(), 0); + + EXPECT_TRUE(restoredChats[2].isMUC); + EXPECT_EQ(restoredChats[2].jid, "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].chatName, "room 2"); + EXPECT_EQ(restoredChats[2].activity, "Some text 2"); + EXPECT_EQ(restoredChats[2].nick, "Nick Name"); + ASSERT_EQ(restoredChats[2].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[2].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + EXPECT_EQ(restoredChats[2].password.get_value_or(""), ""); + ASSERT_EQ(restoredChats[2].inviteesNames.size(), 1); + EXPECT_EQ(restoredChats[2].inviteesNames["user1@domain.com"], "user1@domain.com"); + + EXPECT_TRUE(restoredChats[3].isMUC); + EXPECT_EQ(restoredChats[3].jid, "testuser3@domain.com"); + EXPECT_EQ(restoredChats[3].chatName, "room 3"); + EXPECT_EQ(restoredChats[3].activity, "Some text 2"); + EXPECT_EQ(restoredChats[3].nick, "Nick Name"); + ASSERT_EQ(restoredChats[3].impromptuJIDs.size(), 2); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser1@domain.com"], "testuser1@domain.com"); + EXPECT_EQ(restoredChats[3].impromptuJIDs["testuser2@domain.com"], "testuser2@domain.com"); + EXPECT_EQ(restoredChats[3].password.get_value_or(""), "pass"); + ASSERT_EQ(restoredChats[3].inviteesNames.size(), 1); + EXPECT_EQ(restoredChats[3].inviteesNames["user1@domain.com"], "user1@domain.com"); + } + } +} + diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index e06a3c7..4a46b32 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Isode Limited. + * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -32,9 +32,12 @@ #include <Swiften/Elements/Forwarded.h> #include <Swiften/Elements/MUCInvitationPayload.h> #include <Swiften/Elements/MUCUserPayload.h> +#include <Swiften/Elements/PrivateStorage.h> +#include <Swiften/Elements/Storage.h> #include <Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/MUC/MUCManager.h> +#include <Swiften/MUC/UnitTest/MockMUC.h> #include <Swiften/Network/DummyTimerFactory.h> #include <Swiften/Presence/DirectedPresenceSender.h> #include <Swiften/Presence/PresenceOracle.h> @@ -71,7 +74,6 @@ #include <SwifTools/Notifier/Notifier.h> #include <Swift/QtUI/QtSwiftUtil.h> -#include <Swiften/MUC/UnitTest/MockMUC.h> using namespace Swift; @@ -155,6 +157,11 @@ class ChatsManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST(testImpromptuChatWindowTitle); CPPUNIT_TEST(testStandardMUCChatWindowTitle); + // Bookmark tests + CPPUNIT_TEST(testReceivingBookmarksWithDomainJID); + CPPUNIT_TEST(testReceivingBookmarksWithBareJID); + CPPUNIT_TEST(testReceivingBookmarksWithFullJID); + CPPUNIT_TEST_SUITE_END(); public: @@ -1228,6 +1235,11 @@ public: CPPUNIT_ASSERT_EQUAL(forwardedBody, MockChatWindow::bodyFromMessage(window->lastAddedMessage_)); CPPUNIT_ASSERT_EQUAL(false, window->lastAddedMessageSenderIsSelf_); + + auto recentChats = manager_->getRecentChats(); + CPPUNIT_ASSERT_EQUAL(recentChats.size(), size_t(1)); + CPPUNIT_ASSERT_EQUAL(recentChats[0].jid, originalMessage->getFrom().toBare()); + CPPUNIT_ASSERT_EQUAL(recentChats[0].activity, std::string("Some further text.")); } } @@ -1264,6 +1276,11 @@ public: CPPUNIT_ASSERT_EQUAL(true, window->lastAddedMessageSenderIsSelf_); CPPUNIT_ASSERT_EQUAL(size_t(1), window->receiptChanges_.size()); CPPUNIT_ASSERT_EQUAL(ChatWindow::ReceiptRequested, window->receiptChanges_[0].second); + + auto recentChats = manager_->getRecentChats(); + CPPUNIT_ASSERT_EQUAL(recentChats.size(), size_t(1)); + CPPUNIT_ASSERT_EQUAL(recentChats[0].jid, originalMessage->getTo().toBare()); + CPPUNIT_ASSERT_EQUAL(recentChats[0].activity, std::string("Some text my other resource sent.")); } // incoming carbons message for the received delivery receipt to the other resource @@ -1280,6 +1297,12 @@ public: CPPUNIT_ASSERT_EQUAL(size_t(2), window->receiptChanges_.size()); CPPUNIT_ASSERT_EQUAL(ChatWindow::ReceiptReceived, window->receiptChanges_[1].second); + + //Delivery receipt should not change the latest recent entry. Checking for the original message. + auto recentChats = manager_->getRecentChats(); + CPPUNIT_ASSERT_EQUAL(recentChats.size(), size_t(1)); + CPPUNIT_ASSERT_EQUAL(recentChats[0].jid, messageJID.toBare()); + CPPUNIT_ASSERT_EQUAL(recentChats[0].activity, std::string("Some text my other resource sent.")); } } @@ -1319,6 +1342,11 @@ public: manager_->handleIncomingMessage(messageWrapper); CPPUNIT_ASSERT_EQUAL(std::string(), MockChatWindow::bodyFromMessage(window->lastAddedMessage_)); CPPUNIT_ASSERT_EQUAL(false, window->lastAddedMessageSenderIsSelf_); + + auto recentChats = manager_->getRecentChats(); + CPPUNIT_ASSERT_EQUAL(recentChats.size(), size_t(1)); + CPPUNIT_ASSERT_EQUAL(recentChats[0].jid, originalMessage->getFrom().toBare()); + CPPUNIT_ASSERT_EQUAL(recentChats[0].activity, std::string("Some further text.")); } } @@ -1602,6 +1630,78 @@ public: CPPUNIT_ASSERT_EQUAL(std::string("mucroom"), window->name_); } + static std::shared_ptr<Storage> createBookmarkStorageWithJID(const JID& jid) { + auto storage = std::make_shared<Storage>(); + auto room = Storage::Room(); + room.jid = jid; + room.autoJoin = true; + storage->addRoom(room); + return storage; + } + + void testReceivingBookmarksWithDomainJID() { + auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]); + CPPUNIT_ASSERT(bookmarkRequest); + CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType()); + + auto privateStorage = bookmarkRequest->getPayload<PrivateStorage>(); + CPPUNIT_ASSERT(privateStorage); + + auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload()); + CPPUNIT_ASSERT(storage); + + auto response = IQ::createResult( + bookmarkRequest->getFrom(), + bookmarkRequest->getTo(), + bookmarkRequest->getID(), + std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("montague.lit")) + ); + stanzaChannel_->onIQReceived(response); + } + + void testReceivingBookmarksWithBareJID() { + auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]); + CPPUNIT_ASSERT(bookmarkRequest); + CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType()); + + auto privateStorage = bookmarkRequest->getPayload<PrivateStorage>(); + CPPUNIT_ASSERT(privateStorage); + + auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload()); + CPPUNIT_ASSERT(storage); + + MockChatWindow* window = new MockChatWindow(); + mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(JID("example@montague.lit"), uiEventStream_).Return(window); + + auto response = IQ::createResult( + bookmarkRequest->getFrom(), + bookmarkRequest->getTo(), + bookmarkRequest->getID(), + std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("example@montague.lit")) + ); + stanzaChannel_->onIQReceived(response); + } + + void testReceivingBookmarksWithFullJID() { + auto bookmarkRequest = std::dynamic_pointer_cast<IQ>(stanzaChannel_->sentStanzas[0]); + CPPUNIT_ASSERT(bookmarkRequest); + CPPUNIT_ASSERT_EQUAL(IQ::Get, bookmarkRequest->getType()); + + auto privateStorage = bookmarkRequest->getPayload<PrivateStorage>(); + CPPUNIT_ASSERT(privateStorage); + + auto storage = std::dynamic_pointer_cast<Storage>(privateStorage->getPayload()); + CPPUNIT_ASSERT(storage); + + auto response = IQ::createResult( + bookmarkRequest->getFrom(), + bookmarkRequest->getTo(), + bookmarkRequest->getID(), + std::make_shared<PrivateStorage>(createBookmarkStorageWithJID("example@montague.lit/someresource")) + ); + stanzaChannel_->onIQReceived(response); + } + private: std::shared_ptr<Message> makeDeliveryReceiptTestMessage(const JID& from, const std::string& id) { std::shared_ptr<Message> message = std::make_shared<Message>(); @@ -1668,4 +1768,3 @@ private: }; CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest); - diff --git a/Swift/Controllers/Highlighting/HighlightAction.cpp b/Swift/Controllers/Highlighting/HighlightAction.cpp index e9f14df..60ace42 100644 --- a/Swift/Controllers/Highlighting/HighlightAction.cpp +++ b/Swift/Controllers/Highlighting/HighlightAction.cpp @@ -12,6 +12,8 @@ #include <Swift/Controllers/Highlighting/HighlightAction.h> +BOOST_CLASS_VERSION(Swift::HighlightAction, 1) + namespace Swift { diff --git a/Swift/Controllers/Highlighting/HighlightAction.h b/Swift/Controllers/Highlighting/HighlightAction.h index da92901..d11f3ec 100644 --- a/Swift/Controllers/Highlighting/HighlightAction.h +++ b/Swift/Controllers/Highlighting/HighlightAction.h @@ -12,11 +12,14 @@ #pragma once +#include <map> +#include <memory> #include <string> #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/optional.hpp> +#include <boost/serialization/map.hpp> #include <boost/serialization/optional.hpp> namespace Swift { @@ -57,12 +60,53 @@ namespace Swift { bool operator ==(const HighlightAction& a, const HighlightAction& b); bool operator !=(const HighlightAction& a, const HighlightAction& b); + template<class Archive> - void HighlightAction::serialize(Archive& ar, const unsigned int /*version*/) { - ar & frontColor_; - ar & backColor_; - ar & soundFilePath_; - ar & systemNotificaitonEnabled_; + void HighlightAction::serialize(Archive& ar, const unsigned int version) { + auto inputStream = dynamic_cast<boost::archive::text_iarchive*>(&ar); + auto outputStream = dynamic_cast<boost::archive::text_oarchive*>(&ar); + + if (version == 0) { + if (inputStream) { + const boost::archive::library_version_type BoostArchiveSkipVersion(15); + auto archiveLibraryVersion = boost::archive::BOOST_ARCHIVE_VERSION(); + //Due to https://svn.boost.org/trac10/ticket/13050 the boost::optional fields may fail to load and crash the client. Therefore we skip loading the values from previous versions. + if (archiveLibraryVersion == BoostArchiveSkipVersion && archiveLibraryVersion > inputStream->get_library_version()) { + return; + } + } + ar & frontColor_; + ar & backColor_; + ar & soundFilePath_; + ar & systemNotificaitonEnabled_; + } + else if (version == 1) { + //Using a map instead of optional values that may cause a problems when serialised with boost::archive 15 version + std::map<std::string, std::string> properties; + if (outputStream) { + if (frontColor_.is_initialized()) { + properties["frontColor"] = frontColor_.get(); + } + if (backColor_.is_initialized()) { + properties["backColor"] = backColor_.get(); + } + if (soundFilePath_.is_initialized()) { + properties["soundFilePath"] = soundFilePath_.get(); + } + } + ar & properties; + ar & systemNotificaitonEnabled_; + if (inputStream) { + if (properties.find("frontColor") != properties.end()) { + frontColor_ = properties["frontColor"]; + } + if (properties.find("backColor") != properties.end()) { + backColor_ = properties["backColor"]; + } + if (properties.find("soundFilePath") != properties.end()) { + soundFilePath_ = properties["soundFilePath"]; + } + } + } } - } diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index 0c3127c..bc5c2c0 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -93,6 +93,7 @@ if env["SCONS_STAGE"] == "build" : ]) env.Append(UNITTEST_SOURCES = [ + File("Chat/UnitTest/ChatListWindowChatTest.cpp"), File("Chat/UnitTest/ChatMessageParserTest.cpp"), File("Chat/UnitTest/ChatsManagerTest.cpp"), File("Chat/UnitTest/MUCControllerTest.cpp"), diff --git a/Swift/Controllers/Storages/AvatarFileStorage.cpp b/Swift/Controllers/Storages/AvatarFileStorage.cpp index a103920..9d9b9ea 100644 --- a/Swift/Controllers/Storages/AvatarFileStorage.cpp +++ b/Swift/Controllers/Storages/AvatarFileStorage.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Storages/AvatarFileStorage.h> -#include <iostream> - #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/StringCodecs/Hexify.h> @@ -31,13 +30,13 @@ AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, jidAvatars.insert(std::make_pair(jid, r.first)); } else if (!r.first.empty() || !r.second.empty()) { - std::cerr << "Invalid entry in avatars file: " << r.second << std::endl; + SWIFT_LOG(error) << "Invalid entry in avatars file: " << r.second << std::endl; } } } } catch (...) { - std::cerr << "Error reading avatars file" << std::endl; + SWIFT_LOG(error) << "Error reading avatars file" << std::endl; } } } @@ -55,12 +54,17 @@ void AvatarFileStorage::addAvatar(const std::string& hash, const ByteArray& avat boost::filesystem::create_directories(avatarPath.parent_path()); } catch (const boost::filesystem::filesystem_error& e) { - std::cerr << "ERROR: " << e.what() << std::endl; + SWIFT_LOG(error) << "filesystem error: " << e.what() << std::endl; } } - boost::filesystem::ofstream file(avatarPath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out); - file.write(reinterpret_cast<const char*>(vecptr(avatar)), static_cast<std::streamsize>(avatar.size())); - file.close(); + + try { + boost::filesystem::ofstream file(avatarPath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out); + file.write(reinterpret_cast<const char*>(vecptr(avatar)), static_cast<std::streamsize>(avatar.size())); + } + catch (const boost::filesystem::filesystem_error& e) { + SWIFT_LOG(error) << "filesystem error: " << e.what() << std::endl; + } } boost::filesystem::path AvatarFileStorage::getAvatarPath(const std::string& hash) const { @@ -69,7 +73,12 @@ boost::filesystem::path AvatarFileStorage::getAvatarPath(const std::string& hash ByteArray AvatarFileStorage::getAvatar(const std::string& hash) const { ByteArray data; - readByteArrayFromFile(data, getAvatarPath(hash)); + try { + readByteArrayFromFile(data, getAvatarPath(hash)); + } + catch (const boost::filesystem::filesystem_error& e) { + SWIFT_LOG(error) << "filesystem error: " << e.what() << std::endl; + } return data; } @@ -98,7 +107,7 @@ void AvatarFileStorage::saveJIDAvatars() { file.close(); } catch (...) { - std::cerr << "Error writing avatars file" << std::endl; + SWIFT_LOG(error) << "Error writing avatars file" << std::endl; } } diff --git a/Swift/Packaging/Debian/Testing/swift-distr-tests.sh b/Swift/Packaging/Debian/Testing/swift-distr-tests.sh index 8d03282..e817974 100755 --- a/Swift/Packaging/Debian/Testing/swift-distr-tests.sh +++ b/Swift/Packaging/Debian/Testing/swift-distr-tests.sh @@ -40,25 +40,31 @@ arr[0,0]="ubuntu" arr[0,1]="http://archive.ubuntu.com/ubuntu" arr[0,2]="xenial" -#Ubuntu yakkety +#Ubuntu artful arr[1,0]="ubuntu" arr[1,1]="http://archive.ubuntu.com/ubuntu" -arr[1,2]="yakkety" +arr[1,2]="artful" #Debian jessie arr[2,0]="debian" arr[2,1]="http://deb.debian.org/debian/" arr[2,2]="jessie" -#Debian sid +#Debian stretch arr[3,0]="debian" arr[3,1]="http://deb.debian.org/debian/" -arr[3,2]="sid" +arr[3,2]="stretch" + +#Debian sid +arr[4,0]="debian" +arr[4,1]="http://deb.debian.org/debian/" +arr[4,2]="sid" + DIST="$1" RETURN_VALUE=0 -for counter in {0..3} +for counter in {0..4} do # for ARCH in "amd64" "i386" for ARCH in "amd64" diff --git a/Swift/Packaging/Debian/debian/control.in b/Swift/Packaging/Debian/debian/control.in index 26544e5..e779f21 100644 --- a/Swift/Packaging/Debian/debian/control.in +++ b/Swift/Packaging/Debian/debian/control.in @@ -3,7 +3,7 @@ Section: net Priority: optional Maintainer: Swift Package Maintainer <packages@swift.im> Uploaders: Remko Tronçon <dev@el-tramo.be>, Kevin Smith <kevin@kismith.co.uk> -Build-Depends: debhelper (>= 9), scons (>= 1.2.0), libssl-dev (>= 0.9.8g), qtbase5-dev (>= 5.0.0), qtchooser, qtbase5-dev-tools (>= 5.0.0), libqt5x11extras5-dev (>= 5.0.0), libqt5webkit5-dev (>= 5.0.0), qtmultimedia5-dev (>=5.0.0), qttools5-dev-tools (>=5.0.0), qt5-image-formats-plugins (>=5.0.0), libqt5svg5-dev (>=5.0.0), libxml2-dev (>= 2.7.6), libxss-dev (>= 1.2.0), libboost-dev (>= 1.34.1), libboost-filesystem-dev (>= 1.34.1), libboost-program-options-dev (>= 1.34.1), libboost-regex-dev (>= 1.34.1), libboost-signals-dev (>= 1.34.1), libboost-system-dev (>= 1.34.1), libboost-thread-dev (>= 1.34.1), libboost-date-time-dev (>= 1.34.1), libidn11-dev (>= 1.10), docbook-xsl (>= 1.75.0), docbook-xml (>= 4.5), xsltproc, libxml2-utils, libnatpmp-dev, libminiupnpc-dev, libsqlite3-dev, libhunspell-dev, zlib1g-dev +Build-Depends: debhelper (>= 9), scons (>= 1.2.0), libssl-dev (>= 0.9.8g), qtbase5-dev (>= 5.0.0), qtchooser, qtbase5-dev-tools (>= 5.0.0), libqt5x11extras5-dev (>= 5.0.0), libqt5webkit5-dev (>= 5.0.0), qtmultimedia5-dev (>=5.0.0), qttools5-dev-tools (>=5.0.0), qt5-image-formats-plugins (>=5.0.0), libqt5svg5-dev (>=5.0.0), libxml2-dev (>= 2.7.6), libxss-dev (>= 1.2.0), libboost-dev (>= 1.34.1), libboost-filesystem-dev (>= 1.34.1), libboost-program-options-dev (>= 1.34.1), libboost-regex-dev (>= 1.34.1), libboost-signals-dev (>= 1.34.1), libboost-system-dev (>= 1.34.1), libboost-thread-dev (>= 1.34.1), libboost-date-time-dev (>= 1.34.1), libidn11-dev (>= 1.10), docbook-xsl (>= 1.75.0), docbook-xml (>= 4.5), xsltproc, libxml2-utils, libnatpmp-dev, libminiupnpc-dev, libsqlite3-dev, libhunspell-dev, zlib1g-dev, help2man Standards-Version: 3.9.8 Vcs-Git: git://swift.im/swift Vcs-Browser: http://swift.im/git/swift diff --git a/Swift/Packaging/Debian/debian/rules b/Swift/Packaging/Debian/debian/rules index 87c551b..ed432bb 100755 --- a/Swift/Packaging/Debian/debian/rules +++ b/Swift/Packaging/Debian/debian/rules @@ -4,7 +4,7 @@ export PYTHONDONTWRITEBYTECODE=1 export QT_SELECT=qt5 -SCONS_FLAGS=V=1 qt5=1 optimize=1 debug=1 allow_warnings=1 swiften_dll=1 docbook_xsl=/usr/share/xml/docbook/stylesheet/docbook-xsl docbook_xml=/usr/share/xml/docbook/schema/dtd/4.5 linkflags="$(shell dpkg-buildflags --get LDFLAGS)" ccflags="$(shell dpkg-buildflags --get CPPFLAGS) $(shell dpkg-buildflags --get CFLAGS)" +SCONS_FLAGS=V=1 qt5=1 optimize=1 debug=1 allow_warnings=1 swiften_dll=1 help2man=1 docbook_xsl=/usr/share/xml/docbook/stylesheet/docbook-xsl docbook_xml=/usr/share/xml/docbook/schema/dtd/4.5 linkflags="$(shell dpkg-buildflags --get LDFLAGS)" ccflags="$(shell dpkg-buildflags --get CPPFLAGS) $(shell dpkg-buildflags --get CFLAGS)" SCONS_INSTALL_BASE=$(CURDIR)/debian/tmp SCONS_INSTALL_FLAGS=SWIFT_INSTALLDIR=$(SCONS_INSTALL_BASE)/usr SWIFTEN_INSTALLDIR=$(SCONS_INSTALL_BASE)/usr SWIFT_INSTALLDIR=$(SCONS_INSTALL_BASE)/usr SWIFTEN_INSTALLDIR=$(SCONS_INSTALL_BASE)/usr @@ -21,7 +21,7 @@ override_dh_clean: override_dh_configure: override_dh_auto_build: - scons $(SCONS_FLAGS) $(SCONS_EXTRA_FLAGS) Swift Swiften + scons $(SCONS_FLAGS) $(SCONS_EXTRA_FLAGS) Swift Swiften debian/swift-im.1 debian/swiften-config.1 override_dh_auto_install: scons $(SCONS_FLAGS) $(SCONS_EXTRA_FLAGS) $(SCONS_INSTALL_FLAGS) $(SCONS_INSTALL_BASE) diff --git a/Swift/Packaging/Debian/package.sh b/Swift/Packaging/Debian/package.sh index d19f5dc..62dfff0 100755 --- a/Swift/Packaging/Debian/package.sh +++ b/Swift/Packaging/Debian/package.sh @@ -95,18 +95,6 @@ cat $DIRNAME/debian/control.in | sed -e "s/%SWIFTEN_SOVERSION%/$SWIFTEN_SOVERSIO rm $DIRNAME/debian/control.in mv $DIRNAME/debian/libswiften.install $DIRNAME/debian/libswiften$SWIFTEN_SOVERSION.install cat ../../../COPYING.thirdparty | tail -n +3 >> $DIRNAME/debian/copyright -# Generate updated man-page if possible -if type "help2man" > /dev/null 2>&1; then - if [ -f ../../QtUI/swift-im ]; then - help2man -m "Swift Manual" -S "Swift" -n "swift-im" -N ../../QtUI/swift-im > $DIRNAME/debian/swift-im.1 - fi - if [ -f ../../../Swiften/Config/swiften-config ]; then - help2man -m "Swift Manual" -S "swiften-config" -n "swiften-config" -N ../../../Swiften/Config/swiften-config > $DIRNAME/debian/swiften-config.1 - fi -else - >2& echo "Unable to generate man pages. Please ensure that help2man is installed" - exit 1; -fi # Build cd $DIRNAME diff --git a/Swift/Packaging/Debian/package_all_platforms.sh b/Swift/Packaging/Debian/package_all_platforms.sh index 097fe38..afd0621 100755 --- a/Swift/Packaging/Debian/package_all_platforms.sh +++ b/Swift/Packaging/Debian/package_all_platforms.sh @@ -24,9 +24,15 @@ export SWIFT_FORCE_LUCID="yep" unset SWIFT_FORCE_LUCID ./package.sh -for distro in xenial yakkety jessie sid; do +if [ -z ${SWIFT_PACKAGE_PLATFORMS+x} ]; +then + platformsarray=( xenial artful jessie stretch sid ) +else + platformsarray=( $SWIFT_PACKAGE_PLATFORMS ) +fi + +for distro in "${platformsarray[@]}"; do for arch in amd64; do pbuilder-dist $distro $arch build *.dsc done done - diff --git a/Swift/Packaging/Debian/update_debian_repo.sh b/Swift/Packaging/Debian/update_debian_repo.sh index d62a376..b057103 100644 --- a/Swift/Packaging/Debian/update_debian_repo.sh +++ b/Swift/Packaging/Debian/update_debian_repo.sh @@ -73,12 +73,23 @@ command -v reprepro >/dev/null 2>&1 || { echo >&2 "This script requires aptly bu mkdir -p $APT_REPO_ROOT +if [ -z ${SWIFT_PACKAGE_PLATFORMS+x} ]; then + platformsarray=( xenial artful jessie stretch sid ) +else + platformsarray=( $SWIFT_PACKAGE_PLATFORMS ) +fi + # distros for full_distribution_path in $INCOMING_FOLDER/{debian,ubuntu}/*; do distro_version=`basename $full_distribution_path` distro_name=$(basename `dirname $full_distribution_path`) distro_reprepro_root=${APT_REPO_ROOT}/${distro_name}/${distro_version} + if ! [[ $SWIFT_PACKAGE_PLATFORMS == *"$distro_version"* ]]; then + echo "$distro_version was not found in SWIFT_PACKAGE_PLATFORMS. Skipping..." + continue + fi + # ensure reprepro diretctory for this distribution version is present if [ ! -d "$distro_preprepro_root" ]; then echo "Create distribution repository for $distro_name/$distro_version" @@ -89,7 +100,7 @@ for full_distribution_path in $INCOMING_FOLDER/{debian,ubuntu}/*; do write_reprepo_conf_incoming_to_file "${distro_reprepro_root}/conf/incoming" "$full_distribution_path" fi - # This is workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808558 + # This is workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808558 # and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=843402 if [ "$distro_name/$distro_version" = "debian/sid" ]; then sed -i '/dbgsym/ d' $full_distribution_path/*.changes diff --git a/Swift/Packaging/SConscript b/Swift/Packaging/SConscript new file mode 100644 index 0000000..3aa791f --- /dev/null +++ b/Swift/Packaging/SConscript @@ -0,0 +1,29 @@ +Import("env") +import os + +################################################################################ +# Build +################################################################################ + +if env["SCONS_STAGE"] == "build" : + help2man = env.WhereIs('help2man', os.environ['PATH']) + if help2man: + env['HELP2MAN'] = help2man + env['HELP2MANSTR'] = "HELP2MAN $TARGET" + + if Dir("#/debian").exists(): + # This is needed for debian packaging using pbuilder which expects + # generated man pages in this location. + env['HELP2MAN_DEBIAN_DIR'] = "#/debian" + else: + env['HELP2MAN_DEBIAN_DIR'] = "Debian/debian" + + swiftenConfigHelp = env.Command( + target='$HELP2MAN_DEBIAN_DIR/swiften-config.1', source='#/Swiften/Config/swiften-config', + action = Action('$HELP2MAN --no-discard-stderr -m "Swift Manual" -S "swiften-config" -n "swiften-config" -N $SOURCE > $TARGET', cmdstr = "$HELP2MANSTR")) + swiftHelp = env.Command( + target='$HELP2MAN_DEBIAN_DIR/swift-im.1', source='#/Swift/QtUI/swift-im', + action = Action('$HELP2MAN --no-discard-stderr -m "Swift Manual" -S "Swift" -n "swift-im" -N $SOURCE > $TARGET', cmdstr = "$HELP2MANSTR")) + else: + print "Enabled help2man but help2man is not in the PATH of the current environment." + Exit(1) diff --git a/Swift/Packaging/WiX/include.xslt b/Swift/Packaging/WiX/include.xslt index ec1ad50..df86446 100644 --- a/Swift/Packaging/WiX/include.xslt +++ b/Swift/Packaging/WiX/include.xslt @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns="http://schemas.microsoft.com/wix/2006/wi" exclude-result-prefixes="xsl wix"> <xsl:template match='wix:Directory[@Id="Swift"]/@Id'> <xsl:attribute name='Id'>INSTALLDIR</xsl:attribute> @@ -11,4 +11,14 @@ <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> + + <xsl:template match="wix:Component"> + <xsl:copy> + <xsl:apply-templates select="@*"/> + <xsl:value-of select="concat(preceding-sibling::text(), ' ')" /> + <RemoveFile Id="remove_{@Id}" Name="{@Id}" On="install" /> + <xsl:apply-templates select="node()"/> + </xsl:copy> + </xsl:template> + </xsl:stylesheet> diff --git a/Swift/QtUI/CAPICertificateSelector.cpp b/Swift/QtUI/CAPICertificateSelector.cpp index 36d8c54..e47121b 100644 --- a/Swift/QtUI/CAPICertificateSelector.cpp +++ b/Swift/QtUI/CAPICertificateSelector.cpp @@ -18,7 +18,9 @@ #include <boost/algorithm/string.hpp> #include <Swift/Controllers/Intl.h> #include <Swift/QtUI/QtSwiftUtil.h> + #include <Swiften/Base/Log.h> +#include <Swiften/TLS/Schannel/SchannelUtil.h> namespace Swift { @@ -87,23 +89,22 @@ std::string selectCAPICertificate() { } } - - + std::string result; /* Call Windows dialog to select a suitable certificate */ - PCCERT_CONTEXT cert = CryptUIDlgSelectCertificateFromStore(hstore, hwnd, titleChars, promptChars, exclude_columns, 0, NULL); + { + ScopedCertContext cert(CryptUIDlgSelectCertificateFromStore(hstore, hwnd, titleChars, promptChars, exclude_columns, 0, NULL)); + if (cert) { + result = getCertUri(cert, certStoreName); + } + } delete[] titleChars; delete[] promptChars; if (hstore) { - CertCloseStore(hstore, 0); - } - - std::string result; - - if (cert) { - result = getCertUri(cert, certStoreName); - CertFreeCertificateContext(cert); + if (CertCloseStore(hstore, 0) == FALSE) { + SWIFT_LOG(debug) << "Failed to close the certificate store handle." << std::endl; + } } return result; diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp index ad95a07..f4d0d46 100644 --- a/Swift/QtUI/QtChatTabs.cpp +++ b/Swift/QtUI/QtChatTabs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -18,8 +18,8 @@ #include <QMenu> #include <QTabBar> #include <QTabWidget> -#include <QtGlobal> #include <QWindow> +#include <QtGlobal> #include <Swiften/Base/Log.h> @@ -112,8 +112,6 @@ void QtChatTabs::setViewMenu(QMenu* viewMenu) { if (trellisMode_) { viewMenu->addSeparator(); QAction* action = new QAction(tr("Change &layout"), this); - action->setShortcutContext(Qt::ApplicationShortcut); - action->setShortcut(QKeySequence(tr("Ctrl+Alt+L"))); connect(action, SIGNAL(triggered()), this, SLOT(handleOpenLayoutChangeDialog())); viewMenu->addAction(action); diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 96162ba..5981f9c 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -707,9 +707,9 @@ void QtChatWindow::handleEmojiClicked(QString emoji) { if (isVisible()) { input_->textCursor().insertText(emoji); input_->setFocus(); - // The next line also deletes the emojisGrid_, as it was added to the - // layout of the emojisMenu_. - emojisMenu_.reset(); + // We cannot delete the emojisGrid_ + // Grid may not close yet and we should not try to destroy it. + emojisMenu_->setVisible(false); } } diff --git a/Swift/QtUI/QtColorToolButton.cpp b/Swift/QtUI/QtColorToolButton.cpp index b349a47..6452cf4 100644 --- a/Swift/QtUI/QtColorToolButton.cpp +++ b/Swift/QtUI/QtColorToolButton.cpp @@ -36,6 +36,7 @@ void QtColorToolButton::setColor(const QColor& color) void QtColorToolButton::onClicked() { QColor c = QColorDialog::getColor(color_, this); + window()->raise(); if (c.isValid()) { setColor(c); } diff --git a/Swift/QtUI/QtSoundSelectionStyledItemDelegate.h b/Swift/QtUI/QtSoundSelectionStyledItemDelegate.h index fabf668..f03cacc 100644 --- a/Swift/QtUI/QtSoundSelectionStyledItemDelegate.h +++ b/Swift/QtUI/QtSoundSelectionStyledItemDelegate.h @@ -11,6 +11,7 @@ namespace Swift { class QtSoundSelectionStyledItemDelegate : public QStyledItemDelegate { + Q_OBJECT public: QtSoundSelectionStyledItemDelegate(QObject* parent = nullptr); diff --git a/Swift/QtUI/QtStrings.h b/Swift/QtUI/QtStrings.h index d0cd421..84bc7f9 100644 --- a/Swift/QtUI/QtStrings.h +++ b/Swift/QtUI/QtStrings.h @@ -26,6 +26,14 @@ QT_TRANSLATE_NOOP("QLineEdit", "&Copy"); QT_TRANSLATE_NOOP("QLineEdit", "&Paste"); QT_TRANSLATE_NOOP("QLineEdit", "Delete"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "Select All"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "&Undo"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "&Redo"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "Cu&t"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "&Copy"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "&Paste"); +QT_TRANSLATE_NOOP("QWidgetTextControl", "Delete"); + QT_TRANSLATE_NOOP("QScrollBar", "Scroll here"); QT_TRANSLATE_NOOP("QScrollBar", "Top"); QT_TRANSLATE_NOOP("QScrollBar", "Bottom"); @@ -76,6 +84,10 @@ QT_TRANSLATE_NOOP("QDialogButtonBox", "Cancel"); QT_TRANSLATE_NOOP("QMessageBox", "Show Details..."); QT_TRANSLATE_NOOP("QMessageBox", "Hide Details..."); +QT_TRANSLATE_NOOP("QPlatformTheme", "OK"); +QT_TRANSLATE_NOOP("QPlatformTheme", "Cancel"); +QT_TRANSLATE_NOOP("QPlatformTheme", "Restore Defaults"); + QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU", "Services"); QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU", "Hide %1"); QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU", "Hide Others"); diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 7b4e2c3..7daa5ce 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -101,6 +101,7 @@ po::options_description QtSwift::getOptionsDescription() { #if QT_VERSION >= 0x040800 ("language", po::value<std::string>(), "Use a specific language, instead of the system-wide one") #endif + ("logfile", po::value<std::string>()->implicit_value(""), "Save all logging information to a file") ; return result; } @@ -189,6 +190,16 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa Log::setLogLevel(Swift::Log::debug); } + if (options.count("logfile")) { + try { + std::string fileName = options["logfile"].as<std::string>(); + Log::setLogFile(fileName); + } + catch (...) { + SWIFT_LOG(error) << "Error while retrieving the specified log file name from the command line" << std::endl; + } + } + // Load fonts std::vector<std::string> fontNames = { "themes/Default/Lato2OFL/Lato-Black.ttf", @@ -214,7 +225,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa for (auto&& fontName : fontNames) { std::string fontPath = std::string(":/") + fontName; int error = QFontDatabase::addApplicationFont(P2QSTRING(fontPath)); - assert((error != -1) && "Failed to load font."); + SWIFT_LOG_ASSERT(error != -1, error) << "Failed to load font " << fontPath << std::endl; } bool enableAdHocCommandOnJID = options.count("enable-jid-adhocs") > 0; diff --git a/Swift/QtUI/QtTabWidget.cpp b/Swift/QtUI/QtTabWidget.cpp index 67e3ae9..99ef6ee 100644 --- a/Swift/QtUI/QtTabWidget.cpp +++ b/Swift/QtUI/QtTabWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Isode Limited. + * Copyright (c) 2010-2017 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -57,7 +57,7 @@ void QtTabWidget::paintEvent(QPaintEvent * event) { label.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); label.setGeometry(QRect(QPoint(0,0), size()) - QMargins(10,10,10,10)); label.setWordWrap(true); - label.setText(tr("This empty cell is a placeholder for chat windows. You can move existing chats to this cell by dragging the tab over here. You can change the number of cells via the 'Change layout' dialog under the 'View' menu or by using the %1 shortcut.").arg(QKeySequence(tr("Ctrl+Alt+L")).toString(QKeySequence::NativeText))); + label.setText(tr("This empty cell is a placeholder for chat windows. You can move existing chats to this cell by dragging the tab over here. You can change the number of cells via the 'Change layout' dialog under the 'View' menu.")); QPainter painter(this); painter.drawPixmap(label.geometry().topLeft(), label.grab()); } diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index ece29ec..583c477 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -10,6 +10,7 @@ #include <QSplitter> +#include <Swiften/Base/Log.h> #include <Swiften/Whiteboard/WhiteboardSession.h> #include <Swift/Controllers/Settings/SettingsProviderHierachy.h> @@ -46,6 +47,13 @@ QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* this->tabs = dynamic_cast<QtChatTabs*>(tabsBase); } +QtUIFactory::~QtUIFactory() { + SWIFT_LOG(debug) << "Entering QtUIFactory destructor. chatWindows size:" << chatWindows.size() << std::endl; + for (auto chat : chatWindows) { + SWIFT_LOG_ASSERT(chat.isNull(), debug) << "QtUIFactory has active chat windows and has not been reset properly" << std::endl; + } +} + XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() { QtXMLConsoleWidget* widget = new QtXMLConsoleWidget(); tabsBase->addTab(widget); diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 18bf9fe..9989101 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -36,7 +36,7 @@ namespace Swift { Q_OBJECT public: QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabsBase* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, AutoUpdater* autoUpdater, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID); - + ~QtUIFactory(); virtual XMLConsoleWidget* createXMLConsoleWidget(); virtual HistoryWindow* createHistoryWindow(UIEventStream*); virtual MainWindow* createMainWindow(UIEventStream* eventStream); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 77731df..3755187 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -501,7 +501,18 @@ if env["PLATFORM"] == "win32" : lightTask = myenv.WiX_Light('#/Packages/Swift/Swift-' + myenv["SWIFT_VERSION"] + '.msi', ['..\\Packaging\\WiX\\gen_files.wixobj','..\\Packaging\\WiX\\Swift.wixobj']) if myenv.get("SIGNTOOL_KEY_PFX", None) and myenv.get("SIGNTOOL_TIMESTAMP_URL", None) : def signToolAction(target = None, source = None, env = None): - env.Execute('signtool.exe sign /fd SHA256 /f "${SIGNTOOL_KEY_PFX}" /t "${SIGNTOOL_TIMESTAMP_URL}" ' + str(target[0])) + signresult = 0 + for x in range (1, 4) : + print "Attemping to sign the packages [%s]" % x + signresult = env.Execute('signtool.exe sign /fd SHA256 /f "${SIGNTOOL_KEY_PFX}" /t "${SIGNTOOL_TIMESTAMP_URL}" /d "Swift Installer" ' + str(target[0])) + if signresult != 1 : + break + #If all 3 attemps to sign the package failed, stop the build. + if signresult == 1 : + print "Error: The build has failed to sign the installer package" + Exit(1) + if signresult == 2 : + print "Signing was completed with warnings." myenv.AddPostAction(lightTask, signToolAction) diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp index b753ffa..2509b3f 100644 --- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp +++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp @@ -144,7 +144,9 @@ void QtDynamicGridLayout::removeTab(int index) { int tabIndex = -1; QtTabWidget* tabWidget = indexToTabWidget(index, tabIndex); if (tabWidget) { + QWidget* tab = tabWidget->widget(tabIndex); tabWidget->removeTab(tabIndex); + tab->setParent(nullptr); } } diff --git a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp index 8c46e38..e55ee80 100644 --- a/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp +++ b/Swift/QtUI/UserSearch/QtSuggestingJIDInput.cpp @@ -205,7 +205,7 @@ void QtSuggestingJIDInput::hidePopup() { // Give focus back to input widget because the hide() call passes the focus to the wrong widget. setFocus(); -#if defined(Q_WS_MAC) +#if defined(Q_OS_MAC) // This workaround is needed on OS X, to bring the dialog containing this widget back to the front after // the popup is hidden. Ubuntu 16.04 and Windows 8 do not have this issue. window()->raise(); diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp index 8d15739..4489bc0 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp @@ -606,6 +606,7 @@ void QtUserSearchWindow::clear() { howText = QString(tr("Who do you want to invite to the chat?")); } firstMultiJIDPage_->howLabel_->setText(howText); + firstMultiJIDPage_->groupBox->setEnabled(true); } clearForm(); resultsPage_->results_->setModel(nullptr); diff --git a/Swift/QtUI/main.cpp b/Swift/QtUI/main.cpp index 81dc670..3e20e23 100644 --- a/Swift/QtUI/main.cpp +++ b/Swift/QtUI/main.cpp @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) { qtTranslator.load(QString(SWIFT_APPLICATION_NAME).toLower() + "_" + P2QSTRING(language), P2QSTRING(Swift::pathToString(someTranslationPath.parent_path()))); } else { - qtTranslator.load(QLocale::system(), QString(SWIFT_APPLICATION_NAME).toLower(), "_", P2QSTRING(Swift::pathToString(someTranslationPath))); + qtTranslator.load(QLocale::system(), QString(SWIFT_APPLICATION_NAME).toLower(), "_", P2QSTRING(Swift::pathToString(someTranslationPath.parent_path()))); } #else //std::cout << "Loading " << std::string(QLocale::system().name().toUtf8()) << std::endl; diff --git a/Swift/SConscript b/Swift/SConscript index daff755..b211435 100644 --- a/Swift/SConscript +++ b/Swift/SConscript @@ -13,5 +13,11 @@ if env["SCONS_STAGE"] == "build" : try : SConscript("QtUI/SConscript") except Exception as e: - print "Warning: %s" % str(e) + print "Warning: %s" % str(e) env["PROJECTS"].remove("Swift") +if "Swift" in env["PROJECTS"] and env["BOOST_1_64_DETECTED"] and not env.get("allow_boost_1_64") and not env.GetOption("clean") : + #Version 1.64 has some issues with the serialization of boost::optional, see https://svn.boost.org/trac10/ticket/13050 + print "Boost 1.64 has been detected. It is not recommended to use this version due to a regression within the library. Swift has been removed from the current build. You can still use this version by setting allow_boost_1_64 to true, but recent chats and highlighting rules will reset." + env["PROJECTS"].remove("Swift") +if env["help2man"]: + SConscript("Packaging/SConscript")
\ No newline at end of file diff --git a/Swift/Translations/swift_de.ts b/Swift/Translations/swift_de.ts index a658c45..73e0ed8 100644 --- a/Swift/Translations/swift_de.ts +++ b/Swift/Translations/swift_de.ts @@ -62,7 +62,7 @@ <message> <location filename="../Controllers/Chat/ChatController.cpp" line="481"/> <source> and has been idle since %1%</source> - <translation>und ist untätig seit %1%</translation> + <translation> und ist untätig seit %1%</translation> </message> <message> <source>The day is now %1%</source> @@ -834,12 +834,12 @@ <translation>Verbannter</translation> </message> <message> - <location filename="../QtUI/CAPICertificateSelector.cpp" line="63"/> + <location filename="../QtUI/CAPICertificateSelector.cpp" line="65"/> <source>TLS Client Certificate Selection</source> <translation>TLS Clientzertifikatauswahl</translation> </message> <message> - <location filename="../QtUI/CAPICertificateSelector.cpp" line="64"/> + <location filename="../QtUI/CAPICertificateSelector.cpp" line="66"/> <source>Select a certificate to use for authentication</source> <translation>Wähle ein Zertifikat zur Authentifizierung</translation> </message> @@ -879,39 +879,47 @@ </message> </context> <context> + <name>Form</name> + <message> + <location filename="../QtUI/Form.ui" line="16"/> + <source>Form</source> + <translation>Formular</translation> + </message> +</context> +<context> <name>MAC_APPLICATION_MENU</name> <message> - <location filename="../QtUI/QtStrings.h" line="79"/> + <location filename="../QtUI/QtStrings.h" line="91"/> <source>Services</source> <translation>Dienste</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="80"/> + <location filename="../QtUI/QtStrings.h" line="92"/> <source>Hide %1</source> <translation>Verstecke %1</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="81"/> + <location filename="../QtUI/QtStrings.h" line="93"/> <source>Hide Others</source> <translation>Verstecke andere</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="82"/> + <location filename="../QtUI/QtStrings.h" line="94"/> <source>Show All</source> <translation>Zeige alle</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="83"/> + <location filename="../QtUI/QtStrings.h" line="95"/> <source>Preferences...</source> <translation>Einstellungen...</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="84"/> + <location filename="../QtUI/QtStrings.h" line="96"/> <source>Quit %1</source> <translation>Beende %1</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="85"/> + <location filename="../QtUI/QtStrings.h" line="97"/> <source>About %1</source> <translation>Über %1</translation> </message> @@ -927,32 +935,32 @@ <context> <name>QDialogButtonBox</name> <message> - <location filename="../QtUI/QtStrings.h" line="69"/> + <location filename="../QtUI/QtStrings.h" line="77"/> <source>&Yes</source> <translation>&Ja</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="70"/> + <location filename="../QtUI/QtStrings.h" line="78"/> <source>&No</source> <translation>&Nein</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="71"/> + <location filename="../QtUI/QtStrings.h" line="79"/> <source>&OK</source> <translation>&Ok</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="72"/> + <location filename="../QtUI/QtStrings.h" line="80"/> <source>OK</source> <translation>Ok</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="73"/> + <location filename="../QtUI/QtStrings.h" line="81"/> <source>&Cancel</source> <translation>&Abbrechen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="74"/> + <location filename="../QtUI/QtStrings.h" line="82"/> <source>Cancel</source> <translation>Abbrechen</translation> </message> @@ -1012,12 +1020,12 @@ <context> <name>QMessageBox</name> <message> - <location filename="../QtUI/QtStrings.h" line="76"/> + <location filename="../QtUI/QtStrings.h" line="84"/> <source>Show Details...</source> <translation>Details anzeigen...</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="77"/> + <location filename="../QtUI/QtStrings.h" line="85"/> <source>Hide Details...</source> <translation>Details verstecken...</translation> </message> @@ -1242,39 +1250,57 @@ </message> </context> <context> + <name>QPlatformTheme</name> + <message> + <location filename="../QtUI/QtStrings.h" line="87"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="88"/> + <source>Cancel</source> + <translation>Abbrechen</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="89"/> + <source>Restore Defaults</source> + <translation>Standardeinstellungen</translation> + </message> +</context> +<context> <name>QScrollBar</name> <message> - <location filename="../QtUI/QtStrings.h" line="29"/> + <location filename="../QtUI/QtStrings.h" line="37"/> <source>Scroll here</source> <translation>Hier scrollen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="30"/> + <location filename="../QtUI/QtStrings.h" line="38"/> <source>Top</source> <translation>Oben</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="31"/> + <location filename="../QtUI/QtStrings.h" line="39"/> <source>Bottom</source> <translation>Unten</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="32"/> + <location filename="../QtUI/QtStrings.h" line="40"/> <source>Page up</source> <translation>Seite hoch</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="33"/> + <location filename="../QtUI/QtStrings.h" line="41"/> <source>Page down</source> <translation>Seite runter</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="34"/> + <location filename="../QtUI/QtStrings.h" line="42"/> <source>Scroll up</source> <translation>raufscrollen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="35"/> + <location filename="../QtUI/QtStrings.h" line="43"/> <source>Scroll down</source> <translation>runterscrollen</translation> </message> @@ -1282,37 +1308,37 @@ <context> <name>QTextControl</name> <message> - <location filename="../QtUI/QtStrings.h" line="37"/> + <location filename="../QtUI/QtStrings.h" line="45"/> <source>Select All</source> <translation>Alles auswählen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="38"/> + <location filename="../QtUI/QtStrings.h" line="46"/> <source>&Copy</source> <translation>&Kopieren</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="39"/> + <location filename="../QtUI/QtStrings.h" line="47"/> <source>&Undo</source> <translation>&Rückgängig</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="40"/> + <location filename="../QtUI/QtStrings.h" line="48"/> <source>&Redo</source> <translation>&Wiederherstellen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="41"/> + <location filename="../QtUI/QtStrings.h" line="49"/> <source>Cu&t</source> <translation>&Ausschneiden</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="42"/> + <location filename="../QtUI/QtStrings.h" line="50"/> <source>&Paste</source> <translation>&Einfügen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="43"/> + <location filename="../QtUI/QtStrings.h" line="51"/> <source>Delete</source> <translation>Löschen</translation> </message> @@ -1320,115 +1346,153 @@ <context> <name>QWebPage</name> <message> - <location filename="../QtUI/QtStrings.h" line="45"/> + <location filename="../QtUI/QtStrings.h" line="53"/> <source>Copy Link</source> <translation>Verknüpfung kopieren</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="46"/> + <location filename="../QtUI/QtStrings.h" line="54"/> <source>Copy</source> <translation>Kopieren</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="47"/> + <location filename="../QtUI/QtStrings.h" line="55"/> <source>Copy Image</source> <translation>Bild kopieren</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="48"/> + <location filename="../QtUI/QtStrings.h" line="56"/> <source>Scroll here</source> <translation>Hier scrollen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="49"/> + <location filename="../QtUI/QtStrings.h" line="57"/> <source>Top</source> <translation>Oben</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="50"/> + <location filename="../QtUI/QtStrings.h" line="58"/> <source>Bottom</source> <translation>Unten</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="51"/> + <location filename="../QtUI/QtStrings.h" line="59"/> <source>Page up</source> <translation>Seite hoch</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="52"/> + <location filename="../QtUI/QtStrings.h" line="60"/> <source>Page down</source> <translation>Seite runter</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="53"/> + <location filename="../QtUI/QtStrings.h" line="61"/> <source>Scroll up</source> <translation>hochscrollen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="54"/> + <location filename="../QtUI/QtStrings.h" line="62"/> <source>Scroll down</source> <translation>runterscrollen</translation> </message> </context> <context> + <name>QWidgetTextControl</name> + <message> + <location filename="../QtUI/QtStrings.h" line="29"/> + <source>Select All</source> + <translation>Alles auswählen</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="30"/> + <source>&Undo</source> + <translation>&Rückgängig</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="31"/> + <source>&Redo</source> + <translation>&Wiederherstellen</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="32"/> + <source>Cu&t</source> + <translation>&Ausschneiden</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="33"/> + <source>&Copy</source> + <translation>&Kopieren</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="34"/> + <source>&Paste</source> + <translation>&Einfügen</translation> + </message> + <message> + <location filename="../QtUI/QtStrings.h" line="35"/> + <source>Delete</source> + <translation>Löschen</translation> + </message> +</context> +<context> <name>QWizard</name> <message> - <location filename="../QtUI/QtStrings.h" line="56"/> + <location filename="../QtUI/QtStrings.h" line="64"/> <source>< &Back</source> <translation>< &Zurück</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="57"/> + <location filename="../QtUI/QtStrings.h" line="65"/> <source>&Finish</source> <translation>&Abschließen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="58"/> + <location filename="../QtUI/QtStrings.h" line="66"/> <source>&Help</source> <translation>&Hilfe</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="59"/> + <location filename="../QtUI/QtStrings.h" line="67"/> <source>Go Back</source> <translation>Zurück</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="60"/> + <location filename="../QtUI/QtStrings.h" line="68"/> <source>Continue</source> <translation>Weiter</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="61"/> + <location filename="../QtUI/QtStrings.h" line="69"/> <source>Commit</source> <translation>Festlegen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="62"/> + <location filename="../QtUI/QtStrings.h" line="70"/> <source>Done</source> <translation>Fertig</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="63"/> + <location filename="../QtUI/QtStrings.h" line="71"/> <source>Quit</source> <translation>Beenden</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="64"/> + <location filename="../QtUI/QtStrings.h" line="72"/> <source>Help</source> <translation>Hilfe</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="65"/> + <location filename="../QtUI/QtStrings.h" line="73"/> <source>Cancel</source> <translation>Abbrechen</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="66"/> + <location filename="../QtUI/QtStrings.h" line="74"/> <source>&Next</source> <translation>&Nächstes</translation> </message> <message> - <location filename="../QtUI/QtStrings.h" line="67"/> + <location filename="../QtUI/QtStrings.h" line="75"/> <source>&Next ></source> <translation>&Nächstes ></translation> </message> @@ -1437,49 +1501,41 @@ <name>QtAffiliationEditor</name> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="14"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="122"/> <source>Edit Affiliations</source> <translation>Zugehörigkeiten bearbeiten</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="28"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="124"/> <source>Affiliation:</source> <translation>Zugehörigkeit:</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="36"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="127"/> <source>Owner</source> <translation>Besitzer</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="41"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="128"/> <source>Administrator</source> <translation>Administrator</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="46"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="129"/> <source>Member</source> <translation>Mitglied</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="51"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="130"/> <source>Outcast (Banned)</source> <translation>Verbannter</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="68"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="132"/> <source>Add User</source> <translation>Benutzer hinzufügen</translation> </message> <message> <location filename="../QtUI/QtAffiliationEditor.ui" line="75"/> - <location filename="../QtUI/ui_QtAffiliationEditor.h" line="133"/> <source>Remove User</source> <translation>Benutzer entfernen</translation> </message> @@ -1488,19 +1544,16 @@ <name>QtBlockListEditorWindow</name> <message> <location filename="../QtUI/QtBlockListEditorWindow.ui" line="14"/> - <location filename="../QtUI/ui_QtBlockListEditorWindow.h" line="103"/> <source>Edit Block List</source> <translation>Blockliste bearbeiten</translation> </message> <message> <location filename="../QtUI/QtBlockListEditorWindow.ui" line="35"/> - <location filename="../QtUI/ui_QtBlockListEditorWindow.h" line="104"/> <source><html><head/><body><p align="justify">The following list shows all contacts that you have currently blocked. You can add contacts to the list at the bottom of the list and remove contacts by clicking on the right column.</p></body></html></source> <translation><html><head/><body><p align="justify">Die folgende Liste zeigt alle Kontakte, die aktuell blockiert sind. Sie können Kontakte am unteren Ende via Mausklick hinzufügen oder Kontakte von der Liste entfernen, indem Sie in die rechte Spalte klicken.</p></body></html></translation> </message> <message> <location filename="../QtUI/QtBlockListEditorWindow.ui" line="101"/> - <location filename="../QtUI/ui_QtBlockListEditorWindow.h" line="107"/> <source>Save</source> <translation>Speichern</translation> </message> @@ -1509,37 +1562,31 @@ <name>QtBookmarkDetailWindow</name> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="20"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="138"/> <source>Edit Bookmark Details</source> <translation>Lesezeichendetails editieren</translation> </message> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="48"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="139"/> <source>Bookmark Name:</source> <translation>Lesezeichenname:</translation> </message> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="58"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="140"/> <source>Room Address:</source> <translation>Chatraumadresse:</translation> </message> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="68"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="141"/> <source>Your Nickname:</source> <translation>Dein Nickname:</translation> </message> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="78"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="142"/> <source>Room password:</source> <translation>Chatraum Passwort:</translation> </message> <message> <location filename="../QtUI/QtBookmarkDetailWindow.ui" line="101"/> - <location filename="../QtUI/ui_QtBookmarkDetailWindow.h" line="143"/> <source>Enter automatically</source> <translation>Automatisch betreten</translation> </message> @@ -1548,7 +1595,6 @@ <name>QtCertificateViewerDialog</name> <message> <location filename="../QtUI/QtCertificateViewerDialog.ui" line="14"/> - <location filename="../QtUI/ui_QtCertificateViewerDialog.h" line="98"/> <source>Certificate Viewer</source> <translation>Zertifikatsbetrachter</translation> </message> @@ -1557,79 +1603,66 @@ <name>QtConnectionSettings</name> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="14"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="394"/> <source>Connection Options</source> <translation>Verbindungsoptionen</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="22"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="395"/> <source>Connection Method:</source> <translation>Verbindungsmethode:</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="36"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="398"/> <source>Automatic</source> <translation>Automatisch</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="41"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="399"/> <source>Manual</source> <translation>Manuell</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="46"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="400"/> <source>BOSH</source> <translation>BOSH</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="99"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="402"/> <source>Secure connection:</source> <translation>Sichere Verbindung:</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="107"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="405"/> <source>Never</source> <translation>Niemals</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="112"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="406"/> <source>Encrypt when possible</source> <translation>Verschlüsselung wenn möglich</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="117"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="407"/> <source>Always encrypt</source> <translation>Immer Verschlüsseln</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="127"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="409"/> <source>Allow Compression</source> <translation>Komprimierung erlaubt</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="134"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="410"/> <source>Allow sending password over insecure connection</source> <translation>Erlaube das Versenden des Passworts über unsichere Verbindungen</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="141"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="411"/> <source>Limit encryption to TLS 1.0</source> <translation>Beschränke Verschlüsselung auf TLS 1.0</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="164"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="412"/> <source>Manually select server</source> <translation>Manuelle Serverauswahl</translation> </message> @@ -1637,9 +1670,6 @@ <location filename="../QtUI/QtConnectionSettings.ui" line="192"/> <location filename="../QtUI/QtConnectionSettings.ui" line="322"/> <location filename="../QtUI/QtConnectionSettings.ui" line="436"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="413"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="425"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="429"/> <source>Hostname:</source> <translation>Hostname:</translation> </message> @@ -1647,69 +1677,56 @@ <location filename="../QtUI/QtConnectionSettings.ui" line="215"/> <location filename="../QtUI/QtConnectionSettings.ui" line="345"/> <location filename="../QtUI/QtConnectionSettings.ui" line="459"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="414"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="426"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="430"/> <source>Port:</source> <translation>Port:</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="237"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="415"/> <source>Connection Proxy</source> <translation>Verbindungsproxy</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="245"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="416"/> <source>Proxy type:</source> <translation>Proxyart:</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="256"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="419"/> <source>None</source> <translation>Kein Proxy</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="261"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="420"/> <source>Use system-configured proxy</source> <translation>Benutze System-Proxykonfiguration</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="266"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="421"/> <source>SOCKS5</source> <translation>SOCKS5</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="271"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="422"/> <source>HTTP Connect</source> <translation>HTTP Connect</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="294"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="424"/> <source>Override system-configured proxy</source> <translation>Über System-Proxykonfiguration hinwegsetzen</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="389"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="427"/> <source>BOSH URI:</source> <translation>BOSH URI:</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="408"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="428"/> <source>Manually select HTTP proxy</source> <translation>Manuelle Auswahl des HTTP Proxy</translation> </message> <message> <location filename="../QtUI/QtConnectionSettings.ui" line="498"/> - <location filename="../QtUI/ui_QtConnectionSettings.h" line="431"/> <source>Connection options will be saved when next connecting to this account.</source> <translation>Verbindungsoptionen werden beim nächsten Verbindungsversuch zu diesem Konto gespeichert.</translation> </message> @@ -1806,19 +1823,19 @@ </message> <message> <source>No Sound</source> - <translation type="vanished">Keinen Ton</translation> + <translation type="vanished">Keinen Sound</translation> </message> <message> <source>Default Sound</source> - <translation type="vanished">Standartton</translation> + <translation type="vanished">Standardsound</translation> </message> <message> <source>Custom Sound</source> - <translation type="vanished">Benutzerdefinierter Ton</translation> + <translation type="vanished">Benutzerdefinierter Sound</translation> </message> <message> <source>...</source> - <translation type="vanished">Ton auswählen…</translation> + <translation type="vanished">Sound auswählen…</translation> </message> </context> <context> @@ -1832,147 +1849,118 @@ <name>QtHighlightNotificationConfigDialog</name> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="14"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="305"/> <source>Highlight and Notification Configuration</source> <translation>Hervorhebungs- und Benachrichtigungseinstellungen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="26"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="306"/> <source>Highlight messages from these people</source> <translation>Nachrichten von folgenden Personen hervorheben</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="87"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="312"/> <source>Nickname</source> - <translation>Spitzname</translation> + <translation>Nickname</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="92"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="258"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="311"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="320"/> <source>Text color</source> <translation>Textfarbe</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="97"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="263"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="310"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="319"/> <source>Background color</source> <translation>Hintergrundfrabe</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="102"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="268"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="309"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="318"/> <source>Play sound</source> <translation>Sound abspielen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="107"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="273"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="308"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="317"/> <source>Create notification</source> <translation>Benachrichtigung erstellen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="158"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="295"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="313"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="323"/> <source>+</source> <translation>+</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="174"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="311"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="314"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="324"/> <source>-</source> <translation>-</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="199"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="315"/> <source>Highlight messages containing these keywords</source> <translation>Nachrichten hervorheben die folgende Schlüsselwörter enthalten</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="248"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="322"/> <source>Keyword</source> <translation>Schlüsselwort</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="253"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="321"/> <source>Match case sensitive</source> <translation>Groß-/Kleinschreibung beachten</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="336"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="325"/> <source>General notification settings</source> <translation>Globale Benachrichtigungseinstellungen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="350"/> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="435"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="326"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="334"/> <source>...</source> <translation>...</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="357"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="327"/> <source>Highlight background color on own mention</source> <translation>Hintergrundfarbe hervorheben wen Sie selber erwähnt wurden</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="379"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="328"/> <source>Create notification on incoming group messages</source> <translation>Benachrichtigen wenn eine Gruppennachricht eintrifft</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="386"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="329"/> <source>Create notification when my name is mentioned</source> <translation>Benachrichtigen wenn dein Name erwähnt wurde</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="393"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="330"/> <source>Play sound on incoming direct messages</source> <translation>Bei einkommenden direkten Nachrichten Sound abspielen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="400"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="331"/> <source>Play sound on incoming group messages</source> <translation>Bei einkommenden Gruppennachrichten Sound abspielen</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="407"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="332"/> <source>Create notification on incoming direct messages</source> <translation>Benachrichtigen wenn eine direkte Nachricht eintrifft</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="414"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="333"/> <source>Play sound when my name is mentioned</source> <translation>Sound abspielen wenn dein Name erwähnt wurde</translation> </message> <message> <location filename="../QtUI/QtHighlightNotificationConfigDialog.ui" line="442"/> - <location filename="../QtUI/ui_QtHighlightNotificationConfigDialog.h" line="335"/> <source>Highlight text color on own mention</source> <translation>Textfarbe hervorheben wen Sie selber erwähnt wurden</translation> </message> @@ -1981,25 +1969,21 @@ <name>QtHistoryWindow</name> <message> <location filename="../QtUI/QtHistoryWindow.ui" line="14"/> - <location filename="../QtUI/ui_QtHistoryWindow.h" line="132"/> <source>History</source> <translation>Verlauf</translation> </message> <message> <location filename="../QtUI/QtHistoryWindow.ui" line="22"/> - <location filename="../QtUI/ui_QtHistoryWindow.h" line="133"/> <source>Search:</source> <translation>Suche:</translation> </message> <message> <location filename="../QtUI/QtHistoryWindow.ui" line="42"/> - <location filename="../QtUI/ui_QtHistoryWindow.h" line="134"/> <source>Next</source> <translation>Weiter</translation> </message> <message> <location filename="../QtUI/QtHistoryWindow.ui" line="52"/> - <location filename="../QtUI/ui_QtHistoryWindow.h" line="135"/> <source>Previous</source> <translation>Zurück</translation> </message> @@ -2009,44 +1993,36 @@ <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="20"/> <location filename="../QtUI/QtJoinMUCWindow.ui" line="113"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="143"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="151"/> <source>Enter Room</source> <translation>Chatraum betreten</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="28"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="144"/> <source>Room Address:</source> <translation>Chatraumadresse:</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="42"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="146"/> <source>Your Nickname:</source> <translation>Dein Nickname:</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="56"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="148"/> <source>Room Password:</source> <translation>Chatraum Passwort:</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="71"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="149"/> <source>Automatically configure newly created rooms</source> <translation>Automatisch Konfigurieren bei Betreten</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="35"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="145"/> <source>Search ...</source> <translation>Suchen ...</translation> </message> <message> <location filename="../QtUI/QtJoinMUCWindow.ui" line="106"/> - <location filename="../QtUI/ui_QtJoinMUCWindow.h" line="150"/> <source>Enter automatically in future</source> <translation>In Zukunft automatisch eintreten</translation> </message> @@ -2055,37 +2031,31 @@ <name>QtMUCSearchWindow</name> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="14"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="123"/> <source>Search Room</source> <translation>Chatraum suchen</translation> </message> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="33"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="124"/> <source>Service:</source> <translation>Service:</translation> </message> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="55"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="125"/> <source>Cancel</source> <translation>Abbrechen</translation> </message> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="96"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="129"/> <source>List rooms</source> <translation>Chaträume auflisten</translation> </message> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="106"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="130"/> <source>Search for</source> <translation>Suche nach</translation> </message> <message> <location filename="../QtUI/MUCSearch/QtMUCSearchWindow.ui" line="65"/> - <location filename="../QtUI/MUCSearch/ui_QtMUCSearchWindow.h" line="126"/> <source>OK</source> <translation>Ok</translation> </message> @@ -2094,21 +2064,17 @@ <name>QtProfileWindow</name> <message> <location filename="../QtUI/QtProfileWindow.ui" line="14"/> - <location filename="../QtUI/ui_QtProfileWindow.h" line="104"/> <source>Edit Profile</source> <translation>Profil editieren</translation> </message> <message> <location filename="../QtUI/QtProfileWindow.ui" line="26"/> <location filename="../QtUI/QtProfileWindow.ui" line="36"/> - <location filename="../QtUI/ui_QtProfileWindow.h" line="105"/> - <location filename="../QtUI/ui_QtProfileWindow.h" line="106"/> <source>TextLabel</source> <translation>Textbezeichnung</translation> </message> <message> <location filename="../QtUI/QtProfileWindow.ui" line="84"/> - <location filename="../QtUI/ui_QtProfileWindow.h" line="109"/> <source>Save</source> <translation>Speichern</translation> </message> @@ -2117,13 +2083,11 @@ <name>QtSpellCheckerWindow</name> <message> <location filename="../QtUI/QtSpellCheckerWindow.ui" line="14"/> - <location filename="../QtUI/ui_QtSpellCheckerWindow.h" line="100"/> <source>Dialog</source> <translation>Dialog</translation> </message> <message> <location filename="../QtUI/QtSpellCheckerWindow.ui" line="20"/> - <location filename="../QtUI/ui_QtSpellCheckerWindow.h" line="101"/> <source>Spell Checker Enabled</source> <translation>Rechtschreibprüfung aktiviert</translation> </message> @@ -2141,19 +2105,16 @@ </message> <message> <location filename="../QtUI/QtSpellCheckerWindow.ui" line="32"/> - <location filename="../QtUI/ui_QtSpellCheckerWindow.h" line="102"/> <source>Language:</source> <translation>Sprache:</translation> </message> <message> <location filename="../QtUI/QtSpellCheckerWindow.ui" line="53"/> - <location filename="../QtUI/ui_QtSpellCheckerWindow.h" line="103"/> <source>Cancel</source> <translation>Abbrechen</translation> </message> <message> <location filename="../QtUI/QtSpellCheckerWindow.ui" line="60"/> - <location filename="../QtUI/ui_QtSpellCheckerWindow.h" line="104"/> <source>Apply</source> <translation>Anwenden</translation> </message> @@ -2162,43 +2123,36 @@ <name>QtUpdateFeedSelectionDialog</name> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="14"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="96"/> <source>Select Update Channel</source> <translation>Update Kanal auswählen</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="27"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="97"/> <source>Stable Channel</source> <translation>Kanal für stabile Versionen</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="35"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="98"/> <source>Testing Channel</source> <translation>Kanal für Testversionen</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="43"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="99"/> <source>Development Channel</source> <translation>Kanal für Entwicklungsversionen</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="54"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="102"/> <source>This release channel includes our stable releases. They went throught internal QA testing and had previous RC releases to find critical bugs.</source> <translation>Dieser Freigabekanal enthält die stabilen Freigaben. Diese Freigaben sind durchliefen interne QA-Tests und hatten vorangegangen RC-Freigaben um kritische Fehler zu finden.</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="76"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="103"/> <source>This release channel includes our stable releases, beta releases and release candidates. They should be free from obvious bugs and are released for wider testing to find more obscure bugs.</source> <translation>Dieser Freigabekanal enthält die stabilen Releases, Beta Releases und Releasekandidaten. Diese Freigaben sollten frei von offensichtlichen Fehlern sein und werden freigegeben um größeren Testrahmen zu erreichen und mehr obskure Fehler zu finden.</translation> </message> <message> <location filename="../QtUI/QtUpdateFeedSelectionDialog.ui" line="89"/> - <location filename="../QtUI/ui_QtUpdateFeedSelectionDialog.h" line="104"/> <source>This release channel includes our stable releases, beta releases, release candidates and development releases. The development releases are not thoroughly tested and might contain bugs.</source> <translation>Dieser Freigabekanal enthält die stabilen Releases, Beta Releases, Releasekandidaten und Entwicklungsreleases. Die Entwicklungsreleases sind nicht wirklich getest und können Fehler enthalten.</translation> </message> @@ -2314,7 +2268,6 @@ <name>QtUserSearchWizard</name> <message> <location filename="../QtUI/UserSearch/QtUserSearchWizard.ui" line="14"/> - <location filename="../QtUI/UserSearch/ui_QtUserSearchWizard.h" line="38"/> <source>Find User</source> <translation>Benutzer finden</translation> </message> @@ -2633,57 +2586,57 @@ </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="110"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="138"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="136"/> <source>Organization</source> <translation>Organisation</translation> </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="111"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="139"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="137"/> <source>Common Name</source> <translation>Gemeiner Name</translation> </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="112"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="140"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="138"/> <source>Locality</source> <translation>Lokalität</translation> </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="113"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="141"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="139"/> <source>Organizational Unit</source> <translation>Unternehmensabteilung</translation> </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="114"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="142"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="140"/> <source>Country</source> <translation>Land</translation> </message> <message> <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="115"/> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="143"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="141"/> <source>State</source> <translation>Land</translation> </message> <message> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="125"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="123"/> <source>Alternate Subject Names</source> <translation>Alternativer Subjektname</translation> </message> <message> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="129"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="127"/> <source>E-mail Address</source> <translation>E-Mail Adresse</translation> </message> <message> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="131"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="129"/> <source>DNS Name</source> <translation>DNS Name</translation> </message> <message> - <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="137"/> + <location filename="../QtUI/QtCertificateViewerDialog.cpp" line="135"/> <source>Issuer</source> <translation>Herausgeber</translation> </message> @@ -2733,9 +2686,8 @@ <translation>&Anordnung ändern</translation> </message> <message> - <location filename="../QtUI/QtChatTabs.cpp" line="116"/> <source>Ctrl+Alt+L</source> - <translation>Ctrl+Alt+L</translation> + <translation type="vanished">Ctrl+Alt+L</translation> </message> <message> <location filename="../QtUI/QtChatTabs.cpp" line="120"/> @@ -3602,7 +3554,7 @@ <location filename="../QtUI/QtSoundSelectionStyledItemDelegate.cpp" line="44"/> <location filename="../QtUI/QtSoundSelectionStyledItemDelegate.cpp" line="69"/> <source>Default sound</source> - <translation>Default Sound</translation> + <translation>Standardsound</translation> </message> </context> <context> @@ -3679,12 +3631,12 @@ <context> <name>Swift::QtSwift</name> <message> - <location filename="../QtUI/QtSwift.cpp" line="363"/> + <location filename="../QtUI/QtSwift.cpp" line="374"/> <source>Swift Update Available</source> <translation>Swift Update verfügbar</translation> </message> <message> - <location filename="../QtUI/QtSwift.cpp" line="363"/> + <location filename="../QtUI/QtSwift.cpp" line="374"/> <source>Restart Swift to update to the new Swift version.</source> <translation>Swift muss neugestartet werden damit das Update installiert werden kann.</translation> </message> @@ -3692,25 +3644,28 @@ <context> <name>Swift::QtTabWidget</name> <message> - <location filename="../QtUI/QtTabWidget.cpp" line="60"/> <source>This empty cell is a placeholder for chat windows. You can move existing chats to this cell by dragging the tab over here. You can change the number of cells via the 'Change layout' dialog under the 'View' menu or by using the %1 shortcut.</source> - <translation>Diese leere Zelle ist ein Platzhalter für Chatfenster. Sie können bestehende Chatfenster zu dieser Zelle bewegen indem Sie das Tab hierher ziehen. Sie können die Anzahl von Zellen anhand des "Anordnung ändern" Dialogs im Menü "Ansicht" ändern oder indem Sie die Tastenkombination %1 nutzen.</translation> + <translation type="vanished">Diese leere Zelle ist ein Platzhalter für Chatfenster. Sie können bestehende Chatfenster zu dieser Zelle bewegen indem Sie das Tab hierher ziehen. Sie können die Anzahl von Zellen anhand des "Anordnung ändern" Dialogs im Menü "Ansicht" ändern oder indem Sie die Tastenkombination %1 nutzen.</translation> </message> <message> - <location filename="../QtUI/QtTabWidget.cpp" line="60"/> <source>Ctrl+Alt+L</source> - <translation>Ctrl+Alt+L</translation> + <translation type="vanished">Ctrl+Alt+L</translation> + </message> + <message> + <location filename="../QtUI/QtTabWidget.cpp" line="60"/> + <source>This empty cell is a placeholder for chat windows. You can move existing chats to this cell by dragging the tab over here. You can change the number of cells via the 'Change layout' dialog under the 'View' menu.</source> + <translation>Diese leere Zelle ist ein Platzhalter für Chatfenster. Sie können bestehende Chatfenster zu dieser Zelle bewegen indem Sie das Tab hierher ziehen. Sie können die Anzahl von Zellen anhand des "Anordnung ändern" Dialogs im Menü "Ansicht" ändern.</translation> </message> </context> <context> <name>Swift::QtTextEdit</name> <message> - <location filename="../QtUI/QtTextEdit.cpp" line="164"/> + <location filename="../QtUI/QtTextEdit.cpp" line="166"/> <source>Spell Checker Options</source> <translation>Rechtschreibprüfungsoptionen</translation> </message> <message> - <location filename="../QtUI/QtTextEdit.cpp" line="209"/> + <location filename="../QtUI/QtTextEdit.cpp" line="211"/> <source>No Suggestions</source> <translation>Keine Korrekturempfehlungen</translation> </message> diff --git a/Swift/Translations/swift_nl.ts b/Swift/Translations/swift_nl.ts index 2686e5e..7b37e72 100644 --- a/Swift/Translations/swift_nl.ts +++ b/Swift/Translations/swift_nl.ts @@ -32,10 +32,6 @@ <translation>%1% is nu bezet</translation> </message> <message> - <source>The day is now %1%</source> - <translation>De huidige dag is nu %1%</translation> - </message> - <message> <source>Error sending message</source> <translation>Fout tijdens het versturen van bericht</translation> </message> @@ -540,10 +536,6 @@ <translation>%1% heeft de %2% betreden.</translation> </message> <message> - <source>%1%</source> - <translation>%1%</translation> - </message> - <message> <source>You've blocked this room. To enter the room, first unblock it using the cog menu and try again</source> <translation>U heeft deze kamer geblokkeerd. Om de kamer te betreden moet u deze eerst deblokkeren met behulp van het tandradmenu, en het dan opnieuw proberen</translation> </message> @@ -608,10 +600,6 @@ <translation>Deze server ondersteunt het delen van echte identiteiten in deze conversatie niet.</translation> </message> <message> - <source>Empty Chat</source> - <translation>Lege conversatie</translation> - </message> - <message> <source>This contact is already on your contact list.</source> <translation>Dit contact staat al op uw contactenlijst.</translation> </message> @@ -655,6 +643,38 @@ <source>Outcast</source> <translation>Verstoteling</translation> </message> + <message> + <source>This user could not be found in the room.</source> + <translation>De gebruiker kan niet worden gevonden in deze kamer.</translation> + </message> + <message> + <source>The room subject has been removed</source> + <translation>Het onderwerp van deze kamer is verwijderd</translation> + </message> + <message> + <source>%1% says</source> + <translation>%1% zegt</translation> + </message> + <message> + <source>%1% in %2% says</source> + <translation>%1% in %2% zegt</translation> + </message> + <message> + <source>%1% mentioned you in %2%</source> + <translation>%1% heeft u genoemd in %2%</translation> + </message> + <message> + <source>%1% mentioned '%2%'</source> + <translation>%1% heeft '%2%' genoemd</translation> + </message> + <message> + <source>There was an error fetching your current profile data</source> + <translation>Er is een fout opgetreden bij het ophalen van uw profielgegevens</translation> + </message> + <message> + <source>Failed to retrieve recent profile for user.</source> + <translation>Ophalen van recente profielgegevens is mislukt.</translation> + </message> </context> <context> <name>CloseButton</name> @@ -695,12 +715,7 @@ </message> </context> <context> - <name>QGuiApplication</name> - <message> - <source>QT_LAYOUT_DIRECTION</source> - <comment>Translate this to LTR for left-to-right or RTL for right-to-left languages</comment> - <translation>LTR</translation> - </message> + <name>QApplication</name> <message> <source>QT_LAYOUT_DIRECTION</source> <translation>LTR</translation> @@ -734,6 +749,18 @@ </message> </context> <context> + <name>QGuiApplication</name> + <message> + <source>QT_LAYOUT_DIRECTION</source> + <comment>Translate this to LTR for left-to-right or RTL for right-to-left languages</comment> + <translation>LTR</translation> + </message> + <message> + <source>QT_LAYOUT_DIRECTION</source> + <translation>LTR</translation> + </message> +</context> +<context> <name>QLineEdit</name> <message> <source>Select All</source> @@ -951,6 +978,21 @@ </message> </context> <context> + <name>QPlatformTheme</name> + <message> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <source>Cancel</source> + <translation>Annuleren</translation> + </message> + <message> + <source>Restore Defaults</source> + <translation>Standaardintellingen</translation> + </message> +</context> +<context> <name>QScrollBar</name> <message> <source>Scroll here</source> @@ -1056,6 +1098,37 @@ </message> </context> <context> + <name>QWidgetTextControl</name> + <message> + <source>Select All</source> + <translation>Alles selecteren</translation> + </message> + <message> + <source>&Undo</source> + <translation>&Herstel</translation> + </message> + <message> + <source>&Redo</source> + <translation>&Opnieuw</translation> + </message> + <message> + <source>Cu&t</source> + <translation>&Knip</translation> + </message> + <message> + <source>&Copy</source> + <translation>&Kopieer</translation> + </message> + <message> + <source>&Paste</source> + <translation>&Plak</translation> + </message> + <message> + <source>Delete</source> + <translation>Verwijder</translation> + </message> +</context> +<context> <name>QWizard</name> <message> <source>< &Back</source> @@ -1202,7 +1275,7 @@ </message> <message> <source>Manual</source> - <translation>Manueel</translation> + <translation>Handmatig</translation> </message> <message> <source>BOSH</source> @@ -1234,7 +1307,7 @@ </message> <message> <source>Manually select server</source> - <translation>Manuele serverselectie</translation> + <translation>Handmatige serverselectie</translation> </message> <message> <source>Hostname:</source> @@ -1278,7 +1351,7 @@ </message> <message> <source>Manually select HTTP proxy</source> - <translation>Selecteer HTTP proxy manueel</translation> + <translation>Selecteer HTTP proxy handmatig</translation> </message> <message> <source>Connection Options</source> @@ -1401,34 +1474,94 @@ </message> </context> <context> - <name>QtHighlightEditorWidget</name> + <name>QtHighlightNotificationConfigDialog</name> <message> - <source>Form</source> - <translation>Formulier</translation> + <source>Highlight and Notification Configuration</source> + <translation>Markeer- en meldingsinstellingen</translation> </message> <message> - <source>Incoming messages are checked against the following rules. First rule that matches will be executed.</source> - <translation>Inkomende berichten worden gecontrolleerd aan de hand van de volgende regels. De eerst overeenkomende regel wordt uitgevoerd.</translation> + <source>Highlight messages from these people</source> + <translation>Markeer berichten van deze mensen</translation> </message> <message> - <source>New</source> - <translation>Nieuw</translation> + <source>Nickname</source> + <translation>Roepnaam</translation> </message> <message> - <source>Delete</source> - <translation>Verwijder</translation> + <source>Text color</source> + <translation>Tekstkleur</translation> </message> <message> - <source>Move up</source> - <translation>Verplaats omhoog</translation> + <source>Background color</source> + <translation>Achtergrondkleur</translation> </message> <message> - <source>Move down</source> - <translation>Verplaats omlaag</translation> + <source>Play sound</source> + <translation>Speel geluid</translation> </message> <message> - <source>Close</source> - <translation>Sluit tab</translation> + <source>Create notification</source> + <translation>Melding</translation> + </message> + <message> + <source>+</source> + <translation>+</translation> + </message> + <message> + <source>-</source> + <translation>-</translation> + </message> + <message> + <source>Highlight messages containing these keywords</source> + <translation>Markeer berichten die deze sleutelwoorden bevatten</translation> + </message> + <message> + <source>Keyword</source> + <translation>Sleutelwoord</translation> + </message> + <message> + <source>Match case sensitive</source> + <translation>Identieke hoofdletters/kleine letters</translation> + </message> + <message> + <source>General notification settings</source> + <translation>Algemene meldingsinstellingen</translation> + </message> + <message> + <source>...</source> + <translation>...</translation> + </message> + <message> + <source>Highlight background color on own mention</source> + <translation>Achtergrondkleur van vermeldingen van mijn naam</translation> + </message> + <message> + <source>Create notification on incoming group messages</source> + <translation>Melding bij binnenkomende berichten uit een kamer</translation> + </message> + <message> + <source>Create notification when my name is mentioned</source> + <translation>Melding wanneer mijn naam genoemd wordt</translation> + </message> + <message> + <source>Play sound on incoming direct messages</source> + <translation>Speel geluid bij binnenkomende directe berichten</translation> + </message> + <message> + <source>Play sound on incoming group messages</source> + <translation>Speel geluid bij binnenkomende groepsgesprekken</translation> + </message> + <message> + <source>Create notification on incoming direct messages</source> + <translation>Melding bij binnenkomende directe berichten</translation> + </message> + <message> + <source>Play sound when my name is mentioned</source> + <translation>Speel geluid wanneer mijn naam genoemd wordt</translation> + </message> + <message> + <source>Highlight text color on own mention</source> + <translation>Tekstkleur van vermeldingen van mijn naam</translation> </message> </context> <context> @@ -1503,6 +1636,10 @@ <source>OK</source> <translation>OK</translation> </message> + <message> + <source>Search for</source> + <translation>Zoek naar</translation> + </message> </context> <context> <name>QtProfileWindow</name> @@ -1530,18 +1667,6 @@ <translation>Spellingscontrole ingeschakeld</translation> </message> <message> - <source>Dictionary Path:</source> - <translation>Pad woordenboek:</translation> - </message> - <message> - <source>Change</source> - <translation>Wijzig</translation> - </message> - <message> - <source>Current Language:</source> - <translation>Huidige taal:</translation> - </message> - <message> <source>Language:</source> <translation>Taal:</translation> </message> @@ -1555,6 +1680,37 @@ </message> </context> <context> + <name>QtUpdateFeedSelectionDialog</name> + <message> + <source>Select Update Channel</source> + <translation>Kies updatekanaal</translation> + </message> + <message> + <source>Stable Channel</source> + <translation>Stabiel kanaal</translation> + </message> + <message> + <source>Testing Channel</source> + <translation>Testkanaal</translation> + </message> + <message> + <source>Development Channel</source> + <translation>Ontwikkelkanaal</translation> + </message> + <message> + <source>This release channel includes our stable releases. They went throught internal QA testing and had previous RC releases to find critical bugs.</source> + <translation>Dit kanaal bevat onze stabiele versies. Deze hebben uitgebreide interne kwaliteitscontrole gehad, en hebben testversies gehad om kritische fouten te vinden.</translation> + </message> + <message> + <source>This release channel includes our stable releases, beta releases and release candidates. They should be free from obvious bugs and are released for wider testing to find more obscure bugs.</source> + <translation>Dit kanaal bevat onze stabiele versies, betaversies en release candidates. Deze versies zouden vrij moeten zijn van opvallende fouten en worden verspreidt om minder opvallende fouten te vinden.</translation> + </message> + <message> + <source>This release channel includes our stable releases, beta releases, release candidates and development releases. The development releases are not thoroughly tested and might contain bugs.</source> + <translation>Dit kanaal bevat onze stabiele versies, betaversies, release candidates en ontwikkelversies. De ontwikkelversies zijn niet uitvoerig getest en kunnen fouten bevatten.</translation> + </message> +</context> +<context> <name>QtUserSearchFieldsPage</name> <message> <source>Nickname:</source> @@ -1738,6 +1894,46 @@ <source>Close</source> <translation>Sluiten</translation> </message> + <message> + <source>View Changes</source> + <translation>Belijk Wijzigingen</translation> + </message> + <message> + <source>You are receiving updates from the Stable update channel.</source> + <translation>U ontvangt updates vanuit het stabiele updatekanaal.</translation> + </message> + <message> + <source>You are receiving updates from the Development update channel.</source> + <translation>U ontvangt updates vanuit het ontwikkelupdatekanaal.</translation> + </message> + <message> + <source>You are receiving updates from the Testing update channel.</source> + <translation>U ontvangt updates vanuit het testupdatekanaal.</translation> + </message> + <message> + <source>Change the update channel.</source> + <translation>Wijzig het updatekanaal.</translation> + </message> + <message> + <source>Checking for updates…</source> + <translation>Controlleren op updates…</translation> + </message> + <message> + <source>Error checking for updates!</source> + <translation>Fout tijdens het controlleren op updates!</translation> + </message> + <message> + <source>Swift is up to date.</source> + <translation>Swift is up-to-date.</translation> + </message> + <message> + <source>Downloading update…</source> + <translation>Update aan het downloaden…</translation> + </message> + <message> + <source>Update will be installed when you next restart Swift.</source> + <translation>De update wordt geinstalleerd wanneer u Swift herstart.</translation> + </message> </context> <context> <name>Swift::QtAdHocCommandWindow</name> @@ -1941,10 +2137,6 @@ afbeelding</translation> <translation>Wijzig &opmaak</translation> </message> <message> - <source>Ctrl+Alt+L</source> - <translation>Ctrl+Alt+L</translation> - </message> - <message> <source>Move Tab right</source> <translation>Verplaats tab naar rechts</translation> </message> @@ -2063,6 +2255,10 @@ afbeelding</translation> <source>Edit bookmark...</source> <translation>Bewerk bladwijzer...</translation> </message> + <message> + <source>The day is now %1</source> + <translation>De huidige dag is nu %1</translation> + </message> </context> <context> <name>Swift::QtConnectionSettingsWindow</name> @@ -2118,6 +2314,13 @@ afbeelding</translation> </message> </context> <context> + <name>Swift::QtEmojisSelector</name> + <message> + <source>Recent</source> + <translation>Recent</translation> + </message> +</context> +<context> <name>Swift::QtEventWindow</name> <message> <source>Display Notice</source> @@ -2136,108 +2339,10 @@ afbeelding</translation> </message> </context> <context> - <name>Swift::QtHighlightEditor</name> - <message> - <source>Highlight Rules</source> - <translation>Markeerregels</translation> - </message> - <message> - <source>Apply to all chat messages</source> - <translation>Pas toe op alle berichten in conversaties</translation> - </message> - <message> - <source>Apply to all room messages</source> - <translation>Pas toe op alle berichten in kamers</translation> - </message> - <message> - <source>Select sound file...</source> - <translation>Selecteer geluidsbestand...</translation> - </message> -</context> -<context> - <name>Swift::QtHighlightEditorWidget</name> - <message> - <source>Highlight Rules</source> - <translation>Markeerregels</translation> - </message> -</context> -<context> - <name>Swift::QtHighlightRulesItemModel</name> - <message> - <source>Apply to</source> - <translation>Pas toe op</translation> - </message> + <name>Swift::QtGridSelectionDialog</name> <message> - <source>Sender</source> - <translation>Afzender</translation> - </message> - <message> - <source>Keyword</source> - <translation>Sleutelwoord</translation> - </message> - <message> - <source>Action</source> - <translation>Actie</translation> - </message> - <message> - <source>Nick Is Keyword</source> - <translation>Roepnaam is sleutelwoord</translation> - </message> - <message> - <source>Match Case</source> - <translation>Identieke hoofdletters/kleine letters</translation> - </message> - <message> - <source>Match Whole Words</source> - <translation>Heel woord</translation> - </message> - <message> - <source>Highlight Text</source> - <translation>Markeer tekst</translation> - </message> - <message> - <source>Text Color</source> - <translation>Voorgrondkleur</translation> - </message> - <message> - <source>Text Background</source> - <translation>Achtergrondkleur</translation> - </message> - <message> - <source>Play Sounds</source> - <translation>Speel geluid</translation> - </message> - <message> - <source>Sound File</source> - <translation>Geluidsbestand</translation> - </message> - <message> - <source><nick></source> - <translation><roepnaam></translation> - </message> - <message> - <source>Highlight text</source> - <translation>Markeer tekst</translation> - </message> - <message> - <source>Play sound</source> - <translation>Speel geluid</translation> - </message> - <message> - <source>None</source> - <translation>Geen</translation> - </message> - <message> - <source>Chat or MUC</source> - <translation>Conversatie of kamer</translation> - </message> - <message> - <source>Chat</source> - <translation>Conversatie</translation> - </message> - <message> - <source>MUC</source> - <translation>Kamer</translation> + <source>Select the number of rows and columns for your layout. You can change the size by moving the mouse or cursor keys.</source> + <translation>Kies het aantal rijen en kolommen voor uw opmaak. U kunt de grootte wijzigen met de muis of met de pijltjestoetsen.</translation> </message> </context> <context> @@ -2572,35 +2677,35 @@ afbeelding</translation> <name>Swift::QtPlainChatView</name> <message> <source>Chat Messages</source> - <translation type="unfinished"></translation> + <translation>Berichten</translation> </message> <message> <source>At %1 %2 said:</source> - <translation type="unfinished"></translation> + <translation>Om %1 zei %2:</translation> </message> <message> <source>At %1 <i>%2 </source> - <translation type="unfinished"></translation> + <translation>Om %1 <i>%2</translation> </message> <message> <source>At %1 %2 corrected the last message to:</source> - <translation type="unfinished"></translation> + <translation>Om %1 corrigeerde %2 het laatste bericht naar:</translation> </message> <message> <source>At %1 %2 corrected the last action to: <i></source> - <translation type="unfinished"></translation> + <translation>Om %1 corrigeerde %2 de laatste actie naar: <i></translation> </message> <message> <source>File transfer description</source> - <translation type="unfinished">Beschrijving bestand</translation> + <translation>Beschrijving bestand</translation> </message> <message> <source>Description:</source> - <translation type="unfinished">Beschrijving:</translation> + <translation>Beschrijving:</translation> </message> <message> <source>Save File</source> - <translation type="unfinished">Bestand opslaan</translation> + <translation>Bestand opslaan</translation> </message> </context> <context> @@ -2695,18 +2800,14 @@ afbeelding</translation> </message> </context> <context> - <name>Swift::QtSpellCheckerWindow</name> - <message> - <source>Dictionary Path</source> - <translation>Pad woordenboek</translation> - </message> + <name>Swift::QtSoundSelectionStyledItemDelegate</name> <message> - <source>Select Personal Dictionary</source> - <translation>Kies persoonlijk woordenboek</translation> + <source>No sound</source> + <translation>Geen geluid</translation> </message> <message> - <source>(*.dic</source> - <translation>(*.dic</translation> + <source>Default sound</source> + <translation>Standaardgeluid</translation> </message> </context> <context> @@ -2756,6 +2857,24 @@ afbeelding</translation> </message> </context> <context> + <name>Swift::QtSwift</name> + <message> + <source>Swift Update Available</source> + <translation>Swift-update beschikbaar</translation> + </message> + <message> + <source>Restart Swift to update to the new Swift version.</source> + <translation>Herstart Swift om bij te werken naar de nieuwe versie.</translation> + </message> +</context> +<context> + <name>Swift::QtTabWidget</name> + <message> + <source>This empty cell is a placeholder for chat windows. You can move existing chats to this cell by dragging the tab over here. You can change the number of cells via the 'Change layout' dialog under the 'View' menu.</source> + <translation>Dit lege vak is vulling voor berichtenschermen. U kunt bestaande gesprekken naar dit vak verplaatsen door het tabje hier heen te slepen. U kunt het aantal vakken veranderen door middel van het 'Wijzig opmaak'-scherm in het 'Beeld'-menu.</translation> + </message> +</context> +<context> <name>Swift::QtTextEdit</name> <message> <source>Spell Checker Options</source> @@ -3028,7 +3147,7 @@ afbeelding</translation> </message> <message> <source>0118 999 881 999 119 7253</source> - <translation></translation> + <translation>0118 999 881 999 119 7253</translation> </message> </context> <context> @@ -3253,7 +3372,7 @@ afbeelding</translation> <message> <source>TRANSLATION_LICENSE</source> <comment>This string contains the license under which this translation is licensed. We ask you to license the translation under the BSD license. Please read http://www.opensource.org/licenses/bsd-license.php, and if you agree to release your translation under this license, use the following (untranslated) text: 'This translation is licensed under the BSD License. See http://www.opensource.org/licenses/bsd-license.php'</comment> - <translation>This translation is licensed under the GNU General Public License v3. See Documentation/Licenses/GPLv3.txt for more information</translation> + <translation>This translation is licensed under the BSD License. See http://www.opensource.org/licenses/bsd-license.php</translation> </message> </context> </TS> |