Added tags to the MessageComposer.

Added context menu to contact list in MessageComposer.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4213 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2011-05-21 16:26:00 +00:00
parent 4c13280fed
commit f14b529009
13 changed files with 807 additions and 423 deletions

View File

@ -124,7 +124,55 @@ int p3MsgService::status()
return 1;
}
int p3MsgService::incomingMsgs()
void p3MsgService::processMsg(RsMsgItem *mi)
{
mi -> recvTime = time(NULL);
mi -> msgId = getNewUniqueMsgId();
std::string mesg;
RsStackMutex stack(mMsgMtx); /*** STACK LOCKED MTX ***/
if (mi -> PeerId() == mConnMgr->getOwnId())
{
/* from the loopback device */
mi -> msgFlags |= RS_MSG_FLAGS_OUTGOING;
}
else
{
mi -> msgFlags = RS_MSG_FLAGS_NEW;
/* from a peer */
MsgInfoSummary mis;
initRsMIS(mi, mis);
// msgNotifications.push_back(mis);
pqiNotify *notify = getPqiNotify();
if (notify)
{
std::string message , title;
notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId(),
title.assign(mi->subject.begin(), mi->subject.end()),
message.assign(mi->message.begin(),mi->message.end()));
std::ostringstream out;
out << mi->msgId;
notify->AddFeedItem(RS_FEED_ITEM_MESSAGE, out.str(), "", "");
}
}
imsg[mi->msgId] = mi;
RsMsgSrcId* msi = new RsMsgSrcId();
msi->msgId = mi->msgId;
msi->srcId = mi->PeerId();
mSrcIds.insert(std::pair<uint32_t, RsMsgSrcId*>(msi->msgId, msi));
msgChanged.IndicateChanged();
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
/**** STACK UNLOCKED ***/
}
int p3MsgService::incomingMsgs()
{
RsMsgItem *mi;
int i = 0;
@ -134,50 +182,8 @@ int p3MsgService::incomingMsgs()
{
changed = true ;
++i;
mi -> recvTime = time(NULL);
mi -> msgId = getNewUniqueMsgId();
std::string mesg;
RsStackMutex stack(mMsgMtx); /*** STACK LOCKED MTX ***/
if (mi -> PeerId() == mConnMgr->getOwnId())
{
/* from the loopback device */
mi -> msgFlags |= RS_MSG_FLAGS_OUTGOING;
}
else
{
mi -> msgFlags = RS_MSG_FLAGS_NEW;
/* from a peer */
MsgInfoSummary mis;
initRsMIS(mi, mis);
// msgNotifications.push_back(mis);
pqiNotify *notify = getPqiNotify();
if (notify)
{
std::string message , title;
notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId(),
title.assign(mi->subject.begin(), mi->subject.end()),
message.assign(mi->message.begin(),mi->message.end()));
std::ostringstream out;
out << mi->msgId;
notify->AddFeedItem(RS_FEED_ITEM_MESSAGE, out.str(), "", "");
}
}
imsg[mi->msgId] = mi;
RsMsgSrcId* msi = new RsMsgSrcId();
msi->msgId = mi->msgId;
msi->srcId = mi->PeerId();
mSrcIds.insert(std::pair<uint32_t, RsMsgSrcId*>(msi->msgId, msi));
msgChanged.IndicateChanged();
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
/**** STACK UNLOCKED ***/
processMsg(mi);
}
if(changed)
rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD);
@ -307,8 +313,8 @@ bool p3MsgService::saveList(bool& cleanup, std::list<RsItem*>& itemList)
for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++)
itemList.push_back(mit->second) ;
for(mit2 = mTags.begin(); mit2 != mTags.end(); mit2++)
itemList.push_back(mit2->second);
for(mit2 = mTags.begin(); mit2 != mTags.end(); mit2++)
itemList.push_back(mit2->second);
for(mit3 = mMsgTags.begin(); mit3 != mMsgTags.end(); mit3++)
itemList.push_back(mit3->second);
@ -886,7 +892,14 @@ bool p3MsgService::MessageSend(MessageInfo &info)
RsMsgItem *msg = initMIRsMsg(info, mConnMgr->getOwnId());
if (msg)
{
sendMessage(msg);
/* use processMsg to get the new msgId */
// sendMessage(msg);
processMsg(msg);
// return new message id
std::ostringstream out;
out << msg->msgId;
info.msgId = out.str();
}
return true;

View File

@ -105,6 +105,7 @@ int checkOutgoingMessages();
uint32_t getNewUniqueMsgId();
int sendMessage(RsMsgItem *item);
int incomingMsgs();
void processMsg(RsMsgItem *mi);
void initRsMI(RsMsgItem *msg, MessageInfo &mi);
void initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis);
@ -136,7 +137,7 @@ void initStandardTagTypes();
uint32_t mMsgUniqueId;
// used delete msgSrcIds after config save
std::map<uint32_t, RsMsgSrcId*> mSrcIds;
std::map<uint32_t, RsMsgSrcId*> mSrcIds;
// save the parent of the messages in draft for replied and forwarded
std::map<uint32_t, RsMsgParentId*> mParentId;

View File

@ -269,6 +269,7 @@ HEADERS += rshare.h \
gui/channels/ShareKey.h \
gui/connect/ConfCertDialog.h \
gui/msgs/MessageComposer.h \
gui/msgs/TagsMenu.h \
gui/msgs/textformat.h \
gui/images/retroshare_win.rc.h \
gui/settings/rsharesettings.h \
@ -499,6 +500,7 @@ SOURCES += main.cpp \
gui/chat/ChatStyle.cpp \
gui/connect/ConfCertDialog.cpp \
gui/msgs/MessageComposer.cpp \
gui/msgs/TagsMenu.cpp \
gui/common/vmessagebox.cpp \
gui/common/rwindow.cpp \
gui/common/html.cpp \

View File

@ -20,8 +20,6 @@
****************************************************************/
#include <QMessageBox>
#include <QPainter>
#include <QPaintEvent>
#include <QStandardItemModel>
#include <QShortcut>
#include <QTimer>
@ -30,9 +28,12 @@
#include <QPrintDialog>
#include <QTextStream>
#include <QTextCodec>
#include <QKeyEvent>
#include <QFileDialog>
#include "MessagesDialog.h"
#include "msgs/MessageComposer.h"
#include "msgs/TagsMenu.h"
#include "util/printpreview.h"
#include "settings/rsharesettings.h"
#include "util/misc.h"
@ -45,6 +46,7 @@
#include <retroshare/rsinit.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rsmsgs.h>
#include <algorithm>
@ -85,61 +87,6 @@
#define ROW_SENTBOX 3
#define ROW_TRASHBOX 4
#define ACTION_TAGSINDEX_SIZE 3
#define ACTION_TAGSINDEX_TYPE "Type"
#define ACTION_TAGSINDEX_ID "ID"
#define ACTION_TAGSINDEX_COLOR "Color"
#define ACTION_TAGS_REMOVEALL 0
#define ACTION_TAGS_TAG 1
#define ACTION_TAGS_NEWTAG 2
class MessagesMenu : public QMenu
{
public:
MessagesMenu(const QString &title, QWidget *parent) : QMenu (title, parent)
{
}
protected:
virtual void paintEvent(QPaintEvent *e)
{
QMenu::paintEvent(e);
QPainter p(this);
QRegion emptyArea = QRegion(rect());
//draw the items with color
foreach (QAction *pAction, actions()) {
QRect adjustedActionRect = actionGeometry(pAction);
if (!e->rect().intersects(adjustedActionRect))
continue;
const QMap<QString, QVariant> &Values = pAction->data().toMap();
if (Values.size () != ACTION_TAGSINDEX_SIZE) {
continue;
}
if (Values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) {
continue;
}
//set the clip region to be extra safe (and adjust for the scrollers)
QRegion adjustedActionReg(adjustedActionRect);
emptyArea -= adjustedActionReg;
p.setClipRegion(adjustedActionReg);
QStyleOptionMenuItem opt;
initStyleOption(&opt, pAction);
opt.palette.setColor(QPalette::ButtonText, QColor(Values [ACTION_TAGSINDEX_COLOR].toInt()));
// needed for Cleanlooks
opt.palette.setColor(QPalette::Text, QColor(Values [ACTION_TAGSINDEX_COLOR].toInt()));
opt.rect = adjustedActionRect;
style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
}
}
};
MessagesDialog::LockUpdate::LockUpdate (MessagesDialog *pDialog, bool bUpdate)
{
@ -366,6 +313,14 @@ MessagesDialog::MessagesDialog(QWidget *parent)
ui.listWidget->setCurrentRow(ROW_INBOX);
// create tag menu
TagsMenu *menu = new TagsMenu (tr("Tags"), this);
connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow()));
connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool)));
connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll()));
ui.tagButton->setMenu(menu);
// fill tags
fillTags();
// create timer for navigation
@ -464,95 +419,46 @@ bool MessagesDialog::eventFilter(QObject *obj, QEvent *event)
void MessagesDialog::fillTags()
{
MsgTagType Tags;
rsMsgs->getMessageTagTypes(Tags);
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator Tag;
MsgTagType tags;
rsMsgs->getMessageTagTypes(tags);
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator tag;
// create tag menu
QMenu *pMenu = new MessagesMenu (tr("Tags"), this);
connect(pMenu, SIGNAL(triggered (QAction*)), this, SLOT(tagTriggered(QAction*)));
connect(pMenu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow()));
// fill tags
m_bInChange = true;
bool bUser = false;
// save current selection
QListWidgetItem *item = ui.tagWidget->currentItem();
uint32_t nSelectecTagId = 0;
if (item) {
nSelectecTagId = item->data(Qt::UserRole).toInt();
}
QString text;
QAction *pAction;
QMap<QString, QVariant> Values;
QListWidgetItem *itemToSelect = NULL;
if (Tags.types.size()) {
pAction = new QAction(tr("Remove All Tags"), pMenu);
Values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_REMOVEALL;
Values [ACTION_TAGSINDEX_ID] = 0;
Values [ACTION_TAGSINDEX_COLOR] = 0;
pAction->setData (Values);
pMenu->addAction(pAction);
QString text;
pMenu->addSeparator();
ui.tagWidget->clear();
for (tag = tags.types.begin(); tag != tags.types.end(); tag++) {
text = TagDefs::name(tag->first, tag->second.first);
for (Tag = Tags.types.begin(); Tag != Tags.types.end(); Tag++) {
text = TagDefs::name(Tag->first, Tag->second.first);
item = new QListWidgetItem (text, ui.tagWidget);
item->setForeground(QBrush(QColor(tag->second.second)));
item->setIcon(QIcon(":/images/foldermail.png"));
item->setData(Qt::UserRole, tag->first);
item->setData(Qt::UserRole + 1, text); // for updateMessageSummaryList
pAction = new QAction(text, pMenu);
Values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_TAG;
Values [ACTION_TAGSINDEX_ID] = Tag->first;
Values [ACTION_TAGSINDEX_COLOR] = QRgb(Tag->second.second);
pAction->setData (Values);
pAction->setCheckable(true);
if (tag->first == nSelectecTagId) {
itemToSelect = item;
}
}
if (Tag->first >= RS_MSGTAGTYPE_USER && bUser == false) {
bUser = true;
pMenu->addSeparator();
}
if (itemToSelect) {
ui.tagWidget->setCurrentItem(itemToSelect);
}
pMenu->addAction(pAction);
}
m_bInChange = false;
pMenu->addSeparator();
}
pAction = new QAction(tr("New tag ..."), pMenu);
Values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_NEWTAG;
Values [ACTION_TAGSINDEX_ID] = 0;
Values [ACTION_TAGSINDEX_COLOR] = 0;
pAction->setData (Values);
pMenu->addAction(pAction);
ui.tagButton->setMenu(pMenu);
// fill tags
m_bInChange = true;
// save current selection
QListWidgetItem *pItem = ui.tagWidget->currentItem();
uint32_t nSelectecTagId = 0;
if (pItem) {
nSelectecTagId = pItem->data(Qt::UserRole).toInt();
}
QListWidgetItem *pItemToSelect = NULL;
ui.tagWidget->clear();
for (Tag = Tags.types.begin(); Tag != Tags.types.end(); Tag++) {
text = TagDefs::name(Tag->first, Tag->second.first);
pItem = new QListWidgetItem (text, ui.tagWidget);
pItem->setForeground(QBrush(QColor(Tag->second.second)));
pItem->setIcon(QIcon(":/images/foldermail.png"));
pItem->setData(Qt::UserRole, Tag->first);
pItem->setData(Qt::UserRole + 1, text); // for updateMessageSummaryList
if (Tag->first == nSelectecTagId) {
pItemToSelect = pItem;
}
}
if (pItemToSelect) {
ui.tagWidget->setCurrentItem(pItemToSelect);
}
m_bInChange = false;
updateMessageSummaryList();
updateMessageSummaryList();
}
// replaced by shortcut
@ -982,6 +888,8 @@ void MessagesDialog::messagesTagsChanged()
fillTags();
insertMessages();
showTagLabels();
}
static void InitIconAndFont(QStandardItem *pItem [COLUMN_COUNT])
@ -1533,6 +1441,7 @@ void MessagesDialog::showTagLabels()
Tag = Tags.types.find(*tagId);
if (Tag != Tags.types.end()) {
QLabel *tagLabel = new QLabel(TagDefs::name(Tag->first, Tag->second.first), this);
tagLabel->setMaximumHeight(16);
tagLabel->setStyleSheet(TagDefs::labelStyleSheet(Tag->second.second));
tagLabels.push_back(tagLabel);
ui.taglayout->addWidget(tagLabel);
@ -2161,113 +2070,69 @@ void MessagesDialog::clearFilter()
void MessagesDialog::tagAboutToShow()
{
// activate actions from the first selected row
MsgTagInfo tagInfo;
TagsMenu *menu = dynamic_cast<TagsMenu*>(ui.tagButton->menu());
if (menu == NULL) {
return;
}
QList<int> Rows;
getSelectedMsgCount (&Rows, NULL, NULL);
// activate actions from the first selected row
MsgTagInfo tagInfo;
if (Rows.size()) {
QStandardItem* pItem = MessagesModel->item(Rows [0], COLUMN_DATA);
std::string msgId = pItem->data(ROLE_MSGID).toString().toStdString();
QList<int> rows;
getSelectedMsgCount (&rows, NULL, NULL);
rsMsgs->getMessageTag(msgId, tagInfo);
}
if (rows.size()) {
QStandardItem* item = MessagesModel->item(rows [0], COLUMN_DATA);
std::string msgId = item->data(ROLE_MSGID).toString().toStdString();
QMenu *pMenu = ui.tagButton->menu();
rsMsgs->getMessageTag(msgId, tagInfo);
}
foreach(QObject *pObject, pMenu->children()) {
QAction *pAction = qobject_cast<QAction*> (pObject);
if (pAction == NULL) {
continue;
}
const QMap<QString, QVariant> &Values = pAction->data().toMap();
if (Values.size () != ACTION_TAGSINDEX_SIZE) {
continue;
}
if (Values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) {
continue;
}
std::list<uint32_t>::iterator tagId = std::find(tagInfo.tagIds.begin(), tagInfo.tagIds.end(), Values [ACTION_TAGSINDEX_ID]);
pAction->setChecked(tagId != tagInfo.tagIds.end());
}
menu->activateActions(tagInfo.tagIds);
}
void MessagesDialog::tagTriggered(QAction *pAction)
void MessagesDialog::tagRemoveAll()
{
if (pAction == NULL) {
return;
}
LockUpdate Lock (this, false);
const QMap<QString, QVariant> &Values = pAction->data().toMap();
if (Values.size () != ACTION_TAGSINDEX_SIZE) {
return;
}
QList<int> rows;
getSelectedMsgCount (&rows, NULL, NULL);
for (int row = 0; row < rows.size(); row++) {
QStandardItem* item = MessagesModel->item(rows [row], COLUMN_DATA);
std::string msgId = item->data(ROLE_MSGID).toString().toStdString();
LockUpdate Lock (this, false);
rsMsgs->setMessageTag(msgId, 0, false);
Lock.setUpdate(true);
}
bool bRemoveAll = false;
int nId = 0;
bool bSet = false;
showTagLabels();
if (Values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_REMOVEALL) {
// remove all tags
bRemoveAll = true;
} else if (Values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_NEWTAG) {
// new tag
MsgTagType Tags;
rsMsgs->getMessageTagTypes(Tags);
// LockUpdate -> insertMessages();
}
NewTag TagDlg(Tags);
if (TagDlg.exec() == QDialog::Accepted && TagDlg.m_nId) {
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator Tag = Tags.types.find(TagDlg.m_nId);
if (Tag == Tags.types.end()) {
return;
}
if (rsMsgs->setMessageTagType(Tag->first, Tag->second.first, Tag->second.second) == false) {
return;
}
fillTags();
nId = TagDlg.m_nId;
bSet = true;
} else {
return;
}
} else if (Values [ACTION_TAGSINDEX_TYPE].toInt() == ACTION_TAGS_TAG) {
nId = Values [ACTION_TAGSINDEX_ID].toInt();
if (nId == 0) {
return;
}
bSet = pAction->isChecked();
} else {
return;
}
void MessagesDialog::tagSet(int tagId, bool set)
{
if (tagId == 0) {
return;
}
QList<int> Rows;
getSelectedMsgCount (&Rows, NULL, NULL);
for (int nRow = 0; nRow < Rows.size(); nRow++) {
QStandardItem* pItem = MessagesModel->item(Rows [nRow], COLUMN_DATA);
std::string msgId = pItem->data(ROLE_MSGID).toString().toStdString();
LockUpdate Lock (this, false);
if (bRemoveAll) {
// remove all
rsMsgs->setMessageTag(msgId, 0, false);
Lock.setUpdate(true);
QList<int> rows;
getSelectedMsgCount (&rows, NULL, NULL);
for (int row = 0; row < rows.size(); row++) {
QStandardItem* item = MessagesModel->item(rows [row], COLUMN_DATA);
std::string msgId = item->data(ROLE_MSGID).toString().toStdString();
} else {
// set or unset tag
MsgTagInfo tagInfo;
if (rsMsgs->setMessageTag(msgId, nId, bSet)) {
Lock.setUpdate(true);
}
}
}
if (rsMsgs->setMessageTag(msgId, tagId, set)) {
Lock.setUpdate(true);
}
}
showTagLabels();
// LockUpdate -> insertMessages();
showTagLabels();
// LockUpdate -> insertMessages();
}
void MessagesDialog::emptyTrash()

View File

@ -22,19 +22,11 @@
#ifndef _MESSAGESDIALOG_H
#define _MESSAGESDIALOG_H
#include <list>
#include <QFileDialog>
#include <QModelIndex>
#include <QSortFilterProxyModel>
#include <QVariant>
#include <retroshare/rsmsgs.h>
#include "mainpage.h"
#include "ui_MessagesDialog.h"
#include "settings/NewTag.h"
class MessagesDialog : public MainPage
{
Q_OBJECT
@ -105,8 +97,9 @@ private slots:
void filterColumnChanged();
void clearFilter();
void tagTriggered(QAction *pAction);
void tagAboutToShow();
void tagSet(int tagId, bool set);
void tagRemoveAll();
private:
class LockUpdate

View File

@ -53,8 +53,12 @@
#include "gui/common/Emoticons.h"
#include "textformat.h"
#include "util/misc.h"
#include "TagsMenu.h"
#include "gui/common/TagDefs.h"
#include "gui/connect/ConfCertDialog.h"
#define IMAGE_GROUP16 ":/images/user/group16.png"
#define IMAGE_GROUP16 ":/images/user/group16.png"
#define IMAGE_FRIENDINFO ":/images/peerdetails_16x16.png"
#define COLUMN_CONTACT_NAME 0
#define COLUMN_CONTACT_DATA 0
@ -161,6 +165,7 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WFlags flags)
connect(ui.msgText->document(), SIGNAL(redoAvailable(bool)), actionRedo, SLOT(setEnabled(bool)));
connect(ui.msgFileList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuFileList(QPoint)));
connect(ui.msgSendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuMsgSendList(QPoint)));
setWindowModified(ui.msgText->document()->isModified());
actionSave->setEnabled(ui.msgText->document()->isModified());
@ -182,11 +187,11 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WFlags flags)
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
connect(ui.addToButton, SIGNAL(clicked(void)), this, SLOT(btnClickEvent()));
connect(ui.addCcButton, SIGNAL(clicked(void)), this, SLOT(btnClickEvent()));
connect(ui.addBccButton, SIGNAL(clicked(void)), this, SLOT(btnClickEvent()));
connect(ui.addRecommendButton, SIGNAL(clicked(void)), this, SLOT(recommendButtonClicked()));
connect(ui.msgSendList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(btnClickEvent()));
connect(ui.addToButton, SIGNAL(clicked(void)), this, SLOT(addTo()));
connect(ui.addCcButton, SIGNAL(clicked(void)), this, SLOT(addCc()));
connect(ui.addBccButton, SIGNAL(clicked(void)), this, SLOT(addBcc()));
connect(ui.addRecommendButton, SIGNAL(clicked(void)), this, SLOT(addRecommend()));
connect(ui.msgSendList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(addTo()));
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged(int)));
connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&,int)), this, SLOT(peerStatusChanged(const QString&,int)));
@ -289,6 +294,14 @@ MessageComposer::MessageComposer(QWidget *parent, Qt::WFlags flags)
/* set focus to subject */
ui.titleEdit->setFocus();
// create tag menu
TagsMenu *menu = new TagsMenu (tr("Tags"), this);
connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow()));
connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool)));
connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll()));
ui.tagButton->setMenu(menu);
setAcceptDrops(true);
#ifdef RS_RELEASE_VERSION
@ -473,6 +486,29 @@ void MessageComposer::contextMenuFileList(QPoint)
contextMnu.exec(QCursor::pos());
}
void MessageComposer::contextMenuMsgSendList(QPoint)
{
QMenu contextMnu(this);
int selectedCount = ui.msgSendList->selectedItems().count();
QAction *action = contextMnu.addAction(QIcon(), tr("Add to \"To\""), this, SLOT(addTo()));
action->setEnabled(selectedCount);
action = contextMnu.addAction(QIcon(), tr("Add to \"CC\""), this, SLOT(addCc()));
action->setEnabled(selectedCount);
action = contextMnu.addAction(QIcon(), tr("Add to \"BCC\""), this, SLOT(addBcc()));
action->setEnabled(selectedCount);
action = contextMnu.addAction(QIcon(), tr("Add as Recommend"), this, SLOT(addRecommend()));
action->setEnabled(selectedCount);
contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Friend Details"), this, SLOT(friendDetails()));
action->setEnabled(selectedCount == 1);
contextMnu.exec(QCursor::pos());
}
void MessageComposer::pasteRecommended()
{
std::vector<RetroShareLink> links;
@ -943,6 +979,12 @@ MessageComposer *MessageComposer::newMsg(const std::string &msgId /*= ""*/)
msgComposer->addRecipient(MessageComposer::BCC, *it, false) ;
}
MsgTagInfo tagInfo;
rsMsgs->getMessageTag(msgId, tagInfo);
msgComposer->m_tagIds = tagInfo.tagIds;
msgComposer->showTagLabels();
msgComposer->ui.msgText->document()->setModified(false);
}
@ -1261,6 +1303,25 @@ bool MessageComposer::sendMessage_internal(bool bDraftbox)
}
}
if (mi.msgId.empty() == false) {
MsgTagInfo tagInfo;
rsMsgs->getMessageTag(mi.msgId, tagInfo);
/* insert new tags */
std::list<uint32_t>::iterator tag;
for (tag = m_tagIds.begin(); tag != m_tagIds.end(); tag++) {
if (std::find(tagInfo.tagIds.begin(), tagInfo.tagIds.end(), *tag) == tagInfo.tagIds.end()) {
rsMsgs->setMessageTag(mi.msgId, *tag, true);
} else {
tagInfo.tagIds.remove(*tag);
}
}
/* remove deleted tags */
for (tag = tagInfo.tagIds.begin(); tag != tagInfo.tagIds.end(); tag++) {
rsMsgs->setMessageTag(mi.msgId, *tag, false);
}
}
ui.msgText->document()->setModified(false);
return true;
}
@ -2302,19 +2363,8 @@ bool MessageComposer::FilterItem(QTreeWidgetItem *pItem, QString &sPattern)
return (bVisible || nVisibleChildCount);
}
void MessageComposer::btnClickEvent()
void MessageComposer::addContact(enumType type)
{
enumType type;
if (QObject::sender() == ui.addToButton || QObject::sender() == ui.msgSendList) {
type = TO;
} else if (QObject::sender() == ui.addCcButton) {
type = CC;
} else if (QObject::sender() == ui.addBccButton) {
type = BCC;
} else {
return;
}
QTreeWidgetItemIterator itemIterator(ui.msgSendList);
QTreeWidgetItem *item;
while ((item = *itemIterator) != NULL) {
@ -2328,7 +2378,22 @@ void MessageComposer::btnClickEvent()
}
}
void MessageComposer::recommendButtonClicked()
void MessageComposer::addTo()
{
addContact(TO);
}
void MessageComposer::addCc()
{
addContact(CC);
}
void MessageComposer::addBcc()
{
addContact(BCC);
}
void MessageComposer::addRecommend()
{
std::list<std::string> gpgIds;
@ -2375,6 +2440,22 @@ void MessageComposer::recommendButtonClicked()
ui.msgText->setFocus(Qt::OtherFocusReason);
}
void MessageComposer::friendDetails()
{
QList<QTreeWidgetItem*> selectedItems = ui.msgSendList->selectedItems();
if (selectedItems.count() != 1) {
return;
}
QTreeWidgetItem *item = selectedItems[0];
if (item->type() == TYPE_GROUP) {
return;
}
std::string id = item->data(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID).toString().toStdString();
ConfCertDialog::showIt(id, ConfCertDialog::PageDetails);
}
void MessageComposer::dragEnterEvent(QDragEnterEvent *event)
{
/* print out mimeType */
@ -2450,3 +2531,78 @@ void MessageComposer::dropEvent(QDropEvent *event)
event->setDropAction(Qt::CopyAction);
event->accept();
}
void MessageComposer::tagAboutToShow()
{
TagsMenu *menu = dynamic_cast<TagsMenu*>(ui.tagButton->menu());
if (menu == NULL) {
return;
}
menu->activateActions(m_tagIds);
}
void MessageComposer::tagRemoveAll()
{
m_tagIds.clear();
showTagLabels();
}
void MessageComposer::tagSet(int tagId, bool set)
{
if (tagId == 0) {
return;
}
std::list<uint32_t>::iterator tag = std::find(m_tagIds.begin(), m_tagIds.end(), tagId);
if (tag == m_tagIds.end()) {
if (set) {
m_tagIds.push_back(tagId);
/* Keep the list sorted */
m_tagIds.sort();
}
} else {
if (set == false) {
m_tagIds.remove(tagId);
}
}
showTagLabels();
}
void MessageComposer::clearTagLabels()
{
/* clear all tags */
while (tagLabels.size()) {
delete tagLabels.front();
tagLabels.pop_front();
}
while (ui.tagLayout->count()) {
delete ui.tagLayout->takeAt(0);
}
}
void MessageComposer::showTagLabels()
{
clearTagLabels();
if (m_tagIds.empty() == false) {
MsgTagType tags;
rsMsgs->getMessageTagTypes(tags);
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator tag;
for (std::list<uint32_t>::iterator tagId = m_tagIds.begin(); tagId != m_tagIds.end(); tagId++) {
tag = tags.types.find(*tagId);
if (tag != tags.types.end()) {
QLabel *tagLabel = new QLabel(TagDefs::name(tag->first, tag->second.first), this);
tagLabel->setMaximumHeight(16);
tagLabel->setStyleSheet(TagDefs::labelStyleSheet(tag->second.second));
tagLabels.push_back(tagLabel);
ui.tagLayout->addWidget(tagLabel);
ui.tagLayout->addSpacing(3);
}
}
ui.tagLayout->addStretch();
}
}

