]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphin.cpp
Fix i18n
[dolphin.git] / src / dolphin.cpp
1 /***************************************************************************
2 * Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at> *
3 * Copyright (C) 2006 by Stefan Monov <logixoul@gmail.com> *
4 * Copyright (C) 2006 by Cvetoslav Ludmiloff <ludmiloff@gmail.com> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
21
22 #include "dolphin.h"
23
24 #include <assert.h>
25
26 #include <kactioncollection.h>
27 #include <ktoggleaction.h>
28 #include <kbookmarkmanager.h>
29 #include <kglobal.h>
30 #include <kpropertiesdialog.h>
31 #include <kicon.h>
32 #include <kiconloader.h>
33 #include <kdeversion.h>
34 #include <kstatusbar.h>
35 #include <kio/netaccess.h>
36 #include <kfiledialog.h>
37 #include <kconfig.h>
38 #include <kurl.h>
39 #include <kstdaccel.h>
40 #include <kaction.h>
41 #include <kstdaction.h>
42 #include <kmenu.h>
43 #include <kio/renamedlg.h>
44 #include <kinputdialog.h>
45 #include <kshell.h>
46 #include <kdesktopfile.h>
47 #include <kstandarddirs.h>
48 #include <kprotocolinfo.h>
49 #include <kmessagebox.h>
50 #include <kservice.h>
51 #include <kstandarddirs.h>
52 #include <krun.h>
53 #include <klocale.h>
54
55 #include <qclipboard.h>
56 #include <q3dragobject.h>
57 //Added by qt3to4:
58 #include <Q3ValueList>
59 #include <QCloseEvent>
60 #include <QSplitter>
61
62 #include "urlnavigator.h"
63 #include "viewpropertiesdialog.h"
64 #include "viewproperties.h"
65 #include "dolphinsettings.h"
66 #include "dolphinsettingsdialog.h"
67 #include "dolphinstatusbar.h"
68 #include "undomanager.h"
69 #include "progressindicator.h"
70 #include "dolphinsettings.h"
71 #include "sidebar.h"
72 #include "sidebarsettings.h"
73 #include "generalsettings.h"
74
75 Dolphin& Dolphin::mainWin()
76 {
77 static Dolphin* instance = 0;
78 if (instance == 0) {
79 instance = new Dolphin();
80 instance->init();
81 }
82 return *instance;
83 }
84
85 Dolphin::~Dolphin()
86 {
87 }
88
89 void Dolphin::setActiveView(DolphinView* view)
90 {
91 assert((view == m_view[PrimaryIdx]) || (view == m_view[SecondaryIdx]));
92 if (m_activeView == view) {
93 return;
94 }
95
96 m_activeView = view;
97
98 updateHistory();
99 updateEditActions();
100 updateViewActions();
101 updateGoActions();
102
103 setCaption(m_activeView->url().fileName());
104
105 emit activeViewChanged();
106 }
107
108 void Dolphin::dropUrls(const KUrl::List& urls,
109 const KUrl& destination)
110 {
111 int selectedIndex = -1;
112
113 /* KDE4-TODO
114 const ButtonState keyboardState = KApplication::keyboardMouseState();
115 const bool shiftPressed = (keyboardState & ShiftButton) > 0;
116 const bool controlPressed = (keyboardState & ControlButton) > 0;
117
118
119
120 if (shiftPressed && controlPressed) {
121 // shortcut for 'Linke Here' is used
122 selectedIndex = 2;
123 }
124 else if (controlPressed) {
125 // shortcut for 'Copy Here' is used
126 selectedIndex = 1;
127 }
128 else if (shiftPressed) {
129 // shortcut for 'Move Here' is used
130 selectedIndex = 0;
131 }
132 else*/ {
133 // no shortcut is used, hence open a popup menu
134 KMenu popup(this);
135
136 popup.insertItem(SmallIcon("goto"), i18n("&Move Here") + "\t" /* KDE4-TODO: + KKey::modFlagLabel(KKey::SHIFT)*/, 0);
137 popup.insertItem(SmallIcon("editcopy"), i18n( "&Copy Here" ) /* KDE4-TODO + "\t" + KKey::modFlagLabel(KKey::CTRL)*/, 1);
138 popup.insertItem(i18n("&Link Here") /* KDE4-TODO + "\t" + KKey::modFlagLabel((KKey::ModFlag)(KKey::CTRL|KKey::SHIFT)) */, 2);
139 popup.insertSeparator();
140 popup.insertItem(SmallIcon("stop"), i18n("Cancel"), 3);
141 popup.setAccel(i18n("Escape"), 3);
142
143 /* KDE4-TODO: selectedIndex = popup.exec(QCursor::pos()); */
144 popup.exec(QCursor::pos());
145 selectedIndex = 0; // KD4-TODO: use QAction instead of switch below
146 }
147
148 if (selectedIndex < 0) {
149 return;
150 }
151
152 switch (selectedIndex) {
153 case 0: {
154 // 'Move Here' has been selected
155 updateViewProperties(urls);
156 moveUrls(urls, destination);
157 break;
158 }
159
160 case 1: {
161 // 'Copy Here' has been selected
162 updateViewProperties(urls);
163 copyUrls(urls, destination);
164 break;
165 }
166
167 case 2: {
168 // 'Link Here' has been selected
169 KIO::Job* job = KIO::link(urls, destination);
170 addPendingUndoJob(job, DolphinCommand::Link, urls, destination);
171 break;
172 }
173
174 default:
175 // 'Cancel' has been selected
176 break;
177 }
178 }
179
180 void Dolphin::refreshViews()
181 {
182 const bool split = DolphinSettings::instance().generalSettings()->splitView();
183 const bool isPrimaryViewActive = (m_activeView == m_view[PrimaryIdx]);
184 KUrl url;
185 for (int i = PrimaryIdx; i <= SecondaryIdx; ++i) {
186 if (m_view[i] != 0) {
187 url = m_view[i]->url();
188
189 // delete view instance...
190 m_view[i]->close();
191 m_view[i]->deleteLater();
192 m_view[i] = 0;
193 }
194
195 if (split || (i == PrimaryIdx)) {
196 // ... and recreate it
197 ViewProperties props(url);
198 m_view[i] = new DolphinView(m_splitter,
199 url,
200 props.viewMode(),
201 props.isShowHiddenFilesEnabled());
202 m_view[i]->show();
203 }
204 }
205
206 m_activeView = isPrimaryViewActive ? m_view[PrimaryIdx] : m_view[SecondaryIdx];
207 assert(m_activeView != 0);
208
209 updateViewActions();
210 emit activeViewChanged();
211 }
212
213 void Dolphin::slotHistoryChanged()
214 {
215 updateHistory();
216 }
217
218 void Dolphin::slotUrlChanged(const KUrl& url)
219 {
220 updateEditActions();
221 updateGoActions();
222 setCaption(url.fileName());
223 }
224
225 void Dolphin::slotUrlChangeRequest(const KUrl& url)
226 {
227 clearStatusBar();
228 m_activeView->setUrl(url);
229 }
230
231 void Dolphin::slotViewModeChanged()
232 {
233 updateViewActions();
234 }
235
236 void Dolphin::slotShowHiddenFilesChanged()
237 {
238 KToggleAction* showHiddenFilesAction =
239 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
240 showHiddenFilesAction->setChecked(m_activeView->isShowHiddenFilesEnabled());
241 }
242
243 void Dolphin::slotShowFilterBarChanged()
244 {
245 KToggleAction* showFilterBarAction =
246 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
247 showFilterBarAction->setChecked(m_activeView->isFilterBarVisible());
248 }
249
250 void Dolphin::slotSortingChanged(DolphinView::Sorting sorting)
251 {
252 KAction* action = 0;
253 switch (sorting) {
254 case DolphinView::SortByName:
255 action = actionCollection()->action("by_name");
256 break;
257 case DolphinView::SortBySize:
258 action = actionCollection()->action("by_size");
259 break;
260 case DolphinView::SortByDate:
261 action = actionCollection()->action("by_date");
262 break;
263 default:
264 break;
265 }
266
267 if (action != 0) {
268 KToggleAction* toggleAction = static_cast<KToggleAction*>(action);
269 toggleAction->setChecked(true);
270 }
271 }
272
273 void Dolphin::slotSortOrderChanged(Qt::SortOrder order)
274 {
275 KToggleAction* descending = static_cast<KToggleAction*>(actionCollection()->action("descending"));
276 const bool sortDescending = (order == Qt::Descending);
277 descending->setChecked(sortDescending);
278 }
279
280 void Dolphin::slotSelectionChanged()
281 {
282 updateEditActions();
283
284 assert(m_view[PrimaryIdx] != 0);
285 int selectedUrlsCount = m_view[PrimaryIdx]->selectedUrls().count();
286 if (m_view[SecondaryIdx] != 0) {
287 selectedUrlsCount += m_view[SecondaryIdx]->selectedUrls().count();
288 }
289
290 KAction* compareFilesAction = actionCollection()->action("compare_files");
291 compareFilesAction->setEnabled(selectedUrlsCount == 2);
292
293 m_activeView->updateStatusBar();
294
295 emit selectionChanged();
296 }
297
298 void Dolphin::closeEvent(QCloseEvent* event)
299 {
300 // KDE4-TODO
301 //KConfig* config = KGlobal::config();
302 //config->setGroup("General");
303 //config->writeEntry("First Run", false);
304
305 DolphinSettings& settings = DolphinSettings::instance();
306 GeneralSettings* generalSettings = settings.generalSettings();
307 generalSettings->setFirstRun(false);
308
309 SidebarSettings* sidebarSettings = settings.sidebarSettings();
310 const bool isSidebarVisible = (m_sidebar != 0);
311 sidebarSettings->setVisible(isSidebarVisible);
312 if (isSidebarVisible) {
313 sidebarSettings->setWidth(m_sidebar->width());
314 }
315
316 settings.save();
317
318 KMainWindow::closeEvent(event);
319 }
320
321 void Dolphin::saveProperties(KConfig* config)
322 {
323 config->setGroup("Primary view");
324 config->writeEntry("Url", m_view[PrimaryIdx]->url().url());
325 config->writeEntry("Editable Url", m_view[PrimaryIdx]->isUrlEditable());
326 if (m_view[SecondaryIdx] != 0) {
327 config->setGroup("Secondary view");
328 config->writeEntry("Url", m_view[SecondaryIdx]->url().url());
329 config->writeEntry("Editable Url", m_view[SecondaryIdx]->isUrlEditable());
330 }
331 }
332
333 void Dolphin::readProperties(KConfig* config)
334 {
335 config->setGroup("Primary view");
336 m_view[PrimaryIdx]->setUrl(config->readEntry("Url"));
337 m_view[PrimaryIdx]->setUrlEditable(config->readBoolEntry("Editable Url"));
338 if (config->hasGroup("Secondary view")) {
339 config->setGroup("Secondary view");
340 if (m_view[SecondaryIdx] == 0) {
341 toggleSplitView();
342 }
343 m_view[SecondaryIdx]->setUrl(config->readEntry("Url"));
344 m_view[SecondaryIdx]->setUrlEditable(config->readBoolEntry("Editable Url"));
345 }
346 else if (m_view[SecondaryIdx] != 0) {
347 toggleSplitView();
348 }
349 }
350
351 void Dolphin::createFolder()
352 {
353 // Parts of the following code have been taken
354 // from the class KonqPopupMenu located in
355 // libqonq/konq_popupmenu.h of Konqueror.
356 // (Copyright (C) 2000 David Faure <faure@kde.org>,
357 // Copyright (C) 2001 Holger Freyther <freyther@yahoo.com>)
358
359 clearStatusBar();
360
361 DolphinStatusBar* statusBar = m_activeView->statusBar();
362 const KUrl baseUrl(m_activeView->url());
363
364 QString name(i18n("New Folder"));
365 baseUrl.path(KUrl::AddTrailingSlash);
366
367
368 if (baseUrl.isLocalFile() && QFileInfo(baseUrl.path(KUrl::AddTrailingSlash) + name).exists()) {
369 name = KIO::RenameDlg::suggestName(baseUrl, i18n("New Folder"));
370 }
371
372 bool ok = false;
373 name = KInputDialog::getText(i18n("New Folder"),
374 i18n("Enter folder name:" ),
375 name,
376 &ok,
377 this);
378
379 if (!ok) {
380 // the user has pressed 'Cancel'
381 return;
382 }
383
384 assert(!name.isEmpty());
385
386 KUrl url;
387 if ((name[0] == '/') || (name[0] == '~')) {
388 url.setPath(KShell::tildeExpand(name));
389 }
390 else {
391 name = KIO::encodeFileName(name);
392 url = baseUrl;
393 url.addPath(name);
394 }
395 ok = KIO::NetAccess::mkdir(url, this);
396
397 // TODO: provide message type hint
398 if (ok) {
399 statusBar->setMessage(i18n("Created folder %1.",url.path()),
400 DolphinStatusBar::OperationCompleted);
401
402 DolphinCommand command(DolphinCommand::CreateFolder, KUrl::List(), url);
403 UndoManager::instance().addCommand(command);
404 }
405 else {
406 // Creating of the folder has been failed. Check whether the creating
407 // has been failed because a folder with the same name exists...
408 if (KIO::NetAccess::exists(url, true, this)) {
409 statusBar->setMessage(i18n("A folder named %1 already exists.",url.path()),
410 DolphinStatusBar::Error);
411 }
412 else {
413 statusBar->setMessage(i18n("Creating of folder %1 failed.",url.path()),
414 DolphinStatusBar::Error);
415 }
416
417 }
418 }
419
420 void Dolphin::createFile()
421 {
422 // Parts of the following code have been taken
423 // from the class KonqPopupMenu located in
424 // libqonq/konq_popupmenu.h of Konqueror.
425 // (Copyright (C) 2000 David Faure <faure@kde.org>,
426 // Copyright (C) 2001 Holger Freyther <freyther@yahoo.com>)
427
428 clearStatusBar();
429
430 // TODO: const Entry& entry = m_createFileTemplates[QString(sender->name())];
431 // should be enough. Anyway: the implemantation of [] does a linear search internally too.
432 KSortableList<CreateFileEntry, QString>::ConstIterator it = m_createFileTemplates.begin();
433 KSortableList<CreateFileEntry, QString>::ConstIterator end = m_createFileTemplates.end();
434
435 const QString senderName(sender()->name());
436 bool found = false;
437 CreateFileEntry entry;
438 while (!found && (it != end)) {
439 if ((*it).index() == senderName) {
440 entry = (*it).value();
441 found = true;
442 }
443 else {
444 ++it;
445 }
446 }
447
448 DolphinStatusBar* statusBar = m_activeView->statusBar();
449 if (!found || !QFile::exists(entry.templatePath)) {
450 statusBar->setMessage(i18n("Could not create file."), DolphinStatusBar::Error);
451 return;
452 }
453
454 // Get the source path of the template which should be copied.
455 // The source path is part of the Url entry of the desktop file.
456 const int pos = entry.templatePath.findRev('/');
457 QString sourcePath(entry.templatePath.left(pos + 1));
458 sourcePath += KDesktopFile(entry.templatePath, true).readPathEntry("Url");
459
460 QString name(i18n(entry.name.ascii()));
461 // Most entry names end with "..." (e. g. "HTML File..."), which is ok for
462 // menus but no good choice for a new file name -> remove the dots...
463 name.replace("...", QString::null);
464
465 // add the file extension to the name
466 name.append(sourcePath.right(sourcePath.length() - sourcePath.findRev('.')));
467
468 // Check whether a file with the current name already exists. If yes suggest automatically
469 // a unique file name (e. g. "HTML File" will be replaced by "HTML File_1").
470 const KUrl viewUrl(m_activeView->url());
471 const bool fileExists = viewUrl.isLocalFile() &&
472 QFileInfo(viewUrl.path(KUrl::AddTrailingSlash) + KIO::encodeFileName(name)).exists();
473 if (fileExists) {
474 name = KIO::RenameDlg::suggestName(viewUrl, name);
475 }
476
477 // let the user change the suggested file name
478 bool ok = false;
479 name = KInputDialog::getText(entry.name,
480 entry.comment,
481 name,
482 &ok,
483 this);
484 if (!ok) {
485 // the user has pressed 'Cancel'
486 return;
487 }
488
489 // before copying the template to the destination path check whether a file
490 // with the given name already exists
491 const QString destPath(viewUrl.pathOrUrl() + "/" + KIO::encodeFileName(name));
492 const KUrl destUrl(destPath);
493 if (KIO::NetAccess::exists(destUrl, false, this)) {
494 statusBar->setMessage(i18n("A file named %1 already exists.",name),
495 DolphinStatusBar::Error);
496 return;
497 }
498
499 // copy the template to the destination path
500 const KUrl sourceUrl(sourcePath);
501 KIO::CopyJob* job = KIO::copyAs(sourceUrl, destUrl);
502 job->setDefaultPermissions(true);
503 if (KIO::NetAccess::synchronousRun(job, this)) {
504 statusBar->setMessage(i18n("Created file %1.",name),
505 DolphinStatusBar::OperationCompleted);
506
507 KUrl::List list;
508 list.append(sourceUrl);
509 DolphinCommand command(DolphinCommand::CreateFile, list, destUrl);
510 UndoManager::instance().addCommand(command);
511
512 }
513 else {
514 statusBar->setMessage(i18n("Creating of file %1 failed.",name),
515 DolphinStatusBar::Error);
516 }
517 }
518
519 void Dolphin::rename()
520 {
521 clearStatusBar();
522 m_activeView->renameSelectedItems();
523 }
524
525 void Dolphin::moveToTrash()
526 {
527 clearStatusBar();
528 KUrl::List selectedUrls = m_activeView->selectedUrls();
529 KIO::Job* job = KIO::trash(selectedUrls);
530 addPendingUndoJob(job, DolphinCommand::Trash, selectedUrls, m_activeView->url());
531 }
532
533 void Dolphin::deleteItems()
534 {
535 clearStatusBar();
536
537 KUrl::List list = m_activeView->selectedUrls();
538 const uint itemCount = list.count();
539 assert(itemCount >= 1);
540
541 QString text;
542 if (itemCount > 1) {
543 text = i18n("Do you really want to delete the %1 selected items?",itemCount);
544 }
545 else {
546 const KUrl& url = list.first();
547 text = i18n("Do you really want to delete '%1'?",url.fileName());
548 }
549
550 const bool del = KMessageBox::warningContinueCancel(this,
551 text,
552 QString::null,
553 KGuiItem(i18n("Delete"), SmallIcon("editdelete"))
554 ) == KMessageBox::Continue;
555 if (del) {
556 KIO::Job* job = KIO::del(list);
557 connect(job, SIGNAL(result(KIO::Job*)),
558 this, SLOT(slotHandleJobError(KIO::Job*)));
559 connect(job, SIGNAL(result(KIO::Job*)),
560 this, SLOT(slotDeleteFileFinished(KIO::Job*)));
561 }
562 }
563
564 void Dolphin::properties()
565 {
566 const KFileItemList* sourceList = m_activeView->selectedItems();
567 if (sourceList == 0) {
568 return;
569 }
570
571 KFileItemList list;
572 KFileItemList::const_iterator it = sourceList->begin();
573 const KFileItemList::const_iterator end = sourceList->end();
574 KFileItem* item = 0;
575 while (it != end) {
576 list.append(item);
577 ++it;
578 }
579
580 new KPropertiesDialog(list, this);
581 }
582
583 void Dolphin::quit()
584 {
585 close();
586 }
587
588 void Dolphin::slotHandleJobError(KIO::Job* job)
589 {
590 if (job->error() != 0) {
591 m_activeView->statusBar()->setMessage(job->errorString(),
592 DolphinStatusBar::Error);
593 }
594 }
595
596 void Dolphin::slotDeleteFileFinished(KIO::Job* job)
597 {
598 if (job->error() == 0) {
599 m_activeView->statusBar()->setMessage(i18n("Delete operation completed."),
600 DolphinStatusBar::OperationCompleted);
601
602 // TODO: In opposite to the 'Move to Trash' operation in the class KFileIconView
603 // no rearranging of the item position is done when a file has been deleted.
604 // This is bypassed by reloading the view, but it might be worth to investigate
605 // deeper for the root of this issue.
606 m_activeView->reload();
607 }
608 }
609
610 void Dolphin::slotUndoAvailable(bool available)
611 {
612 KAction* undoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Undo));
613 if (undoAction != 0) {
614 undoAction->setEnabled(available);
615 }
616 }
617
618 void Dolphin::slotUndoTextChanged(const QString& text)
619 {
620 KAction* undoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Undo));
621 if (undoAction != 0) {
622 undoAction->setText(text);
623 }
624 }
625
626 void Dolphin::slotRedoAvailable(bool available)
627 {
628 KAction* redoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Redo));
629 if (redoAction != 0) {
630 redoAction->setEnabled(available);
631 }
632 }
633
634 void Dolphin::slotRedoTextChanged(const QString& text)
635 {
636 KAction* redoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Redo));
637 if (redoAction != 0) {
638 redoAction->setText(text);
639 }
640 }
641
642 void Dolphin::cut()
643 {
644 m_clipboardContainsCutData = true;
645 /* KDE4-TODO: Q3DragObject* data = new KUrlDrag(m_activeView->selectedUrls(),
646 widget());
647 QApplication::clipboard()->setData(data);*/
648 }
649
650 void Dolphin::copy()
651 {
652 m_clipboardContainsCutData = false;
653 /* KDE4-TODO:
654 Q3DragObject* data = new KUrlDrag(m_activeView->selectedUrls(),
655 widget());
656 QApplication::clipboard()->setData(data);*/
657 }
658
659 void Dolphin::paste()
660 {
661 /* KDE4-TODO:
662 QClipboard* clipboard = QApplication::clipboard();
663 QMimeSource* data = clipboard->data();
664 if (!KUrlDrag::canDecode(data)) {
665 return;
666 }
667
668 clearStatusBar();
669
670 KUrl::List sourceUrls;
671 KUrlDrag::decode(data, sourceUrls);
672
673 // per default the pasting is done into the current Url of the view
674 KUrl destUrl(m_activeView->url());
675
676 // check whether the pasting should be done into a selected directory
677 KUrl::List selectedUrls = m_activeView->selectedUrls();
678 if (selectedUrls.count() == 1) {
679 const KFileItem fileItem(S_IFDIR,
680 KFileItem::Unknown,
681 selectedUrls.first(),
682 true);
683 if (fileItem.isDir()) {
684 // only one item is selected which is a directory, hence paste
685 // into this directory
686 destUrl = selectedUrls.first();
687 }
688 }
689
690
691 updateViewProperties(sourceUrls);
692 if (m_clipboardContainsCutData) {
693 moveUrls(sourceUrls, destUrl);
694 m_clipboardContainsCutData = false;
695 clipboard->clear();
696 }
697 else {
698 copyUrls(sourceUrls, destUrl);
699 }*/
700 }
701
702 void Dolphin::updatePasteAction()
703 {
704 KAction* pasteAction = actionCollection()->action(KStdAction::stdName(KStdAction::Paste));
705 if (pasteAction == 0) {
706 return;
707 }
708
709 QString text(i18n("Paste"));
710 QClipboard* clipboard = QApplication::clipboard();
711 QMimeSource* data = clipboard->data();
712 /* KDE4-TODO:
713 if (KUrlDrag::canDecode(data)) {
714 pasteAction->setEnabled(true);
715
716 KUrl::List urls;
717 KUrlDrag::decode(data, urls);
718 const int count = urls.count();
719 if (count == 1) {
720 pasteAction->setText(i18n("Paste 1 File"));
721 }
722 else {
723 pasteAction->setText(i18n("Paste %1 Files").arg(count));
724 }
725 }
726 else {*/
727 pasteAction->setEnabled(false);
728 pasteAction->setText(i18n("Paste"));
729 //}
730
731 if (pasteAction->isEnabled()) {
732 KUrl::List urls = m_activeView->selectedUrls();
733 const uint count = urls.count();
734 if (count > 1) {
735 // pasting should not be allowed when more than one file
736 // is selected
737 pasteAction->setEnabled(false);
738 }
739 else if (count == 1) {
740 // Only one file is selected. Pasting is only allowed if this
741 // file is a directory.
742 const KFileItem fileItem(S_IFDIR,
743 KFileItem::Unknown,
744 urls.first(),
745 true);
746 pasteAction->setEnabled(fileItem.isDir());
747 }
748 }
749 }
750
751 void Dolphin::selectAll()
752 {
753 clearStatusBar();
754 m_activeView->selectAll();
755 }
756
757 void Dolphin::invertSelection()
758 {
759 clearStatusBar();
760 m_activeView->invertSelection();
761 }
762 void Dolphin::setIconsView()
763 {
764 m_activeView->setMode(DolphinView::IconsView);
765 }
766
767 void Dolphin::setDetailsView()
768 {
769 m_activeView->setMode(DolphinView::DetailsView);
770 }
771
772 void Dolphin::setPreviewsView()
773 {
774 m_activeView->setMode(DolphinView::PreviewsView);
775 }
776
777 void Dolphin::sortByName()
778 {
779 m_activeView->setSorting(DolphinView::SortByName);
780 }
781
782 void Dolphin::sortBySize()
783 {
784 m_activeView->setSorting(DolphinView::SortBySize);
785 }
786
787 void Dolphin::sortByDate()
788 {
789 m_activeView->setSorting(DolphinView::SortByDate);
790 }
791
792 void Dolphin::toggleSortOrder()
793 {
794 const Qt::SortOrder order = (m_activeView->sortOrder() == Qt::Ascending) ?
795 Qt::Descending :
796 Qt::Ascending;
797 m_activeView->setSortOrder(order);
798 }
799
800 void Dolphin::toggleSplitView()
801 {
802 if (m_view[SecondaryIdx] == 0) {
803 // create a secondary view
804 m_view[SecondaryIdx] = new DolphinView(m_splitter,
805 m_view[PrimaryIdx]->url(),
806 m_view[PrimaryIdx]->mode(),
807 m_view[PrimaryIdx]->isShowHiddenFilesEnabled());
808 m_view[SecondaryIdx]->show();
809 }
810 else {
811 // remove secondary view
812 if (m_activeView == m_view[PrimaryIdx]) {
813 m_view[SecondaryIdx]->close();
814 m_view[SecondaryIdx]->deleteLater();
815 m_view[SecondaryIdx] = 0;
816 setActiveView(m_view[PrimaryIdx]);
817 }
818 else {
819 // The secondary view is active, hence from the users point of view
820 // the content of the secondary view should be moved to the primary view.
821 // From an implementation point of view it is more efficient to close
822 // the primary view and exchange the internal pointers afterwards.
823 m_view[PrimaryIdx]->close();
824 m_view[PrimaryIdx]->deleteLater();
825 m_view[PrimaryIdx] = m_view[SecondaryIdx];
826 m_view[SecondaryIdx] = 0;
827 setActiveView(m_view[PrimaryIdx]);
828 }
829 }
830 }
831
832 void Dolphin::reloadView()
833 {
834 clearStatusBar();
835 m_activeView->reload();
836 }
837
838 void Dolphin::stopLoading()
839 {
840 }
841
842 void Dolphin::showHiddenFiles()
843 {
844 clearStatusBar();
845
846 const KToggleAction* showHiddenFilesAction =
847 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
848 const bool show = showHiddenFilesAction->isChecked();
849 m_activeView->setShowHiddenFilesEnabled(show);
850 }
851
852 void Dolphin::showFilterBar()
853 {
854 const KToggleAction* showFilterBarAction =
855 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
856 const bool show = showFilterBarAction->isChecked();
857 m_activeView->slotShowFilterBar(show);
858 }
859
860 void Dolphin::zoomIn()
861 {
862 m_activeView->zoomIn();
863 updateViewActions();
864 }
865
866 void Dolphin::zoomOut()
867 {
868 m_activeView->zoomOut();
869 updateViewActions();
870 }
871
872 void Dolphin::toggleEditLocation()
873 {
874 clearStatusBar();
875
876 KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
877
878 bool editOrBrowse = action->isChecked();
879 // action->setChecked(action->setChecked);
880 m_activeView->setUrlEditable(editOrBrowse);
881 }
882
883 void Dolphin::editLocation()
884 {
885 KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
886 action->setChecked(true);
887 m_activeView->setUrlEditable(true);
888 }
889
890 void Dolphin::adjustViewProperties()
891 {
892 clearStatusBar();
893 ViewPropertiesDialog dlg(m_activeView);
894 dlg.exec();
895 }
896
897 void Dolphin::goBack()
898 {
899 clearStatusBar();
900 m_activeView->goBack();
901 }
902
903 void Dolphin::goForward()
904 {
905 clearStatusBar();
906 m_activeView->goForward();
907 }
908
909 void Dolphin::goUp()
910 {
911 clearStatusBar();
912 m_activeView->goUp();
913 }
914
915 void Dolphin::goHome()
916 {
917 clearStatusBar();
918 m_activeView->goHome();
919 }
920
921 void Dolphin::openTerminal()
922 {
923 QString command("konsole --workdir \"");
924 command.append(m_activeView->url().path());
925 command.append('\"');
926
927 KRun::runCommand(command, "Konsole", "konsole");
928 }
929
930 void Dolphin::findFile()
931 {
932 KRun::run("kfind", m_activeView->url());
933 }
934
935 void Dolphin::compareFiles()
936 {
937 // The method is only invoked if exactly 2 files have
938 // been selected. The selected files may be:
939 // - both in the primary view
940 // - both in the secondary view
941 // - one in the primary view and the other in the secondary
942 // view
943 assert(m_view[PrimaryIdx] != 0);
944
945 KUrl urlA;
946 KUrl urlB;
947 KUrl::List urls = m_view[PrimaryIdx]->selectedUrls();
948
949 switch (urls.count()) {
950 case 0: {
951 assert(m_view[SecondaryIdx] != 0);
952 urls = m_view[SecondaryIdx]->selectedUrls();
953 assert(urls.count() == 2);
954 urlA = urls[0];
955 urlB = urls[1];
956 break;
957 }
958
959 case 1: {
960 urlA = urls[0];
961 assert(m_view[SecondaryIdx] != 0);
962 urls = m_view[SecondaryIdx]->selectedUrls();
963 assert(urls.count() == 1);
964 urlB = urls[0];
965 break;
966 }
967
968 case 2: {
969 urlA = urls[0];
970 urlB = urls[1];
971 break;
972 }
973
974 default: {
975 // may not happen: compareFiles may only get invoked if 2
976 // files are selected
977 assert(false);
978 }
979 }
980
981 QString command("kompare -c \"");
982 command.append(urlA.pathOrUrl());
983 command.append("\" \"");
984 command.append(urlB.pathOrUrl());
985 command.append('\"');
986 KRun::runCommand(command, "Kompare", "kompare");
987
988 }
989
990 void Dolphin::editSettings()
991 {
992 // TODO: make a static method for opening the settings dialog
993 DolphinSettingsDialog dlg;
994 dlg.exec();
995 }
996
997 void Dolphin::addUndoOperation(KIO::Job* job)
998 {
999 if (job->error() != 0) {
1000 slotHandleJobError(job);
1001 }
1002 else {
1003 const int id = job->progressId();
1004
1005 // set iterator to the executed command with the current id...
1006 Q3ValueList<UndoInfo>::Iterator it = m_pendingUndoJobs.begin();
1007 const Q3ValueList<UndoInfo>::Iterator end = m_pendingUndoJobs.end();
1008 bool found = false;
1009 while (!found && (it != end)) {
1010 if ((*it).id == id) {
1011 found = true;
1012 }
1013 else {
1014 ++it;
1015 }
1016 }
1017
1018 if (found) {
1019 DolphinCommand command = (*it).command;
1020 if (command.type() == DolphinCommand::Trash) {
1021 // To be able to perform an undo for the 'Move to Trash' operation
1022 // all source Urls must be updated with the trash Url. E. g. when moving
1023 // a file "test.txt" and a second file "test.txt" to the trash,
1024 // then the filenames in the trash are "0-test.txt" and "1-test.txt".
1025 QMap<QString, QString> metaData = job->metaData();
1026 KUrl::List newSourceUrls;
1027
1028 KUrl::List sourceUrls = command.source();
1029 KUrl::List::Iterator sourceIt = sourceUrls.begin();
1030 const KUrl::List::Iterator sourceEnd = sourceUrls.end();
1031
1032 while (sourceIt != sourceEnd) {
1033 QMap<QString, QString>::ConstIterator metaIt = metaData.find("trashUrl-" + (*sourceIt).path());
1034 if (metaIt != metaData.end()) {
1035 newSourceUrls.append(KUrl(metaIt.data()));
1036 }
1037 ++sourceIt;
1038 }
1039 command.setSource(newSourceUrls);
1040 }
1041
1042 UndoManager::instance().addCommand(command);
1043 m_pendingUndoJobs.erase(it);
1044
1045 DolphinStatusBar* statusBar = m_activeView->statusBar();
1046 switch (command.type()) {
1047 case DolphinCommand::Copy:
1048 statusBar->setMessage(i18n("Copy operation completed."),
1049 DolphinStatusBar::OperationCompleted);
1050 break;
1051 case DolphinCommand::Move:
1052 statusBar->setMessage(i18n("Move operation completed."),
1053 DolphinStatusBar::OperationCompleted);
1054 break;
1055 case DolphinCommand::Trash:
1056 statusBar->setMessage(i18n("Move to trash operation completed."),
1057 DolphinStatusBar::OperationCompleted);
1058 break;
1059 default:
1060 break;
1061 }
1062 }
1063 }
1064 }
1065
1066 void Dolphin::toggleSidebar()
1067 {
1068 if (m_sidebar == 0) {
1069 openSidebar();
1070 }
1071 else {
1072 closeSidebar();
1073 }
1074
1075 KToggleAction* sidebarAction = static_cast<KToggleAction*>(actionCollection()->action("sidebar"));
1076 sidebarAction->setChecked(m_sidebar != 0);
1077 }
1078
1079 void Dolphin::closeSidebar()
1080 {
1081 if (m_sidebar == 0) {
1082 // the sidebar has already been closed
1083 return;
1084 }
1085
1086 // store width of sidebar and remember that the sidebar has been closed
1087 SidebarSettings* settings = DolphinSettings::instance().sidebarSettings();
1088 settings->setVisible(false);
1089 settings->setWidth(m_sidebar->width());
1090
1091 m_sidebar->deleteLater();
1092 m_sidebar = 0;
1093 }
1094
1095 Dolphin::Dolphin() :
1096 KMainWindow(0, "Dolphin"),
1097 m_splitter(0),
1098 m_sidebar(0),
1099 m_activeView(0),
1100 m_clipboardContainsCutData(false)
1101 {
1102 m_view[PrimaryIdx] = 0;
1103 m_view[SecondaryIdx] = 0;
1104
1105 m_fileGroupActions.setAutoDelete(true);
1106
1107 // TODO: the following members are not used yet. See documentation
1108 // of Dolphin::linkGroupActions() and Dolphin::linkToDeviceActions()
1109 // in the header file for details.
1110 //m_linkGroupActions.setAutoDelete(true);
1111 //m_linkToDeviceActions.setAutoDelete(true);
1112 }
1113
1114 void Dolphin::init()
1115 {
1116 // Check whether Dolphin runs the first time. If yes then
1117 // a proper default window size is given at the end of Dolphin::init().
1118 GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
1119 const bool firstRun = generalSettings->firstRun();
1120
1121 setAcceptDrops(true);
1122
1123 m_splitter = new QSplitter(this);
1124
1125 DolphinSettings& settings = DolphinSettings::instance();
1126
1127 KBookmarkManager* manager = settings.bookmarkManager();
1128 assert(manager != 0);
1129 KBookmarkGroup root = manager->root();
1130 if (root.first().isNull()) {
1131 root.addBookmark(manager, i18n("Home"), settings.generalSettings()->homeUrl(), "folder_home");
1132 root.addBookmark(manager, i18n("Storage Media"), KUrl("media:/"), "blockdevice");
1133 root.addBookmark(manager, i18n("Network"), KUrl("remote:/"), "network_local");
1134 root.addBookmark(manager, i18n("Root"), KUrl("/"), "folder_red");
1135 root.addBookmark(manager, i18n("Trash"), KUrl("trash:/"), "trashcan_full");
1136 }
1137
1138 setupActions();
1139 setupGUI(Keys|Save|Create|ToolBar);
1140
1141 const KUrl& homeUrl = root.first().url();
1142 setCaption(homeUrl.fileName());
1143 ViewProperties props(homeUrl);
1144 m_view[PrimaryIdx] = new DolphinView(m_splitter,
1145 homeUrl,
1146 props.viewMode(),
1147 props.isShowHiddenFilesEnabled());
1148
1149 m_activeView = m_view[PrimaryIdx];
1150
1151 setCentralWidget(m_splitter);
1152
1153 // open sidebar
1154 SidebarSettings* sidebarSettings = settings.sidebarSettings();
1155 assert(sidebarSettings != 0);
1156 if (sidebarSettings->visible()) {
1157 openSidebar();
1158 }
1159
1160 createGUI();
1161
1162 stateChanged("new_file");
1163 setAutoSaveSettings();
1164
1165 QClipboard* clipboard = QApplication::clipboard();
1166 connect(clipboard, SIGNAL(dataChanged()),
1167 this, SLOT(updatePasteAction()));
1168 updatePasteAction();
1169 updateGoActions();
1170
1171 setupCreateNewMenuActions();
1172
1173 loadSettings();
1174
1175 if (firstRun) {
1176 // assure a proper default size if Dolphin runs the first time
1177 resize(640, 480);
1178 }
1179 }
1180
1181 void Dolphin::loadSettings()
1182 {
1183 GeneralSettings* settings = DolphinSettings::instance().generalSettings();
1184
1185 KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));
1186 if (settings->splitView()) {
1187 splitAction->setChecked(true);
1188 toggleSplitView();
1189 }
1190
1191 updateViewActions();
1192 }
1193
1194 void Dolphin::setupActions()
1195 {
1196 // setup 'File' menu
1197 KAction* createFolder = new KAction(i18n("Folder..."), actionCollection(), "create_folder");
1198 createFolder->setIcon(KIcon("folder"));
1199 createFolder->setShortcut(Qt::Key_N);
1200 connect(createFolder, SIGNAL(triggered()), this, SLOT(createFolder()));
1201
1202 KAction* rename = new KAction(i18n("Rename"), actionCollection(), "rename");
1203 rename->setShortcut(Qt::Key_F2);
1204 connect(rename, SIGNAL(triggered()), this, SLOT(rename()));
1205
1206 KAction* moveToTrash = new KAction(i18n("Move to Trash"), actionCollection(), "move_to_trash");
1207 moveToTrash->setIcon(KIcon("edittrash"));
1208 moveToTrash->setShortcut(QKeySequence::Delete);
1209 connect(moveToTrash, SIGNAL(triggered()), this, SLOT(moveToTrash()));
1210
1211 KAction* deleteAction = new KAction(i18n("Delete"), actionCollection(), "delete");
1212 deleteAction->setShortcut(Qt::ALT | Qt::Key_Delete);
1213 deleteAction->setIcon(KIcon("editdelete"));
1214 connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItems()));
1215
1216 KAction* properties = new KAction(i18n("Propert&ies"), actionCollection(), "properties");
1217 properties->setShortcut(Qt::Key_Alt | Qt::Key_Return);
1218 connect(properties, SIGNAL(triggered()), this, SLOT(properties()));
1219
1220 KStdAction::quit(this, SLOT(quit()), actionCollection());
1221
1222 // setup 'Edit' menu
1223 UndoManager& undoManager = UndoManager::instance();
1224 KStdAction::undo(&undoManager,
1225 SLOT(undo()),
1226 actionCollection());
1227 connect(&undoManager, SIGNAL(undoAvailable(bool)),
1228 this, SLOT(slotUndoAvailable(bool)));
1229 connect(&undoManager, SIGNAL(undoTextChanged(const QString&)),
1230 this, SLOT(slotUndoTextChanged(const QString&)));
1231
1232 KStdAction::redo(&undoManager,
1233 SLOT(redo()),
1234 actionCollection());
1235 connect(&undoManager, SIGNAL(redoAvailable(bool)),
1236 this, SLOT(slotRedoAvailable(bool)));
1237 connect(&undoManager, SIGNAL(redoTextChanged(const QString&)),
1238 this, SLOT(slotRedoTextChanged(const QString&)));
1239
1240 KStdAction::cut(this, SLOT(cut()), actionCollection());
1241 KStdAction::copy(this, SLOT(copy()), actionCollection());
1242 KStdAction::paste(this, SLOT(paste()), actionCollection());
1243
1244 KAction* selectAll = new KAction(i18n("Select All"), actionCollection(), "select_all");
1245 selectAll->setShortcut(Qt::CTRL + Qt::Key_A);
1246 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
1247
1248 KAction* invertSelection = new KAction(i18n("Invert Selection"), actionCollection(), "invert_selection");
1249 invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
1250 connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
1251
1252 // setup 'View' menu
1253 KStdAction::zoomIn(this,
1254 SLOT(zoomIn()),
1255 actionCollection());
1256
1257 KStdAction::zoomOut(this,
1258 SLOT(zoomOut()),
1259 actionCollection());
1260
1261 KToggleAction* iconsView = new KToggleAction(i18n("Icons"), actionCollection(), "icons");
1262 iconsView->setShortcut(Qt::CTRL | Qt::Key_1);
1263 iconsView->setIcon(KIcon("view_icon"));
1264 connect(iconsView, SIGNAL(triggered()), this, SLOT(setIconsView()));
1265
1266 KToggleAction* detailsView = new KToggleAction(i18n("Details"), actionCollection(), "details");
1267 detailsView->setShortcut(Qt::CTRL | Qt::Key_2);
1268 detailsView->setIcon(KIcon("view_text"));
1269 connect(detailsView, SIGNAL(triggered()), this, SLOT(setIconsView()));
1270
1271 KToggleAction* previewsView = new KToggleAction(i18n("Previews"), actionCollection(), "previews");
1272 previewsView->setShortcut(Qt::CTRL | Qt::Key_3);
1273 previewsView->setIcon(KIcon("gvdirpart"));
1274 connect(previewsView, SIGNAL(triggered()), this, SLOT(setPreviewsView()));
1275
1276 QActionGroup* viewModeGroup = new QActionGroup(this);
1277 viewModeGroup->addAction(iconsView);
1278 viewModeGroup->addAction(detailsView);
1279 viewModeGroup->addAction(previewsView);
1280
1281 KToggleAction* sortByName = new KToggleAction(i18n("By Name"), actionCollection(), "by_name");
1282 connect(sortByName, SIGNAL(triggered()), this, SLOT(sortByName()));
1283
1284 KToggleAction* sortBySize = new KToggleAction(i18n("By Size"), actionCollection(), "by_size");
1285 connect(sortBySize, SIGNAL(triggered()), this, SLOT(sortBySize()));
1286
1287 KToggleAction* sortByDate = new KToggleAction(i18n("By Date"), actionCollection(), "by_date");
1288 connect(sortByDate, SIGNAL(triggered()), this, SLOT(sortByDate()));
1289
1290 QActionGroup* sortGroup = new QActionGroup(this);
1291 sortGroup->addAction(sortByName);
1292 sortGroup->addAction(sortBySize);
1293 sortGroup->addAction(sortByDate);
1294
1295 KToggleAction* sortDescending = new KToggleAction(i18n("Descending"), actionCollection(), "descending");
1296 connect(sortDescending, SIGNAL(triggered()), this, SLOT(toggleSortOrder()));
1297
1298 KToggleAction* showHiddenFiles = new KToggleAction(i18n("Show Hidden Files"), actionCollection(), "show_hidden_files");
1299 //showHiddenFiles->setShortcut(Qt::ALT | Qt::Key_ KDE4-TODO: what Qt-Key represents '.'?
1300 connect(showHiddenFiles, SIGNAL(triggered()), this, SLOT(showHiddenFiles()));
1301
1302 KToggleAction* split = new KToggleAction(i18n("Split View"), actionCollection(), "split_view");
1303 split->setShortcut(Qt::Key_F10);
1304 split->setIcon(KIcon("view_left_right"));
1305 connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
1306
1307 KAction* reload = new KAction(i18n("Reload"), "F5", actionCollection(), "reload");
1308 reload->setShortcut(Qt::Key_F5);
1309 reload->setIcon(KIcon("reload"));
1310 connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
1311
1312 KAction* stop = new KAction(i18n("Stop"), actionCollection(), "stop");
1313 stop->setIcon(KIcon("stop"));
1314 connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
1315
1316 KToggleAction* showFullLocation = new KToggleAction(i18n("Show Full Location"), actionCollection(), "editable_location");
1317 showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);
1318 connect(showFullLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
1319
1320 KToggleAction* editLocation = new KToggleAction(i18n("Edit Location"), actionCollection(), "edit_location");
1321 editLocation->setShortcut(Qt::Key_F6);
1322 connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation()));
1323
1324 KToggleAction* sidebar = new KToggleAction(i18n("Sidebar"), actionCollection(), "sidebar");
1325 sidebar->setShortcut(Qt::Key_F9);
1326 connect(sidebar, SIGNAL(triggered()), this, SLOT(toggleSidebar()));
1327
1328 KAction* adjustViewProps = new KAction(i18n("Adjust View Properties..."), actionCollection(), "view_properties");
1329 connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties()));
1330
1331 // setup 'Go' menu
1332 KStdAction::back(this, SLOT(goBack()), actionCollection());
1333 KStdAction::forward(this, SLOT(goForward()), actionCollection());
1334 KStdAction::up(this, SLOT(goUp()), actionCollection());
1335 KStdAction::home(this, SLOT(goHome()), actionCollection());
1336
1337 // setup 'Tools' menu
1338 KAction* openTerminal = new KAction(i18n("Open Terminal"), actionCollection(), "open_terminal");
1339 openTerminal->setShortcut(Qt::Key_F4);
1340 openTerminal->setIcon(KIcon("konsole"));
1341 connect(openTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));
1342
1343 KAction* findFile = new KAction(i18n("Find File..."), actionCollection(), "find_file");
1344 findFile->setShortcut(Qt::Key_F);
1345 findFile->setIcon(KIcon("filefind"));
1346 connect(findFile, SIGNAL(triggered()), this, SLOT(findFile()));
1347
1348 KToggleAction* showFilterBar = new KToggleAction(i18n("Show Filter Bar"), actionCollection(), "show_filter_bar");
1349 showFilterBar->setShortcut(Qt::Key_Slash);
1350 connect(showFilterBar, SIGNAL(triggered()), this, SLOT(showFilterBar()));
1351
1352 KAction* compareFiles = new KAction(i18n("Compare Files"), actionCollection(), "compare_files");
1353 compareFiles->setIcon(KIcon("kompare"));
1354 compareFiles->setEnabled(false);
1355 connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
1356
1357 // setup 'Settings' menu
1358 KStdAction::preferences(this, SLOT(editSettings()), actionCollection());
1359 }
1360
1361 void Dolphin::setupCreateNewMenuActions()
1362 {
1363 // Parts of the following code have been taken
1364 // from the class KNewMenu located in
1365 // libqonq/knewmenu.h of Konqueror.
1366 // Copyright (C) 1998, 1999 David Faure <faure@kde.org>
1367 // 2003 Sven Leiber <s.leiber@web.de>
1368
1369 QStringList files = actionCollection()->instance()->dirs()->findAllResources("templates");
1370 for (QStringList::Iterator it = files.begin() ; it != files.end(); ++it) {
1371 if ((*it)[0] != '.' ) {
1372 KSimpleConfig config(*it, true);
1373 config.setDesktopGroup();
1374
1375 // tricky solution to ensure that TextFile is at the beginning
1376 // because this filetype is the most used (according kde-core discussion)
1377 const QString name(config.readEntry("Name"));
1378 QString key(name);
1379
1380 const QString path(config.readPathEntry("Url"));
1381 if (!path.endsWith("emptydir")) {
1382 if (path.endsWith("TextFile.txt")) {
1383 key = "1" + key;
1384 }
1385 else if (!KDesktopFile::isDesktopFile(path)) {
1386 key = "2" + key;
1387 }
1388 else if (path.endsWith("Url.desktop")){
1389 key = "3" + key;
1390 }
1391 else if (path.endsWith("Program.desktop")){
1392 key = "4" + key;
1393 }
1394 else {
1395 key = "5";
1396 }
1397
1398 const QString icon(config.readEntry("Icon"));
1399 const QString comment(config.readEntry("Comment"));
1400 const QString type(config.readEntry("Type"));
1401
1402 const QString filePath(*it);
1403
1404
1405 if (type == "Link") {
1406 CreateFileEntry entry;
1407 entry.name = name;
1408 entry.icon = icon;
1409 entry.comment = comment;
1410 entry.templatePath = filePath;
1411 m_createFileTemplates.insert(key, entry);
1412 }
1413 }
1414 }
1415 }
1416 m_createFileTemplates.sort();
1417
1418 unplugActionList("create_actions");
1419 KSortableList<CreateFileEntry, QString>::ConstIterator it = m_createFileTemplates.begin();
1420 KSortableList<CreateFileEntry, QString>::ConstIterator end = m_createFileTemplates.end();
1421 /* KDE4-TODO:
1422 while (it != end) {
1423 CreateFileEntry entry = (*it).value();
1424 KAction* action = new KAction(entry.name);
1425 action->setIcon(entry.icon);
1426 action->setName((*it).index());
1427 connect(action, SIGNAL(activated()),
1428 this, SLOT(createFile()));
1429
1430 const QChar section = ((*it).index()[0]);
1431 switch (section) {
1432 case '1':
1433 case '2': {
1434 m_fileGroupActions.append(action);
1435 break;
1436 }
1437
1438 case '3':
1439 case '4': {
1440 // TODO: not used yet. See documentation of Dolphin::linkGroupActions()
1441 // and Dolphin::linkToDeviceActions() in the header file for details.
1442 //m_linkGroupActions.append(action);
1443 break;
1444 }
1445
1446 case '5': {
1447 // TODO: not used yet. See documentation of Dolphin::linkGroupActions()
1448 // and Dolphin::linkToDeviceActions() in the header file for details.
1449 //m_linkToDeviceActions.append(action);
1450 break;
1451 }
1452 default:
1453 break;
1454 }
1455 ++it;
1456 }
1457
1458 plugActionList("create_file_group", m_fileGroupActions);
1459 //plugActionList("create_link_group", m_linkGroupActions);
1460 //plugActionList("link_to_device", m_linkToDeviceActions);*/
1461 }
1462
1463 void Dolphin::updateHistory()
1464 {
1465 int index = 0;
1466 const Q3ValueList<UrlNavigator::HistoryElem> list = m_activeView->urlHistory(index);
1467
1468 KAction* backAction = actionCollection()->action("go_back");
1469 if (backAction != 0) {
1470 backAction->setEnabled(index < static_cast<int>(list.count()) - 1);
1471 }
1472
1473 KAction* forwardAction = actionCollection()->action("go_forward");
1474 if (forwardAction != 0) {
1475 forwardAction->setEnabled(index > 0);
1476 }
1477 }
1478
1479 void Dolphin::updateEditActions()
1480 {
1481 const KFileItemList* list = m_activeView->selectedItems();
1482 if ((list == 0) || (*list).isEmpty()) {
1483 stateChanged("has_no_selection");
1484 }
1485 else {
1486 stateChanged("has_selection");
1487
1488 KAction* renameAction = actionCollection()->action("rename");
1489 if (renameAction != 0) {
1490 renameAction->setEnabled(list->count() >= 1);
1491 }
1492
1493 bool enableMoveToTrash = true;
1494
1495 KFileItemList::const_iterator it = list->begin();
1496 const KFileItemList::const_iterator end = list->end();
1497 while (it != end) {
1498 KFileItem* item = *it;
1499 const KUrl& url = item->url();
1500 // only enable the 'Move to Trash' action for local files
1501 if (!url.isLocalFile()) {
1502 enableMoveToTrash = false;
1503 }
1504 ++it;
1505 }
1506
1507 KAction* moveToTrashAction = actionCollection()->action("move_to_trash");
1508 moveToTrashAction->setEnabled(enableMoveToTrash);
1509 }
1510 updatePasteAction();
1511 }
1512
1513 void Dolphin::updateViewActions()
1514 {
1515 KAction* zoomInAction = actionCollection()->action(KStdAction::stdName(KStdAction::ZoomIn));
1516 if (zoomInAction != 0) {
1517 zoomInAction->setEnabled(m_activeView->isZoomInPossible());
1518 }
1519
1520 KAction* zoomOutAction = actionCollection()->action(KStdAction::stdName(KStdAction::ZoomOut));
1521 if (zoomOutAction != 0) {
1522 zoomOutAction->setEnabled(m_activeView->isZoomOutPossible());
1523 }
1524
1525 KAction* action = 0;
1526 switch (m_activeView->mode()) {
1527 case DolphinView::IconsView:
1528 action = actionCollection()->action("icons");
1529 break;
1530 case DolphinView::DetailsView:
1531 action = actionCollection()->action("details");
1532 break;
1533 case DolphinView::PreviewsView:
1534 action = actionCollection()->action("previews");
1535 break;
1536 default:
1537 break;
1538 }
1539
1540 if (action != 0) {
1541 KToggleAction* toggleAction = static_cast<KToggleAction*>(action);
1542 toggleAction->setChecked(true);
1543 }
1544
1545 slotSortingChanged(m_activeView->sorting());
1546 slotSortOrderChanged(m_activeView->sortOrder());
1547
1548 KToggleAction* showFilterBarAction =
1549 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
1550 showFilterBarAction->setChecked(m_activeView->isFilterBarVisible());
1551
1552 KToggleAction* showHiddenFilesAction =
1553 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
1554 showHiddenFilesAction->setChecked(m_activeView->isShowHiddenFilesEnabled());
1555
1556 KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));
1557 splitAction->setChecked(m_view[SecondaryIdx] != 0);
1558
1559 KToggleAction* sidebarAction = static_cast<KToggleAction*>(actionCollection()->action("sidebar"));
1560 sidebarAction->setChecked(m_sidebar != 0);
1561 }
1562
1563 void Dolphin::updateGoActions()
1564 {
1565 KAction* goUpAction = actionCollection()->action(KStdAction::stdName(KStdAction::Up));
1566 const KUrl& currentUrl = m_activeView->url();
1567 goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
1568 }
1569
1570 void Dolphin::updateViewProperties(const KUrl::List& urls)
1571 {
1572 if (urls.isEmpty()) {
1573 return;
1574 }
1575
1576 // Updating the view properties might take up to several seconds
1577 // when dragging several thousand Urls. Writing a KIO slave for this
1578 // use case is not worth the effort, but at least the main widget
1579 // must be disabled and a progress should be shown.
1580 ProgressIndicator progressIndicator(i18n("Updating view properties..."),
1581 QString::null,
1582 urls.count());
1583
1584 KUrl::List::ConstIterator end = urls.end();
1585 for(KUrl::List::ConstIterator it = urls.begin(); it != end; ++it) {
1586 progressIndicator.execOperation();
1587
1588 ViewProperties props(*it);
1589 props.save();
1590 }
1591 }
1592
1593 void Dolphin::copyUrls(const KUrl::List& source, const KUrl& dest)
1594 {
1595 KIO::Job* job = KIO::copy(source, dest);
1596 addPendingUndoJob(job, DolphinCommand::Copy, source, dest);
1597 }
1598
1599 void Dolphin::moveUrls(const KUrl::List& source, const KUrl& dest)
1600 {
1601 KIO::Job* job = KIO::move(source, dest);
1602 addPendingUndoJob(job, DolphinCommand::Move, source, dest);
1603 }
1604
1605 void Dolphin::addPendingUndoJob(KIO::Job* job,
1606 DolphinCommand::Type commandType,
1607 const KUrl::List& source,
1608 const KUrl& dest)
1609 {
1610 connect(job, SIGNAL(result(KIO::Job*)),
1611 this, SLOT(addUndoOperation(KIO::Job*)));
1612
1613 UndoInfo undoInfo;
1614 undoInfo.id = job->progressId();
1615 undoInfo.command = DolphinCommand(commandType, source, dest);
1616 m_pendingUndoJobs.append(undoInfo);
1617 }
1618
1619 void Dolphin::clearStatusBar()
1620 {
1621 m_activeView->statusBar()->clear();
1622 }
1623
1624 void Dolphin::openSidebar()
1625 {
1626 if (m_sidebar != 0) {
1627 // the sidebar is already open
1628 return;
1629 }
1630
1631 m_sidebar = new Sidebar(m_splitter);
1632 m_sidebar->show();
1633
1634 connect(m_sidebar, SIGNAL(urlChanged(const KUrl&)),
1635 this, SLOT(slotUrlChangeRequest(const KUrl&)));
1636 m_splitter->setCollapsible(m_sidebar, false);
1637 m_splitter->setResizeMode(m_sidebar, QSplitter::KeepSize);
1638 m_splitter->moveToFirst(m_sidebar);
1639
1640 SidebarSettings* settings = DolphinSettings::instance().sidebarSettings();
1641 settings->setVisible(true);
1642 }
1643
1644 #include "dolphin.moc"