diff --git a/.gitmodules b/.gitmodules index 6ae5adcfb..7692f4556 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,8 +31,8 @@ branch = master [submodule "libretroshare"] path = libretroshare - url = ../libretroshare + url = https://github.com/RetroShare/libretroshare.git branch = master [submodule "retroshare-webui"] path = retroshare-webui - url = ../RSNewWebUI + url = https://github.com/RetroShare/RSNewWebUI.git diff --git a/libbitdht b/libbitdht index 659423769..2ddc86fb5 160000 --- a/libbitdht +++ b/libbitdht @@ -1 +1 @@ -Subproject commit 659423769541169457c41f71c8a038e2d64ba079 +Subproject commit 2ddc86fb575a61170f4c06a00152e3e7dc74c8f4 diff --git a/libretroshare b/libretroshare index 8c02b54e4..3bb5a2b28 160000 --- a/libretroshare +++ b/libretroshare @@ -1 +1 @@ -Subproject commit 8c02b54e4d16e38b28e77263a0b1570c50df4c99 +Subproject commit 3bb5a2b282949bc170dcff6141424cb095e4bb7b diff --git a/plugins/FeedReader/services/p3FeedReaderThread.cc b/plugins/FeedReader/services/p3FeedReaderThread.cc index 01e449323..845b5c82b 100644 --- a/plugins/FeedReader/services/p3FeedReaderThread.cc +++ b/plugins/FeedReader/services/p3FeedReaderThread.cc @@ -1151,10 +1151,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe if (isRunning()) { /* process description */ - bool processPostedFirstImage = (feed.flag & RS_FEED_FLAG_POSTED_FIRST_IMAGE) ? TRUE : FALSE; + bool processPostedFirstImage = (feed.flag & RS_FEED_FLAG_POSTED_FIRST_IMAGE) ? true : false; if (!msg->attachmentBinary.empty()) { /* use attachment as image */ - processPostedFirstImage = FALSE; + processPostedFirstImage = false; } //long todo; // encoding diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp index 2ecf442e4..832970833 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.cpp @@ -86,6 +86,18 @@ const int SearchDialog::FILETYPE_IDX_DIRECTORY = 8; QMap * SearchDialog::FileTypeExtensionMap = new QMap(); bool SearchDialog::initialised = false; +struct SearchDialog::FileDetail +{ +public: + RsPeerId id; + std::string name; + RsFileHash hash; + std::string path; + uint64_t size; + uint32_t mtime; + uint32_t rank; +}; + /** Constructor */ SearchDialog::SearchDialog(QWidget *parent) : MainPage(parent), @@ -265,6 +277,8 @@ void SearchDialog::handleEvent_main_thread(std::shared_ptr event) f.hash = fe->mResults[i].fHash; f.name = fe->mResults[i].fName; f.size = fe->mResults[i].fSize; + f.mtime = 0; // zero what's not available, otherwise we'll get some random values displayed. + f.rank = 0; updateFiles(fe->mRequestId,f); } @@ -966,7 +980,7 @@ void SearchDialog::searchKeywords(const QString& keywords) } } -void SearchDialog::updateFiles(qulonglong search_id,FileDetail file) +void SearchDialog::updateFiles(qulonglong search_id,const FileDetail& file) { searchResultsQueue.push_back(std::pair(search_id,file)) ; @@ -1320,8 +1334,8 @@ void SearchDialog::insertFile(qulonglong searchId, const FileDetail& file, int s item->setText(SR_SIZE_COL, QString::number(file.size)); item->setData(SR_SIZE_COL, ROLE_SORT, (qulonglong) file.size); - item->setText(SR_AGE_COL, QString::number(file.age)); - item->setData(SR_AGE_COL, ROLE_SORT, file.age); + item->setText(SR_AGE_COL, QString::number(file.mtime)); + item->setData(SR_AGE_COL, ROLE_SORT, file.mtime); item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); int friendSource = 0; int anonymousSource = 0; @@ -1396,21 +1410,21 @@ void SearchDialog::resultsToTree(const QString& txt,qulonglong searchId, const s std::list::const_iterator it; for(it = results.begin(); it != results.end(); ++it) - if (it->type == DIR_TYPE_FILE) { + if (it->type == DIR_TYPE_FILE) + { FileDetail fd; fd.id = it->id; fd.name = it->name; fd.hash = it->hash; fd.path = it->path; fd.size = it->size; - fd.age = it->mtime; + fd.mtime= it->mtime; fd.rank = 0; insertFile(searchId,fd, FRIEND_SEARCH); - } else if (it->type == DIR_TYPE_DIR) { -// insertDirectory(txt, searchId, *it, NULL); + } + else if (it->type == DIR_TYPE_DIR) insertDirectory(txt, searchId, *it); - } ui.searchResultWidget->setSortingEnabled(true); } diff --git a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h index 5661f6246..8aa7bac64 100644 --- a/retroshare-gui/src/gui/FileTransfer/SearchDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/SearchDialog.h @@ -43,6 +43,7 @@ class SearchDialog : public MainPage Q_PROPERTY(QColor textColorLowSources READ textColorLowSources WRITE setTextColorLowSources) Q_PROPERTY(QColor textColorHighSources READ textColorHighSources WRITE setTextColorHighSources) + struct FileDetail; // useful structure to store search results. public: /** Default Constructor */ SearchDialog(QWidget *parent = 0); @@ -63,8 +64,7 @@ public: void setTextColorLowSources(QColor color) { mTextColorLowSources = color; } void setTextColorHighSources(QColor color) { mTextColorHighSources = color; } -public slots: - void updateFiles(qulonglong request_id,FileDetail file) ; + void updateFiles(qulonglong request_id, const FileDetail& file) ; private slots: diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp index d0b4d5fc7..6fc45a070 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.cpp @@ -442,7 +442,7 @@ public: { QString strPath = QString::fromUtf8(fileInfo.path.c_str()); QString strPathAfterDL = strPath; - strPathAfterDL.replace(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()),""); + strPathAfterDL.replace(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()),"[Download Dir]"); return QVariant(strPathAfterDL); } @@ -2074,22 +2074,23 @@ void TransfersDialog::dlOpenFolder() break; } + openFolder(info); +} + +void TransfersDialog::openFolder(const FileInfo& info) +{ /* make path for downloaded or downloading files */ - QFileInfo qinfo; - std::string path; - if (info.downloadStatus == FT_STATE_COMPLETE) { - path = info.path; - } else { - path = rsFiles->getPartialsDirectory(); - } + QDir directory; + + if (info.downloadStatus == FT_STATE_COMPLETE) + directory = QFileInfo(QString::fromStdString(info.path)).absoluteDir().path(); + else + directory = QDir(QString::fromStdString(rsFiles->getPartialsDirectory())); /* open folder with a suitable application */ - qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists() && qinfo.isDir()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { - std::cerr << "dlOpenFolder(): can't open folder " << path << std::endl; - } - } + + if (directory.exists() && !RsUrlHandler::openUrl(QUrl::fromLocalFile(directory.path()))) + std::cerr << "dlOpenFolder(): can't open folder " << directory.path().toStdString() << std::endl; } void TransfersDialog::ulOpenFolder() @@ -2104,19 +2105,7 @@ void TransfersDialog::ulOpenFolder() break; } - /* make path for uploading files */ - QFileInfo qinfo; - std::string path; - path = info.path.substr(0,info.path.length()-info.fname.length()); - - /* open folder with a suitable application */ - qinfo.setFile(QString::fromUtf8(path.c_str())); - if (qinfo.exists() && qinfo.isDir()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { - std::cerr << "ulOpenFolder(): can't open folder " << path << std::endl; - } - } - + openFolder(info); } void TransfersDialog::dlPreviewFile() @@ -2139,7 +2128,7 @@ void TransfersDialog::dlPreviewFile() /* make path for downloaded or downloading files */ QFileInfo fileInfo; if (info.downloadStatus == FT_STATE_COMPLETE) { - fileInfo = QFileInfo(QString::fromUtf8(info.path.c_str()), QString::fromUtf8(info.fname.c_str())); + fileInfo = QFileInfo(QString::fromUtf8(info.path.c_str())); } else { fileInfo = QFileInfo(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()), QString::fromUtf8(info.hash.toStdString().c_str())); @@ -2204,7 +2193,7 @@ void TransfersDialog::dlOpenFile() /* make path for downloaded or downloading files */ std::string path; if (info.downloadStatus == FT_STATE_COMPLETE) { - path = info.path + "/" + info.fname; + path = info.path ; /* open file with a suitable application */ QFileInfo qinfo; @@ -2244,6 +2233,10 @@ void TransfersDialog::chunkStreaming() } void TransfersDialog::chunkRandom() { +#ifdef WINDOWS_SYS + if(QMessageBox::Yes != QMessageBox::warning(nullptr,tr("Warning"),tr("On Windows systems, writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway?"),QMessageBox::Yes,QMessageBox::No)) + return; +#endif setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; } void TransfersDialog::chunkProgressive() diff --git a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h index 87396fc81..19e2df363 100644 --- a/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h +++ b/retroshare-gui/src/gui/FileTransfer/TransfersDialog.h @@ -173,6 +173,7 @@ signals: void playFiles(QStringList files); private: + void openFolder(const FileInfo& info); RsDownloadListModel *DLListModel; QSortFilterProxyModel *DLLFilterModel; diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp index 216117f67..7c2b3fd14 100644 --- a/retroshare-gui/src/gui/NetworkDialog.cpp +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -83,7 +83,7 @@ NetworkDialog::NetworkDialog(QWidget */*parent*/) ui.connectTreeWidget->setUpdatesEnabled(true); ui.connectTreeWidget->setSortingEnabled(true); ui.connectTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows); - ui.connectTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui.connectTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(ui.connectTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connectTreeWidgetCostumPopupMenu( QPoint ) ) ); connect(ui.connectTreeWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(peerdetails())); @@ -117,24 +117,12 @@ void NetworkDialog::connectTreeWidgetCostumPopupMenu( QPoint /*point*/ ) { return; } - QMenu *contextMnu = new QMenu; - RsPgpId peer_id(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()) ; - - // That's what context menus are made for - RsPeerDetails detail; - if(!rsPeers->getGPGDetails(peer_id, detail)) // that is not suppose to fail. - return ; - - if(peer_id == rsPeers->getGPGOwnId()) - contextMnu->addAction(QIcon(), tr("Export/create a new node"), this, SLOT(on_actionExportKey_activated())); - contextMnu->addAction(QIcon(IMAGE_PEERDETAILS), tr("Profile details..."), this, SLOT(peerdetails())); contextMnu->addSeparator() ; contextMnu->addAction(QIcon(), tr("Remove unused keys..."), this, SLOT(removeUnusedKeys())); contextMnu->addAction(QIcon(), tr("Remove this key"), this, SLOT(removeSelectedKeys())); - contextMnu->exec(QCursor::pos()); } @@ -177,11 +165,34 @@ void NetworkDialog::removeSelectedKeys() QModelIndexList l = ui.connectTreeWidget->selectionModel()->selection().indexes(); if(l.empty()) return; - std::set selected; - selected.insert(RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l.begin()->row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString())); - removeKeys(selected); + std::set friends; + for (int i = 0; i < l.size(); i++) + { + RsPgpId peer_id = RsPgpId(ui.connectTreeWidget->model()->data(ui.connectTreeWidget->model()->index(l[i].row(), pgpid_item_model::PGP_ITEM_MODEL_COLUMN_PEERID)).toString().toStdString()); + RsPeerDetails details ; + if(rsPeers->getGPGDetails(peer_id,details)) + { + if(details.accept_connection) + friends.insert(peer_id); + else + selected.insert(peer_id); + } + } + if(!friends.empty()) + { + if ((QMessageBox::question(this, "RetroShare", tr("You have selected %1 accepted peers among others,\n Are you sure you want to un-friend them?").arg(friends.size()), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) + { + for(std::set::const_iterator it(friends.begin());it!=friends.end();++it) + rsPeers->removeFriend(*it); + selected.insert(friends.begin(),friends.end()); + } + } + if(!selected.empty()) + removeKeys(selected); + + updateDisplay(); } void NetworkDialog::removeKeys(std::set selected) diff --git a/retroshare-gui/src/gui/Posted/PostedItem.cpp b/retroshare-gui/src/gui/Posted/PostedItem.cpp index 06b585614..8f1cddf7d 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.cpp +++ b/retroshare-gui/src/gui/Posted/PostedItem.cpp @@ -74,7 +74,7 @@ BasePostedItem::BasePostedItem( FeedHolder *feedHolder, uint32_t feedId BasePostedItem::~BasePostedItem() { - auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(200); + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(200); while( (mIsLoadingGroup || mIsLoadingMessage || mIsLoadingComment) && std::chrono::steady_clock::now() < timeout) { diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp index 5c63ce2e9..1798bb4bc 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "retroshare/rsgxscircles.h" @@ -72,6 +73,7 @@ static const int POSTED_TABS_POSTS = 1; // #define IMAGE_COPYLINK ":/images/copyrslink.png" #define IMAGE_AUTHOR ":/images/user/personal64.png" +#define IMAGE_COPYHTTP ":/images/emblem-web.png" Q_DECLARE_METATYPE(RsPostedPost); @@ -340,7 +342,18 @@ void PostedListWidgetWithModel::postContextMenu(const QPoint& point) // 2 - generate the menu for that post. + RsPostedPost post = index.data(Qt::UserRole).value() ; + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyMessageLink()))->setData(index); + + QByteArray urlarray(post.mLink.c_str()); + QUrl url = QUrl::fromEncoded(urlarray.trimmed()); + + std::cerr << "Using link: \"" << post.mLink << "\"" << std::endl; + + if(url.scheme()=="http" || url.scheme()=="https") + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_COPYHTTP), tr("Copy http Link"), this, SLOT(copyHttpLink()))->setData(index); + menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR), tr("Show author in People tab"), this, SLOT(showAuthorInPeople()))->setData(index); #ifdef TODO @@ -456,6 +469,31 @@ void PostedListWidgetWithModel::showAuthorInPeople() MainWindow::showWindow(MainWindow::People); idDialog->navigate(RsGxsId(post.mMeta.mAuthorId)); } +void PostedListWidgetWithModel::copyHttpLink() +{ + try + { + if (groupId().isNull()) + throw std::runtime_error("No channel currently selected!"); + + QModelIndex index = qobject_cast(QObject::sender())->data().toModelIndex(); + + if(!index.isValid()) + throw std::runtime_error("No post under mouse!"); + + RsPostedPost post = index.data(Qt::UserRole).value() ; + + if(post.mMeta.mMsgId.isNull()) + throw std::runtime_error("Post has empty MsgId!"); + + QApplication::clipboard()->setText(QString::fromStdString(post.mLink)) ; + QMessageBox::information(NULL,tr("information"),tr("The Retrohare link was copied to your clipboard.")) ; + } + catch(std::exception& e) + { + QMessageBox::critical(NULL,tr("Link creation error"),tr("Link could not be created: ")+e.what()); + } +} void PostedListWidgetWithModel::copyMessageLink() { try @@ -823,6 +861,7 @@ void PostedListWidgetWithModel::insertBoardDetails(const RsPostedGroup& group) ui->subscribeToolButton->setText(tr("Subscribe")); ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount)); + ui->poplabel->setText(QString::number(group.mMeta.mPop)); if(group.mMeta.mLastPost==0) ui->infoLastPost->setText(tr("Never")); diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h index e6b98120a..cb7dcfd39 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h @@ -147,6 +147,7 @@ private slots: void settingsChanged(); void postPostLoad(); void copyMessageLink(); + void copyHttpLink(); void nextPosts(); void prevPosts(); void filterItems(QString s); diff --git a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui index 2bafbc8a2..8074388dc 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui +++ b/retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui @@ -54,7 +54,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html> @@ -84,8 +84,11 @@ p, li { white-space: pre-wrap; } true + + <html><head/><body><p>Maximum number of data items (including posts, comments, votes) across friend nodes.</p></body></html> + - Contributions: + Items (at friends): @@ -179,6 +182,9 @@ p, li { white-space: pre-wrap; } true + + Number of subscribed friend nodes + Popularity: @@ -615,8 +621,8 @@ p, li { white-space: pre-wrap; } - + diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h index 3e9a3e412..18943c1dc 100644 --- a/retroshare-gui/src/gui/RSHumanReadableDelegate.h +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -91,7 +91,8 @@ class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate QStyleOptionViewItem opt(option) ; setPainterOptions(painter,opt,index) ; - painter->drawText(opt.rect, Qt::AlignCenter, misc::timeRelativeToNow(index.data().toLongLong())) ; + if(index.data().toLongLong() > 0) // no date is present. + painter->drawText(opt.rect, Qt::AlignCenter, misc::timeRelativeToNow(index.data().toLongLong())) ; } }; diff --git a/retroshare-gui/src/gui/TheWire/CustomFrame.cpp b/retroshare-gui/src/gui/TheWire/CustomFrame.cpp new file mode 100644 index 000000000..4f1308df5 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/CustomFrame.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* + * gui/TheWire/CustomFrame.cpp * + * * + * Copyright (c) 2012-2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include "CustomFrame.h" +#include + +// Constructor +CustomFrame::CustomFrame(QWidget *parent) : QFrame(parent) +{ + // Any initializations for this frame. +} + +// Overriding the inbuilt paint function +void CustomFrame::paintEvent(QPaintEvent *event) +{ + QFrame::paintEvent(event); + QPainter painter(this); + painter.drawPixmap(rect(), backgroundImage); +} + +// Function to set the member variable 'backgroundImage' +void CustomFrame::setPixmap(QPixmap pixmap){ + backgroundImage = pixmap; +} diff --git a/retroshare-gui/src/gui/TheWire/CustomFrame.h b/retroshare-gui/src/gui/TheWire/CustomFrame.h new file mode 100644 index 000000000..e75a6087a --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/CustomFrame.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * gui/TheWire/CustomFrame.h * + * * + * Copyright (c) 2012-2020 Robert Fernie * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef CUSTOMFRAMEH_H +#define CUSTOMFRAMEH_H + +#include +#include + +// This class is made to implement the background image in a Qframe or any widget + +class CustomFrame : public QFrame +{ + Q_OBJECT + +public: + explicit CustomFrame(QWidget *parent = nullptr); + void setPixmap(QPixmap pixmap); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QPixmap backgroundImage; +}; + +#endif //CUSTOMFRAMEH_H diff --git a/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui b/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui index 077b72473..1959244d3 100644 --- a/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui +++ b/retroshare-gui/src/gui/TheWire/PulseTopLevel.ui @@ -767,7 +767,6 @@ 12 - 75 true diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp index 8707eaf8c..475c74034 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp @@ -24,86 +24,149 @@ #include #include "PulseViewGroup.h" +#include "CustomFrame.h" +#include "WireGroupDialog.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" #include "util/DateTime.h" +Q_DECLARE_METATYPE(RsWireGroup) + /** Constructor */ PulseViewGroup::PulseViewGroup(PulseViewHolder *holder, RsWireGroupSPtr group) :PulseViewItem(holder), mGroup(group) { - setupUi(this); - setAttribute ( Qt::WA_DeleteOnClose, true ); - setup(); + setupUi(this); + setAttribute ( Qt::WA_DeleteOnClose, true ); + setup(); + + connect(editButton, SIGNAL(clicked()), this, SLOT(editProfile())); + } void PulseViewGroup::setup() { - if (mGroup) { - connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); + if (mGroup) { + connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); - label_groupName->setText("@" + QString::fromStdString(mGroup->mMeta.mGroupName)); - label_authorName->setText(BoldString(QString::fromStdString(mGroup->mMeta.mAuthorId.toStdString()))); - label_date->setText(DateTime::formatDateTime(mGroup->mMeta.mPublishTs)); - label_tagline->setText(QString::fromStdString(mGroup->mTagline)); - label_location->setText(QString::fromStdString(mGroup->mLocation)); + label_groupName->setText("@" + QString::fromStdString(mGroup->mMeta.mGroupName)); + label_authorName->setText(BoldString(QString::fromStdString(mGroup->mMeta.mAuthorId.toStdString()))); + label_date->setText(DateTime::formatDateTime(mGroup->mMeta.mPublishTs)); + label_tagline->setText(QString::fromStdString(mGroup->mTagline)); + label_location->setText(QString::fromStdString(mGroup->mLocation)); - // need to draw mGroup->mMasthead, as background to headshot. - // TODO frame_headerBackground->setBackground() - if (mGroup->mHeadshot.mData) - { - QPixmap pixmap; - if (GxsIdDetails::loadPixmapFromData( - mGroup->mHeadshot.mData, - mGroup->mHeadshot.mSize, - pixmap,GxsIdDetails::ORIGINAL)) - { - pixmap = pixmap.scaled(50,50); - label_headshot->setPixmap(pixmap); - } - } - else - { + if (mGroup->mMasthead.mData) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + mGroup->mMasthead.mData, + mGroup->mMasthead.mSize, + pixmap, GxsIdDetails::ORIGINAL)) + { + QSize frameSize = frame_masthead->size(); + + // Scale the pixmap based on the frame size + pixmap = pixmap.scaledToWidth(frameSize.width(), Qt::SmoothTransformation); + frame_masthead->setPixmap(pixmap); + } + } +// Uncomment the below code for default background +// else +// { +// // Default pixmap +// QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png"); +// QSize frameSize = frame_masthead->size(); + +// // Scale the pixmap based on the frame size +// pixmap = pixmap.scaled(frameSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); +// frame_masthead->setPixmap(pixmap); +// } + + if (mGroup->mHeadshot.mData) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + mGroup->mHeadshot.mData, + mGroup->mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + pixmap = pixmap.scaled(100,100, Qt::KeepAspectRatio, Qt::SmoothTransformation); + label_headshot->setPixmap(pixmap); + } + } + else + { // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/png/posted.png").scaled(50,50); - label_headshot->setPixmap(pixmap); - } + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(100,100, Qt::KeepAspectRatio, Qt::SmoothTransformation); + label_headshot->setPixmap(pixmap); + } - if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - uint32_t pulses = mGroup->mGroupPulses + mGroup->mGroupReplies; - uint32_t replies = mGroup->mRefReplies; - uint32_t republishes = mGroup->mRefRepublishes; - uint32_t likes = mGroup->mRefLikes; + if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + uint32_t pulses = mGroup->mGroupPulses + mGroup->mGroupReplies; + uint32_t replies = mGroup->mRefReplies; + uint32_t republishes = mGroup->mRefRepublishes; + uint32_t likes = mGroup->mRefLikes; - label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); - label_extra_replies->setText(BoldString(ToNumberUnits(replies))); - label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); - label_extra_likes->setText(BoldString(ToNumberUnits(likes))); + label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); + label_extra_replies->setText(BoldString(ToNumberUnits(replies))); + label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); + label_extra_likes->setText(BoldString(ToNumberUnits(likes))); - // hide follow. - widget_actions->setVisible(false); - } - else - { - // hide stats. - widget_replies->setVisible(false); - } + // hide follow. + widget_actions->setVisible(false); + } + else + { + // hide stats. + widget_replies->setVisible(false); + } + } + + setGroupSet(); +} + +void PulseViewGroup::setGroupSet() +{ + if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { + editButton->show(); + } + else if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) + { + editButton->hide(); + } + else + { + editButton->hide(); } } void PulseViewGroup::actionFollow() { - RsGxsGroupId groupId = mGroup->mMeta.mGroupId; - std::cerr << "PulseViewGroup::actionFollow() following "; - std::cerr << groupId; - std::cerr << std::endl; + RsGxsGroupId groupId = mGroup->mMeta.mGroupId; + std::cerr << "PulseViewGroup::actionFollow() following "; + std::cerr << groupId; + std::cerr << std::endl; - if (mHolder) { - mHolder->PVHfollow(groupId); - } + if (mHolder) { + mHolder->PVHfollow(groupId); + } +} + +void PulseViewGroup::editProfile() +{ + RsGxsGroupId groupId = mGroup->mMeta.mGroupId; + if (groupId.isNull()) + { + std::cerr << "PulseViewGroup::editProfile() No Group selected"; + std::cerr << std::endl; + return; + } + + WireGroupDialog wireEdit(GxsGroupDialog::MODE_EDIT, groupId, this); + wireEdit.exec (); } diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h index 4d00090ca..62da0a228 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h @@ -35,10 +35,13 @@ public: private slots: void actionFollow(); + void editProfile(); protected: void setup(); +private: + void setGroupSet(); protected: RsWireGroupSPtr mGroup; diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index 77329e3c2..79d9964f6 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -6,7 +6,7 @@ 0 0 - 745 + 746 483 @@ -48,19 +48,37 @@ QFrame::Raised - + - - + + + + 0 + 0 + + + + + 700 + 135 + + + + + + - + Qt::Horizontal + + QSizePolicy::Expanding + - 283 - 20 + 277 + 17 @@ -79,19 +97,22 @@ 100 + + + headshot - + Qt::Horizontal - 23 + 281 20 @@ -115,38 +136,6 @@ - - - - Qt::Horizontal - - - - 518 - 58 - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> - - - @@ -182,6 +171,45 @@ + + + + + 0 + 0 + + + + + 0 + 20 + + + + <html><head/><body><p><span style=" color:#555753;">@sidler_here</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 518 + 58 + + + + + + + + Edit profile + + + @@ -206,41 +234,6 @@ - - - - - 0 - 0 - - - - - 0 - 20 - - - - <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - @@ -260,19 +253,6 @@ - - - - Qt::Horizontal - - - - 2000 - 20 - - - - @@ -292,6 +272,54 @@ + + + + + 0 + 0 + + + + + 0 + 20 + + + + <html><head/><body><p><span style=" color:#2e3436;">3:58 AM · Apr 13, 2020 ·</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 2000 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + @@ -538,10 +566,25 @@ + widget_header + widget_publish + line_1 + widget_replies + line_2 + widget_actions + frame_masthead + + + CustomFrame + QFrame +
gui/TheWire/CustomFrame.h
+ 1 +
+
diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index b794a96e0..4cdf4a174 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -434,8 +434,8 @@ - + diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp index e13cd4f8f..e832540de 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp @@ -152,7 +152,7 @@ bool WireGroupDialog::service_updateGroup(const RsGroupMetaData &editedMeta) std::cerr << "WireGroupDialog::service_updateGroup() submitting changes"; std::cerr << std::endl; - bool success = rsWire->updateGroup(grp); + bool success = rsWire->editWire(grp); // TODO updateGroup should refresh groupId or Data return success; } diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp b/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp index b6a1c5440..8ed6d4d4b 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.cpp @@ -34,13 +34,19 @@ WireGroupExtra::~WireGroupExtra() void WireGroupExtra::setUp() { - connect(ui.pushButton_masthead, SIGNAL(clicked() ), this , SLOT(addMasthead())); -} + connect(ui.pushButton_masthead, SIGNAL(clicked() ), this , SLOT(addMasthead())); + int desired_height = ui.pushButton_masthead->height() + ui.removeButton->height() + ui.lineEdit_Tagline->height(); + int desired_width = 3/1.0 * desired_height + ui.lineEdit_Tagline->width(); + + ui.label_masthead->setFixedSize(desired_width, desired_height); + + setMasthead(QPixmap()); +} void WireGroupExtra::addMasthead() { - QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Masthead"), 400, 100); + QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Masthead"), 800, 600); if (img.isNull()) return; @@ -48,7 +54,6 @@ void WireGroupExtra::addMasthead() setMasthead(img); } - void WireGroupExtra::setTagline(const std::string &str) { ui.lineEdit_Tagline->setText(QString::fromStdString(str)); @@ -61,8 +66,21 @@ void WireGroupExtra::setLocation(const std::string &str) void WireGroupExtra::setMasthead(const QPixmap &pixmap) { - mMasthead = pixmap; - ui.label_masthead->setPixmap(mMasthead); + mMasthead = pixmap; + + if (!mMasthead.isNull()) { + ui.label_masthead->setPicture(mMasthead); + ui.label_masthead->setToolTip(tr("Use the mouse to zoom and adjust the image for your background.")); + } else { + ui.label_masthead->setPicture(QPixmap()); + ui.label_masthead->setText(tr("MastHead background Image")); + } +} + +void WireGroupExtra::on_removeButton_clicked() +{ + ui.label_masthead->setPicture(QPixmap()); + ui.label_masthead->setText(tr("MastHead background Image")); } std::string WireGroupExtra::getTagline() @@ -77,7 +95,5 @@ std::string WireGroupExtra::getLocation() QPixmap WireGroupExtra::getMasthead() { - return mMasthead; + return ui.label_masthead->extractCroppedScaledPicture(); } - - diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.h b/retroshare-gui/src/gui/TheWire/WireGroupExtra.h index ce606feb3..429be088b 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.h +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.h @@ -34,7 +34,6 @@ public: void setMasthead(const QPixmap &pixmap); QPixmap getMasthead(); - void setTagline(const std::string &str); void setLocation(const std::string &str); @@ -43,7 +42,7 @@ public: private slots: void addMasthead(); - + void on_removeButton_clicked(); private: void setUp(); private: diff --git a/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui b/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui index fb1da5e73..4c03b8fe8 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupExtra.ui @@ -7,7 +7,7 @@ 0 0 516 - 199 + 133 @@ -19,50 +19,127 @@ Form - + + + 0 + + + 0 + - - - Masthead - - - - - - - MastHead background Image - - + + + + + + + + Tagline: + + + + + + + + + + Remove + + + + + + + Location: + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + Select Image + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + QFrame::Plain + + + 1 + + + MastHead background Image + + + Qt::PlainText + + + false + + + Qt::AlignCenter + + + + - - - Select Image + + + Qt::Vertical - - - - - - Tagline: + + + 20 + 10 + - - - - - - - - - Location: - - - - - + + + + ZoomableLabel + QLabel +
gui/gxschannels/GxsChannelPostThumbnail.h
+
+
diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp index 8ab62260a..199800581 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -65,8 +65,7 @@ WireGroupItem::WireGroupItem(WireGroupHolder *holder, const RsWireGroup &grp) setAttribute ( Qt::WA_DeleteOnClose, true ); setup(); - // disabled, still not yet functional Edit/Update - editButton->setEnabled(false); + editButton->setEnabled(true); } RsGxsGroupId &WireGroupItem::groupId() @@ -93,14 +92,14 @@ void WireGroupItem::setup() QImage circleImage = getCirclePhoto(orginalImage,orginalImage.size().width()); pixmap.convertFromImage(circleImage); - pixmap = pixmap.scaled(40,40); + pixmap = pixmap.scaled(40,40, Qt::KeepAspectRatio, Qt::SmoothTransformation); label_headshot->setPixmap(pixmap); } } else { // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(32,32); + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png").scaled(32,32, Qt::KeepAspectRatio, Qt::SmoothTransformation); label_headshot->setPixmap(pixmap); } diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui index 2da79ddc6..a53448157 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.ui +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.ui @@ -6,8 +6,8 @@ 0 0 - 276 - 114 + 292 + 115
diff --git a/retroshare-gui/src/gui/common/ElidedLabel.cpp b/retroshare-gui/src/gui/common/ElidedLabel.cpp index 31351b08d..2486d0cae 100644 --- a/retroshare-gui/src/gui/common/ElidedLabel.cpp +++ b/retroshare-gui/src/gui/common/ElidedLabel.cpp @@ -258,7 +258,11 @@ void ElidedLabel::mousePressEvent(QMouseEvent *ev) return; // eat event } QLabel::mousePressEvent(ev); - emit clicked(ev->pos()); + + if(ev->buttons()==Qt::LeftButton) + emit clicked(ev->pos()); + else if(ev->buttons()==Qt::RightButton) + emit rightClicked(ev->pos()); } void ElidedLabel::setTextColor(const QColor &color) diff --git a/retroshare-gui/src/gui/common/ElidedLabel.h b/retroshare-gui/src/gui/common/ElidedLabel.h index 9290a61d1..2faa2f0ef 100644 --- a/retroshare-gui/src/gui/common/ElidedLabel.h +++ b/retroshare-gui/src/gui/common/ElidedLabel.h @@ -77,7 +77,8 @@ protected: signals: void elisionChanged(bool elided); - void clicked(QPoint pos); + void rightClicked(QPoint pos); + void clicked(QPoint pos); private: bool mElided; diff --git a/retroshare-gui/src/gui/common/FriendListModel.cpp b/retroshare-gui/src/gui/common/FriendListModel.cpp index f8740466d..622ae3930 100644 --- a/retroshare-gui/src/gui/common/FriendListModel.cpp +++ b/retroshare-gui/src/gui/common/FriendListModel.cpp @@ -1145,8 +1145,6 @@ void RsFriendListModel::updateInternalData() mLocations.clear(); mTopLevel.clear(); - endResetModel(); - auto TL = mTopLevel ; // This allows to fill TL without touching mTopLevel outside of [begin/end]InsertRows(). // create a map of profiles and groups @@ -1282,7 +1280,8 @@ void RsFriendListModel::updateInternalData() endInsertRows(); } - postMods(); + endResetModel(); + postMods(); mLastInternalDataUpdate = time(NULL); } diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp index 102dfb637..17036a15e 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp @@ -49,6 +49,10 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsGxsChannels, autoUpdate), mGroupMeta(group_meta) { + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingComment = false; + mPost.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded mPost.mMeta.mGroupId = mGroupMeta.mGroupId; @@ -136,6 +140,19 @@ void GxsChannelPostItem::paintEvent(QPaintEvent *e) GxsChannelPostItem::~GxsChannelPostItem() { + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingComment) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingComment ? "Comment " : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + delete(ui); } @@ -277,6 +294,7 @@ void GxsChannelPostItem::loadGroup() std::cerr << "GxsChannelGroupItem::loadGroup()"; std::cerr << std::endl; #endif + mLoadingGroup = true; RsThread::async([this]() { @@ -306,6 +324,7 @@ void GxsChannelPostItem::loadGroup() * after a blocking call to RetroShare API complete */ mGroupMeta = group.mMeta; + mLoadingGroup = false; }, this ); }); @@ -316,6 +335,8 @@ void GxsChannelPostItem::loadMessage() std::cerr << "GxsChannelPostItem::loadMessage()"; std::cerr << std::endl; #endif + mLoadingMessage = true; + RsThread::async([this]() { // 1 - get group data @@ -337,7 +358,11 @@ void GxsChannelPostItem::loadMessage() #endif const RsGxsChannelPost& post(posts[0]); - RsQThreadUtils::postToObject( [post,this]() { setPost(post); }, this ); + RsQThreadUtils::postToObject( [post,this]() + { + setPost(post); + mLoadingMessage = false; + }, this ); } else if(comments.size() == 1) { @@ -356,7 +381,8 @@ void GxsChannelPostItem::loadMessage() setMessageId(cmt.mMeta.mThreadId); requestMessage(); - }, this ); + mLoadingMessage = false; + }, this ); } else @@ -366,7 +392,11 @@ void GxsChannelPostItem::loadMessage() std::cerr << std::endl; #endif - RsQThreadUtils::postToObject( [this]() { removeItem(); }, this ); + RsQThreadUtils::postToObject( [this]() + { + removeItem(); + mLoadingMessage = false; + }, this ); } }); } @@ -377,6 +407,7 @@ void GxsChannelPostItem::loadComment() std::cerr << "GxsChannelPostItem::loadComment()"; std::cerr << std::endl; #endif + mLoadingComment = true; RsThread::async([this]() { @@ -407,6 +438,7 @@ void GxsChannelPostItem::loadComment() sComButText = tr("Comments ").append("(%1)").arg(comNb); ui->commentButton->setText(sComButText); + mLoadingComment = false; }, this ); }); diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h index 8370b885e..b3e7843c0 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h @@ -119,7 +119,12 @@ private: private: bool mInFill; bool mCloseOnRead; - bool mLoaded; + bool mLoaded; + + bool mLoadingMessage; + bool mLoadingGroup; + bool mLoadingComment; + RsGroupMetaData mGroupMeta; RsGxsChannelPost mPost; diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp index eedb4ae20..f4d091179 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp @@ -47,7 +47,13 @@ GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const { mMessage.mMeta.mMsgId = messageId; // useful for uniqueIdentifier() before the post is actually loaded mMessage.mMeta.mGroupId = groupId; - setup(); + + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingSetAsRead = false; + mLoadingParentMessage = false; + + setup(); requestGroup(); requestMessage(); @@ -83,6 +89,19 @@ GxsForumMsgItem::GxsForumMsgItem(FeedHolder *feedHolder, uint32_t feedId, const GxsForumMsgItem::~GxsForumMsgItem() { + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingSetAsRead || mLoadingParentMessage) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingParentMessage ? "Parent message " : "") + << (mLoadingSetAsRead ? "Set as read" : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } delete(ui); } @@ -167,6 +186,8 @@ QString GxsForumMsgItem::groupName() void GxsForumMsgItem::loadGroup() { + mLoadingGroup = true; + RsThread::async([this]() { // 1 - get group data @@ -199,6 +220,7 @@ void GxsForumMsgItem::loadGroup() * after a blocking call to RetroShare API complete */ setGroup(group); + mLoadingGroup = false; }, this ); }); @@ -210,6 +232,7 @@ void GxsForumMsgItem::loadMessage() std::cerr << "GxsForumMsgItem::loadMessage(): messageId=" << messageId() << " groupId=" << groupId() ; std::cerr << std::endl; #endif + mLoadingMessage = true; RsThread::async([this]() { @@ -244,6 +267,7 @@ void GxsForumMsgItem::loadMessage() * after a blocking call to RetroShare API complete */ setMessage(msg); + mLoadingMessage = false; }, this ); }); @@ -255,6 +279,7 @@ void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) std::cerr << "GxsForumMsgItem::loadParentMessage()"; std::cerr << std::endl; #endif + mLoadingParentMessage = true; RsThread::async([parent_msg,this]() { @@ -291,6 +316,8 @@ void GxsForumMsgItem::loadParentMessage(const RsGxsMessageId& parent_msg) mParentMessage = msg; fillParentMessage(); + mLoadingParentMessage = false; + }, this ); }); } @@ -480,6 +507,7 @@ void GxsForumMsgItem::setAsRead(bool doUpdate) } mCloseOnRead = false; + mLoadingSetAsRead = true; RsThread::async( [this, doUpdate]() { RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); @@ -489,6 +517,7 @@ void GxsForumMsgItem::setAsRead(bool doUpdate) if (doUpdate) { RsQThreadUtils::postToObject( [this]() { setReadStatus(false, true); + mLoadingSetAsRead = false; } ); } }); diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h index 34166ee59..ec933d96e 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.h @@ -87,6 +87,10 @@ private: private: bool mInFill; bool mCloseOnRead; + bool mLoadingMessage; + bool mLoadingParentMessage; + bool mLoadingGroup; + bool mLoadingSetAsRead; RsGxsForumGroup mGroup; RsGxsForumMsg mMessage; diff --git a/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp b/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp index 7b9e28131..1233b3100 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentDialog.cpp @@ -29,6 +29,8 @@ #include #include +//#define DEBUG_COMMENT_DIALOG 1 + /** Constructor */ GxsCommentDialog::GxsCommentDialog(QWidget *parent, const RsGxsId &default_author, RsGxsCommentService *comment_service) : QWidget(parent), ui(new Ui::GxsCommentDialog) @@ -95,8 +97,11 @@ void GxsCommentDialog::commentClear() } void GxsCommentDialog::commentLoad(const RsGxsGroupId &grpId, const std::set& msg_versions,const RsGxsMessageId& most_recent_msgId,bool use_cache) { - std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")"; - std::cerr << std::endl; +#ifdef DEBUG_COMMENT_DIALOG + std::cerr << "GxsCommentDialog::commentLoad(" << grpId << ", most recent msg version: " << most_recent_msgId << ")" << std::endl; + for(const auto& mid:msg_versions) + std::cerr << " msg version: " << mid << std::endl; +#endif mGrpId = grpId; mMostRecentMsgId = most_recent_msgId; diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp index 0b65b7c3d..bd230fe9c 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp @@ -42,6 +42,8 @@ #include +//#define DEBUG_COMMENT_TREE_WIDGET + #define PCITEM_COLUMN_COMMENT 0 #define PCITEM_COLUMN_AUTHOR 1 #define PCITEM_COLUMN_DATE 2 @@ -73,6 +75,7 @@ std::map > GxsCommentTreeWidget::mComm QMutex GxsCommentTreeWidget::mCacheMutex; //#define USE_NEW_DELEGATE 1 +//#define DEBUG_GXSCOMMENT_TREEWIDGET 1 // This class allows to draw the item using an appropriate size @@ -464,11 +467,7 @@ void GxsCommentTreeWidget::replyToComment() void GxsCommentTreeWidget::copyComment() { QString txt = dynamic_cast(sender())->data().toString(); - - QMimeData *mimeData = new QMimeData(); - mimeData->setHtml(""+txt+""); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setMimeData(mimeData, QClipboard::Clipboard); + QApplication::clipboard()->setText(txt) ; } void GxsCommentTreeWidget::setup(RsGxsCommentService *comment_service) @@ -512,6 +511,8 @@ void GxsCommentTreeWidget::service_requestComments(const RsGxsGroupId& group_id, /* request comments */ #ifdef DEBUG_GXSCOMMENT_TREEWIDGET std::cerr << "GxsCommentTreeWidget::service_requestComments for group " << group_id << std::endl; + for(const auto& mid:msgIds) + std::cerr << " including message " << mid << std::endl; #endif RsThread::async([this,group_id,msgIds]() @@ -769,8 +770,10 @@ void GxsCommentTreeWidget::insertComments(const std::vector& comme new_comments.push_back(comment.mMeta.mMsgId); /* convert to a QTreeWidgetItem */ +#ifdef DEBUG_COMMENT_TREE_WIDGET std::cerr << "GxsCommentTreeWidget::service_loadThread() Got Comment: " << comment.mMeta.mMsgId; std::cerr << std::endl; +#endif GxsIdRSTreeWidgetItem *item = new GxsIdRSTreeWidgetItem(NULL,GxsIdDetails::ICON_TYPE_AVATAR) ; QString text; diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index 3b1aad916..9d8d66d61 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -1105,7 +1105,12 @@ void GxsGroupFrameDialog::updateGroupSummary() * Qt::QueuedConnection is important! */ - insertGroupsData(*groupInfo); + // Here we save the focus, and restore it afterwards: there's no need to grab the focus here and + // if we do, it may harm the navitation in forums, channels, boards, etc. + + auto w = QApplication::focusWidget(); + + insertGroupsData(*groupInfo); updateSearchResults(); mStateHelper->setLoading(TOKEN_TYPE_GROUP_SUMMARY, false); @@ -1132,7 +1137,12 @@ void GxsGroupFrameDialog::updateGroupSummary() delete groupInfo; - }, this ); + // Restore the focus. + + if(w) + w->setFocus(); + + }, this ); }); } @@ -1165,16 +1175,16 @@ void GxsGroupFrameDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) * Qt::QueuedConnection is important! */ - QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); - if (!item) - return; + QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); + + if (item) + ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); - ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); mCachedGroupStats[groupId] = stats; getUserNotify()->updateIcon(); - }, this ); + }, this ); }); } diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 97f128447..053590e11 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -193,17 +193,25 @@ void GxsIdTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem QStyleOptionViewItem ownOption (option); initStyleOption(&ownOption, index); - RsGxsId id(index.data(Qt::UserRole).toString().toStdString()); - QString cmt; + QString dt = index.data(Qt::UserRole).toString(); + RsGxsId id(index.data(Qt::UserRole).toString().toStdString()); - if(id.isNull()) + // This is a trick: UserRole in Mail generally is 0000...00000 when there is a notification, and is empty when there are multiple + // destinations at once. This is not so nice to do that this way, but it's a quick workaround to a more complex method involving an + // additional Qt role only to determine the number of destinations. + + if(dt == "") + ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/svg/people2.svg"); + else if(id.isNull()) + { + if (ownOption.icon.isNull()) + ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.svg"); + } + else { - if (ownOption.icon.isNull()) - ownOption.icon = FilesDefs::getIconFromQtResourcePath(":/icons/notification.svg"); - } - else - { - if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt)) + QString cmt; + + if(! computeNameIconAndComment(id,ownOption.text,ownOption.icon,cmt)) { if(mReloadPeriod > 3) { diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.h b/retroshare-gui/src/gui/gxs/GxsUserNotify.h index cfbec97be..66890a1c3 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.h +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.h @@ -46,7 +46,6 @@ protected: bool mCountChildMsgs; // Count new child messages? private: - RsGxsUpdateBroadcastBase *mBase; const GxsGroupFrameDialog *mGroupFrameDialog; unsigned int mNewThreadMessageCount; diff --git a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp index 05ce9bda6..bc2f5d960 100644 --- a/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp +++ b/retroshare-gui/src/gui/gxschannels/CreateGxsChannelMsg.cpp @@ -35,6 +35,7 @@ #include "util/rsdir.h" #include "util/qtthreadsutils.h" #include "util/RichTextEdit.h" +#include "util/imageutil.h" #include @@ -607,11 +608,13 @@ bool CreateGxsChannelMsg::setThumbNail(const std::string& path, int frame){ if(imageBuffer == NULL) return false; - QImage tNail(imageBuffer, width, height, QImage::Format_RGB32); + QImage tNail(imageBuffer, width, height, QImage::Format_RGBA32); QByteArray ba; QBuffer buffer(&ba); + bool has_transparency = ImageUtil::hasAlphaContent(tNail.toImage()); + buffer.open(QIODevice::WriteOnly); - tNail.save(&buffer, "JPG"); + tNail.save(&buffer, has_transparency?"PNG":"JPG"); QPixmap img; img.loadFromData(ba, "PNG"); img = img.scaled(thumbnail_label->width(), thumbnail_label->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); @@ -797,15 +800,19 @@ void CreateGxsChannelMsg::sendMessage(const std::string &subject, const std::str QByteArray ba; QBuffer buffer(&ba); - RsGxsImage image; + RsGxsImage image; + QPixmap pixmap; + pixmap = preview_W->getCroppedScaledPicture(); + QImage qimg = pixmap.toImage(); + bool has_transparency = ImageUtil::hasAlphaContent(qimg); if(!picture.isNull()) { // send chan image buffer.open(QIODevice::WriteOnly); - preview_W->getCroppedScaledPicture().save(&buffer, "JPG"); // writes image into ba in PNG format - image.copy((uint8_t *) ba.data(), ba.size()); + preview_W->getCroppedScaledPicture().save(&buffer, has_transparency?"PNG":"JPG"); // writes image into ba in PNG format + image.copy((uint8_t *) ba.data(), ba.size()); } std::string error_string; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp index 66eb0f793..23f5f5b93 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.cpp @@ -50,15 +50,12 @@ GxsChannelFilesStatusWidget::GxsChannelFilesStatusWidget(const RsGxsFile &file, connect(ui->openFilePushButton, SIGNAL(clicked()), this, SLOT(openFile())); ui->downloadPushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); - ui->openFolderToolButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/arrow.png")); - QAction *openfolder = new QAction(tr("Open folder"), this); - connect(openfolder, SIGNAL(triggered()), this, SLOT(openFolder())); + ui->openFolderPushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/folderopen.png")); + ui->openFolderPushButton->setToolTip(tr("Open folder")); + + connect(ui->openFolderPushButton, SIGNAL(clicked()), this, SLOT(openFolder())); - QMenu *menu = new QMenu(); - menu->addAction(openfolder); - ui->openFolderToolButton->setMenu(menu); - check(); } @@ -90,7 +87,9 @@ void GxsChannelFilesStatusWidget::setSize(uint64_t size) void GxsChannelFilesStatusWidget::check() { FileInfo fileInfo; - if (rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + + if(haveFile(fileInfo)) + { mState = STATE_LOCAL; setSize(fileInfo.size); @@ -103,27 +102,25 @@ void GxsChannelFilesStatusWidget::check() ui->openFilePushButton->setText(tr("Play")); ui->openFilePushButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); } - - } else { - FileInfo fileInfo; - bool detailsOk = rsFiles->FileDetails(mFile.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, fileInfo); - - if (detailsOk) { - switch (fileInfo.downloadStatus) { + } + else + { + switch (fileInfo.downloadStatus) + { case FT_STATE_WAITING: mState = STATE_WAITING; break; case FT_STATE_DOWNLOADING: - if (fileInfo.avail == fileInfo.size) { + if (fileInfo.avail == fileInfo.size) mState = STATE_LOCAL; - } else { + else mState = STATE_DOWNLOAD; - } + setSize(fileInfo.size); ui->progressBar->setValue(fileInfo.avail / mDivisor); break; - case FT_STATE_COMPLETE: - mState = STATE_DOWNLOAD; + case FT_STATE_COMPLETE: // this should not happen, since the case is handled earlier + mState = STATE_ERROR; break; case FT_STATE_QUEUED: mState = STATE_WAITING; @@ -134,14 +131,11 @@ void GxsChannelFilesStatusWidget::check() case FT_STATE_CHECKING_HASH: mState = STATE_CHECKING; break; - case FT_STATE_FAILED: - mState = STATE_ERROR; - break; - } - } else { - mState = STATE_REMOTE; - } - } + default: + mState = STATE_REMOTE; + break; + } + } int repeat = 0; QString statusText; @@ -156,7 +150,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Error"); @@ -171,7 +165,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); break; @@ -184,7 +178,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->show(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); break; @@ -197,7 +191,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Paused"); @@ -212,7 +206,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Waiting"); @@ -227,7 +221,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->show(); ui->progressBar->hide(); ui->openFilePushButton->hide(); - ui->openFolderToolButton->hide(); + ui->openFolderPushButton->hide(); statusText = tr("Checking"); @@ -242,7 +236,7 @@ void GxsChannelFilesStatusWidget::check() ui->cancelToolButton->hide(); ui->progressBar->hide(); ui->openFilePushButton->show(); - ui->openFolderToolButton->show(); + ui->openFolderPushButton->show(); break; } @@ -324,35 +318,60 @@ void GxsChannelFilesStatusWidget::cancel() void GxsChannelFilesStatusWidget::openFolder() { FileInfo fileInfo; - if (!rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + if (!haveFile(fileInfo)) return; - } - /* open folder with a suitable application */ - QDir dir = QFileInfo(QString::fromUtf8(fileInfo.path.c_str())).absoluteDir(); - if (dir.exists()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(dir.absolutePath()))) { - if(!mUsedAsEditor) - QMessageBox::warning(this, "", QString("%1 %2").arg(tr("Can't open folder"), dir.absolutePath())); - else - RsErr() << "Can't open folder " << dir.absolutePath().toStdString() ; + QFileInfo finfo; + finfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); - } - } + /* open folder with a suitable application */ + if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(finfo.absolutePath()))) { + if(!mUsedAsEditor) + QMessageBox::warning(this, "", QString("%1 %2").arg(tr("Can't open folder"), finfo.absolutePath())); + else + RsErr() << "Can't open folder " << finfo.absolutePath().toStdString() ; + } +} + +bool GxsChannelFilesStatusWidget::haveFile(FileInfo& info) +{ + bool already_has_file = rsFiles->alreadyHaveFile(mFile.mHash, info); + + if(!already_has_file) + if(!(rsFiles->FileDetails(mFile.mHash, RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, info) && info.downloadStatus==FT_STATE_COMPLETE)) + return false; + + // We need the code below because FileDetails() returns fileInfo.path as the directory when the file in COMPLETE and + // as a full path when the file is shared. The former is inconsistent with the documentation in rstypes.h, but I'm not + // sure what are the implications of changing the code in libretroshare so that the full path is always returned. + + QFileInfo finfo; + + if(QDir(QString::fromUtf8(info.path.c_str())).exists()) + finfo.setFile(QString::fromUtf8(info.path.c_str()),QString::fromUtf8(info.fname.c_str())); + else if(QFile(QString::fromUtf8(info.path.c_str())).exists()) + finfo.setFile(QString::fromUtf8(info.path.c_str())); + else + { + RsErr() << "Cannot find file!" << std::endl; + return false; + } + + info.path = finfo.absoluteFilePath().toStdString(); + return true; } void GxsChannelFilesStatusWidget::openFile() { FileInfo fileInfo; - if (!rsFiles->alreadyHaveFile(mFile.mHash, fileInfo)) { + if(!haveFile(fileInfo)) return; - } - /* open file with a suitable application */ - QFileInfo qinfo; - qinfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); - if (qinfo.exists()) { - if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + QFileInfo finfo; + finfo.setFile(QString::fromUtf8(fileInfo.path.c_str())); + + if (finfo.exists()) { + if (!RsUrlHandler::openUrl(QUrl::fromLocalFile(finfo.absoluteFilePath()))) { std::cerr << "GxsChannelFilesStatusWidget(): can't open file " << fileInfo.path << std::endl; } }else{ diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h index 7ae09ce6b..0dbb5c072 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.h @@ -53,6 +53,7 @@ private slots: private: void setSize(uint64_t size); + bool haveFile(FileInfo& info); private: enum State diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui index 2c51ded6c..e8ee2d512 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelFilesStatusWidget.ui @@ -6,8 +6,8 @@ 0 0 - 421 - 29 + 473 + 36 @@ -139,7 +139,7 @@ - + 0 diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp index 856ef32e1..0796b6ce1 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostFilesModel.cpp @@ -342,10 +342,20 @@ public: case RsGxsChannelPostFilesModel::COLUMN_FILES_FILE: { FileInfo fi1,fi2; - rsFiles->FileDetails(f1.mHash,RS_FILE_HINTS_DOWNLOAD,fi1); - rsFiles->FileDetails(f2.mHash,RS_FILE_HINTS_DOWNLOAD,fi2); + bool r1 = rsFiles->FileDetails(f1.mHash,RS_FILE_HINTS_DOWNLOAD,fi1); + bool r2 = rsFiles->FileDetails(f2.mHash,RS_FILE_HINTS_DOWNLOAD,fi2); - return (ord==Qt::AscendingOrder)?(fi1.transferedfi2.transfered); + if(r1 && r2) + return (ord==Qt::AscendingOrder)?(fi1.transferedfi2.transfered); + else + { + FileInfo fitmp; + + if(!r1 && rsFiles->alreadyHaveFile(f1.mHash,fitmp)) fi1.downloadStatus = FT_STATE_COMPLETE; + if(!r2 && rsFiles->alreadyHaveFile(f2.mHash,fitmp)) fi2.downloadStatus = FT_STATE_COMPLETE; + + return (ord==Qt::AscendingOrder)?(fi1.downloadStatusfi2.downloadStatus); + } } } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp index e9be3e6ed..a42587d85 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp @@ -176,6 +176,25 @@ int RsGxsChannelPostsModel::rowCount(const QModelIndex& parent) const return 0; } +int RsGxsChannelPostsModel::columnCount(int row) const +{ + if(mTreeMode == TREE_MODE_GRID) + { + if(row+1 == rowCount()) + { + int r = ((int)mFilteredPosts.size() % (int)mColumns); + + if(r > 0) + return r; + else + return columnCount(); + } + else + return columnCount(); + } + else + return 2; +} int RsGxsChannelPostsModel::columnCount(const QModelIndex &/*parent*/) const { if(mTreeMode == TREE_MODE_GRID) @@ -245,7 +264,7 @@ bool RsGxsChannelPostsModel::convertRefPointerToTabEntry(quintptr ref, uint32_t& QModelIndex RsGxsChannelPostsModel::index(int row, int column, const QModelIndex & parent) const { - if(row < 0 || column < 0 || column >= (int)mColumns) + if(row < 0 || column < 0 || row >= rowCount() || column >= columnCount(row)) return QModelIndex(); quintptr ref = getChildRef(parent.internalId(),(mTreeMode == TREE_MODE_GRID)?(column + row*mColumns):row); diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h index 42dcbb9f7..c447f11a3 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h @@ -105,6 +105,7 @@ public: QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; + int columnCount(int row) const; // columns in the row of this particular index. std::vector > getPostVersions(const RsGxsMessageId& mid) const; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp index 35f8df044..2e292444e 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.cpp @@ -411,7 +411,7 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI connect(ui->channelPostFiles_TV->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumnPostFiles(int,Qt::SortOrder))); connect(ui->channelFiles_TV->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumnFiles(int,Qt::SortOrder))); - connect(ui->channelPostFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelFilesContextMenu(QPoint))); + connect(ui->channelPostFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelPostFilesContextMenu(QPoint))); connect(ui->channelFiles_TV,SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showChannelFilesContextMenu(QPoint))); connect(ui->postsTree->selectionModel(),SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),this,SLOT(showPostDetails())); @@ -504,6 +504,30 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI }, mEventHandlerId, RsEventType::GXS_CHANNELS ); } +void GxsChannelPostsWidgetWithModel::keyPressEvent(QKeyEvent *e) +{ + QModelIndex index = ui->postsTree->selectionModel()->currentIndex(); + + if(index.isValid() && mChannelPostsModel->getMode() == RsGxsChannelPostsModel::TREE_MODE_GRID) + { + int n = mChannelPostsModel->columnCount(index.row())-1; + + if(e->key() == Qt::Key_Left && index.column()==0) + { + ui->postsTree->setCurrentIndex(index.sibling(index.row(),n)); + e->accept(); + return; + } + if(e->key() == Qt::Key_Right && index.column()==n) + { + ui->postsTree->setCurrentIndex(index.sibling(index.row(),0)); + e->accept(); + return; + } + } + + GxsMessageFrameWidget::keyPressEvent(e); +} void GxsChannelPostsWidgetWithModel::resizeEvent(QResizeEvent *e) { GxsMessageFrameWidget::resizeEvent(e); @@ -1344,13 +1368,26 @@ void GxsChannelPostsWidgetWithModel::insertChannelDetails(const RsGxsChannelGrou showPostDetails(); } - -void GxsChannelPostsWidgetWithModel::showChannelFilesContextMenu(QPoint /*p*/) +void GxsChannelPostsWidgetWithModel::showChannelFilesContextMenu(QPoint p) { - QMenu contextMnu(this) ; + QModelIndex index = ui->channelFiles_TV->indexAt(p); - QAction *action = contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink())); - action->setData(QVariant::fromValue(sender())); + if(!index.isValid()) + return; + + QMenu contextMnu(this) ; + contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink()))->setData(QVariant::fromValue(index)); + contextMnu.exec(QCursor::pos()); +} +void GxsChannelPostsWidgetWithModel::showChannelPostFilesContextMenu(QPoint p) +{ + QModelIndex index = ui->channelPostFiles_TV->indexAt(p); + + if(!index.isValid()) + return; + + QMenu contextMnu(this) ; + contextMnu.addAction(QIcon(), tr("Copy Retroshare link"), this, SLOT(copyChannelFilesLink()))->setData(QVariant::fromValue(index)); contextMnu.exec(QCursor::pos()); } @@ -1358,16 +1395,11 @@ void GxsChannelPostsWidgetWithModel::copyChannelFilesLink() { // Block the popup if no results available QAction *action = dynamic_cast(sender()); - RSTreeView *tree = dynamic_cast(action->data().value()); - - QModelIndexList sel = tree->selectionModel()->selection().indexes(); - - if(sel.empty()) - return; + QModelIndex s = action->data().toModelIndex(); ChannelPostFileInfo file; - if(!static_cast(tree->model())->getFileData(sel.front(),file)) + if(!static_cast(s.model())->getFileData(s,file)) return; RetroShareLink link = RetroShareLink::createFile(QString::fromUtf8(file.mName.c_str()), file.mSize, QString::fromStdString(file.mHash.toStdString())); diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h index c325c722b..8891b57dd 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidgetWithModel.h @@ -139,6 +139,7 @@ protected: /* GxsMessageFrameWidget */ virtual void setAllMessagesReadDo(bool read) override; virtual void resizeEvent(QResizeEvent *e) override; + virtual void keyPressEvent(QKeyEvent *e) override; private slots: void showPostDetails(); @@ -166,6 +167,7 @@ public slots: void sortColumnPostFiles(int col,Qt::SortOrder so); void updateCommentsCount(int n); void showChannelFilesContextMenu(QPoint p); + void showChannelPostFilesContextMenu(QPoint p); void copyChannelFilesLink(); private: diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index c92057c29..ff3771075 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -15,6 +15,7 @@ icons/svg/display_options.svg icons/svg/listlayout.svg icons/svg/gridlayout.svg + icons/svg/people2.svg icons/stars/star0.png icons/stars/star1.png icons/stars/star2.png diff --git a/retroshare-gui/src/gui/icons/svg/wire-notify.svg b/retroshare-gui/src/gui/icons/svg/wire-notify.svg new file mode 100644 index 000000000..7d4d6ccce --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/wire-notify.svg @@ -0,0 +1,56 @@ + + + +image/svg+xml diff --git a/retroshare-gui/src/gui/icons/svg/wire.svg b/retroshare-gui/src/gui/icons/svg/wire.svg new file mode 100644 index 000000000..9a8029016 --- /dev/null +++ b/retroshare-gui/src/gui/icons/svg/wire.svg @@ -0,0 +1,56 @@ + + + +image/svg+xml diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.h b/retroshare-gui/src/gui/msgs/MessageComposer.h index 0df2dbd8e..040681095 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.h +++ b/retroshare-gui/src/gui/msgs/MessageComposer.h @@ -255,7 +255,7 @@ private: QList tagLabels; // needed to send system flags with reply - unsigned msgFlags; + unsigned int msgFlags; RSTreeWidgetItemCompareRole *m_compareRole; QCompleter *m_completer; diff --git a/retroshare-gui/src/gui/msgs/MessageModel.cpp b/retroshare-gui/src/gui/msgs/MessageModel.cpp index a19087dc0..6116e42b4 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.cpp +++ b/retroshare-gui/src/gui/msgs/MessageModel.cpp @@ -459,14 +459,6 @@ QVariant RsMessageModel::sortRole(const Rs::Msgs::MsgInfoSummary& fmpe,int colum case COLUMN_THREAD_SPAM: return QVariant((fmpe.msgflags & RS_MSG_SPAM)? 1:0); - case COLUMN_THREAD_TO: { - QString name; - - if(GxsIdTreeItemDelegate::computeName(RsGxsId(fmpe.to.toStdString()),name)) - return name; - return ""; //Not Found - } - case COLUMN_THREAD_AUTHOR:{ QString name; @@ -474,8 +466,10 @@ QVariant RsMessageModel::sortRole(const Rs::Msgs::MsgInfoSummary& fmpe,int colum return name; return ""; //Not Found } - default: - return displayRole(fmpe,column); + + case COLUMN_THREAD_TO: // fallthrough. In this case, the "to" field is not filled because the msg potentially has multiple destinations. + default: + return displayRole(fmpe,column); } } @@ -585,7 +579,18 @@ QVariant RsMessageModel::userRole(const Rs::Msgs::MsgInfoSummary& fmpe,int col) { case COLUMN_THREAD_AUTHOR: return QVariant(QString::fromStdString(fmpe.from.toStdString())); case COLUMN_THREAD_MSGID: return QVariant(QString::fromStdString(fmpe.msgId)); - case COLUMN_THREAD_TO: return QVariant(QString::fromStdString(fmpe.to.toStdString())); + case COLUMN_THREAD_TO: + { + // First check if the .to field is filled. + + if(!fmpe.to.toStdString().empty()) + return QVariant(QString::fromStdString(fmpe.to.toStdString())); + + // In the Send box, .to is never filled. In this case we look into destinations. + + if(fmpe.destinations.size()==1) + return QVariant(QString::fromStdString((*fmpe.destinations.begin()).toStdString())); + } default: return QVariant(); } @@ -685,6 +690,10 @@ void RsMessageModel::setCurrentBox(Rs::Msgs::BoxName bn) } } +Rs::Msgs::BoxName RsMessageModel::currentBox() const +{ + return mCurrentBox; +} void RsMessageModel::setQuickViewFilter(QuickViewFilter fn) { if(fn != mQuickViewFilter) diff --git a/retroshare-gui/src/gui/msgs/MessageModel.h b/retroshare-gui/src/gui/msgs/MessageModel.h index fb8c6daa5..d23b21f86 100644 --- a/retroshare-gui/src/gui/msgs/MessageModel.h +++ b/retroshare-gui/src/gui/msgs/MessageModel.h @@ -100,6 +100,7 @@ public: // This method will asynchroneously update the data void setCurrentBox(Rs::Msgs::BoxName bn) ; + Rs::Msgs::BoxName currentBox() const ; void setQuickViewFilter(QuickViewFilter fn) ; void setFilter(FilterType filter_type, const QStringList& strings) ; diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp index d74505e63..0d2e934f2 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -738,7 +738,8 @@ void MessageWidget::remove() return; } - bool deleteReal = false; +#ifdef TO_REMOVE + bool deleteReal = false; if (msgInfo.msgflags & RS_MSG_TRASH) { deleteReal = true; } else { @@ -763,8 +764,8 @@ void MessageWidget::remove() deleteLater(); } } - - emit messageRemoved(); +#endif + emit messageRemovalRequested(currMsgId); } void MessageWidget::print() @@ -905,10 +906,8 @@ void MessageWidget::sendInvite() if(mi.from.type()!=MsgAddress::MSG_ADDRESS_TYPE_RSGXSID) return; - if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want send a invite with your Certificate?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Cancel))== QMessageBox::Yes) - { - MessageComposer::sendInvite(mi.from.toGxsId(),false); - } + //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want to send an invite with your Certificate?"),QMessageBox::Yes, QMessageBox::No))== QMessageBox::Yes) + MessageComposer::sendInvite(mi.from.toGxsId(),false); } void MessageWidget::setToolbarButtonStyle(Qt::ToolButtonStyle style) diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.h b/retroshare-gui/src/gui/msgs/MessageWidget.h index d6465e5cf..53b043720 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.h +++ b/retroshare-gui/src/gui/msgs/MessageWidget.h @@ -61,6 +61,7 @@ public: signals: void messageRemoved(); + void messageRemovalRequested(std::string); private slots: void reply(); diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp index 1fb55821f..be9eedf6b 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp @@ -95,6 +95,7 @@ #define ROW_SENTBOX 3 #define ROW_TRASHBOX 4 +// #define DEBUG_MESSAGES_DIALOG 1 class MessageSortFilterProxyModel: public QSortFilterProxyModel { @@ -144,7 +145,7 @@ MessagesDialog::MessagesDialog(QWidget *parent) msgWidget = new MessageWidget(true, this); ui.msgLayout->addWidget(msgWidget); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); connectActions(); @@ -365,15 +366,18 @@ void MessagesDialog::preModelUpdate() if (m.isValid()) { mTmpSavedCurrentId = m.sibling(m.row(), RsMessageModel::COLUMN_THREAD_MSGID).data(RsMessageModel::MsgIdRole).toString(); } - +#ifdef DEBUG_MESSAGES_DIALOG std::cerr << "Pre-change: saving selection for " << mTmpSavedSelectedIds.size() << " indexes" << std::endl; +#endif } void MessagesDialog::postModelUpdate() { // restore selection +#ifdef DEBUG_MESSAGES_DIALOG std::cerr << "Post-change: restoring selection for " << mTmpSavedSelectedIds.size() << " indexes" << std::endl; +#endif QItemSelection sel; foreach(const QString& s,mTmpSavedSelectedIds) @@ -838,7 +842,7 @@ void MessagesDialog::openAsWindow() } msgWidget->activateWindow(); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); /* window will destroy itself! */ } @@ -858,7 +862,7 @@ void MessagesDialog::openAsTab() ui.tabWidget->addTab(msgWidget,FilesDefs::getIconFromQtResourcePath(IMAGE_MAIL), msgWidget->subject(true)); ui.tabWidget->setCurrentWidget(msgWidget); - connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); + connect(msgWidget, SIGNAL(messageRemovalRequested(std::string)), this, SLOT(removemessage())); /* window will destroy itself! */ } @@ -921,9 +925,9 @@ void MessagesDialog::changeBox(int box_row) ui.messageTreeWidget->setPlaceholderText(placeholderText); ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_READ,box_row!=ROW_INBOX); - ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_STAR,box_row==ROW_OUTBOX); - ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_SPAM,box_row==ROW_OUTBOX); - ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_TAGS,box_row==ROW_OUTBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_STAR,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_SPAM,box_row!=ROW_INBOX); + ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_TAGS,box_row!=ROW_INBOX); ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_MSGID,true); ui.messageTreeWidget->setColumnHidden(RsMessageModel::COLUMN_THREAD_CONTENT,true); } @@ -1292,7 +1296,7 @@ void MessagesDialog::updateMessageSummaryList() /* calculating the new messages */ std::list msgList; - rsMail->getMessageSummaries(Rs::Msgs::BoxName::BOX_ALL,msgList); + rsMail->getMessageSummaries(mMessageModel->currentBox(),msgList); QMap tagCount; diff --git a/retroshare-gui/src/gui/notifyqt.h b/retroshare-gui/src/gui/notifyqt.h index 0f9ae11e2..5782ef5b7 100644 --- a/retroshare-gui/src/gui/notifyqt.h +++ b/retroshare-gui/src/gui/notifyqt.h @@ -117,7 +117,6 @@ class NotifyQt: public QObject, public NotifyClient void chatStatusChanged(const ChatId&,const QString&) const ; void chatCleared(const ChatId&) const ; void peerHasNewCustomStateString(const QString& /* peer_id */, const QString& /* status_string */) const ; - void gotTurtleSearchResult(qulonglong search_id,FileDetail file) const ; void peerHasNewAvatar(const QString& peer_id) const ; void ownAvatarChanged() const ; void ownStatusMessageChanged() const ; diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss index ee320a012..7497440c5 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss @@ -2552,3 +2552,10 @@ OpModeStatus[opMode="Minimal"] { [WrongValue="true"] { background-color: #702020; } + +/**** The Wire ****/ + +QLabel#label_masthead{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss index 923477e11..061ca0518 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Light.qss @@ -2687,6 +2687,11 @@ PulseReply QLabel#label_groupName{ color: #5b7083; } +QLabel#label_masthead{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} + /**** PhotoShare ****/ AlbumItem QFrame#albumFrame { border: 2px solid #CCCCCC; diff --git a/retroshare-gui/src/gui/settings/AppearancePage.cpp b/retroshare-gui/src/gui/settings/AppearancePage.cpp index 2fb86e5a2..8ad086ae9 100755 --- a/retroshare-gui/src/gui/settings/AppearancePage.cpp +++ b/retroshare-gui/src/gui/settings/AppearancePage.cpp @@ -74,8 +74,13 @@ AppearancePage::AppearancePage(QWidget * parent, Qt::WindowFlags flags) foreach (QString code, LanguageSupport::languageCodes()) { ui.cmboLanguage->addItem(FilesDefs::getIconFromQtResourcePath(":/images/flags/" + code + ".png"), LanguageSupport::languageName(code), code); } - foreach (QString style, QStyleFactory::keys()) { - ui.cmboStyle->addItem(style, style.toLower()); + + // Note: apparently, on some linux systems (e.g. Debian 11), the gtk2 style makes Qt libs crash when the environment variable is not set. + // So we first check that it's here before start. + + foreach (QString style, QStyleFactory::keys()) { + if(style.toLower() != "gtk2" || (getenv("QT_QPA_PLATFORMTHEME")!=nullptr && !strcmp(getenv("QT_QPA_PLATFORMTHEME"),"gtk2"))) + ui.cmboStyle->addItem(style, style.toLower()); } QMap styleSheets; @@ -266,9 +271,9 @@ void AppearancePage::load() index = ui.mainPageButtonType_CB->findData(Settings->getPageButtonLoc()); if (index != 0) { - ui.cmboTollButtonsStyle->hide(); - }else { - ui.cmboTollButtonsStyle->show(); + ui.cmboTollButtonsStyle->show(); + }else { + ui.cmboTollButtonsStyle->hide(); } whileBlocking(ui.mainPageButtonType_CB)->setCurrentIndex(!Settings->getPageButtonLoc()); diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.cc b/retroshare-gui/src/gui/settings/JsonApiPage.cc index a824a5fa0..67e5f22b8 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.cc +++ b/retroshare-gui/src/gui/settings/JsonApiPage.cc @@ -23,11 +23,14 @@ #include "rsharesettings.h" #include "jsonapi/jsonapi.h" #include "util/misc.h" +#include "util/qtthreadsutils.h" #include #include #include +#define IMAGE_LEDOFF ":/images/ledoff1.png" +#define IMAGE_LEDON ":/images/ledon1.png" JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) { @@ -57,9 +60,31 @@ JsonApiPage::JsonApiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this); ui.listenAddressLineEdit->setValidator(ipValidator); + ui.providersListView->setSelectionMode(QAbstractItemView::NoSelection); // prevents edition. + mEventHandlerId = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr /* event */) + { + std::cerr << "Caught JSONAPI event!" << std::endl; + RsQThreadUtils::postToObject([=]() { load(); }, this ); + }, + mEventHandlerId, RsEventType::JSON_API ); } +JsonApiPage::~JsonApiPage() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); +} +QString JsonApiPage::helpText() const +{ + return tr("

  Webinterface