View File

@ -88,6 +88,7 @@ private slots:
void contextMenu(QPoint);
void pasteLink();
void contextMenuFileList(QPoint);
void contextMenuMsgSendList(QPoint);
void pasteRecommended();
void on_contactsdockWidget_visibilityChanged(bool visible);
void toggleContacts();
@ -135,16 +136,24 @@ private slots:
void titleChanged();
// Add to To/Cc/Bcc address fields
void btnClickEvent();
void recommendButtonClicked();
void addTo();
void addCc();
void addBcc();
void addRecommend();
void editingRecipientFinished();
void friendDetails();
void groupsChanged(int type);
void peerStatusChanged(const QString& peer_id, int status);
void tagAboutToShow();
void tagSet(int tagId, bool set);
void tagRemoveAll();
private:
void processSettings(bool bLoad);
void addContact(enumType type);
void setTextColor(const QColor& col) ;
void setupFileActions();
void setupEditActions();
@ -173,6 +182,9 @@ private:
bool getRecipientFromRow(int row, enumType &type, std::string &id, bool &group);
void setRecipientToRow(int row, enumType type, std::string id, bool group);
void clearTagLabels();
void showTagLabels();
QAction *actionSave,
*actionAlignLeft,
*actionAlignCenter,
@ -201,6 +213,8 @@ private:
std::string m_msgParentId; // parent message id
std::string m_sDraftMsgId; // existing message id
enumMessageType m_msgType;
std::list<uint32_t> m_tagIds;
QList<QLabel*> tagLabels;
/* maps of files */
std::list<AttachFileItem *> mAttachments;

