filebrowser.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. #include "filebrowser.h"
  2. #include <QMessageBox>
  3. #include <QDebug>
  4. #include <QLabel>
  5. #include <QFileIconProvider>
  6. #include <QPainter>
  7. #include <QInputDialog>
  8. FileBrowser::FileBrowser( QWidget *parent )
  9. : QWidget(parent)
  10. {
  11. init();
  12. }
  13. FileBrowser::FileBrowser( QString homedir, QWidget *parent )
  14. :QWidget (parent)
  15. {
  16. init(homedir);
  17. setBasePath(homedir);
  18. //qDebug("Home dir es -> "+homedir.toLatin1());
  19. }
  20. void FileBrowser::init(QString home){
  21. grabGesture(Qt::TapAndHoldGesture);
  22. grabGesture(Qt::TapGesture);
  23. setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
  24. QVBoxLayout *layout= new QVBoxLayout(this);
  25. layout->setMargin(0);
  26. layout->setSpacing(0);
  27. copyProgress = new QProgressBar(this);
  28. copyProgress->setVisible(false);
  29. copyProgress->setFormat("%v");
  30. listView= new QListView(this);
  31. tableView= new QTableView(this);
  32. tableView->setShowGrid(false);
  33. tableView->verticalHeader()->setVisible(false);
  34. tableView->setIconSize(QSize(32,32));
  35. tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
  36. tableView->setSelectionMode(QAbstractItemView::SingleSelection);
  37. tableView->setColumnWidth(0,400);
  38. if (DDeviceInformation::isTouchable()){
  39. tableView->setAlternatingRowColors(true);
  40. copyProgress->setTextVisible(false);
  41. connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(openResource()));
  42. connect(listView, SIGNAL(clicked(QModelIndex)), this, SLOT(openResource()));
  43. }
  44. layout->addWidget(copyProgress);
  45. layout->addWidget(listView);
  46. layout->addWidget(tableView);
  47. setLayout(layout);
  48. QDesktopWidget *desk=QApplication::desktop();
  49. if (desk->screenGeometry().height()<900 && desk->screenGeometry().width()<900 || DDeviceInformation::isTouchable()){ //Probably a mobile device
  50. setListViewConfiguration();
  51. }
  52. else{
  53. setIconViewConfiguration();
  54. }
  55. listView->setSelectionRectVisible(false);
  56. dirModel = new QFileSystemModel(this);
  57. dirModel->setReadOnly(false);
  58. dirModel->setRootPath(home);
  59. dirModel->setFilter(QDir::AllEntries);
  60. dirModel->setNameFilters(QStringList("[^.]*"));
  61. dirModel->setNameFilterDisables(false);
  62. listdelegate= new ListViewDelegate();
  63. listView->setItemDelegate(listdelegate);
  64. listdelegate->setBasePath(home);
  65. listView->setModel(dirModel);
  66. tableView->setItemDelegate(listdelegate);
  67. tableView->setModel(dirModel);
  68. tableView->setHidden(true);
  69. listView->setContextMenuPolicy(Qt::CustomContextMenu);
  70. tableView->setContextMenuPolicy(Qt::CustomContextMenu);
  71. connect(listView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(menu(QPoint )));
  72. connect(tableView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(menu(QPoint )));
  73. connect(this,SIGNAL(changeDirectory(QString)),this,SLOT(adaptTreeViewColumns()));
  74. currentPath = home;
  75. setRootPath(currentPath, false);
  76. listView->setCurrentIndex(dirModel->index(currentPath));
  77. tableView->setCurrentIndex(dirModel->index(currentPath));
  78. clipboard = QApplication::clipboard();
  79. mimeData = clipboard->mimeData();
  80. }
  81. QString FileBrowser::getCurrentPath()
  82. {
  83. return currentPath;
  84. }
  85. void FileBrowser::goBack()
  86. {
  87. if (history.count()>0)
  88. {
  89. future.push(currentPath);
  90. currentPath = history.pop();
  91. setRootPath(currentPath, false);
  92. }
  93. }
  94. void FileBrowser::goForward()
  95. {
  96. if (future.count()>0)
  97. {
  98. history.push(currentPath);
  99. currentPath = future.pop();
  100. setRootPath(currentPath, false);
  101. }
  102. }
  103. void FileBrowser::goUp()
  104. {
  105. changeDir(getRootIndex().parent());
  106. }
  107. void FileBrowser::goHome()
  108. {
  109. if (dirModel->isDir(dirModel->index(basePath)))
  110. setRootPath(basePath);
  111. else
  112. setRootPath(QDir::homePath());
  113. refresh();
  114. }
  115. void FileBrowser::refresh()
  116. {
  117. dirModel->setRootPath(currentPath);
  118. }
  119. void FileBrowser::setRootPath(const QString& path, bool remember)
  120. {
  121. changeDir(dirModel->index(path), remember);
  122. }
  123. void FileBrowser::changeDir(const QModelIndex& index, bool remember)
  124. {
  125. QModelIndex dir = index.sibling(index.row(), 0);
  126. if (!dirModel->isDir(dir))
  127. dir = dir.parent();
  128. if (dir != getRootIndex() && dirModel->isDir(dir))
  129. {
  130. if (remember)
  131. {
  132. future.clear();
  133. history.push(currentPath);
  134. }
  135. currentPath = dirModel->filePath(dir);
  136. listView->setRootIndex(dir);
  137. tableView->setRootIndex(dir);
  138. }
  139. updateActions();
  140. emit changeDirectory(currentPath);
  141. refresh();
  142. }
  143. void FileBrowser::updateActions()
  144. {
  145. emit setBackButtonEnabled(!history.isEmpty());
  146. emit setNextButtonEnabled(!future.isEmpty());
  147. emit setUpButtonEnabled(!dirModel->fileInfo(getCurrentIndex()).isRoot());
  148. }
  149. QFileSystemModel * FileBrowser::getDirModel(){
  150. return dirModel;
  151. }
  152. void FileBrowser::setContextMenu(ContextMenu *menu){
  153. fbMenu=menu;
  154. connect(fbMenu, SIGNAL(openTriggered()), this, SLOT(openResource()));
  155. connect(fbMenu, SIGNAL(copyTriggered()), this, SLOT(copyResourceToBuffer()));
  156. connect(fbMenu, SIGNAL(cutTriggered()), this, SLOT(cutResourceToBuffer()));
  157. connect(fbMenu, SIGNAL(pasteTriggered()), this, SLOT(pasteResource()));
  158. connect(fbMenu, SIGNAL(renameTriggered()), this, SLOT(renameResource()));
  159. connect(fbMenu, SIGNAL(deleteTriggered()), this, SLOT(deleteResourceRequest()));
  160. connect(fbMenu, SIGNAL(createFolderTriggered()), this, SLOT(createFolder()));
  161. }
  162. int FileBrowser::viewMode()
  163. {
  164. return currentViewMode;
  165. }
  166. QWidget *FileBrowser::listViewWidget()
  167. {
  168. return listView;
  169. }
  170. QWidget *FileBrowser::tableViewWidget()
  171. {
  172. return tableView;
  173. }
  174. void FileBrowser::menu(QPoint pos)
  175. {
  176. //qDebug() << "Seleccionado al entrar al menu " << dirModel->filePath(QModelIndex(getCurrentIndex()));
  177. // for most widgets
  178. //QPoint globalPos = this->mapToGlobal(pos);
  179. // for QAbstractScrollArea and derived classes you would use:
  180. QPoint globalPos = listView->viewport()->mapToGlobal(pos);
  181. if(dirModel->filePath(listView->indexAt(pos)).length()==0){
  182. listView->clearSelection();
  183. listView->setCurrentIndex(dirModel->index(currentPath));
  184. tableView->clearSelection();
  185. tableView->setCurrentIndex(dirModel->index(currentPath));
  186. fbMenu->setRenameEnabled(false);
  187. fbMenu->setDeleteEnabled(false);
  188. fbMenu->setOpenEnabled(false);
  189. }
  190. else{
  191. fbMenu->setRenameEnabled(true);
  192. fbMenu->setDeleteEnabled(true);
  193. fbMenu->setOpenEnabled(true);
  194. }
  195. if (dirModel->isDir(getCurrentIndex()))
  196. fbMenu->setNewFolderEnabled(true);
  197. else
  198. fbMenu->setNewFolderEnabled(false);
  199. if (QApplication::clipboard()->text().length()>0 || QApplication::clipboard()->mimeData()->hasUrls())
  200. fbMenu->setPasteEnabled(true);
  201. QAction* selectedItem = fbMenu->exec(globalPos);
  202. if (selectedItem)
  203. { // something was chosen, do stuff
  204. //qDebug() << "test" << selectedItem->text();
  205. }
  206. else
  207. {
  208. // nothing was chosen
  209. }
  210. }
  211. void FileBrowser::setIconViewConfiguration(){
  212. listView->setViewMode(QListView::IconMode);
  213. currentViewMode=FileBrowser::icon;
  214. listView->setIconSize(QSize(32,32));
  215. if (DDeviceInformation::isTouchable()){
  216. listView->setGridSize(QSize(192,96));
  217. listView->setAlternatingRowColors(false);
  218. }
  219. else
  220. listView->setGridSize(QSize(96,64));
  221. listView->setResizeMode(QListView::Adjust);
  222. if (listView->isHidden()){
  223. tableView->setHidden(true);
  224. listView->setHidden(false);
  225. }
  226. }
  227. void FileBrowser::setListViewConfiguration(){
  228. listView->setViewMode(QListView::ListMode);
  229. listView->setIconSize(QSize(32,32));
  230. if (DDeviceInformation::isTouchable()){
  231. listView->setAlternatingRowColors(true);
  232. listView->setGridSize(QSize(64,48));
  233. }
  234. else{
  235. listView->setGridSize(QSize(34,34));
  236. }
  237. currentViewMode=FileBrowser::list;
  238. listView->setResizeMode(QListView::Adjust);
  239. if (listView->isHidden()){
  240. tableView->setHidden(true);
  241. listView->setHidden(false);
  242. }
  243. }
  244. void FileBrowser::setDetailViewConfiguration(){
  245. currentViewMode=FileBrowser::detail;
  246. if (tableView->isHidden()){
  247. tableView->setHidden(false);
  248. listView->setHidden(true);
  249. }
  250. }
  251. void FileBrowser::adaptTreeViewColumns ()
  252. {
  253. if (tableView->isVisible())
  254. tableView->setColumnWidth(0,this->width()/2);
  255. else
  256. tableView->setColumnWidth(0,400);
  257. tableView->horizontalHeader()->setStretchLastSection(true);
  258. }
  259. void FileBrowser::openResource(){
  260. QModelIndex index;
  261. index=getCurrentIndex();
  262. if (dirModel->isDir(index))
  263. changeDir(index);
  264. else
  265. QDesktopServices::openUrl("file:///"+dirModel->filePath(index));
  266. }
  267. void FileBrowser::deleteResourceRequest(){
  268. QMessageBox msg;
  269. QModelIndex index= getCurrentIndex();
  270. //qDebug()<< "los estilos son" << DDeviceInformation::getStyleName();
  271. QFile qss(DDeviceInformation::getStyleName().replace(".qss","_qmessagebox.qss"));
  272. if( ! qss.open( QIODevice::ReadOnly ) )
  273. qDebug() << "Unable to open qss file " << qss.fileName();
  274. else if( qss.isOpen() )
  275. {
  276. QString styleSheet = QLatin1String(qss.readAll());
  277. msg.setStyleSheet(styleSheet );
  278. }
  279. //msg.setStyleSheet("QWidget {color: white;}");
  280. msg.setWindowTitle(tr("Delete?"));
  281. msg.setText("Delete " +dirModel->filePath(index)+ " ?");
  282. if (DDeviceInformation::isTouchable())
  283. msg.setWindowState(Qt::WindowMaximized);
  284. msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  285. int confirm = msg.exec();
  286. if (confirm==QMessageBox::Yes)
  287. deleteResource(index);
  288. }
  289. void FileBrowser::deleteCutResource(){
  290. deleteResource(copied_resource);
  291. }
  292. void FileBrowser::deleteResource(QModelIndex index){
  293. if ( dirModel->isDir(index)){
  294. rmFolder(dirModel->filePath(index));
  295. }
  296. else if (!dirModel->isDir(index))
  297. dirModel->remove(index);
  298. }
  299. void FileBrowser::renameResource(){
  300. if (listView->isVisible())
  301. listView->edit(getCurrentIndex());
  302. else if (tableView->isVisible())
  303. tableView->edit(getCurrentIndex());
  304. refresh();
  305. }
  306. void FileBrowser::copyResourceToBuffer(){
  307. copied_resource=getCurrentIndex();
  308. QMimeData *data= new QMimeData();
  309. QList <QUrl> lUrl;
  310. lUrl.append(QUrl::fromLocalFile(dirModel->filePath(QModelIndex(copied_resource))));
  311. data->setUrls(lUrl);
  312. data->setText(QUrl::fromLocalFile(dirModel->filePath(QModelIndex(copied_resource))).toString());
  313. QApplication::clipboard()->setMimeData(data);
  314. //qDebug() <<"Copiado " << data->text();
  315. }
  316. void FileBrowser::cutResourceToBuffer(){
  317. copyResourceToBuffer();
  318. cutResource=true;
  319. }
  320. void FileBrowser::pasteResource(){
  321. copyFromClipboard();
  322. QApplication::clipboard()->clear();
  323. //QApplication::clipboard()->mimeData()->clear();
  324. }
  325. bool FileBrowser::copyFromClipboard(){
  326. bool returnValue=false;
  327. mimeData = clipboard->mimeData();
  328. if (mimeData->hasUrls()){
  329. //qDebug() << "Pegando " << mimeData->text();
  330. //TODO: split "\n" and iterate for paste all files
  331. QList <QUrl> lUrl=mimeData->urls();
  332. QFile file;
  333. for (int i=0;i<lUrl.count();i++){
  334. file.setFileName(lUrl.at(i).toLocalFile());
  335. if (file.exists()){
  336. if (dirModel->isDir(dirModel->index(file.fileName()))){
  337. if (cutResource){
  338. if (!file.rename(file.fileName(),QDir::toNativeSeparators(currentPath)+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last()))
  339. qDebug() << "Error copying " << QDir::toNativeSeparators(file.fileName()) << "to " << currentPath+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last() << file.errorString();
  340. else
  341. returnValue=true;
  342. cutResource=false;
  343. }
  344. else {
  345. copyProgress->setMaximum(0);
  346. copyProgress->setVisible(true);
  347. if (copyFolder(file.fileName(),this->currentPath+QDir::separator()+QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last()))
  348. returnValue=true;
  349. copyProgress->setVisible(false);
  350. }
  351. }
  352. else{
  353. //qDebug() << file.fileName() << "mime ";//QDir::toNativeSeparators(currentPath+QDir::separator()+
  354. if (cutResource){
  355. if (!file.rename(file.fileName(),QDir::toNativeSeparators(currentPath)+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last()))
  356. qDebug() << "Error copying " << QDir::toNativeSeparators(file.fileName()) << "to " << currentPath+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last() << file.errorString();
  357. else
  358. returnValue=true;
  359. cutResource=false;
  360. }
  361. else if ( !file.copy(QDir::toNativeSeparators(currentPath)+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last() )){
  362. qDebug() << "Error copying " << QDir::toNativeSeparators(file.fileName()) << "to " << currentPath+QDir::separator()+ QDir::toNativeSeparators(file.fileName()).split(QDir::separator()).last() << file.errorString();
  363. }
  364. else
  365. returnValue=true;
  366. }
  367. }
  368. }
  369. }
  370. return returnValue;
  371. }
  372. QModelIndex FileBrowser::getCurrentIndex(){
  373. QModelIndex index;
  374. if (listView->isVisible())
  375. index=listView->currentIndex();
  376. else if (tableView->isVisible())
  377. index=tableView->currentIndex();
  378. return index;
  379. }
  380. QModelIndex FileBrowser::getRootIndex(){
  381. QModelIndex index;
  382. if (listView->isVisible())
  383. index=listView->rootIndex();
  384. else if (tableView->isVisible())
  385. index=tableView->rootIndex();
  386. return index;
  387. }
  388. void FileBrowser::changeView(int view){
  389. if (view==FileBrowser::icon)
  390. setIconViewConfiguration();
  391. else if(view==FileBrowser::list)
  392. setListViewConfiguration();
  393. else if(view==FileBrowser::detail)
  394. setDetailViewConfiguration();
  395. }
  396. bool FileBrowser::copyFolder(QString sourceFolder, QString destFolder)
  397. {
  398. bool returnValue=false;
  399. QDir sourceDir(sourceFolder);
  400. if(!sourceDir.exists())
  401. return false;
  402. QDir destDir(destFolder);
  403. if(!destDir.exists())
  404. {
  405. destDir.mkdir(destFolder);
  406. }
  407. QStringList files = sourceDir.entryList(QDir::Files);
  408. copyProgress->setMaximum(copyProgress->maximum()+files.count());
  409. for(int i = 0; i< files.count(); i++)
  410. {
  411. copyProgress->setValue(copyProgress->value()+1);
  412. QString srcName = sourceFolder + QDir::separator() + files[i];
  413. QString destName = destFolder + QDir::separator() + files[i];
  414. QFile::copy(srcName, destName);
  415. }
  416. files.clear();
  417. files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
  418. copyProgress->setMaximum(copyProgress->maximum()+files.count());
  419. for(int i = 0; i< files.count(); i++)
  420. {
  421. copyProgress->setValue(copyProgress->value()+1);
  422. QString srcName = sourceFolder + QDir::separator() + files[i];
  423. QString destName = destFolder + QDir::separator() + files[i];
  424. if (destName.compare(srcName + QDir::separator() + files[i])!=0){
  425. copyFolder(srcName, destName);
  426. returnValue=true;
  427. }
  428. }
  429. return returnValue;
  430. }
  431. bool FileBrowser::rmFolder(const QString sourceFolder)
  432. {
  433. QDir dir(sourceFolder);
  434. if (!dir.exists())
  435. return true;
  436. foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
  437. if (info.isDir()) {
  438. if (!rmFolder(info.filePath()))
  439. return false;
  440. } else {
  441. if (!dir.remove(info.fileName()))
  442. return false;
  443. }
  444. }
  445. QDir parentDir(QFileInfo(sourceFolder).path());
  446. return parentDir.rmdir(QFileInfo(sourceFolder).fileName());
  447. }
  448. bool FileBrowser::createFolder(){
  449. bool ok;
  450. QString text = QInputDialog::getText(this, tr("New folder"),
  451. tr("Folder name:"), QLineEdit::Normal,
  452. QDir::home().dirName(), &ok);
  453. if (ok && !text.isEmpty()){
  454. QDir *dir=new QDir();
  455. if (dirModel->isDir(getCurrentIndex()))
  456. dir->setPath(dirModel->filePath(getCurrentIndex()));
  457. else
  458. dir->setPath(currentPath);
  459. return dir->mkdir(text);
  460. }
  461. else return false;
  462. }
  463. //Alternative path to user's home directory. Used for home button
  464. void FileBrowser::setBasePath(QString path){
  465. if (dirModel->isDir(dirModel->index(path)))
  466. basePath=path;
  467. }
  468. void FileBrowser::setItemWidget(QString path, QWidget *widget){
  469. listView->setIndexWidget(dirModel->index(path),widget);
  470. }
  471. void FileBrowser::setOverlayStatus(QString path, int status){
  472. listdelegate->setOverlayStatus(dirModel->index(path).internalId(),status);
  473. }
  474. void FileBrowser::removeOverlayStatus(QString path){
  475. listdelegate->removeOverlayStatus(dirModel->index(path).internalId());
  476. }
  477. void FileBrowser::setMap(QMap<qint64, int> *map){
  478. listdelegate->setMap(map);
  479. }
  480. bool FileBrowser::event(QEvent *event)
  481. {
  482. if (event->type() == QEvent::Gesture){
  483. return gestureEvent(static_cast<QGestureEvent*>(event));
  484. }
  485. return QWidget::event(event);
  486. }
  487. bool FileBrowser::gestureEvent(QGestureEvent *event)
  488. {
  489. if (QGesture *swipe = event->gesture(Qt::TapAndHoldGesture)){
  490. //ungrabGesture(Qt::TapGesture);
  491. tapAndHoldTriggered(static_cast<QTapAndHoldGesture *>(swipe));
  492. }
  493. if (QGesture *swipe = event->gesture(Qt::TapGesture)){
  494. tapTriggered(static_cast<QTapGesture *>(swipe));
  495. }
  496. return true;
  497. }
  498. void FileBrowser::tapAndHoldTriggered(QTapAndHoldGesture* gesture)
  499. {
  500. if (gesture->state() == Qt::GestureStarted) {
  501. //qDebug("comienaz el tab and hold");
  502. }
  503. else if (gesture->state() == Qt::GestureFinished) {
  504. //grabGesture(Qt::TapGesture);
  505. QPoint position(gesture->position().toPoint());
  506. //We need to change from global coordinates to filebrowser ones
  507. if (listView->isVisible()){
  508. menu(listView->mapFromGlobal(position));
  509. }
  510. else if (tableView->isVisible())
  511. menu(tableView->mapFromGlobal(position));
  512. }
  513. }
  514. void FileBrowser::tapTriggered(QTapGesture* gesture)
  515. {
  516. if (gesture->state() == Qt::GestureStarted) {
  517. //qDebug() << "comienza el tab";
  518. setAcceptDrops(false);
  519. listView->setAcceptDrops(false);
  520. }
  521. else if (gesture->state() == Qt::GestureFinished) {
  522. openResource();
  523. }
  524. }