Merge branch 'master' into extra_locators_merge

This commit is contained in:
Gioacchino Mazzurco 2018-07-02 12:22:23 +02:00
commit 1dd707710b
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
241 changed files with 20454 additions and 3066 deletions

View file

@ -446,7 +446,8 @@ QString TorManagerPrivate::torExecutablePath() const
{
SettingsObject settings(QStringLiteral("tor"));
QString path = settings.read("executablePath").toString();
if (!path.isEmpty())
if (!path.isEmpty() && QFile::exists(path))
return path;
#ifdef Q_OS_WIN
@ -456,6 +457,7 @@ QString TorManagerPrivate::torExecutablePath() const
#endif
path = qApp->applicationDirPath();
if (QFile::exists(path + filename))
return path + filename;

View file

@ -36,6 +36,8 @@
#include "gui/settings/rsharesettings.h"
#include "util/QtVersion.h"
#include "util/RsAction.h"
#include "util/misc.h"
#include "util/rstime.h"
#include <retroshare/rsexpr.h>
#include <retroshare/rsfiles.h>
@ -81,6 +83,8 @@
#define MAX_SEARCH_RESULTS 3000
#define DISABLE_SEARCH_WHILE_TYPING 1
// Define to avoid using the search in treeview, because it is really slow for now.
//
//#define DONT_USE_SEARCH_IN_TREE_VIEW 1
@ -146,7 +150,7 @@ public:
/** Constructor */
SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareDirModel *_flat_model,QWidget *parent)
: RsAutoUpdatePage(1000,parent),model(NULL)
: RsAutoUpdatePage(1000,parent), model(NULL)
{
/* Invoke the Qt Designer generated object setup routine */
ui.setupUi(this);
@ -163,18 +167,26 @@ SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareD
tree_model = _tree_model ;
flat_model = _flat_model ;
connect(flat_model, SIGNAL(layoutChanged()), this, SLOT(updateDirTreeView()) );
// For filtering items we use a trick: the underlying model will use this FilterRole role to highlight selected items
// while the filterProxyModel will select them using the pre-chosen string "filtered".
tree_proxyModel = new SFDSortFilterProxyModel(tree_model, this);
tree_proxyModel->setSourceModel(tree_model);
tree_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
tree_proxyModel->setSortRole(RetroshareDirModel::SortRole);
tree_proxyModel->sort(COLUMN_NAME);
tree_proxyModel->setFilterRole(RetroshareDirModel::FilterRole);
tree_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ;
flat_proxyModel = new SFDSortFilterProxyModel(flat_model, this);
flat_proxyModel->setSourceModel(flat_model);
flat_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
flat_proxyModel->setSortRole(RetroshareDirModel::SortRole);
flat_proxyModel->sort(COLUMN_NAME);
flat_proxyModel->setFilterRole(RetroshareDirModel::FilterRole);
flat_proxyModel->setFilterRegExp(QRegExp(QString(RETROSHARE_DIR_MODEL_FILTER_STRING))) ;
// Mr.Alice: I removed this because it causes a crash for some obscur reason. Apparently when the model is changed, the proxy model cannot
// deal with the change by itself. Should I call something specific? I've no idea. Removing this does not seem to cause any harm either.
@ -185,7 +197,14 @@ SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareD
connect(ui.filterClearButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
connect(ui.filterStartButton, SIGNAL(clicked()), this, SLOT(startFilter()));
connect(ui.filterPatternLineEdit, SIGNAL(returnPressed()), this, SLOT(startFilter()));
connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged()));
connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onFilterTextEdited()));
//Hidden by default, shown on onFilterTextEdited
ui.filterClearButton->hide();
ui.filterStartButton->hide();
// mFilterTimer = new RsProtectedTimer( this );
// mFilterTimer->setSingleShot( true ); // Ensure the timer will fire only once after it was started
// connect(mFilterTimer, SIGNAL(timeout()), this, SLOT(filterRegExpChanged()));
/* Set header resize modes and initial section sizes */
QHeaderView * header = ui.dirTreeView->header () ;
@ -229,12 +248,6 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent)
// load settings
processSettings(true);
// Force to show columns even if hidden in setting
ui.dirTreeView->setColumnHidden(COLUMN_NAME, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_SIZE, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_AGE, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_FRIEND_ACCESS, false) ;
// Setup the current view model.
//
changeCurrentViewModel(ui.viewType_CB->currentIndex()) ;
@ -260,16 +273,11 @@ RemoteSharedFilesDialog::RemoteSharedFilesDialog(QWidget *parent)
ui.checkButton->hide() ;
connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadRemoteSelected()));
connect(ui.dirTreeView, SIGNAL( expanded(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
connect(ui.dirTreeView, SIGNAL( doubleClicked(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
connect(ui.dirTreeView, SIGNAL( expanded(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
connect(ui.dirTreeView, SIGNAL( doubleClicked(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
// load settings
processSettings(true);
// Force to show columns even if hidden in setting
ui.dirTreeView->setColumnHidden(COLUMN_NAME, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_SIZE, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_AGE, false) ;
// Setup the current view model.
//
changeCurrentViewModel(ui.viewType_CB->currentIndex()) ;
@ -346,7 +354,7 @@ void LocalSharedFilesDialog::processSettings(bool bLoad)
}
void RemoteSharedFilesDialog::processSettings(bool bLoad)
{
Settings->beginGroup("SharedFilesDialog");
Settings->beginGroup("RemoteSharedFilesDialog");
if (bLoad) {
// load settings
@ -420,15 +428,11 @@ void SharedFilesDialog::changeCurrentViewModel(int viewTypeIndex)
ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, COLUMN_NAME, COLUMN_WN_VISU_DIR) ;
// recursRestoreExpandedItems(ui.dirTreeView->rootIndex(),expanded_indexes);
FilterItems();
FilterItems();
}
void LocalSharedFilesDialog::showProperColumns()
{
ui.dirTreeView->setColumnHidden(COLUMN_NAME, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_SIZE, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_AGE, false) ;
if(model == tree_model)
{
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
@ -454,10 +458,6 @@ void LocalSharedFilesDialog::showProperColumns()
}
void RemoteSharedFilesDialog::showProperColumns()
{
ui.dirTreeView->setColumnHidden(COLUMN_NAME, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_SIZE, false) ;
ui.dirTreeView->setColumnHidden(COLUMN_AGE, false) ;
if(model == tree_model)
{
ui.dirTreeView->setColumnHidden(COLUMN_FILENB, false) ;
@ -509,53 +509,63 @@ void RemoteSharedFilesDialog::spawnCustomPopupMenu( QPoint point )
{
if (!rsPeers) return; /* not ready yet! */
QMenu *contextMenu = new QMenu(this);
QModelIndex idx = ui.dirTreeView->indexAt(point) ;
if (!idx.isValid()) return;
QModelIndex midx = proxyModel->mapToSource(idx) ;
if (!midx.isValid()) return;
currentFile = model->data(midx, RetroshareDirModel::FileNameRole).toString() ;
int type = model->getType(midx) ;
if (type != DIR_TYPE_DIR && type != DIR_TYPE_FILE) return;
QMenu contextMnu( this ) ;
collCreateAct->setEnabled(true);
collOpenAct->setEnabled(true);
QMenu collectionMenu(tr("Collection"), this);
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
collectionMenu.addAction(collCreateAct);
collectionMenu.addAction(collOpenAct);
QModelIndexList list = ui.dirTreeView->selectionModel()->selectedRows() ;
if(type == DIR_TYPE_DIR || list.size() > 1)
if (idx.isValid())
{
QAction *downloadActI = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download..." ), &contextMnu ) ;
connect( downloadActI , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelectedInteractive() ) ) ;
contextMnu.addAction( downloadActI) ;
}
else
{
QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), &contextMnu ) ;
connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ;
contextMnu.addAction( downloadAct) ;
QModelIndex midx = proxyModel->mapToSource(idx) ;
if (midx.isValid())
{
currentFile = model->data(midx, RetroshareDirModel::FileNameRole).toString() ;
int type = model->getType(midx) ;
if ( (type == DIR_TYPE_DIR) || (type == DIR_TYPE_FILE) )
{
collCreateAct->setEnabled(true);
collOpenAct->setEnabled(true);
QModelIndexList list = ui.dirTreeView->selectionModel()->selectedRows() ;
if(type == DIR_TYPE_DIR || list.size() > 1)
{
QAction *downloadActI = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download..." ), contextMenu ) ;
connect( downloadActI , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelectedInteractive() ) ) ;
contextMenu->addAction( downloadActI) ;
}
else
{
QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr( "Download" ), contextMenu ) ;
connect( downloadAct , SIGNAL( triggered() ), this, SLOT( downloadRemoteSelected() ) ) ;
contextMenu->addAction( downloadAct) ;
}
contextMenu->addSeparator() ;//------------------------------------
contextMenu->addAction( copylinkAct) ;
contextMenu->addAction( sendlinkAct) ;
contextMenu->addSeparator() ;//------------------------------------
contextMenu->addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
contextMenu->addSeparator() ;//------------------------------------
QMenu collectionMenu(tr("Collection"), this);
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
collectionMenu.addAction(collCreateAct);
collectionMenu.addAction(collOpenAct);
contextMenu->addMenu(&collectionMenu) ;
}
}
}
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction( copylinkAct) ;
contextMnu.addAction( sendlinkAct) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to..."), this, SLOT(recommendFilesToMsg())) ;
contextMenu = model->getContextMenu(contextMenu);
if (!contextMenu->children().isEmpty())
contextMenu->exec(QCursor::pos()) ;
contextMnu.addSeparator() ;//------------------------------------
contextMnu.addMenu(&collectionMenu) ;
contextMnu.exec(QCursor::pos()) ;
delete contextMenu;
}
QModelIndexList SharedFilesDialog::getSelected()
@ -926,11 +936,44 @@ void SharedFilesDialog::restoreExpandedPathsAndSelection(const std::set<std::str
std::string path = ui.dirTreeView->model()->index(row,0).data(Qt::DisplayRole).toString().toStdString();
recursRestoreExpandedItems(ui.dirTreeView->model()->index(row,0),path,expanded_indexes,hidden_indexes,selected_indexes);
}
QItemSelection selection ;
//QItemSelection selection ;
ui.dirTreeView->blockSignals(false) ;
}
void SharedFilesDialog::expandAll()
{
if(ui.dirTreeView->model() == NULL || ui.dirTreeView->model() == flat_proxyModel) // this method causes infinite loops on flat models
return ;
ui.dirTreeView->blockSignals(true) ;
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "Restoring expanded items. " << std::endl;
#endif
for(int row = 0; row < ui.dirTreeView->model()->rowCount(); ++row)
{
std::string path = ui.dirTreeView->model()->index(row,0).data(Qt::DisplayRole).toString().toStdString();
recursExpandAll(ui.dirTreeView->model()->index(row,0));
}
ui.dirTreeView->blockSignals(false) ;
}
void SharedFilesDialog::recursExpandAll(const QModelIndex& index)
{
ui.dirTreeView->setExpanded(index,true) ;
for(int row=0;row<ui.dirTreeView->model()->rowCount(index);++row)
{
QModelIndex idx(index.child(row,0)) ;
if(ui.dirTreeView->model()->rowCount(idx) > 0)
recursExpandAll(idx) ;
}
}
void SharedFilesDialog::recursSaveExpandedItems(const QModelIndex& index,const std::string& path,std::set<std::string>& exp,
std::set<std::string>& vis,
std::set<std::string>& sel
@ -982,8 +1025,8 @@ void SharedFilesDialog::recursRestoreExpandedItems(const QModelIndex& index, con
bool invisible = vis.find(local_path) != vis.end();
ui.dirTreeView->setRowHidden(index.row(),index.parent(),invisible ) ;
if(invisible)
mHiddenIndexes.push_back(proxyModel->mapToSource(index));
// if(invisible)
// mHiddenIndexes.push_back(proxyModel->mapToSource(index));
if(!invisible && exp.find(local_path) != exp.end())
{
@ -1015,12 +1058,12 @@ void SharedFilesDialog::postModDirectories(bool local)
flat_model->postMods();
ui.dirTreeView->update() ;
if (ui.filterPatternLineEdit->text().isEmpty() == false)
if (ui.filterPatternLineEdit->text().isEmpty() == false)
FilterItems();
ui.dirTreeView->setSortingEnabled(true);
ui.dirTreeView->setSortingEnabled(true);
restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes) ;
restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes) ;
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "****** updated directories! Re-enabling sorting ******" << std::endl;
@ -1254,34 +1297,44 @@ void SharedFilesDialog::indicatorChanged(int index)
updateDisplay() ;
}
void SharedFilesDialog::filterRegExpChanged()
void SharedFilesDialog::onFilterTextEdited()
{
QString text = ui.filterPatternLineEdit->text();
QString text = ui.filterPatternLineEdit->text();
if (text.isEmpty()) {
ui.filterClearButton->hide();
} else {
ui.filterClearButton->show();
}
if (text.isEmpty()) {
ui.filterClearButton->hide();
} else {
ui.filterClearButton->show();
}
if (text == lastFilterString) {
ui.filterStartButton->hide();
} else {
ui.filterStartButton->show();
}
//bool valid = false ;
//QColor color ;
if (text == lastFilterString) {
ui.filterStartButton->hide();
} else {
ui.filterStartButton->show();
}
if(text.length() > 0 && text.length() < 3)
{
//valid = false;
ui.filterStartButton->setEnabled(false) ;
ui.filterPatternFrame->setToolTip(tr("Search string should be at least 3 characters long.")) ;
return ;
}
ui.filterStartButton->setEnabled(true) ;
ui.filterPatternFrame->setToolTip(QString());
//FilterItems();
#ifndef DISABLE_SEARCH_WHILE_TYPING
mFilterTimer->start( 500 ); // This will fire filterRegExpChanged after 500 ms.
// If the user types something before it fires, the timer restarts counting
#endif
}
#ifdef DEPRECATED_CODE
void SharedFilesDialog::filterRegExpChanged()
{
QString text = ui.filterPatternLineEdit->text();
if(text.length() > 0 && proxyModel == tree_proxyModel)
{
std::list<DirDetails> result_list ;
@ -1314,17 +1367,8 @@ void SharedFilesDialog::filterRegExpChanged()
ui.filterStartButton->setEnabled(true) ;
ui.filterPatternFrame->setToolTip(QString());
/* unpolish widget to clear the stylesheet's palette cache */
// ui.filterPatternFrame->style()->unpolish(ui.filterPatternFrame);
// QPalette palette = ui.filterPatternLineEdit->palette();
// palette.setColor(ui.filterPatternLineEdit->backgroundRole(), color);
// ui.filterPatternLineEdit->setPalette(palette);
// //ui.searchLineFrame->setProperty("valid", valid);
// Rshare::refreshStyleSheet(ui.filterPatternFrame, false);
}
#endif
/* clear Filter */
void SharedFilesDialog::clearFilter()
@ -1338,19 +1382,35 @@ void SharedFilesDialog::clearFilter()
/* clear Filter */
void SharedFilesDialog::startFilter()
{
ui.filterStartButton->hide();
lastFilterString = ui.filterPatternLineEdit->text();
ui.filterStartButton->hide();
lastFilterString = ui.filterPatternLineEdit->text();
FilterItems();
FilterItems();
}
void SharedFilesDialog::updateDirTreeView()
{
if (model == flat_model)
{
size_t maxSize = 0;
FlatStyle_RDM* flat = dynamic_cast<FlatStyle_RDM*>(flat_model);
if (flat && flat->isMaxRefsTableSize(&maxSize))
{
ui.dirTreeView->setToolTip(tr("Warning: You reach max (%1) files in flat list. No more will be added.").arg(maxSize));
return;
}
}
ui.dirTreeView->setToolTip("");
}
//#define DEBUG_SHARED_FILES_DIALOG
#ifdef DEPRECATED_CODE
// This macro make the search expand all items that contain the searched text.
// A bug however, makes RS expand everything when nothing is selected, which is a pain.
#define EXPAND_WHILE_SEARCHING 1
//#define DEBUG_SHARED_FILES_DIALOG
void recursMakeVisible(QTreeView *tree,const QSortFilterProxyModel *proxyModel,const QModelIndex& indx,uint32_t depth,const std::vector<std::set<void*> >& pointers,QList<QModelIndex>& hidden_list)
{
#ifdef DEBUG_SHARED_FILES_DIALOG
@ -1406,6 +1466,8 @@ void recursMakeVisible(QTreeView *tree,const QSortFilterProxyModel *proxyModel,c
void SharedFilesDialog::restoreInvisibleItems()
{
std::cerr << "Restoring " << mHiddenIndexes.size() << " invisible indexes" << std::endl;
for(QList<QModelIndex>::const_iterator it(mHiddenIndexes.begin());it!=mHiddenIndexes.end();++it)
{
QModelIndex indx = proxyModel->mapFromSource(*it);
@ -1416,6 +1478,7 @@ void SharedFilesDialog::restoreInvisibleItems()
mHiddenIndexes.clear();
}
#endif
class QCursorContextBlocker
{
@ -1448,115 +1511,60 @@ void SharedFilesDialog::FilterItems()
if(mLastFilterText == text) // do not filter again if we already did. This is an optimization
{
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "Last text is equal to text. skipping" << std::endl;
#endif
return ;
}
std::cerr << "New last text. Performing the filter" << std::endl;
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "New last text. Performing the filter on string \"" << text.toStdString() << "\"" << std::endl;
#endif
mLastFilterText = text ;
model->update() ;
restoreInvisibleItems();
QCursorContextBlocker q(ui.dirTreeView) ;
if(proxyModel == tree_proxyModel)
QCoreApplication::processEvents() ;
std::list<DirDetails> result_list ;
uint32_t found = 0 ;
if(text == "")
{
QCoreApplication::processEvents() ;
std::list<std::string> keywords ;
std::list<DirDetails> result_list ;
if(text == "")
return ;
if(text.length() < 3)
return ;
FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
QStringList lst = text.split(" ",QString::SkipEmptyParts) ;
for(auto it(lst.begin());it!=lst.end();++it)
keywords.push_back((*it).toStdString());
if(keywords.size() > 1)
{
RsRegularExpression::NameExpression exp(RsRegularExpression::ContainsAllStrings,keywords,true);
rsFiles->SearchBoolExp(&exp,result_list, flags) ;
}
else
rsFiles->SearchKeywords(keywords,result_list, flags) ;
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "Found " << result_list.size() << " results" << std::endl;
#endif
if(result_list.size() > MAX_SEARCH_RESULTS)
return ;
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << "Found this result: " << std::endl;
#endif
std::vector<std::set<void*> > pointers(2,std::set<void*>()); // at least two levels need to be here.
// Then show only the ones we need
for(auto it(result_list.begin());it!=result_list.end();++it)
{
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << (void*)(*it).ref << " parents: " ;
#endif
DirDetails& det(*it) ;
void *p = NULL;
std::list<void*> lst ;
lst.push_back(det.ref) ;
while(det.type == DIR_TYPE_FILE || det.type == DIR_TYPE_DIR)
{
p = det.parent ;
rsFiles->RequestDirDetails( p, det, flags);
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << " " << (void*)p << "(" << (int)det.type << ")";
#endif
lst.push_front(p) ;
}
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << std::endl;
#endif
uint32_t u=0;
for(auto it2(lst.begin());it2!=lst.end();++it2,++u)
{
if(pointers.size() <= u)
pointers.resize(u+5) ;
pointers[u].insert(*it2) ;
}
}
int rowCount = ui.dirTreeView->model()->rowCount();
for (int row = 0; row < rowCount; ++row)
recursMakeVisible(ui.dirTreeView,proxyModel,ui.dirTreeView->model()->index(row, COLUMN_NAME),0,pointers,mHiddenIndexes);
model->filterItems(std::list<std::string>(),found) ;
model->update() ;
return ;
}
if(text.length() < 3)
return ;
FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
QStringList lst = text.split(" ",QString::SkipEmptyParts) ;
std::list<std::string> keywords ;
for(auto it(lst.begin());it!=lst.end();++it)
keywords.push_back((*it).toStdString());
model->filterItems(keywords,found) ;
model->update() ;
if(found > 0)
expandAll();
if(found == 0)
ui.filterPatternFrame->setToolTip(tr("No result.")) ;
else if(found > MAX_SEARCH_RESULTS)
ui.filterPatternFrame->setToolTip(tr("More than %1 results. Add more/longer search words to select less.").arg(MAX_SEARCH_RESULTS)) ;
else
{
int rowCount = ui.dirTreeView->model()->rowCount();
for (int row = 0; row < rowCount; ++row)
flat_FilterItem(ui.dirTreeView->model()->index(row, COLUMN_NAME), text, 0);
}
ui.filterPatternFrame->setToolTip(tr("Found %1 results.").arg(found)) ;
#ifdef DEPRECATED_CODE
int rowCount = ui.dirTreeView->model()->rowCount();
for (int row = 0; row < rowCount; ++row)
if(proxyModel == tree_proxyModel)
tree_FilterItem(ui.dirTreeView->model()->index(row, COLUMN_NAME), text, 0);
else
flat_FilterItem(ui.dirTreeView->model()->index(row, COLUMN_NAME), text, 0);
#ifdef DEBUG_SHARED_FILES_DIALOG
std::cerr << found << " results found by search." << std::endl;
#endif
}
#ifdef DEPRECATED_CODE
bool SharedFilesDialog::flat_FilterItem(const QModelIndex &index, const QString &text, int /*level*/)
{
if(index.data(RetroshareDirModel::FileNameRole).toString().contains(text, Qt::CaseInsensitive))
@ -1606,4 +1614,4 @@ bool SharedFilesDialog::tree_FilterItem(const QModelIndex &index, const QString
return (visible || visibleChildCount);
}
#endif

View file

@ -22,10 +22,13 @@
#ifndef _SHAREDFILESDIALOG_H
#define _SHAREDFILESDIALOG_H
#include <set>
#include "ui_SharedFilesDialog.h"
#include "RsAutoUpdatePage.h"
#include "gui/RetroShareLink.h"
#include "ui_SharedFilesDialog.h"
#include "util/RsProtectedTimer.h"
#include <set>
class RetroshareDirModel;
class QSortFilterProxyModel;
@ -73,10 +76,13 @@ private slots:
void indicatorChanged(int index);
void filterRegExpChanged();
void onFilterTextEdited();
//void filterRegExpChanged();
void clearFilter();
void startFilter();
void updateDirTreeView();
public slots:
void changeCurrentViewModel(int viewTypeIndex);
signals:
@ -91,6 +97,8 @@ protected:
void recursSaveExpandedItems(const QModelIndex& index, const std::string &path, std::set<std::string> &exp,std::set<std::string>& vis, std::set<std::string>& sel);
void saveExpandedPathsAndSelection(std::set<std::string>& paths,std::set<std::string>& visible_indexes, std::set<std::string>& selected_indexes) ;
void restoreExpandedPathsAndSelection(const std::set<std::string>& paths,const std::set<std::string>& visible_indexes, const std::set<std::string>& selected_indexes) ;
void recursExpandAll(const QModelIndex& index);
void expandAll();
protected:
//now context menu are created again every time theu are called ( in some
@ -107,8 +115,6 @@ protected:
bool tree_FilterItem(const QModelIndex &index, const QString &text, int level);
bool flat_FilterItem(const QModelIndex &index, const QString &text, int level);
void restoreInvisibleItems();
QModelIndexList getSelected();
/** Defines the actions for the context menu for QTreeWidget */
@ -135,8 +141,7 @@ protected:
QString lastFilterString;
QString mLastFilterText ;
QList<QModelIndex> mHiddenIndexes;
RsProtectedTimer* mFilterTimer;
};
class LocalSharedFilesDialog : public SharedFilesDialog
@ -193,7 +198,7 @@ class RemoteSharedFilesDialog : public SharedFilesDialog
private slots:
void downloadRemoteSelected();
void downloadRemoteSelectedInteractive();
void expanded(const QModelIndex& indx);
void expanded(const QModelIndex& indx);
};
#endif

View file

@ -96,8 +96,15 @@
#define IMAGE_TUNNEL_ANON ":/images/blue_lock_open.png"
#define IMAGE_TUNNEL_FRIEND ":/icons/avatar_128.png"
//#define DEBUG_DOWNLOADLIST 1
Q_DECLARE_METATYPE(FileProgressInfo)
std::ostream& operator<<(std::ostream& o, const QModelIndex& i)
{
return o << i.row() << "," << i.column() << "," << i.internalPointer() ;
}
class RsDownloadListModel : public QAbstractItemModel
{
// Q_OBJECT
@ -113,19 +120,32 @@ public:
void *ref = (parent.isValid())?parent.internalPointer():NULL ;
if(!ref)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "rowCount-1(" << parent << ") : " << mDownloads.size() << std::endl;
#endif
return mDownloads.size() ;
}
uint32_t entry = 0 ;
int source_id ;
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size())
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || source_id > -1)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "rowCount-2(" << parent << ") : " << 0 << std::endl;
#endif
return 0 ;
}
return mDownloads[entry].peers.size(); // costly
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "rowCount-3(" << parent << ") : " << mDownloads[entry].peers.size() << std::endl;
#endif
return mDownloads[entry].peers.size();
}
int columnCount(const QModelIndex &parent = QModelIndex()) const
{
return 13 ;
return COLUMN_COUNT ;
}
bool hasChildren(const QModelIndex &parent = QModelIndex()) const
{
@ -134,64 +154,101 @@ public:
int source_id=0 ;
if(!ref)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "hasChildren-1(" << parent << ") : " << true << std::endl;
#endif
return true ;
}
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || source_id > -1)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "hasChildren-2(" << parent << ") : " << false << std::endl;
#endif
return false ;
}
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "hasChildren-3(" << parent << ") : " << !mDownloads[entry].peers.empty() << std::endl;
#endif
return !mDownloads[entry].peers.empty();
}
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const
{
if(row < 0)
if(row < 0 || column < 0 || column >= COLUMN_COUNT)
return QModelIndex();
void *ref = (parent.isValid())?parent.internalPointer():NULL ;
void *parent_ref = (parent.isValid())?parent.internalPointer():NULL ;
uint32_t entry = 0;
int source_id=0 ;
void *subref = NULL ;
if(!ref) // top level. The entry is that of a transfer
if(!parent_ref) // top level. The entry is that of a transfer
{
if(row >= mDownloads.size() || !convertTabEntryToRefPointer(row,-1,subref))
return QModelIndex() ;
void *ref = NULL ;
return createIndex(row,column,subref) ;
if(row >= (int)mDownloads.size() || !convertTabEntryToRefPointer(row,-1,ref))
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "index-1(" << row << "," << column << " parent=" << parent << ") : " << "NULL" << std::endl;
#endif
return QModelIndex() ;
}
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "index-2(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref) ;
}
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= source_id)
if(!convertRefPointerToTabEntry(parent_ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= row)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "index-5(" << row << "," << column << " parent=" << parent << ") : " << "NULL"<< std::endl ;
#endif
return QModelIndex() ;
}
if(source_id != -1)
std::cerr << "ERROR: parent.source_id != -1 in index()" << std::endl;
if(!convertTabEntryToRefPointer(entry,row,subref))
return QModelIndex() ;
void *ref = NULL ;
return createIndex(row,column,subref) ;
if(!convertTabEntryToRefPointer(entry,row,ref))
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "index-4(" << row << "," << column << " parent=" << parent << ") : " << "NULL" << std::endl;
#endif
return QModelIndex() ;
}
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "index-3(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref) ;
}
QModelIndex parent(const QModelIndex& child) const
{
void *ref = (child.isValid())?child.internalPointer():NULL ;
void *child_ref = (child.isValid())?child.internalPointer():NULL ;
uint32_t entry = 0;
int source_id=0 ;
if(!ref)
if(!child_ref)
return QModelIndex() ;
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= source_id)
if(!convertRefPointerToTabEntry(child_ref,entry,source_id) || entry >= mDownloads.size() || int(mDownloads[entry].peers.size()) <= source_id)
return QModelIndex() ;
if(source_id < 0)
return QModelIndex() ;
void *subref =NULL;
void *parent_ref =NULL;
if(!convertTabEntryToRefPointer(entry,-1,subref))
if(!convertTabEntryToRefPointer(entry,-1,parent_ref))
return QModelIndex() ;
return createIndex(entry,0,subref) ;
return createIndex(entry,child.column(),parent_ref) ;
}
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
@ -241,17 +298,44 @@ public:
uint32_t entry = 0;
int source_id=0 ;
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "data(" << index << ")" ;
#endif
if(!ref)
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << " [empty]" << std::endl;
#endif
return QVariant() ;
}
if(!convertRefPointerToTabEntry(ref,entry,source_id) || entry >= mDownloads.size())
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "Bad pointer: " << (void*)ref << std::endl;
#endif
return QVariant() ;
}
#ifdef DEBUG_DOWNLOADLIST
std::cerr << " source_id=" << source_id ;
#endif
if(source_id >= int(mDownloads[entry].peers.size()))
{
#ifdef DEBUG_DOWNLOADLIST
std::cerr << " [empty]" << std::endl;
#endif
return QVariant() ;
}
const FileInfo& finfo(mDownloads[entry]) ;
#ifdef DEBUG_DOWNLOADLIST
std::cerr << " [ok]" << std::endl;
#endif
switch(role)
{
case Qt::DisplayRole: return displayRole (finfo,source_id,index.column()) ;
@ -264,22 +348,24 @@ public:
QVariant sizeHintRole(int col) const
{
float factor = QFontMetricsF(QApplication::font()).height()/14.0f ;
switch(col)
{
default:
case COLUMN_NAME: return QVariant( 170 );
case COLUMN_SIZE: return QVariant( 70 );
case COLUMN_COMPLETED: return QVariant( 75 );
case COLUMN_DLSPEED: return QVariant( 75 );
case COLUMN_PROGRESS: return QVariant( 170 );
case COLUMN_SOURCES: return QVariant( 90 );
case COLUMN_STATUS: return QVariant( 100 );
case COLUMN_PRIORITY: return QVariant( 100 );
case COLUMN_REMAINING: return QVariant( 100 );
case COLUMN_DOWNLOADTIME: return QVariant( 100 );
case COLUMN_ID: return QVariant( 100 );
case COLUMN_LASTDL: return QVariant( 100 );
case COLUMN_PATH: return QVariant( 100 );
case COLUMN_NAME: return QVariant( factor * 170 );
case COLUMN_SIZE: return QVariant( factor * 70 );
case COLUMN_COMPLETED: return QVariant( factor * 75 );
case COLUMN_DLSPEED: return QVariant( factor * 75 );
case COLUMN_PROGRESS: return QVariant( factor * 170 );
case COLUMN_SOURCES: return QVariant( factor * 90 );
case COLUMN_STATUS: return QVariant( factor * 100 );
case COLUMN_PRIORITY: return QVariant( factor * 100 );
case COLUMN_REMAINING: return QVariant( factor * 100 );
case COLUMN_DOWNLOADTIME: return QVariant( factor * 100 );
case COLUMN_ID: return QVariant( factor * 100 );
case COLUMN_LASTDL: return QVariant( factor * 100 );
case COLUMN_PATH: return QVariant( factor * 100 );
}
}
@ -446,7 +532,7 @@ public:
{
FileChunksInfo fcinfo;
if (!rsFiles->FileDownloadChunksDetails(fileInfo.hash, fcinfo))
return -1;
return QVariant();
FileProgressInfo pinfo;
pinfo.cmap = fcinfo.chunks;
@ -480,34 +566,21 @@ public:
{
case COLUMN_PROGRESS:
{
FileProgressInfo peerpinfo ;
if(!rsFiles->FileUploadChunksDetails(fileInfo.hash, fileInfo.peers[source_id].peerId, peerpinfo.cmap) )
FileChunksInfo fcinfo;
if (!rsFiles->FileDownloadChunksDetails(fileInfo.hash, fcinfo))
return QVariant();
// Estimate the completion. We need something more accurate, meaning that we need to
// transmit the completion info.
//
uint32_t chunk_size = 1024*1024 ;
uint32_t nb_chunks = (uint32_t)((fileInfo.size + (uint64_t)chunk_size - 1) / (uint64_t)(chunk_size)) ;
RsPeerId pid = fileInfo.peers[source_id].peerId;
CompressedChunkMap& cmap(fcinfo.compressed_peer_availability_maps[pid]) ;
uint32_t filled_chunks = peerpinfo.cmap.filledChunks(nb_chunks) ;
peerpinfo.type = FileProgressInfo::UPLOAD_LINE ;
peerpinfo.nb_chunks = peerpinfo.cmap._map.empty()?0:nb_chunks ;
qlonglong completed ;
FileProgressInfo pinfo;
pinfo.cmap = cmap;
pinfo.type = FileProgressInfo::DOWNLOAD_SOURCE;
pinfo.progress = 0.0; // we dont display completion for sources
pinfo.nb_chunks = pinfo.cmap._map.empty() ? 0 : fcinfo.chunks.size();
if(filled_chunks > 0 && nb_chunks > 0)
{
completed = peerpinfo.cmap.computeProgress(fileInfo.size,chunk_size) ;
peerpinfo.progress = completed / (float)fileInfo.size * 100.0f ;
}
else
{
completed = fileInfo.peers[source_id].transfered % chunk_size ; // use the position with respect to last request.
peerpinfo.progress = (fileInfo.size>0)?((fileInfo.peers[source_id].transfered % chunk_size)*100.0/fileInfo.size):0 ;
}
return QVariant::fromValue(peerpinfo);
//std::cerr << "User role of source id " << source_id << std::endl;
return QVariant::fromValue(pinfo);
}
case COLUMN_ID: return QVariant(QString::fromStdString(fileInfo.hash.toStdString()) + QString::fromStdString(fileInfo.peers[source_id].peerId.toStdString()));
@ -529,7 +602,7 @@ public:
QString iconName,tooltip;
TransfersDialog::getPeerName(fileInfo.peers[source_id].peerId, iconName, tooltip);
return QVariant(iconName);
return QVariant(QIcon(iconName));
}
}
else
@ -538,8 +611,6 @@ public:
void update_transfers()
{
// beginResetModel();
std::list<RsFileHash> downHashes;
rsFiles->FileDownloads(downHashes);
@ -556,82 +627,64 @@ public:
else if(mDownloads.size() < old_size)
{
beginRemoveRows(QModelIndex(), mDownloads.size(), old_size-1);
removeRows(old_size, old_size - mDownloads.size());
removeRows(mDownloads.size(), old_size - mDownloads.size());
endRemoveRows();
}
//std::cerr << "updating file list: found " << mDownloads.size() << " transfers." << std::endl;
uint32_t i=0;
for(auto it(downHashes.begin());it!=downHashes.end();++it,++i)
{
FileInfo& fileInfo(mDownloads[i]);
FileInfo fileInfo(mDownloads[i]); // we dont update the data itself but only a copy of it....
int old_size = fileInfo.peers.size() ;
rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, fileInfo);
int new_size = fileInfo.peers.size() ;
if(old_size < new_size)
{
beginInsertRows(index(i,0), old_size, new_size-1);
insertRows(old_size, new_size - old_size,index(i,0));
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "called insert rows ( " << old_size << ", " << new_size - old_size << ",index(" << index(i,0)<< "))" << std::endl;
#endif
endInsertRows();
}
else if(new_size < old_size)
{
beginRemoveRows(index(i,0), new_size, old_size-1);
removeRows(new_size, old_size - new_size,index(i,0));
#ifdef DEBUG_DOWNLOADLIST
std::cerr << "called remove rows ( " << old_size << ", " << old_size - new_size << ",index(" << index(i,0)<< "))" << std::endl;
#endif
endRemoveRows();
}
uint32_t old_status = mDownloads[i].downloadStatus ;
mDownloads[i] = fileInfo ; // ... because insertRows() calls rowCount() which needs to be consistent with the *old* number of rows.
if(fileInfo.downloadStatus == FT_STATE_DOWNLOADING || old_status != fileInfo.downloadStatus)
{
QModelIndex topLeft = createIndex(i,0), bottomRight = createIndex(i, COLUMN_COUNT-1);
emit dataChanged(topLeft, bottomRight);
}
// This is apparently not needed.
//
// if(!mDownloads.empty())
// {
// QModelIndex topLeft = createIndex(0,0), bottomRight = createIndex(mDownloads.size()-1, COLUMN_COUNT-1);
// emit dataChanged(topLeft, bottomRight);
// mDownloads[i] = fileInfo ;
// }
}
// endResetModel();
QModelIndex topLeft = createIndex(0,0), bottomRight = createIndex(mDownloads.size()-1, COLUMN_COUNT-1);
emit dataChanged(topLeft, bottomRight);
//shit code follow (rewrite this please)
// size_t old_size = neighs.size(), new_size = 0;
// std::list<RsPgpId> old_neighs = neighs;
//
// new_size = new_neighs.size();
// //set model data to new cleaned up data
// neighs = new_neighs;
// neighs.sort();
// neighs.unique(); //remove possible dups
//
// //reflect actual row count in model
// if(old_size < new_size)
// {
// beginInsertRows(QModelIndex(), old_size, new_size);
// insertRows(old_size, new_size - old_size);
// endInsertRows();
// }
// else if(new_size < old_size)
// {
// beginRemoveRows(QModelIndex(), new_size, old_size);
// removeRows(old_size, old_size - new_size);
// endRemoveRows();
// }
// //update data in ui, to avoid unnecessary redraw and ui updates, updating only changed elements
// //TODO: libretroshare should implement a way to obtain only changed elements via some signalling non-blocking api.
// {
// size_t ii1 = 0;
// for(auto i1 = neighs.begin(), end1 = neighs.end(), i2 = old_neighs.begin(), end2 = old_neighs.end(); i1 != end1; ++i1, ++i2, ii1++)
// {
// if(i2 == end2)
// break;
// if(*i1 != *i2)
// {
// QModelIndex topLeft = createIndex(ii1,0), bottomRight = createIndex(ii1, COLUMN_COUNT-1);
// emit dataChanged(topLeft, bottomRight);
// }
// }
// }
// if(new_size > old_size)
// {
// QModelIndex topLeft = createIndex(old_size ? old_size -1 : 0 ,0), bottomRight = createIndex(new_size -1, COLUMN_COUNT-1);
// emit dataChanged(topLeft, bottomRight);
// }
// //dirty solution for initial data fetch
// //TODO: do it properly!
// if(!old_size)
// {
// beginResetModel();
// endResetModel();
// }
}
private:
static const uint32_t TRANSFERS_NB_DOWNLOADS_BITS_32BITS = 22 ; // Means 2^22 simultaneous transfers
static const uint32_t TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS = 0x003fffff ; // actual bit mask corresponding to previous number of bits
static const uint32_t TRANSFERS_NB_SOURCES_BITS_32BITS = 10 ; // Means 2^10 simultaneous sources
static const uint32_t TRANSFERS_NB_DOWNLOADS_BITS_32BITS = 22 ; // Means 2^22 simultaneous transfers
static const uint32_t TRANSFERS_NB_SOURCES_BITS_32BITS = 10 ; // Means 2^10 simultaneous sources
static const uint32_t TRANSFERS_NB_SOURCES_BIT_MASK_32BITS = (1 << TRANSFERS_NB_SOURCES_BITS_32BITS)-1 ;// actual bit mask corresponding to previous number of bits
static bool convertTabEntryToRefPointer(uint32_t entry,int source_id,void *& ref)
{
@ -642,30 +695,33 @@ private:
}
// the pointer is formed the following way:
//
// [ 10 bits | 22 bits ]
// [ 22 bits | 10 bits ]
//
// This means that the whoel software has the following build-in limitation:
// * 1023 sources
// This means that the whole software has the following build-in limitation:
// * 4M simultaenous file transfers
// * 1023 sources
if(uint32_t(source_id+1) >= (1u<<TRANSFERS_NB_SOURCES_BITS_32BITS) || (entry+1) >= (1u<< TRANSFERS_NB_DOWNLOADS_BITS_32BITS))
if(uint32_t(source_id+1) >= (1u<<TRANSFERS_NB_SOURCES_BITS_32BITS) || uint32_t(entry+1) >= (1u<< TRANSFERS_NB_DOWNLOADS_BITS_32BITS))
{
std::cerr << "(EE) cannot convert download index " << entry << " and source " << source_id << " to pointer." << std::endl;
return false ;
}
ref = reinterpret_cast<void*>( ( uint32_t(1+source_id) << TRANSFERS_NB_DOWNLOADS_BITS_32BITS ) + ( (entry+1) & TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS)) ;
ref = reinterpret_cast<void*>( ( uint32_t(1+entry) << TRANSFERS_NB_SOURCES_BITS_32BITS ) + ( (source_id+1) & TRANSFERS_NB_SOURCES_BIT_MASK_32BITS)) ;
assert(ref != NULL) ;
return true;
}
static bool convertRefPointerToTabEntry(void *ref,uint32_t& entry,int& source_id)
{
assert(ref != NULL) ;
// we pack the couple (id of DL, id of source) into a single 32-bits pointer that is required by the AbstractItemModel class.
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
uint32_t ntr = uint32_t( *reinterpret_cast<uint32_t*>(&ref) & TRANSFERS_NB_DOWNLOADS_BIT_MASK_32BITS ) ;
uint32_t src = ( *reinterpret_cast<uint32_t*>(&ref)) >> TRANSFERS_NB_DOWNLOADS_BITS_32BITS ;
uint32_t src = uint32_t( *reinterpret_cast<uint32_t*>(&ref) & TRANSFERS_NB_SOURCES_BIT_MASK_32BITS ) ;
uint32_t ntr = ( *reinterpret_cast<uint32_t*>(&ref)) >> TRANSFERS_NB_SOURCES_BITS_32BITS ;
#pragma GCC diagnostic pop
if(ntr == 0)

View file

@ -233,7 +233,9 @@ void xProgressBar::paint()
uint32_t ss = _pinfo.nb_chunks ;
if(ss > 1) // for small files we use a more progressive display
QRect bounding = painter->boundingRect(rect, Qt::AlignCenter, QLocale().toString(_pinfo.progress, 'f', 2) + "%");
if((ss > 1) && (rect.width() > (1.5*bounding.width()))) // for small files we use a more progressive display
{
if(!_pinfo.cmap._map.empty())
{
@ -303,7 +305,7 @@ void xProgressBar::paint()
overPaintSelectedChunks( _pinfo.chunks_in_progress , QColor(170, 20,9), QColor(223,121,123), width,ss) ;
overPaintSelectedChunks( _pinfo.chunks_in_checking , QColor(186,143,0), QColor(223,196, 61), width,ss) ;
}
else
else if ((rect.width() < bounding.width()) || !displayText)
{
// calculate progress value
int preWidth = static_cast<int>((rect.width() - 1 - hSpan)*(_pinfo.progress/100.0f));
@ -318,11 +320,20 @@ void xProgressBar::paint()
// paint text?
if (displayText)
if (displayText && (rect.width() >= bounding.width()))
{
QLocale locale;
QColor colorInt (255-textColor.red(), 255-textColor.green(), 255-textColor.blue(), 127);
QColor colorBor (255-textColor.red(), 255-textColor.green(), 255-textColor.blue(), 63);
QRadialGradient radialGrad(bounding.x()+(bounding.width()/2), bounding.y()+(bounding.height()/2),bounding.width()/2);
radialGrad.setColorAt(0.0, colorInt);
radialGrad.setColorAt(1.0, colorBor);
radialGrad.setSpread(QGradient::ReflectSpread);
painter->setPen(colorBor);
painter->setBrush(radialGrad);
painter->drawRoundedRect(bounding.adjusted(-2,2,2,-3),4.0,4.0);
painter->setPen(textColor);
painter->drawText(rect, Qt::AlignCenter, locale.toString(_pinfo.progress, 'f', 2) + "%");
painter->drawText(rect, Qt::AlignCenter, QLocale().toString(_pinfo.progress, 'f', 2) + "%");
}
backgroundColor.setRgb(255, 255, 255);

View file

@ -1994,7 +1994,8 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
}
case RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION: // Chat lobby msgs are signed, so each time one comes, or a chat lobby event comes, a signature verificaiton happens.
{
RetroShareLink l = RetroShareLink::createChatRoom(ChatId(ChatLobbyId(u.mAdditionalId)),QString::number(u.mAdditionalId));
ChatId id = ChatId(ChatLobbyId(u.mAdditionalId));
RetroShareLink l = RetroShareLink::createChatRoom(id, QString::fromStdString(id.toStdString()));
return tr("Message in chat room %1").arg(l.toHtml()) ;
}
case RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK: // Global router message validation
@ -2124,19 +2125,19 @@ void IdDialog::updateDisplay(bool complete)
if (complete) {
/* Fill complete */
requestIdList();
requestIdDetails();
//requestIdDetails();
requestRepList();
return;
}
requestCircleGroupMeta();
std::list<RsGxsGroupId> grpIds;
std::set<RsGxsGroupId> grpIds;
getAllGrpIds(grpIds);
if (!getGrpIds().empty()) {
requestIdList();
if (!mId.isNull() && std::find(grpIds.begin(), grpIds.end(), mId) != grpIds.end()) {
if (!mId.isNull() && grpIds.find(mId)!=grpIds.end()) {
requestIdDetails();
requestRepList();
}

View file

@ -107,10 +107,13 @@
#include "gui/common/RsCollection.h"
#include "settings/rsettingswin.h"
#include "settings/rsharesettings.h"
#include "settings/WebuiPage.h"
#include "common/StatusDefs.h"
#include "gui/notifyqt.h"
#ifdef ENABLE_WEBUI
# include "settings/WebuiPage.h"
#endif
#include <iomanip>
#include <unistd.h>
@ -730,16 +733,16 @@ void MainWindow::updateStatus()
if (ratesstatus)
ratesstatus->getRatesStatus(downKb, upKb);
if(torstatus)
torstatus->getTorStatus();
if(torstatus)
torstatus->getTorStatus();
if(!hiddenmode)
{
if (natstatus)
natstatus->getNATStatus();
if (dhtstatus)
dhtstatus->getDHTStatus();
if (natstatus)
natstatus->getNATStatus();
if (dhtstatus)
dhtstatus->getDHTStatus();
}
if (discstatus) {
@ -1431,27 +1434,37 @@ void MainWindow::settingsChanged()
void MainWindow::externalLinkActivated(const QUrl &url)
{
static bool already_warned = false ;
bool never_ask_me = Settings->value("NeverAskMeForExternalLinkActivated",false).toBool();
if(!already_warned)
if(!already_warned && !never_ask_me)
{
QMessageBox mb(QObject::tr("Confirmation"), QObject::tr("Do you want this link to be handled by your system?")+"<br/><br/>"+ url.toString()+"<br/><br/>"+tr("Make sure this link has not been forged to drag you to a malicious website."), QMessageBox::Question, QMessageBox::Yes,QMessageBox::No, 0);
QCheckBox *checkbox = new QCheckBox(tr("Don't ask me again")) ;
QCheckBox *dontAsk_CB = new QCheckBox(tr("Don't ask me again"));
QCheckBox *neverAsk_CB = new QCheckBox(tr("Never ask me again"));
dontAsk_CB->setToolTip(tr("This will be saved only for this session."));
neverAsk_CB->setToolTip(tr("This will be saved permanently. You'll need to clean RetroShare.conf to revert."));
QGridLayout* layout = qobject_cast<QGridLayout*>(mb.layout());
if (layout)
{
layout->addWidget(checkbox,layout->rowCount(),0,1, layout->columnCount(), Qt::AlignLeft);
layout->addWidget(dontAsk_CB,layout->rowCount(),0,1, layout->columnCount(), Qt::AlignLeft);
layout->addWidget(neverAsk_CB,layout->rowCount(),0,1, layout->columnCount(), Qt::AlignLeft);
} else {
//Not QGridLayout so add at end
mb.layout()->addWidget(checkbox) ;
mb.layout()->addWidget(dontAsk_CB);
mb.layout()->addWidget(neverAsk_CB);
}
int res = mb.exec() ;
if (res == QMessageBox::No)
return ;
else if(checkbox->isChecked())
if(dontAsk_CB->isChecked())
already_warned = true ;
if(neverAsk_CB->isChecked())
Settings->setValue("NeverAskMeForExternalLinkActivated",true);
}
QDesktopServices::openUrl(url) ;

View file

@ -366,8 +366,8 @@ void NewsFeed::updateDisplay()
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect_msgIds = msgIds[grpId];
vect_msgIds.push_back(msgId);
std::set<RsGxsMessageId> &vect_msgIds = msgIds[grpId];
vect_msgIds.insert(msgId);
uint32_t token;
mTokenQueueCircle->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_MESSAGE);

View file

@ -22,6 +22,7 @@
*/
#include <QDateTime>
#include <QStyle>
#include "rshare.h"
#include "PostedItem.h"

View file

@ -30,6 +30,7 @@
#include "retroshare/rsfiles.h"
#include "retroshare/rspeers.h"
#include "util/misc.h"
#include "retroshare/rsexpr.h"
#include <QDir>
#include <QFileInfo>
@ -43,28 +44,48 @@
/*****
* #define RDM_DEBUG
* #define RDM_SEARCH_DEBUG
****/
static const uint32_t FLAT_VIEW_MAX_REFS_PER_SECOND = 2000 ;
static const uint32_t FLAT_VIEW_MAX_REFS_TABLE_SIZE = 10000 ; //
static const size_t FLAT_VIEW_MAX_REFS_TABLE_SIZE = 10000 ; //
static const uint32_t FLAT_VIEW_MIN_DELAY_BETWEEN_UPDATES = 120 ; // dont rebuild ref list more than every 2 mins.
RetroshareDirModel::RetroshareDirModel(bool mode, QObject *parent)
: QAbstractItemModel(parent),
ageIndicator(IND_ALWAYS),
RemoteMode(mode), nIndex(1), indexSet(1) /* ass zero index cant be used */
: QAbstractItemModel(parent), _visible(false)
, ageIndicator(IND_ALWAYS)
, RemoteMode(mode)//, nIndex(1), indexSet(1) /* ass zero index cant be used */
, mLastRemote(false), mLastReq(0), mUpdating(false)
{
_visible = false ;
#if QT_VERSION < QT_VERSION_CHECK (5, 0, 0)
setSupportedDragActions(Qt::CopyAction);
#endif
treeStyle();
mDirDetails.ref = (void*)intptr_t(0xffffffff) ;
mLastRemote = false ;
mUpdating = false;
mDirDetails.ref = (void*)intptr_t(0xffffffff) ;
}
TreeStyle_RDM::TreeStyle_RDM(bool mode)
: RetroshareDirModel(mode), _showEmpty(false)
{
_showEmptyAct = new QAction(QIcon(), tr("Show Empty"), this);
_showEmptyAct->setCheckable(true);
_showEmptyAct->setChecked(_showEmpty);
connect(_showEmptyAct, SIGNAL(toggled(bool)), this, SLOT(showEmpty(bool)));
}
FlatStyle_RDM::FlatStyle_RDM(bool mode)
: RetroshareDirModel(mode), _ref_mutex("Flat file list")
{
_needs_update = true ;
{
RS_STACK_MUTEX(_ref_mutex) ;
_last_update = 0 ;
}
}
// QAbstractItemModel::setSupportedDragActions() was replaced by virtual QAbstractItemModel::supportedDragActions()
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
Qt::DropActions RetroshareDirModel::supportedDragActions() const
@ -78,7 +99,6 @@ static bool isNewerThanEpoque(uint32_t ts)
return ts > 0 ; // this should be conservative enough
}
void RetroshareDirModel::treeStyle()
{
categoryIcon.addPixmap(QPixmap(":/images/folder16.png"),
@ -97,6 +117,21 @@ void TreeStyle_RDM::updateRef(const QModelIndex& indx) const
rsFiles->requestDirUpdate(indx.internalPointer()) ;
}
QMenu* TreeStyle_RDM::getContextMenu(QMenu* contextMenu)
{
if (!contextMenu){
contextMenu = new QMenu();
} else {
if (RemoteMode)
contextMenu->addSeparator();
}
if (RemoteMode)
contextMenu->addAction( _showEmptyAct) ;
return contextMenu;
}
bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
{
@ -137,7 +172,7 @@ bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
}
/* PERSON/DIR*/
#ifdef RDM_DEBUG
std::cerr << "lookup PER/DIR #" << details->count;
std::cerr << "lookup PER/DIR #" << details.count;
std::cerr << std::endl;
#endif
return (details.count > 0); /* do we have children? */
@ -171,9 +206,13 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
void *ref = (parent.isValid())? parent.internalPointer() : NULL ;
DirDetails details ;
if ((!ref) && RemoteMode)
_parentRow.clear(); //Only clear it when asking root child number and in remote mode.
if (! requestDirDetails(ref, RemoteMode,details))
DirDetails details ;
if (! requestDirDetails(ref, RemoteMode,details))
{
#ifdef RDM_DEBUG
std::cerr << "lookup failed -> 0";
@ -181,7 +220,7 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
#endif
return 0;
}
if (details.type == DIR_TYPE_FILE)
if (details.type == DIR_TYPE_FILE)
{
#ifdef RDM_DEBUG
std::cerr << "lookup FILE: 0";
@ -192,12 +231,24 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
/* else PERSON/DIR*/
#ifdef RDM_DEBUG
std::cerr << "lookup PER/DIR #" << details->count;
std::cerr << "lookup PER/DIR #" << details.count;
std::cerr << std::endl;
#endif
return details.count;
if ((details.type == DIR_TYPE_ROOT) && !_showEmpty && RemoteMode)
{
DirDetails childDetails;
//Scan all children to know if they are empty.
//And save their real row index
//Prefer do like that than modify requestDirDetails with a new flag (rsFiles->RequestDirDetails)
for(uint64_t i = 0; i < details.count; ++i)
{
if (requestDirDetails(details.children[i].ref, RemoteMode,childDetails) && (childDetails.count > 0))
_parentRow.push_back(i);
}
return _parentRow.size();
}
return details.count;
}
int FlatStyle_RDM::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
@ -210,6 +261,7 @@ int FlatStyle_RDM::rowCount(const QModelIndex &parent) const
return _ref_entries.size() ;
}
int TreeStyle_RDM::columnCount(const QModelIndex &/*parent*/) const
{
return COLUMN_COUNT;
@ -218,6 +270,7 @@ int FlatStyle_RDM::columnCount(const QModelIndex &/*parent*/) const
{
return COLUMN_COUNT;
}
QString RetroshareDirModel::getFlagsString(FileStorageFlags flags)
{
char str[11] = "- - -" ;
@ -253,7 +306,6 @@ QString RetroshareDirModel::getGroupsString(FileStorageFlags flags,const std::li
return groups_str ;
}
QString RetroshareDirModel::getAgeIndicatorString(const DirDetails &details) const
{
QString ret("");
@ -317,11 +369,19 @@ const QIcon& RetroshareDirModel::getFlagsIcon(FileStorageFlags flags)
static_icons[n] = new QIcon(pix);
std::cerr << "Generated icon for flags " << std::hex << flags << std::endl;
std::cerr << "Generated icon for flags " << std::hex << flags << std::dec << std::endl;
}
return *static_icons[n] ;
}
QVariant RetroshareDirModel::filterRole(const DirDetails& details, int /*coln*/) const
{
if(mFilteredPointers.empty() || mFilteredPointers.find(details.ref) != mFilteredPointers.end())
return QString(RETROSHARE_DIR_MODEL_FILTER_STRING);
else
return QVariant();
}
QVariant RetroshareDirModel::decorationRole(const DirDetails& details,int coln) const
{
if(coln == COLUMN_FRIEND_ACCESS)
@ -496,17 +556,6 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const
return QVariant();
} /* end of DisplayRole */
FlatStyle_RDM::FlatStyle_RDM(bool mode)
: RetroshareDirModel(mode), _ref_mutex("Flat file list")
{
_needs_update = true ;
{
RS_STACK_MUTEX(_ref_mutex) ;
_last_update = 0 ;
}
}
void FlatStyle_RDM::update()
{
if(_needs_update)
@ -516,6 +565,13 @@ void FlatStyle_RDM::update()
}
}
bool FlatStyle_RDM::isMaxRefsTableSize(size_t *maxSize/*=NULL*/)
{
if (maxSize)
*maxSize = FLAT_VIEW_MAX_REFS_TABLE_SIZE;
return (_ref_entries.size() >= FLAT_VIEW_MAX_REFS_TABLE_SIZE);
}
QString FlatStyle_RDM::computeDirectoryPath(const DirDetails& details) const
{
QString dir ;
@ -643,7 +699,6 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails&
}
return QVariant();
}
QVariant FlatStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& details,int coln) const
{
/*
@ -671,9 +726,6 @@ QVariant FlatStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails&
return QVariant();
} /* end of SortRole */
QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
{
#ifdef RDM_DEBUG
@ -761,9 +813,15 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
if (role == SortRole)
return sortRole(index,details,coln) ;
if (role == FilterRole)
return filterRole(details,coln) ;
return QVariant();
}
/****
//void RetroshareDirModel::getAgeIndicatorRec(const DirDetails &details, QString &ret) const {
// if (details.type == DIR_TYPE_FILE) {
// ret = getAgeIndicatorString(details);
@ -779,6 +837,7 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
// }
// }
//}
****/
QVariant TreeStyle_RDM::headerData(int section, Qt::Orientation orientation, int role) const
{
@ -888,8 +947,8 @@ QModelIndex TreeStyle_RDM::index(int row, int column, const QModelIndex & parent
std::cerr << ": row:" << row << " col:" << column << " ";
#endif
// This function is used extensively. There's no way we can use requestDirDetails() in it, which would
// cause far too much overhead. So we use a dedicated function that only grabs the required information.
// This function is used extensively. There's no way we can use requestDirDetails() in it, which would
// cause far too much overhead. So we use a dedicated function that only grabs the required information.
if(row < 0)
return QModelIndex() ;
@ -903,15 +962,19 @@ QModelIndex TreeStyle_RDM::index(int row, int column, const QModelIndex & parent
}
********/
//If on root and don't show empty child, get real parent row
if ((!ref) && (!_showEmpty) && RemoteMode && ((size_t)row >= _parentRow.size()))
return QModelIndex();
void *result ;
int parentRow = ((!ref) && (!_showEmpty) && RemoteMode) ? _parentRow[row] : row ;
if(rsFiles->findChildPointer(ref, row, result, ((RemoteMode) ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL)))
return createIndex(row, column, result) ;
else
void *result ;
if(rsFiles->findChildPointer(ref, parentRow, result, ((RemoteMode) ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL)))
return createIndex(row, column, result) ;
else
return QModelIndex();
}
QModelIndex FlatStyle_RDM::index(int row, int column, const QModelIndex & parent) const
{
Q_UNUSED(parent);
@ -957,10 +1020,10 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
}
void *ref = index.internalPointer();
DirDetails details ;
DirDetails details ;
if (! requestDirDetails(ref, RemoteMode,details))
{
if (! requestDirDetails(ref, RemoteMode,details))
{
#ifdef RDM_DEBUG
std::cerr << "Failed Lookup -> invalid";
std::cerr << std::endl;
@ -968,7 +1031,7 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
return QModelIndex();
}
if (!(details.parent))
if (!(details.parent))
{
#ifdef RDM_DEBUG
std::cerr << "success. parent is Root/NULL --> invalid";
@ -978,12 +1041,13 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
}
#ifdef RDM_DEBUG
std::cerr << "success index(" << details->prow << ",0," << details->parent << ")";
std::cerr << "success index(" << details.prow << ",0," << details.parent << ")";
std::cerr << std::endl;
std::cerr << "Creating index 3 row=" << details.prow << ", column=" << 0 << ", ref=" << (void*)details.parent << std::endl;
std::cerr << "Creating index 3 row=" << details.prow << ", column=" << 0 << ", ref=" << (void*)details.parent << std::endl;
#endif
return createIndex(details.prow, COLUMN_NAME, details.parent);
return createIndex(details.prow, COLUMN_NAME, details.parent);
}
QModelIndex FlatStyle_RDM::parent( const QModelIndex & index ) const
{
@ -1032,7 +1096,7 @@ Qt::ItemFlags RetroshareDirModel::flags( const QModelIndex & index ) const
/* Callback from */
/* Callback from Core*/
void RetroshareDirModel::preMods()
{
emit layoutAboutToBeChanged();
@ -1049,7 +1113,7 @@ void RetroshareDirModel::preMods()
#endif
}
/* Callback from */
/* Callback from Core*/
void RetroshareDirModel::postMods()
{
// emit layoutAboutToBeChanged();
@ -1068,6 +1132,30 @@ void RetroshareDirModel::postMods()
emit layoutChanged();
}
void FlatStyle_RDM::postMods()
{
time_t now = time(NULL);
if(_last_update + FLAT_VIEW_MIN_DELAY_BETWEEN_UPDATES > now)
return ;
if(visible())
{
emit layoutAboutToBeChanged();
{
RS_STACK_MUTEX(_ref_mutex) ;
_ref_stack.clear() ;
_ref_stack.push_back(NULL) ; // init the stack with the topmost parent directory
_ref_entries.clear();
_last_update = now;
}
QTimer::singleShot(100,this,SLOT(updateRefs())) ;
}
else
_needs_update = true ;
}
bool RetroshareDirModel::requestDirDetails(void *ref, bool remote,DirDetails& d) const
{
#ifdef RDM_DEBUG
@ -1266,10 +1354,10 @@ void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, s
#ifdef RDM_DEBUG
std::cerr << "::::::::::::FileRecommend:::: " << std::endl;
std::cerr << "Name: " << details->name << std::endl;
std::cerr << "Hash: " << details->hash << std::endl;
std::cerr << "Size: " << details->count << std::endl;
std::cerr << "Path: " << details->path << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
// Note: for directories, the returned hash, is the peer id, so if we collect
// dirs, we need to be a bit more conservative for the
@ -1376,6 +1464,72 @@ void RetroshareDirModel::getFilePaths(const QModelIndexList &list, std::list<std
#endif
}
void RetroshareDirModel::filterItems(const std::list<std::string>& keywords,uint32_t& found)
{
FileSearchFlags flags = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
std::list<DirDetails> result_list ;
found = 0 ;
if(keywords.empty())
{
mFilteredPointers.clear();
return ;
}
else if(keywords.size() > 1)
{
RsRegularExpression::NameExpression exp(RsRegularExpression::ContainsAllStrings,keywords,true);
rsFiles->SearchBoolExp(&exp,result_list, flags) ;
}
else
rsFiles->SearchKeywords(keywords,result_list, flags) ;
#ifdef RDM_SEARCH_DEBUG
std::cerr << "Found " << result_list.size() << " results" << std::endl;
#endif
if(result_list.empty()) // in this case we dont clear the list of filtered items, so that we can keep the old filter list
return ;
mFilteredPointers.clear();
#ifdef RDM_SEARCH_DEBUG
std::cerr << "Found this result: " << std::endl;
#endif
// Then show only the ones we need
for(auto it(result_list.begin());it!=result_list.end();++it)
{
DirDetails& det(*it) ;
#ifdef RDM_SEARCH_DEBUG
std::cerr << (void*)(*it).ref << " name=\"" << det.name << "\" parents: " ;
#endif
void *p = det.ref ;
mFilteredPointers.insert(p) ;
++found ;
while(det.type == DIR_TYPE_FILE || det.type == DIR_TYPE_DIR)
{
p = det.parent ;
rsFiles->RequestDirDetails( p, det, flags);
#ifdef RDM_SEARCH_DEBUG
std::cerr << " " << (void*)p << "(" << (int)det.type << ")";
#endif
mFilteredPointers.insert(p) ;
}
#ifdef RDM_SEARCH_DEBUG
std::cerr << std::endl;
#endif
}
#ifdef RDM_SEARCH_DEBUG
std::cerr << mFilteredPointers.size() << " pointers in filter set." << std::endl;
#endif
}
/* Drag and Drop Functionality */
QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) const
{
@ -1395,10 +1549,10 @@ QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) con
#ifdef RDM_DEBUG
std::cerr << "::::::::::::FileDrag:::: " << std::endl;
std::cerr << "Name: " << details->name << std::endl;
std::cerr << "Hash: " << details->hash << std::endl;
std::cerr << "Size: " << details->count << std::endl;
std::cerr << "Path: " << details->path << std::endl;
std::cerr << "Name: " << details.name << std::endl;
std::cerr << "Hash: " << details.hash << std::endl;
std::cerr << "Size: " << details.count << std::endl;
std::cerr << "Path: " << details.path << std::endl;
#endif
if (details.type != DIR_TYPE_FILE)
@ -1468,35 +1622,11 @@ int RetroshareDirModel::getType ( const QModelIndex & index ) const
return rsFiles->getType(index.internalPointer(),flags);
}
FlatStyle_RDM::~FlatStyle_RDM()
{
}
TreeStyle_RDM::~TreeStyle_RDM()
{
}
void FlatStyle_RDM::postMods()
FlatStyle_RDM::~FlatStyle_RDM()
{
time_t now = time(NULL);
if(_last_update + FLAT_VIEW_MIN_DELAY_BETWEEN_UPDATES > now)
return ;
if(visible())
{
emit layoutAboutToBeChanged();
{
RS_STACK_MUTEX(_ref_mutex) ;
_ref_stack.clear() ;
_ref_stack.push_back(NULL) ; // init the stack with the topmost parent directory
_ref_entries.clear();
_last_update = now;
}
QTimer::singleShot(100,this,SLOT(updateRefs())) ;
}
else
_needs_update = true ;
}
void FlatStyle_RDM::updateRefs()
@ -1515,7 +1645,7 @@ void FlatStyle_RDM::updateRefs()
{
RS_STACK_MUTEX(_ref_mutex) ;
while(!_ref_stack.empty())
while( !_ref_stack.empty() && (_ref_entries.size() <= FLAT_VIEW_MAX_REFS_TABLE_SIZE) )
{
void *ref = _ref_stack.back() ;
#ifdef RDM_DEBUG
@ -1539,7 +1669,7 @@ void FlatStyle_RDM::updateRefs()
// Limit the size of the table to display, otherwise it becomes impossible to Qt.
if(_ref_entries.size() > FLAT_VIEW_MAX_REFS_TABLE_SIZE)
return ;
continue;
if(++nb_treated_refs > FLAT_VIEW_MAX_REFS_PER_SECOND) // we've done enough, let's give back hand to
{ // the user and setup a timer to finish the job later.
@ -1556,3 +1686,8 @@ void FlatStyle_RDM::updateRefs()
RetroshareDirModel::postMods() ;
}
void TreeStyle_RDM::showEmpty(const bool value)
{
_showEmpty = value;
update();
}

View file

@ -25,7 +25,9 @@
#include <retroshare/rstypes.h>
#include <QAbstractItemModel>
#include <QAction>
#include <QIcon>
#include <QMenu>
#include <stdint.h>
#include <vector>
@ -37,6 +39,7 @@
#define COLUMN_FRIEND_ACCESS 4
#define COLUMN_WN_VISU_DIR 5
#define COLUMN_COUNT 6
#define RETROSHARE_DIR_MODEL_FILTER_STRING "filtered"
class DirDetails;
@ -58,12 +61,12 @@ class RetroshareDirModel : public QAbstractItemModel
Q_OBJECT
public:
enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2 };
enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2, FilterRole = Qt::UserRole+3 };
RetroshareDirModel(bool mode, QObject *parent = 0);
virtual ~RetroshareDirModel() {}
Qt::ItemFlags flags ( const QModelIndex & index ) const;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
/* Callback from Core */
virtual void preMods();
@ -82,18 +85,22 @@ class RetroshareDirModel : public QAbstractItemModel
void getFileInfoFromIndexList(const QModelIndexList& list, std::list<DirDetails>& files_info) ;
void openSelected(const QModelIndexList &list);
void getFilePaths(const QModelIndexList &list, std::list<std::string> &fullpaths);
void getFilePath(const QModelIndex& index, std::string& fullpath);
void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; }
void getFilePath(const QModelIndex& index, std::string& fullpath);
void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; }
bool requestDirDetails(void *ref, bool remote,DirDetails& d) const;
bool requestDirDetails(void *ref, bool remote,DirDetails& d) const;
virtual void update() {}
virtual void updateRef(const QModelIndex&) const =0;
virtual void updateRef(const QModelIndex&) const =0;
virtual QMenu* getContextMenu(QMenu* contextMenu) {return contextMenu;}
public:
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const;
void filterItems(const std::list<std::string>& keywords, uint32_t& found) ;
//Overloaded from QAbstractItemModel
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual QStringList mimeTypes () const;
virtual QVariant data(const QModelIndex &index, int role) const;
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const;
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
virtual Qt::DropActions supportedDragActions() const;
#endif
@ -104,61 +111,62 @@ class RetroshareDirModel : public QAbstractItemModel
void treeStyle();
void downloadDirectory(const DirDetails & details, int prefixLen);
static QString getFlagsString(FileStorageFlags f) ;
static QString getGroupsString(FileStorageFlags flags, const std::list<RsNodeGroupId> &) ;
static QString getGroupsString(FileStorageFlags flags, const std::list<RsNodeGroupId> &) ;
QString getAgeIndicatorString(const DirDetails &) const;
// void getAgeIndicatorRec(const DirDetails &details, QString &ret) const;
static const QIcon& getFlagsIcon(FileStorageFlags flags) ;
static const QIcon& getFlagsIcon(FileStorageFlags flags) ;
virtual QVariant displayRole(const DirDetails&,int) const = 0 ;
virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const =0;
QVariant decorationRole(const DirDetails&,int) const ;
QVariant filterRole(const DirDetails& details,int coln) const;
uint32_t ageIndicator;
QIcon categoryIcon;
QIcon peerIcon;
class RemoteIndex
{
public:
RemoteIndex() {}
RemoteIndex(std::string in_person,
std::string in_path,
int in_idx,
int in_row,
int in_column,
std::string in_name,
int in_size,
int in_type,
int in_ts, int in_rank)
:id(in_person), path(in_path), parent(in_idx),
row(in_row), column(in_column),
name(in_name), size(in_size),
type(in_type), timestamp(in_ts), rank(in_rank)
{
return;
}
std::string id;
std::string path;
int parent;
int row;
int column;
/* display info */
std::string name;
int size;
int type;
int timestamp;
int rank;
};
//class RemoteIndex
//{
// public:
// RemoteIndex() {}
// RemoteIndex(std::string in_person,
// std::string in_path,
// int in_idx,
// int in_row,
// int in_column,
// std::string in_name,
// int in_size,
// int in_type,
// int in_ts, int in_rank)
// :id(in_person), path(in_path), parent(in_idx),
// row(in_row), column(in_column),
// name(in_name), size(in_size),
// type(in_type), timestamp(in_ts), rank(in_rank)
// {
// return;
// }
//
// std::string id;
// std::string path;
// int parent;
// int row;
// int column;
//
// /* display info */
// std::string name;
// int size;
// int type;
// int timestamp;
// int rank;
//
//};
bool RemoteMode;
mutable int nIndex;
mutable std::vector<RemoteIndex> indexSet;
//mutable int nIndex;
//mutable std::vector<RemoteIndex> indexSet;
// This material attempts to keep last request in cache, with no search cost.
@ -167,6 +175,8 @@ class RetroshareDirModel : public QAbstractItemModel
mutable time_t mLastReq;
bool mUpdating ;
std::set<void*> mFilteredPointers ;
};
// This class shows the classical hierarchical directory view of shared files
@ -178,28 +188,36 @@ class TreeStyle_RDM: public RetroshareDirModel
Q_OBJECT
public:
TreeStyle_RDM(bool mode)
: RetroshareDirModel(mode)
{
}
TreeStyle_RDM(bool mode);
virtual ~TreeStyle_RDM() ;
protected:
virtual void updateRef(const QModelIndex&) const ;
//Overloaded from RetroshareDirModel
virtual void update() ;
/* These are all overloaded Virtual Functions */
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual void updateRef(const QModelIndex&) const ;
virtual QMenu* getContextMenu(QMenu* contextMenu) ;
virtual QVariant displayRole(const DirDetails&,int) const ;
virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const ;
//Overloaded from QAbstractItemModel
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const;
virtual QModelIndex parent ( const QModelIndex & index ) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
private slots:
void showEmpty(const bool value);
private:
QAction *_showEmptyAct;
bool _showEmpty;
protected:
mutable std::vector<int> _parentRow ; // used to store the real parent row for non empty child
};
// This class shows a flat list of all shared files
@ -212,36 +230,41 @@ class FlatStyle_RDM: public RetroshareDirModel
public:
FlatStyle_RDM(bool mode);
virtual ~FlatStyle_RDM() ;
//Overloaded from RetroshareDirModel
virtual void update() ;
bool isMaxRefsTableSize(size_t* maxSize = NULL);
protected slots:
void updateRefs() ;
protected:
virtual void updateRef(const QModelIndex&) const {}
virtual void postMods();
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
//Overloaded from RetroshareDirModel
virtual void postMods();/* Callback from Core */
virtual void updateRef(const QModelIndex&) const {}
virtual QVariant displayRole(const DirDetails&,int) const ;
virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const ;
//Overloaded from QAbstractItemModel
virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const;
virtual QModelIndex parent ( const QModelIndex & index ) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QString computeDirectoryPath(const DirDetails& details) const ;
mutable RsMutex _ref_mutex ;
std::vector<void *> _ref_entries ;// used to store the refs to display
std::vector<void *> _ref_stack ; // used to store the refs to update
mutable RsMutex _ref_mutex ;
std::vector<void *> _ref_entries ; // used to store the refs to display
std::vector<void *> _ref_stack ; // used to store the refs to update
bool _needs_update ;
time_t _last_update ;
time_t _last_update ;
};

