1 //////////////////////////////////////////////////////////////////////
2 //
3 // BeeBEEP Copyright (C) 2010-2021 Marco Mastroddi
4 //
5 // BeeBEEP is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published
7 // by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // BeeBEEP is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with BeeBEEP. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // Author: Marco Mastroddi <marco.mastroddi(AT)gmail.com>
19 //
20 // $Id: GuiShareLocal.cpp 1455 2020-12-23 10:17:53Z mastroddi $
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "BeeUtils.h"
25 #include "GuiShareLocal.h"
26 #include "FileDialog.h"
27 #include "FileShare.h"
28 #include "IconManager.h"
29 #include "Settings.h"
30
31
GuiShareLocal(QWidget * parent)32 GuiShareLocal::GuiShareLocal( QWidget *parent )
33 : QWidget(parent)
34 {
35 setupUi( this );
36 setAcceptDrops( true );
37
38 QString window_title = QString( "<b>%1</b> (%2)" ).arg( tr( "Share your folders or files" ) ).arg( Settings::instance().enableFileSharing() ? tr( "max <b>%1</b> files" ).arg( Settings::instance().maxFileShared() ) : tr( "disabled" ) );
39 mp_lTitle->setText( window_title );
40
41 mp_twMyShares->setContextMenuPolicy( Qt::CustomContextMenu );
42 mp_twMyShares->setRootIsDecorated( false );
43 mp_twMyShares->setSortingEnabled( true );
44 mp_twMyShares->setAlternatingRowColors( true );
45 mp_twMyShares->setSortingEnabled( true );
46
47 QStringList labels;
48 labels << tr( "File" ) << tr( "Size" ) << tr( "Path" );
49 mp_twMyShares->setHeaderLabels( labels );
50
51 QHeaderView* header_view = mp_twMyShares->header();
52 #if QT_VERSION >= 0x050000
53 header_view->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
54 header_view->setSectionResizeMode( 1, QHeaderView::ResizeToContents );
55 header_view->setSectionResizeMode( 2, QHeaderView::Stretch );
56 #else
57 header_view->setResizeMode( 0, QHeaderView::ResizeToContents );
58 header_view->setResizeMode( 1, QHeaderView::ResizeToContents );
59 header_view->setResizeMode( 2, QHeaderView::Stretch );
60 #endif
61 header_view->setSortIndicator( 2, Qt::AscendingOrder );
62
63 mp_menuContext = new QMenu( this );
64
65 connect( mp_twMyShares, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( openMySharesMenu( const QPoint& ) ) );
66 connect( mp_twMyShares, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( openItemDoubleClicked( QTreeWidgetItem*, int ) ) );
67 }
68
setupToolBar(QToolBar * bar)69 void GuiShareLocal::setupToolBar( QToolBar* bar )
70 {
71 mp_labelShareStats = new QLabel( bar );
72 mp_labelShareStats->setObjectName( "GuiLabelLocalShareStats" );
73 mp_labelShareStats->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
74 bar->addWidget( mp_labelShareStats );
75 bar->addSeparator();
76
77 mp_actAddFile = bar->addAction( IconManager::instance().icon( "file-add.png" ), tr( "Share a file" ), this, SLOT( addFilePath() ) );
78 mp_actAddFile->setStatusTip( tr( "Add a file to your local share" ) );
79
80 mp_actAddFolder = bar->addAction( IconManager::instance().icon( "folder-add.png" ), tr( "Share a folder" ), this, SLOT( addFolderPath() ) );
81 mp_actAddFolder->setStatusTip( tr( "Add a folder to your local share" ) );
82
83 mp_actUpdate = bar->addAction( IconManager::instance().icon( "update.png" ), tr( "Update shares" ), this, SLOT( updateList() ) );
84 mp_actUpdate->setStatusTip( tr( "Update shared folders and files" ) );
85
86 mp_actRemove = bar->addAction( IconManager::instance().icon( "delete.png" ), tr( "Remove shared path" ), this, SLOT( removePath() ) );
87 mp_actRemove->setStatusTip( tr( "Remove shared path from the list" ) );
88
89 mp_actClear = bar->addAction( IconManager::instance().icon( "clear.png" ), tr( "Clear all shares" ), this, SLOT( clearAllPaths() ) );
90 mp_actClear->setStatusTip( tr( "Clear all shared paths from the list" ) );
91
92 showStats( 0, 0 );
93 setActionsEnabled( true );
94 }
95
showStats(int file_count,FileSizeType total_file_size)96 void GuiShareLocal::showStats( int file_count, FileSizeType total_file_size )
97 {
98 if( Settings::instance().enableFileTransfer() && Settings::instance().enableFileSharing() )
99 mp_labelShareStats->setText( QString( "%1: <b>%2</b> (%3) " ).arg( tr( "Shared files" ) ).arg( file_count ).arg( Bee::bytesToString( total_file_size ) ) );
100 else
101 mp_labelShareStats->setText( QString( "<b>%1</b> " ).arg( tr( "File transfer is disabled" ) ) );
102 }
103
setActionsEnabled(bool enable)104 void GuiShareLocal::setActionsEnabled( bool enable )
105 {
106 mp_actAddFile->setEnabled( enable );
107 mp_actAddFolder->setEnabled( enable );
108 mp_actRemove->setEnabled( enable && mp_twMyShares->topLevelItemCount() > 0 );
109 mp_actUpdate->setEnabled( enable && mp_twMyShares->topLevelItemCount() > 0 );
110 mp_actClear->setEnabled( enable && mp_twMyShares->topLevelItemCount() > 0 );
111 if( enable )
112 setCursor( Qt::ArrowCursor );
113 else
114 setCursor( Qt::WaitCursor );
115 }
116
addFilePath()117 void GuiShareLocal::addFilePath()
118 {
119 QStringList file_path_list = FileDialog::getOpenFileNames( true, this, tr( "Select a file to share" ),
120 Settings::instance().lastDirectorySelected() );
121 if( file_path_list.isEmpty() )
122 return;
123
124 Settings::instance().setLastDirectorySelectedFromFile( file_path_list.last() );
125
126 foreach( QString file_path, file_path_list )
127 addSharePath( file_path );
128 }
129
addFolderPath()130 void GuiShareLocal::addFolderPath()
131 {
132 QString folder_path = FileDialog::getExistingDirectory( this, tr( "Select a folder to share" ),
133 Settings::instance().lastDirectorySelected() );
134 if( folder_path.isEmpty() )
135 return;
136
137 Settings::instance().setLastDirectorySelected( Bee::convertToNativeFolderSeparator( folder_path ) );
138
139 addSharePath( folder_path );
140 }
141
removePath()142 void GuiShareLocal::removePath()
143 {
144 if( Settings::instance().localShare().isEmpty() )
145 return;
146
147 QList<QTreeWidgetItem*> item_list = mp_twMyShares->selectedItems();
148 if( item_list.isEmpty() )
149 {
150 QMessageBox::information( this, Settings::instance().programName(), tr( "Please select a shared path." ) );
151 mp_twMyShares->setFocus();
152 return;
153 }
154
155 QString share_selected = item_list.first()->text( 2 );
156
157 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you want to remove this path:" )
158 + QString( "\n%1").arg( share_selected ),
159 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
160 return;
161
162 setActionsEnabled( false );
163
164 emit sharePathRemoved( share_selected );
165 }
166
clearAllPaths()167 void GuiShareLocal::clearAllPaths()
168 {
169 if( Settings::instance().localShare().isEmpty() )
170 return;
171
172 if( QMessageBox::question( this, Settings::instance().programName(), tr( "Do you want to remove all shared paths?" ),
173 tr( "Yes" ), tr( "No" ), QString(), 1, 1 ) != 0 )
174 return;
175
176 emit removeAllPathsRequest();
177 }
178
updatePaths()179 void GuiShareLocal::updatePaths()
180 {
181 mp_twMyShares->clear();
182 if( Settings::instance().localShare().isEmpty() )
183 return;
184 QTreeWidgetItem *item;
185 mp_twMyShares->setUpdatesEnabled( false );
186 foreach( QString share_path, Settings::instance().localShare() )
187 {
188 item = new QTreeWidgetItem( mp_twMyShares );
189 item->setText( 0, QString::number( FileShare::instance().local().count( share_path ) ) );
190 item->setData( 0, Qt::UserRole + 1, share_path );
191 item->setText( 1, Bee::bytesToString( FileShare::instance().localSize( share_path ) ) );
192 item->setText( 2, share_path );
193 }
194 mp_twMyShares->setUpdatesEnabled( true );
195 }
196
updateFileSharedList()197 void GuiShareLocal::updateFileSharedList()
198 {
199 setActionsEnabled( false );
200 updatePaths();
201 int file_count = 0;
202 FileSizeType total_file_size = 0;
203
204 if( !FileShare::instance().local().isEmpty() )
205 {
206 foreach( FileInfo fi, FileShare::instance().local() )
207 {
208 file_count++;
209 total_file_size += fi.size();
210 }
211 }
212
213 showStats( file_count, total_file_size );
214 setActionsEnabled( true );
215 }
216
addSharePath(const QString & sp)217 void GuiShareLocal::addSharePath( const QString& sp )
218 {
219 QString share_path = Bee::convertToNativeFolderSeparator( sp );
220 if( Settings::instance().hasLocalSharePath( share_path ) )
221 {
222 QMessageBox::information( this, Settings::instance().programName(),
223 tr( "%1 is already shared." ).arg( share_path ) );
224 return;
225 }
226
227 QStringList local_share = Settings::instance().localShare();
228 local_share << share_path;
229 Settings::instance().setLocalShare( local_share );
230
231 updatePaths();
232
233 if( !isFileSharingEnabled() )
234 return;
235
236 setActionsEnabled( false );
237
238 emit sharePathAdded( share_path );
239 }
240
openItemDoubleClicked(QTreeWidgetItem * item,int)241 void GuiShareLocal::openItemDoubleClicked( QTreeWidgetItem* item, int )
242 {
243 if( !item )
244 return;
245
246 QString file_path = item->data( 0, Qt::UserRole + 1 ).toString();
247 if( !file_path.isEmpty() )
248 emit openUrlRequest( QUrl::fromLocalFile( file_path ) );
249 }
250
updateList()251 void GuiShareLocal::updateList()
252 {
253 if( !isFileSharingEnabled() )
254 return;
255 setActionsEnabled( false );
256 emit updateListRequest();
257 }
258
isFileSharingEnabled()259 bool GuiShareLocal::isFileSharingEnabled()
260 {
261 if( Settings::instance().enableFileTransfer() && Settings::instance().enableFileSharing() )
262 return true;
263
264 QMessageBox::information( this, Settings::instance().programName(), tr( "File transfer is disabled. Open the option menu to enable it." ) );
265 return false;
266 }
267
dragEnterEvent(QDragEnterEvent * event)268 void GuiShareLocal::dragEnterEvent( QDragEnterEvent *event )
269 {
270 if( event->mimeData()->hasUrls() )
271 event->acceptProposedAction();
272 }
273
dropEvent(QDropEvent * event)274 void GuiShareLocal::dropEvent( QDropEvent *event )
275 {
276 if( event->mimeData()->hasUrls() )
277 {
278 foreach( QUrl url, event->mimeData()->urls() )
279 {
280 #if QT_VERSION >= 0x040800
281 if( url.isLocalFile() )
282 #else
283 if( url.scheme() == QLatin1String( "file" ) )
284 #endif
285 addSharePath( url.toLocalFile() );
286 }
287 }
288 }
289
openMySharesMenu(const QPoint & p)290 void GuiShareLocal::openMySharesMenu( const QPoint& p )
291 {
292 QTreeWidgetItem* item = mp_twMyShares->itemAt( p );
293
294 mp_menuContext->clear();
295
296 if( item )
297 {
298 if( !item->isSelected() )
299 item->setSelected( true );
300 mp_menuContext->addAction( mp_actRemove );
301 }
302 else
303 {
304 mp_menuContext->addAction( mp_actAddFile );
305 mp_menuContext->addAction( mp_actAddFolder );
306 }
307
308 mp_menuContext->exec( QCursor::pos() );
309 }
310