\ +

Retroshare provides a JSON API allowing other softwares to communicate with its core using token-controlled HTTP requests to http://localhost:[port]. \ + Please refer to the Retroshare documentation for how to use this feature.

\ +

Unless you know what you're doing, you shouldn't need to change anything in this page. \ + The web interface for instance will automatically register its own token to the JSON API which will be visible \ + in the list of authenticated tokens after you enable it.

"); +} void JsonApiPage::enableJsonApi(bool checked) { ui.addTokenPushButton->setEnabled(checked); @@ -93,9 +118,9 @@ bool JsonApiPage::updateParams() void JsonApiPage::load() { - whileBlocking(ui.portSpinBox)->setValue(Settings->getJsonApiPort()); - whileBlocking(ui.listenAddressLineEdit)->setText(Settings->getJsonApiListenAddress()); - whileBlocking(ui.enableCheckBox)->setChecked(Settings->getJsonApiEnabled()); + whileBlocking(ui.portSpinBox)->setValue(rsJsonApi->listeningPort()); + whileBlocking(ui.listenAddressLineEdit)->setText(QString::fromStdString(rsJsonApi->getBindingAddress())); + whileBlocking(ui.enableCheckBox)->setChecked(rsJsonApi->isRunning()); QStringList newTk; @@ -104,10 +129,20 @@ void JsonApiPage::load() QString::fromStdString(it.first) + ":" + QString::fromStdString(it.second) ); - whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); -} + whileBlocking(ui.tokensListView)->setModel(new QStringListModel(newTk)); -QString JsonApiPage::helpText() const { return ""; } + QStringList newTk2; + + for(const auto& it : rsJsonApi->getResourceProviders()) + newTk2.push_back( QString::fromStdString(it.get().getName())) ; + + whileBlocking(ui.providersListView)->setModel(new QStringListModel(newTk2)); + + if(rsJsonApi->isRunning()) + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDON)) ; + else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; +} bool JsonApiPage::checkStartJsonApi() { diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.h b/retroshare-gui/src/gui/settings/JsonApiPage.h index 7f69bbd1e..ef28a4294 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.h +++ b/retroshare-gui/src/gui/settings/JsonApiPage.h @@ -20,6 +20,8 @@ #pragma once +#include "retroshare/rsevents.h" + #include "retroshare-gui/configpage.h" #include "gui/common/FilesDefs.h" #include "ui_JsonApiPage.h" @@ -31,7 +33,7 @@ class JsonApiPage : public ConfigPage public: JsonApiPage(QWidget * parent = nullptr, Qt::WindowFlags flags = 0); - ~JsonApiPage() override = default; + ~JsonApiPage() override ; virtual QPixmap iconPixmap() const override { @@ -63,4 +65,6 @@ public slots: private: Ui::JsonApiPage ui; /// Qt Designer generated object + RsEventsHandlerId_t mEventHandlerId; }; + diff --git a/retroshare-gui/src/gui/settings/JsonApiPage.ui b/retroshare-gui/src/gui/settings/JsonApiPage.ui index 24b534712..f8d31e38f 100644 --- a/retroshare-gui/src/gui/settings/JsonApiPage.ui +++ b/retroshare-gui/src/gui/settings/JsonApiPage.ui @@ -13,7 +13,7 @@ Form - + @@ -25,13 +25,65 @@ JSON API Server - + - - - Enable RetroShare JSON API Server - - + + + + + Enable RetroShare JSON API Server + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Status: + + + + + + + + + + :/images/ledoff1.png + + + + + + + + + + + Listen Address: + + + + + + + 127.0.0.1 + + + + @@ -57,24 +109,6 @@ - - - - - - Listen Address: - - - - - - - 127.0.0.1 - - - - - @@ -110,13 +144,23 @@ - Authenticated Tokens + Authenticated Tokens: + + + + Registered services: + + + + + +
@@ -142,6 +186,8 @@ - + + + diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index 3dfe9069d..adb1d655c 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -107,6 +107,8 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) ui.hiddenpage_proxyPort_tor->setEnabled(false) ; ui.hiddenpage_localAddress->setEnabled(false) ; ui.hiddenpage_localPort->setEnabled(false) ; + ui.hiddenpage_serviceAddress->setEnabled(false) ; + ui.hiddenpage_servicePort->setEnabled(false) ; ui.testIncoming_PB->hide() ; ui.l_incomingTestResult->hide() ; ui.iconlabel_service_incoming->hide() ; diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp index c0cf3608f..915eaa679 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.cpp +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -30,6 +30,7 @@ #include "retroshare/rspeers.h" #include +#include #include #include @@ -46,6 +47,8 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags) ui._max_tr_up_per_sec_SB->setMinimum(max_tr_low); ui._max_tr_up_per_sec_SB->setMaximum(max_tr_high); + whileBlocking(ui._trustFriendNodesWithBannedFiles_CB)->setChecked(rsFiles->trustFriendNodesWithBannedFiles()); + QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ; QObject::connect(ui._max_up_SB,SIGNAL(valueChanged(int)),this,SLOT(updateMaxUploadSlots(int))) ; QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ; @@ -53,6 +56,7 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ; QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) ); QObject::connect(ui._filePermDirectDL_CB,SIGNAL(activated(int)),this,SLOT(updateFilePermDirectDL(int))); + QObject::connect(ui._trustFriendNodesWithBannedFiles_CB,SIGNAL(toggled(bool)),this,SLOT(toggleTrustFriendNodesWithBannedFiles(bool))) ; QObject::connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) ); QObject::connect(ui.autoDLColl_CB, SIGNAL(toggled(bool)), this, SLOT(updateAutoDLColl())); @@ -94,7 +98,10 @@ void TransferPage::updateIgnoreLists() std::cerr << " suffixes: " ; for(auto it(ls.begin());it!=ls.end();++it) std::cerr << "\"" << *it << "\" " ; std::cerr << std::endl; #endif } - +void TransferPage::toggleTrustFriendNodesWithBannedFiles(bool b) +{ + rsFiles->setTrustFriendNodesWithBannedFiles(b); +} void TransferPage::updateMaxTRUpRate(int b) { rsTurtle->setMaxTRForwardRate(b) ; @@ -208,11 +215,19 @@ void TransferPage::updateDefaultStrategy(int i) case 0: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; break ; - case 2: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - break ; + case 2: +#ifdef WINDOWS_SYS + if(QMessageBox::Yes != QMessageBox::warning(nullptr,tr("Warning"),tr("On Windows systems, randomly writing in the middle of large empty files may hang the software for several seconds. Do you want to use this option anyway (otherwise use \"progressive\")?"),QMessageBox::Yes,QMessageBox::No)) + { + ui._defaultStrategy_CB->setCurrentIndex(1); + return; + } +#endif + rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + break ; case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - break ; + break ; default: ; } } diff --git a/retroshare-gui/src/gui/settings/TransferPage.h b/retroshare-gui/src/gui/settings/TransferPage.h index 1a88d29d5..a2a0a1061 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.h +++ b/retroshare-gui/src/gui/settings/TransferPage.h @@ -58,7 +58,8 @@ class TransferPage: public ConfigPage void updateAutoDLColl(); void setPartialsDirectory(); void toggleAutoCheckDirectories(bool); - void updateFontSize(); + void toggleTrustFriendNodesWithBannedFiles(bool); + void updateFontSize(); void updateAutoCheckDirectories() ; void updateAutoScanDirectoriesPeriod() ; diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui index b1e7b7630..b6d8cd7ff 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.ui +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -14,7 +14,7 @@ - 0 + 1 @@ -30,7 +30,7 @@ - Edit Share + Configure shared directories @@ -443,7 +443,7 @@ p, li { white-space: pre-wrap; } true
- <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior. <span style=" font-weight:600;">Progressive</span> is a compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Streaming </span>causes the transfer to request 1MB file chunks in increasing order, facilitating preview while downloading. <span style=" font-weight:600;">Random</span> is purely random and favors swarming behavior (although not recommended on Windows systems). <span style=" font-weight:600;">Progressive</span> is a good compromise, selecting the next chunk at random within less than 50MB after the end of the partial file. That allows some randomness while preventing large empty file initialization times.</p></body></html> @@ -547,7 +547,7 @@ p, li { white-space: pre-wrap; } - + Trust friend nodes with banned files diff --git a/retroshare-gui/src/gui/settings/WebuiPage.cpp b/retroshare-gui/src/gui/settings/WebuiPage.cpp index f0006fec3..d7ff0b894 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.cpp +++ b/retroshare-gui/src/gui/settings/WebuiPage.cpp @@ -27,6 +27,7 @@ #include #include "util/misc.h" +#include "util/qtthreadsutils.h" #include "retroshare/rswebui.h" #include "retroshare/rsjsonapi.h" @@ -40,6 +41,8 @@ resource_api::ApiServerLocal* WebuiPage::apiServerLocal = 0; #endif resource_api::RsControlModule* WebuiPage::controlModule = 0; +#define IMAGE_LEDOFF ":/images/ledoff1.png" +#define IMAGE_LEDON ":/images/ledon1.png" WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) { @@ -50,11 +53,20 @@ WebuiPage::WebuiPage(QWidget */*parent*/, Qt::WindowFlags /*flags*/) connect(ui.password_LE, SIGNAL(textChanged(QString)), this, SLOT(onPasswordValueChanged(QString))); connect(ui.startWebBrowser_PB, SIGNAL(clicked()), this, SLOT(onStartWebBrowserClicked())); connect(ui.webInterfaceFilesDirectory_PB, SIGNAL(clicked()), this, SLOT(selectWebInterfaceDirectory())); + + mEventsHandlerId = 0; + + rsEvents->registerEventsHandler( [this](std::shared_ptr /* event */) + { + std::cerr << "Caught JSONAPI event in webui!" << std::endl; + RsQThreadUtils::postToObject([=]() { load(); }, this ); + }, + mEventsHandlerId, RsEventType::JSON_API ); } WebuiPage::~WebuiPage() { - + rsEvents->unregisterEventsHandler(mEventsHandlerId); } void WebuiPage::selectWebInterfaceDirectory() @@ -73,22 +85,12 @@ void WebuiPage::selectWebInterfaceDirectory() bool WebuiPage::updateParams(QString &errmsg) { std::cerr << "WebuiPage::save()" << std::endl; - bool ok = true; - bool changed = false; - if(ui.enableWebUI_CB->isChecked() != Settings->getWebinterfaceEnabled()) - changed = true; - if(ui.webInterfaceFiles_LE->text() != Settings->getWebinterfaceFilesDirectory()) - changed = true; - if(changed) - { - // store config - Settings->setWebinterfaceEnabled(ui.enableWebUI_CB->isChecked()); - Settings->setWebinterfaceFilesDirectory(ui.webInterfaceFiles_LE->text()); + // store config + Settings->setWebinterfaceEnabled(ui.enableWebUI_CB->isChecked()); + Settings->setWebinterfaceFilesDirectory(ui.webInterfaceFiles_LE->text()); - rsWebUi->setHtmlFilesDirectory(ui.webInterfaceFiles_LE->text().toStdString()); - } - return ok; + return true; } void WebuiPage::onPasswordValueChanged(QString password) @@ -112,10 +114,23 @@ void WebuiPage::onPasswordValueChanged(QString password) bool WebuiPage::restart() { - return checkStartWebui(); + if(ui.password_LE->text().isNull()) + { + QMessageBox::critical(nullptr,tr("Missing passphrase"),tr("Please set a passphrase to proect the access to the WEB interface.")); + return false; + } + + rsWebUi->setUserPassword(ui.password_LE->text().toStdString()); + rsWebUi->setHtmlFilesDirectory(ui.webInterfaceFiles_LE->text().toStdString()); + + setCursor(Qt::WaitCursor) ; + rsWebUi->restart(); + setCursor(Qt::ArrowCursor) ; + + return true; } -void WebuiPage::load() +void WebuiPage::loadParams() { std::cerr << "WebuiPage::load()" << std::endl; whileBlocking(ui.enableWebUI_CB)->setChecked(Settings->getWebinterfaceEnabled()); @@ -127,6 +142,13 @@ void WebuiPage::load() if(it != smap.end()) whileBlocking(ui.password_LE)->setText(QString::fromStdString(it->second)); + + if(rsWebUi->isRunning()) + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDON)) ; + else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; +#else + ui.statusLabelLED->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_LEDOFF)) ; #endif } @@ -138,13 +160,11 @@ QString WebuiPage::helpText() const