View file

@ -1213,7 +1213,6 @@ bool RetroShareLink::checkRadix64(const QString& s)
return false;
}
}
std::cerr << "Radix check: passed" << std::endl;
return true ;
}
@ -1968,7 +1967,9 @@ void RSLinkClipboard::parseText(QString text, QList<RetroShareLink> &links,Retro
{
links.clear();
#ifdef DEBUG_RSLINK
std::cerr << "Parsing text:" << text.toStdString() << std::endl ;
#endif
QRegExp rx(QString("retroshare://(%1)[^\r\n]+").arg(HOST_REGEXP));

View file

@ -715,7 +715,7 @@ void WikiEditDialog::loadBaseHistory(const uint32_t &token)
std::cerr << " ParentId: " << page.mMeta.mParentId;
std::cerr << std::endl;
GxsIdRSTreeWidgetItem *modItem = new GxsIdRSTreeWidgetItem(mThreadCompareRole);
GxsIdRSTreeWidgetItem *modItem = new GxsIdRSTreeWidgetItem(mThreadCompareRole, GxsIdDetails::ICON_TYPE_AVATAR);
modItem->setData(WET_DATA_COLUMN, WET_ROLE_ORIGPAGEID, QString::fromStdString(page.mMeta.mOrigMsgId.toStdString()));
modItem->setData(WET_DATA_COLUMN, WET_ROLE_PAGEID, QString::fromStdString(page.mMeta.mMsgId.toStdString()));
@ -830,7 +830,7 @@ void WikiEditDialog::loadEditTreeData(const uint32_t &token)
}
/* create an Entry */
GxsIdRSTreeWidgetItem *modItem = new GxsIdRSTreeWidgetItem(mThreadCompareRole);
GxsIdRSTreeWidgetItem *modItem = new GxsIdRSTreeWidgetItem(mThreadCompareRole, GxsIdDetails::ICON_TYPE_AVATAR);
modItem->setData(WET_DATA_COLUMN, WET_ROLE_ORIGPAGEID, QString::fromStdString(snapshot.mMeta.mOrigMsgId.toStdString()));
modItem->setData(WET_DATA_COLUMN, WET_ROLE_PAGEID, QString::fromStdString(snapshot.mMeta.mMsgId.toStdString()));
modItem->setData(WET_DATA_COLUMN, WET_ROLE_PARENTID, QString::fromStdString(snapshot.mMeta.mParentId.toStdString()));

View file

@ -33,6 +33,7 @@
#include "gui/ChatLobbyWidget.h"
#include "gui/FriendsDialog.h"
#include "gui/MainWindow.h"
#include "gui/chat/ChatWidget.h"
#include "gui/common/html.h"
#include "gui/common/FriendSelectionDialog.h"
#include "gui/common/RSTreeWidgetItem.h"
@ -97,7 +98,7 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
votePositiveAct = new QAction(QIcon(":/icons/png/thumbs-up.png"), tr("Give positive opinion"), this);
distantChatAct = new QAction(QIcon(":/images/chat_24.png"), tr("Start private chat"), this);
sendMessageAct = new QAction(QIcon(":/images/mail_new.png"), tr("Send Message"), this);
showinpeopleAct = new QAction(QIcon(), tr("Show author in people tab"), this);
showInPeopleAct = new QAction(QIcon(), tr("Show author in people tab"), this);
QActionGroup *sortgrp = new QActionGroup(this);
actionSortByName = new QAction(QIcon(), tr("Sort by Name"), this);
@ -111,17 +112,13 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
actionSortByActivity->setActionGroup(sortgrp);
connect(muteAct, SIGNAL(triggered()), this, SLOT(changePartipationState()));
connect(muteAct, SIGNAL(triggered()), this, SLOT(changeParticipationState()));
connect(distantChatAct, SIGNAL(triggered()), this, SLOT(distantChatParticipant()));
connect(sendMessageAct, SIGNAL(triggered()), this, SLOT(sendMessage()));
connect(votePositiveAct, SIGNAL(triggered()), this, SLOT(voteParticipant()));
connect(voteNeutralAct, SIGNAL(triggered()), this, SLOT(voteParticipant()));
connect(voteNegativeAct, SIGNAL(triggered()), this, SLOT(voteParticipant()));
connect(showinpeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab()));
votePositiveAct->setData(RsReputations::OPINION_POSITIVE);
voteNeutralAct->setData(RsReputations::OPINION_NEUTRAL);
voteNegativeAct->setData(RsReputations::OPINION_NEGATIVE);
connect(showInPeopleAct, SIGNAL(triggered()), this, SLOT(showInPeopleTab()));
connect(actionSortByName, SIGNAL(triggered()), this, SLOT(sortParcipants()));
connect(actionSortByActivity, SIGNAL(triggered()), this, SLOT(sortParcipants()));
@ -172,7 +169,8 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
ui.chatWidget->addToolsAction(checkableAction);
//getChatWidget()->addChatBarWidget(ownIdChooser);
connect(ui.chatWidget, SIGNAL(textBrowserAskContextMenu(QMenu*,QString,QPoint)), this, SLOT(textBrowserAskContextMenu(QMenu*,QString,QPoint)));
connect(ownIdChooser,SIGNAL(currentIndexChanged(int)),this,SLOT(changeNickname())) ;
@ -226,33 +224,76 @@ void ChatLobbyDialog::inviteFriends()
void ChatLobbyDialog::participantsTreeWidgetCustomPopupMenu(QPoint)
{
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
QList<RsGxsId> idList;
QList<QTreeWidgetItem*>::iterator item;
for (item = selectedItems.begin(); item != selectedItems.end(); ++item)
{
RsGxsId gxs_id ;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*item)->getId(gxs_id) ;
idList.append(gxs_id);
}
QMenu contextMnu(this);
contextMnu.addAction(actionSortByActivity);
contextMnu.addAction(actionSortByName);
contextMnu.addAction(distantChatAct);
contextMnu.addAction(sendMessageAct);
contextMnu.addSeparator();
contextMnu.addAction(actionSortByActivity);
contextMnu.addAction(actionSortByName);
contextMnu.addSeparator();
contextMnu.addAction(muteAct);
contextMnu.addAction(votePositiveAct);
contextMnu.addAction(voteNeutralAct);
contextMnu.addAction(voteNegativeAct);
contextMnu.addAction(showinpeopleAct);
contextMnu.addSeparator();
initParticipantsContextMenu(&contextMnu, idList);
contextMnu.exec(QCursor::pos());
}
void ChatLobbyDialog::textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint /*point*/)
{
if (anchorForPosition.startsWith(PERSONID)){
QString strId = anchorForPosition.replace(PERSONID,"");
if (strId.contains(" "))
strId.truncate(strId.indexOf(" "));
contextMnu->addSeparator();
QList<RsGxsId> idList;
idList.append(RsGxsId(strId.toStdString()));
initParticipantsContextMenu(contextMnu, idList);
}
}
void ChatLobbyDialog::initParticipantsContextMenu(QMenu *contextMnu, QList<RsGxsId> idList)
{
if (!contextMnu)
return;
contextMnu->addAction(distantChatAct);
contextMnu->addAction(sendMessageAct);
contextMnu->addSeparator();
contextMnu->addAction(muteAct);
contextMnu->addAction(votePositiveAct);
contextMnu->addAction(voteNeutralAct);
contextMnu->addAction(voteNegativeAct);
contextMnu->addAction(showInPeopleAct);
distantChatAct->setEnabled(false);
sendMessageAct->setEnabled(selectedItems.count()==1);
sendMessageAct->setEnabled(true);
muteAct->setEnabled(false);
muteAct->setCheckable(true);
muteAct->setEnabled(false);
muteAct->setChecked(false);
votePositiveAct->setEnabled(false);
voteNeutralAct->setEnabled(false);
voteNegativeAct->setEnabled(false);
showinpeopleAct->setEnabled(selectedItems.count()==1);
if(selectedItems.count()==1)
{
RsGxsId gxsid(selectedItems.at(0)->text(COLUMN_ID).toStdString());
muteAct->setChecked(false);
votePositiveAct->setEnabled(false);
voteNeutralAct->setEnabled(false);
voteNegativeAct->setEnabled(false);
showInPeopleAct->setEnabled(idList.count()==1);
distantChatAct->setData(QVariant::fromValue(idList));
sendMessageAct->setData(QVariant::fromValue(idList));
muteAct->setData(QVariant::fromValue(idList));
votePositiveAct->setData(QVariant::fromValue(idList));
voteNeutralAct->setData(QVariant::fromValue(idList));
voteNegativeAct->setData(QVariant::fromValue(idList));
showInPeopleAct->setData(QVariant::fromValue(idList));
if(idList.count()==1)
{
RsGxsId gxsid = idList.at(0);
if(!gxsid.isNull() && !rsIdentity->isOwnId(gxsid))
{
@ -263,49 +304,56 @@ void ChatLobbyDialog::participantsTreeWidgetCustomPopupMenu(QPoint)
muteAct->setEnabled(true);
muteAct->setChecked(isParticipantMuted(gxsid));
}
}
contextMnu.exec(QCursor::pos());
}
}
void ChatLobbyDialog::voteParticipant()
{
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
if (selectedItems.isEmpty())
return;
QList<QTreeWidgetItem*>::iterator item;
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
RsReputations::Opinion op = RsReputations::Opinion(act->data().toUInt()) ;
for (item = selectedItems.begin(); item != selectedItems.end(); ++item)
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
RsGxsId nickname;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*item)->getId(nickname) ;
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
rsReputations->setOwnOpinion(nickname, op);
std::cerr << "Giving opinion to GXS id " << nickname << " to " << op<< std::endl;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*item)->forceUpdate();
}
QList<RsGxsId> idList = act->data().value<QList<RsGxsId>>();
RsReputations::Opinion op = RsReputations::OPINION_NEUTRAL ;
if (act == votePositiveAct)
op = RsReputations::OPINION_POSITIVE;
if (act == voteNegativeAct)
op = RsReputations::OPINION_NEGATIVE;
for (QList<RsGxsId>::iterator item = idList.begin(); item != idList.end(); ++item)
{
rsReputations->setOwnOpinion(*item, op);
std::cerr << "Giving opinion to GXS id " << *item << " to " << op << std::endl;
}
updateParticipantsList();
}
void ChatLobbyDialog::showInPeopleTab()
{
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
if (selectedItems.count()!=1)
return;
RsGxsId nickname;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*selectedItems.begin())->getId(nickname);
IdDialog *idDialog = dynamic_cast<IdDialog*>(MainWindow::getPage(MainWindow::People));
if (!idDialog)
return ;
MainWindow::showWindow(MainWindow::People);
idDialog->navigate(nickname);
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
QList<RsGxsId> idList = act->data().value<QList<RsGxsId>>();
if (idList.count() != 1)
return;
RsGxsId nickname = idList.at(0);
IdDialog *idDialog = dynamic_cast<IdDialog*>(MainWindow::getPage(MainWindow::People));
if (!idDialog)
return ;
MainWindow::showWindow(MainWindow::People);
idDialog->navigate(nickname);
}
void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/)
@ -586,34 +634,28 @@ void ChatLobbyDialog::updateParticipantsList()
}
/**
* Called when a Participant in QTree get Clicked / Changed
* Called when a Participant get Clicked / Changed
*
* Check if the Checkbox altered and Mute User
*
* @todo auf rsid
*
* @param QTreeWidgetItem Participant to check
*/
void ChatLobbyDialog::changePartipationState()
void ChatLobbyDialog::changeParticipationState()
{
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
if (selectedItems.isEmpty()) {
return;
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
QList<QTreeWidgetItem*>::iterator item;
for (item = selectedItems.begin(); item != selectedItems.end(); ++item) {
QList<RsGxsId> idList = act->data().value<QList<RsGxsId>>();
RsGxsId gxs_id ;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*item)->getId(gxs_id) ;
std::cerr << "check Partipation status for '" << gxs_id << std::endl;
if (muteAct->isChecked()) {
muteParticipant(gxs_id);
for (QList<RsGxsId>::iterator item = idList.begin(); item != idList.end(); ++item)
{
std::cerr << "check Partipation status for '" << *item << std::endl;
if (act->isChecked()) {
muteParticipant(*item);
} else {
unMuteParticipant(gxs_id);
unMuteParticipant(*item);
}
}
@ -650,75 +692,68 @@ void ChatLobbyDialog::participantsTreeWidgetDoubleClicked(QTreeWidgetItem *item,
void ChatLobbyDialog::distantChatParticipant()
{
std::cerr << " initiating distant chat" << std::endl;
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
std::cerr << " initiating distant chat" << std::endl;
if (selectedItems.isEmpty())
return;
QList<RsGxsId> idList = act->data().value<QList<RsGxsId>>();
if (idList.count() != 1)
return;
if(selectedItems.size() != 1)
return ;
RsGxsId gxs_id = idList.at(0);
if (gxs_id.isNull())
return;
GxsIdRSTreeWidgetItem *item = dynamic_cast<GxsIdRSTreeWidgetItem*>(selectedItems.front());
RsGxsId own_id;
rsMsgs->getIdentityForChatLobby(lobbyId, own_id);
if(!item)
return ;
DistantChatPeerId tunnel_id;
uint32_t error_code ;
RsGxsId gxs_id ;
item->getId(gxs_id) ;
RsGxsId own_id;
rsMsgs->getIdentityForChatLobby(lobbyId, own_id);
uint32_t error_code ;
DistantChatPeerId tunnel_id;
if(! rsMsgs->initiateDistantChatConnexion(gxs_id,own_id,tunnel_id,error_code))
{
QString error_str ;
switch(error_code)
{
case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED : error_str = tr("Decryption failed.") ; break ;
case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH : error_str = tr("Signature mismatch") ; break ;
case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY : error_str = tr("Unknown key") ; break ;
case RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH : error_str = tr("Unknown hash") ; break ;
default:
error_str = tr("Unknown error.") ;
}
QMessageBox::warning(NULL,tr("Cannot start distant chat"),tr("Distant chat cannot be initiated:")+" "+error_str
+QString::number(error_code)) ;
}
if(! rsMsgs->initiateDistantChatConnexion(gxs_id,own_id,tunnel_id,error_code))
{
QString error_str ;
switch(error_code)
{
case RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED : error_str = tr("Decryption failed.") ; break ;
case RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH : error_str = tr("Signature mismatch") ; break ;
case RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY : error_str = tr("Unknown key") ; break ;
case RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH : error_str = tr("Unknown hash") ; break ;
default:
error_str = tr("Unknown error.") ;
}
QMessageBox::warning(NULL,tr("Cannot start distant chat"),tr("Distant chat cannot be initiated:")+" "+error_str
+QString::number(error_code)) ;
}
}
void ChatLobbyDialog::sendMessage()
{
QAction *act = dynamic_cast<QAction*>(sender()) ;
if(!act)
{
std::cerr << "No sender! Some bug in the code." << std::endl;
return ;
}
QList<QTreeWidgetItem*> selectedItems = ui.participantsList->selectedItems();
QList<RsGxsId> idList = act->data().value<QList<RsGxsId>>();
if (selectedItems.isEmpty())
return;
MessageComposer *nMsgDialog = MessageComposer::newMsg();
if (nMsgDialog == NULL)
return;
QList<QTreeWidgetItem*>::iterator item;
for (item = selectedItems.begin(); item != selectedItems.end(); ++item) {
for (QList<RsGxsId>::iterator item = idList.begin(); item != idList.end(); ++item)
nMsgDialog->addRecipient(MessageComposer::TO, *item);
RsGxsId gxs_id ;
dynamic_cast<GxsIdRSTreeWidgetItem*>(*item)->getId(gxs_id) ;
MessageComposer *nMsgDialog = MessageComposer::newMsg();
if (nMsgDialog == NULL) {
return;
}
nMsgDialog->addRecipient(MessageComposer::TO, RsGxsId(gxs_id));
nMsgDialog->show();
nMsgDialog->activateWindow();
/* window will destroy itself! */
}
nMsgDialog->show();
nMsgDialog->activateWindow();
/* window will destroy itself! */
}

View file

@ -27,6 +27,9 @@
#include "gui/common/RSTreeWidgetItem.h"
#include "ChatDialog.h"
Q_DECLARE_METATYPE(RsGxsId)
Q_DECLARE_METATYPE(QList<RsGxsId>)
class GxsIdChooser ;
class QToolButton;
class QWidgetAction;
@ -51,6 +54,7 @@ public:
private slots:
void participantsTreeWidgetCustomPopupMenu( QPoint point );
void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point);
void inviteFriends() ;
void leaveLobby() ;
void filterChanged(const QString &text);
@ -77,7 +81,7 @@ protected:
protected slots:
void changeNickname();
void changePartipationState();
void changeParticipationState();
void distantChatParticipant();
void participantsTreeWidgetDoubleClicked(QTreeWidgetItem *item, int column);
void sendMessage();
@ -85,6 +89,7 @@ protected slots:
private:
void updateParticipantsList();
void initParticipantsContextMenu(QMenu* contextMnu, QList<RsGxsId> idList);
void filterIds();
@ -117,8 +122,8 @@ private:
QAction *actionSortByActivity;
QWidgetAction *checkableAction;
QAction *sendMessageAct;
QAction *showinpeopleAct;
QAction *showInPeopleAct;
GxsIdChooser *ownIdChooser ;
//icons cache
QIcon bullet_red_128, bullet_grey_128, bullet_green_128, bullet_yellow_128;

View file

@ -20,6 +20,8 @@
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QTabBar>
#include "ChatTabWidget.h"
#include "ui_ChatTabWidget.h"
#include "ChatDialog.h"

View file

@ -66,8 +66,6 @@
#define FMM 2.5//fontMetricsMultiplicator
#define PERSONID "PersonId:"
/*****
* #define CHAT_DEBUG 1
*****/
@ -389,7 +387,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title)
name = QString::fromUtf8(historyIt->peerName.c_str());
}
addChatMsg(historyIt->incoming, name, QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), MSGTYPE_HISTORY);
addChatMsg(historyIt->incoming, name, RsGxsId(historyIt->peerName.c_str()), QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), MSGTYPE_HISTORY);
}
}
}
@ -474,6 +472,7 @@ uint32_t ChatWidget::maxMessageSize()
bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
{
//QEvent::Type type = event->type();
if (obj == ui->textBrowser || obj == ui->textBrowser->viewport()
|| obj == ui->leSearch || obj == ui->chatTextEdit) {
if (event->type() == QEvent::KeyPress) {
@ -593,31 +592,15 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::ToolTip) {
QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
QTextCursor cursor = ui->textBrowser->cursorForPosition(helpEvent->pos());
cursor.select(QTextCursor::WordUnderCursor);
QString toolTipText = "";
if (!cursor.selectedText().isEmpty()){
QRegExp rx("<a name=\"(.*)\"",Qt::CaseSensitive, QRegExp::RegExp2);
rx.setMinimal(true);
QString sel=cursor.selection().toHtml();
QStringList anchors;
int pos=0;
while ((pos = rx.indexIn(sel,pos)) != -1) {
anchors << rx.cap(1);
pos += rx.matchedLength();
}
if (!anchors.isEmpty()){
toolTipText = anchors.at(0);
}
if (toolTipText.isEmpty() && !ui->textBrowser->getShowImages()){
QString imageStr;
if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) {
toolTipText = imageStr;
}
} else if (toolTipText.startsWith(PERSONID)){
toolTipText = toolTipText.replace(PERSONID, tr("Person id: ") );
toolTipText = toolTipText.append(tr("\nDouble click on it to add his name on text writer.") );
QString toolTipText = ui->textBrowser->anchorForPosition(helpEvent->pos());
if (toolTipText.isEmpty() && !ui->textBrowser->getShowImages()){
QString imageStr;
if (ui->textBrowser->checkImage(helpEvent->pos(), imageStr)) {
toolTipText = imageStr;
}
} else if (toolTipText.startsWith(PERSONID)){
toolTipText = toolTipText.replace(PERSONID, tr("Person id: ") );
toolTipText = toolTipText.append(tr("\nDouble click on it to add his name on text writer.") );
}
if (!toolTipText.isEmpty()){
QToolTip::showText(helpEvent->globalPos(), toolTipText);
@ -673,6 +656,17 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
}
}
}
if (event->type() == QEvent::StyleChange)
{
QString colorName = currentColor.name();
qreal desiredContrast = Settings->valueFromGroup("Chat", "MinimumContrast", 4.5).toDouble();
QColor backgroundColor = ui->chatTextEdit->palette().base().color();
RsHtml::findBestColor(colorName, backgroundColor, desiredContrast);
currentColor = QColor(colorName);
ui->chatTextEdit->setTextColor(currentColor);
colorChanged();
}
} else if (obj == ui->leSearch) {
if (event->type() == QEvent::KeyPress) {
@ -698,32 +692,19 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::MouseButtonDblClick) {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
QTextCursor cursor = ui->textBrowser->cursorForPosition(mouseEvent->pos());
cursor.select(QTextCursor::WordUnderCursor);
if (!cursor.selectedText().isEmpty()){
QRegExp rx("<a name=\"(.*)\"",Qt::CaseSensitive, QRegExp::RegExp2);
rx.setMinimal(true);
QString sel=cursor.selection().toHtml();
QStringList anchors;
int pos=0;
while ((pos = rx.indexIn(sel,pos)) != -1) {
anchors << rx.cap(1);
pos += rx.matchedLength();
}
QString anchor = ui->textBrowser->anchorForPosition(mouseEvent->pos());
if (!anchor.isEmpty()){
if (anchor.startsWith(PERSONID)){
QString strId = anchor.replace(PERSONID,"");
if (strId.contains(" "))
strId.truncate(strId.indexOf(" "));
if (!anchors.isEmpty()){
if (anchors.at(0).startsWith(PERSONID)){
QString strId = QString(anchors.at(0)).replace(PERSONID,"");
if (strId.contains(" "))
strId.truncate(strId.indexOf(" "));
RsGxsId mId = RsGxsId(strId.toStdString());
if(!mId.isNull()) {
RsIdentityDetails details;
if (rsIdentity->getIdDetails(mId, details)){
QString text = QString("@").append(GxsIdDetails::getName(details)).append(" ");
ui->chatTextEdit->textCursor().insertText(text);
}
RsGxsId mId = RsGxsId(strId.toStdString());
if(!mId.isNull()) {
RsIdentityDetails details;
if (rsIdentity->getIdDetails(mId, details)){
QString text = QString("@").append(GxsIdDetails::getName(details)).append(" ");
ui->chatTextEdit->textCursor().insertText(text);
}
}
}
@ -731,6 +712,13 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
}
}
} else {
if (event->type() == QEvent::WindowActivate) {
if (isVisible() && (window() == NULL || window()->isActiveWindow())) {
newMessages = false;
emit infoChanged(this);
}
}
}
// pass the event on to the parent class
return QWidget::eventFilter(obj, event);
@ -1119,6 +1107,9 @@ void ChatWidget::contextMenuTextBrowser(QPoint point)
contextMnu->addAction(ui->actionSave_image);
}
QString anchor = ui->textBrowser->anchorForPosition(point);
emit textBrowserAskContextMenu(contextMnu, anchor, point);
contextMnu->exec(ui->textBrowser->viewport()->mapToGlobal(point));
delete(contextMnu);
}
@ -1586,7 +1577,7 @@ void ChatWidget::fileHashingFinished(QList<HashedFile> hashedFiles)
QList<HashedFile>::iterator it;
for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) {
HashedFile& hashedFile = *it;
//QString ext = QFileInfo(hashedFile.filename).suffix();
QString ext = QFileInfo(hashedFile.filename).suffix().toUpper();
RetroShareLink link;
@ -1598,9 +1589,23 @@ void ChatWidget::fileHashingFinished(QList<HashedFile> hashedFiles)
message += QString("<img src=\"file:///%1\" width=\"100\" height=\"100\">").arg(hashedFile.filepath);
message+="<br>";
} else {
QString image = FilesDefs::getImageFromFilename(hashedFile.filename, false);
if (!image.isEmpty()) {
message += QString("<img src=\"%1\">").arg(image);
bool preview = false;
if(hashedFiles.size()==1 && (ext == "JPG" || ext == "PNG" || ext == "JPEG" || ext == "GIF"))
{
QString encodedImage;
uint32_t maxMessageSize = this->maxMessageSize();
if (RsHtml::makeEmbeddedImage(hashedFile.filepath, encodedImage, 640*480, maxMessageSize - 200 - link.toHtmlSize().length()))
{ QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage);
ui->chatTextEdit->textCursor().insertFragment(fragment);
preview=true;
}
}
if(!preview)
{
QString image = FilesDefs::getImageFromFilename(hashedFile.filename, false);
if (!image.isEmpty()) {
message += QString("<img src=\"%1\">").arg(image);
}
}
}
message += link.toHtmlSize();
@ -1779,7 +1784,7 @@ void ChatWidget::updatePeersCustomStateString(const QString& /*peer_id*/, const
void ChatWidget::updateStatusString(const QString &statusMask, const QString &statusString, bool permanent)
{
ui->typingLabel->setText(QString(statusMask).arg(tr(statusString.toUtf8()))); // displays info for 5 secs.
ui->typingLabel->setText(QString(statusMask).arg(trUtf8(statusString.toUtf8()))); // displays info for 5 secs.
ui->typingPixmapLabel->setPixmap(QPixmap(":images/typing.png") );
if (statusString == "is typing...") {

View file

@ -37,6 +37,9 @@
#include <retroshare/rsmsgs.h>
#include <retroshare/rsfiles.h>
//For PersonId anchor.
#define PERSONID "PersonId:"
class QAction;
class QTextEdit;
class QPushButton;
@ -137,6 +140,7 @@ signals:
void infoChanged(ChatWidget*);
void newMessage(ChatWidget*);
void statusChanged(int);
void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point);
protected:
bool eventFilter(QObject *obj, QEvent *event);

View file

@ -135,7 +135,7 @@ void PopupDistantChatDialog::updateDisplay()
break ;
case RS_DISTANT_CHAT_STATUS_TUNNEL_DN:
//std::cerr << "Tunnel asked. Waiting for reponse. " << std::endl;
_status_label->setIcon(QIcon(IMAGE_RED_LED));
_status_label->setIcon(QIcon(IMAGE_YEL_LED));
msg = QObject::tr( "Tunnel is pending... Messages will be delivered as"
" soon as possible" );
_status_label->setToolTip(msg);

View file

@ -496,22 +496,21 @@ void FriendList::groupsChanged()
static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay)
{
int avatarWidth = avatar.width();
int avatarHeight = avatar.height();
int avatarWidth = avatar.width();
int avatarHeight = avatar.height();
QPixmap pixmap(avatar);
QPixmap pixmap(avatar);
int overlayWidth = avatarWidth / 2.5;
int overlayHeight = avatarHeight / 2.5;
int overlayX = avatarWidth - overlayWidth;
int overlayY = avatarHeight - overlayHeight;
int overlaySize = (avatarWidth > avatarHeight) ? (avatarWidth/2.5) : (avatarHeight/2.5);
int overlayX = avatarWidth - overlaySize;
int overlayY = avatarHeight - overlaySize;
QPainter painter(&pixmap);
painter.drawPixmap(overlayX, overlayY, overlayWidth, overlayHeight, overlay);
QPainter painter(&pixmap);
painter.drawPixmap(overlayX, overlayY, overlaySize, overlaySize, overlay);
QIcon icon;
icon.addPixmap(pixmap);
return icon;
QIcon icon;
icon.addPixmap(pixmap);
return icon;
}
static void getNameWidget(QTreeWidget *treeWidget, QTreeWidgetItem *item, ElidedLabel *&nameLabel, ElidedLabel *&textLabel)

View file

@ -43,7 +43,8 @@
#define COLUMN_NAME 0
#define COLUMN_UNREAD 1
#define COLUMN_POPULARITY 2
#define COLUMN_COUNT 3
#define COLUMN_LAST_POST 3
#define COLUMN_COUNT 4
#define COLUMN_DATA COLUMN_NAME
#define ROLE_ID Qt::UserRole
@ -100,9 +101,12 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) :
/* Initialize tree widget */
ui->treeWidget->setColumnCount(COLUMN_COUNT);
ui->treeWidget->enableColumnCustomize(true);
ui->treeWidget->setColumnCustomizable(COLUMN_NAME, false);
int S = QFontMetricsF(font()).height() ;
int W = QFontMetricsF(font()).width("999") ;
int D = QFontMetricsF(font()).width("9999-99-99[]") ;
/* Set header resize modes and initial section sizes */
QHeaderView *header = ui->treeWidget->header ();
@ -113,6 +117,15 @@ GroupTreeWidget::GroupTreeWidget(QWidget *parent) :
header->resizeSection(COLUMN_UNREAD, W+4) ;
QHeaderView_setSectionResizeModeColumn(header, COLUMN_POPULARITY, QHeaderView::Fixed);
header->resizeSection(COLUMN_POPULARITY, 2*S) ;
QHeaderView_setSectionResizeModeColumn(header, COLUMN_LAST_POST, QHeaderView::Fixed);
header->resizeSection(COLUMN_LAST_POST, D+4) ;
header->setSectionHidden(COLUMN_LAST_POST, true);
QTreeWidgetItem *headerItem = ui->treeWidget->headerItem();
headerItem->setText(COLUMN_NAME, tr("Name"));
headerItem->setText(COLUMN_UNREAD, tr("Unread"));
headerItem->setText(COLUMN_POPULARITY, tr("Popularity"));
headerItem->setText(COLUMN_LAST_POST, tr("Last Post"));
/* add filter actions */
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), FILTER_NAME_INDEX , tr("Search Title"));
@ -192,9 +205,10 @@ void GroupTreeWidget::addToolButton(QToolButton *toolButton)
ui->titleBarFrame->layout()->addWidget(toolButton);
}
void GroupTreeWidget::processSettings(RshareSettings *settings, bool load)
// Load and save settings (group must be started from the caller)
void GroupTreeWidget::processSettings(bool load)
{
if (settings == NULL) {
if (Settings == NULL) {
return;
}
@ -204,16 +218,18 @@ void GroupTreeWidget::processSettings(RshareSettings *settings, bool load)
const int SORTBY_POSTS = 4;
const int SORTBY_UNREAD = 5;
ui->treeWidget->processSettings(load);
if (load) {
// load settings
// load Settings
// state of order
bool ascSort = settings->value("GroupAscSort", true).toBool();
bool ascSort = Settings->value("GroupAscSort", true).toBool();
actionSortAscending->setChecked(ascSort);
actionSortDescending->setChecked(!ascSort);
// state of sort
int sortby = settings->value("GroupSortBy").toInt();
int sortby = Settings->value("GroupSortBy").toInt();
switch (sortby) {
case SORTBY_NAME:
if (actionSortByName) {
@ -242,10 +258,10 @@ void GroupTreeWidget::processSettings(RshareSettings *settings, bool load)
break;
}
} else {
// save settings
// save Settings
// state of order
settings->setValue("GroupAscSort", !(actionSortDescending && actionSortDescending->isChecked())); //True by default
Settings->setValue("GroupAscSort", !(actionSortDescending && actionSortDescending->isChecked())); //True by default
// state of sort
int sortby = SORTBY_NAME;
@ -260,7 +276,7 @@ void GroupTreeWidget::processSettings(RshareSettings *settings, bool load)
} else if (actionSortByUnread && actionSortByUnread->isChecked()) {
sortby = SORTBY_UNREAD;
}
settings->setValue("GroupSortBy", sortby);
Settings->setValue("GroupSortBy", sortby);
}
}
@ -453,6 +469,11 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
/* Set last post */
qlonglong lastPost = itemInfo.lastpost.toTime_t();
item->setData(COLUMN_DATA, ROLE_LASTPOST, -lastPost); // negative for correct sorting
if(itemInfo.lastpost == QDateTime::fromTime_t(0))
item->setText(COLUMN_LAST_POST, tr("Never"));
else
item->setText(COLUMN_LAST_POST, itemInfo.lastpost.toString(Qt::ISODate).replace("T"," "));
/* Set visible posts */
item->setData(COLUMN_DATA, ROLE_POSTS, -itemInfo.max_visible_posts);// negative for correct sorting
@ -481,12 +502,14 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
tooltip += "\n" + QString::number(itemInfo.max_visible_posts) + " messages available" ;
// if(itemInfo.max_visible_posts) // wtf? this=0 when there are some posts definitely exist - lastpost is recent
if(itemInfo.lastpost == QDateTime::fromTime_t(0))
tooltip += "\n" + tr("Last Post") + ": " + tr("Never") ;
tooltip += "\n" + tr("Last Post") + ": " + tr("Never") ;
else
tooltip += "\n" + tr("Last Post") + ": " + DateTime::formatLongDateTime(itemInfo.lastpost) ;
if(!IS_GROUP_SUBSCRIBED(itemInfo.subscribeFlags))
tooltip += "\n" + tr("Subscribe to download and read messages") ;
tooltip += "\n" + tr("Description") + ": " + itemInfo.description;
item->setToolTip(COLUMN_NAME, tooltip);
item->setToolTip(COLUMN_UNREAD, tooltip);
item->setToolTip(COLUMN_POPULARITY, tooltip);

View file

@ -77,8 +77,8 @@ public:
// Add a tool button to the tool area
void addToolButton(QToolButton *toolButton);
// Load and save settings (group must be startet from the caller)
void processSettings(RshareSettings *settings, bool load);
// Load and save settings (group must be started from the caller)
void processSettings(bool load);
// Add a new category item
QTreeWidgetItem *addCategoryItem(const QString &name, const QIcon &icon, bool expand);

View file

@ -243,3 +243,30 @@ bool RSTextBrowser::checkImage(QPoint pos, QString &imageStr)
}
return false;
}
/**
* @brief RSTextBrowser::anchorForPosition Replace anchorAt that doesn't works as expected.
* @param pos Where to get anchor from text
* @return anchor If text at pos is inside anchor, else empty string.
*/
QString RSTextBrowser::anchorForPosition(const QPoint &pos) const
{
QTextCursor cursor = cursorForPosition(pos);
cursor.select(QTextCursor::WordUnderCursor);
QString anchor = "";
if (!cursor.selectedText().isEmpty()){
QRegExp rx("<a name=\"(.*)\"",Qt::CaseSensitive, QRegExp::RegExp2);
rx.setMinimal(true);
QString sel = cursor.selection().toHtml();
QStringList anchors;
int pos=0;
while ((pos = rx.indexIn(sel,pos)) != -1) {
anchors << rx.cap(1);
pos += rx.matchedLength();
}
if (!anchors.isEmpty()){
anchor = anchors.at(0);
}
}
return anchor;
}

