From bffcbfe467601a9079075a363afd796c196c4640 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 2 May 2010 21:37:54 +0000 Subject: [PATCH] fixed the sorting of SearchDialog by age and by size, by using proper delegates for displaying the numbers. Removed the SR_REALSIZE_COL column, that is no longer necessary. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@2840 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- retroshare-gui/src/RetroShare.pro | 1 + .../src/gui/RSHumanReadableDelegate.h | 70 +++++++++++++++++++ retroshare-gui/src/gui/SearchDialog.cpp | 59 +++++++--------- retroshare-gui/src/util/misc.h | 54 +++++++------- 4 files changed, 121 insertions(+), 63 deletions(-) create mode 100644 retroshare-gui/src/gui/RSHumanReadableDelegate.h diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index 53f4c541f..f87d7c841 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -148,6 +148,7 @@ HEADERS += rshare.h \ gui/mainpage.h \ gui/mainpagestack.h \ gui/MainWindow.h \ + gui/RSHumanReadableDelegate.h \ gui/TurtleRouterDialog.h \ gui/AboutDialog.h \ gui/AddLinksDialog.h \ diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h new file mode 100644 index 000000000..39b3d4009 --- /dev/null +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -0,0 +1,70 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 Cyril Soler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +/** Use this class for displaying dates and sizes in a readable format, while allowing to read the + * real size in the column. + * + * To use: + * + * - in the QABstractItemView constructor, do a + * + * myView->setItemDelegateForColumn(SR_SIZE_COL,new RSHumanReadableSizeDelegate()) ; + * + * - each field must be filled with a string that allows a proper sorting based on lexicographic + * order. For Sizes, use this: + * + * myView->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); + * + * Note: there's no .cpp file, because the code here is really simple. + */ + +#include +#include + +class RSHumanReadableDelegate: public QAbstractItemDelegate +{ + public: + virtual QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const + { + return QSize(50,17) ; + } + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const = 0; +}; + +class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate +{ + public: + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const + { + painter->drawText(option.rect, Qt::AlignCenter, misc::userFriendlyDuration(index.data().toLongLong())) ; + } +}; + +class RSHumanReadableSizeDelegate: public RSHumanReadableDelegate +{ + public: + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const + { + painter->drawText(option.rect, Qt::AlignRight, misc::friendlyUnit(index.data().toULongLong())); + } +}; + diff --git a/retroshare-gui/src/gui/SearchDialog.cpp b/retroshare-gui/src/gui/SearchDialog.cpp index 59fe02a84..a8789fca3 100644 --- a/retroshare-gui/src/gui/SearchDialog.cpp +++ b/retroshare-gui/src/gui/SearchDialog.cpp @@ -25,6 +25,7 @@ #include "SearchDialog.h" #include "RetroShareLink.h" #include "msgs/ChanMsgDialog.h" +#include #include "rsiface/rsiface.h" #include "rsiface/rsexpr.h" @@ -61,11 +62,8 @@ #define SR_TYPE_COL 3 #define SR_AGE_COL 4 #define SR_HASH_COL 5 - #define SR_SEARCH_ID_COL 6 - #define SR_UID_COL 7 -#define SR_REALSIZE_COL 8 /* indicies for search summary item columns SS_ = Search Summary */ #define SS_TEXT_COL 0 @@ -123,22 +121,25 @@ SearchDialog::SearchDialog(QWidget *parent) connect( ui.resetButton, SIGNAL(clicked()), this, SLOT(clearKeyword())); connect( ui.lineEdit, SIGNAL( textChanged(const QString &)), this, SLOT(togglereset())); - //connect( ui.searchSummaryWidget, SIGNAL( itemSelectionChanged ( void ) ), this, SLOT( selectSearchResults( void ) ) ); - connect( ui.searchResultWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(download())); connect ( ui.searchSummaryWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ), this, SLOT( selectSearchResults( void ) ) ); - //connect(ui.FileTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboIndexChanged(int))); connect(ui.FileTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectSearchResults(int))); /* hide the Tree +/- */ ui.searchResultWidget -> setRootIsDecorated( true ); ui.searchResultWidget -> setColumnHidden( SR_UID_COL,true ); - ui.searchResultWidget -> setColumnHidden( SR_REALSIZE_COL,true ); ui.searchSummaryWidget -> setRootIsDecorated( false ); + // We set some delegates to handle the display of size and date. + // To allow a proper sorting, be careful to pad at right with spaces. This + // is achieved by using QString("%1").arg(number,15,10). + // + ui.searchResultWidget->setItemDelegateForColumn(SR_SIZE_COL,new RSHumanReadableSizeDelegate()) ; + ui.searchResultWidget->setItemDelegateForColumn(SR_AGE_COL,new RSHumanReadableAgeDelegate()) ; + /* make it extended selection */ ui.searchResultWidget -> setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -279,22 +280,15 @@ void SearchDialog::download() std::cerr << "SearchDialog::download() Calling File Request"; std::cerr << std::endl; std::list srcIds; -#ifdef SUSPENDED - // I suspend this. For turtle F2F download, we dont' need sources: - // - if we put sources, they make double with some tunnels. - // - they won't transfer because ASSUME_AVAILABILITY can't be used, - // and no chunk maps are transfered except in tunnels. - srcIds.push_back(item->text(SR_UID_COL).toStdString()) ; -#endif if(!rsFiles -> FileRequest((item->text(SR_NAME_COL)).toStdString(), (item->text(SR_HASH_COL)).toStdString(), - (item->text(SR_REALSIZE_COL)).toULongLong(), + (item->text(SR_SIZE_COL)).toULongLong(), "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) attemptDownloadLocal = true ; else { - std::cout << "isuing file request from search dialog: -" << (item->text(SR_NAME_COL)).toStdString() << "-" << (item->text(SR_HASH_COL)).toStdString() << "-" << (item->text(SR_REALSIZE_COL)).toULongLong() << "-ids=" ; + std::cout << "isuing file request from search dialog: -" << (item->text(SR_NAME_COL)).toStdString() << "-" << (item->text(SR_HASH_COL)).toStdString() << "-" << (item->text(SR_SIZE_COL)).toULongLong() << "-ids=" ; for(std::list::const_iterator it(srcIds.begin());it!=srcIds.end();++it) std::cout << *it << "-" << std::endl ; } @@ -308,11 +302,9 @@ void SearchDialog::download() void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base) { - if (!item->childCount()) { + if (!item->childCount()) + { std::list srcIds; -#ifdef SUSPENDED - srcIds.push_back(item->text(SR_UID_COL).toStdString()); -#endif QString path = QString::fromStdString(rsFiles->getDownloadDirectory()) + tr("/") + base + tr("/"); @@ -320,14 +312,14 @@ void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString rsFiles->FileRequest(item->text(SR_NAME_COL).toStdString(), item->text(SR_HASH_COL).toStdString(), - item->text(SR_REALSIZE_COL).toULongLong(), + item->text(SR_SIZE_COL).toULongLong(), cleanPath.toStdString(),RS_FILE_HINTS_NETWORK_WIDE, srcIds); std::cout << "SearchDialog::downloadDirectory(): "\ "issuing file request from search dialog: -" << (item->text(SR_NAME_COL)).toStdString() << "-" << (item->text(SR_HASH_COL)).toStdString() - << "-" << (item->text(SR_REALSIZE_COL)).toULongLong() + << "-" << (item->text(SR_SIZE_COL)).toULongLong() << "-ids=" ; for(std::list::const_iterator it(srcIds.begin()); it!=srcIds.end();++it) @@ -671,9 +663,8 @@ void SearchDialog::insertDirectory(const std::string &txt, qulonglong searchId, child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); QString ext = QFileInfo(QString::fromStdString(dir.name)).suffix(); - child->setText(SR_SIZE_COL, misc::friendlyUnit(dir.count)); - child->setText(SR_AGE_COL, misc::userFriendlyDuration(dir.age)); - child->setText(SR_REALSIZE_COL, QString::number(dir.count)); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.age,15,10)); child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_ID_COL, QString::number(1)); @@ -700,9 +691,9 @@ void SearchDialog::insertDirectory(const std::string &txt, qulonglong searchId, child->setIcon(SR_NAME_COL, QIcon(IMAGE_DIRECTORY)); child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); - child->setText(SR_SIZE_COL, misc::toQString(dir.count)); - child->setText(SR_AGE_COL, misc::userFriendlyDuration(dir.age)); - child->setText(SR_REALSIZE_COL, QString::number(dir.count)); + //child->setText(SR_SIZE_COL, misc::toQString(dir.count)); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,15,10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.age,15,10)); child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_ID_COL, QString::number(1)); child->setTextAlignment( SR_ID_COL, Qt::AlignRight ); @@ -763,9 +754,8 @@ void SearchDialog::insertDirectory(const std::string &txt, qulonglong searchId, child->setIcon(SR_NAME_COL, QIcon(IMAGE_DIRECTORY)); child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); - child->setText(SR_SIZE_COL, misc::toQString(dir.count)); - child->setText(SR_AGE_COL, misc::userFriendlyDuration(dir.min_age)); - child->setText(SR_REALSIZE_COL, QString::number(dir.count)); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.min_age,15,10)); child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); child->setText(SR_ID_COL, QString::number(1)); child->setTextAlignment( SR_ID_COL, Qt::AlignRight ); @@ -969,9 +959,8 @@ void SearchDialog::insertFile(const std::string& txt,qulonglong searchId, const * to facilitate downlaods we need to save the file size too */ - item->setText(SR_SIZE_COL, misc::friendlyUnit(file.size)); - item->setText(SR_REALSIZE_COL, QString::number(file.size)); - item->setText(SR_AGE_COL, misc::userFriendlyDuration(file.age)); + item->setText(SR_SIZE_COL, QString("%1").arg(file.size,15,10)); // very important for sorting + item->setText(SR_AGE_COL, QString("%1").arg(file.age,15,10)); item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); if(searchType == FRIEND_SEARCH) { @@ -1204,7 +1193,7 @@ void SearchDialog::copysearchLink() std::cerr << std::endl; QString fhash = item->text(SR_HASH_COL); - qulonglong fsize = item->text(SR_REALSIZE_COL).toULongLong(); + qulonglong fsize = item->text(SR_SIZE_COL).toULongLong(); QString fname = item->text(SR_NAME_COL); RetroShareLink link(fname, fsize, fhash); diff --git a/retroshare-gui/src/util/misc.h b/retroshare-gui/src/util/misc.h index 6758cc0ea..57cf5ebd8 100644 --- a/retroshare-gui/src/util/misc.h +++ b/retroshare-gui/src/util/misc.h @@ -300,34 +300,32 @@ class misc : public QObject{ // Take a number of seconds and return an user-friendly // time duration like "1d 2h 10m". - static QString userFriendlyDuration(qlonglong seconds) { - if(seconds < 0) { - return tr("Unknown"); - } - if(seconds < 60) { - return tr("< 1m", "< 1 minute"); - } - int minutes = seconds / 60; - if(minutes < 60) { - return tr("%1 minutes","e.g: 10minutes").arg(QString::QString::fromUtf8(misc::toString(minutes).c_str())); - } - int hours = minutes / 60; - minutes = minutes - hours*60; - if(hours < 24) { - return tr("%1h %2m", "e.g: 3hours 5minutes").arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); - } - int days = hours / 24; - hours = hours - days * 24; - if(days < 365) { - return tr("%1d %2h %3m", "e.g: 2days 10hours 2minutes").arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); - } - int years = days / 365; - days = days - years * 365; - if(years > 1) { - return tr("%1y %2d %3h %4m", "e.g: 2 years 2days 10hours 2minutes").arg(QString::fromUtf8(misc::toString(years).c_str())).arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); - } - return tr("Unknown"); - } + static QString userFriendlyDuration(qlonglong seconds) + { + if(seconds < 0) { + return tr("Unknown"); + } + if(seconds < 60) { + return tr("< 1m", "< 1 minute"); + } + int minutes = seconds / 60; + if(minutes < 60) { + return tr("%1 minutes","e.g: 10minutes").arg(QString::QString::fromUtf8(misc::toString(minutes).c_str())); + } + int hours = minutes / 60; + minutes = minutes - hours*60; + if(hours < 24) { + return tr("%1h %2m", "e.g: 3hours 5minutes").arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); + } + int days = hours / 24; + hours = hours - days * 24; + if(days < 365) { + return tr("%1d %2h", "e.g: 2days 10hours").arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())); + } + int years = days / 365; + days = days - years * 365; + return tr("%1y %2d", "e.g: 2 years 2days ").arg(QString::fromUtf8(misc::toString(years).c_str())).arg(QString::fromUtf8(misc::toString(days).c_str())); + } }; // Trick to get a portable sleep() function