RetroShare/retroshare-gui/src/gui/ShareManager.cpp
2017-03-04 16:39:39 +01:00

442 lines
14 KiB
C++

/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2006, 2007 crypton
*
* 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.
****************************************************************/
#include <QContextMenuEvent>
#include <QMenu>
#include <QCheckBox>
#include <QHeaderView>
#include <QMessageBox>
#include <QUrl>
#include <QMimeData>
#include <retroshare/rsfiles.h>
#include <retroshare/rstypes.h>
#include <retroshare/rspeers.h>
#include "ShareManager.h"
#include "settings/rsharesettings.h"
#include "gui/common/GroupFlagsWidget.h"
#include "gui/common/GroupSelectionBox.h"
#include "gui/common/GroupDefs.h"
#include "gui/notifyqt.h"
#include "util/QtVersion.h"
/* Images for context menu icons */
#define IMAGE_CANCEL ":/images/delete.png"
#define IMAGE_EDIT ":/images/edit_16.png"
#define COLUMN_PATH 0
#define COLUMN_VIRTUALNAME 1
#define COLUMN_SHARE_FLAGS 2
#define COLUMN_GROUPS 3
ShareManager *ShareManager::_instance = NULL ;
/** Default constructor */
ShareManager::ShareManager()
: QDialog(NULL, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)
{
/* Invoke Qt Designer generated QObject setup routine */
ui.setupUi(this);
ui.headerFrame->setHeaderImage(QPixmap(":/images/fileshare64.png"));
ui.headerFrame->setHeaderText(tr("Share Manager"));
isLoading = false;
Settings->loadWidgetInformation(this);
connect(ui.addButton, SIGNAL(clicked( bool ) ), this , SLOT( addShare() ) );
connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(applyAndClose()));
connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
connect(ui.shareddirList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(shareddirListCustomPopupMenu(QPoint)));
connect(ui.shareddirList, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(doubleClickedCell(int,int)));
connect(ui.shareddirList, SIGNAL(cellChanged(int,int)), this, SLOT(handleCellChange(int,int)));
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(reload()));
QHeaderView* header = ui.shareddirList->horizontalHeader();
QHeaderView_setSectionResizeModeColumn(header, COLUMN_PATH, QHeaderView::Stretch);
header->setHighlightSections(false);
setAcceptDrops(true);
setAttribute(Qt::WA_DeleteOnClose, true);
reload();
}
void ShareManager::handleCellChange(int row,int column)
{
if(isLoading)
return ;
if(column == COLUMN_VIRTUALNAME)
{
// check if the thing already exists
for(uint32_t i=0;i<mDirInfos.size();++i)
if(i != (uint32_t)row && (mDirInfos[row].virtualname == std::string(ui.shareddirList->item(i,COLUMN_VIRTUALNAME)->text().toUtf8())))
{
ui.shareddirList->item(row,COLUMN_VIRTUALNAME)->setText(QString::fromUtf8(mDirInfos[row].virtualname.c_str())) ;
return ;
}
mDirInfos[row].virtualname = std::string(ui.shareddirList->item(row,COLUMN_VIRTUALNAME)->text().toUtf8()) ;
}
}
void ShareManager::editShareDirectory()
{
QTableWidget *listWidget = ui.shareddirList;
int row = listWidget->currentRow();
int col = listWidget->currentColumn();
if(col == COLUMN_VIRTUALNAME)
{
QModelIndex index = ui.shareddirList->model()->index(row,col,QModelIndex());
ui.shareddirList->edit(index);
}
else
doubleClickedCell(row,col) ;
}
void ShareManager::doubleClickedCell(int row,int column)
{
if(column == COLUMN_PATH)
{
QString dirname = QFileDialog::getExistingDirectory(NULL,tr("Choose directory"),QString(),QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly);
if(!dirname.isNull())
{
std::string new_name( dirname.toUtf8() );
for(uint32_t i=0;i<mDirInfos.size();++i)
if(mDirInfos[row].filename == new_name)
return ;
mDirInfos[row].filename = new_name ;
load();
}
}
else if(column == COLUMN_GROUPS)
{
std::list<RsNodeGroupId> selected_groups = GroupSelectionDialog::selectGroups(mDirInfos[row].parent_groups) ;
mDirInfos[row].parent_groups = selected_groups ;
load();
}
}
ShareManager::~ShareManager()
{
_instance = NULL;
Settings->saveWidgetInformation(this);
}
void ShareManager::cancel()
{
close();
}
void ShareManager::applyAndClose()
{
// This is the only place where we change things.
std::list<SharedDirInfo> infos ;
for(uint32_t i=0;i<mDirInfos.size();++i)
infos.push_back(mDirInfos[i]) ;
rsFiles->setSharedDirectories(infos) ;
close() ;
}
void ShareManager::shareddirListCustomPopupMenu( QPoint /*point*/ )
{
QMenu contextMnu( this );
int col = ui.shareddirList->currentColumn();
QString edit_text ;
switch(col)
{
case COLUMN_GROUPS: edit_text = tr("Change group visibility...") ; break ;
case COLUMN_PATH: edit_text = tr("Choose directory to share...") ; break;
case COLUMN_VIRTUALNAME: edit_text = tr("Choose visible name...") ; break;
default:
case COLUMN_SHARE_FLAGS: return ;
}
QAction *editAct = new QAction(QIcon(IMAGE_EDIT), edit_text, &contextMnu );
connect( editAct , SIGNAL( triggered() ), this, SLOT( editShareDirectory() ) );
QAction *removeAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Remove" ), &contextMnu );
connect( removeAct , SIGNAL( triggered() ), this, SLOT( removeShareDirectory() ) );
contextMnu.addAction( editAct );
contextMnu.addAction( removeAct );
contextMnu.exec(QCursor::pos());
}
void ShareManager::reload()
{
std::list<SharedDirInfo> dirs ;
rsFiles->getSharedDirectories(dirs) ;
mDirInfos.clear();
for(std::list<SharedDirInfo>::const_iterator it(dirs.begin());it!=dirs.end();++it)
mDirInfos.push_back(*it) ;
load();
}
/** Loads the settings for this page */
void ShareManager::load()
{
if(isLoading)
return ;
isLoading = true;
/* get a link to the table */
QTableWidget *listWidget = ui.shareddirList;
/* set new row count */
listWidget->setRowCount(mDirInfos.size());
for(uint32_t row=0;row<mDirInfos.size();++row)
{
listWidget->setItem(row, COLUMN_PATH, new QTableWidgetItem(QString::fromUtf8(mDirInfos[row].filename.c_str())));
if(mDirInfos[row].virtualname.empty())
listWidget->setItem(row, COLUMN_VIRTUALNAME, new QTableWidgetItem(tr("[Unset] (Double click to change)"))) ;
else
listWidget->setItem(row, COLUMN_VIRTUALNAME, new QTableWidgetItem(QString::fromUtf8(mDirInfos[row].virtualname.c_str())));
GroupFlagsWidget *widget = new GroupFlagsWidget(NULL,mDirInfos[row].shareflags);
listWidget->setRowHeight(row, 32 * QFontMetricsF(font()).height()/14.0);
listWidget->setCellWidget(row, COLUMN_SHARE_FLAGS, widget);
listWidget->setItem(row, COLUMN_GROUPS, new QTableWidgetItem()) ;
listWidget->item(row,COLUMN_GROUPS)->setBackgroundColor(QColor(183,236,181)) ;
connect(widget,SIGNAL(flagsChanged(FileStorageFlags)),this,SLOT(updateFlags())) ;
listWidget->item(row,COLUMN_GROUPS)->setToolTip(tr("Double click to select which groups of friends can see the files")) ;
listWidget->item(row,COLUMN_VIRTUALNAME)->setToolTip(tr("Double click to change the name that friends will see.")) ;
listWidget->item(row,COLUMN_GROUPS)->setText(getGroupString(mDirInfos[row].parent_groups));
QFont font = listWidget->item(row,COLUMN_GROUPS)->font();
font.setBold(mDirInfos[row].shareflags & DIR_FLAGS_BROWSABLE) ;
listWidget->item(row,COLUMN_GROUPS)->setTextColor( (mDirInfos[row].shareflags & DIR_FLAGS_BROWSABLE)? (Qt::black):(Qt::lightGray)) ;
listWidget->item(row,COLUMN_GROUPS)->setFont(font);
if(QDir(QString::fromUtf8(mDirInfos[row].filename.c_str())).exists())
{
listWidget->item(row,COLUMN_PATH)->setTextColor(Qt::black);
listWidget->item(row,COLUMN_PATH)->setToolTip(tr("Double click to change shared directory path")) ;
}
else
{
listWidget->item(row,COLUMN_PATH)->setTextColor(Qt::lightGray);
listWidget->item(row,COLUMN_PATH)->setToolTip(tr("Directory does not exist! Double click to change shared directory path")) ;
}
}
listWidget->setColumnWidth(COLUMN_SHARE_FLAGS,132 * QFontMetricsF(font()).height()/14.0) ;
listWidget->update(); /* update display */
update();
isLoading = false ;
}
void ShareManager::showYourself()
{
if(_instance == NULL)
_instance = new ShareManager() ;
_instance->reload() ;
_instance->show() ;
_instance->activateWindow();
}
/*static*/ void ShareManager::postModDirectories(bool update_local)
{
if (_instance == NULL || _instance->isHidden()) {
return;
}
if (update_local) {
_instance->reload();
}
}
void ShareManager::updateFlags()
{
for(int row=0;row<ui.shareddirList->rowCount();++row)
{
FileStorageFlags flags = (dynamic_cast<GroupFlagsWidget*>(ui.shareddirList->cellWidget(row,COLUMN_SHARE_FLAGS)))->flags() ;
mDirInfos[row].shareflags = flags ;
}
load() ; // update the GUI.
}
QString ShareManager::getGroupString(const std::list<RsNodeGroupId>& groups)
{
if(groups.empty())
return tr("[All friend nodes]") ;
int n = 0;
QString group_string ;
for (std::list<RsNodeGroupId>::const_iterator it(groups.begin());it!=groups.end();++it,++n)
{
if (n>0)
group_string += ", " ;
RsGroupInfo groupInfo;
rsPeers->getGroupInfo(*it, groupInfo);
group_string += GroupDefs::name(groupInfo);
}
return group_string ;
}
void ShareManager::removeShareDirectory()
{
/* id current dir */
/* ask for removal */
QTableWidget *listWidget = ui.shareddirList;
int row = listWidget -> currentRow();
QTableWidgetItem *qdir = listWidget->item(row, COLUMN_PATH);
if (qdir)
{
if ((QMessageBox::question(this, tr("Warning!"),tr("Do you really want to stop sharing this directory ?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes)
{
for(uint32_t i=row;i+1<mDirInfos.size();++i)
mDirInfos[i] = mDirInfos[i+1] ;
mDirInfos.pop_back() ;
load();
}
}
}
void ShareManager::showEvent(QShowEvent *event)
{
if (!event->spontaneous())
{
load();
}
}
void ShareManager::addShare()
{
QString fname = QFileDialog::getExistingDirectory(NULL,tr("Choose a directory to share"),QString(),QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly);
if(fname.isNull())
return;
std::string dir_name ( fname.toUtf8() );
// check that the directory does not already exist
for(uint32_t i=0;i<mDirInfos.size();++i)
if(mDirInfos[i].filename == dir_name)
return ;
mDirInfos.push_back(SharedDirInfo());
mDirInfos.back().filename = dir_name ;
mDirInfos.back().virtualname = std::string();
mDirInfos.back().shareflags = DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_ANONYMOUS_SEARCH;
mDirInfos.back().parent_groups.clear();
load();
}
void ShareManager::shareddirListCurrentCellChanged(int /*currentRow*/, int /*currentColumn*/, int /*previousRow*/, int /*previousColumn*/)
{
}
void ShareManager::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls()) {
event->acceptProposedAction();
}
}
void ShareManager::dropEvent(QDropEvent *event)
{
if (!(Qt::CopyAction & event->possibleActions())) {
/* can't do it */
return;
}
QStringList formats = event->mimeData()->formats();
QStringList::iterator it;
bool errorShown = false;
if (event->mimeData()->hasUrls()) {
QList<QUrl> urls = event->mimeData()->urls();
QList<QUrl>::iterator it;
for (it = urls.begin(); it != urls.end(); ++it) {
QString localpath = it->toLocalFile();
if (localpath.isEmpty() == false) {
QDir dir(localpath);
if (dir.exists()) {
SharedDirInfo sdi;
sdi.filename = localpath.toUtf8().constData();
sdi.virtualname.clear();
sdi.shareflags.clear() ;
/* add new share */
rsFiles->addSharedDirectory(sdi);
} else if (QFile::exists(localpath)) {
if (errorShown == false) {
QMessageBox mb(tr("Drop file error."), tr("File can't be dropped, only directories are accepted."), QMessageBox::Information, QMessageBox::Ok, 0, 0, this);
mb.exec();
errorShown = true;
}
} else {
QMessageBox mb(tr("Drop file error."), tr("Directory not found or directory name not accepted."), QMessageBox::Information, QMessageBox::Ok, 0, 0, this);
mb.exec();
}
}
}
}
event->setDropAction(Qt::CopyAction);
event->accept();
load();
}