View File

@ -17,7 +17,7 @@
<string>Compose</string>
</property>
<property name="windowIcon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/folder-draft.png</normaloff>:/images/folder-draft.png</iconset>
</property>
<property name="styleSheet">
@ -168,6 +168,9 @@ border-image: url(:/images/closepressed.png)
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
@ -394,7 +397,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/format_font_size_more.png</normaloff>:/images/textedit/format_font_size_more.png</iconset>
</property>
<property name="iconSize">
@ -426,7 +429,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/format_font_size_less.png</normaloff>:/images/textedit/format_font_size_less.png</iconset>
</property>
<property name="iconSize">
@ -464,7 +467,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/textbold.png</normaloff>:/images/textedit/textbold.png</iconset>
</property>
<property name="iconSize">
@ -505,7 +508,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/textitalic.png</normaloff>:/images/textedit/textitalic.png</iconset>
</property>
<property name="iconSize">
@ -611,7 +614,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/add_image24.png</normaloff>:/images/add_image24.png</iconset>
</property>
<property name="iconSize">
@ -637,7 +640,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/hi22-action-format-text-code.png</normaloff>:/images/textedit/hi22-action-format-text-code.png</iconset>
</property>
<property name="iconSize">
@ -670,7 +673,7 @@ border: 1px solid #CCCCCC;}</string>
<enum>Qt::NoFocus</enum>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/emoticons/kopete/kopete020.png</normaloff>:/images/emoticons/kopete/kopete020.png</iconset>
</property>
<property name="iconSize">
@ -708,7 +711,7 @@ border: 1px solid #CCCCCC;}</string>
<string/>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/textedit/textunder.png</normaloff>:/images/textedit/textunder.png</iconset>
</property>
<property name="iconSize">
@ -746,33 +749,6 @@ border: 1px solid #CCCCCC;}</string>
</property>
</widget>
</item>
<item row="2" column="0" rowspan="2">
<layout class="QHBoxLayout" name="SubjectHLayout" stretch="0,0">
<property name="spacing">
<number>6</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Subject:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="titleEdit"/>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QTableWidget" name="recipientWidget">
<property name="sizePolicy">
@ -819,6 +795,72 @@ border: 1px solid #CCCCCC;}</string>
</attribute>
</widget>
</item>
<item row="2" column="0" rowspan="2">
<layout class="QGridLayout" name="gridLayout_6">
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Subject:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="5">
<widget class="QLineEdit" name="titleEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Tags:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="tagButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Tags</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/images/tag24.png</normaloff>:/images/tag24.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<layout class="QHBoxLayout" name="tagLayout"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_1">
@ -964,7 +1006,7 @@ border: 1px solid #CCCCCC;}</string>
</widget>
<action name="actionSend">
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/send24.png</normaloff>:/images/send24.png</iconset>
</property>
<property name="text">
@ -976,7 +1018,7 @@ border: 1px solid #CCCCCC;}</string>
</action>
<action name="actionReply">
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/replymail24.png</normaloff>:/images/replymail24.png</iconset>
</property>
<property name="text">
@ -985,7 +1027,7 @@ border: 1px solid #CCCCCC;}</string>
</action>
<action name="actionContactsView">
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/contacts24.png</normaloff>:/images/contacts24.png</iconset>
</property>
<property name="text">
@ -997,7 +1039,7 @@ border: 1px solid #CCCCCC;}</string>
</action>
<action name="actionSaveas">
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/save24.png</normaloff>:/images/save24.png</iconset>
</property>
<property name="text">
@ -1009,7 +1051,7 @@ border: 1px solid #CCCCCC;}</string>
</action>
<action name="actionAttach">
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/attach.png</normaloff>:/images/attach.png</iconset>
</property>
<property name="text">
@ -1024,7 +1066,7 @@ border: 1px solid #CCCCCC;}</string>
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<iconset>
<normaloff>:/images/quote_24.png</normaloff>:/images/quote_24.png</iconset>
</property>
<property name="text">
@ -1051,8 +1093,6 @@ border: 1px solid #CCCCCC;}</string>
<tabstop>comboFont</tabstop>
<tabstop>hashBox</tabstop>
</tabstops>
<resources>
<include location="../images.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,199 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2006,2007 RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QPainter>
#include <QPaintEvent>
#include <QStyleOptionMenuItem>
#include <algorithm>
#include <retroshare/rsmsgs.h>
#include "TagsMenu.h"
#include "gui/common/TagDefs.h"
#include "gui/settings/NewTag.h"
#include "gui/notifyqt.h"
#define ACTION_TAGSINDEX_SIZE 3
#define ACTION_TAGSINDEX_TYPE "Type"
#define ACTION_TAGSINDEX_ID "ID"
#define ACTION_TAGSINDEX_COLOR "Color"
#define ACTION_TAGS_REMOVEALL 0
#define ACTION_TAGS_TAG 1
#define ACTION_TAGS_NEWTAG 2
TagsMenu::TagsMenu(const QString &title, QWidget *parent)
: QMenu (title, parent)
{
connect(this, SIGNAL(triggered (QAction*)), this, SLOT(tagTriggered(QAction*)));
connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(fillTags()));
fillTags();
}
void TagsMenu::paintEvent(QPaintEvent *e)
{
QMenu::paintEvent(e);
QPainter p(this);
QRegion emptyArea = QRegion(rect());
//draw the items with color
foreach (QAction *action, actions()) {
QRect adjustedActionRect = actionGeometry(action);
if (!e->rect().intersects(adjustedActionRect))
continue;
const QMap<QString, QVariant> &values = action->data().toMap();
if (values.size () != ACTION_TAGSINDEX_SIZE) {
continue;
}
if (values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) {
continue;
}
//set the clip region to be extra safe (and adjust for the scrollers)
QRegion adjustedActionReg(adjustedActionRect);
emptyArea -= adjustedActionReg;
p.setClipRegion(adjustedActionReg);
QStyleOptionMenuItem opt;
initStyleOption(&opt, action);
opt.palette.setColor(QPalette::ButtonText, QColor(values [ACTION_TAGSINDEX_COLOR].toInt()));
// needed for Cleanlooks
opt.palette.setColor(QPalette::Text, QColor(values [ACTION_TAGSINDEX_COLOR].toInt()));
opt.rect = adjustedActionRect;
style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
}
}
void TagsMenu::fillTags()
{
clear();
MsgTagType tags;
rsMsgs->getMessageTagTypes(tags);
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator tag;
bool user = false;
QString text;
QAction *action;
QMap<QString, QVariant> values;
if (tags.types.size()) {
action = new QAction(tr("Remove All Tags"), this);
values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_REMOVEALL;
values [ACTION_TAGSINDEX_ID] = 0;
values [ACTION_TAGSINDEX_COLOR] = 0;
action->setData (values);
addAction(action);
addSeparator();
for (tag = tags.types.begin(); tag != tags.types.end(); tag++) {
text = TagDefs::name(tag->first, tag->second.first);
action = new QAction(text, this);
values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_TAG;
values [ACTION_TAGSINDEX_ID] = tag->first;
values [ACTION_TAGSINDEX_COLOR] = QRgb(tag->second.second);
action->setData (values);
action->setCheckable(true);
if (tag->first >= RS_MSGTAGTYPE_USER && user == false) {
user = true;
addSeparator();
}
addAction(action);
}
addSeparator();
}
action = new QAction(tr("New tag ..."), this);
values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_NEWTAG;
values [ACTION_TAGSINDEX_ID] = 0;
values [ACTION_TAGSINDEX_COLOR] = 0;
action->setData (values);
addAction(action);
}
void TagsMenu::activateActions(std::list<uint32_t>& tagIds)
{
foreach(QObject *object, children()) {
QAction *action = qobject_cast<QAction*> (object);
if (action == NULL) {
continue;
}
const QMap<QString, QVariant> &values = action->data().toMap();
if (values.size () != ACTION_TAGSINDEX_SIZE) {
continue;
}
if (values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) {
continue;
}
std::list<uint32_t>::iterator tagId = std::find(tagIds.begin(), tagIds.end(), values [ACTION_TAGSINDEX_ID]);
action->setChecked(tagId != tagIds.end());
}
}
void TagsMenu::tagTriggered(QAction *action)
{
if (action == NULL) {
return;
}
const QMap<QString, QVariant> &values = action->data().toMap();
if (values.size () != ACTION_TAGSINDEX_SIZE) {
return;
}
if (values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_REMOVEALL) {
// remove all tags
emit tagRemoveAll();
} else if (values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_NEWTAG) {
// new tag
MsgTagType tags;
rsMsgs->getMessageTagTypes(tags);
NewTag tagDlg(tags);
if (tagDlg.exec() == QDialog::Accepted && tagDlg.m_nId) {
std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator tag = tags.types.find(tagDlg.m_nId);
if (tag != tags.types.end()) {
if (rsMsgs->setMessageTagType(tag->first, tag->second.first, tag->second.second)) {
emit tagSet(tagDlg.m_nId, true);
}
}
}
} else if (values [ACTION_TAGSINDEX_TYPE].toInt() == ACTION_TAGS_TAG) {
int tagId = values [ACTION_TAGSINDEX_ID].toInt();
if (tagId) {
emit tagSet(tagId, action->isChecked());
}
}
}

