Fixed bluetooth sending, no need to "copy" files first
[cuteexplorer] / src / filelistwidget.cpp
1 #include "filelistwidget.h"
2 #include <QHeaderView>
3 #include <QMessageBox>
4 #include <QInputDialog>
5 #include <QDesktopServices>
6 #include <QUrl>
7 #include <QProcess>
8 #include <QDBusInterface>
9 #ifdef Q_WS_MAEMO_5
10 #   include <hildon-mime.h>
11 #   include <dbus/dbus.h>
12 #endif
13 /*!
14 Widget that shows filesystemmodel and handles navigation
15 in directory tree and opening files with assosiated programs
16
17 @todo in symbian and windows filesystems navigating to "root" wont show drives
18   */
19 FileListWidget::FileListWidget(QWidget *parent) :
20     QListView(parent),
21     fileSystemModel( new QFileSystemModel(this)),
22     currentDir(QDir::homePath()),
23     mode_cut(false),
24     mode_copy(false),
25     select(false)
26 {
27     this->setModel(fileSystemModel);
28     this->setRootIndex(fileSystemModel->index(currentDir.absolutePath()));
29     fileSystemModel->setRootPath(currentDir.absolutePath());
30     fileSystemModel->setFilter(fileSystemModel->filter() | QDir::System);
31     connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(handleItemActivation(QModelIndex)));
32
33 }
34
35 /**
36   Switches view mode
37   @param iconmode true shows iconview, false shows listview
38   */
39 void FileListWidget::actionSwitchMode(bool iconmode)
40 {
41     if(iconmode) {
42         this->setViewMode(QListView::IconMode);
43         this->setWordWrap(true);
44         this->setGridSize(QSize(80,80));
45     } else {
46         this->setViewMode(QListView::ListMode);
47         this->setWordWrap(false);
48         this->setGridSize(QSize());
49     }
50 }
51
52 /**
53   Switches show hidden
54   @param show true shows hidden files
55   */
56 void FileListWidget::actionShowHidden(bool show)
57 {
58     if(show)
59         fileSystemModel->setFilter(fileSystemModel->filter() | QDir::Hidden);
60     else
61         fileSystemModel->setFilter(fileSystemModel->filter() &~ QDir::Hidden);
62
63     this->clearSelection();
64 }
65
66 /**
67   Rename selected file
68   */
69 void FileListWidget::actionRename()
70 {
71     QFileInfo file = fileSystemModel->fileInfo(this->selectedIndexes().first());
72     QString newName = QInputDialog::getText(this, tr("Rename"), tr("New filename: "), QLineEdit::Normal, file.fileName());
73     if(newName != file.fileName())
74     {
75         if(QFile::rename(file.absoluteFilePath(), file.absolutePath()+"/"+newName))
76             return;
77         else
78             QMessageBox::critical(this,tr("Error!")
79                                   ,tr("Renaming file %1 failed")
80                                     .arg(file.fileName())
81                                   ,QMessageBox::Ok);
82     }
83 }
84 /**
85   Selected files will be moved when actionPaste is called
86   */
87 void FileListWidget::actionCut()
88 {
89     mode_cut = true;
90     mode_copy = false;
91     selectedFiles = this->selectedIndexes();
92 }
93 /**
94   Selected files will be copied when actionPaste is called
95   */
96 void FileListWidget::actionCopy()
97 {
98     mode_cut = false;
99     mode_copy = true;
100     selectedFiles = this->selectedIndexes();
101 }
102
103 /**
104   Moves or copies files that were selected when actionCut or actionCopy called
105   */
106 void FileListWidget::actionPaste()
107 {
108     fileSystemModel->setReadOnly(false);
109     if(mode_copy) {
110         //Copy files until filelist is empty or error occured
111         while(!selectedFiles.isEmpty()) {
112             if(QFile::copy(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
113                         , fileSystemModel->rootPath()+"/"+fileSystemModel->fileName(selectedFiles.first()))) {
114                 selectedFiles.removeFirst();
115             }
116             else if(QFile::copy(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
117                     , fileSystemModel->rootPath()+"/copy_"+fileSystemModel->fileName(selectedFiles.first()))) {
118                 selectedFiles.removeFirst();
119             } else {
120                 QMessageBox::critical(this,tr("Error!")
121                                       ,tr("Copying file %1 failed")
122                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
123                                       ,QMessageBox::Ok);
124                 break;
125             }
126         }
127         if(selectedFiles.isEmpty())
128             mode_copy = false;
129     } else if(mode_cut) {
130         //Move files until filelist is empty or error occured
131         while(!selectedFiles.isEmpty()) {
132             if(QFile::rename(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
133                         , fileSystemModel->rootPath()+"/"+fileSystemModel->fileName(selectedFiles.first()))) {
134                     selectedFiles.removeFirst();
135             } else {
136                 QMessageBox::critical(this,tr("Error!")
137                                       ,tr("Moving file %1 failed")
138                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
139                                       ,QMessageBox::Ok);
140                 break;
141             }
142         }
143         if(selectedFiles.isEmpty())
144             mode_cut = false;
145     }
146     fileSystemModel->setReadOnly(true);
147     this->clearSelection();
148 }
149
150 /**
151   Deletes selected files
152   */
153 void FileListWidget::actionDelete()
154 {
155     mode_cut = false;
156     mode_copy = false;
157     if(QMessageBox::Yes == QMessageBox::warning(this, tr("Deleting file")
158                             ,tr("You are about to delete %1 file(s).\nAre you sure you want to continue?")
159                                 .arg(this->selectedIndexes().count())
160                             , QMessageBox::Yes, QMessageBox::No)) {
161         fileSystemModel->setReadOnly(false);
162         selectedFiles = this->selectedIndexes();
163         //delete files until filelist empty or error occured
164         while(!selectedFiles.isEmpty()) {
165             if(fileSystemModel->remove(selectedFiles.first())) {
166                 selectedFiles.removeFirst();
167             } else {
168                 QMessageBox::critical(this,tr("Error!")
169                                       ,tr("Deleting file %1 failed")
170                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
171                                       ,QMessageBox::Ok);
172                 break;
173             }
174         }
175         fileSystemModel->setReadOnly(true);
176         this->clearSelection();
177     }
178 }
179
180 /**
181   @return Current directory shown
182   */
183 QString FileListWidget::getPath()
184 {
185     return currentDir.absolutePath();
186 }
187
188 /**
189   Changes current directory
190   @param path directory to change to
191   */
192 void FileListWidget::changePath(QString path)
193 {
194     currentDir.cd(path);
195     QString newPath = currentDir.absolutePath();
196     fileSystemModel->setRootPath(newPath);
197     this->clearSelection();
198     this->setRootIndex(fileSystemModel->index(newPath));
199     emit pathChanged(newPath);
200 }
201
202 /**
203   Equivalent to changePath("..")
204   */
205 void FileListWidget::changePathUp()
206 {
207     changePath("..");
208 }
209
210 void FileListWidget::handleItemActivation(QModelIndex index)
211 {
212     if(!select) {
213         QFileInfo file = fileSystemModel->fileInfo(index);
214         if(file.isDir()) {
215             changePath(file.absoluteFilePath());
216         } else if(file.isExecutable()) {
217             // Make process
218             QProcess::startDetached(file.absoluteFilePath());
219         } else {
220 #ifdef Q_WS_MAEMO_5 // Uses native file opening method
221             //TODO: find better solution for this, maybe get fixed in Qt
222             DBusConnection* conn;
223             conn = dbus_bus_get(DBUS_BUS_SESSION, 0);
224             hildon_mime_open_file(conn, QUrl::fromLocalFile(file.absoluteFilePath()).toEncoded().constData());
225 #else
226             /*
227             Not working with maemo5.
228             Uses hildon_uri_open function from
229             libhildonmime which should work,
230             but all files opened in browser.
231             */
232             QDesktopServices::openUrl(QUrl::fromLocalFile(file.absoluteFilePath()));
233 #endif
234         }
235     }
236 }
237 /**
238   @param mode true activates file selection
239   */
240 void FileListWidget::setSelectMode(bool mode)
241 {
242     select = mode;
243 }
244
245 /**
246   Opens native bluetooth dialog to choose receiving device and sends selected files there.
247   */
248 void FileListWidget::actionSendFiles()
249 {
250 #ifdef Q_WS_MAEMO_5
251     // Create list of file urls
252     QStringList files;
253     foreach(QModelIndex index, this->selectedIndexes()) {
254         files.append(QUrl::fromLocalFile(fileSystemModel->fileInfo(index)).absoluteFilePath()).toString());
255     }
256
257     // Make dbuscall to send files
258     QDBusInterface interface("com.nokia.bt_ui", "/com/nokia/bt_ui", "com.nokia.bt_ui",QDBusConnection::systemBus());
259     interface.call("show_send_file_dlg", files);
260 #else
261     QMessageBox::information(this,
262                              tr("Sending files"),
263                              tr("Only in maemo5 for now"),
264                              QMessageBox::Cancel);
265 #endif
266
267 }
268