View file

@ -24,6 +24,8 @@ public:
QPixmap getBlockedImage();
bool checkImage(QPoint pos, QString &imageStr);
bool checkImage(QPoint pos) {QString imageStr; return checkImage(pos, imageStr); }
QString anchorForPosition(const QPoint &pos) const;
void activateLinkClick(bool active);

View file

@ -639,8 +639,17 @@ void RsCollectionDialog::directoryLoaded(QString dirLoaded)
*/
void RsCollectionDialog::updateSizes()
{
ui._selectedFiles_TL->setText(QString::number(getRootItem()->data(COLUMN_FILEC,ROLE_SELFILEC).toULongLong())) ;
ui._totalSize_TL->setText(misc::friendlyUnit(getRootItem()->data(COLUMN_SIZE,ROLE_SELSIZE).toULongLong())) ;
uint64_t total_size = 0 ;
uint32_t total_count = 0 ;
for(uint32_t i=0;i<ui._fileEntriesTW->topLevelItemCount();++i)
{
total_size += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_SIZE ,ROLE_SELSIZE ).toULongLong();
total_count += ui._fileEntriesTW->topLevelItem(i)->data(COLUMN_FILEC,ROLE_SELFILEC).toULongLong();
}
ui._selectedFiles_TL->setText(QString::number(total_count));
ui._totalSize_TL->setText(misc::friendlyUnit(total_size));
}
/**

View file

@ -23,6 +23,7 @@
#include <QTimer>
#include <QFileInfo>
#include <QStyle>
#include "rshare.h"
#include "GxsChannelPostItem.h"

View file

@ -23,6 +23,7 @@
#include <QTimer>
#include <QFileInfo>
#include <QStyle>
#include "rshare.h"
#include "GxsForumMsgItem.h"
@ -437,8 +438,8 @@ void GxsForumMsgItem::requestParentMessage(const RsGxsMessageId &msgId)
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect_msgIds = msgIds[groupId()];
vect_msgIds.push_back(msgId);
std::set<RsGxsMessageId> &vect_msgIds = msgIds[groupId()];
vect_msgIds.insert(msgId);
uint32_t token;
mLoadQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeParentMessage);

View file

@ -93,19 +93,15 @@ void GxsFeedItem::fillDisplay(RsGxsUpdateBroadcastBase *updateBroadcastBase, boo
{
GxsGroupFeedItem::fillDisplay(updateBroadcastBase, complete);
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgs;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > msgs;
updateBroadcastBase->getAllMsgIds(msgs);
if (!msgs.empty())
{
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator mit = msgs.find(groupId());
if (mit != msgs.end())
{
const std::vector<RsGxsMessageId> &msgIds = mit->second;
if (std::find(msgIds.begin(), msgIds.end(), messageId()) != msgIds.end()) {
std::map<RsGxsGroupId, std::set<RsGxsMessageId> >::const_iterator mit = msgs.find(groupId());
if (mit != msgs.end() && mit->second.find(messageId()) != mit->second.end())
requestMessage();
}
}
}
}
@ -129,8 +125,8 @@ void GxsFeedItem::requestMessage()
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect_msgIds = msgIds[groupId()];
vect_msgIds.push_back(mMessageId);
std::set<RsGxsMessageId> &vect_msgIds = msgIds[groupId()];
vect_msgIds.insert(mMessageId);
uint32_t token;
mLoadQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeMessage);

View file

@ -170,12 +170,11 @@ void GxsGroupFeedItem::fillDisplaySlot(bool complete)
void GxsGroupFeedItem::fillDisplay(RsGxsUpdateBroadcastBase *updateBroadcastBase, bool /*complete*/)
{
std::list<RsGxsGroupId> grpIds;
std::set<RsGxsGroupId> grpIds;
updateBroadcastBase->getAllGrpIds(grpIds);
if (std::find(grpIds.begin(), grpIds.end(), groupId()) != grpIds.end()) {
if (grpIds.find(groupId()) != grpIds.end())
requestGroup();
}
}
/***********************************************************/

