7fbc3269727f9bcf1441ad9504f058c3736d32aa
[cuteexplorer] / 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     setSelectMode(false);
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() && !newName.isEmpty())
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     setSelectMode(false);
84 }
85 /**
86   Selected files will be moved when actionPaste is called
87   */
88 void FileListWidget::actionCut()
89 {
90     mode_cut = true;
91     mode_copy = false;
92     selectedFiles = this->selectedIndexes();
93 }
94 /**
95   Selected files will be copied when actionPaste is called
96   */
97 void FileListWidget::actionCopy()
98 {
99     mode_cut = false;
100     mode_copy = true;
101     selectedFiles = this->selectedIndexes();
102 }
103
104 /**
105   Moves or copies files that were selected when actionCut or actionCopy called
106   */
107 void FileListWidget::actionPaste()
108 {
109     fileSystemModel->setReadOnly(false);
110     if(mode_copy) {
111         //Copy files until filelist is empty or error occured
112         while(!selectedFiles.isEmpty()) {
113             if(QFile::copy(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
114                         , fileSystemModel->rootPath()+"/"+fileSystemModel->fileName(selectedFiles.first()))) {
115                 selectedFiles.removeFirst();
116             }
117             else if(QFile::copy(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
118                     , fileSystemModel->rootPath()+"/copy_"+fileSystemModel->fileName(selectedFiles.first()))) {
119                 selectedFiles.removeFirst();
120             } else {
121                 QMessageBox::critical(this,tr("Error!")
122                                       ,tr("Copying file %1 failed")
123                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
124                                       ,QMessageBox::Ok);
125                 break;
126             }
127         }
128         if(selectedFiles.isEmpty())
129             mode_copy = false;
130     } else if(mode_cut) {
131         //Move files until filelist is empty or error occured
132         while(!selectedFiles.isEmpty()) {
133             if(QFile::rename(fileSystemModel->fileInfo(selectedFiles.first()).absoluteFilePath()
134                         , fileSystemModel->rootPath()+"/"+fileSystemModel->fileName(selectedFiles.first()))) {
135                     selectedFiles.removeFirst();
136             } else {
137                 QMessageBox::critical(this,tr("Error!")
138                                       ,tr("Moving file %1 failed")
139                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
140                                       ,QMessageBox::Ok);
141                 break;
142             }
143         }
144         if(selectedFiles.isEmpty())
145             mode_cut = false;
146     }
147     fileSystemModel->setReadOnly(true);
148     this->clearSelection();
149     setSelectMode(false);
150 }
151
152 /**
153   Deletes selected files
154   */
155 void FileListWidget::actionDelete()
156 {
157     mode_cut = false;
158     mode_copy = false;
159     if(QMessageBox::Yes == QMessageBox::warning(this, tr("Deleting file")
160                             ,tr("You are about to delete %1 file(s).\nAre you sure you want to continue?")
161                                 .arg(this->selectedIndexes().count())
162                             , QMessageBox::Yes, QMessageBox::No)) {
163         fileSystemModel->setReadOnly(false);
164         selectedFiles = this->selectedIndexes();
165         //delete files until filelist empty or error occured
166         while(!selectedFiles.isEmpty()) {
167             if(fileSystemModel->remove(selectedFiles.first())) {
168                 selectedFiles.removeFirst();
169             } else {
170                 QMessageBox::critical(this,tr("Error!")
171                                       ,tr("Deleting file %1 failed")
172                                         .arg(fileSystemModel->fileName(selectedFiles.first()))
173                                       ,QMessageBox::Ok);
174                 break;
175             }
176         }
177         fileSystemModel->setReadOnly(true);
178         this->clearSelection();
179     }
180     setSelectMode(false);
181 }
182
183 /**
184   @return Current directory shown
185   */
186 QString FileListWidget::getPath()
187 {
188     return currentDir.absolutePath();
189 }
190
191 /**
192   Changes current directory
193   @param path directory to change to
194   */
195 void FileListWidget::changePath(QString path)
196 {
197     currentDir.cd(path);
198     QString newPath = currentDir.absolutePath();
199     fileSystemModel->setRootPath(newPath);
200     this->clearSelection();
201     this->setRootIndex(fileSystemModel->index(newPath));
202     emit pathChanged(newPath);
203     setSelectMode(false);
204 }
205
206 /**
207   Equivalent to changePath("..")
208   */
209 void FileListWidget::changePathUp()
210 {
211     changePath("..");
212 }
213
214 void FileListWidget::handleItemActivation(QModelIndex index)
215 {
216     if(!select) {
217         QFileInfo file = fileSystemModel->fileInfo(index);
218         if(file.isDir()) {
219             changePath(file.absoluteFilePath());
220         } else if(file.isExecutable()) {
221             // Make process
222             QProcess::startDetached(file.absoluteFilePath());
223         } else {
224 #ifdef Q_WS_MAEMO_5 // Uses native file opening method
225             //TODO: find better solution for this, maybe get fixed in Qt
226             DBusConnection* conn;
227             conn = dbus_bus_get(DBUS_BUS_SESSION, 0);
228             hildon_mime_open_file(conn, QUrl::fromLocalFile(file.absoluteFilePath()).toEncoded().constData());
229 #else
230             /*
231             Not working with maemo5.
232             Uses hildon_uri_open function from
233             libhildonmime which should work,
234             but all files opened in browser.
235             */
236             QDesktopServices::openUrl(QUrl::fromLocalFile(file.absoluteFilePath()));
237 #endif
238         }
239     }
240     setSelectMode(false);
241 }
242 /**
243   @param mode true activates file selection
244   */
245 void FileListWidget::setSelectMode(bool mode)
246 {
247     if(mode)
248         this->setSelectionMode(QAbstractItemView::ExtendedSelection);
249     else
250         this->setSelectionMode(QAbstractItemView::SingleSelection);
251     select = mode;
252 }
253
254 /**
255   Opens native bluetooth dialog to choose receiving device and sends selected files there.
256   */
257 void FileListWidget::actionSendFiles()
258 {
259 #ifdef Q_WS_MAEMO_5
260     // Create list of file urls
261     QStringList files;
262     QFileInfo file;
263     foreach(QModelIndex index, this->selectedIndexes()) {
264         file = fileSystemModel->fileInfo(index);
265         if(file.isDir()) {
266             QMessageBox::warning(this,
267                                      tr("Sending files"),
268                                      tr("Sending directories not supported"),
269                                      QMessageBox::Cancel);
270             return;
271         }
272         files.append(QUrl::fromLocalFile(file.absoluteFilePath()).toString());
273     }
274
275     // Make dbuscall to send files
276     QDBusInterface interface("com.nokia.bt_ui", "/com/nokia/bt_ui", "com.nokia.bt_ui",QDBusConnection::systemBus());
277     interface.call(QDBus::Block, "show_send_file_dlg", files);
278
279 #else
280     QMessageBox::information(this,
281                              tr("Sending files"),
282                              tr("Only in maemo5 for now"),
283                              QMessageBox::Cancel);
284 #endif
285     setSelectMode(false);
286 }
287