diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp index 0932e3378..237fb1c16 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.cpp +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.cpp @@ -25,6 +25,7 @@ #include #include "gui/Circles/CirclesDialog.h" +#include "gui/Circles/CreateCircleDialog.h" #include #include @@ -49,6 +50,7 @@ CirclesDialog::CirclesDialog(QWidget *parent) ui.setupUi(this); connect( ui.pushButton_refresh, SIGNAL(clicked()), this, SLOT(reloadAll())); + connect( ui.pushButton_circle, SIGNAL(clicked()), this, SLOT(create())); QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); @@ -84,6 +86,13 @@ void CirclesDialog::checkUpdate() #define CIRCLEGROUP_FRIEND_COL_NAME 0 #define CIRCLEGROUP_FRIEND_COL_ID 1 +void CirclesDialog::create() +{ + CreateCircleDialog *createDialog = new CreateCircleDialog(); + createDialog->show(); +} + + void CirclesDialog::reloadAll() { requestGroupMeta(); diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.h b/retroshare-gui/src/gui/Circles/CirclesDialog.h index 6fe5ce7a8..b037da8cf 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.h +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.h @@ -44,6 +44,8 @@ void loadRequest(const TokenQueue *queue, const TokenRequest &req); private slots: +void create(); + void checkUpdate(); void reloadAll(); diff --git a/retroshare-gui/src/gui/Circles/CirclesDialog.ui b/retroshare-gui/src/gui/Circles/CirclesDialog.ui index 8bac2a020..95eb89b0e 100644 --- a/retroshare-gui/src/gui/Circles/CirclesDialog.ui +++ b/retroshare-gui/src/gui/Circles/CirclesDialog.ui @@ -24,9 +24,9 @@ - + - Create Public Group + Create Circle diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp new file mode 100644 index 000000000..637a06117 --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.cpp @@ -0,0 +1,783 @@ +/* + * Retroshare Circles. + * + * Copyright 2012-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "gui/Circles/CreateCircleDialog.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#if 0 +#include "gui/settings/rsharesettings.h" +#include "gui/RetroShareLink.h" +#include "gui/common/Emoticons.h" + +#include "util/HandleRichText.h" +#include "util/misc.h" + +#include +#include +#endif + + +#define CREATECIRCLEDIALOG_CIRCLEINFO 2 +#define CREATECIRCLEDIALOG_IDINFO 3 + +#define RSCIRCLEID_COL_NICKNAME 0 +#define RSCIRCLEID_COL_KEYID 1 +#define RSCIRCLEID_COL_IDTYPE 2 + + + +/** Constructor */ +CreateCircleDialog::CreateCircleDialog() +: QDialog(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + + /* Setup Queue */ + mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this); + mIdQueue = new TokenQueue(rsIdentity->getTokenService(), this); + + //QString text = pId.empty() ? tr("Start New Thread") : tr("Post Forum Message"); + //setWindowTitle(text); + //Settings->loadWidgetInformation(this); + + //connect(ui.forumMessage, SIGNAL( customContextMenuRequested(QPoint)), this, SLOT(forumMessageCostumPopupMenu(QPoint))); + //connect(ui.hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); + + // connect up the buttons. + connect(ui.addButton, SIGNAL(clicked()), this, SLOT(addMember())); + connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(removeMember())); + + //connect(ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); + //connect(ui.attachFileButton, SIGNAL(clicked()), this, SLOT(addFile())); + //connect(ui.pastersButton, SIGNAL(clicked()), this, SLOT(pasteLink())); + + connect(ui.treeWidget_membership, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectedMember(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(ui.treeWidget_IdList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectedId(QTreeWidgetItem*, QTreeWidgetItem*))); + + ui.removeButton->setEnabled(false); + ui.addButton->setEnabled(false); + ui.radioButton_ListAll->setChecked(true); + requestIdentities(); +} + + + +CreateCircleDialog::~CreateCircleDialog() +{ + delete(mCircleQueue); + delete(mIdQueue); +} + + +void CreateCircleDialog::selectedId(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous); + ui.addButton->setEnabled(current != NULL); +} + +void CreateCircleDialog::selectedMember(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous); + ui.removeButton->setEnabled(current != NULL); +} + + +#if 0 +#define CREATEGXSFORUMMSG_FORUMINFO 1 +#define CREATEGXSFORUMMSG_PARENTMSG 2 + + +/** Constructor */ +CreateCircleDialog::CreateCircleDialog(const std::string &fId, const std::string &pId) +: QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), mForumId(fId), mParentId(pId) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + + /* Setup Queue */ + mForumQueue = new TokenQueue(rsGxsForums->getTokenService(), this); + + QString text = pId.empty() ? tr("Start New Thread") : tr("Post Forum Message"); + setWindowTitle(text); + + ui.headerFrame->setHeaderImage(QPixmap(":/images/konversation64.png")); + ui.headerFrame->setHeaderText(text); + + Settings->loadWidgetInformation(this); + + connect(ui.forumMessage, SIGNAL( customContextMenuRequested(QPoint)), this, SLOT(forumMessageCostumPopupMenu(QPoint))); + + connect(ui.hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); + + // connect up the buttons. + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(createMsg())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); + connect(ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); + connect(ui.attachFileButton, SIGNAL(clicked()), this, SLOT(addFile())); + connect(ui.pastersButton, SIGNAL(clicked()), this, SLOT(pasteLink())); + + setAcceptDrops(true); + ui.hashBox->setDropWidget(this); + ui.hashBox->setAutoHide(false); + + mParentMsgLoaded = false; + mForumMetaLoaded = false; + + newMsg(); +} + +CreateCircleDialog::~CreateCircleDialog() +{ + delete(mForumQueue); +} + +void CreateCircleDialog::forumMessageCostumPopupMenu(QPoint point) +{ + QMenu *contextMnu = ui.forumMessage->createStandardContextMenu(point); + + contextMnu->addSeparator(); + + QAction *pasteLinkAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + QAction *pasteLinkFullAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste full RetroShare Link"), this, SLOT(pasteLinkFull())); + contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste my certificate link"), this, SLOT(pasteOwnCertificateLink())); + + if (RSLinkClipboard::empty()) { + pasteLinkAct->setDisabled (true); + pasteLinkFullAct->setDisabled (true); + } + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void CreateCircleDialog::newMsg() +{ + /* clear all */ + mParentMsgLoaded = false; + mForumMetaLoaded = false; + + /* fill in the available OwnIds for signing */ + ui.idChooser->loadIds(IDCHOOSER_ID_REQUIRED, ""); + + /* lock gui */ + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + ui.innerFrame->setEnabled(false); + + if (mForumId.empty()) { + ui.forumName->setText(tr("No Forum")); + return; + } + ui.forumName->setText(tr("Loading")); + + /* request Data */ + { + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; + + std::list groupIds; + groupIds.push_back(mForumId); + + std::cerr << "ForumsV2Dialog::newMsg() Requesting Group Summary(" << mForumId << ")"; + std::cerr << std::endl; + + uint32_t token; + mForumQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, groupIds, CREATEGXSFORUMMSG_FORUMINFO); + } + + if (mParentId.empty()) + { + mParentMsgLoaded = true; + } + else + { + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; + + GxsMsgReq msgIds; + std::vector &vect = msgIds[mForumId]; + vect.push_back(mParentId); + + std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")"; + std::cerr << std::endl; + + uint32_t token; + mForumQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, CREATEGXSFORUMMSG_PARENTMSG); + } +} + +void CreateCircleDialog::saveForumInfo(const RsGroupMetaData &meta) +{ + mForumMeta = meta; + mForumMetaLoaded = true; + + loadFormInformation(); +} + +void CreateCircleDialog::saveParentMsg(const RsGxsForumMsg &msg) +{ + mParentMsg = msg; + mParentMsgLoaded = true; + + loadFormInformation(); +} + +void CreateCircleDialog::loadFormInformation() +{ + if ((!mParentMsgLoaded) && (!mParentId.empty())) + { + std::cerr << "CreateCircleDialog::loadMsgInformation() ParentMsg not Loaded Yet"; + std::cerr << std::endl; + return; + } + + if (!mForumMetaLoaded) + { + std::cerr << "CreateCircleDialog::loadMsgInformation() ForumMeta not Loaded Yet"; + std::cerr << std::endl; + return; + } + + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + ui.innerFrame->setEnabled(true); + + std::cerr << "CreateCircleDialog::loadMsgInformation() Data Available!"; + std::cerr << std::endl; + + QString name = QString::fromUtf8(mForumMeta.mGroupName.c_str()); + QString subj; + if (!mParentId.empty()) + { + QString title = QString::fromUtf8(mParentMsg.mMeta.mMsgName.c_str()); + name += " " + tr("In Reply to") + ": "; + name += title; + + QString text = title; + + if (text.startsWith("Re:", Qt::CaseInsensitive)) + { + subj = title; + } + else + { + subj = "Re: " + title; + } + } + + ui.forumName->setText(misc::removeNewLine(name)); + ui.forumSubject->setText(misc::removeNewLine(subj)); + + if (ui.forumSubject->text().isEmpty()) + { + ui.forumSubject->setFocus(); + } + else + { + ui.forumMessage->setFocus(); + } + +#ifdef TOGXS + if (mForumMeta.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) +#else + if (1) +#endif + { + ui.signBox->setChecked(true); + ui.signBox->setEnabled(false); + } + else + { + /* Uncheck sign box by default for anonymous forums */ + ui.signBox->setChecked(false); + ui.signBox->setEnabled(true); + } + + ui.forumMessage->setText(""); +} + +void CreateCircleDialog::createMsg() +{ + QString name = misc::removeNewLine(ui.forumSubject->text()); + QString desc; + + RsHtml::optimizeHtml(ui.forumMessage, desc); + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please set a Forum Subject and Forum Message"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty Subject!! + } + + RsGxsForumMsg msg; + msg.mMeta.mGroupId = mForumId; + msg.mMeta.mParentId = mParentId; + msg.mMeta.mMsgId = ""; + if (mParentMsgLoaded) + { + msg.mMeta.mThreadId = mParentMsg.mMeta.mThreadId; + } + + msg.mMeta.mMsgName = std::string(name.toUtf8()); + msg.mMsg = std::string(desc.toUtf8()); +#ifdef TOGXS + msg.mMeta.mMsgFlags = RS_DISTRIB_AUTHEN_REQ; +#endif + + if ((msg.mMsg == "") && (msg.mMeta.mMsgName == "")) + return; /* do nothing */ + + if (ui.signBox->isChecked()) + { + RsGxsId authorId; + if (ui.idChooser->getChosenId(authorId)) + { + msg.mMeta.mAuthorId = authorId; + std::cerr << "CreateCircleDialog::createMsg() AuthorId: " << authorId; + std::cerr << std::endl; + } + else + { + std::cerr << "CreateCircleDialog::createMsg() ERROR GETTING AuthorId!"; + std::cerr << std::endl; + QMessageBox::warning(this, tr("RetroShare"),tr("Please choose Signing Id"), + QMessageBox::Ok, QMessageBox::Ok); + + return; + } + } + else + { + std::cerr << "CreateCircleDialog::createMsg() No Signature (for now :)"; + std::cerr << std::endl; + QMessageBox::warning(this, tr("RetroShare"),tr("Please choose Signing Id, it is required"), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + uint32_t token; + rsGxsForums->createMsg(token, msg); + close(); +} + +void CreateCircleDialog::closeEvent (QCloseEvent * /*event*/) +{ + Settings->saveWidgetInformation(this); +} + +void CreateCircleDialog::smileyWidgetForums() +{ + Emoticons::showSmileyWidget(this, ui.emoticonButton, SLOT(addSmileys()), false); +} + +void CreateCircleDialog::addSmileys() +{ + ui.forumMessage->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +void CreateCircleDialog::addFile() +{ + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + ui.hashBox->addAttachments(files,RS_FILE_REQ_ANONYMOUS_ROUTING); + } +} + +void CreateCircleDialog::fileHashingFinished(QList hashedFiles) +{ + std::cerr << "CreateCircleDialog::fileHashingFinished() started." << std::endl; + + QString mesgString; + + QList::iterator it; + for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) { + HashedFile& hashedFile = *it; + RetroShareLink link; + if (link.createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash))) { + mesgString += link.toHtmlSize() + "
"; + } + } + +#ifdef CHAT_DEBUG + std::cerr << "CreateCircleDialog::anchorClicked mesgString : " << mesgString.toStdString() << std::endl; +#endif + + if (!mesgString.isEmpty()) { + ui.forumMessage->textCursor().insertHtml(mesgString); + } + + ui.forumMessage->setFocus( Qt::OtherFocusReason ); +} + +void CreateCircleDialog::pasteLink() +{ + ui.forumMessage->insertHtml(RSLinkClipboard::toHtml()) ; +} + +void CreateCircleDialog::pasteLinkFull() +{ + ui.forumMessage->insertHtml(RSLinkClipboard::toHtmlFull()) ; +} + +void CreateCircleDialog::pasteOwnCertificateLink() +{ + RetroShareLink link ; + std::string ownId = rsPeers->getOwnId() ; + if( link.createCertificate(ownId) ) { + ui.forumMessage->insertHtml(link.toHtml() + " "); + } +} + +void CreateCircleDialog::loadForumInfo(const uint32_t &token) +{ + std::cerr << "CreateCircleDialog::loadForumInfo()"; + std::cerr << std::endl; + + std::list groupInfo; + rsGxsForums->getGroupSummary(token, groupInfo); + + if (groupInfo.size() == 1) + { + RsGroupMetaData fi = groupInfo.front(); + saveForumInfo(fi); + } + else + { + std::cerr << "CreateCircleDialog::loadForumInfo() ERROR INVALID Number of Forums"; + std::cerr << std::endl; + } +} + +void CreateCircleDialog::loadParentMsg(const uint32_t &token) +{ + std::cerr << "CreateCircleDialog::loadParentMsg()"; + std::cerr << std::endl; + + // Only grab one.... ignore more (shouldn't be any). + std::vector msgs; + if (rsGxsForums->getMsgData(token, msgs)) + { + if (msgs.size() != 1) + { + /* error */ + std::cerr << "CreateCircleDialog::loadParentMsg() ERROR wrong number of msgs"; + std::cerr << std::endl; + } + saveParentMsg(msgs[0]); + } +} + +void CreateCircleDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "CreateCircleDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue == mForumQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case CREATEGXSFORUMMSG_FORUMINFO: + loadForumInfo(req.mToken); + break; + case CREATEGXSFORUMMSG_PARENTMSG: + loadParentMsg(req.mToken); + break; + default: + std::cerr << "CreateCircleDialog::loadRequest() UNKNOWN UserType "; + std::cerr << std::endl; + + } + } +} +#endif + + +void CreateCircleDialog::addMember() +{ + QTreeWidgetItem *item = ui.treeWidget_IdList->currentItem(); + if (!item) + { + return; + } + QTreeWidgetItem *member = new QTreeWidgetItem(); + member->setText(RSCIRCLEID_COL_NICKNAME, item->text(RSCIRCLEID_COL_NICKNAME)); + member->setText(RSCIRCLEID_COL_KEYID, item->text(RSCIRCLEID_COL_KEYID)); + member->setText(RSCIRCLEID_COL_IDTYPE, item->text(RSCIRCLEID_COL_IDTYPE)); + + ui.treeWidget_membership->addTopLevelItem(member); + +} + + +void CreateCircleDialog::removeMember() +{ + QTreeWidgetItem *item = ui.treeWidget_membership->currentItem(); + if (!item) + { + return; + } + + // does this just work? + delete(item); +} + + + +void CreateCircleDialog::createCircle() +{ + QString name = ui.circleName->text(); + QString desc; + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please set a Name your Circle"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty Subject!! + } + + RsGxsCircleGroup circle; + + circle.mMeta.mGroupName = std::string(name.toUtf8()); + + RsGxsId authorId; + if (ui.idChooser->getChosenId(authorId)) + { + circle.mMeta.mAuthorId = authorId; + std::cerr << "CreateCircleDialog::createCircle() AuthorId: " << authorId; + std::cerr << std::endl; + } + else + { + std::cerr << "CreateCircleDialog::createCircle() No AuthorId Chosen!"; + std::cerr << std::endl; + } + + + /* copy Ids from GUI */ + + + + uint32_t token; + rsGxsCircles->createGroup(token, circle); + close(); +} + + + +void CreateCircleDialog::requestCircle(const RsGxsGroupId &groupId) +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::list groupIds; + groupIds.push_back(groupId); + + std::cerr << "CreateCircleDialog::requestCircle() Requesting Group Summary(" << groupId << ")"; + std::cerr << std::endl; + + uint32_t token; + mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds, CREATECIRCLEDIALOG_CIRCLEINFO); +} + +void CreateCircleDialog::loadCircle(uint32_t token) +{ + std::cerr << "CreateCircleDialog::loadCircle(" << token << ")"; + std::cerr << std::endl; + + QTreeWidget *tree = ui.treeWidget_membership; + + tree->clear(); + + std::list ids; + std::list::iterator it; + + RsGxsIdGroup data; + std::vector groups; + if (!rsGxsCircles->getGroupData(token, groups)) + { + std::cerr << "CreateCircleDialog::loadCircle() Error getting GroupData"; + std::cerr << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "CreateCircleDialog::loadCircle() Error Group.size() != 1"; + std::cerr << std::endl; + return; + } + + std::cerr << "CreateCircleDialog::loadCircle() Unfinished Loading"; + std::cerr << std::endl; + + //mCircleGroup = groups[0]; +} + + +void CreateCircleDialog::requestIdentities() +{ + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + + std::cerr << "CreateCircleDialog::requestIdentities()"; + std::cerr << std::endl; + + uint32_t token; + mIdQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, CREATECIRCLEDIALOG_IDINFO); +} + + + + + +void CreateCircleDialog::loadIdentities(uint32_t token) +{ + std::cerr << "CreateCircleDialog::loadIdentities(" << token << ")"; + std::cerr << std::endl; + + QTreeWidget *tree = ui.treeWidget_IdList; + + tree->clear(); + + std::list ids; + std::list::iterator it; + + bool acceptAll = ui.radioButton_ListAll->isChecked(); + bool acceptAllPGP = ui.radioButton_ListAllPGP->isChecked(); + bool acceptKnownPGP = ui.radioButton_ListKnownPGP->isChecked(); + + RsGxsIdGroup data; + std::vector datavector; + std::vector::iterator vit; + if (!rsIdentity->getGroupData(token, datavector)) + { + std::cerr << "CreateCircleDialog::insertIdentities() Error getting GroupData"; + std::cerr << std::endl; + return; + } + + for(vit = datavector.begin(); vit != datavector.end(); vit++) + { + data = (*vit); + + /* do filtering */ + bool ok = false; + if (acceptAll) + { + ok = true; + } + else if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (acceptAllPGP) + { + ok = true; + } + else if (data.mPgpKnown) + { + ok = true; + } + } + + if (!ok) + { + std::cerr << "CreateCircleDialog::insertIdentities() Skipping ID: " << data.mMeta.mGroupId; + std::cerr << std::endl; + continue; + } + + + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(RSCIRCLEID_COL_NICKNAME, QString::fromStdString(data.mMeta.mGroupName)); + item->setText(RSCIRCLEID_COL_KEYID, QString::fromStdString(data.mMeta.mGroupId)); + if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) + { + if (data.mPgpKnown) + { + RsPeerDetails details; + rsPeers->getGPGDetails(data.mPgpId, details); + item->setText(RSCIRCLEID_COL_IDTYPE, QString::fromStdString(details.name)); + } + else + { + item->setText(RSCIRCLEID_COL_IDTYPE, "PGP Linked Id"); + } + } + else + { + item->setText(RSCIRCLEID_COL_IDTYPE, "Anon Id"); + } + tree->addTopLevelItem(item); + } +} + + + +void CreateCircleDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) +{ + std::cerr << "CreateCircleDialog::loadRequest() UserType: " << req.mUserType; + std::cerr << std::endl; + + if (queue == mCircleQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case CREATECIRCLEDIALOG_CIRCLEINFO: + loadCircle(req.mToken); + break; + default: + std::cerr << "CreateCircleDialog::loadRequest() UNKNOWN UserType "; + std::cerr << std::endl; + + } + } + + if (queue == mIdQueue) + { + /* now switch on req */ + switch(req.mUserType) + { + case CREATECIRCLEDIALOG_IDINFO: + loadIdentities(req.mToken); + break; + default: + std::cerr << "CreateCircleDialog::loadRequest() UNKNOWN UserType "; + std::cerr << std::endl; + + } + } +} diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.h b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h new file mode 100644 index 000000000..7ce292c71 --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.h @@ -0,0 +1,112 @@ +/* + * Retroshare Circles. + * + * Copyright 2012-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_CREATE_CIRCLE_DIALOG_H +#define MRK_CREATE_CIRCLE_DIALOG_H + +#include "ui_CreateCircleDialog.h" + +#include "util/TokenQueue.h" + +#include +#include + +class CreateCircleDialog : public QDialog, public TokenResponse +{ + Q_OBJECT + +public: + CreateCircleDialog(); + ~CreateCircleDialog(); + +#if 0 + void newMsg(); /* cleanup */ +#endif + + virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req); + +private slots: + + void addMember(); + void removeMember(); + + void selectedId(QTreeWidgetItem*, QTreeWidgetItem*); + void selectedMember(QTreeWidgetItem*, QTreeWidgetItem*); + +#if 0 + /** Create the context popup menu and it's submenus */ + void forumMessageCostumPopupMenu( QPoint point ); + + void fileHashingFinished(QList hashedFiles); + /* actions to take.... */ + void createMsg(); + void pasteLink(); + void pasteLinkFull(); + void pasteOwnCertificateLink(); + + void smileyWidgetForums(); + void addSmileys(); + void addFile(); +#endif + +protected: + +#if 0 + void closeEvent (QCloseEvent * event); +#endif + +private: + +#if 0 + void saveForumInfo(const RsGroupMetaData &meta); + void saveParentMsg(const RsGxsForumMsg &msg); + void loadFormInformation(); + + void loadForumInfo(const uint32_t &token); + void loadParentMsg(const uint32_t &token); + + std::string mForumId; + std::string mParentId; + + bool mParentMsgLoaded; + bool mForumMetaLoaded; + RsGxsForumMsg mParentMsg; + RsGroupMetaData mForumMeta; +#endif + + void createCircle(); + + void loadCircle(uint32_t token); + void loadIdentities(uint32_t token); + + void requestCircle(const RsGxsGroupId &groupId); + void requestIdentities(); + + TokenQueue *mCircleQueue; + TokenQueue *mIdQueue; + + /** Qt Designer generated object */ + Ui::CreateCircleDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui new file mode 100644 index 000000000..005a1d28c --- /dev/null +++ b/retroshare-gui/src/gui/Circles/CreateCircleDialog.ui @@ -0,0 +1,299 @@ + + + CreateCircleDialog + + + + 0 + 0 + 746 + 568 + + + + + + + + + + Circle Details + + + + + + + + + 75 + true + + + + Name + + + + + + + + + + + 75 + true + + + + Creator + + + + + + + + + + + + + + + 75 + true + + + + Distribution + + + + + + + Public + + + + + + + Self-Restricted + + + + + + + Restricted to: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Circle Membership + + + + + + + Name + + + + + IDs + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 188 + + + + + + + + << Add + + + + + + + >> Remove + + + + + + + Qt::Vertical + + + + 20 + 178 + + + + + + + + + + Known Identities + + + + + + + + All IDs + + + + + + + All PGP IDs + + + + + + + Known PGP + + + + + + + + + + + Filter + + + + + + + + + + + + + Nickname + + + + + ID + + + + + Type + + + + + + + + + + + + + Qt::Horizontal + + + + 418 + 20 + + + + + + + + Cancel + + + + + + + Create Group + + + + + + + + + + GxsIdChooser + QComboBox +
gui/gxs/GxsIdChooser.h
+
+ + GxsCircleChooser + QComboBox +
gui/gxs/GxsCircleChooser.h
+
+
+ + + + +
diff --git a/retroshare-gui/src/gui/GxsForumsDialog.cpp b/retroshare-gui/src/gui/GxsForumsDialog.cpp index 162c40bc4..de4263d1d 100644 --- a/retroshare-gui/src/gui/GxsForumsDialog.cpp +++ b/retroshare-gui/src/gui/GxsForumsDialog.cpp @@ -321,12 +321,20 @@ void GxsForumsDialog::insertForumsData(const std::list &forumLi GroupItemInfo groupItemInfo; forumInfoToGroupItemInfo(*it, groupItemInfo); - if (IS_GROUP_ADMIN(flags)) { - adminList.push_back(groupItemInfo); - } else if (IS_GROUP_SUBSCRIBED(flags)) { - /* subscribed forum */ - subList.push_back(groupItemInfo); - } else { + if (IS_GROUP_SUBSCRIBED(flags)) + { + if (IS_GROUP_ADMIN(flags)) + { + adminList.push_back(groupItemInfo); + } + else + { + /* subscribed forum */ + subList.push_back(groupItemInfo); + } + } + else + { /* rate the others by popularity */ popMap.insert(std::make_pair(it->mPop, groupItemInfo)); } diff --git a/retroshare-gui/src/gui/Posted/PostedListDialog.cpp b/retroshare-gui/src/gui/Posted/PostedListDialog.cpp index 4d7b7f377..2a18c51bc 100644 --- a/retroshare-gui/src/gui/Posted/PostedListDialog.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListDialog.cpp @@ -95,6 +95,8 @@ PostedListDialog::PostedListDialog(QWidget *parent) connect( ui.newTopicButton, SIGNAL( clicked() ), this, SLOT( newTopic() ) ); connect(ui.refreshButton, SIGNAL(clicked()), this, SLOT(refreshTopics())); connect(ui.submitPostButton, SIGNAL(clicked()), this, SLOT(newPost())); + + refreshTopics(); } void PostedListDialog::getRankings() @@ -182,10 +184,25 @@ void PostedListDialog::refreshTopics() void PostedListDialog::groupListCustomPopupMenu( QPoint /*point*/ ) { - QMenu contextMnu( this ); + if (mCurrTopicId.empty()) + { + return; + } + + uint32_t subscribeFlags = ui.groupTreeWidget->subscribeFlags(QString::fromStdString(mCurrTopicId)); + + QMenu contextMnu(this); + + //bool isAdmin = IS_GROUP_ADMIN(subscribeFlags); + //bool isPublisher = IS_GROUP_PUBLISHER(subscribeFlags); + bool isSubscribed = IS_GROUP_SUBSCRIBED(subscribeFlags); QAction *action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Submit Post"), this, SLOT(newPost())); - action->setDisabled (mCurrTopicId.empty()); + action->setEnabled(isSubscribed); + action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Subscribe"), this, SLOT(subscribeTopic())); + action->setEnabled(!isSubscribed); + action = contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("Unsubscribe"), this, SLOT(unsubscribeTopic())); + action->setEnabled(isSubscribed); contextMnu.exec(QCursor::pos()); } @@ -195,10 +212,54 @@ void PostedListDialog::newPost() if(mCurrTopicId.empty()) return; - PostedCreatePostDialog cp(mPostedQueue, rsPosted, mCurrTopicId, this); - cp.exec(); + uint32_t subscribeFlags = ui.groupTreeWidget->subscribeFlags(QString::fromStdString(mCurrTopicId)); + bool isSubscribed = IS_GROUP_SUBSCRIBED(subscribeFlags); + + if (isSubscribed) + { + PostedCreatePostDialog cp(mPostedQueue, rsPosted, mCurrTopicId, this); + cp.exec(); + } } + +void PostedListDialog::unsubscribeTopic() +{ + std::cerr << "PostedListDialog::unsubscribeTopic()"; + std::cerr << std::endl; + + if(mCurrTopicId.empty()) + return; + + uint32_t token; + rsPosted->subscribeToGroup(token, mCurrTopicId, false); + mPostedQueue->queueRequest(token, 0 , RS_TOKREQ_ANSTYPE_ACK, TOKEN_USER_TYPE_SUBSCRIBE_CHANGE); +} + + +void PostedListDialog::subscribeTopic() +{ + std::cerr << "PostedListDialog::subscribeTopic()"; + std::cerr << std::endl; + + if(mCurrTopicId.empty()) + return; + + uint32_t token; + rsPosted->subscribeToGroup(token, mCurrTopicId, true); + mPostedQueue->queueRequest(token, 0 , RS_TOKREQ_ANSTYPE_ACK, TOKEN_USER_TYPE_SUBSCRIBE_CHANGE); +} + + + + + + + + + + + void PostedListDialog::submitVote(const RsGxsGrpMsgIdPair &msgId, bool up) { #if 0 @@ -386,12 +447,12 @@ void PostedListDialog::loadGroupSummary(const uint32_t &token) if (groupInfo.size() > 0) { - insertGroupData(groupInfo); + insertGroupData(groupInfo); } else { - std::cerr << "PostedListDialog::loadGroupSummary() ERROR No Groups..."; - std::cerr << std::endl; + std::cerr << "PostedListDialog::loadGroupSummary() ERROR No Groups..."; + std::cerr << std::endl; } } @@ -637,6 +698,19 @@ void PostedListDialog::updateCurrentDisplayComplete(const uint32_t &token) } } + +void PostedListDialog::acknowledgeSubscribeChange(const uint32_t &token) +{ + std::cerr << "PostedListDialog::acknowledgeSubscribeChange()"; + std::cerr << std::endl; + + std::vector posts; + RsGxsGroupId groupId; + rsPosted->acknowledgeGrp(token, groupId); + + refreshTopics(); +} + /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ @@ -709,6 +783,8 @@ void PostedListDialog::loadRequest(const TokenQueue *queue, const TokenRequest & std::cerr << "Error, unexpected anstype:" << req.mAnsType << std::endl; break; } + case TOKEN_USER_TYPE_SUBSCRIBE_CHANGE: + acknowledgeSubscribeChange(req.mToken); break; default: std::cerr << "PostedListDialog::loadRequest() ERROR: INVALID TYPE"; @@ -746,6 +822,7 @@ void PostedListDialog::groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo //groupItemInfo.description = QString::fromUtf8(groupInfo.forumDesc); groupItemInfo.popularity = groupInfo.mPop; groupItemInfo.lastpost = QDateTime::fromTime_t(groupInfo.mLastPost); + groupItemInfo.subscribeFlags = groupInfo.mSubscribeFlags; } @@ -761,23 +838,30 @@ void PostedListDialog::insertGroupData(const std::list &groupLi QList otherList; std::multimap popMap; - for (it = groupList.begin(); it != groupList.end(); it++) { + for (it = groupList.begin(); it != groupList.end(); it++) + { /* sort it into Publish (Own), Subscribed, Popular and Other */ uint32_t flags = it->mSubscribeFlags; - GroupItemInfo groupItemInfo; - groupInfoToGroupItemInfo(*it, groupItemInfo); + GroupItemInfo groupItemInfo; + groupInfoToGroupItemInfo(*it, groupItemInfo); - // if (flags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { - adminList.push_back(groupItemInfo); - // } else if (flags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { - /* subscribed forum */ - // subList.push_back(groupItemInfo); - // } else { - /* rate the others by popularity */ -// popMap.insert(std::make_pair(it->mPop, groupItemInfo)); + if (IS_GROUP_SUBSCRIBED(flags)) + { + if (IS_GROUP_ADMIN(flags) || IS_GROUP_PUBLISHER(flags)) + { + adminList.push_back(groupItemInfo); + } + else + { + subList.push_back(groupItemInfo); + } } -// } + else + { + popMap.insert(std::make_pair(it->mPop, groupItemInfo)); + } + } /* iterate backwards through popMap - take the top 5 or 10% of list */ uint32_t popCount = 5; diff --git a/retroshare-gui/src/gui/Posted/PostedListDialog.h b/retroshare-gui/src/gui/Posted/PostedListDialog.h index 60489ff5c..7f214f26d 100644 --- a/retroshare-gui/src/gui/Posted/PostedListDialog.h +++ b/retroshare-gui/src/gui/Posted/PostedListDialog.h @@ -80,6 +80,9 @@ private slots: void getRankings(); + void subscribeTopic(); + void unsubscribeTopic(); + private: void clearPosts(); @@ -101,6 +104,9 @@ private: void loadGroupSummary_CurrentForum(const uint32_t &token); + // subscribe/unsubscribe ack. + void acknowledgeSubscribeChange(const uint32_t &token); + // posts void acknowledgePostMsg(const uint32_t &token); void loadPostData(const uint32_t &token); diff --git a/retroshare-gui/src/gui/Posted/PostedUserTypes.h b/retroshare-gui/src/gui/Posted/PostedUserTypes.h index e802ae986..c772ee8c6 100644 --- a/retroshare-gui/src/gui/Posted/PostedUserTypes.h +++ b/retroshare-gui/src/gui/Posted/PostedUserTypes.h @@ -6,5 +6,6 @@ #define TOKEN_USER_TYPE_TOPIC 6 #define TOKEN_USER_TYPE_POST_MOD 7 #define TOKEN_USER_TYPE_POST_RANKINGS 8 +#define TOKEN_USER_TYPE_SUBSCRIBE_CHANGE 9 #endif // POSTEDUSERTYPES_H diff --git a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp index d87e767c3..579998eaf 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupDialog.cpp @@ -352,7 +352,7 @@ void GxsGroupDialog::createGroup() meta.mSignFlags = getGroupSignFlags(); setCircleParameters(meta); - ui.idChooser->getChosenId(meta.mAuthorId); + ui.idChooser->getChosenId(meta.mAuthorId); if (service_CreateGroup(token, meta)) { diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp index 094a962e7..631380d6d 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp @@ -64,6 +64,14 @@ #define USE_THREAD + +#define TOKEN_TYPE_GROUP_CHANGE 1 // THIS MUST MIRROR GxsGroupDialog parameters. + +#define TOKEN_TYPE_MESSAGE_CHANGE 4 +#define TOKEN_TYPE_LISTING 5 +#define TOKEN_TYPE_GROUP_DATA 6 +#define TOKEN_TYPE_POSTS 7 + /** Constructor */ GxsChannelDialog::GxsChannelDialog(QWidget *parent) : RsAutoUpdatePage(1000,parent), GxsServiceDialog(dynamic_cast(parent)) @@ -112,7 +120,7 @@ GxsChannelDialog::GxsChannelDialog(QWidget *parent) /* load settings */ processSettings(true); - //updateChannelMsgs(); + insertChannels(); } GxsChannelDialog::~GxsChannelDialog() @@ -122,6 +130,49 @@ GxsChannelDialog::~GxsChannelDialog() } +void GxsChannelDialog::updateDisplay() +{ + if (!rsGxsChannels) + return; + + std::list groupIds; + std::map > msgs; + + if (rsGxsChannels->updated(true, true)) + { + /* update Forums List */ + + rsGxsChannels->groupsChanged(groupIds); + if(!groupIds.empty()) + { + // just always update. + insertChannels(); + //std::list::iterator it = std::find(groupIds.begin(), groupIds.end(), mChannelId); + + //if(it != groupIds.end()){ + // requestGroupSummary(); + // return; + //} + } + + rsGxsChannels->msgsChanged(msgs); + if(!msgs.empty()) + { + std::map >::iterator mit = msgs.find(mChannelId); + if(mit != msgs.end()) + { + requestPosts(mChannelId); + } + } + } +} + + + + + + + // Callback from Widget->FeedHolder->ServiceDialog->CommentContainer->CommentDialog, void GxsChannelDialog::openComments(uint32_t type, const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title) { @@ -419,18 +470,6 @@ void GxsChannelDialog::selectChannel(const QString &id) //updateChannelMsgs(); } -void GxsChannelDialog::updateDisplay() -{ - if (!rsGxsChannels) { - return; - } - - if (rsGxsChannels->updated()) - { - insertChannels(); - } -} - void GxsChannelDialog::forceUpdateDisplay() { std::cerr << "GxsChannelDialog::forceUpdateDisplay()"; @@ -468,12 +507,20 @@ void GxsChannelDialog::insertChannelData(const std::list &chann GroupItemInfo groupItemInfo; channelInfoToGroupItemInfo(*it, groupItemInfo); - if (IS_GROUP_ADMIN(flags)) { - adminList.push_back(groupItemInfo); - } else if (IS_GROUP_SUBSCRIBED(flags)) { - /* subscribed forum */ - subList.push_back(groupItemInfo); - } else { + if (IS_GROUP_SUBSCRIBED(flags)) + { + if (IS_GROUP_ADMIN(flags) || IS_GROUP_PUBLISHER(flags)) + { + adminList.push_back(groupItemInfo); + } + else + { + /* subscribed forum */ + subList.push_back(groupItemInfo); + } + } + else + { /* rate the others by popularity */ popMap.insert(std::make_pair(it->mPop, groupItemInfo)); } @@ -719,13 +766,12 @@ void GxsChannelDialog::unsubscribeChannel() std::cerr << std::endl; #endif -#if 0 - if (rsChannels) { - rsChannels->channelSubscribe(mChannelId, false, false); - } + if(mChannelId.empty()) + return; - updateChannelMsgs(); -#endif + uint32_t token = 0; + rsGxsChannels->subscribeToGroup(token, mChannelId, false); + mChannelQueue->queueRequest(token, 0 , RS_TOKREQ_ANSTYPE_ACK, TOKEN_TYPE_GROUP_CHANGE); } @@ -736,14 +782,12 @@ void GxsChannelDialog::subscribeChannel() std::cerr << std::endl; #endif -#if 0 - if (rsChannels) { - rsChannels->channelSubscribe(mChannelId, true, false); - } - - updateChannelMsgs(); -#endif + if(mChannelId.empty()) + return; + uint32_t token = 0; + rsGxsChannels->subscribeToGroup(token, mChannelId, true); + mChannelQueue->queueRequest(token, 0 , RS_TOKREQ_ANSTYPE_ACK, TOKEN_TYPE_GROUP_CHANGE); } void GxsChannelDialog::showChannelDetails() @@ -872,10 +916,6 @@ void GxsChannelDialog::setAutoDownloadButton(bool autoDl) /** Request / Response of Data ********************************/ /*********************** **** **** **** ***********************/ -#define TOKEN_TYPE_LISTING 1 -#define TOKEN_TYPE_GROUP_DATA 2 -#define TOKEN_TYPE_POSTS 3 - void GxsChannelDialog::insertChannels() { requestGroupSummary(); @@ -1012,6 +1052,31 @@ void GxsChannelDialog::loadPosts(const uint32_t &token) } +void GxsChannelDialog::acknowledgeGroupUpdate(const uint32_t &token) +{ + std::cerr << "GxsChannelDialog::acknowledgeGroupUpdate()"; + std::cerr << std::endl; + + RsGxsGroupId grpId; + rsGxsChannels->acknowledgeGrp(token, grpId); + insertChannels(); +} + + +void GxsChannelDialog::acknowledgeMessageUpdate(const uint32_t &token) +{ + std::cerr << "GxsChannelDialog::acknowledgeMessageUpdate() TODO"; + std::cerr << std::endl; + + std::pair msgId; + rsGxsChannels->acknowledgeMsg(token, msgId); + if (msgId.first == mChannelId) + { + requestPosts(mChannelId); + } +} + + void GxsChannelDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) { std::cerr << "GxsChannelDialog::loadRequest() UserType: " << req.mUserType; @@ -1022,6 +1087,12 @@ void GxsChannelDialog::loadRequest(const TokenQueue *queue, const TokenRequest & /* now switch on req */ switch(req.mUserType) { + case TOKEN_TYPE_GROUP_CHANGE: + acknowledgeGroupUpdate(req.mToken); + break; + case TOKEN_TYPE_MESSAGE_CHANGE: + acknowledgeMessageUpdate(req.mToken); + break; case TOKEN_TYPE_LISTING: loadGroupSummary(req.mToken); break; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h index 814ad056f..a0f09932c 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h @@ -128,8 +128,8 @@ private: void insertChannelDetails(const RsGxsChannelGroup &group); void insertChannelPosts(const std::vector &posts); - - + void acknowledgeGroupUpdate(const uint32_t &token); + void acknowledgeMessageUpdate(const uint32_t &token); std::string mChannelId; /* current Channel */ TokenQueue *mChannelQueue; diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 636d3ba93..8b3394ba6 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -1019,11 +1019,14 @@ circles { HEADERS += \ gui/Circles/CirclesDialog.h \ + gui/Circles/CreateCircleDialog.h \ FORMS += gui/Circles/CirclesDialog.ui \ + gui/Circles/CreateCircleDialog.ui \ SOURCES += \ gui/Circles/CirclesDialog.cpp \ + gui/Circles/CreateCircleDialog.cpp \ }