View file

@ -194,7 +194,7 @@ void GxsGroupFrameDialog::processSettings(bool load)
Settings->setValue("Splitter", ui->splitter->saveState());
}
ui->groupTreeWidget->processSettings(Settings, load);
ui->groupTreeWidget->processSettings(load);
Settings->endGroup();
}
@ -236,11 +236,10 @@ void GxsGroupFrameDialog::updateDisplay(bool complete)
requestGroupSummary();
} else {
/* Update all groups of changed messages */
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > msgIds;
getAllMsgIds(msgIds);
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator msgIt;
for (msgIt = msgIds.begin(); msgIt != msgIds.end(); ++msgIt) {
for (auto msgIt = msgIds.begin(); msgIt != msgIds.end(); ++msgIt) {
updateMessageSummaryList(msgIt->first);
}
}
@ -253,94 +252,100 @@ void GxsGroupFrameDialog::todo()
void GxsGroupFrameDialog::groupTreeCustomPopupMenu(QPoint point)
{
QString id = ui->groupTreeWidget->itemIdAt(point);
if (id.isEmpty()) return;
mGroupId = RsGxsGroupId(id.toStdString());
int subscribeFlags = ui->groupTreeWidget->subscribeFlags(QString::fromStdString(mGroupId.toStdString()));
bool isAdmin = IS_GROUP_ADMIN(subscribeFlags);
bool isPublisher = IS_GROUP_PUBLISHER(subscribeFlags);
bool isSubscribed = IS_GROUP_SUBSCRIBED(subscribeFlags);
QMenu contextMnu(this);
QAction *action;
if (mMessageWidget) {
action = contextMnu.addAction(QIcon(IMAGE_TABNEW), tr("Open in new tab"), this, SLOT(openInNewTab()));
if (mGroupId.isNull() || messageWidget(mGroupId, true)) {
action->setEnabled(false);
QString id = ui->groupTreeWidget->itemIdAt(point);
if (!id.isEmpty())
{
mGroupId = RsGxsGroupId(id.toStdString());
int subscribeFlags = ui->groupTreeWidget->subscribeFlags(QString::fromStdString(mGroupId.toStdString()));
bool isAdmin = IS_GROUP_ADMIN(subscribeFlags);
bool isPublisher = IS_GROUP_PUBLISHER(subscribeFlags);
bool isSubscribed = IS_GROUP_SUBSCRIBED(subscribeFlags);
QAction *action;
if (mMessageWidget) {
action = contextMnu.addAction(QIcon(IMAGE_TABNEW), tr("Open in new tab"), this, SLOT(openInNewTab()));
if (mGroupId.isNull() || messageWidget(mGroupId, true)) {
action->setEnabled(false);
}
}
if (isSubscribed) {
action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe"), this, SLOT(unsubscribeGroup()));
action->setEnabled (!mGroupId.isNull() && IS_GROUP_SUBSCRIBED(subscribeFlags));
} else {
action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe"), this, SLOT(subscribeGroup()));
action->setDisabled (mGroupId.isNull() || IS_GROUP_SUBSCRIBED(subscribeFlags));
}
contextMnu.addSeparator();
contextMnu.addAction(QIcon(icon(ICON_NEW)), text(TEXT_NEW), this, SLOT(newGroup()));
action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Details"), this, SLOT(showGroupDetails()));
action->setEnabled (!mGroupId.isNull());
action = contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Details"), this, SLOT(editGroupDetails()));
action->setEnabled (!mGroupId.isNull() && isAdmin);
uint32_t current_store_time = mInterface->getStoragePeriod(mGroupId)/86400 ;
uint32_t current_sync_time = mInterface->getSyncPeriod(mGroupId)/86400 ;
std::cerr << "Got sync=" << current_sync_time << ". store=" << current_store_time << std::endl;
QAction *actnn = NULL;
QMenu *ctxMenu2 = contextMnu.addMenu(tr("Synchronise posts of last...")) ;
actnn = ctxMenu2->addAction(tr(" 5 days" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 5)) ; if(current_sync_time == 5) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 2 weeks" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 15)) ; if(current_sync_time == 15) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 month" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 30)) ; if(current_sync_time == 30) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 3 months" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 90)) ; if(current_sync_time == 90) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 6 months" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant(180)) ; if(current_sync_time ==180) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 year " ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant(372)) ; if(current_sync_time ==372) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" Indefinitly"),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 0)) ; if(current_sync_time == 0) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
ctxMenu2 = contextMnu.addMenu(tr("Store posts for at most...")) ;
actnn = ctxMenu2->addAction(tr(" 5 days" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 5)) ; if(current_store_time == 5) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 2 weeks" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 15)) ; if(current_store_time == 15) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 month" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 30)) ; if(current_store_time == 30) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 3 months" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 90)) ; if(current_store_time == 90) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 6 months" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant(180)) ; if(current_store_time ==180) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 year " ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant(372)) ; if(current_store_time ==372) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" Indefinitly"),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 0)) ; if(current_store_time == 0) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
if (shareKeyType()) {
action = contextMnu.addAction(QIcon(IMAGE_SHARE), tr("Share publish permissions"), this, SLOT(sharePublishKey()));
action->setEnabled(!mGroupId.isNull() && isPublisher);
}
if (getLinkType() != RetroShareLink::TYPE_UNKNOWN) {
action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyGroupLink()));
action->setEnabled(!mGroupId.isNull());
}
contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsRead()));
action->setEnabled (!mGroupId.isNull() && isSubscribed);
action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnread()));
action->setEnabled (!mGroupId.isNull() && isSubscribed);
/* Add special actions */
QList<QAction*> actions;
groupTreeCustomActions(mGroupId, subscribeFlags, actions);
if (!actions.isEmpty()) {
contextMnu.addSeparator();
contextMnu.addActions(actions);
}
}
if (isSubscribed) {
action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe"), this, SLOT(unsubscribeGroup()));
action->setEnabled (!mGroupId.isNull() && IS_GROUP_SUBSCRIBED(subscribeFlags));
} else {
action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe"), this, SLOT(subscribeGroup()));
action->setDisabled (mGroupId.isNull() || IS_GROUP_SUBSCRIBED(subscribeFlags));
}
contextMnu.addSeparator();
contextMnu.addAction(QIcon(icon(ICON_NEW)), text(TEXT_NEW), this, SLOT(newGroup()));
action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Details"), this, SLOT(showGroupDetails()));
action->setEnabled (!mGroupId.isNull());
action = contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Details"), this, SLOT(editGroupDetails()));
action->setEnabled (!mGroupId.isNull() && isAdmin);
uint32_t current_store_time = mInterface->getStoragePeriod(mGroupId)/86400 ;
uint32_t current_sync_time = mInterface->getSyncPeriod(mGroupId)/86400 ;
std::cerr << "Got sync=" << current_sync_time << ". store=" << current_store_time << std::endl;
QAction *actnn = NULL;
QMenu *ctxMenu2 = contextMnu.addMenu(tr("Synchronise posts of last...")) ;
actnn = ctxMenu2->addAction(tr(" 5 days" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 5)) ; if(current_sync_time == 5) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 2 weeks" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 15)) ; if(current_sync_time == 15) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 month" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 30)) ; if(current_sync_time == 30) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 3 months" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 90)) ; if(current_sync_time == 90) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 6 months" ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant(180)) ; if(current_sync_time ==180) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 year " ),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant(372)) ; if(current_sync_time ==372) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" Indefinitly"),this,SLOT(setSyncPostsDelay())) ; actnn->setData(QVariant( 0)) ; if(current_sync_time == 0) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
ctxMenu2 = contextMnu.addMenu(tr("Store posts for at most...")) ;
actnn = ctxMenu2->addAction(tr(" 5 days" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 5)) ; if(current_store_time == 5) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 2 weeks" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 15)) ; if(current_store_time == 15) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 month" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 30)) ; if(current_store_time == 30) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 3 months" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 90)) ; if(current_store_time == 90) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 6 months" ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant(180)) ; if(current_store_time ==180) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" 1 year " ),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant(372)) ; if(current_store_time ==372) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
actnn = ctxMenu2->addAction(tr(" Indefinitly"),this,SLOT(setStorePostsDelay())) ; actnn->setData(QVariant( 0)) ; if(current_store_time == 0) { actnn->setEnabled(false);actnn->setIcon(QIcon(":/images/start.png"));}
if (shareKeyType()) {
action = contextMnu.addAction(QIcon(IMAGE_SHARE), tr("Share publish permissions"), this, SLOT(sharePublishKey()));
action->setEnabled(!mGroupId.isNull() && isPublisher);
}
if (getLinkType() != RetroShareLink::TYPE_UNKNOWN) {
action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyGroupLink()));
action->setEnabled(!mGroupId.isNull());
}
contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsRead()));
action->setEnabled (!mGroupId.isNull() && isSubscribed);
action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnread()));
action->setEnabled (!mGroupId.isNull() && isSubscribed);
/* Add special actions */
QList<QAction*> actions;
groupTreeCustomActions(mGroupId, subscribeFlags, actions);
if (!actions.isEmpty()) {
contextMnu.addSeparator();
contextMnu.addActions(actions);
}
//Add Standard Menu
ui->groupTreeWidget->treeWidget()->createStandardContextMenu(&contextMnu);
contextMnu.exec(QCursor::pos());
}

