diff --git a/libretroshare/src/rsiface/rsmsgs.h b/libretroshare/src/rsiface/rsmsgs.h index 79cd3b0e7..0bd560b17 100644 --- a/libretroshare/src/rsiface/rsmsgs.h +++ b/libretroshare/src/rsiface/rsmsgs.h @@ -47,7 +47,8 @@ #define RS_MSG_OUTBOX 0x03 /* Outbox */ #define RS_MSG_DRAFTBOX 0x05 /* Draftbox */ -#define RS_MSG_NEW 0x0010 +#define RS_MSG_NEW 0x0010 /* New */ +#define RS_MSG_TRASH 0x0020 /* Trash */ class MessageInfo { @@ -121,10 +122,11 @@ virtual ~RsMsgs() { return; } virtual bool getMessageSummaries(std::list &msgList) = 0; virtual bool getMessage(std::string mId, MessageInfo &msg) = 0; -virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox) = 0; +virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) = 0; virtual bool MessageSend(MessageInfo &info) = 0; virtual bool MessageToDraft(MessageInfo &info) = 0; +virtual bool MessageToTrash(std::string mid, bool bTrash) = 0; virtual bool MessageDelete(std::string mid) = 0; virtual bool MessageRead(std::string mid) = 0; diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index 0c3a1a1d1..7b33ab10c 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -62,9 +62,9 @@ bool p3Msgs::getMessage(std::string mid, MessageInfo &msg) return mMsgSrv->getMessage(mid, msg); } -void p3Msgs::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox) +void p3Msgs::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) { - mMsgSrv->getMessageCount(pnInbox, pnInboxNew, pnOutbox, pnDraftbox, pnSentbox); + mMsgSrv->getMessageCount(pnInbox, pnInboxNew, pnOutbox, pnDraftbox, pnSentbox, pnTrashbox); } /****************************************/ @@ -80,6 +80,11 @@ bool p3Msgs::MessageToDraft(MessageInfo &info) return mMsgSrv->MessageToDraft(info); } +bool p3Msgs::MessageToTrash(std::string mid, bool bTrash) +{ + return mMsgSrv->MessageToTrash(mid, bTrash); +} + /****************************************/ /****************************************/ bool p3Msgs::MessageDelete(std::string mid) diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h index 67d41e112..59976b452 100644 --- a/libretroshare/src/rsserver/p3msgs.h +++ b/libretroshare/src/rsserver/p3msgs.h @@ -55,10 +55,11 @@ class p3Msgs: public RsMsgs */ virtual bool getMessageSummaries(std::list &msgList); virtual bool getMessage(std::string mId, MessageInfo &msg); - virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox); + virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox); virtual bool MessageSend(MessageInfo &info); virtual bool MessageToDraft(MessageInfo &info); + virtual bool MessageToTrash(std::string mid, bool bTrash); virtual bool MessageDelete(std::string mid); virtual bool MessageRead(std::string mid); diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h index 96298ac30..d304a10a1 100644 --- a/libretroshare/src/serialiser/rsmsgitems.h +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -141,6 +141,7 @@ const uint32_t RS_MSG_FLAGS_OUTGOING = 0x0001; const uint32_t RS_MSG_FLAGS_PENDING = 0x0002; const uint32_t RS_MSG_FLAGS_DRAFT = 0x0004; const uint32_t RS_MSG_FLAGS_NEW = 0x0010; +const uint32_t RS_MSG_FLAGS_TRASH = 0x0020; class RsMsgItem: public RsItem { diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index f4650a1a6..58916350b 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -199,6 +199,9 @@ int p3MsgService::checkOutgoingMessages() std::map::iterator mit; for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) { + if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) { + continue; + } /* find the certificate */ std::string pid = mit->second->PeerId(); @@ -476,7 +479,7 @@ bool p3MsgService::getMessage(std::string mId, MessageInfo &msg) return true; } -void p3MsgService::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox) +void p3MsgService::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) { RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ @@ -485,6 +488,7 @@ void p3MsgService::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxN if (pnOutbox) *pnOutbox = 0; if (pnDraftbox) *pnDraftbox = 0; if (pnSentbox) *pnSentbox = 0; + if (pnTrashbox) *pnTrashbox = 0; std::map::iterator mit; std::map *apMsg [2] = { &imsg, &msgOutgoing }; @@ -494,6 +498,10 @@ void p3MsgService::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxN MsgInfoSummary mis; initRsMIS(mit->second, mis); + if (mis.msgflags & RS_MSG_TRASH) { + if (pnTrashbox) (*pnTrashbox)++; + continue; + } switch (mis.msgflags & RS_MSG_BOXMASK) { case RS_MSG_INBOX: if (pnInbox) (*pnInbox)++; @@ -661,8 +669,7 @@ bool p3MsgService::MessageToDraft(MessageInfo &info) { uint32_t msgId = 0; if (info.msgId.empty() == false) { - std::istringstream instream(info.msgId); - instream >> msgId; + msgId = atoi(info.msgId.c_str()); } if (msgId) { @@ -679,11 +686,13 @@ bool p3MsgService::MessageToDraft(MessageInfo &info) if (msgId) { // remove existing message - RsMsgItem *existingMsg = imsg[msgId]; - if (existingMsg) { - delete (existingMsg); + std::map::iterator mit; + mit = imsg.find(msgId); + if (mit != imsg.end()) { + RsMsgItem *mi = mit->second; + imsg.erase(mit); + delete mi; } - imsg.erase(msgId); } /* STORE MsgID */ imsg[msg->msgId] = msg; @@ -699,6 +708,58 @@ bool p3MsgService::MessageToDraft(MessageInfo &info) return false; } +/* move message to trash based on the unique mid */ +bool p3MsgService::MessageToTrash(std::string mid, bool bTrash) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mid.c_str()); + + bool bChanged = false; + bool bFound = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + RsMsgItem *mi = NULL; + + mit = imsg.find(msgId); + if (mit != imsg.end()) { + mi = mit->second; + } else { + mit = msgOutgoing.find(msgId); + if (mit != msgOutgoing.end()) { + mi = mit->second; + } + } + + if (mi) { + bFound = true; + + if (bTrash) { + if ((mi->msgFlags & RS_MSG_FLAGS_TRASH) == 0) { + mi->msgFlags |= RS_MSG_FLAGS_TRASH; + bChanged = true; + } + } else { + if (mi->msgFlags & RS_MSG_FLAGS_TRASH) { + mi->msgFlags &= ~RS_MSG_FLAGS_TRASH; + bChanged = true; + } + } + } + } + + if (bChanged) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + checkOutgoingMessages(); + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + } + + return bFound; +} + /****************************************/ /****************************************/ @@ -813,6 +874,10 @@ void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis) { mis.msgflags |= RS_MSG_NEW; } + if (msg->msgFlags & RS_MSG_FLAGS_TRASH) + { + mis.msgflags |= RS_MSG_TRASH; + } mis.srcId = msg->PeerId(); { diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h index 3284c1f78..a551eb072 100644 --- a/libretroshare/src/services/p3msgservice.h +++ b/libretroshare/src/services/p3msgservice.h @@ -57,14 +57,14 @@ bool getMessageNotifications(std::list ¬eList); bool getMessageSummaries(std::list &msgList); bool getMessage(std::string mid, MessageInfo &msg); -void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox); +void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox); bool removeMsgId(std::string mid); bool markMsgIdRead(std::string mid); bool MessageSend(MessageInfo &info); bool MessageToDraft(MessageInfo &info); - +bool MessageToTrash(std::string mid, bool bTrash); void loadWelcomeMsg(); /* startup message */ diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index e3a4c6353..f5034fef6 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -375,7 +375,7 @@ void MainWindow::updateStatus() rsPeers->getPeerCount (NULL, &online); unsigned int newInboxCount = 0; - rsMsgs->getMessageCount (NULL, &newInboxCount, NULL, NULL, NULL); + rsMsgs->getMessageCount (NULL, &newInboxCount, NULL, NULL, NULL, NULL); if(newInboxCount) messageAction->setIcon(QIcon(QPixmap(":/images/messages_new.png"))) ; diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp index d10a39cd8..c61b8c91d 100644 --- a/retroshare-gui/src/gui/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -53,6 +53,14 @@ #define COLUMN_CONTENT 7 #define COLUMN_TAGS 8 +#define ROW_INBOX 0 +#define ROW_OUTBOX 1 +#define ROW_DRAFTBOX 2 +#define ROW_SENTBOX 3 +#define ROW_TRASHBOX 4 +#define ROW_INBOX_TOTAL 6 +#define ROW_SENTBOX_TOTAL 7 + #define ACTION_TAGSINDEX_SIZE 3 #define ACTION_TAGSINDEX_TYPE "Type" #define ACTION_TAGSINDEX_ID "ID" @@ -270,6 +278,8 @@ MessagesDialog::MessagesDialog(QWidget *parent) // http://bugreports.qt.nokia.com/browse/QTBUG-8270 QShortcut *Shortcut = new QShortcut(QKeySequence (Qt::Key_Delete), ui.messagestreeView, 0, 0, Qt::WidgetShortcut); connect(Shortcut, SIGNAL(activated()), this, SLOT( removemessage ())); + Shortcut = new QShortcut(QKeySequence (Qt::SHIFT | Qt::Key_Delete), ui.messagestreeView, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT( removemessage ())); /* hide the Tree +/- */ ui.msgList->setRootIsDecorated( false ); @@ -330,7 +340,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) // fill folder list updateMessageSummaryList(); - ui.listWidget->setCurrentRow(0); + ui.listWidget->setCurrentRow(ROW_INBOX); #ifdef STATIC_MSGID // create tag menu @@ -724,6 +734,19 @@ void MessagesDialog::messageslistWidgetCostumPopupMenu( QPoint point ) connect( removemsgAct , SIGNAL( triggered() ), this, SLOT( removemessage() ) ); contextMnu.addAction( removemsgAct); + int listrow = ui.listWidget -> currentRow(); + if (listrow == ROW_TRASHBOX) { + QAction *undeleteAct = new QAction(tr( "Undelete" ), this ); + connect(undeleteAct, SIGNAL(triggered()), this, SLOT(undeletemessage())); + contextMnu.addAction(undeleteAct); + + if (nCount) { + undeleteAct->setEnabled(true); + } else { + undeleteAct->setDisabled(true); + } + } + contextMnu.addAction( ui.actionSave_as); contextMnu.addAction( ui.actionPrintPreview); contextMnu.addAction( ui.actionPrint); @@ -1124,20 +1147,24 @@ void MessagesDialog::insertMessages() /* check the mode we are in */ unsigned int msgbox = 0; + bool bTrash = false; bool bFill = true; switch(listrow) { - case 3: - msgbox = RS_MSG_SENTBOX; + case ROW_INBOX: + msgbox = RS_MSG_INBOX; break; - case 2: - msgbox = RS_MSG_DRAFTBOX; - break; - case 1: + case ROW_OUTBOX: msgbox = RS_MSG_OUTBOX; break; - case 0: - msgbox = RS_MSG_INBOX; + case ROW_DRAFTBOX: + msgbox = RS_MSG_DRAFTBOX; + break; + case ROW_SENTBOX: + msgbox = RS_MSG_SENTBOX; + break; + case ROW_TRASHBOX: + bTrash = true; break; default: bFill = false; @@ -1160,8 +1187,17 @@ void MessagesDialog::insertMessages() int nRow = 0; for (nRow = 0; nRow < nRowCount; ) { for(it = msgList.begin(); it != msgList.end(); it++) { - if ((it->msgflags & RS_MSG_BOXMASK) != msgbox) { - continue; + if (bTrash) { + if ((it->msgflags & RS_MSG_TRASH) == 0) { + continue; + } + } else { + if (it->msgflags & RS_MSG_TRASH) { + continue; + } + if ((it->msgflags & RS_MSG_BOXMASK) != msgbox) { + continue; + } } if (it->msgId == MessagesModel->item(nRow, COLUMN_MSGID)->text().toStdString()) { @@ -1197,11 +1233,17 @@ void MessagesDialog::insertMessages() * */ - if ((it -> msgflags & RS_MSG_BOXMASK) != msgbox) - { - //std::cerr << "Msg from other box: " << it->msgflags; - //std::cerr << std::endl; - continue; + if (bTrash) { + if ((it->msgflags & RS_MSG_TRASH) == 0) { + continue; + } + } else { + if (it->msgflags & RS_MSG_TRASH) { + continue; + } + if ((it->msgflags & RS_MSG_BOXMASK) != msgbox) { + continue; + } } bGotInfo = false; @@ -1760,23 +1802,48 @@ void MessagesDialog::removemessage() } } + bool bDelete = false; + int listrow = ui.listWidget -> currentRow(); + if (listrow == ROW_TRASHBOX) { + bDelete = true; + } else { + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { + bDelete = true; + } + } + for(QList::const_iterator it1(rowList.begin());it1!=rowList.end();++it1) { QString mid = MessagesModel->item((*it1),COLUMN_MSGID)->text(); - rsMsgs->MessageDelete(mid.toStdString()); + if (bDelete) { + rsMsgs->MessageDelete(mid.toStdString()); - // clean locale config - m_pConfig->beginGroup(CONFIG_SECTION_UNREAD); - m_pConfig->remove (mid); - m_pConfig->endGroup(); + // clean locale config + m_pConfig->beginGroup(CONFIG_SECTION_UNREAD); + m_pConfig->remove (mid); + m_pConfig->endGroup(); - // remove tag - m_pConfig->beginGroup(CONFIG_SECTION_TAG); - m_pConfig->remove (mid); - m_pConfig->endGroup(); + // remove tag + m_pConfig->beginGroup(CONFIG_SECTION_TAG); + m_pConfig->remove (mid); + m_pConfig->endGroup(); + } else { + rsMsgs->MessageToTrash(mid.toStdString(), true); + } + } + + insertMessages(); +} + +void MessagesDialog::undeletemessage() +{ + QList Rows; + getSelectedMsgCount (&Rows, NULL, NULL); + for (int nRow = 0; nRow < Rows.size(); nRow++) { + QString mid = MessagesModel->item (Rows [nRow], COLUMN_MSGID)->text(); + rsMsgs->MessageToTrash(mid.toStdString(), false); } insertMessages(); - return; } void MessagesDialog::print() @@ -1967,6 +2034,7 @@ void MessagesDialog::updateMessageSummaryList() unsigned int newDraftCount = 0; unsigned int newSentboxCount = 0; unsigned int inboxCount = 0; + unsigned int trashboxCount = 0; /* calculating the new messages */ // rsMsgs->getMessageCount (&inboxCount, &newInboxCount, &newOutboxCount, &newDraftCount, &newSentboxCount); @@ -1978,6 +2046,11 @@ void MessagesDialog::updateMessageSummaryList() /*calculating the new messages*/ for (it = msgList.begin(); it != msgList.end(); it++) { + if (it->msgflags & RS_MSG_TRASH) { + trashboxCount++; + continue; + } + switch (it->msgflags & RS_MSG_BOXMASK) { case RS_MSG_INBOX: inboxCount++; @@ -2010,7 +2083,7 @@ void MessagesDialog::updateMessageSummaryList() /*updating the labels in leftcolumn*/ //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const - QListWidgetItem* item = ui.listWidget->item(0); + QListWidgetItem* item = ui.listWidget->item(ROW_INBOX); if (newInboxCount != 0) { textItem = tr("Inbox") + " " + "(" + QString::number(newInboxCount)+")"; @@ -2033,7 +2106,7 @@ void MessagesDialog::updateMessageSummaryList() } //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const - item = ui.listWidget->item(1); + item = ui.listWidget->item(ROW_OUTBOX); if (newOutboxCount != 0) { textItem = tr("Outbox") + " " + "(" + QString::number(newOutboxCount)+")"; @@ -2053,7 +2126,7 @@ void MessagesDialog::updateMessageSummaryList() } //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const - item = ui.listWidget->item(2); + item = ui.listWidget->item(ROW_DRAFTBOX); if (newDraftCount != 0) { textItem = tr("Draft") + "(" + QString::number(newDraftCount)+")"; @@ -2072,13 +2145,25 @@ void MessagesDialog::updateMessageSummaryList() } + item = ui.listWidget->item(ROW_TRASHBOX); + if (trashboxCount != 0) + { + textItem = tr("Trash") + "(" + QString::number(trashboxCount)+")"; + item->setText(textItem); + } + else + { + textItem = tr("Trash"); + item->setText(textItem); + } + /* Total Inbox */ - item = ui.listWidget->item(5); + item = ui.listWidget->item(ROW_INBOX_TOTAL); textItem = tr("Total Inbox:") + " " + QString::number(inboxCount); item->setText(textItem); /* Total Sent */ - item = ui.listWidget->item(6); + item = ui.listWidget->item(ROW_SENTBOX_TOTAL); textItem = tr("Total Sent:") + " " + QString::number(newSentboxCount); item->setText(textItem); } diff --git a/retroshare-gui/src/gui/MessagesDialog.h b/retroshare-gui/src/gui/MessagesDialog.h index f740ec203..711bb84b5 100644 --- a/retroshare-gui/src/gui/MessagesDialog.h +++ b/retroshare-gui/src/gui/MessagesDialog.h @@ -88,6 +88,7 @@ private slots: bool fileSaveAs(); void removemessage(); + void undeletemessage(); #ifdef STATIC_MSGID void markAsRead(); diff --git a/retroshare-gui/src/gui/MessagesDialog.ui b/retroshare-gui/src/gui/MessagesDialog.ui index 0a35ed0c0..3d6a87872 100644 --- a/retroshare-gui/src/gui/MessagesDialog.ui +++ b/retroshare-gui/src/gui/MessagesDialog.ui @@ -1072,6 +1072,15 @@ border-image: url(:/images/closepressed.png) :/images/folder-sent.png:/images/folder-sent.png + + + Trash + + + + :/images/folder-trash.png:/images/folder-trash.png + + diff --git a/retroshare-gui/src/gui/feeds/MsgItem.cpp b/retroshare-gui/src/gui/feeds/MsgItem.cpp index 0fc6d50ae..43103fb6d 100644 --- a/retroshare-gui/src/gui/feeds/MsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/MsgItem.cpp @@ -223,7 +223,7 @@ void MsgItem::gotoHome() #endif } -/*********** SPECIFIC FUNCTIOSN ***********************/ +/*********** SPECIFIC FUNCTIONS ***********************/ void MsgItem::deleteMsg() diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index 7921412c4..caa2e3552 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -178,6 +178,7 @@ images/folder-inbox-new.png images/folder-outbox.png images/folder-sent.png + images/folder-trash.png images/folder_doments.png images/folder_green.png images/folder_red.png diff --git a/retroshare-gui/src/gui/images/folder-trash.png b/retroshare-gui/src/gui/images/folder-trash.png new file mode 100644 index 000000000..0712aaa71 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-trash.png differ