View File

@ -0,0 +1,48 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2007, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef _TAGSMENU_H
#define _TAGSMENU_H
#include <QMenu>
class TagsMenu : public QMenu
{
Q_OBJECT
public:
TagsMenu(const QString &title, QWidget *parent);
void activateActions(std::list<uint32_t>& tagIds);
signals:
void tagSet(int tagId, bool set);
void tagRemoveAll();
protected:
virtual void paintEvent(QPaintEvent *e);
private slots:
void fillTags();
void tagTriggered(QAction *action);
};
#endif

View File

@ -28,7 +28,6 @@
#include <algorithm>
#include "../MainWindow.h"
#include "NewTag.h"
MessagePage::MessagePage(QWidget * parent, Qt::WFlags flags)

View File

@ -1440,7 +1440,7 @@ p, li { white-space: pre-wrap; }
<context>
<name>ConfCertDialog</name>
<message>
<location filename="../gui/connect/ConfCertDialog.ui" line="+665"/>
<location filename="../gui/connect/ConfCertDialog.ui" line="+689"/>
<source>Cancel</source>
<translation>Abbrechen</translation>
</message>
@ -1450,7 +1450,7 @@ p, li { white-space: pre-wrap; }
<translation>OK</translation>
</message>
<message>
<location line="-614"/>
<location line="-638"/>
<source>Peer Info</source>
<translation>Nachbar Info</translation>
</message>
@ -1470,7 +1470,7 @@ p, li { white-space: pre-wrap; }
<translation>Peer ID</translation>
</message>
<message>
<location line="+87"/>
<location line="+111"/>
<source>Peer Address</source>
<translation>Adresse des Nachbarn</translation>
</message>
@ -1511,7 +1511,7 @@ p, li { white-space: pre-wrap; }
<translation>Nachbar Schlüssel ist unterzeichnet von:</translation>
</message>
<message>
<location line="-395"/>
<location line="-419"/>
<source>Last Contact</source>
<translation>Letzter Kontakt</translation>
</message>
@ -1531,7 +1531,7 @@ p, li { white-space: pre-wrap; }
<translation>Ort</translation>
</message>
<message>
<location line="+28"/>
<location line="+52"/>
<source>Status</source>
<translation>Status</translation>
</message>
@ -1600,18 +1600,18 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location filename="../gui/connect/ConfCertDialog.cpp" line="+133"/>
<location line="+201"/>
<location line="+207"/>
<source>RetroShare</source>
<translation></translation>
</message>
<message>
<location line="-200"/>
<location line="+201"/>
<location line="-206"/>
<location line="+207"/>
<source>Error : cannot get peer details.</source>
<translation>Fehler: Kann Peer Details nicht ermitteln.</translation>
</message>
<message>
<location line="-121"/>
<location line="-122"/>
<source>Your key is signed by : </source>
<translation>Ihr Schlüssel ist unterzeichnet von: </translation>
</message>
@ -1658,7 +1658,7 @@ und meinen GPG Schlüssel unterzeichnet</translation>
und meinen GPG Schlüssel nicht unterzeichnet</translation>
</message>
<message>
<location line="+112"/>
<location line="+113"/>
<source>Signature Failure</source>
<translation>Signatur Fehler</translation>
</message>
@ -1683,17 +1683,16 @@ und meinen GPG Schlüssel nicht unterzeichnet</translation>
<translation>Zeige Hilfe</translation>
</message>
<message>
<location line="-333"/>
<location line="-357"/>
<source>RetroShare ID</source>
<translation></translation>
</message>
<message>
<location filename="../gui/connect/ConfCertDialog.cpp" line="+31"/>
<source>Copy Peer</source>
<translation>Kopiere Nachbar</translation>
<translation type="obsolete">Kopiere Nachbar</translation>
</message>
<message>
<location filename="../gui/connect/ConfCertDialog.ui" line="+507"/>
<location line="+531"/>
<source>Certificate</source>
<translation>Zertifikat</translation>
</message>
@ -5652,18 +5651,18 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<name>MessageComposer</name>
<message>
<location filename="../gui/msgs/MessageComposer.ui" line="+17"/>
<location filename="../gui/msgs/MessageComposer.cpp" line="+791"/>
<location filename="../gui/msgs/MessageComposer.cpp" line="+827"/>
<source>Compose</source>
<translation>Verfassen</translation>
</message>
<message>
<location line="+49"/>
<location line="+926"/>
<location line="+968"/>
<source>Contacts</source>
<translation>Kontakte</translation>
</message>
<message>
<location line="-911"/>
<location line="-953"/>
<source>Search for Name:</source>
<translation>Suche Name:</translation>
</message>
@ -5673,7 +5672,7 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>Zurücksetzen</translation>
</message>
<message>
<location line="+67"/>
<location line="+70"/>
<source>Send To:</source>
<translation>Senden an:</translation>
</message>
@ -5693,22 +5692,22 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>&gt;&gt; Bcc</translation>
</message>
<message>
<location line="+537"/>
<location line="+573"/>
<source>Subject:</source>
<translation>Betreff:</translation>
</message>
<message>
<location line="-457"/>
<location line="-493"/>
<source>Paragraph</source>
<translation>Absatz</translation>
</message>
<message>
<location line="-222"/>
<location line="-225"/>
<source>Search Friends</source>
<translation>Suche Freunde</translation>
</message>
<message>
<location line="+159"/>
<location line="+162"/>
<source>&gt;&gt; Recommend</source>
<translation>&gt;&gt; Empfehlen</translation>
</message>
@ -5769,7 +5768,18 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>Unterstrichen</translation>
</message>
<message>
<location line="-203"/>
<location line="+111"/>
<source>Tags:</source>
<translation>Schlagwörter:</translation>
</message>
<message>
<location line="+16"/>
<location filename="../gui/msgs/MessageComposer.cpp" line="-529"/>
<source>Tags</source>
<translation>Schlagwörter</translation>
</message>
<message>
<location line="-330"/>
<source>Italic</source>
<translation>Kursiv</translation>
</message>
@ -5794,7 +5804,7 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>Setzt Schriftart auf Codestil</translation>
</message>
<message>
<location filename="../gui/msgs/MessageComposer.cpp" line="+529"/>
<location filename="../gui/msgs/MessageComposer.cpp" line="+1083"/>
<source>To</source>
<translation>An</translation>
</message>
@ -5809,7 +5819,7 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>Bcc</translation>
</message>
<message>
<location filename="../gui/msgs/MessageComposer.ui" line="+214"/>
<location filename="../gui/msgs/MessageComposer.ui" line="+253"/>
<source>Recommended Files</source>
<translation>Empfohlene Dateien</translation>
</message>
@ -5879,7 +5889,7 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>Blockquote hinzufügen</translation>
</message>
<message>
<location filename="../gui/msgs/MessageComposer.cpp" line="-1116"/>
<location filename="../gui/msgs/MessageComposer.cpp" line="-1172"/>
<source>&amp;Left</source>
<translation>&amp;Links</translation>
</message>
@ -5899,13 +5909,13 @@ Bitte gib etwas Speicher frei und drücke OK.</translation>
<translation>&amp;Blocksatz</translation>
</message>
<message>
<location line="+206"/>
<location line="+1605"/>
<location line="+214"/>
<location line="+1653"/>
<source>Save Message</source>
<translation>Nachricht speichern</translation>
</message>
<message>
<location line="-1604"/>
<location line="-1652"/>
<source>Message has not been Sent.
Do you want to save message to draft box?</source>
<translation>Nachricht wurde noch nicht gesendet.
@ -5918,7 +5928,32 @@ Möchtest Du die Nachricht in den Entwürfen speichern?</translation>
<translation>RetroShare Link einfügen</translation>
</message>
<message>
<location line="+571"/>
<location line="+12"/>
<source>Add to &quot;To&quot;</source>
<translation>Zu &quot;An&quot; hinzufügen</translation>
</message>
<message>
<location line="+2"/>
<source>Add to &quot;CC&quot;</source>
<translation>Zu &quot;Cc&quot; hinzufügen</translation>
</message>
<message>
<location line="+2"/>
<source>Add to &quot;BCC&quot;</source>
<translation>Zu &quot;Bcc&quot; hinzufügen</translation>
</message>
<message>
<location line="+2"/>
<source>Add as Recommend</source>
<translation>Als empfohlen hinzufügen</translation>
</message>
<message>
<location line="+5"/>
<source>Friend Details</source>
<translation>Freund-Details</translation>
</message>
<message>
<location line="+577"/>
<source>Re:</source>
<translation>Re:</translation>
</message>
@ -5944,7 +5979,7 @@ Möchtest Du die Nachricht in den Entwürfen speichern?</translation>
<translation>Bitte geben sie mindestens einen Empfänger ein.</translation>
</message>
<message>
<location line="+112"/>
<location line="+131"/>
<source>Unknown</source>
<translation>Unbekannt</translation>
</message>
@ -6107,7 +6142,7 @@ Willst Du die Nachricht speichern ?</translation>
<translation>Zusätzliche Datei hinzufügen</translation>
</message>
<message>
<location line="+274"/>
<location line="+294"/>
<location line="+6"/>
<source>Drop file error.</source>
<translation>Dateifehler bei Drag&apos;n&apos;Drop.</translation>
@ -6123,7 +6158,7 @@ Willst Du die Nachricht speichern ?</translation>
<translation>Datei nicht gefunden oder Dateiname nicht akzeptiert.</translation>
</message>
<message>
<location line="-2043"/>
<location line="-2111"/>
<source>Friend Recommendation(s)</source>
<translation>Freundempfehlung(en)</translation>
</message>
@ -6176,7 +6211,7 @@ Willst Du die Nachricht speichern ?</translation>
<translation>Standard</translation>
</message>
<message>
<location filename="../gui/settings/MessagePage.cpp" line="+148"/>
<location filename="../gui/settings/MessagePage.cpp" line="+147"/>
<source>Edit Tag</source>
<translation>Schlagwort bearbeiten</translation>
</message>
@ -6208,7 +6243,7 @@ Willst Du die Nachricht speichern ?</translation>
<name>MessagesDialog</name>
<message>
<location filename="../gui/MessagesDialog.ui" line="+576"/>
<location filename="../gui/MessagesDialog.cpp" line="+684"/>
<location filename="../gui/MessagesDialog.cpp" line="+596"/>
<source>New Message</source>
<translation>Neue Nachricht</translation>
</message>
@ -6224,14 +6259,14 @@ Willst Du die Nachricht speichern ?</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.ui" line="+393"/>
<location filename="../gui/MessagesDialog.cpp" line="-396"/>
<location filename="../gui/MessagesDialog.cpp" line="-362"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location line="-5"/>
<location filename="../gui/MessagesDialog.cpp" line="-1"/>
<location line="+854"/>
<location line="+820"/>
<source>From</source>
<translation>Von</translation>
</message>
@ -6316,15 +6351,15 @@ p, li { white-space: pre-wrap; }
<message>
<location line="+180"/>
<location filename="../gui/MessagesDialog.cpp" line="-44"/>
<location line="+986"/>
<location line="+989"/>
<location line="+10"/>
<source>Inbox</source>
<translation>Posteingang</translation>
</message>
<message>
<location line="+9"/>
<location filename="../gui/MessagesDialog.cpp" line="-991"/>
<location line="+1004"/>
<location filename="../gui/MessagesDialog.cpp" line="-994"/>
<location line="+1007"/>
<location line="+8"/>
<source>Outbox</source>
<translation>Postausgang</translation>
@ -6336,7 +6371,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location line="+9"/>
<location filename="../gui/MessagesDialog.cpp" line="-1002"/>
<location filename="../gui/MessagesDialog.cpp" line="-1005"/>
<source>Sent</source>
<translation>Gesendet</translation>
</message>
@ -6403,13 +6438,13 @@ p, li { white-space: pre-wrap; }
<translation>Speichern unter...</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.cpp" line="+758"/>
<location filename="../gui/MessagesDialog.cpp" line="+761"/>
<source>Print Document</source>
<translation>Dokument drucken</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.ui" line="-839"/>
<location filename="../gui/MessagesDialog.cpp" line="-1585"/>
<location filename="../gui/MessagesDialog.cpp" line="-1554"/>
<source>Subject</source>
<translation>Betreff</translation>
</message>
@ -6444,12 +6479,12 @@ p, li { white-space: pre-wrap; }
<translation>Drucken</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.cpp" line="+56"/>
<location filename="../gui/MessagesDialog.cpp" line="+63"/>
<source>Forward selected Message</source>
<translation>Gewählte Nachricht weiterleiten</translation>
</message>
<message>
<location line="+341"/>
<location line="+300"/>
<source>Remove Messages</source>
<translation>Löschen</translation>
</message>
@ -6459,31 +6494,38 @@ p, li { white-space: pre-wrap; }
<translation>Weiterleiten</translation>
</message>
<message>
<location line="-314"/>
<source>Click to sort by attachments</source>
<translation type="obsolete">Klicken, um nach Anhang zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Anhang zu sortieren</translation>
</message>
<message>
<location line="+1"/>
<source>Click to sort by subject</source>
<translation type="obsolete">Klicken, um nach Betreff zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Betreff zu sortieren</translation>
</message>
<message>
<location line="+1"/>
<source>Click to sort by read</source>
<translation type="obsolete">Klicken, um nach Gelesen / Ungelesen zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Gelesen / Ungelesen zu sortieren</translation>
</message>
<message>
<location line="+1"/>
<location line="+813"/>
<source>Click to sort by from</source>
<translation type="obsolete">Klicken, um nach Von zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Von zu sortieren</translation>
</message>
<message>
<location line="-812"/>
<source>Click to sort by date</source>
<translation type="obsolete">Klicken, um nach Datum zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Datum zu sortieren</translation>
</message>
<message>
<location line="+1"/>
<source>Click to sort by tags</source>
<translation type="obsolete">Klicken, um nach Schlagwörter zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Schlagwörter zu sortieren</translation>
</message>
<message>
<location line="+89"/>
<location line="+398"/>
<source>Download</source>
<translation>Herunterladen</translation>
</message>
@ -6498,11 +6540,12 @@ p, li { white-space: pre-wrap; }
<translation>Empfohlene Dateien einblenden</translation>
</message>
<message>
<location line="+273"/>
<source>Click to sort by to</source>
<translation type="obsolete">Klicken, um nach Empfänger zu sortieren</translation>
<translation type="unfinished">Klicken, um nach Empfänger zu sortieren</translation>
</message>
<message>
<location line="+894"/>
<location line="+624"/>
<source>File</source>
<translation>Datei</translation>
</message>
@ -6522,8 +6565,8 @@ p, li { white-space: pre-wrap; }
<translation>HTML-Dateien (*.htm *.html);;Alle Dateien (*)</translation>
</message>
<message>
<location line="-1562"/>
<location line="+294"/>
<location line="-1524"/>
<location line="+253"/>
<source>Reply to All</source>
<translation>Allen antworten</translation>
</message>
@ -6541,7 +6584,7 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location line="-277"/>
<location filename="../gui/MessagesDialog.cpp" line="-346"/>
<location filename="../gui/MessagesDialog.cpp" line="-312"/>
<source>Content</source>
<translation>Inhalt</translation>
</message>
@ -6549,7 +6592,7 @@ p, li { white-space: pre-wrap; }
<location line="+5"/>
<location line="+11"/>
<location filename="../gui/MessagesDialog.cpp" line="-1"/>
<location line="+200"/>
<location line="+104"/>
<source>Tags</source>
<translation>Schlagwörter</translation>
</message>
@ -6560,8 +6603,8 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location line="+177"/>
<location filename="../gui/MessagesDialog.cpp" line="+628"/>
<location line="+1028"/>
<location filename="../gui/MessagesDialog.cpp" line="+690"/>
<location line="+1031"/>
<location line="+5"/>
<source>Trash</source>
<translation>Papierkorb</translation>
@ -6577,17 +6620,15 @@ p, li { white-space: pre-wrap; }
<translation>Ordner</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.cpp" line="-1650"/>
<source>Remove All Tags</source>
<translation>Alle Schlagwörter entfernen</translation>
<translation type="obsolete">Alle Schlagwörter entfernen</translation>
</message>
<message>
<location line="+30"/>
<source>New tag ...</source>
<translation>Neues Schlagwort...</translation>
<translation type="obsolete">Neues Schlagwort...</translation>
</message>
<message>
<location line="+130"/>
<location filename="../gui/MessagesDialog.cpp" line="-1493"/>
<source>Mark as read</source>
<translation>Als gelesen markieren</translation>
</message>
@ -6608,23 +6649,23 @@ p, li { white-space: pre-wrap; }
</message>
<message>
<location line="+358"/>
<location line="+1019"/>
<location line="+1022"/>
<location line="+8"/>
<source>Drafts</source>
<translation>Entwürfe</translation>
</message>
<message>
<location line="-991"/>
<location line="-993"/>
<source>To</source>
<translation>An</translation>
</message>
<message>
<location line="-495"/>
<location line="-496"/>
<source>Edit...</source>
<translation>Editieren...</translation>
</message>
<message>
<location line="+1406"/>
<location line="+1409"/>
<location line="+4"/>
<location line="+4"/>
<location line="+4"/>
@ -9019,7 +9060,7 @@ Lockdatei:
<translation>Vielleicht ist das Passwort falsch</translation>
</message>
<message>
<location filename="../gui/RetroShareLink.cpp" line="+657"/>
<location filename="../gui/RetroShareLink.cpp" line="+659"/>
<source>File Request Confirmation</source>
<translation>Bestätigung der Dateianforderung</translation>
</message>
@ -9029,7 +9070,7 @@ Lockdatei:
<translation>Die Datei wurde zur Downloadliste hinzugefügt.</translation>
</message>
<message>
<location filename="../gui/MessagesDialog.cpp" line="-1146"/>
<location filename="../gui/MessagesDialog.cpp" line="-1149"/>
<location filename="../gui/RetroShareLink.cpp" line="+8"/>
<source>File Request canceled</source>
<translation>Dateianforderung abgebrochen</translation>
@ -9048,17 +9089,17 @@ Lockdatei:
</message>
<message>
<location line="+23"/>
<location line="+9"/>
<location line="+10"/>
<source>Friend Request Confirmation</source>
<translation>Freundanfrage bestätigen</translation>
</message>
<message>
<location line="-9"/>
<location line="-10"/>
<source>The friend is already in your list.</source>
<translation>Der Freund ist schon in Deiner Liste.</translation>
</message>
<message>
<location line="+9"/>
<location line="+10"/>
<source>The friend has been added to your list.</source>
<translation>Der Freund wurde zu Deiner Liste hinzugefügt.</translation>
</message>
@ -11490,6 +11531,19 @@ p, li { white-space: pre-wrap; }
<translation>Später</translation>
</message>
</context>
<context>
<name>TagsMenu</name>
<message>
<location filename="../gui/msgs/TagsMenu.cpp" line="+106"/>
<source>Remove All Tags</source>
<translation>Alle Schlagwörter entfernen</translation>
</message>
<message>
<location line="+30"/>
<source>New tag ...</source>
<translation>Neues Schlagwort...</translation>
</message>
</context>
<context>
<name>TextPage</name>
<message>