View file

@ -109,21 +109,22 @@ void GxsMessageFramePostWidget::updateDisplay(bool complete)
}
bool updateGroup = false;
const std::list<RsGxsGroupId> &grpIdsMeta = getGrpIdsMeta();
if (std::find(grpIdsMeta.begin(), grpIdsMeta.end(), groupId()) != grpIdsMeta.end()) {
updateGroup = true;
}
const std::set<RsGxsGroupId> &grpIdsMeta = getGrpIdsMeta();
const std::list<RsGxsGroupId> &grpIds = getGrpIds();
if (!groupId().isNull() && std::find(grpIds.begin(), grpIds.end(), groupId()) != grpIds.end()) {
if(grpIdsMeta.find(groupId())!=grpIdsMeta.end())
updateGroup = true;
const std::set<RsGxsGroupId> &grpIds = getGrpIds();
if (!groupId().isNull() && grpIds.find(groupId())!=grpIds.end())
{
updateGroup = true;
/* Do we need to fill all posts? */
requestAllPosts();
} else {
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgs;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > msgs;
getAllMsgIds(msgs);
if (!msgs.empty()) {
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator mit = msgs.find(groupId());
auto mit = msgs.find(groupId());
if (mit != msgs.end()) {
requestPosts(mit->second);
}
@ -341,7 +342,7 @@ void GxsMessageFramePostWidget::loadAllPosts(const uint32_t &token)
emit groupChanged(this);
}
void GxsMessageFramePostWidget::requestPosts(const std::vector<RsGxsMessageId> &msgIds)
void GxsMessageFramePostWidget::requestPosts(const std::set<RsGxsMessageId> &msgIds)
{
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostWidget::requestPosts()";

View file

@ -72,7 +72,7 @@ protected:
void loadAllPosts(const uint32_t &token);
virtual void insertAllPosts(const uint32_t &token, GxsMessageFramePostThread *thread) = 0;
void requestPosts(const std::vector<RsGxsMessageId> &msgIds);
void requestPosts(const std::set<RsGxsMessageId> &msgIds);
void loadPosts(const uint32_t &token);
virtual void insertPosts(const uint32_t &token) = 0;

View file

@ -15,7 +15,7 @@ RsGxsUpdateBroadcastBase::RsGxsUpdateBroadcastBase(RsGxsIfaceHelper *ifaceImpl,
mUpdateBroadcast = RsGxsUpdateBroadcast::get(ifaceImpl);
connect(mUpdateBroadcast, SIGNAL(changed()), this, SLOT(updateBroadcastChanged()));
connect(mUpdateBroadcast, SIGNAL(grpsChanged(std::list<RsGxsGroupId>, std::list<RsGxsGroupId>)), this, SLOT(updateBroadcastGrpsChanged(std::list<RsGxsGroupId>,std::list<RsGxsGroupId>)));
connect(mUpdateBroadcast, SIGNAL(msgsChanged(std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >, std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >)), this, SLOT(updateBroadcastMsgsChanged(std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >,std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >)));
connect(mUpdateBroadcast, SIGNAL(msgsChanged(std::map<RsGxsGroupId,std::set<RsGxsMessageId> >, std::map<RsGxsGroupId,std::set<RsGxsMessageId> >)), this, SLOT(updateBroadcastMsgsChanged(std::map<RsGxsGroupId,std::set<RsGxsMessageId> >,std::map<RsGxsGroupId,std::set<RsGxsMessageId> >)));
}
RsGxsUpdateBroadcastBase::~RsGxsUpdateBroadcastBase()
@ -67,6 +67,17 @@ void RsGxsUpdateBroadcastBase::updateBroadcastChanged()
/* Update only update when the widget is visible. */
if (mUpdateWhenInvisible || !widget || widget->isVisible()) {
// (cyril) Re-load the entire group is new messages are here, or if group metadata has changed (e.g. visibility permissions, admin rights, etc).
// Do not re-load if Msg data has changed, which means basically the READ flag has changed, because this action is done in the UI in the
// first place so there's no need to re-update the UI once this is done.
//
// The question to whether we should re=load when mGrpIds is not empty is still open. It's not harmful anyway.
// This should probably be decided by the service itself.
if (!mGrpIds.empty() || !mGrpIdsMeta.empty() /*|| !mMsgIds.empty()*/ || !mMsgIdsMeta.empty())
mFillComplete = true ;
securedUpdateDisplay();
}
}
@ -74,79 +85,36 @@ void RsGxsUpdateBroadcastBase::updateBroadcastChanged()
void RsGxsUpdateBroadcastBase::updateBroadcastGrpsChanged(const std::list<RsGxsGroupId> &grpIds, const std::list<RsGxsGroupId> &grpIdsMeta)
{
std::list<RsGxsGroupId>::const_iterator it;
for (it = grpIds.begin(); it != grpIds.end(); ++it) {
if (std::find(mGrpIds.begin(), mGrpIds.end(), *it) == mGrpIds.end()) {
mGrpIds.push_back(*it);
}
}
for (it = grpIdsMeta.begin(); it != grpIdsMeta.end(); ++it) {
if (std::find(mGrpIdsMeta.begin(), mGrpIdsMeta.end(), *it) == mGrpIdsMeta.end()) {
mGrpIdsMeta.push_back(*it);
}
}
for (it = grpIds.begin(); it != grpIds.end(); ++it)
mGrpIds.insert(*it) ;
for (it = grpIdsMeta.begin(); it != grpIdsMeta.end(); ++it)
mGrpIdsMeta.insert(*it);
}
void RsGxsUpdateBroadcastBase::updateBroadcastMsgsChanged(const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds, const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIdsMeta)
template<class U> void merge(std::set<U>& dst,const std::set<U>& src) { for(auto it(src.begin());it!=src.end();++it) dst.insert(*it) ; }
void RsGxsUpdateBroadcastBase::updateBroadcastMsgsChanged(const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds, const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIdsMeta)
{
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator mapIt;
for (mapIt = msgIds.begin(); mapIt != msgIds.end(); ++mapIt) {
const RsGxsGroupId &grpId = mapIt->first;
const std::vector<RsGxsMessageId> &srcMsgIds = mapIt->second;
std::vector<RsGxsMessageId> &destMsgIds = mMsgIds[grpId];
for (auto mapIt = msgIds.begin(); mapIt != msgIds.end(); ++mapIt)
merge(mMsgIds[mapIt->first],mapIt->second) ;
std::vector<RsGxsMessageId>::const_iterator msgIt;
for (msgIt = srcMsgIds.begin(); msgIt != srcMsgIds.end(); ++msgIt) {
if (std::find(destMsgIds.begin(), destMsgIds.end(), *msgIt) == destMsgIds.end()) {
destMsgIds.push_back(*msgIt);
}
}
}
for (mapIt = msgIdsMeta.begin(); mapIt != msgIdsMeta.end(); ++mapIt) {
const RsGxsGroupId &grpId = mapIt->first;
const std::vector<RsGxsMessageId> &srcMsgIds = mapIt->second;
std::vector<RsGxsMessageId> &destMsgIds = mMsgIdsMeta[grpId];
std::vector<RsGxsMessageId>::const_iterator msgIt;
for (msgIt = srcMsgIds.begin(); msgIt != srcMsgIds.end(); ++msgIt) {
if (std::find(destMsgIds.begin(), destMsgIds.end(), *msgIt) == destMsgIds.end()) {
destMsgIds.push_back(*msgIt);
}
}
}
for (auto mapIt = msgIdsMeta.begin(); mapIt != msgIdsMeta.end(); ++mapIt)
merge(mMsgIdsMeta[mapIt->first],mapIt->second) ;
}
void RsGxsUpdateBroadcastBase::getAllGrpIds(std::list<RsGxsGroupId> &grpIds)
void RsGxsUpdateBroadcastBase::getAllGrpIds(std::set<RsGxsGroupId> &grpIds)
{
std::list<RsGxsGroupId>::const_iterator it;
for (it = mGrpIds.begin(); it != mGrpIds.end(); ++it) {
if (std::find(grpIds.begin(), grpIds.end(), *it) == grpIds.end()) {
grpIds.push_back(*it);
}
}
for (it = mGrpIdsMeta.begin(); it != mGrpIdsMeta.end(); ++it) {
if (std::find(grpIds.begin(), grpIds.end(), *it) == grpIds.end()) {
grpIds.push_back(*it);
}
}
grpIds = mGrpIds;
merge(grpIds,mGrpIdsMeta) ;
}
void RsGxsUpdateBroadcastBase::getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds)
void RsGxsUpdateBroadcastBase::getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds)
{
/* Copy first map */
msgIds = mMsgIds;
/* Append second map */
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator mapIt;
for (mapIt = mMsgIdsMeta.begin(); mapIt != mMsgIdsMeta.end(); ++mapIt) {
const RsGxsGroupId &grpId = mapIt->first;
const std::vector<RsGxsMessageId> &srcMsgIds = mapIt->second;
std::vector<RsGxsMessageId> &destMsgIds = msgIds[grpId];
std::vector<RsGxsMessageId>::const_iterator msgIt;
for (msgIt = srcMsgIds.begin(); msgIt != srcMsgIds.end(); ++msgIt) {
if (std::find(destMsgIds.begin(), destMsgIds.end(), *msgIt) == destMsgIds.end()) {
destMsgIds.push_back(*msgIt);
}
}
}
for (auto mapIt = mMsgIdsMeta.begin(); mapIt != mMsgIdsMeta.end(); ++mapIt)
merge(msgIds[mapIt->first],mapIt->second);
}

