mirror of
https://github.com/RetroShare/RetroShare.git
synced 2026-01-22 02:45:25 -05:00
Fix autocollapse in tree view
This commit is contained in:
parent
0495b96c00
commit
a2294a9fda
2 changed files with 302 additions and 368 deletions
|
|
@ -57,6 +57,31 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* Helper class to block signals and show wait cursor during UI updates.
|
||||
* Prevents the view from reacting to model changes while we are
|
||||
* restoring the tree state.
|
||||
*/
|
||||
class QCursorContextBlocker
|
||||
{
|
||||
public:
|
||||
QCursorContextBlocker(QWidget *w)
|
||||
: mW(w)
|
||||
{
|
||||
mW->setCursor(Qt::WaitCursor);
|
||||
mW->blockSignals(true);
|
||||
}
|
||||
|
||||
~QCursorContextBlocker()
|
||||
{
|
||||
mW->setCursor(Qt::ArrowCursor);
|
||||
mW->blockSignals(false);
|
||||
}
|
||||
|
||||
private:
|
||||
QWidget *mW ;
|
||||
};
|
||||
|
||||
#define SHARED_FILES_DIALOG_COLUMN_NAME 0
|
||||
#define SHARED_FILES_DIALOG_COLUMN_FILENB 1
|
||||
#define SHARED_FILES_DIALOG_COLUMN_SIZE 2
|
||||
|
|
@ -196,16 +221,16 @@ SharedFilesDialog::~SharedFilesDialog()
|
|||
delete flat_model;
|
||||
delete tree_proxyModel;
|
||||
}
|
||||
/** Constructor */
|
||||
|
||||
/**
|
||||
* Constructor for the base SharedFilesDialog.
|
||||
*/
|
||||
SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
||||
: RsAutoUpdatePage(1000,parent), model(NULL), uploadedOnly_CB(NULL)
|
||||
{
|
||||
/* Invoke the Qt Designer generated object setup routine */
|
||||
ui.setupUi(this);
|
||||
|
||||
//connect(notify, SIGNAL(filesPreModChanged(bool)), this, SLOT(preModDirectories(bool)));
|
||||
//connect(notify, SIGNAL(filesPostModChanged(bool)), this, SLOT(postModDirectories(bool)));
|
||||
|
||||
mEventHandlerId = 0;
|
||||
|
||||
rsEvents->registerEventsHandler([this](std::shared_ptr<const RsEvent> event)
|
||||
|
|
@ -238,14 +263,21 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
connect(ui.dirTreeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT( spawnCustomPopupMenu( QPoint ) ) );
|
||||
connect(ui.indicatorCBox, SIGNAL(currentIndexChanged(int)), this, SLOT(indicatorChanged(int)));
|
||||
|
||||
// Ensure the combo box items are not bold
|
||||
QFont normalFont = ui.viewType_CB->font();
|
||||
normalFont.setBold(false);
|
||||
ui.viewType_CB->setFont(normalFont);
|
||||
|
||||
// Reset specific items font role to ensure no bolding from UI files
|
||||
for(int i = 0; i < ui.viewType_CB->count(); ++i) {
|
||||
ui.viewType_CB->setItemData(i, normalFont, Qt::FontRole);
|
||||
}
|
||||
|
||||
tree_model = new TreeStyle_RDM(remote_mode);
|
||||
flat_model = new FlatStyle_RDM(remote_mode);
|
||||
|
||||
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);
|
||||
|
|
@ -266,15 +298,10 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
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(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 () ;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||
int charWidth = ui.dirTreeView->fontMetrics().width("_");
|
||||
|
|
@ -286,26 +313,22 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FILENB , charWidth*15 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_SIZE , charWidth*10 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_AGE , charWidth*6 );
|
||||
// REDUCED WIDTH: Set to 4 instead of 10 to only fit icons
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS, charWidth*4 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR , charWidth*20 );
|
||||
header->resizeSection ( SHARED_FILES_DIALOG_COLUMN_UPLOADED , charWidth*20 );
|
||||
|
||||
header->setStretchLastSection(true);
|
||||
|
||||
/* Set Multi Selection */
|
||||
ui.dirTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
/* Hide platform specific features */
|
||||
copylinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard" ), this );
|
||||
connect( copylinkAct , SIGNAL( triggered() ), this, SLOT( copyLink() ) );
|
||||
copylinkhtmlAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard (HTML)" ), this );
|
||||
connect( copylinkhtmlAct , SIGNAL( triggered() ), this, SLOT( copyLinkhtml() ) );
|
||||
sendlinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links" ), this );
|
||||
connect( sendlinkAct , SIGNAL( triggered() ), this, SLOT( sendLinkTo( ) ) );
|
||||
copylinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard" ), this );
|
||||
connect( copylinkAct , SIGNAL( triggered() ), this, SLOT( copyLink() ) );
|
||||
copylinkhtmlAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard (HTML)" ), this );
|
||||
connect( copylinkhtmlAct , SIGNAL( triggered() ), this, SLOT( copyLinkhtml() ) );
|
||||
sendlinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links" ), this );
|
||||
connect( sendlinkAct , SIGNAL( triggered() ), this, SLOT( sendLinkTo( ) ) );
|
||||
|
||||
removeExtraFileAct = new QAction(QIcon(IMAGE_UNSHAREEXTRA), tr( "Stop sharing this file" ), this );
|
||||
connect( removeExtraFileAct , SIGNAL( triggered() ), this, SLOT( removeExtraFile() ) );
|
||||
removeExtraFileAct = new QAction(QIcon(IMAGE_UNSHAREEXTRA), tr( "Stop sharing this file" ), this );
|
||||
connect( removeExtraFileAct , SIGNAL( triggered() ), this, SLOT( removeExtraFile() ) );
|
||||
|
||||
collCreateAct= new QAction(QIcon(IMAGE_COLLCREATE), tr("Create Collection..."), this) ;
|
||||
connect(collCreateAct,SIGNAL(triggered()),this,SLOT(collCreate())) ;
|
||||
|
|
@ -317,26 +340,25 @@ SharedFilesDialog::SharedFilesDialog(bool remote_mode, QWidget *parent)
|
|||
connect(collOpenAct, SIGNAL(triggered()), this, SLOT(collOpen())) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for LocalSharedFilesDialog.
|
||||
*/
|
||||
LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent)
|
||||
: SharedFilesDialog(false,parent)
|
||||
{
|
||||
// CREATION & POSITIONING: Box created only here and placed right of view selector
|
||||
uploadedOnly_CB = new QCheckBox(tr("Uploaded only"), this);
|
||||
uploadedOnly_CB->setToolTip(tr("Show only files and folders that have been uploaded"));
|
||||
// Updated label to "Popular files" as requested
|
||||
uploadedOnly_CB = new QCheckBox(tr("Popular files"), this);
|
||||
uploadedOnly_CB->setToolTip(tr("Show only files and folders that have been uploaded by others"));
|
||||
|
||||
int viewTypeIdx = ui.horizontalLayout_2->indexOf(ui.viewType_CB);
|
||||
ui.horizontalLayout_2->insertWidget(viewTypeIdx + 1, uploadedOnly_CB);
|
||||
int cbIndex = ui.horizontalLayout_2->indexOf(ui.viewType_CB);
|
||||
ui.horizontalLayout_2->insertWidget(cbIndex + 1, uploadedOnly_CB);
|
||||
|
||||
connect(uploadedOnly_CB, SIGNAL(toggled(bool)), this, SLOT(filterUploadedOnlyToggled(bool)));
|
||||
|
||||
// Hide columns after loading the settings
|
||||
ui.dirTreeView->setColumnHidden(SHARED_FILES_DIALOG_COLUMN_WN_VISU_DIR, false) ;
|
||||
ui.downloadButton->hide() ;
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
// Setup the current view model.
|
||||
//
|
||||
changeCurrentViewModel(ui.viewType_CB->currentIndex()) ;
|
||||
|
||||
connect(ui.addShares_PB, SIGNAL(clicked()), this, SLOT(addShares())) ;
|
||||
|
|
@ -348,7 +370,6 @@ LocalSharedFilesDialog::LocalSharedFilesDialog(QWidget *parent)
|
|||
connect(openfolderAct, SIGNAL(triggered()), this, SLOT(openfolder())) ;
|
||||
|
||||
ui.titleBarPixmap->setPixmap(FilesDefs::getPixmapFromQtResourcePath(IMAGE_MYFILES)) ;
|
||||
|
||||
ui.dirTreeView->setItemDelegateForColumn(SHARED_FILES_DIALOG_COLUMN_FRIEND_ACCESS,new ShareFlagsItemDelegate()) ;
|
||||
}
|
||||
|
||||
|
|
@ -1179,41 +1200,99 @@ void SharedFilesDialog::recursRestoreExpandedItems(const QModelIndex& index, con
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void SharedFilesDialog::postModDirectories(bool local)
|
||||
/**
|
||||
* Handles directory updates after model changes.
|
||||
* Fixed to prevent autocollapse by restoring state after sorting.
|
||||
*/
|
||||
void SharedFilesDialog::postModDirectories(bool local)
|
||||
{
|
||||
if (isRemote() == local)
|
||||
return;
|
||||
|
||||
std::set<std::string> expanded_indexes,selected_indexes,hidden_indexes;
|
||||
std::set<std::string> expanded_indexes, selected_indexes, hidden_indexes;
|
||||
|
||||
saveExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes) ;
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Saving expanded items. " << expanded_indexes.size() << " items found" << std::endl;
|
||||
#endif
|
||||
// 1. Save current state
|
||||
saveExpandedPathsAndSelection(expanded_indexes, hidden_indexes, selected_indexes) ;
|
||||
|
||||
/* Notify both models, only one is visible */
|
||||
// 2. Update models
|
||||
tree_model->postMods();
|
||||
flat_model->postMods();
|
||||
ui.dirTreeView->update() ;
|
||||
|
||||
if (ui.filterPatternLineEdit->text().isEmpty() == false)
|
||||
FilterItems();
|
||||
|
||||
/** FIX: Restore selection and expansion BEFORE enabling sorting to avoid mismatch */
|
||||
restoreExpandedPathsAndSelection(expanded_indexes,hidden_indexes,selected_indexes) ;
|
||||
|
||||
// 3. Re-enable sorting BEFORE restoring expansion to stabilize the view
|
||||
ui.dirTreeView->setSortingEnabled(true);
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "****** updated directories! Re-enabling sorting ******" << std::endl;
|
||||
#endif
|
||||
// 4. Re-apply the text filter
|
||||
if (ui.filterPatternLineEdit->text().isEmpty() == false) {
|
||||
FilterItems();
|
||||
}
|
||||
|
||||
// 5. Finally restore expansion on a stable model
|
||||
restoreExpandedPathsAndSelection(expanded_indexes, hidden_indexes, selected_indexes) ;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK (6, 0, 0)
|
||||
QCoreApplication::flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies text filtering to the current model.
|
||||
* Optimized to avoid recursive model resets.
|
||||
*/
|
||||
void SharedFilesDialog::FilterItems()
|
||||
{
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
if(proxyModel == tree_proxyModel)
|
||||
return;
|
||||
#endif
|
||||
|
||||
QString text = ui.filterPatternLineEdit->text();
|
||||
|
||||
if(mLastFilterText == text)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
mLastFilterText = text ;
|
||||
|
||||
QCursorContextBlocker q(ui.dirTreeView) ;
|
||||
QCoreApplication::processEvents() ;
|
||||
|
||||
uint32_t found = 0 ;
|
||||
|
||||
if(text == "")
|
||||
{
|
||||
model->filterItems(std::list<std::string>(), found) ;
|
||||
if (tree_proxyModel) tree_proxyModel->invalidate();
|
||||
if (flat_proxyModel) flat_proxyModel->invalidate();
|
||||
return ;
|
||||
}
|
||||
|
||||
if(text.length() < 3)
|
||||
return ;
|
||||
|
||||
QStringList lst = text.split(" ", QtSkipEmptyParts) ;
|
||||
std::list<std::string> keywords ;
|
||||
|
||||
for(auto it(lst.begin()); it != lst.end(); ++it)
|
||||
keywords.push_back((*it).toStdString());
|
||||
|
||||
model->filterItems(keywords, found) ;
|
||||
|
||||
if (tree_proxyModel) tree_proxyModel->invalidate();
|
||||
if (flat_proxyModel) flat_proxyModel->invalidate();
|
||||
|
||||
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
|
||||
ui.filterPatternFrame->setToolTip(tr("Found %1 results.").arg(found)) ;
|
||||
}
|
||||
|
||||
class ChannelCompare
|
||||
{
|
||||
public:
|
||||
|
|
@ -1656,90 +1735,6 @@ void SharedFilesDialog::restoreInvisibleItems()
|
|||
}
|
||||
#endif
|
||||
|
||||
class QCursorContextBlocker
|
||||
{
|
||||
public:
|
||||
QCursorContextBlocker(QWidget *w)
|
||||
: mW(w)
|
||||
{
|
||||
mW->setCursor(Qt::WaitCursor);
|
||||
mW->blockSignals(true) ;
|
||||
}
|
||||
|
||||
~QCursorContextBlocker()
|
||||
{
|
||||
mW->setCursor(Qt::ArrowCursor);
|
||||
mW->blockSignals(false) ;
|
||||
}
|
||||
|
||||
private:
|
||||
QWidget *mW ;
|
||||
};
|
||||
|
||||
void SharedFilesDialog::FilterItems()
|
||||
{
|
||||
#ifdef DONT_USE_SEARCH_IN_TREE_VIEW
|
||||
if(proxyModel == tree_proxyModel)
|
||||
return;
|
||||
#endif
|
||||
|
||||
QString text = ui.filterPatternLineEdit->text();
|
||||
|
||||
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 ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "New last text. Performing the filter on string \"" << text.toStdString() << "\"" << std::endl;
|
||||
#endif
|
||||
mLastFilterText = text ;
|
||||
|
||||
QCursorContextBlocker q(ui.dirTreeView) ;
|
||||
|
||||
QCoreApplication::processEvents() ;
|
||||
|
||||
std::list<DirDetails> result_list ;
|
||||
uint32_t found = 0 ;
|
||||
|
||||
if(text == "")
|
||||
{
|
||||
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(" ",QtSkipEmptyParts) ;
|
||||
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
|
||||
ui.filterPatternFrame->setToolTip(tr("Found %1 results.").arg(found)) ;
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << found << " results found by search." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SharedFilesDialog::removeExtraFile()
|
||||
{
|
||||
std::list<DirDetails> files_info ;
|
||||
|
|
|
|||
|
|
@ -544,183 +544,6 @@ QVariant RetroshareDirModel::decorationRole(const DirDetails& details,int coln)
|
|||
|
||||
} /* end of DecorationRole */
|
||||
|
||||
QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const
|
||||
{
|
||||
|
||||
/*
|
||||
* Person: name, id, 0, 0;
|
||||
* File : name, size, rank, (0) ts
|
||||
* Dir : name, (0) count, (0) path, (0) ts
|
||||
*/
|
||||
|
||||
|
||||
if (details.type == DIR_TYPE_PERSON) /* Person */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME: {
|
||||
//SharedDirStats stats ;
|
||||
QString res ;
|
||||
|
||||
if(RemoteMode)
|
||||
res = QString::fromUtf8(rsPeers->getPeerName(details.id).c_str());
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
res = tr("My files");
|
||||
else
|
||||
res = tr("Temporary shared files");
|
||||
|
||||
return res ;
|
||||
}
|
||||
case REMOTEDIRMODEL_COLUMN_FILENB: {
|
||||
SharedDirStats stats ;
|
||||
|
||||
if(RemoteMode)
|
||||
rsFiles->getSharedDirStatistics(details.id,stats) ;
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ;
|
||||
else
|
||||
stats.total_number_of_files = details.children.size();
|
||||
|
||||
if(stats.total_number_of_files > 0)
|
||||
{
|
||||
if (stats.total_number_of_files > 1)
|
||||
return QString::number(stats.total_number_of_files) + " " + tr("Files");
|
||||
else
|
||||
return QString::number(stats.total_number_of_files) + " " + tr("File");
|
||||
}
|
||||
return tr("Empty");
|
||||
}
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE: {
|
||||
SharedDirStats stats ;
|
||||
|
||||
if(RemoteMode)
|
||||
rsFiles->getSharedDirStatistics(details.id,stats) ;
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ;
|
||||
else
|
||||
return QString();
|
||||
|
||||
if(stats.total_shared_size > 0)
|
||||
return misc::friendlyUnit(stats.total_shared_size) ;
|
||||
|
||||
return QString();
|
||||
}
|
||||
case REMOTEDIRMODEL_COLUMN_AGE:
|
||||
if(!isNewerThanEpoque(details.max_mtime))
|
||||
return QString();
|
||||
else if(details.id != rsPeers->getOwnId())
|
||||
return QString();
|
||||
else
|
||||
return misc::timeRelativeToNow(details.max_mtime);
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
if(!RemoteMode && details.id == rsPeers->getOwnId()) // Totals in "My files" row
|
||||
{
|
||||
uint64_t n = rsFiles->getCumulativeUploadNum();
|
||||
if(n)
|
||||
return QString(misc::friendlyUnit(rsFiles->getCumulativeUploadAll()) + QString(" - %1 files").arg(n));
|
||||
else
|
||||
return QString("-");
|
||||
}
|
||||
}
|
||||
default:
|
||||
return QString() ;
|
||||
}
|
||||
}
|
||||
else if (details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) /* File */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME:
|
||||
return QString::fromUtf8(details.name.c_str());
|
||||
case REMOTEDIRMODEL_COLUMN_FILENB:
|
||||
return QVariant();
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE:
|
||||
return misc::friendlyUnit(details.size);
|
||||
case REMOTEDIRMODEL_COLUMN_AGE:
|
||||
{
|
||||
if(details.type == DIR_TYPE_FILE)
|
||||
return misc::timeRelativeToNow(details.max_mtime);
|
||||
else if(details.type == DIR_TYPE_EXTRA_FILE)
|
||||
{
|
||||
FileInfo fi;
|
||||
if (rsFiles->FileDetails(details.hash, RS_FILE_HINTS_EXTRA , fi))
|
||||
return misc::timeRelativeToNow((rstime_t)fi.age-(30 * 3600 * 24)); // AFI_DEFAULT_PERIOD
|
||||
return QString();
|
||||
}
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS:
|
||||
return QVariant();
|
||||
case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR:
|
||||
return getGroupsString(details.flags,details.parent_groups) ;
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
uint64_t x = rsFiles->getCumulativeUpload(details.hash);
|
||||
if(x)
|
||||
return misc::friendlyUnit(x);
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
default:
|
||||
return tr("FILE");
|
||||
}
|
||||
}
|
||||
else if (details.type == DIR_TYPE_DIR) /* Dir */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME:
|
||||
return QString::fromUtf8(details.name.c_str());
|
||||
case REMOTEDIRMODEL_COLUMN_FILENB:
|
||||
if (details.children.size() > 1)
|
||||
{
|
||||
return QString::number(details.children.size()) + " " + tr("Files");
|
||||
}
|
||||
return QString::number(details.children.size()) + " " + tr("File");
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE:
|
||||
return misc::friendlyUnit(details.size);
|
||||
case REMOTEDIRMODEL_COLUMN_AGE:
|
||||
return misc::timeRelativeToNow(details.max_mtime);
|
||||
case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS:
|
||||
return getFlagsString(details.flags);
|
||||
case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR:
|
||||
return getGroupsString(details.flags,details.parent_groups) ;
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
// New logic: Check if we have a calculated total for this directory
|
||||
|
||||
// Based on logs, the 'details.path' for a directory IS the full path to that directory.
|
||||
// We do NOT need to append the name.
|
||||
|
||||
QString path = QDir::cleanPath(QString::fromUtf8(details.path.c_str()));
|
||||
|
||||
// Fallback / Safety: try constructed path if direct path fails (covers root vs sub-dir anomalies)
|
||||
auto it = m_folderUploadTotals.find(path);
|
||||
|
||||
// DEBUG: Display role request
|
||||
// std::cerr << "UPLOAD_DBG: Display Role for DIR. Name: " << details.name
|
||||
// << " | Raw Path: " << details.path
|
||||
// << " | Lookup Key: [" << path.toStdString() << "]" << std::endl;
|
||||
|
||||
if(it != m_folderUploadTotals.end() && it.value() > 0)
|
||||
{
|
||||
// std::cerr << "UPLOAD_DBG: -> FOUND! Value: " << it.value() << std::endl;
|
||||
return misc::friendlyUnit(it.value());
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
default:
|
||||
return tr("DIR");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
} /* end of DisplayRole */
|
||||
|
||||
void FlatStyle_RDM::update()
|
||||
{
|
||||
if(_needs_update)
|
||||
|
|
@ -1619,71 +1442,187 @@ void RetroshareDirModel::getFilePaths(const QModelIndexList &list, std::list<std
|
|||
#endif
|
||||
}
|
||||
|
||||
void RetroshareDirModel::filterItems(const std::list<std::string>& keywords,uint32_t& found)
|
||||
void RetroshareDirModel::filterItems(const std::list<std::string>& keywords, uint32_t& found)
|
||||
{
|
||||
FileSearchFlags flags = RemoteMode?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
|
||||
FileSearchFlags flags = RemoteMode ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL;
|
||||
|
||||
std::list<DirDetails> result_list ;
|
||||
found = 0 ;
|
||||
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) ;
|
||||
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())
|
||||
return ;
|
||||
|
||||
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();
|
||||
|
||||
mFilteredPointers.clear();
|
||||
// Mark matching pointers and their hierarchy as visible
|
||||
for(auto it(result_list.begin()); it != result_list.end(); ++it)
|
||||
{
|
||||
DirDetails& det(*it) ;
|
||||
void *p = det.ref ;
|
||||
mFilteredPointers.insert(p) ;
|
||||
++found ;
|
||||
|
||||
#ifdef RDM_SEARCH_DEBUG
|
||||
std::cerr << "Found this result: " << std::endl;
|
||||
#endif
|
||||
while(det.type == DIR_TYPE_FILE || det.type == DIR_TYPE_EXTRA_FILE || det.type == DIR_TYPE_DIR)
|
||||
{
|
||||
p = det.parent ;
|
||||
if (!rsFiles->RequestDirDetails(p, det, flags))
|
||||
break;
|
||||
|
||||
// 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_EXTRA_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
|
||||
mFilteredPointers.insert(p) ;
|
||||
}
|
||||
}
|
||||
|
||||
// CRITICAL: Removed update() call to prevent full model reset and collapse
|
||||
}
|
||||
|
||||
QVariant TreeStyle_RDM::displayRole(const DirDetails& details, int coln) const
|
||||
{
|
||||
if (details.type == DIR_TYPE_PERSON) /* Person */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME:
|
||||
{
|
||||
QString res ;
|
||||
if(RemoteMode)
|
||||
res = QString::fromUtf8(rsPeers->getPeerName(details.id).c_str());
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
res = tr("My files");
|
||||
else
|
||||
res = tr("Temporary shared files");
|
||||
return res ;
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTEDIRMODEL_COLUMN_FILENB:
|
||||
{
|
||||
SharedDirStats stats ;
|
||||
if(RemoteMode)
|
||||
rsFiles->getSharedDirStatistics(details.id,stats) ;
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ;
|
||||
else
|
||||
stats.total_number_of_files = details.children.size();
|
||||
|
||||
if(stats.total_number_of_files > 0)
|
||||
{
|
||||
if (stats.total_number_of_files > 1)
|
||||
return QString::number(stats.total_number_of_files) + " " + tr("Files");
|
||||
else
|
||||
return QString::number(stats.total_number_of_files) + " " + tr("File");
|
||||
}
|
||||
return tr("Empty");
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE:
|
||||
{
|
||||
SharedDirStats stats ;
|
||||
if(RemoteMode)
|
||||
rsFiles->getSharedDirStatistics(details.id,stats) ;
|
||||
else if(details.id == rsPeers->getOwnId())
|
||||
rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ;
|
||||
else
|
||||
return QString();
|
||||
|
||||
if(stats.total_shared_size > 0)
|
||||
return misc::friendlyUnit(stats.total_shared_size) ;
|
||||
return QString();
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTEDIRMODEL_COLUMN_AGE:
|
||||
{
|
||||
if(!isNewerThanEpoque(details.max_mtime))
|
||||
return QString();
|
||||
else if(details.id != rsPeers->getOwnId())
|
||||
return QString();
|
||||
else
|
||||
return misc::timeRelativeToNow(details.max_mtime);
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
if(!RemoteMode && details.id == rsPeers->getOwnId())
|
||||
{
|
||||
uint64_t n = rsFiles->getCumulativeUploadNum();
|
||||
if(n)
|
||||
return QString(misc::friendlyUnit(rsFiles->getCumulativeUploadAll()) + QString(" - %1 files").arg(n));
|
||||
else
|
||||
return QString("-");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
break;
|
||||
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
else if (details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) /* File */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str());
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE: return misc::friendlyUnit(details.size);
|
||||
case REMOTEDIRMODEL_COLUMN_AGE:
|
||||
{
|
||||
if(details.type == DIR_TYPE_FILE)
|
||||
return misc::timeRelativeToNow(details.max_mtime);
|
||||
else if(details.type == DIR_TYPE_EXTRA_FILE)
|
||||
{
|
||||
FileInfo fi;
|
||||
if (rsFiles->FileDetails(details.hash, RS_FILE_HINTS_EXTRA , fi))
|
||||
return misc::timeRelativeToNow((rstime_t)fi.age-(30 * 3600 * 24));
|
||||
return QString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
uint64_t x = rsFiles->getCumulativeUpload(details.hash);
|
||||
return x ? misc::friendlyUnit(x) : QString();
|
||||
}
|
||||
break;
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
else if (details.type == DIR_TYPE_DIR) /* Directory */
|
||||
{
|
||||
switch(coln)
|
||||
{
|
||||
case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str());
|
||||
case REMOTEDIRMODEL_COLUMN_FILENB:
|
||||
return QString::number(details.children.size()) + " " + (details.children.size() > 1 ? tr("Files") : tr("File"));
|
||||
case REMOTEDIRMODEL_COLUMN_SIZE: return misc::friendlyUnit(details.size);
|
||||
case REMOTEDIRMODEL_COLUMN_AGE: return misc::timeRelativeToNow(details.max_mtime);
|
||||
case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return getFlagsString(details.flags);
|
||||
case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return getGroupsString(details.flags,details.parent_groups) ;
|
||||
case REMOTEDIRMODEL_COLUMN_UPLOADED:
|
||||
{
|
||||
QString path = QDir::cleanPath(QString::fromUtf8(details.path.c_str()));
|
||||
auto it = m_folderUploadTotals.find(path);
|
||||
return (it != m_folderUploadTotals.end() && it.value() > 0) ? misc::friendlyUnit(it.value()) : "";
|
||||
}
|
||||
break;
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/* Drag and Drop Functionality */
|
||||
QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) const
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue