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