View file

@ -19,12 +19,12 @@ public:
RsGxsUpdateBroadcastBase(RsGxsIfaceHelper* ifaceImpl, QWidget *parent = NULL);
virtual ~RsGxsUpdateBroadcastBase();
const std::list<RsGxsGroupId> &getGrpIds() { return mGrpIds; }
const std::list<RsGxsGroupId> &getGrpIdsMeta() { return mGrpIdsMeta; }
void getAllGrpIds(std::list<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIds() { return mMsgIds; }
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIdsMeta() { return mMsgIdsMeta; }
void getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds);
const std::set<RsGxsGroupId> &getGrpIds() { return mGrpIds; }
const std::set<RsGxsGroupId> &getGrpIdsMeta() { return mGrpIdsMeta; }
void getAllGrpIds(std::set<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIds() { return mMsgIds; }
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIdsMeta() { return mMsgIdsMeta; }
void getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds);
protected:
void fillComplete();
@ -38,15 +38,15 @@ signals:
private slots:
void updateBroadcastChanged();
void updateBroadcastGrpsChanged(const std::list<RsGxsGroupId>& grpIds, const std::list<RsGxsGroupId> &grpIdsMeta);
void updateBroadcastMsgsChanged(const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIdsMeta);
void updateBroadcastMsgsChanged(const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIdsMeta);
void securedUpdateDisplay();
private:
RsGxsUpdateBroadcast *mUpdateBroadcast;
bool mFillComplete;
bool mUpdateWhenInvisible; // Update also when not visible
std::list<RsGxsGroupId> mGrpIds;
std::list<RsGxsGroupId> mGrpIdsMeta;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > mMsgIds;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > mMsgIdsMeta;
std::set<RsGxsGroupId> mGrpIds;
std::set<RsGxsGroupId> mGrpIdsMeta;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > mMsgIds;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > mMsgIdsMeta;
};