Warning: don't expose the webinterface to the internet, because there is no access control and no encryption. If you want to use the webinterface over the internet, use a SSH tunnel or a proxy to secure the connection.

"); } -/*static*/ bool WebuiPage::checkStartWebui() +/*static*/ bool WebuiPage::checkStartWebui() // This is supposed to be called from main(). But normally the parameters below (including the paswd + // for the webUI should be saved in p3webui instead. { - if(!Settings->getWebinterfaceEnabled()) - return false; - - rsWebUi->setHtmlFilesDirectory(Settings->getWebinterfaceFilesDirectory().toStdString()); - rsWebUi->restart(); + rsWebUi->setHtmlFilesDirectory(Settings->getWebinterfaceFilesDirectory().toStdString()); + rsWebUi->restart(); return true; } @@ -173,15 +193,21 @@ QString WebuiPage::helpText() const void WebuiPage::onEnableCBClicked(bool checked) { - ui.params_GB->setEnabled(checked); - ui.apply_PB->setEnabled(checked); - ui.startWebBrowser_PB->setEnabled(checked); - QString S; + QString errmsg; + updateParams(errmsg); - Settings->setWebinterfaceEnabled(checked); + ui.params_GB->setEnabled(checked); + ui.startWebBrowser_PB->setEnabled(checked); + ui.apply_PB->setEnabled(checked); if(checked) - checkStartWebui(); + { + if(!restart()) + { + QMessageBox::warning(0, tr("failed to start Webinterface"), "Failed to start the webinterface."); + return; + } + } else checkShutdownWebui(); } @@ -199,18 +225,12 @@ void WebuiPage::onAllIPCBClicked(bool /*checked*/) } void WebuiPage::onApplyClicked() { - rsWebUi->setUserPassword(ui.password_LE->text().toStdString()); - QString errmsg; updateParams(errmsg); - if(!restart()) - { - QMessageBox::warning(0, tr("failed to start Webinterface"), "Failed to start the webinterface."); - return; - } + restart(); - emit passwordChanged(); + load(); } void WebuiPage::onStartWebBrowserClicked() { showWebui(); } diff --git a/retroshare-gui/src/gui/settings/WebuiPage.h b/retroshare-gui/src/gui/settings/WebuiPage.h index 9ba8886ac..391612cf8 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.h +++ b/retroshare-gui/src/gui/settings/WebuiPage.h @@ -20,6 +20,8 @@ #pragma once +#include "retroshare/rsevents.h" + #include "retroshare-gui/configpage.h" #include "gui/common/FilesDefs.h" #include "ui_WebuiPage.h" @@ -42,11 +44,11 @@ public: ~WebuiPage(); /** Loads the settings for this page */ - virtual void load(); + virtual void load() override { loadParams() ; } - virtual QPixmap iconPixmap() const { return FilesDefs::getPixmapFromQtResourcePath(":/icons/settings/webinterface.svg") ; } - virtual QString pageName() const { return tr("Webinterface") ; } - virtual QString helpText() const; + virtual QPixmap iconPixmap() const override { return FilesDefs::getPixmapFromQtResourcePath(":/icons/settings/webinterface.svg") ; } + virtual QString pageName() const override { return tr("Webinterface") ; } + virtual QString helpText() const override ; // call this after start of libretroshare/Retroshare // checks the settings and starts the webinterface if required @@ -67,10 +69,9 @@ public slots: void onApplyClicked(); void onStartWebBrowserClicked(); -signals: - void passwordChanged(); - private: + virtual void loadParams(); + /** Qt Designer generated object */ Ui::WebuiPage ui; @@ -83,4 +84,6 @@ private: static resource_api::ApiServerLocal* apiServerLocal; #endif static resource_api::RsControlModule* controlModule; + + RsEventsHandlerId_t mEventsHandlerId; }; diff --git a/retroshare-gui/src/gui/settings/WebuiPage.ui b/retroshare-gui/src/gui/settings/WebuiPage.ui index 5ca37e9b6..91d59736f 100644 --- a/retroshare-gui/src/gui/settings/WebuiPage.ui +++ b/retroshare-gui/src/gui/settings/WebuiPage.ui @@ -6,8 +6,8 @@ 0 0 - 960 - 717 + 570 + 646 @@ -15,11 +15,45 @@ - - - Enable Retroshare WEB Interface - - + + + + + Enable Retroshare WEB Interface + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Status: + + + + + + + + + + :/images/ledoff1.png + + + + diff --git a/retroshare-gui/src/gui/settings/rsettingswin.cpp b/retroshare-gui/src/gui/settings/rsettingswin.cpp index 46c85ea8e..1d3d4ecc3 100644 --- a/retroshare-gui/src/gui/settings/rsettingswin.cpp +++ b/retroshare-gui/src/gui/settings/rsettingswin.cpp @@ -178,10 +178,7 @@ SettingsPage::initStackedWidget() JsonApiPage *jsonapi_p = new JsonApiPage() ; addPage(jsonapi_p); #ifdef RS_WEBUI - WebuiPage *webui_p = new WebuiPage() ; - addPage(new WebuiPage() ); - - QObject::connect(webui_p,SIGNAL(passwordChanged()),jsonapi_p,SLOT(load())); + addPage(new WebuiPage()); #endif #endif diff --git a/retroshare-gui/src/gui/statistics/Histogram.cpp b/retroshare-gui/src/gui/statistics/Histogram.cpp index 5884d8306..77e272b31 100644 --- a/retroshare-gui/src/gui/statistics/Histogram.cpp +++ b/retroshare-gui/src/gui/statistics/Histogram.cpp @@ -39,9 +39,9 @@ void Histogram::draw(QPainter */*painter*/) const void Histogram::insert(double val) { - long int bin = (uint32_t)floor((val - mStart)/(mEnd - mStart) * mBins.size()); + long int bin = (long int)floor((val - mStart)/(mEnd - mStart) * mBins.size()); - if(bin >= 0 && bin < mBins.size()) + if(bin >= 0 && bin < (long int)mBins.size()) ++mBins[bin]; } diff --git a/retroshare-gui/src/gui/statistics/Histogram.h b/retroshare-gui/src/gui/statistics/Histogram.h index 91ec84b5d..3931b15db 100644 --- a/retroshare-gui/src/gui/statistics/Histogram.h +++ b/retroshare-gui/src/gui/statistics/Histogram.h @@ -20,7 +20,7 @@ #include #include -#include +#include class QPainter; diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 3361597c8..e33fe795d 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -536,11 +536,9 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); // avoid clashes between infos from threads. // - qRegisterMetaType("FileDetail") ; qRegisterMetaType("RsPeerId") ; std::cerr << "connecting signals and slots" << std::endl ; -// QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->transfersDialog->searchDialog ,SLOT(updateFiles(qulonglong,FileDetail))) ; QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ; QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ; QObject::connect(notify,SIGNAL(diskFull(int,int)) ,w ,SLOT(displayDiskSpaceWarning(int,int))) ; diff --git a/retroshare-gui/src/qss/retroclassic.qss b/retroshare-gui/src/qss/retroclassic.qss index 02da3c18f..df8802f3a 100644 --- a/retroshare-gui/src/qss/retroclassic.qss +++ b/retroshare-gui/src/qss/retroclassic.qss @@ -178,3 +178,9 @@ IdDialog QWidget#idTreeWidget { selection-background-color: #9FCBFF; show-decoration-selected: 1; } + +/* Wire */ +QLabel#label_masthead{ + border: 2px solid #CCCCCC; + border-radius: 4px; +} diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index b8e8365e0..93734b454 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -1220,6 +1220,7 @@ gxsthewire { gui/TheWire/PulseReply.h \ gui/TheWire/PulseReplySeperator.h \ gui/TheWire/PulseMessage.h \ + gui/TheWire/CustomFrame.h \ FORMS += gui/TheWire/WireDialog.ui \ gui/TheWire/WireGroupItem.ui \ @@ -1242,6 +1243,7 @@ gxsthewire { gui/TheWire/PulseReply.cpp \ gui/TheWire/PulseReplySeperator.cpp \ gui/TheWire/PulseMessage.cpp \ + gui/TheWire/CustomFrame.cpp \ RESOURCES += gui/TheWire/TheWire_images.qrc } diff --git a/retroshare-webui b/retroshare-webui index b0ddb0918..542a8c07b 160000 --- a/retroshare-webui +++ b/retroshare-webui @@ -1 +1 @@ -Subproject commit b0ddb09184e8fff86bd3325e00c6d4b329ae1790 +Subproject commit 542a8c07bd02f9bb9082f7aba5aaaed54e643fc1