Diffstat (limited to 'noncore/unsupported/tabmanager/tabmanager.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/unsupported/tabmanager/tabmanager.cpp | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/noncore/unsupported/tabmanager/tabmanager.cpp b/noncore/unsupported/tabmanager/tabmanager.cpp new file mode 100644 index 0000000..85e5814 --- a/dev/null +++ b/noncore/unsupported/tabmanager/tabmanager.cpp | |||
@@ -0,0 +1,510 @@ | |||
1 | #include "tabmanager.h" | ||
2 | #include "app.h" | ||
3 | #include "wait.h" | ||
4 | #include "tabapplnk.h" | ||
5 | |||
6 | #include <opie2/odebug.h> | ||
7 | |||
8 | #include <qpe/applnk.h> | ||
9 | #include <qdir.h> | ||
10 | #include <qfile.h> | ||
11 | #include <qtextstream.h> | ||
12 | #include <qlistview.h> | ||
13 | #include <qheader.h> | ||
14 | #include <qcombobox.h> | ||
15 | #include <qlineedit.h> | ||
16 | #include <qlabel.h> | ||
17 | #include <qmessagebox.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <qpe/qcopenvelope_qws.h> | ||
20 | #include <qpe/qpeapplication.h> | ||
21 | #include <qpe/resource.h> | ||
22 | |||
23 | |||
24 | #define HOME_APP_DIR QPEApplication::qpeDir()+"apps" | ||
25 | #define HOME_APP_INSTALL_DIR "/usr/lib/ipkg/info" | ||
26 | #define NEW_FOLDER "EmptyTab" | ||
27 | #define NEW_APPLICATION "NewApp" | ||
28 | #define APPLICATION_EXTENSION ".desktop" | ||
29 | #define APPLICATION_EXTENSION_LENGTH 8 | ||
30 | |||
31 | /** | ||
32 | * Constructor. Sets up signals. Performs initial scan of applications | ||
33 | * and tabs | ||
34 | */ | ||
35 | TabManager::TabManager( QWidget* parent, const char* name):TabManagerBase(parent, name), changed(false), application(NULL){ | ||
36 | rescanFolder(HOME_APP_DIR); | ||
37 | |||
38 | // Connect the signals and slots | ||
39 | connect(tabList, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(editItem(QListViewItem*))); | ||
40 | (tabList->header())->hide(); | ||
41 | connect(tabList, SIGNAL(moveItem(QListViewItem*,QListViewItem*)), this, SLOT(moveApplication(QListViewItem*,QListViewItem*))); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * If anything in the tab's have been changed then update the system or alert | ||
46 | * the user. | ||
47 | */ | ||
48 | TabManager::~TabManager(){ | ||
49 | if(changed){ | ||
50 | // Prompt. | ||
51 | //int answer = QMessageBox::warning(this, "Message", "Should your desktop be","Yes", "Cancel", 0, 1 ); | ||
52 | //if (answer) | ||
53 | // return; | ||
54 | QCopEnvelope e("QPE/System", "linkChanged(QString)"); | ||
55 | QString link; //we'll just send an empty string | ||
56 | e << link; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Scans root directory for any tabs or applications. Will recursivly go down, | ||
62 | * but will not follow symlinks. | ||
63 | * @param directory - the directory to look in. | ||
64 | * @param parent - the parent to place any new tabs or apps into. If parent is | ||
65 | * NULL then the item is a tab and should be placed as a child of the window. | ||
66 | */ | ||
67 | void TabManager::rescanFolder(QString directory, QListViewItem* parent){ | ||
68 | //odebug << QString("rescanFolder: ") + directory.latin1() << oendl; | ||
69 | |||
70 | QDir d; | ||
71 | d.setPath(directory); | ||
72 | // Show hidden files for .directories | ||
73 | d.setFilter( QDir::Files | QDir::Hidden | QDir::Dirs); | ||
74 | |||
75 | const QFileInfoList *list = d.entryInfoList(); | ||
76 | QFileInfoListIterator it( *list ); // create list iterator | ||
77 | QFileInfo *fi; // pointer for traversing | ||
78 | |||
79 | while ( (fi=it.current()) ) { // for each file... | ||
80 | // If it is a dir and not .. or . then add it as a tab and go down. | ||
81 | if(fi->isDir()){ | ||
82 | if(fi->fileName() != ".." && fi->fileName() != ".") { | ||
83 | QListViewItem* newItem; | ||
84 | if(!parent) | ||
85 | newItem = new QListViewItem(tabList, fi->fileName()); | ||
86 | else | ||
87 | newItem = new QListViewItem(parent, fi->fileName()); | ||
88 | itemList.insert(newItem, directory + "/" + fi->fileName() + "/.directory" ); | ||
89 | rescanFolder(directory + "/" + fi->fileName(), newItem); | ||
90 | } | ||
91 | } | ||
92 | else{ | ||
93 | // it is a file, if not a .directory add to parent. | ||
94 | |||
95 | // Change parents name and icon to reflect icon. | ||
96 | if(fi->fileName() == ".directory"){ | ||
97 | AppLnk app(directory + "/" + fi->fileName()); | ||
98 | if(parent){ | ||
99 | parent->setPixmap(0,app.pixmap()); | ||
100 | parent->setText(0, app.name()); | ||
101 | } | ||
102 | } | ||
103 | else{ | ||
104 | // Add any desktop files found. | ||
105 | QListViewItem* newItem; | ||
106 | if(directory != HOME_APP_DIR){ | ||
107 | if(!parent) | ||
108 | newItem = new QListViewItem(tabList, fi->fileName()); | ||
109 | else | ||
110 | newItem = new QListViewItem(parent, fi->fileName()); | ||
111 | if(fi->fileName().right(APPLICATION_EXTENSION_LENGTH) == APPLICATION_EXTENSION){ | ||
112 | AppLnk app(directory + "/" + fi->fileName()); | ||
113 | newItem->setPixmap(0,app.pixmap()); | ||
114 | newItem->setText(0, app.name()); | ||
115 | itemList.insert(newItem, directory + "/" + fi->fileName()); | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | ++it; // goto next list element | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * Create a new blank Tab. | ||
126 | * Create a physical folder with .directory file | ||
127 | * Create a item on the list | ||
128 | */ | ||
129 | void TabManager::newFolder(){ | ||
130 | QDir r; | ||
131 | r.mkdir(QString(HOME_APP_DIR) + "/" + NEW_FOLDER); | ||
132 | system((QString("echo [Desktop Entry] | cat >> ") + HOME_APP_DIR + "/" + NEW_FOLDER "/.directory").latin1()); | ||
133 | system((QString("echo Name=" NEW_FOLDER " | cat >> ") + HOME_APP_DIR + "/" + NEW_FOLDER "/.directory").latin1()); | ||
134 | |||
135 | QString homeLocation = QString(HOME_APP_DIR) + "/" + NEW_FOLDER + "/.directory"; | ||
136 | QListViewItem *newItem = new QListViewItem(tabList, NEW_FOLDER); | ||
137 | itemList.insert(newItem, homeLocation ); | ||
138 | |||
139 | // We have changed something. | ||
140 | changed = true; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * Create a new blank application | ||
145 | * Make sure a tab is selected | ||
146 | * create physical file | ||
147 | * fill file with default information (entry, name, type). | ||
148 | */ | ||
149 | void TabManager::newApplication(){ | ||
150 | QListViewItem *item = tabList->currentItem(); | ||
151 | if(!item || item->parent()) | ||
152 | return; | ||
153 | |||
154 | QString parentDir = itemList[item].mid(0,itemList[item].length()-11); | ||
155 | QString homeLocation = parentDir + "/" NEW_APPLICATION APPLICATION_EXTENSION; | ||
156 | system((QString("echo [Desktop Entry] | cat >> ") + homeLocation).latin1()); | ||
157 | system((QString("echo Name=" NEW_APPLICATION " | cat >> ") + homeLocation).latin1()); | ||
158 | int slash = parentDir.findRev('/', -1); | ||
159 | QString folderName = parentDir.mid(slash+1, parentDir.length()); | ||
160 | |||
161 | system((QString("echo Type=") + folderName + " | cat >> " + homeLocation).latin1()); | ||
162 | |||
163 | // Insert into the tree | ||
164 | QListViewItem *newItem = new QListViewItem(item, NEW_APPLICATION); | ||
165 | itemList.insert(newItem, homeLocation ); | ||
166 | |||
167 | // We have changed something. | ||
168 | changed = true; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Remove the item. | ||
173 | * Check if we can | ||
174 | * Prompt user | ||
175 | * Delete physical file (Dir, remove .dir, then dir. File, remove file) | ||
176 | * Remove from installer if need too. | ||
177 | */ | ||
178 | void TabManager::removeItem(){ | ||
179 | // Make sure we can delete | ||
180 | QListViewItem *item = tabList->currentItem(); | ||
181 | if(!item) | ||
182 | return; | ||
183 | if(item->childCount() > 0){ | ||
184 | QMessageBox::critical(this, tr("Message"), tr("Can't remove with applications\nstill in the group."), tr("Ok") ); | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | // Prompt. | ||
189 | int answer = QMessageBox::warning(this, tr("Message"), tr("Are you sure you want to delete?"), tr("Yes"), tr("Cancel"), 0, 1 ); | ||
190 | if (answer) | ||
191 | return; | ||
192 | |||
193 | bool removeSuccessful = true; | ||
194 | QString location = itemList[item]; | ||
195 | // Remove file (.directory in a Directory case) | ||
196 | if(!QFile::remove(location)) | ||
197 | removeSuccessful = false; | ||
198 | |||
199 | // Remove directory | ||
200 | if(item->parent() == NULL){ | ||
201 | // Remove .directory file string | ||
202 | location = location.mid(0,location.length()-10); | ||
203 | QDir dir; | ||
204 | if(!dir.rmdir(location)) | ||
205 | removeSuccessful = false; | ||
206 | else | ||
207 | removeSuccessful = true; | ||
208 | } | ||
209 | |||
210 | // If removing failed. | ||
211 | if(!removeSuccessful){ | ||
212 | odebug << (QString("removeItem: ") + location).latin1() << oendl; | ||
213 | QMessageBox::critical(this, tr("Message"), tr("Can't remove."), tr("Ok") ); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | // Remove from the installer so it wont fail. | ||
218 | // Don't need to do this sense the current install uses rm -f so no error | ||
219 | |||
220 | // Remove from the gui list. | ||
221 | itemList.remove(item); | ||
222 | if(item->parent()) | ||
223 | item->parent()->takeItem(item); | ||
224 | delete item; | ||
225 | |||
226 | // We have changed something. | ||
227 | changed = true; | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * Helper function. Edits the current item. | ||
232 | * calls editItem with the currently selected item. | ||
233 | */ | ||
234 | void TabManager::editCurrentItem(){ | ||
235 | editItem(tabList->currentItem()); | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * Edit the item that is passed in. | ||
240 | * Show application dialog and if anything changed | ||
241 | * @param item the item to edit. | ||
242 | */ | ||
243 | void TabManager::editItem( QListViewItem * item){ | ||
244 | if(!item) | ||
245 | return; | ||
246 | |||
247 | TabAppLnk app(itemList[item]); | ||
248 | if(!app.isValid()){ | ||
249 | odebug << QString("editItem: Not a valid applnk file: ") + itemList[item].latin1() << oendl; | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | // Fill with all of the icons | ||
254 | if(!application){ | ||
255 | Wait waitDialog(this, "Wait dialog"); | ||
256 | waitDialog.waitLabel->setText(tr("Gathering icons...")); | ||
257 | waitDialog.show(); | ||
258 | qApp->processEvents(); | ||
259 | application = new AppEdit(this, "Application edit", true); | ||
260 | |||
261 | QDir d(QPEApplication::qpeDir() + "pics/"); | ||
262 | d.setFilter( QDir::Files); | ||
263 | |||
264 | const QFileInfoList *list = d.entryInfoList(); | ||
265 | QFileInfoListIterator it( *list ); // create list iterator | ||
266 | QFileInfo *fi; // pointer for traversing | ||
267 | |||
268 | while ( (fi=it.current()) ) { // for each file... | ||
269 | QString fileName = fi->fileName(); | ||
270 | if(fileName.right(4) == ".png"){ | ||
271 | fileName = fileName.mid(0,fileName.length()-4); | ||
272 | QPixmap imageOfFile(Resource::loadPixmap(fileName)); | ||
273 | QImage foo = imageOfFile.convertToImage(); | ||
274 | foo = foo.smoothScale(16,16); | ||
275 | imageOfFile.convertFromImage(foo); | ||
276 | application->iconLineEdit->insertItem(imageOfFile,fileName); | ||
277 | } | ||
278 | //odebug << fi->fileName().latin1() << oendl; | ||
279 | ++it; | ||
280 | } | ||
281 | waitDialog.hide(); | ||
282 | } | ||
283 | int pixmap = -1; | ||
284 | QString pixmapText = app.pixmapString(); | ||
285 | QComboBox *f = application->iconLineEdit; | ||
286 | for(int i = 0; i < application->iconLineEdit->count(); i++){ | ||
287 | if(f->text(i) == pixmapText){ | ||
288 | pixmap = i; | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | if(pixmap != -1) | ||
293 | application->iconLineEdit->setCurrentItem(pixmap); | ||
294 | else if(pixmapText.isEmpty()){ | ||
295 | application->iconLineEdit->setCurrentItem(0); | ||
296 | } | ||
297 | else{ | ||
298 | QPixmap imageOfFile(Resource::loadPixmap(pixmapText)); | ||
299 | QImage foo = imageOfFile.convertToImage(); | ||
300 | foo = foo.smoothScale(16,16); | ||
301 | imageOfFile.convertFromImage(foo); | ||
302 | application->iconLineEdit->insertItem(imageOfFile,pixmapText,0); | ||
303 | application->iconLineEdit->setCurrentItem(0); | ||
304 | } | ||
305 | |||
306 | application->nameLineEdit->setText(app.name()); | ||
307 | application->execLineEdit->setText(app.exec()); | ||
308 | application->commentLineEdit->setText(app.comment()); | ||
309 | |||
310 | if(item->parent() == NULL){ | ||
311 | application->execLineEdit->setEnabled(false); | ||
312 | application->TextLabel3->setEnabled(false); | ||
313 | application->setCaption(tr("Tab")); | ||
314 | } | ||
315 | else{ | ||
316 | application->execLineEdit->setEnabled(true); | ||
317 | application->TextLabel3->setEnabled(true); | ||
318 | application->setCaption(tr("Application")); | ||
319 | } | ||
320 | |||
321 | // Only do somthing if they hit OK | ||
322 | application->showMaximized(); | ||
323 | if(application->exec() == 0) | ||
324 | return; | ||
325 | |||
326 | // If nothing has changed exit (hmmm why did they hit ok?) | ||
327 | if(app.name() == application->nameLineEdit->text() && | ||
328 | app.pixmapString() == application->iconLineEdit->currentText() && | ||
329 | app.comment() == application->commentLineEdit->text() && | ||
330 | app.exec() == application->execLineEdit->text()) | ||
331 | return; | ||
332 | |||
333 | // Change the applnk file | ||
334 | QString oldName = app.name(); | ||
335 | app.setName(application->nameLineEdit->text()); | ||
336 | app.setIcon(application->iconLineEdit->currentText()); | ||
337 | app.setComment(application->commentLineEdit->text()); | ||
338 | app.setExec(application->execLineEdit->text()); | ||
339 | if(!app.writeLink()){ | ||
340 | QMessageBox::critical(this, tr("Message"), "Can't save.", tr("Ok") ); | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | // Update the gui icon and name | ||
345 | item->setText(0,app.name()); | ||
346 | item->setPixmap(0,app.pixmap()); | ||
347 | |||
348 | // We have changed something. | ||
349 | changed = true; | ||
350 | |||
351 | // If we were dealing with a new folder or new application change | ||
352 | // the file names. Also change the item location in itemList | ||
353 | if(oldName == NEW_FOLDER){ | ||
354 | QDir r; | ||
355 | QString oldName = itemList[item]; | ||
356 | oldName = oldName.mid(0,oldName.length()-11); | ||
357 | QString newName = oldName.mid(0,oldName.length()-9); | ||
358 | newName = newName + "/" + app.name(); | ||
359 | r.rename(oldName, newName); | ||
360 | itemList.remove(item); | ||
361 | itemList.insert(item, newName + "/.directory" ); | ||
362 | } | ||
363 | else if(oldName == NEW_APPLICATION){ | ||
364 | if(!item->parent()) | ||
365 | return; | ||
366 | QString parentDir = itemList[item->parent()]; | ||
367 | QDir r; | ||
368 | QString oldName = itemList[item]; | ||
369 | QString newName = oldName.mid(0, parentDir.length()-10); | ||
370 | newName = newName + app.name() + APPLICATION_EXTENSION; | ||
371 | r.rename(oldName, newName); | ||
372 | itemList.remove(item); | ||
373 | itemList.insert(item, newName); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * Move an application from one directory to another. | ||
379 | * Move in the gui, move in the applnk file, move in the installer. | ||
380 | * @param item the application to move | ||
381 | * @pearam newGroup the new parent of this application | ||
382 | */ | ||
383 | void TabManager::moveApplication(QListViewItem *item, QListViewItem *newGroup){ | ||
384 | // Can we even move it? | ||
385 | if(!item || !item->parent() || newGroup->parent()) | ||
386 | return; | ||
387 | if(item->parent() == newGroup) | ||
388 | return; | ||
389 | |||
390 | // Get the new folder, new file name, | ||
391 | QString newFolder = itemList[newGroup]; | ||
392 | newFolder = newFolder.mid(0,newFolder.length()-11); | ||
393 | int slash = newFolder.findRev('/', -1); | ||
394 | QString folderName = newFolder.mid(slash+1, newFolder.length()); | ||
395 | |||
396 | QString desktopFile = itemList[item]; | ||
397 | slash = desktopFile.findRev('/', -1); | ||
398 | desktopFile = desktopFile.mid(slash, desktopFile.length()); | ||
399 | newFolder = newFolder + desktopFile; | ||
400 | |||
401 | // Move file | ||
402 | QDir r; | ||
403 | if(!r.rename(itemList[item], newFolder)){ | ||
404 | QMessageBox::critical(this, tr("Message"), "Can't move application.", tr("Ok") ); | ||
405 | return; | ||
406 | } | ||
407 | //odebug << (QString("moveApplication: ") + itemList[item]).latin1() << oendl; | ||
408 | //odebug << (QString("moveApplication: ") + newFolder).latin1() << oendl; | ||
409 | |||
410 | // Move in the gui | ||
411 | item->parent()->takeItem(item); | ||
412 | newGroup->insertItem(item); | ||
413 | newGroup->setOpen(true); | ||
414 | |||
415 | // Move file in the installer | ||
416 | QString installedAppFile; | ||
417 | if(findInstalledApplication(desktopFile, installedAppFile)) | ||
418 | swapInstalledLocation(installedAppFile, desktopFile, newFolder); | ||
419 | else | ||
420 | odebug << "moveApplication: No installed app found for dekstop file" << oendl; | ||
421 | |||
422 | // Move application type | ||
423 | AppLnk app(newFolder); | ||
424 | app.setType(folderName); | ||
425 | app.writeLink(); | ||
426 | |||
427 | // Move in our internal list | ||
428 | itemList.remove(item); | ||
429 | itemList.insert(item, newFolder); | ||
430 | |||
431 | // We have changed something. | ||
432 | changed = true; | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * File the installed application that has this desktop file. | ||
437 | * Go through each file in HOME_APP_INSTALL_DIR and see if it contains desktop | ||
438 | * file | ||
439 | * @param desktopFile - the .desktop file to search for [foo.desktop] | ||
440 | * @param installedAppFile - location of the app install list | ||
441 | * @return true if successful, false if file not found. | ||
442 | */ | ||
443 | bool TabManager::findInstalledApplication(QString desktopFile, QString &installedAppFile){ | ||
444 | |||
445 | QDir d; | ||
446 | d.setPath(HOME_APP_INSTALL_DIR); | ||
447 | d.setFilter( QDir::Files ); | ||
448 | |||
449 | const QFileInfoList *list = d.entryInfoList(); | ||
450 | QFileInfoListIterator it( *list ); // create list iterator | ||
451 | QFileInfo *fi; // pointer for traversing | ||
452 | |||
453 | while ( (fi=it.current()) ) { // for each file... | ||
454 | QFile file(QString(HOME_APP_INSTALL_DIR) + "/" + fi->fileName()); | ||
455 | if ( file.open(IO_ReadOnly) ) { // file opened successfully | ||
456 | QTextStream stream( &file ); // use a text stream | ||
457 | QString line; | ||
458 | while ( !stream.eof() ) { // until end of file... | ||
459 | line = stream.readLine(); // line of text excluding '\n' | ||
460 | if(line.contains(desktopFile)){ | ||
461 | installedAppFile = QString(HOME_APP_INSTALL_DIR) + "/" + fi->fileName(); | ||
462 | file.close(); | ||
463 | return true; | ||
464 | } | ||
465 | } | ||
466 | file.close(); | ||
467 | } | ||
468 | else | ||
469 | odebug << (QString("findInstalledApplication: Can't open file") + HOME_APP_INSTALL_DIR + "/" + fi->fileName()).latin1() << oendl; | ||
470 | ++it; // goto next list element | ||
471 | } | ||
472 | return false; | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * Open a file and replace a file containing the old desktop file with the new. | ||
477 | * @param installedAppFile application installed list | ||
478 | * @param desktopFile old .desktop file | ||
479 | * @param newLocation new .desktop file | ||
480 | */ | ||
481 | void TabManager::swapInstalledLocation( QString installedAppFile, QString desktopFile, QString newLocation ){ | ||
482 | QFile file(installedAppFile); | ||
483 | if ( !file.open(IO_ReadOnly) ){ | ||
484 | odebug << QString("swapInstalledLocation: Can't edit file: %1").arg(installedAppFile).latin1() << oendl; | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | QTextStream stream( &file ); // use a text stream | ||
489 | QString allLines; | ||
490 | while ( !stream.eof() ) { // until end of file... | ||
491 | QString line = stream.readLine(); // line of text excluding '\n' | ||
492 | if(line.contains(desktopFile)) | ||
493 | allLines += newLocation; | ||
494 | else | ||
495 | allLines += line; | ||
496 | allLines += '\n'; | ||
497 | } | ||
498 | file.close(); | ||
499 | |||
500 | if ( !file.open(IO_ReadWrite) ){ | ||
501 | odebug << QString("swapInstalledLocation: Can't edit file: %1").arg(installedAppFile).latin1() << oendl; | ||
502 | return; | ||
503 | } | ||
504 | QTextStream streamOut( &file ); | ||
505 | streamOut << allLines; | ||
506 | file.close(); | ||
507 | } | ||
508 | |||
509 | // tabmanager.cpp | ||
510 | |||