View file

@ -22,32 +22,32 @@ void RsGxsUpdateBroadcastPage::setUpdateWhenInvisible(bool update)
mBase->setUpdateWhenInvisible(update);
}
const std::list<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIdsMeta()
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIdsMeta()
{
return mBase->getGrpIdsMeta();
}
void RsGxsUpdateBroadcastPage::getAllGrpIds(std::list<RsGxsGroupId> &grpIds)
void RsGxsUpdateBroadcastPage::getAllGrpIds(std::set<RsGxsGroupId> &grpIds)
{
mBase->getAllGrpIds(grpIds);
}
const std::list<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIds()
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastPage::getGrpIds()
{
return mBase->getGrpIds();
}
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &RsGxsUpdateBroadcastPage::getMsgIdsMeta()
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &RsGxsUpdateBroadcastPage::getMsgIdsMeta()
{
return mBase->getMsgIdsMeta();
}
void RsGxsUpdateBroadcastPage::getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds)
void RsGxsUpdateBroadcastPage::getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds)
{
mBase->getAllMsgIds(msgIds);
}
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &RsGxsUpdateBroadcastPage::getMsgIds()
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &RsGxsUpdateBroadcastPage::getMsgIds()
{
return mBase->getMsgIds();
}

View file

@ -24,12 +24,12 @@ public:
void fillComplete();
void setUpdateWhenInvisible(bool update);
const std::list<RsGxsGroupId> &getGrpIds();
const std::list<RsGxsGroupId> &getGrpIdsMeta();
void getAllGrpIds(std::list<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIds();
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIdsMeta();
void getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds);
const std::set<RsGxsGroupId> &getGrpIds();
const std::set<RsGxsGroupId> &getGrpIdsMeta();
void getAllGrpIds(std::set<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIds();
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIdsMeta();
void getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds);
protected:
virtual void showEvent(QShowEvent *event);
@ -37,7 +37,7 @@ protected:
// This is overloaded in subclasses.
virtual void updateDisplay(bool complete) = 0;
private slots:
public slots:
void fillDisplay(bool complete);
private:

View file

@ -2,12 +2,12 @@
#include "RsGxsUpdateBroadcastBase.h"
RsGxsUpdateBroadcastWidget::RsGxsUpdateBroadcastWidget(RsGxsIfaceHelper *ifaceImpl, QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
: QWidget(parent, flags)
{
mBase = new RsGxsUpdateBroadcastBase(ifaceImpl, this);
connect(mBase, SIGNAL(fillDisplay(bool)), this, SLOT(fillDisplay(bool)));
mBase = new RsGxsUpdateBroadcastBase(ifaceImpl, this);
connect(mBase, SIGNAL(fillDisplay(bool)), this, SLOT(fillDisplay(bool)));
mInterfaceHelper = ifaceImpl;
mInterfaceHelper = ifaceImpl;
}
RsGxsUpdateBroadcastWidget::~RsGxsUpdateBroadcastWidget()
@ -16,52 +16,52 @@ RsGxsUpdateBroadcastWidget::~RsGxsUpdateBroadcastWidget()
void RsGxsUpdateBroadcastWidget::fillComplete()
{
mBase->fillComplete();
mBase->fillComplete();
}
void RsGxsUpdateBroadcastWidget::setUpdateWhenInvisible(bool update)
{
mBase->setUpdateWhenInvisible(update);
mBase->setUpdateWhenInvisible(update);
}
const std::list<RsGxsGroupId> &RsGxsUpdateBroadcastWidget::getGrpIds()
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastWidget::getGrpIds()
{
return mBase->getGrpIds();
return mBase->getGrpIds();
}
const std::list<RsGxsGroupId> &RsGxsUpdateBroadcastWidget::getGrpIdsMeta()
const std::set<RsGxsGroupId> &RsGxsUpdateBroadcastWidget::getGrpIdsMeta()
{
return mBase->getGrpIdsMeta();
return mBase->getGrpIdsMeta();
}
void RsGxsUpdateBroadcastWidget::getAllGrpIds(std::list<RsGxsGroupId> &grpIds)
void RsGxsUpdateBroadcastWidget::getAllGrpIds(std::set<RsGxsGroupId> &grpIds)
{
mBase->getAllGrpIds(grpIds);
mBase->getAllGrpIds(grpIds);
}
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &RsGxsUpdateBroadcastWidget::getMsgIds()
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &RsGxsUpdateBroadcastWidget::getMsgIds()
{
return mBase->getMsgIds();
return mBase->getMsgIds();
}
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &RsGxsUpdateBroadcastWidget::getMsgIdsMeta()
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &RsGxsUpdateBroadcastWidget::getMsgIdsMeta()
{
return mBase->getMsgIdsMeta();
return mBase->getMsgIdsMeta();
}
void RsGxsUpdateBroadcastWidget::getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds)
void RsGxsUpdateBroadcastWidget::getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds)
{
mBase->getAllMsgIds(msgIds);
mBase->getAllMsgIds(msgIds);
}
void RsGxsUpdateBroadcastWidget::fillDisplay(bool complete)
{
updateDisplay(complete);
update(); // Qt flush
updateDisplay(complete);
update(); // Qt flush
}
void RsGxsUpdateBroadcastWidget::showEvent(QShowEvent *event)
{
mBase->showEvent(event);
QWidget::showEvent(event);
mBase->showEvent(event);
QWidget::showEvent(event);
}

View file

@ -24,12 +24,12 @@ public:
void fillComplete();
void setUpdateWhenInvisible(bool update);
const std::list<RsGxsGroupId> &getGrpIds();
const std::list<RsGxsGroupId> &getGrpIdsMeta();
void getAllGrpIds(std::list<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIds();
const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &getMsgIdsMeta();
void getAllMsgIds(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds);
const std::set<RsGxsGroupId> &getGrpIds();
const std::set<RsGxsGroupId> &getGrpIdsMeta();
void getAllGrpIds(std::set<RsGxsGroupId> &grpIds);
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIds();
const std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &getMsgIdsMeta();
void getAllMsgIds(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds);
RsGxsIfaceHelper *interfaceHelper() { return mInterfaceHelper; }

View file

@ -604,7 +604,7 @@ void CreateGxsChannelMsg::newChannelMsg()
GxsMsgReq message_ids;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
message_ids[mChannelId].push_back(mOrigPostId);
message_ids[mChannelId].insert(mOrigPostId);
mChannelQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, message_ids, CREATEMSG_CHANNEL_POST_INFO);
}
}

View file

@ -185,8 +185,8 @@ void CreateGxsForumMsg::newMsg()
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[mForumId];
vect.push_back(mParentId);
std::set<RsGxsMessageId> &vect = msgIds[mForumId];
vect.insert(mParentId);
//std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")";
//std::cerr << std::endl;
@ -205,8 +205,8 @@ void CreateGxsForumMsg::newMsg()
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[mForumId];
vect.push_back(mOrigMsgId);
std::set<RsGxsMessageId> &vect = msgIds[mForumId];
vect.insert(mOrigMsgId);
//std::cerr << "ForumsV2Dialog::newMsg() Requesting Parent Summary(" << mParentId << ")";
//std::cerr << std::endl;

View file

