]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinmainwindow.cpp
reanimated the context menu
[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 list = m_activeView->selectedItems();
593 new KPropertiesDialog(list, this);
594 }
595
596 void DolphinMainWindow::quit()
597 {
598 close();
599 }
600
601 void DolphinMainWindow::slotHandleJobError(KJob* job)
602 {
603 if (job->error() != 0) {
604 m_activeView->statusBar()->setMessage(job->errorString(),
605 DolphinStatusBar::Error);
606 }
607 }
608
609 void DolphinMainWindow::slotDeleteFileFinished(KJob* job)
610 {
611 if (job->error() == 0) {
612 m_activeView->statusBar()->setMessage(i18n("Delete operation completed."),
613 DolphinStatusBar::OperationCompleted);
614
615 // TODO: In opposite to the 'Move to Trash' operation in the class KFileIconView
616 // no rearranging of the item position is done when a file has been deleted.
617 // This is bypassed by reloading the view, but it might be worth to investigate
618 // deeper for the root of this issue.
619 m_activeView->reload();
620 }
621 }
622
623 void DolphinMainWindow::slotUndoAvailable(bool available)
624 {
625 KAction* undoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Undo));
626 if (undoAction != 0) {
627 undoAction->setEnabled(available);
628 }
629 }
630
631 void DolphinMainWindow::slotUndoTextChanged(const QString& text)
632 {
633 KAction* undoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Undo));
634 if (undoAction != 0) {
635 undoAction->setText(text);
636 }
637 }
638
639 void DolphinMainWindow::slotRedoAvailable(bool available)
640 {
641 KAction* redoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Redo));
642 if (redoAction != 0) {
643 redoAction->setEnabled(available);
644 }
645 }
646
647 void DolphinMainWindow::slotRedoTextChanged(const QString& text)
648 {
649 KAction* redoAction = actionCollection()->action(KStdAction::stdName(KStdAction::Redo));
650 if (redoAction != 0) {
651 redoAction->setText(text);
652 }
653 }
654
655 void DolphinMainWindow::cut()
656 {
657 // TODO: this boolean doesn't work between instances of dolphin or with konqueror or with other
658 // apps. The "application/x-kde-cutselection" mimetype should be used instead, see KonqMimeData
659 // in libkonq
660 m_clipboardContainsCutData = true;
661 /* KDE4-TODO: Q3DragObject* data = new KUrlDrag(m_activeView->selectedUrls(),
662 widget());
663 QApplication::clipboard()->setData(data);*/
664 }
665
666 void DolphinMainWindow::copy()
667 {
668 m_clipboardContainsCutData = false;
669 /* KDE4-TODO:
670 Q3DragObject* data = new KUrlDrag(m_activeView->selectedUrls(),
671 widget());
672 QApplication::clipboard()->setData(data);*/
673 }
674
675 void DolphinMainWindow::paste()
676 {
677 /* KDE4-TODO: - see KonqOperations::doPaste
678 QClipboard* clipboard = QApplication::clipboard();
679 QMimeSource* data = clipboard->data();
680 if (!KUrlDrag::canDecode(data)) {
681 return;
682 }
683
684 clearStatusBar();
685
686 KUrl::List sourceUrls;
687 KUrlDrag::decode(data, sourceUrls);
688
689 // per default the pasting is done into the current Url of the view
690 KUrl destUrl(m_activeView->url());
691
692 // check whether the pasting should be done into a selected directory
693 KUrl::List selectedUrls = m_activeView->selectedUrls();
694 if (selectedUrls.count() == 1) {
695 const KFileItem fileItem(S_IFDIR,
696 KFileItem::Unknown,
697 selectedUrls.first(),
698 true);
699 if (fileItem.isDir()) {
700 // only one item is selected which is a directory, hence paste
701 // into this directory
702 destUrl = selectedUrls.first();
703 }
704 }
705
706
707 updateViewProperties(sourceUrls);
708 if (m_clipboardContainsCutData) {
709 moveUrls(sourceUrls, destUrl);
710 m_clipboardContainsCutData = false;
711 clipboard->clear();
712 }
713 else {
714 copyUrls(sourceUrls, destUrl);
715 }*/
716 }
717
718 void DolphinMainWindow::updatePasteAction()
719 {
720 KAction* pasteAction = actionCollection()->action(KStdAction::stdName(KStdAction::Paste));
721 if (pasteAction == 0) {
722 return;
723 }
724
725 QString text(i18n("Paste"));
726 QClipboard* clipboard = QApplication::clipboard();
727 QMimeSource* data = clipboard->data();
728 /* KDE4-TODO:
729 if (KUrlDrag::canDecode(data)) {
730 pasteAction->setEnabled(true);
731
732 KUrl::List urls;
733 KUrlDrag::decode(data, urls);
734 const int count = urls.count();
735 if (count == 1) {
736 pasteAction->setText(i18n("Paste 1 File"));
737 }
738 else {
739 pasteAction->setText(i18n("Paste %1 Files").arg(count));
740 }
741 }
742 else {*/
743 pasteAction->setEnabled(false);
744 pasteAction->setText(i18n("Paste"));
745 //}
746
747 if (pasteAction->isEnabled()) {
748 KUrl::List urls = m_activeView->selectedUrls();
749 const uint count = urls.count();
750 if (count > 1) {
751 // pasting should not be allowed when more than one file
752 // is selected
753 pasteAction->setEnabled(false);
754 }
755 else if (count == 1) {
756 // Only one file is selected. Pasting is only allowed if this
757 // file is a directory.
758 // TODO: this doesn't work with remote protocols; instead we need a
759 // m_activeView->selectedFileItems() to get the real KFileItems
760 const KFileItem fileItem(S_IFDIR,
761 KFileItem::Unknown,
762 urls.first(),
763 true);
764 pasteAction->setEnabled(fileItem.isDir());
765 }
766 }
767 }
768
769 void DolphinMainWindow::selectAll()
770 {
771 clearStatusBar();
772 m_activeView->selectAll();
773 }
774
775 void DolphinMainWindow::invertSelection()
776 {
777 clearStatusBar();
778 m_activeView->invertSelection();
779 }
780 void DolphinMainWindow::setIconsView()
781 {
782 m_activeView->setMode(DolphinView::IconsView);
783 }
784
785 void DolphinMainWindow::setDetailsView()
786 {
787 m_activeView->setMode(DolphinView::DetailsView);
788 }
789
790 void DolphinMainWindow::setPreviewsView()
791 {
792 m_activeView->setMode(DolphinView::PreviewsView);
793 }
794
795 void DolphinMainWindow::sortByName()
796 {
797 m_activeView->setSorting(DolphinView::SortByName);
798 }
799
800 void DolphinMainWindow::sortBySize()
801 {
802 m_activeView->setSorting(DolphinView::SortBySize);
803 }
804
805 void DolphinMainWindow::sortByDate()
806 {
807 m_activeView->setSorting(DolphinView::SortByDate);
808 }
809
810 void DolphinMainWindow::toggleSortOrder()
811 {
812 const Qt::SortOrder order = (m_activeView->sortOrder() == Qt::Ascending) ?
813 Qt::Descending :
814 Qt::Ascending;
815 m_activeView->setSortOrder(order);
816 }
817
818 void DolphinMainWindow::toggleSplitView()
819 {
820 if (m_view[SecondaryIdx] == 0) {
821 // create a secondary view
822 m_view[SecondaryIdx] = new DolphinView(this,
823 m_splitter,
824 m_view[PrimaryIdx]->url(),
825 m_view[PrimaryIdx]->mode(),
826 m_view[PrimaryIdx]->isShowHiddenFilesEnabled());
827 m_view[SecondaryIdx]->show();
828 }
829 else {
830 // remove secondary view
831 if (m_activeView == m_view[PrimaryIdx]) {
832 m_view[SecondaryIdx]->close();
833 m_view[SecondaryIdx]->deleteLater();
834 m_view[SecondaryIdx] = 0;
835 setActiveView(m_view[PrimaryIdx]);
836 }
837 else {
838 // The secondary view is active, hence from the users point of view
839 // the content of the secondary view should be moved to the primary view.
840 // From an implementation point of view it is more efficient to close
841 // the primary view and exchange the internal pointers afterwards.
842 m_view[PrimaryIdx]->close();
843 m_view[PrimaryIdx]->deleteLater();
844 m_view[PrimaryIdx] = m_view[SecondaryIdx];
845 m_view[SecondaryIdx] = 0;
846 setActiveView(m_view[PrimaryIdx]);
847 }
848 }
849 }
850
851 void DolphinMainWindow::reloadView()
852 {
853 clearStatusBar();
854 m_activeView->reload();
855 }
856
857 void DolphinMainWindow::stopLoading()
858 {
859 }
860
861 void DolphinMainWindow::showHiddenFiles()
862 {
863 clearStatusBar();
864
865 const KToggleAction* showHiddenFilesAction =
866 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
867 const bool show = showHiddenFilesAction->isChecked();
868 m_activeView->setShowHiddenFilesEnabled(show);
869 }
870
871 void DolphinMainWindow::showFilterBar()
872 {
873 const KToggleAction* showFilterBarAction =
874 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
875 const bool show = showFilterBarAction->isChecked();
876 m_activeView->slotShowFilterBar(show);
877 }
878
879 void DolphinMainWindow::zoomIn()
880 {
881 m_activeView->zoomIn();
882 updateViewActions();
883 }
884
885 void DolphinMainWindow::zoomOut()
886 {
887 m_activeView->zoomOut();
888 updateViewActions();
889 }
890
891 void DolphinMainWindow::toggleEditLocation()
892 {
893 clearStatusBar();
894
895 KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
896
897 bool editOrBrowse = action->isChecked();
898 // action->setChecked(action->setChecked);
899 m_activeView->setUrlEditable(editOrBrowse);
900 }
901
902 void DolphinMainWindow::editLocation()
903 {
904 KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
905 action->setChecked(true);
906 m_activeView->setUrlEditable(true);
907 }
908
909 void DolphinMainWindow::adjustViewProperties()
910 {
911 clearStatusBar();
912 ViewPropertiesDialog dlg(m_activeView);
913 dlg.exec();
914 }
915
916 void DolphinMainWindow::goBack()
917 {
918 clearStatusBar();
919 m_activeView->goBack();
920 }
921
922 void DolphinMainWindow::goForward()
923 {
924 clearStatusBar();
925 m_activeView->goForward();
926 }
927
928 void DolphinMainWindow::goUp()
929 {
930 clearStatusBar();
931 m_activeView->goUp();
932 }
933
934 void DolphinMainWindow::goHome()
935 {
936 clearStatusBar();
937 m_activeView->goHome();
938 }
939
940 void DolphinMainWindow::openTerminal()
941 {
942 QString command("konsole --workdir \"");
943 command.append(m_activeView->url().path());
944 command.append('\"');
945
946 KRun::runCommand(command, "Konsole", "konsole");
947 }
948
949 void DolphinMainWindow::findFile()
950 {
951 KRun::run("kfind", m_activeView->url());
952 }
953
954 void DolphinMainWindow::compareFiles()
955 {
956 // The method is only invoked if exactly 2 files have
957 // been selected. The selected files may be:
958 // - both in the primary view
959 // - both in the secondary view
960 // - one in the primary view and the other in the secondary
961 // view
962 assert(m_view[PrimaryIdx] != 0);
963
964 KUrl urlA;
965 KUrl urlB;
966 KUrl::List urls = m_view[PrimaryIdx]->selectedUrls();
967
968 switch (urls.count()) {
969 case 0: {
970 assert(m_view[SecondaryIdx] != 0);
971 urls = m_view[SecondaryIdx]->selectedUrls();
972 assert(urls.count() == 2);
973 urlA = urls[0];
974 urlB = urls[1];
975 break;
976 }
977
978 case 1: {
979 urlA = urls[0];
980 assert(m_view[SecondaryIdx] != 0);
981 urls = m_view[SecondaryIdx]->selectedUrls();
982 assert(urls.count() == 1);
983 urlB = urls[0];
984 break;
985 }
986
987 case 2: {
988 urlA = urls[0];
989 urlB = urls[1];
990 break;
991 }
992
993 default: {
994 // may not happen: compareFiles may only get invoked if 2
995 // files are selected
996 assert(false);
997 }
998 }
999
1000 QString command("kompare -c \"");
1001 command.append(urlA.pathOrUrl());
1002 command.append("\" \"");
1003 command.append(urlB.pathOrUrl());
1004 command.append('\"');
1005 KRun::runCommand(command, "Kompare", "kompare");
1006
1007 }
1008
1009 void DolphinMainWindow::editSettings()
1010 {
1011 // TODO: make a static method for opening the settings dialog
1012 DolphinSettingsDialog dlg(this);
1013 dlg.exec();
1014 }
1015
1016 void DolphinMainWindow::addUndoOperation(KJob* job)
1017 {
1018 if (job->error() != 0) {
1019 slotHandleJobError(job);
1020 }
1021 else {
1022 const int id = job->progressId();
1023
1024 // set iterator to the executed command with the current id...
1025 Q3ValueList<UndoInfo>::Iterator it = m_pendingUndoJobs.begin();
1026 const Q3ValueList<UndoInfo>::Iterator end = m_pendingUndoJobs.end();
1027 bool found = false;
1028 while (!found && (it != end)) {
1029 if ((*it).id == id) {
1030 found = true;
1031 }
1032 else {
1033 ++it;
1034 }
1035 }
1036
1037 if (found) {
1038 DolphinCommand command = (*it).command;
1039 if (command.type() == DolphinCommand::Trash) {
1040 // To be able to perform an undo for the 'Move to Trash' operation
1041 // all source Urls must be updated with the trash Url. E. g. when moving
1042 // a file "test.txt" and a second file "test.txt" to the trash,
1043 // then the filenames in the trash are "0-test.txt" and "1-test.txt".
1044 QMap<QString, QString> metaData;
1045 KIO::Job *kiojob = qobject_cast<KIO::Job*>( job );
1046 if ( kiojob )
1047 {
1048 metaData = kiojob->metaData();
1049 }
1050 KUrl::List newSourceUrls;
1051
1052 KUrl::List sourceUrls = command.source();
1053 KUrl::List::Iterator sourceIt = sourceUrls.begin();
1054 const KUrl::List::Iterator sourceEnd = sourceUrls.end();
1055
1056 while (sourceIt != sourceEnd) {
1057 QMap<QString, QString>::ConstIterator metaIt = metaData.find("trashUrl-" + (*sourceIt).path());
1058 if (metaIt != metaData.end()) {
1059 newSourceUrls.append(KUrl(metaIt.data()));
1060 }
1061 ++sourceIt;
1062 }
1063 command.setSource(newSourceUrls);
1064 }
1065
1066 UndoManager::instance().addCommand(command);
1067 m_pendingUndoJobs.erase(it);
1068
1069 DolphinStatusBar* statusBar = m_activeView->statusBar();
1070 switch (command.type()) {
1071 case DolphinCommand::Copy:
1072 statusBar->setMessage(i18n("Copy operation completed."),
1073 DolphinStatusBar::OperationCompleted);
1074 break;
1075 case DolphinCommand::Move:
1076 statusBar->setMessage(i18n("Move operation completed."),
1077 DolphinStatusBar::OperationCompleted);
1078 break;
1079 case DolphinCommand::Trash:
1080 statusBar->setMessage(i18n("Move to trash operation completed."),
1081 DolphinStatusBar::OperationCompleted);
1082 break;
1083 default:
1084 break;
1085 }
1086 }
1087 }
1088 }
1089
1090 void DolphinMainWindow::init()
1091 {
1092 // Check whether Dolphin runs the first time. If yes then
1093 // a proper default window size is given at the end of DolphinMainWindow::init().
1094 GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
1095 const bool firstRun = generalSettings->firstRun();
1096
1097 setAcceptDrops(true);
1098
1099 m_splitter = new QSplitter(this);
1100
1101 DolphinSettings& settings = DolphinSettings::instance();
1102
1103 KBookmarkManager* manager = settings.bookmarkManager();
1104 assert(manager != 0);
1105 KBookmarkGroup root = manager->root();
1106 if (root.first().isNull()) {
1107 root.addBookmark(manager, i18n("Home"), settings.generalSettings()->homeUrl(), "folder_home");
1108 root.addBookmark(manager, i18n("Storage Media"), KUrl("media:/"), "blockdevice");
1109 root.addBookmark(manager, i18n("Network"), KUrl("remote:/"), "network_local");
1110 root.addBookmark(manager, i18n("Root"), KUrl("/"), "folder_red");
1111 root.addBookmark(manager, i18n("Trash"), KUrl("trash:/"), "trashcan_full");
1112 }
1113
1114 setupActions();
1115
1116 const KUrl& homeUrl = root.first().url();
1117 setCaption(homeUrl.fileName());
1118 ViewProperties props(homeUrl);
1119 m_view[PrimaryIdx] = new DolphinView(this,
1120 m_splitter,
1121 homeUrl,
1122 props.viewMode(),
1123 props.isShowHiddenFilesEnabled());
1124
1125 m_activeView = m_view[PrimaryIdx];
1126
1127 setCentralWidget(m_splitter);
1128 setupDockWidgets();
1129
1130 setupGUI(Keys|Save|Create|ToolBar);
1131 createGUI();
1132
1133 stateChanged("new_file");
1134 setAutoSaveSettings();
1135
1136 QClipboard* clipboard = QApplication::clipboard();
1137 connect(clipboard, SIGNAL(dataChanged()),
1138 this, SLOT(updatePasteAction()));
1139 updatePasteAction();
1140 updateGoActions();
1141
1142 setupCreateNewMenuActions();
1143
1144 loadSettings();
1145
1146 if (firstRun) {
1147 // assure a proper default size if Dolphin runs the first time
1148 resize(640, 480);
1149 }
1150 }
1151
1152 void DolphinMainWindow::loadSettings()
1153 {
1154 GeneralSettings* settings = DolphinSettings::instance().generalSettings();
1155
1156 KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));
1157 if (settings->splitView()) {
1158 splitAction->setChecked(true);
1159 toggleSplitView();
1160 }
1161
1162 updateViewActions();
1163 }
1164
1165 void DolphinMainWindow::setupActions()
1166 {
1167 // setup 'File' menu
1168 KAction *action = new KAction(KIcon("window_new"), i18n( "New &Window" ), actionCollection(), "new_window" );
1169 connect(action, SIGNAL(triggered()), this, SLOT(slotNewMainWindow()));
1170
1171 KAction* createFolder = new KAction(i18n("Folder..."), actionCollection(), "create_folder");
1172 createFolder->setIcon(KIcon("folder"));
1173 createFolder->setShortcut(Qt::Key_N);
1174 connect(createFolder, SIGNAL(triggered()), this, SLOT(createFolder()));
1175
1176 KAction* rename = new KAction(i18n("Rename"), actionCollection(), "rename");
1177 rename->setShortcut(Qt::Key_F2);
1178 connect(rename, SIGNAL(triggered()), this, SLOT(rename()));
1179
1180 KAction* moveToTrash = new KAction(i18n("Move to Trash"), actionCollection(), "move_to_trash");
1181 moveToTrash->setIcon(KIcon("edittrash"));
1182 moveToTrash->setShortcut(QKeySequence::Delete);
1183 connect(moveToTrash, SIGNAL(triggered()), this, SLOT(moveToTrash()));
1184
1185 KAction* deleteAction = new KAction(i18n("Delete"), actionCollection(), "delete");
1186 deleteAction->setShortcut(Qt::ALT | Qt::Key_Delete);
1187 deleteAction->setIcon(KIcon("editdelete"));
1188 connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItems()));
1189
1190 KAction* properties = new KAction(i18n("Propert&ies"), actionCollection(), "properties");
1191 properties->setShortcut(Qt::Key_Alt | Qt::Key_Return);
1192 connect(properties, SIGNAL(triggered()), this, SLOT(properties()));
1193
1194 KStdAction::quit(this, SLOT(quit()), actionCollection());
1195
1196 // setup 'Edit' menu
1197 UndoManager& undoManager = UndoManager::instance();
1198 KStdAction::undo(this,
1199 SLOT(slotUndo()),
1200 actionCollection());
1201 connect(&undoManager, SIGNAL(undoAvailable(bool)),
1202 this, SLOT(slotUndoAvailable(bool)));
1203 connect(&undoManager, SIGNAL(undoTextChanged(const QString&)),
1204 this, SLOT(slotUndoTextChanged(const QString&)));
1205
1206 KStdAction::redo(this,
1207 SLOT(slotRedo()),
1208 actionCollection());
1209 connect(&undoManager, SIGNAL(redoAvailable(bool)),
1210 this, SLOT(slotRedoAvailable(bool)));
1211 connect(&undoManager, SIGNAL(redoTextChanged(const QString&)),
1212 this, SLOT(slotRedoTextChanged(const QString&)));
1213
1214 KStdAction::cut(this, SLOT(cut()), actionCollection());
1215 KStdAction::copy(this, SLOT(copy()), actionCollection());
1216 KStdAction::paste(this, SLOT(paste()), actionCollection());
1217
1218 KAction* selectAll = new KAction(i18n("Select All"), actionCollection(), "select_all");
1219 selectAll->setShortcut(Qt::CTRL + Qt::Key_A);
1220 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
1221
1222 KAction* invertSelection = new KAction(i18n("Invert Selection"), actionCollection(), "invert_selection");
1223 invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
1224 connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));
1225
1226 // setup 'View' menu
1227 KStdAction::zoomIn(this,
1228 SLOT(zoomIn()),
1229 actionCollection());
1230
1231 KStdAction::zoomOut(this,
1232 SLOT(zoomOut()),
1233 actionCollection());
1234
1235 KToggleAction* iconsView = new KToggleAction(i18n("Icons"), actionCollection(), "icons");
1236 iconsView->setShortcut(Qt::CTRL | Qt::Key_1);
1237 iconsView->setIcon(KIcon("view_icon"));
1238 connect(iconsView, SIGNAL(triggered()), this, SLOT(setIconsView()));
1239
1240 KToggleAction* detailsView = new KToggleAction(i18n("Details"), actionCollection(), "details");
1241 detailsView->setShortcut(Qt::CTRL | Qt::Key_2);
1242 detailsView->setIcon(KIcon("view_text"));
1243 connect(detailsView, SIGNAL(triggered()), this, SLOT(setDetailsView()));
1244
1245 KToggleAction* previewsView = new KToggleAction(i18n("Previews"), actionCollection(), "previews");
1246 previewsView->setShortcut(Qt::CTRL | Qt::Key_3);
1247 previewsView->setIcon(KIcon("gvdirpart"));
1248 connect(previewsView, SIGNAL(triggered()), this, SLOT(setPreviewsView()));
1249
1250 QActionGroup* viewModeGroup = new QActionGroup(this);
1251 viewModeGroup->addAction(iconsView);
1252 viewModeGroup->addAction(detailsView);
1253 viewModeGroup->addAction(previewsView);
1254
1255 KToggleAction* sortByName = new KToggleAction(i18n("By Name"), actionCollection(), "by_name");
1256 connect(sortByName, SIGNAL(triggered()), this, SLOT(sortByName()));
1257
1258 KToggleAction* sortBySize = new KToggleAction(i18n("By Size"), actionCollection(), "by_size");
1259 connect(sortBySize, SIGNAL(triggered()), this, SLOT(sortBySize()));
1260
1261 KToggleAction* sortByDate = new KToggleAction(i18n("By Date"), actionCollection(), "by_date");
1262 connect(sortByDate, SIGNAL(triggered()), this, SLOT(sortByDate()));
1263
1264 QActionGroup* sortGroup = new QActionGroup(this);
1265 sortGroup->addAction(sortByName);
1266 sortGroup->addAction(sortBySize);
1267 sortGroup->addAction(sortByDate);
1268
1269 KToggleAction* sortDescending = new KToggleAction(i18n("Descending"), actionCollection(), "descending");
1270 connect(sortDescending, SIGNAL(triggered()), this, SLOT(toggleSortOrder()));
1271
1272 KToggleAction* showHiddenFiles = new KToggleAction(i18n("Show Hidden Files"), actionCollection(), "show_hidden_files");
1273 //showHiddenFiles->setShortcut(Qt::ALT | Qt::Key_ KDE4-TODO: what Qt-Key represents '.'?
1274 connect(showHiddenFiles, SIGNAL(triggered()), this, SLOT(showHiddenFiles()));
1275
1276 KToggleAction* split = new KToggleAction(i18n("Split View"), actionCollection(), "split_view");
1277 split->setShortcut(Qt::Key_F10);
1278 split->setIcon(KIcon("view_left_right"));
1279 connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));
1280
1281 KAction* reload = new KAction(i18n("Reload"), "F5", actionCollection(), "reload");
1282 reload->setShortcut(Qt::Key_F5);
1283 reload->setIcon(KIcon("reload"));
1284 connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));
1285
1286 KAction* stop = new KAction(i18n("Stop"), actionCollection(), "stop");
1287 stop->setIcon(KIcon("stop"));
1288 connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
1289
1290 KToggleAction* showFullLocation = new KToggleAction(i18n("Show Full Location"), actionCollection(), "editable_location");
1291 showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);
1292 connect(showFullLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));
1293
1294 KToggleAction* editLocation = new KToggleAction(i18n("Edit Location"), actionCollection(), "edit_location");
1295 editLocation->setShortcut(Qt::Key_F6);
1296 connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation()));
1297
1298 KAction* adjustViewProps = new KAction(i18n("Adjust View Properties..."), actionCollection(), "view_properties");
1299 connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties()));
1300
1301 // setup 'Go' menu
1302 KStdAction::back(this, SLOT(goBack()), actionCollection());
1303 KStdAction::forward(this, SLOT(goForward()), actionCollection());
1304 KStdAction::up(this, SLOT(goUp()), actionCollection());
1305 KStdAction::home(this, SLOT(goHome()), actionCollection());
1306
1307 // setup 'Tools' menu
1308 KAction* openTerminal = new KAction(i18n("Open Terminal"), actionCollection(), "open_terminal");
1309 openTerminal->setShortcut(Qt::Key_F4);
1310 openTerminal->setIcon(KIcon("konsole"));
1311 connect(openTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));
1312
1313 KAction* findFile = new KAction(i18n("Find File..."), actionCollection(), "find_file");
1314 findFile->setShortcut(Qt::Key_F);
1315 findFile->setIcon(KIcon("filefind"));
1316 connect(findFile, SIGNAL(triggered()), this, SLOT(findFile()));
1317
1318 KToggleAction* showFilterBar = new KToggleAction(i18n("Show Filter Bar"), actionCollection(), "show_filter_bar");
1319 showFilterBar->setShortcut(Qt::Key_Slash);
1320 connect(showFilterBar, SIGNAL(triggered()), this, SLOT(showFilterBar()));
1321
1322 KAction* compareFiles = new KAction(i18n("Compare Files"), actionCollection(), "compare_files");
1323 compareFiles->setIcon(KIcon("kompare"));
1324 compareFiles->setEnabled(false);
1325 connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));
1326
1327 // setup 'Settings' menu
1328 KStdAction::preferences(this, SLOT(editSettings()), actionCollection());
1329 }
1330
1331 void DolphinMainWindow::setupCreateNewMenuActions()
1332 {
1333 // Parts of the following code have been taken
1334 // from the class KNewMenu located in
1335 // libqonq/knewmenu.h of Konqueror.
1336 // Copyright (C) 1998, 1999 David Faure <faure@kde.org>
1337 // 2003 Sven Leiber <s.leiber@web.de>
1338
1339 QStringList files = actionCollection()->instance()->dirs()->findAllResources("templates");
1340 for (QStringList::Iterator it = files.begin() ; it != files.end(); ++it) {
1341 if ((*it)[0] != '.' ) {
1342 KSimpleConfig config(*it, true);
1343 config.setDesktopGroup();
1344
1345 // tricky solution to ensure that TextFile is at the beginning
1346 // because this filetype is the most used (according kde-core discussion)
1347 const QString name(config.readEntry("Name"));
1348 QString key(name);
1349
1350 const QString path(config.readPathEntry("Url"));
1351 if (!path.endsWith("emptydir")) {
1352 if (path.endsWith("TextFile.txt")) {
1353 key = "1" + key;
1354 }
1355 else if (!KDesktopFile::isDesktopFile(path)) {
1356 key = "2" + key;
1357 }
1358 else if (path.endsWith("Url.desktop")){
1359 key = "3" + key;
1360 }
1361 else if (path.endsWith("Program.desktop")){
1362 key = "4" + key;
1363 }
1364 else {
1365 key = "5";
1366 }
1367
1368 const QString icon(config.readEntry("Icon"));
1369 const QString comment(config.readEntry("Comment"));
1370 const QString type(config.readEntry("Type"));
1371
1372 const QString filePath(*it);
1373
1374
1375 if (type == "Link") {
1376 CreateFileEntry entry;
1377 entry.name = name;
1378 entry.icon = icon;
1379 entry.comment = comment;
1380 entry.templatePath = filePath;
1381 m_createFileTemplates.insert(key, entry);
1382 }
1383 }
1384 }
1385 }
1386 m_createFileTemplates.sort();
1387
1388 unplugActionList("create_actions");
1389 KSortableList<CreateFileEntry, QString>::ConstIterator it = m_createFileTemplates.begin();
1390 KSortableList<CreateFileEntry, QString>::ConstIterator end = m_createFileTemplates.end();
1391 /* KDE4-TODO: don't port this code; use KNewMenu instead
1392 while (it != end) {
1393 CreateFileEntry entry = (*it).value();
1394 KAction* action = new KAction(entry.name);
1395 action->setIcon(entry.icon);
1396 action->setName((*it).index());
1397 connect(action, SIGNAL(activated()),
1398 this, SLOT(createFile()));
1399
1400 const QChar section = ((*it).index()[0]);
1401 switch (section) {
1402 case '1':
1403 case '2': {
1404 m_fileGroupActions.append(action);
1405 break;
1406 }
1407
1408 case '3':
1409 case '4': {
1410 // TODO: not used yet. See documentation of DolphinMainWindow::linkGroupActions()
1411 // and DolphinMainWindow::linkToDeviceActions() in the header file for details.
1412 //m_linkGroupActions.append(action);
1413 break;
1414 }
1415
1416 case '5': {
1417 // TODO: not used yet. See documentation of DolphinMainWindow::linkGroupActions()
1418 // and DolphinMainWindow::linkToDeviceActions() in the header file for details.
1419 //m_linkToDeviceActions.append(action);
1420 break;
1421 }
1422 default:
1423 break;
1424 }
1425 ++it;
1426 }
1427
1428 plugActionList("create_file_group", m_fileGroupActions);
1429 //plugActionList("create_link_group", m_linkGroupActions);
1430 //plugActionList("link_to_device", m_linkToDeviceActions);*/
1431 }
1432
1433 void DolphinMainWindow::updateHistory()
1434 {
1435 int index = 0;
1436 const Q3ValueList<UrlNavigator::HistoryElem> list = m_activeView->urlHistory(index);
1437
1438 KAction* backAction = actionCollection()->action("go_back");
1439 if (backAction != 0) {
1440 backAction->setEnabled(index < static_cast<int>(list.count()) - 1);
1441 }
1442
1443 KAction* forwardAction = actionCollection()->action("go_forward");
1444 if (forwardAction != 0) {
1445 forwardAction->setEnabled(index > 0);
1446 }
1447 }
1448
1449 void DolphinMainWindow::updateEditActions()
1450 {
1451 const KFileItemList list = m_activeView->selectedItems();
1452 if (list.isEmpty()) {
1453 stateChanged("has_no_selection");
1454 }
1455 else {
1456 stateChanged("has_selection");
1457
1458 KAction* renameAction = actionCollection()->action("rename");
1459 if (renameAction != 0) {
1460 renameAction->setEnabled(list.count() >= 1);
1461 }
1462
1463 bool enableMoveToTrash = true;
1464
1465 KFileItemList::const_iterator it = list.begin();
1466 const KFileItemList::const_iterator end = list.end();
1467 while (it != end) {
1468 KFileItem* item = *it;
1469 const KUrl& url = item->url();
1470 // only enable the 'Move to Trash' action for local files
1471 if (!url.isLocalFile()) {
1472 enableMoveToTrash = false;
1473 }
1474 ++it;
1475 }
1476
1477 KAction* moveToTrashAction = actionCollection()->action("move_to_trash");
1478 moveToTrashAction->setEnabled(enableMoveToTrash);
1479 }
1480 updatePasteAction();
1481 }
1482
1483 void DolphinMainWindow::updateViewActions()
1484 {
1485 KAction* zoomInAction = actionCollection()->action(KStdAction::stdName(KStdAction::ZoomIn));
1486 if (zoomInAction != 0) {
1487 zoomInAction->setEnabled(m_activeView->isZoomInPossible());
1488 }
1489
1490 KAction* zoomOutAction = actionCollection()->action(KStdAction::stdName(KStdAction::ZoomOut));
1491 if (zoomOutAction != 0) {
1492 zoomOutAction->setEnabled(m_activeView->isZoomOutPossible());
1493 }
1494
1495 KAction* action = 0;
1496 switch (m_activeView->mode()) {
1497 case DolphinView::IconsView:
1498 action = actionCollection()->action("icons");
1499 break;
1500 case DolphinView::DetailsView:
1501 action = actionCollection()->action("details");
1502 break;
1503 case DolphinView::PreviewsView:
1504 action = actionCollection()->action("previews");
1505 break;
1506 default:
1507 break;
1508 }
1509
1510 if (action != 0) {
1511 KToggleAction* toggleAction = static_cast<KToggleAction*>(action);
1512 toggleAction->setChecked(true);
1513 }
1514
1515 slotSortingChanged(m_activeView->sorting());
1516 slotSortOrderChanged(m_activeView->sortOrder());
1517
1518 KToggleAction* showFilterBarAction =
1519 static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));
1520 showFilterBarAction->setChecked(m_activeView->isFilterBarVisible());
1521
1522 KToggleAction* showHiddenFilesAction =
1523 static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));
1524 showHiddenFilesAction->setChecked(m_activeView->isShowHiddenFilesEnabled());
1525
1526 KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));
1527 splitAction->setChecked(m_view[SecondaryIdx] != 0);
1528 }
1529
1530 void DolphinMainWindow::updateGoActions()
1531 {
1532 KAction* goUpAction = actionCollection()->action(KStdAction::stdName(KStdAction::Up));
1533 const KUrl& currentUrl = m_activeView->url();
1534 goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
1535 }
1536
1537 void DolphinMainWindow::updateViewProperties(const KUrl::List& urls)
1538 {
1539 if (urls.isEmpty()) {
1540 return;
1541 }
1542
1543 // Updating the view properties might take up to several seconds
1544 // when dragging several thousand Urls. Writing a KIO slave for this
1545 // use case is not worth the effort, but at least the main widget
1546 // must be disabled and a progress should be shown.
1547 ProgressIndicator progressIndicator(this,
1548 i18n("Updating view properties..."),
1549 QString::null,
1550 urls.count());
1551
1552 KUrl::List::ConstIterator end = urls.end();
1553 for(KUrl::List::ConstIterator it = urls.begin(); it != end; ++it) {
1554 progressIndicator.execOperation();
1555
1556 ViewProperties props(*it);
1557 props.save();
1558 }
1559 }
1560
1561 void DolphinMainWindow::copyUrls(const KUrl::List& source, const KUrl& dest)
1562 {
1563 KIO::Job* job = KIO::copy(source, dest);
1564 addPendingUndoJob(job, DolphinCommand::Copy, source, dest);
1565 }
1566
1567 void DolphinMainWindow::moveUrls(const KUrl::List& source, const KUrl& dest)
1568 {
1569 KIO::Job* job = KIO::move(source, dest);
1570 addPendingUndoJob(job, DolphinCommand::Move, source, dest);
1571 }
1572
1573 void DolphinMainWindow::addPendingUndoJob(KIO::Job* job,
1574 DolphinCommand::Type commandType,
1575 const KUrl::List& source,
1576 const KUrl& dest)
1577 {
1578 connect(job, SIGNAL(result(KJob*)),
1579 this, SLOT(addUndoOperation(KJob*)));
1580
1581 UndoInfo undoInfo;
1582 undoInfo.id = job->progressId();
1583 undoInfo.command = DolphinCommand(commandType, source, dest);
1584 m_pendingUndoJobs.append(undoInfo);
1585 }
1586
1587 void DolphinMainWindow::clearStatusBar()
1588 {
1589 m_activeView->statusBar()->clear();
1590 }
1591
1592 void DolphinMainWindow::setupDockWidgets()
1593 {
1594 QDockWidget *shortcutsDock = new QDockWidget(i18n("Shortcuts"));
1595 shortcutsDock->setObjectName("shortcutsDock");
1596 shortcutsDock->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
1597 shortcutsDock->setWidget(new BookmarksSidebarPage(this));
1598 addDockWidget(Qt::LeftDockWidgetArea, shortcutsDock);
1599
1600 QDockWidget *infoDock = new QDockWidget(i18n("Information"));
1601 infoDock->setObjectName("infoDock");
1602 infoDock->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
1603 infoDock->setWidget(new InfoSidebarPage(this));
1604 addDockWidget(Qt::RightDockWidgetArea, infoDock);
1605 }
1606
1607 #include "dolphinmainwindow.moc"