@ -404,25 +404,25 @@ void GxsForumThreadWidget::changeEvent(QEvent *e)
}
}
static void removeMessages(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > &msgIds, QList<RsGxsMessageId> &removeMsgId)
static void removeMessages(std::map<RsGxsGroupId, std::set<RsGxsMessageId> > &msgIds, QList<RsGxsMessageId> &removeMsgId)
{
QList<RsGxsMessageId> removedMsgId;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator grpIt;
for (grpIt = msgIds.begin(); grpIt != msgIds.end(); ) {
std::vector<RsGxsMessageId> &msgs = grpIt->second;
for (auto grpIt = msgIds.begin(); grpIt != msgIds.end(); )
{
std::set<RsGxsMessageId> &msgs = grpIt->second;
QList<RsGxsMessageId>::const_iterator removeMsgIt;
for (removeMsgIt = removeMsgId.begin(); removeMsgIt != removeMsgId.end(); ++removeMsgIt) {
std::vector<RsGxsMessageId>::iterator msgIt = std::find(msgs.begin(), msgs.end(), *removeMsgIt);
if (msgIt != msgs.end()) {
if(msgs.find(*removeMsgIt) != msgs.end())
{
removedMsgId.push_back(*removeMsgIt);
msgs.erase(msgIt);
msgs.erase(*removeMsgIt);
}
}
if (msgs.empty()) {
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator grpItErase = grpIt++;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> >::iterator grpItErase = grpIt++;
msgIds.erase(grpItErase);
} else {
++grpIt;
@ -452,18 +452,18 @@ void GxsForumThreadWidget::updateDisplay(bool complete)
}
bool updateGroup = false;
const std::list<RsGxsGroupId> &grpIdsMeta = getGrpIdsMeta();
if (std::find(grpIdsMeta.begin(), grpIdsMeta.end(), groupId()) != grpIdsMeta.end()) {
updateGroup = true;
}
const std::set<RsGxsGroupId> &grpIdsMeta = getGrpIdsMeta();
const std::list<RsGxsGroupId> &grpIds = getGrpIds();
if (std::find(grpIds.begin(), grpIds.end(), groupId()) != grpIds.end()) {
if(grpIdsMeta.find(groupId())!=grpIdsMeta.end())
updateGroup = true;
const std::set<RsGxsGroupId> &grpIds = getGrpIds();
if (grpIds.find(groupId())!=grpIds.end()){
updateGroup = true;
/* Update threads */
insertThreads();
} else {
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
std::map<RsGxsGroupId, std::set<RsGxsMessageId> > msgIds;
getAllMsgIds(msgIds);
if (!mIgnoredMsgId.empty()) {
@ -2111,8 +2111,8 @@ void GxsForumThreadWidget::flagperson()
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[postId.first];
vect.push_back(postId.second);
std::set<RsGxsMessageId> &vect = msgIds[postId.first];
vect.insert(postId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, token_type);
@ -2413,8 +2413,8 @@ void GxsForumThreadWidget::requestMessageData(const RsGxsGrpMsgIdPair &msgId)
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
std::set<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.insert(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeMessageData);
@ -2464,8 +2464,8 @@ void GxsForumThreadWidget::requestMsgData_ReplyWithPrivateMessage(const RsGxsGrp
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
std::set<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.insert(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeReplyMessage);
@ -2482,8 +2482,8 @@ void GxsForumThreadWidget::requestMsgData_ShowAuthorInPeople(const RsGxsGrpMsgId
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
std::set<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.insert(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeShowAuthorInPeople);
@ -2499,8 +2499,8 @@ void GxsForumThreadWidget::requestMsgData_EditForumMessage(const RsGxsGrpMsgIdPa
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
std::set<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.insert(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeEditForumMessage);
@ -2516,8 +2516,8 @@ void GxsForumThreadWidget::requestMsgData_ReplyForumMessage(const RsGxsGrpMsgIdP
#endif
GxsMsgReq msgIds;
std::vector<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.push_back(msgId.second);
std::set<RsGxsMessageId> &vect = msgIds[msgId.first];
vect.insert(msgId.second);
uint32_t token;
mTokenQueue->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, mTokenTypeReplyForumMessage);

View file

@ -244,9 +244,15 @@ OpModeStatus[opMode="Minimal"] {
background: #FFCCCC;
}
/*Property Values at end to overwrite other settings*/
[new=false] {
background: #F8F8F8;
}
[new=true] {
background: #DCECFD;
}
[WrongValue="true"] {
background-color: #FF8080;
}

View file

@ -39,7 +39,7 @@ public:
/** Loads the settings for this page */
virtual void load();
virtual QPixmap iconPixmap() const { return QPixmap(":/icons/settings/sound.svg") ; }
virtual QPixmap iconPixmap() const { return QPixmap(":/icons/svg/info.svg") ; }
virtual QString pageName() const { return tr("About") ; }
virtual QString helpText() const { return ""; }

View file

@ -197,6 +197,8 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags)
std::cerr << std::endl;
#endif
connect(ui.discComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses()));
connect(ui.netModeComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(saveAddresses()));
connect(ui.localAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses()));
connect(ui.extAddress, SIGNAL(textChanged(QString)),this,SLOT(saveAddresses()));
@ -844,10 +846,15 @@ void ServerPage::updateStatus()
return;
}
/* load up configuration from rsPeers */
RsPeerDetails detail;
if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail))
return;
/* load up configuration from rsPeers */
RsPeerDetails detail;
if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail))
{
std::cerr << __PRETTY_FUNCTION__ << " getPeerDetails(...) failed!"
<< " This is unexpected report to developers please."
<< std::endl;
return;
}
/* only update if can't edit */
if (!ui.localPort->isEnabled())
@ -1005,7 +1012,7 @@ void ServerPage::saveRates()
void ServerPage::tabChanged(int page)
{
if(page == 2)
if(page == TAB_HIDDEN_SERVICE)
updateOutProxyIndicator();
}

View file

@ -26,7 +26,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="tabNetConf">
<attribute name="title">

View file

@ -22,15 +22,17 @@
#include "TransferPage.h"
#include "rshare.h"
#include "gui/ShareManager.h"
#include "util/misc.h"
#include "retroshare/rsiface.h"
#include "retroshare/rsfiles.h"
#include "retroshare/rspeers.h"
#include <QToolTip>
#include <iostream>
#include <util/misc.h>
#include <gui/ShareManager.h>
#include <retroshare/rsiface.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rspeers.h>
TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags)
: ConfigPage(parent, flags)
{
@ -225,11 +227,23 @@ void TransferPage::setIncomingDirectory()
return;
}
ui.incomingDir->setText(qdir);
std::string dir = ui.incomingDir->text().toUtf8().constData();
if(!dir.empty())
rsFiles->setDownloadDirectory(dir);
std::string dir = qdir.toUtf8().constData();
if(!dir.empty())
{
if (!rsFiles->setDownloadDirectory(dir))
{
ui.incomingDir->setToolTip( tr("Invalid Input. Have you got the right to write on it?") );
ui.incomingDir->setProperty("WrongValue", true);
}
else
{
ui.incomingDir->setToolTip( "" );
ui.incomingDir->setProperty("WrongValue", false);
}
}
ui.incomingDir->style()->unpolish(ui.incomingDir);
ui.incomingDir->style()->polish( ui.incomingDir);
whileBlocking(ui.incomingDir)->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()));
}
void TransferPage::setPartialsDirectory()
@ -239,11 +253,25 @@ void TransferPage::setPartialsDirectory()
return;
}
ui.partialsDir->setText(qdir);
std::string dir = ui.partialsDir->text().toUtf8().constData();
std::string dir = qdir.toUtf8().constData();
if (!dir.empty())
rsFiles->setPartialsDirectory(dir);
{
if (!rsFiles->setPartialsDirectory(dir))
{
ui.partialsDir->setToolTip( tr("Invalid Input. It can't be an already shared directory.") );
ui.partialsDir->setProperty("WrongValue", true);
}
else
{
ui.partialsDir->setToolTip( "" );
ui.partialsDir->setProperty("WrongValue", false);
}
}
ui.partialsDir->style()->unpolish(ui.partialsDir);
ui.partialsDir->style()->polish( ui.partialsDir);
whileBlocking(ui.partialsDir)->setText(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()));
}
void TransferPage::toggleAutoCheckDirectories(bool b)
{
ui.autoCheckDirectoriesDelay_SB->setEnabled(b);

View file

@ -41,12 +41,15 @@
#include "PostedPage.h"
#include "PluginsPage.h"
#include "ServicePermissionsPage.h"
#include "WebuiPage.h"
#include "rsharesettings.h"
#include "gui/notifyqt.h"
#include "gui/common/FloatingHelpBrowser.h"
#include "gui/common/RSElidedItemDelegate.h"
#ifdef ENABLE_WEBUI
# include "WebuiPage.h"
#endif
#define IMAGE_GENERAL ":/images/kcmsystem24.png"
#define ITEM_SPACING 2

View file

@ -34,8 +34,8 @@
#include <retroshare/rsnotify.h>
#include <retroshare/rspeers.h>
#if defined(Q_OS_WIN)
#include <util/win32.h>
#ifdef Q_OS_WIN
# include <util/retroshareWin32.h>
#endif
/* Retroshare's Settings */

View file

@ -41,16 +41,19 @@
#include "gui/FileTransfer/TransfersDialog.h"
#include "gui/settings/RsharePeerSettings.h"
#include "gui/settings/rsharesettings.h"
#include "gui/settings/WebuiPage.h"
#include "idle/idle.h"
#include "lang/languagesupport.h"
#include "util/RsGxsUpdateBroadcast.h"
#include "util/rsdir.h"
#include "util/rstime.h"
#ifdef ENABLE_WEBUI
# include "gui/settings/WebuiPage.h"
#endif
#ifdef RETROTOR
#include "TorControl/TorManager.h"
#include "TorControl/TorControlWindow.h"
# include "TorControl/TorManager.h"
# include "TorControl/TorControlWindow.h"
#endif
#include "retroshare/rsidentity.h"

View file

@ -293,9 +293,16 @@ OpModeStatus[opMode="Minimal"] {
background: #700000;
}
/*Property Values at end to overwrite other settings*/
[new=false] {
background: #202020;
}
[new=true] {
background: #005000;
}
[WrongValue=true] {
background-color: #702020;
}

View file

@ -1126,9 +1126,15 @@ OpModeStatus[opMode="Minimal"] {
background: #700000;
}
/*Property Values at end to overwrite other settings*/
[new=false] {
background: #202020;
}
[new=true] {
background: #005000;
}
[WrongValue="true"] {
background-color: #702020;
}

View file

@ -2,28 +2,24 @@
TEMPLATE = app
QT += network xml
CONFIG += qt gui uic qrc resources idle bitdht
CONFIG += link_prl
CONFIG += qt gui uic qrc resources idle
CONFIG += console
TARGET = retroshare
DEFINES += TARGET=\\\"$${TARGET}\\\"
# Plz never commit the .pro with these flags enabled.
# Use this flag when developping new features only.
#
#CONFIG += unfinished
#CONFIG += debug
#DEFINES *= SIGFPE_DEBUG
DEPENDPATH *= $${PWD} $${RS_INCLUDE_DIR} retroshare-gui
INCLUDEPATH *= $${PWD} retroshare-gui
profiling {
QMAKE_CXXFLAGS -= -fomit-frame-pointer
QMAKE_CXXFLAGS *= -pg -g -fno-omit-frame-pointer
QMAKE_LFLAGS *= -pg
libresapihttpserver {
!include("../../libresapi/src/use_libresapi.pri"):error("Including")
HEADERS *= gui/settings/WebuiPage.h
SOURCES *= gui/settings/WebuiPage.cpp
FORMS *= gui/settings/WebuiPage.ui
}
retrotor {
DEFINES *= RETROTOR
!include("../../libretroshare/src/use_libretroshare.pri"):error("Including")
retrotor {
FORMS += TorControl/TorControlWindow.ui
SOURCES += TorControl/TorControlWindow.cpp
HEADERS += TorControl/TorControlWindow.h
@ -59,22 +55,6 @@ RCC_DIR = temp/qrc
UI_DIR = temp/ui
MOC_DIR = temp/moc
#CONFIG += debug
debug {
QMAKE_CFLAGS += -g
QMAKE_CXXFLAGS -= -O2
QMAKE_CXXFLAGS += -O0
QMAKE_CFLAGS -= -O2
QMAKE_CFLAGS += -O0
}
DEPENDPATH *= retroshare-gui
INCLUDEPATH *= retroshare-gui
# treat warnings as error for better removing
#QMAKE_CFLAGS += -Werror
#QMAKE_CXXFLAGS += -Werror
################################# Linux ##########################################
# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib
linux-* {
@ -133,7 +113,7 @@ version_detail_bash_script {
PRE_TARGETDEPS = write_version_detail
write_version_detail.commands = $$PWD/version_detail.sh
}
win32 {
win32-* {
QMAKE_EXTRA_TARGETS += write_version_detail
PRE_TARGETDEPS = write_version_detail
write_version_detail.commands = $$PWD/version_detail.bat
@ -165,10 +145,12 @@ win32-x-g++ {
#################################### Windows #####################################
win32 {
win32-g++ {
CONFIG(debug, debug|release) {
# show console output
CONFIG += console
} else {
CONFIG -= console
}
# Switch on extra warnings
@ -183,8 +165,9 @@ win32 {
QMAKE_LFLAGS += -Wl,-nxcompat
}
# solve linker warnings because of the order of the libraries
QMAKE_LFLAGS += -Wl,--start-group
# Fix linking error (ld.exe: Error: export ordinal too large) due to too
# many exported symbols.
QMAKE_LFLAGS+=-Wl,--exclude-libs,ALL
# Switch off optimization for release version
QMAKE_CXXFLAGS_RELEASE -= -O2
@ -197,15 +180,10 @@ win32 {
#QMAKE_CFLAGS_DEBUG += -O2
OBJECTS_DIR = temp/obj
#LIBS += -L"D/Qt/2009.03/qt/plugins/imageformats"
#QTPLUGIN += qjpeg
for(lib, LIB_DIR):LIBS += -L"$$lib"
for(bin, BIN_DIR):LIBS += -L"$$bin"
dLib = ws2_32 gdi32 uuid ole32 iphlpapi crypt32 winmm
LIBS *= $$linkDynamicLibs(dLib)
LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz -lws2_32
LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32
LIBS += -lwinmm
RC_FILE = gui/images/retroshare_win.rc
# export symbols for the plugins
@ -218,11 +196,6 @@ win32 {
QMAKE_PRE_LINK = $(CHK_DIR_EXISTS) lib || $(MKDIR) lib
}
DEFINES *= WINDOWS_SYS WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T
DEPENDPATH += . $$INC_DIR
INCLUDEPATH += . $$INC_DIR
greaterThan(QT_MAJOR_VERSION, 4) {
# Qt 5
RC_INCLUDEPATH += $$_PRO_FILE_PWD_/../../libretroshare/src
@ -307,32 +280,11 @@ openbsd-* {
LIBS *= -rdynamic
}
############################## Common stuff ######################################
# On Linux systems that alredy have libssl and libcrypto it is advisable
# to rename the patched version of SSL to something like libsslxpgp.a and libcryptoxpg.a
# ###########################################
DEPENDPATH += . $$PWD/../../libretroshare/src/
INCLUDEPATH += $$PWD/../../libretroshare/src/
PRE_TARGETDEPS *= $$OUT_PWD/../../libretroshare/src/lib/libretroshare.a
LIBS *= $$OUT_PWD/../../libretroshare/src/lib/libretroshare.a
wikipoos {
PRE_TARGETDEPS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
LIBS *= $$OUT_PWD/../../supportlibs/pegmarkdown/lib/libpegmarkdown.a
}
# webinterface
DEPENDPATH += $$PWD/../../libresapi/src
INCLUDEPATH += $$PWD/../../libresapi/src
PRE_TARGETDEPS *= $$OUT_PWD/../../libresapi/src/lib/libresapi.a
LIBS += $$OUT_PWD/../../libresapi/src/lib/libresapi.a
retrotor {
HEADERS += TorControl/AddOnionCommand.h \
TorControl/AuthenticateCommand.h \
@ -437,7 +389,6 @@ HEADERS += rshare.h \
util/stringutil.h \
util/RsNetUtil.h \
util/DateTime.h \
util/win32.h \
util/RetroStyleLabel.h \
util/dllexport.h \
util/NonCopyable.h \
@ -617,7 +568,8 @@ HEADERS += rshare.h \
util/imageutil.h \
gui/NetworkDialog/pgpid_item_model.h \
gui/NetworkDialog/pgpid_item_proxy.h \
gui/common/RsCollection.h
gui/common/RsCollection.h \
util/retroshareWin32.h
# gui/ForumsDialog.h \
# gui/forums/ForumDetails.h \
# gui/forums/EditForumDetails.h \
@ -801,7 +753,6 @@ SOURCES += main.cpp \
util/stringutil.cpp \
util/RsNetUtil.cpp \
util/DateTime.cpp \
util/win32.cpp \
util/RetroStyleLabel.cpp \
util/WidgetBackgroundImage.cpp \
util/NonCopyable.cpp \
@ -979,7 +930,8 @@ SOURCES += main.cpp \
util/imageutil.cpp \
gui/NetworkDialog/pgpid_item_model.cpp \
gui/NetworkDialog/pgpid_item_proxy.cpp \
gui/common/RsCollection.cpp
gui/common/RsCollection.cpp \
util/retroshareWin32.cpp
# gui/ForumsDialog.cpp \
# gui/forums/ForumDetails.cpp \
# gui/forums/EditForumDetails.cpp \
@ -1417,9 +1369,3 @@ gxsgui {
}
libresapihttpserver {
HEADERS *= gui/settings/WebuiPage.h
SOURCES *= gui/settings/WebuiPage.cpp
FORMS *= gui/settings/WebuiPage.ui
}

View file

@ -27,7 +27,7 @@
#if defined(Q_OS_WIN)
#include <windows.h>
#include <util/win32.h>
#include "util/retroshareWin32.h"
#endif
#include <QApplication>

View file

@ -50,15 +50,16 @@ void RsGxsUpdateBroadcast::onChangesReceived(const RsGxsChanges& changes)
{
std::cerr << "Received changes for service " << (void*)changes.mService << ", expecting service " << (void*)mIfaceImpl->getTokenService() << std::endl;
std::cerr << " changes content: " << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(changes.mGrps.begin());it!=changes.mGrps.end();++it) std::cerr << " grp id: " << *it << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(changes.mGrpsMeta.begin());it!=changes.mGrpsMeta.end();++it) std::cerr << " grp meta: " << *it << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(changes.mGrps.begin());it!=changes.mGrps.end();++it)
std::cerr << "[GRP CHANGE] grp id: " << *it << std::endl;
for(std::list<RsGxsGroupId>::const_iterator it(changes.mGrpsMeta.begin());it!=changes.mGrpsMeta.end();++it)
std::cerr << "[GRP CHANGE] grp meta: " << *it << std::endl;
for(std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >::const_iterator it(changes.mMsgs.begin());it!=changes.mMsgs.end();++it)
for(uint32_t i=0;i<it->second.size();++i)
std::cerr << " grp id: " << it->first << ". Msg ID " << it->second[i] << std::endl;
std::cerr << "[MSG CHANGE] grp id: " << it->first << ". Msg ID " << it->second[i] << std::endl;
for(std::map<RsGxsGroupId,std::vector<RsGxsMessageId> >::const_iterator it(changes.mMsgsMeta.begin());it!=changes.mMsgsMeta.end();++it)
for(uint32_t i=0;i<it->second.size();++i)
std::cerr << " grp id: " << it->first << ". Msg Meta " << it->second[i] << std::endl;
std::cerr << "[MSG CHANGE] grp id: " << it->first << ". Msg Meta " << it->second[i] << std::endl;
}
#endif
if(changes.mService != mIfaceImpl->getTokenService())

View file

@ -19,7 +19,7 @@ public:
signals:
void changed();
void msgsChanged(const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIdsMeta);
void msgsChanged(const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIds, const std::map<RsGxsGroupId, std::set<RsGxsMessageId> >& msgIdsMeta);
void grpsChanged(const std::list<RsGxsGroupId>& grpIds, const std::list<RsGxsGroupId>& grpIdsMeta);
private slots:

View file

@ -33,7 +33,7 @@
#endif
#include <QDir>
#include "win32.h"
#include "retroshareWin32.h"
/** Finds the location of the "special" Windows folder using the given CSIDL

View file

@ -1,7 +1,8 @@
#pragma once
/****************************************************************
* This file is distributed under the following license:
*
* Copyright (c) 2006-2007, crypton
* This file is distributed under the following license:
*
* Copyright (c) 2006-2007, crypton
* Copyright (c) 2006, Matt Edman, Justin Hipple
*
* This program is free software; you can redistribute it and/or
@ -20,10 +21,6 @@
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef _WIN32_H
#define _WIN32_H
#include <QHash>
#include <QString>
@ -41,6 +38,3 @@ void win32_registry_set_key_value(QString keyLocation, QString keyName, QString
/** Removes the key from the registry if it exists */
void win32_registry_remove_key(QString keyLocation, QString keyName);
#endif