~ubuntu-branches/ubuntu/karmic/digikam/karmic-backports

« back to all changes in this revision

Viewing changes to utilities/imageeditor/editor/editorwindow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ubuntu Archive Auto-Backport
  • Date: 2009-12-07 19:03:53 UTC
  • mfrom: (54.1.4 lucid)
  • Revision ID: james.westby@ubuntu.com-20091207190353-oara3lenjxymto3i
Tags: 2:1.0.0~rc-1ubuntu1~karmic1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * Description : main image editor GUI implementation
8
8
 *
9
9
 * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
10
 * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx dot net>
10
11
 *
11
12
 * This program is free software; you can redistribute it
12
13
 * and/or modify it under the terms of the GNU General
21
22
 *
22
23
 * ============================================================ */
23
24
 
24
 
#include "editorwindow.h"
 
25
//#include "editorwindow.h"
25
26
#include "editorwindow_p.h"
26
27
#include "editorwindow.moc"
27
28
 
52
53
 
53
54
#include <kaboutdata.h>
54
55
#include <kaction.h>
 
56
#include <kactioncategory.h>
55
57
#include <kactioncollection.h>
56
58
#include <kactionmenu.h>
57
59
#include <kapplication.h>
70
72
#include <klocale.h>
71
73
#include <kmenubar.h>
72
74
#include <kmessagebox.h>
 
75
#include <knotifyconfigwidget.h>
73
76
#include <kprotocolinfo.h>
74
77
#include <kselectaction.h>
75
78
#include <kservice.h>
89
92
#include <kxmlguifactory.h>
90
93
#include <kdeversion.h>
91
94
#include <kde_file.h>
 
95
#include <kio/copyjob.h>
 
96
#include <kdebug.h>
92
97
 
93
98
// LibKDcraw includes
94
99
 
99
104
#include "canvas.h"
100
105
#include "colorcorrectiondlg.h"
101
106
#include "dimginterface.h"
 
107
#include "dlogoaction.h"
102
108
#include "dpopupmenu.h"
103
 
#include "dlogoaction.h"
104
109
#include "editorstackview.h"
105
110
#include "editortooliface.h"
106
111
#include "exposurecontainer.h"
107
112
#include "filesaveoptionsbox.h"
108
113
#include "iccmanager.h"
 
114
#include "iccsettings.h"
109
115
#include "iccsettingscontainer.h"
110
 
#include "iccsettings.h"
111
116
#include "icctransform.h"
112
117
#include "imagedialog.h"
113
118
#include "imageplugin.h"
115
120
#include "iofilesettingscontainer.h"
116
121
#include "libsinfodlg.h"
117
122
#include "loadingcacheinterface.h"
 
123
#include "printhelper.h"
 
124
#include "jpegsettings.h"
 
125
#include "pngsettings.h"
118
126
#include "rawcameradlg.h"
119
127
#include "savingcontextcontainer.h"
120
128
#include "sidebar.h"
123
131
#include "statusprogressbar.h"
124
132
#include "themeengine.h"
125
133
#include "thumbbar.h"
126
 
#include "printhelper.h"
127
 
#include "debug.h"
128
134
 
129
135
namespace Digikam
130
136
{
288
294
 
289
295
    connect(IccSettings::instance(), SIGNAL(settingsChanged()),
290
296
            this, SLOT(slotColorManagementOptionsChanged()));
 
297
 
291
298
}
292
299
 
293
300
void EditorWindow::setupStandardActions()
326
333
    m_revertAction->setEnabled(false);
327
334
 
328
335
    d->filePrintAction = new KAction(KIcon("document-print-frame"), i18n("Print Image..."), this);
329
 
    d->filePrintAction->setShortcut(Qt::CTRL+Qt::Key_P);
 
336
    d->filePrintAction->setShortcut(KShortcut(Qt::CTRL+Qt::Key_P));
330
337
    connect(d->filePrintAction, SIGNAL(triggered()), this, SLOT(slotFilePrint()));
331
338
    actionCollection()->addAction("editorwindow_print", d->filePrintAction);
332
339
 
333
340
    m_fileDeleteAction = new KAction(KIcon("user-trash"), i18n("Move to Trash"), this);
334
 
    m_fileDeleteAction->setShortcut(Qt::Key_Delete);
 
341
    m_fileDeleteAction->setShortcut(KShortcut(Qt::Key_Delete));
335
342
    connect(m_fileDeleteAction, SIGNAL(triggered()), this, SLOT(slotDeleteCurrentItem()));
336
343
    actionCollection()->addAction("editorwindow_delete", m_fileDeleteAction);
337
344
 
380
387
    d->redoSignalMapper->setMapping(m_redoAction, 1);
381
388
 
382
389
    d->selectAllAction = new KAction(i18n("Select All"), this);
383
 
    d->selectAllAction->setShortcut(Qt::CTRL+Qt::Key_A);
 
390
    d->selectAllAction->setShortcut(KShortcut(Qt::CTRL+Qt::Key_A));
384
391
    connect(d->selectAllAction, SIGNAL(triggered()), m_canvas, SLOT(slotSelectAll()));
385
392
    actionCollection()->addAction("editorwindow_selectAll", d->selectAllAction);
386
393
 
387
394
    d->selectNoneAction = new KAction(i18n("Select None"), this);
388
 
    d->selectNoneAction->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_A);
 
395
    d->selectNoneAction->setShortcut(KShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_A));
389
396
    connect(d->selectNoneAction, SIGNAL(triggered()), m_canvas, SLOT(slotSelectNone()));
390
397
    actionCollection()->addAction("editorwindow_selectNone", d->selectNoneAction);
391
398
 
393
400
 
394
401
    d->zoomPlusAction = KStandardAction::zoomIn(this, SLOT(slotIncreaseZoom()), this);
395
402
    actionCollection()->addAction("editorwindow_zoomplus", d->zoomPlusAction);
396
 
    d->zoomPlusAction->setShortcut(QKeySequence(Qt::Key_Plus));
 
403
    d->zoomPlusAction->setShortcut(KShortcut(Qt::Key_Plus));
397
404
 
398
405
    d->zoomMinusAction = KStandardAction::zoomOut(this, SLOT(slotDecreaseZoom()), this);
399
406
    actionCollection()->addAction("editorwindow_zoomminus", d->zoomMinusAction);
400
 
    d->zoomMinusAction->setShortcut(QKeySequence(Qt::Key_Minus));
 
407
    d->zoomMinusAction->setShortcut(KShortcut(Qt::Key_Minus));
401
408
 
402
409
    d->zoomTo100percents = new KAction(KIcon("zoom-original"), i18n("Zoom to 100%"), this);
403
 
    d->zoomTo100percents->setShortcut(Qt::ALT+Qt::CTRL+Qt::Key_0);       // NOTE: Photoshop 7 use ALT+CTRL+0
 
410
    d->zoomTo100percents->setShortcut(KShortcut(Qt::ALT+Qt::CTRL+Qt::Key_0));       // NOTE: Photoshop 7 use ALT+CTRL+0
404
411
    connect(d->zoomTo100percents, SIGNAL(triggered()), this, SLOT(slotZoomTo100Percents()));
405
412
    actionCollection()->addAction("editorwindow_zoomto100percents", d->zoomTo100percents);
406
413
 
407
414
    d->zoomFitToWindowAction = new KToggleAction(KIcon("zoom-fit-best"), i18n("Fit to &Window"), this);
408
 
    d->zoomFitToWindowAction->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_E); // NOTE: Gimp 2 use CTRL+SHIFT+E.
 
415
    d->zoomFitToWindowAction->setShortcut(KShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_E)); // NOTE: Gimp 2 use CTRL+SHIFT+E.
409
416
    connect(d->zoomFitToWindowAction, SIGNAL(triggered()), this, SLOT(slotToggleFitToWindow()));
410
417
    actionCollection()->addAction("editorwindow_zoomfit2window", d->zoomFitToWindowAction);
411
418
 
412
419
    d->zoomFitToSelectAction = new KAction(KIcon("zoom-select-fit"), i18n("Fit to &Selection"), this);
413
 
    d->zoomFitToSelectAction->setShortcut(Qt::ALT+Qt::CTRL+Qt::Key_S);   // NOTE: Photoshop 7 use ALT+CTRL+0
 
420
    d->zoomFitToSelectAction->setShortcut(KShortcut(Qt::ALT+Qt::CTRL+Qt::Key_S));   // NOTE: Photoshop 7 use ALT+CTRL+0
414
421
    connect(d->zoomFitToSelectAction, SIGNAL(triggered()), this, SLOT(slotFitToSelect()));
415
422
    actionCollection()->addAction("editorwindow_zoomfit2select", d->zoomFitToSelectAction);
416
423
    d->zoomFitToSelectAction->setEnabled(false);
417
424
    d->zoomFitToSelectAction->setWhatsThis(i18n("This option can be used to zoom the image to the "
418
425
                                                "current selection area."));
419
426
 
 
427
    // --------------------------------------------------------
 
428
 
420
429
    d->zoomCombo = new KComboBox(true);
421
430
    d->zoomCombo->setDuplicatesEnabled(false);
422
431
    d->zoomCombo->setFocusPolicy(Qt::ClickFocus);
423
432
    d->zoomCombo->setInsertPolicy(QComboBox::NoInsert);
424
 
    d->zoomCombo->insertItem(-1, QString("10%"));
425
 
    d->zoomCombo->insertItem(-1, QString("25%"));
426
 
    d->zoomCombo->insertItem(-1, QString("50%"));
427
 
    d->zoomCombo->insertItem(-1, QString("75%"));
428
 
    d->zoomCombo->insertItem(-1, QString("100%"));
429
 
    d->zoomCombo->insertItem(-1, QString("150%"));
430
 
    d->zoomCombo->insertItem(-1, QString("200%"));
431
 
    d->zoomCombo->insertItem(-1, QString("300%"));
432
 
    d->zoomCombo->insertItem(-1, QString("450%"));
433
 
    d->zoomCombo->insertItem(-1, QString("600%"));
434
 
    d->zoomCombo->insertItem(-1, QString("800%"));
435
 
    d->zoomCombo->insertItem(-1, QString("1200%"));
 
433
 
 
434
    QList<double> zoomLevels;
 
435
    zoomLevels << 10.0;
 
436
    zoomLevels << 25.0;
 
437
    zoomLevels << 50.0;
 
438
    zoomLevels << 75.0;
 
439
    zoomLevels << 100.0;
 
440
    zoomLevels << 150.0;
 
441
    zoomLevels << 200.0;
 
442
    zoomLevels << 300.0;
 
443
    zoomLevels << 450.0;
 
444
    zoomLevels << 600.0;
 
445
    zoomLevels << 800.0;
 
446
    zoomLevels << 1200.0;
 
447
 
 
448
    foreach (const double zoom, zoomLevels)
 
449
    {
 
450
        d->zoomCombo->addItem(QString("%1%").arg((int)zoom),
 
451
                              QVariant(zoom));
 
452
    }
436
453
 
437
454
    connect(d->zoomCombo, SIGNAL(activated(int)),
438
 
            this, SLOT(slotZoomSelected()) );
 
455
            this, SLOT(slotZoomSelected(int)));
439
456
 
440
457
    connect(d->zoomCombo, SIGNAL(returnPressed(const QString&)),
441
 
            this, SLOT(slotZoomTextChanged(const QString &)) );
 
458
            this, SLOT(slotZoomTextChanged(const QString&)));
442
459
 
443
460
    d->zoomComboAction = new QWidgetAction(this);
444
461
    d->zoomComboAction->setDefaultWidget(d->zoomCombo);
445
462
    d->zoomComboAction->setText(i18n("Zoom"));
446
463
    actionCollection()->addAction("editorwindow_zoomto", d->zoomComboAction);
447
464
 
 
465
    // --------------------------------------------------------
 
466
 
448
467
    m_fullScreenAction = KStandardAction::fullScreen(this, SLOT(slotToggleFullScreen()), this, this);
449
468
    actionCollection()->addAction("editorwindow_fullscreen", m_fullScreenAction);
450
469
 
451
470
    d->slideShowAction = new KAction(KIcon("view-presentation"), i18n("Slideshow"), this);
452
 
    d->slideShowAction->setShortcut(Qt::Key_F9);
 
471
    d->slideShowAction->setShortcut(KShortcut(Qt::Key_F9));
453
472
    connect(d->slideShowAction, SIGNAL(triggered()), this, SLOT(slotToggleSlideShow()));
454
473
    actionCollection()->addAction("editorwindow_slideshow", d->slideShowAction);
455
474
 
456
475
    d->viewUnderExpoAction = new KToggleAction(KIcon("underexposure"),
457
476
                                               i18n("Under-Exposure Indicator"), this);
458
 
    d->viewUnderExpoAction->setShortcut(Qt::Key_F10);
 
477
    d->viewUnderExpoAction->setShortcut(KShortcut(Qt::Key_F10));
459
478
    connect(d->viewUnderExpoAction, SIGNAL(triggered(bool)), this, SLOT(slotSetUnderExposureIndicator(bool)));
460
479
    actionCollection()->addAction("editorwindow_underexposure", d->viewUnderExpoAction);
461
480
 
462
481
    d->viewOverExpoAction = new KToggleAction(KIcon("overexposure"),
463
482
                                              i18n("Over-Exposure Indicator"), this);
464
 
    d->viewOverExpoAction->setShortcut(Qt::Key_F11);
 
483
    d->viewOverExpoAction->setShortcut(KShortcut(Qt::Key_F11));
465
484
    connect(d->viewOverExpoAction, SIGNAL(triggered(bool)), this, SLOT(slotSetOverExposureIndicator(bool)));
466
485
    actionCollection()->addAction("editorwindow_overexposure", d->viewOverExpoAction);
467
486
 
468
487
    d->viewCMViewAction = new KToggleAction(KIcon("video-display"), i18n("Color-Managed View"), this);
469
 
    d->viewCMViewAction->setShortcut(Qt::Key_F12);
 
488
    d->viewCMViewAction->setShortcut(KShortcut(Qt::Key_F12));
470
489
    connect(d->viewCMViewAction, SIGNAL(triggered()), this, SLOT(slotToggleColorManagedView()));
471
490
    actionCollection()->addAction("editorwindow_cmview", d->viewCMViewAction);
472
491
 
484
503
    // -- Standard 'Transform' menu actions ---------------------------------------------
485
504
 
486
505
    d->cropAction = new KAction(KIcon("transform-crop-and-resize"), i18n("Crop"), this);
487
 
    d->cropAction->setShortcut(Qt::CTRL+Qt::Key_X);
 
506
    d->cropAction->setShortcut(KShortcut(Qt::CTRL+Qt::Key_X));
488
507
    connect(d->cropAction, SIGNAL(triggered()), m_canvas, SLOT(slotCrop()));
489
508
    actionCollection()->addAction("editorwindow_crop", d->cropAction);
490
509
    d->cropAction->setEnabled(false);
494
513
    // -- Standard 'Flip' menu actions ---------------------------------------------
495
514
 
496
515
    d->flipHorizAction = new KAction(KIcon("object-flip-horizontal"), i18n("Flip Horizontally"), this);
497
 
    d->flipHorizAction->setShortcut(Qt::CTRL+Qt::Key_Asterisk);
 
516
    d->flipHorizAction->setShortcut(KShortcut(Qt::CTRL+Qt::Key_Asterisk));
498
517
    connect(d->flipHorizAction, SIGNAL(triggered()), m_canvas, SLOT(slotFlipHoriz()));
499
518
    actionCollection()->addAction("editorwindow_flip_horiz", d->flipHorizAction);
500
519
    d->flipHorizAction->setEnabled(false);
501
520
 
502
521
    d->flipVertAction = new KAction(KIcon("object-flip-vertical"), i18n("Flip Vertically"), this);
503
 
    d->flipVertAction->setShortcut(Qt::CTRL+Qt::Key_Slash);
 
522
    d->flipVertAction->setShortcut(KShortcut(Qt::CTRL+Qt::Key_Slash));
504
523
    connect(d->flipVertAction, SIGNAL(triggered()), m_canvas, SLOT(slotFlipVert()));
505
524
    actionCollection()->addAction("editorwindow_flip_vert", d->flipVertAction);
506
525
    d->flipVertAction->setEnabled(false);
508
527
    // -- Standard 'Rotate' menu actions ----------------------------------------
509
528
 
510
529
    d->rotateLeftAction = new KAction(KIcon("object-rotate-left"), i18n("Rotate Left"), this);
511
 
    d->rotateLeftAction->setShortcut(Qt::SHIFT+Qt::CTRL+Qt::Key_Left);
 
530
    d->rotateLeftAction->setShortcut(KShortcut(Qt::SHIFT+Qt::CTRL+Qt::Key_Left));
512
531
    connect(d->rotateLeftAction, SIGNAL(triggered()), m_canvas, SLOT(slotRotate270()));
513
532
    actionCollection()->addAction("editorwindow_rotate_left", d->rotateLeftAction);
514
533
    d->rotateLeftAction->setEnabled(false);
515
534
 
516
535
    d->rotateRightAction = new KAction(KIcon("object-rotate-right"), i18n("Rotate Right"), this);
517
 
    d->rotateRightAction->setShortcut(Qt::SHIFT+Qt::CTRL+Qt::Key_Right);
 
536
    d->rotateRightAction->setShortcut(KShortcut(Qt::SHIFT+Qt::CTRL+Qt::Key_Right));
518
537
    connect(d->rotateRightAction, SIGNAL(triggered()), m_canvas, SLOT(slotRotate90()));
519
538
    actionCollection()->addAction("editorwindow_rotate_right", d->rotateRightAction);
520
539
    d->rotateRightAction->setEnabled(false);
524
543
    d->showMenuBarAction = KStandardAction::showMenubar(this, SLOT(slotShowMenuBar()), actionCollection());
525
544
    d->showMenuBarAction->setChecked(!menuBar()->isHidden());  // NOTE: workaround for B.K.O #171080
526
545
 
527
 
    KStandardAction::keyBindings(this, SLOT(slotEditKeys()),           actionCollection());
528
 
    KStandardAction::configureToolbars(this, SLOT(slotConfToolbars()), actionCollection());
529
 
    KStandardAction::preferences(this, SLOT(slotSetup()),              actionCollection());
 
546
    KStandardAction::keyBindings(this,            SLOT(slotEditKeys()),          actionCollection());
 
547
    KStandardAction::configureToolbars(this,      SLOT(slotConfToolbars()),      actionCollection());
 
548
    KStandardAction::configureNotifications(this, SLOT(slotConfNotifications()), actionCollection());
 
549
    KStandardAction::preferences(this,            SLOT(slotSetup()),             actionCollection());
530
550
 
531
551
    // ---------------------------------------------------------------------------------
532
552
 
559
579
 
560
580
    // -- Keyboard-only actions added to <MainWindow> ------------------------------
561
581
 
562
 
//    KAction *exitFullscreenAction = new KAction(i18n("Exit Full Screen"), this);
563
 
//    actionCollection()->addAction("editorwindow_exitfullscreen", exitFullscreenAction);
564
 
//    exitFullscreenAction->setShortcut( QKeySequence(Qt::Key_Escape) );
565
 
//    connect(exitFullscreenAction, SIGNAL(triggered()), this, SLOT(slotEscapePressed()));
566
 
 
567
582
    KAction *closeToolAction = new KAction(i18n("Close Tool"), this);
568
583
    actionCollection()->addAction("editorwindow_closetool", closeToolAction);
569
 
    closeToolAction->setShortcut( QKeySequence(Qt::Key_Escape) );
 
584
    closeToolAction->setShortcut(KShortcut(Qt::Key_Escape) );
570
585
    connect(closeToolAction, SIGNAL(triggered()), this, SLOT(slotCloseTool()));
571
586
 
572
587
    KAction *altBackwardAction = new KAction(i18n("Previous Image"), this);
582
597
{
583
598
    m_nameLabel = new StatusProgressBar(statusBar());
584
599
    m_nameLabel->setAlignment(Qt::AlignCenter);
585
 
    m_nameLabel->setMaximumHeight(fontMetrics().height()+2);
586
600
    statusBar()->addWidget(m_nameLabel, 100);
587
601
 
588
602
    d->selectLabel = new QLabel(i18n("No selection"), statusBar());
589
603
    d->selectLabel->setAlignment(Qt::AlignCenter);
590
 
    d->selectLabel->setMaximumHeight(fontMetrics().height()+2);
591
604
    statusBar()->addWidget(d->selectLabel, 100);
592
605
    d->selectLabel->setToolTip( i18n("Information about current selection area"));
593
606
 
594
607
    m_resLabel  = new QLabel(statusBar());
595
608
    m_resLabel->setAlignment(Qt::AlignCenter);
596
 
    m_resLabel->setMaximumHeight(fontMetrics().height()+2);
597
609
    statusBar()->addWidget(m_resLabel, 100);
598
610
    m_resLabel->setToolTip( i18n("Information about image size"));
599
611
 
690
702
    dlg.exec();
691
703
}
692
704
 
 
705
void EditorWindow::slotConfNotifications()
 
706
{
 
707
    KNotifyConfigWidget::configure(this);
 
708
}
 
709
 
693
710
void EditorWindow::slotNewToolbarConfig()
694
711
{
695
712
    applyMainWindowSettings(KGlobal::config()->group("ImageViewer Settings"));
726
743
    d->zoomPlusAction->setEnabled(true);
727
744
    d->zoomComboAction->setEnabled(true);
728
745
    d->zoomMinusAction->setEnabled(true);
729
 
    m_stackView->zoomTo100Percents();
 
746
    m_stackView->zoomTo100Percent();
730
747
}
731
748
 
732
 
void EditorWindow::slotZoomSelected()
 
749
void EditorWindow::slotZoomSelected(int index)
733
750
{
734
 
    QString txt = d->zoomCombo->currentText();
735
 
    txt         = txt.left(txt.indexOf('%'));
736
 
    slotZoomTextChanged(txt);
 
751
    bool ok     = false;
 
752
    double zoom = d->zoomCombo->itemData(index).toDouble(&ok) / 100.0;
 
753
    if (ok && zoom > 0.0)
 
754
    {
 
755
        m_stackView->setZoomFactor(zoom);
 
756
    }
737
757
}
738
758
 
739
759
void EditorWindow::slotZoomTextChanged(const QString& txt)
741
761
    bool r      = false;
742
762
    double zoom = KGlobal::locale()->readNumber(txt, &r) / 100.0;
743
763
    if (r && zoom > 0.0)
 
764
    {
744
765
        m_stackView->setZoomFactor(zoom);
 
766
    }
 
767
 
745
768
}
746
769
 
747
770
void EditorWindow::slotZoomChanged(bool isMax, bool isMin, double zoom)
787
810
            plugin->setEnabledSelectionActions(false);
788
811
 
789
812
            // add actions to imagepluginsActionCollection
790
 
            foreach (QAction* action, plugin->actionCollection()->actions())
791
 
            {
792
 
                d->imagepluginsActionCollection->addAction(action->objectName(), action);
793
 
            }
 
813
#if KDE_IS_VERSION(4,1,68)
 
814
            QString categoryStr = plugin->actionCategory();
 
815
 
 
816
            if (categoryStr != QString("__INVALID__") && !categoryStr.isEmpty())
 
817
            {
 
818
                KActionCategory *category = new KActionCategory(categoryStr, d->imagepluginsActionCollection);
 
819
                foreach (QAction* action, plugin->actionCollection()->actions())
 
820
                {
 
821
                    category->addAction(action->objectName(), action);
 
822
                }
 
823
            }
 
824
            else
 
825
            {
 
826
#endif
 
827
                foreach (QAction* action, plugin->actionCollection()->actions())
 
828
                {
 
829
                    d->imagepluginsActionCollection->addAction(action->objectName(), action);
 
830
                }
 
831
#if KDE_IS_VERSION(4,1,68)
 
832
            }
 
833
#endif
794
834
        }
795
835
        else
796
836
        {
797
 
            kDebug(digiKamAreaCode) << "Invalid plugin to add!";
 
837
            kDebug() << "Invalid plugin to add!";
798
838
        }
799
839
    }
800
840
 
858
898
 
859
899
    KConfigGroup group = config->group("ImageViewer Settings");
860
900
 
861
 
    // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100.
862
 
    m_IOFileSettings->JPEGCompression     = (int)((75.0/100.0)*
863
 
                                                 (float)group.readEntry("JPEGCompression", 75)
864
 
                                                 + 26.0 - (75.0/100.0));
 
901
    m_IOFileSettings->JPEGCompression     = JPEGSettings::convertCompressionForLibJpeg(group.readEntry("JPEGCompression", 75));
865
902
 
866
903
    m_IOFileSettings->JPEGSubSampling     = group.readEntry("JPEGSubSampling", 1);  // Medium subsampling
867
904
 
868
 
    // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1.
869
 
    m_IOFileSettings->PNGCompression      = (int)(((1.0-100.0)/8.0)*
870
 
                                                 (float)group.readEntry("PNGCompression", 1)
871
 
                                                 + 100.0 - ((1.0-100.0)/8.0));
 
905
    m_IOFileSettings->PNGCompression      = PNGSettings::convertCompressionForLibPng(group.readEntry("PNGCompression", 1));
872
906
 
873
907
    // TIFF compression setting.
874
908
    m_IOFileSettings->TIFFCompression     = group.readEntry("TIFFCompression", false);
958
992
                stream >> sizesList;
959
993
                if (sizesList.count() == 3)
960
994
                {
961
 
                    kDebug(digiKamAreaCode) << "Found splitter based config, converting to dockbar";
 
995
                    kDebug() << "Found splitter based config, converting to dockbar";
962
996
                    // Remove the first entry (the thumbbar) and write the rest
963
997
                    // back. Then it should be fine.
964
998
                    sizesList.removeFirst();
1158
1192
 
1159
1193
bool EditorWindow::promptForOverWrite()
1160
1194
{
1161
 
    QFileInfo fi(m_canvas->currentImageFilePath());
1162
 
    QString warnMsg(i18n("About to overwrite file \"%1\"\nAre you sure?", fi.fileName()));
1163
 
    return (KMessageBox::warningContinueCancel(this,
1164
 
                                               warnMsg,
1165
 
                                               i18n("Warning"),
1166
 
                                               KGuiItem(i18n("Overwrite")),
1167
 
                                               KStandardGuiItem::cancel(),
1168
 
                                               QString("editorWindowSaveOverwrite"))
1169
 
            ==  KMessageBox::Continue);
 
1195
 
 
1196
    KUrl destination = saveDestinationUrl();
 
1197
 
 
1198
    if (destination.isLocalFile())
 
1199
    {
 
1200
 
 
1201
        QFileInfo fi(m_canvas->currentImageFilePath());
 
1202
        QString warnMsg(i18n("About to overwrite file \"%1\"\nAre you sure?", fi.fileName()));
 
1203
        return (KMessageBox::warningContinueCancel(this,
 
1204
                                                   warnMsg,
 
1205
                                                   i18n("Warning"),
 
1206
                                                   KGuiItem(i18n("Overwrite")),
 
1207
                                                   KStandardGuiItem::cancel(),
 
1208
                                                   QString("editorWindowSaveOverwrite"))
 
1209
                ==  KMessageBox::Continue);
 
1210
 
 
1211
    }
 
1212
    else
 
1213
    {
 
1214
        // in this case kio handles the overwrite request
 
1215
        return true;
 
1216
    }
 
1217
 
1170
1218
}
1171
1219
 
1172
1220
bool EditorWindow::promptUserSave(const KUrl& url, SaveOrSaveAs saveOrSaveAs, bool allowCancel)
1180
1228
        }
1181
1229
 
1182
1230
        int result;
 
1231
        QString boxMessage = i18n("The image '%1' has been modified.\n"
 
1232
                                  "Do you want to save it?", url.fileName());
1183
1233
        if (allowCancel)
1184
1234
        {
1185
1235
            result = KMessageBox::warningYesNoCancel(this,
1186
 
                                  i18n("The image '%1' has been modified.\n"
1187
 
                                       "Do you want to save it?",
1188
 
                                       url.fileName()),
 
1236
                                  boxMessage,
1189
1237
                                  QString(),
1190
1238
                                  KStandardGuiItem::save(),
1191
1239
                                  KStandardGuiItem::discard());
1193
1241
        else
1194
1242
        {
1195
1243
            result = KMessageBox::warningYesNo(this,
1196
 
                                  i18n("The image '%1' has been modified.\n"
1197
 
                                       "Do you want to save it?",
1198
 
                                       url.fileName()),
 
1244
                                  boxMessage,
1199
1245
                                  QString(),
1200
1246
                                  KStandardGuiItem::save(),
1201
1247
                                  KStandardGuiItem::discard());
1406
1452
 
1407
1453
void EditorWindow::slotSave()
1408
1454
{
 
1455
 
1409
1456
    if (m_canvas->isReadOnly())
1410
1457
        saveAs();
1411
1458
    else if (promptForOverWrite())
1412
1459
        save();
 
1460
 
1413
1461
}
1414
1462
 
1415
1463
void EditorWindow::slotSavingStarted(const QString& /*filename*/)
1424
1472
    m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, i18n("Saving: "));
1425
1473
}
1426
1474
 
 
1475
void EditorWindow::movingSaveFileFinished(bool successful)
 
1476
{
 
1477
 
 
1478
    if (!successful)
 
1479
    {
 
1480
        finishSaving(false);
 
1481
        return;
 
1482
    }
 
1483
 
 
1484
    m_canvas->setUndoHistoryOrigin();
 
1485
 
 
1486
    // remove image from cache since it has changed
 
1487
    LoadingCacheInterface::fileChanged(m_savingContext->destinationURL.toLocalFile());
 
1488
 
 
1489
    // restore state of disabled actions. saveIsComplete can start any other task
 
1490
    // (loading!) which might itself in turn change states
 
1491
    finishSaving(true);
 
1492
 
 
1493
    if (m_savingContext->executedOperation == SavingContextContainer::SavingStateSave)
 
1494
        saveIsComplete();
 
1495
    else
 
1496
        saveAsIsComplete();
 
1497
 
 
1498
    // Take all actions necessary to update information and re-enable sidebar
 
1499
    slotChanged();
 
1500
 
 
1501
 
 
1502
}
 
1503
 
1427
1504
void EditorWindow::slotSavingFinished(const QString& filename, bool success)
1428
1505
{
1429
 
    if (m_savingContext->savingState == SavingContextContainer::SavingStateSave)
 
1506
 
 
1507
    Q_UNUSED(filename);
 
1508
 
 
1509
    // only handle this if we really wanted to save a file...
 
1510
    if ((m_savingContext->savingState == SavingContextContainer::SavingStateSave)
 
1511
                    || (m_savingContext->savingState == SavingContextContainer::SavingStateSaveAs))
1430
1512
    {
 
1513
 
1431
1514
        // from save()
 
1515
        m_savingContext->executedOperation = m_savingContext->savingState;
1432
1516
        m_savingContext->savingState = SavingContextContainer::SavingStateNone;
1433
1517
 
1434
1518
        if (!success)
1443
1527
            return;
1444
1528
        }
1445
1529
 
1446
 
        kDebug(digiKamAreaCode) << "renaming to " << m_savingContext->destinationURL.toLocalFile();
1447
 
 
1448
 
        if (!moveFile())
1449
 
        {
1450
 
            finishSaving(false);
1451
 
            return;
1452
 
        }
1453
 
 
1454
 
        m_canvas->setUndoHistoryOrigin();
1455
 
 
1456
 
        // remove image from cache since it has changed
1457
 
        LoadingCacheInterface::fileChanged(m_savingContext->destinationURL.toLocalFile());
1458
 
        // this won't be in the cache, but does not hurt to do it anyway
1459
 
        LoadingCacheInterface::fileChanged(filename);
1460
 
 
1461
 
        // restore state of disabled actions. saveIsComplete can start any other task
1462
 
        // (loading!) which might itself in turn change states
1463
 
        finishSaving(true);
1464
 
 
1465
 
        saveIsComplete();
1466
 
 
1467
 
        // Take all actions necessary to update information and re-enable sidebar
1468
 
        slotChanged();
 
1530
        moveFile();
 
1531
 
1469
1532
    }
1470
 
    else if (m_savingContext->savingState == SavingContextContainer::SavingStateSaveAs)
 
1533
    else
1471
1534
    {
1472
 
        m_savingContext->savingState = SavingContextContainer::SavingStateNone;
1473
 
 
1474
 
        // from saveAs()
1475
 
        if (!success)
1476
 
        {
1477
 
            if (!m_savingContext->abortingSaving)
1478
 
            {
1479
 
                KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".",
1480
 
                                              m_savingContext->destinationURL.fileName(),
1481
 
                                              m_savingContext->destinationURL.toLocalFile()));
1482
 
            }
1483
 
            finishSaving(false);
1484
 
            return;
1485
 
        }
1486
 
 
1487
 
        // Only try to write Exif if both src and destination are JPEG files
1488
 
 
1489
 
        kDebug(digiKamAreaCode) << "renaming to " << m_savingContext->destinationURL.toLocalFile();
1490
 
 
1491
 
        if (!moveFile())
1492
 
        {
1493
 
            finishSaving(false);
1494
 
            return;
1495
 
        }
1496
 
 
1497
 
        m_canvas->setUndoHistoryOrigin();
1498
 
 
1499
 
        LoadingCacheInterface::fileChanged(m_savingContext->destinationURL.toLocalFile());
1500
 
        LoadingCacheInterface::fileChanged(filename);
1501
 
 
1502
 
        finishSaving(true);
1503
 
        saveAsIsComplete();
1504
 
 
1505
 
        // Take all actions necessary to update information and re-enable sidebar
1506
 
        slotChanged();
 
1535
        kWarning() << "Why was slotSavingFinished called "
 
1536
                                  << "if we did not want to save a file?";
1507
1537
    }
 
1538
 
1508
1539
}
1509
1540
 
1510
1541
void EditorWindow::finishSaving(bool success)
1535
1566
    }
1536
1567
}
1537
1568
 
 
1569
void EditorWindow::setupTempSaveFile(const KUrl & url)
 
1570
{
 
1571
 
 
1572
    QString tempDir = url.directory(KUrl::AppendTrailingSlash);
 
1573
    // use magic file extension which tells the digikamalbums ioslave to ignore the file
 
1574
    m_savingContext->saveTempFile = new KTemporaryFile();
 
1575
    // if the destination url is on local file system, try to set the temp file
 
1576
    // location to the destination folder, otherwise use a local default
 
1577
    if (url.isLocalFile())
 
1578
    {
 
1579
        m_savingContext->saveTempFile->setPrefix(tempDir);
 
1580
    }
 
1581
    m_savingContext->saveTempFile->setSuffix(".digikamtempfile.tmp");
 
1582
    m_savingContext->saveTempFile->setAutoRemove(false);
 
1583
    m_savingContext->saveTempFile->open();
 
1584
 
 
1585
    if (!m_savingContext->saveTempFile->open())
 
1586
    {
 
1587
        KMessageBox::error(this, i18n("Could not open a temporary file in the folder \"%1\": %2 (%3)",
 
1588
                                      tempDir, m_savingContext->saveTempFile->errorString(),
 
1589
                                      m_savingContext->saveTempFile->error()));
 
1590
        return;
 
1591
    }
 
1592
 
 
1593
    m_savingContext->saveTempFileName = m_savingContext->saveTempFile->fileName();
 
1594
    delete m_savingContext->saveTempFile;
 
1595
    m_savingContext->saveTempFile = 0;
 
1596
 
 
1597
}
 
1598
 
1538
1599
void EditorWindow::startingSave(const KUrl& url)
1539
1600
{
 
1601
 
 
1602
    kDebug() << "startSaving url = " << url;
 
1603
 
1540
1604
    // avoid any reentrancy. Should be impossible anyway since actions will be disabled.
1541
1605
    if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
1542
1606
        return;
1544
1608
    if (!checkPermissions(url))
1545
1609
        return;
1546
1610
 
1547
 
    QString tempDir = url.directory(KUrl::AppendTrailingSlash);
1548
 
    // use magic file extension which tells the digikamalbums ioslave to ignore the file
1549
 
    m_savingContext->saveTempFile = new KTemporaryFile();
1550
 
    m_savingContext->saveTempFile->setPrefix(tempDir);
1551
 
    m_savingContext->saveTempFile->setSuffix(".digikamtempfile.tmp");
1552
 
    m_savingContext->saveTempFile->setAutoRemove(false);
1553
 
    m_savingContext->saveTempFile->open();
1554
 
 
1555
 
    if (!m_savingContext->saveTempFile->open())
1556
 
    {
1557
 
        KMessageBox::error(this, i18n("Could not open a temporary file in the folder \"%1\": %2 (%3)",
1558
 
                                      tempDir, m_savingContext->saveTempFile->errorString(),
1559
 
                                      m_savingContext->saveTempFile->error()));
1560
 
        return;
1561
 
    }
1562
 
    m_savingContext->saveTempFileName = m_savingContext->saveTempFile->fileName();
1563
 
    delete m_savingContext->saveTempFile;
1564
 
    m_savingContext->saveTempFile = 0;
 
1611
    setupTempSaveFile(url);
1565
1612
 
1566
1613
    m_savingContext->srcURL             = url;
1567
1614
    m_savingContext->destinationURL     = m_savingContext->srcURL;
1570
1617
    m_savingContext->format             = m_savingContext->originalFormat;
1571
1618
    m_savingContext->abortingSaving     = false;
1572
1619
    m_savingContext->savingState        = SavingContextContainer::SavingStateSave;
 
1620
    m_savingContext->executedOperation  = SavingContextContainer::SavingStateNone;
1573
1621
 
1574
1622
    m_canvas->saveAs(m_savingContext->saveTempFileName, m_IOFileSettings,
1575
1623
                     m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()));
1576
1624
}
1577
1625
 
1578
 
bool EditorWindow::startingSaveAs(const KUrl& url)
 
1626
QStringList EditorWindow::getWritingFilters()
1579
1627
{
1580
 
    if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
1581
 
        return false;
1582
1628
 
 
1629
    // begin with the filtersa KImageIO supports
1583
1630
    QString pattern             = KImageIO::pattern(KImageIO::Writing);
1584
1631
    QStringList writablePattern = pattern.split(QChar('\n'));
1585
 
    kDebug(digiKamAreaCode) << "KDE Offered pattern: " << writablePattern;
 
1632
    kDebug() << "KImageIO offered pattern: " << writablePattern;
 
1633
 
 
1634
    // remove "all images" type
 
1635
    // XXX bad assumption that this is always the first type in the list
 
1636
    writablePattern.removeFirst();
 
1637
 
 
1638
    // append custom file types
1586
1639
    writablePattern.append(QString("*.jp2|") + i18n("JPEG 2000 image"));
1587
1640
    writablePattern.append(QString("*.pgf|") + i18n("Progressive Graphics File"));
1588
1641
 
 
1642
    return writablePattern;
 
1643
 
 
1644
}
 
1645
 
 
1646
QString EditorWindow::findFilterByExtension(const QStringList& allFilters, const QString& extension)
 
1647
{
 
1648
 
 
1649
    kDebug() << "Searching for a filter with extension '" << extension
 
1650
             << "' in: " << allFilters;
 
1651
 
 
1652
    const QString filterExtension = QString("*.%1").arg(extension.toLower());
 
1653
 
 
1654
    foreach(const QString& filter, allFilters)
 
1655
    {
 
1656
 
 
1657
        if (filter.contains(filterExtension))
 
1658
        {
 
1659
            kDebug() << "Found filter '" << filter << "'";
 
1660
            return filter;
 
1661
        }
 
1662
 
 
1663
    }
 
1664
 
 
1665
    // fall back to "all image types"
 
1666
    if (!allFilters.empty() && allFilters.first().contains(filterExtension))
 
1667
    {
 
1668
        kDebug() << "using fall back all images filter: " << allFilters.first();
 
1669
        return allFilters.first();
 
1670
    }
 
1671
 
 
1672
    return QString();
 
1673
 
 
1674
}
 
1675
 
 
1676
QString EditorWindow::getExtensionFromFilter(const QString& filter)
 
1677
{
 
1678
 
 
1679
    kDebug () << "Trying to extract format from filter: " << filter;
 
1680
 
 
1681
    // find locations of interesting characters in the filter string
 
1682
    const int asteriskLocation = filter.indexOf('*');
 
1683
    if (asteriskLocation < 0)
 
1684
    {
 
1685
        kDebug() << "Could not find a * in the filter";
 
1686
        return QString();
 
1687
    }
 
1688
 
 
1689
    const int endLocation = filter.indexOf(QRegExp("[|\\* ]"), asteriskLocation + 1);
 
1690
    if (endLocation < 0)
 
1691
    {
 
1692
        kDebug() << "Could not find a valid end of the format in the filter";
 
1693
        return QString();
 
1694
    }
 
1695
 
 
1696
    kDebug() << "astriskLocation = " << asteriskLocation
 
1697
             << ", endLocation = " << endLocation;
 
1698
 
 
1699
    // extract extension with the locations found above
 
1700
    QString formatString = filter;
 
1701
    formatString.remove(0, asteriskLocation + 2);
 
1702
    formatString = formatString.left(endLocation - asteriskLocation - 2);
 
1703
    kDebug() << "Extracted format " << formatString;
 
1704
    return formatString;
 
1705
 
 
1706
}
 
1707
 
 
1708
bool EditorWindow::selectValidSavingFormat(const QString& filterExtension, const KUrl& targetUrl)
 
1709
{
 
1710
 
 
1711
    kDebug() << "Trying to find a saving format with filterExtension = "
 
1712
             << filterExtension << ", targetUrl = " << targetUrl;
 
1713
 
 
1714
    // build a list of valid types
 
1715
    QStringList validTypes = KImageIO::types(KImageIO::Writing);
 
1716
    kDebug() << "KDE Offered types: " << validTypes;
 
1717
 
 
1718
    validTypes << "TIF";
 
1719
    validTypes << "TIFF";
 
1720
    validTypes << "JPG";
 
1721
    validTypes << "JPEG";
 
1722
    validTypes << "JPE";
 
1723
    validTypes << "J2K";
 
1724
    validTypes << "JP2";
 
1725
    validTypes << "PGF";
 
1726
 
 
1727
    kDebug() << "Writable formats: " << validTypes;
 
1728
 
 
1729
    // first check if the selected filter extension can be used
 
1730
    {
 
1731
        if (!filterExtension.isEmpty() &&
 
1732
            validTypes.contains(filterExtension, Qt::CaseInsensitive))
 
1733
        {
 
1734
            kDebug() << "Using format from filter extension: " << filterExtension;
 
1735
            m_savingContext->format = filterExtension;
 
1736
            return true;
 
1737
        }
 
1738
    }
 
1739
 
 
1740
    // as a second step, try to determine the desired format from the extension
 
1741
    // of the target url
 
1742
    {
 
1743
        QString suffix;
 
1744
        if (targetUrl.isLocalFile())
 
1745
        {
 
1746
            // for local files QFileInfo can be used
 
1747
            QFileInfo fi(targetUrl.toLocalFile());
 
1748
            suffix = fi.suffix();
 
1749
            kDebug() << "Possible format from local file: " << suffix;
 
1750
        }
 
1751
        else
 
1752
        {
 
1753
            // for remote files string manipulation is needed unfortunately
 
1754
            QString fileName = targetUrl.fileName();
 
1755
            const int periodLocation = fileName.lastIndexOf('.');
 
1756
            if (periodLocation >= 0)
 
1757
            {
 
1758
                suffix = fileName.right(fileName.size() - periodLocation - 1);
 
1759
            }
 
1760
            kDebug() << "Possible format from remote file: " << suffix;
 
1761
        }
 
1762
        if (!suffix.isEmpty() && validTypes.contains(suffix, Qt::CaseInsensitive))
 
1763
        {
 
1764
            kDebug() << "Using format from target url " << suffix;
 
1765
            m_savingContext->format = suffix;
 
1766
            return true;
 
1767
        }
 
1768
    }
 
1769
 
 
1770
    // another way to determine the format is to use the original file
 
1771
    {
 
1772
        QString originalFormat(QImageReader::imageFormat(
 
1773
                        m_savingContext->srcURL.toLocalFile()));
 
1774
        if (validTypes.contains(originalFormat, Qt::CaseInsensitive))
 
1775
        {
 
1776
            kDebug() << "Using format from original file: " << originalFormat;
 
1777
            m_savingContext->format = originalFormat;
 
1778
            return true;
 
1779
        }
 
1780
    }
 
1781
 
 
1782
    kDebug() << "No suitable format found";
 
1783
 
 
1784
    return false;
 
1785
 
 
1786
}
 
1787
 
 
1788
bool EditorWindow::startingSaveAs(const KUrl& url)
 
1789
{
 
1790
 
 
1791
    kDebug() << "startSavingAs called";
 
1792
 
 
1793
    if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
 
1794
        return false;
 
1795
 
1589
1796
    m_savingContext->srcURL = url;
1590
1797
 
 
1798
    // prepare the save dialog
1591
1799
    FileSaveOptionsBox *options      = new FileSaveOptionsBox();
1592
1800
    KFileDialog *imageFileSaveDialog = new KFileDialog(m_savingContext->srcURL.isLocalFile() ?
1593
1801
                                                       m_savingContext->srcURL : KUrl(QDir::homePath()),
1612
1820
    KSharedConfig::Ptr config = KGlobal::config();
1613
1821
    KConfigGroup group        = config->group("ImageViewer Settings");
1614
1822
    QString ext               = group.readEntry("LastSavedImageTypeMime", "png");
1615
 
    QString fileName          = info.baseName() + QString(".") + ext;
 
1823
    QString fileName          = info.completeBaseName() + QString(".") + ext;
1616
1824
 
1617
1825
    // Determine the default filter from LastSavedImageTypeMime
1618
 
    QString defaultFilter;
1619
 
    foreach(const QString& filter, writablePattern)
1620
 
    {
1621
 
        if (filter.contains(QString("*.%1").arg(ext.toLower())))
1622
 
        {
1623
 
            defaultFilter = filter;
1624
 
            break;
1625
 
        }
1626
 
    }
1627
 
    imageFileSaveDialog->filterWidget()->setDefaultFilter(defaultFilter);
 
1826
    QStringList writablePattern = getWritingFilters();
1628
1827
    imageFileSaveDialog->setFilter(writablePattern.join(QChar('\n')));
 
1828
    QString initialFilter = findFilterByExtension(writablePattern, ext);
 
1829
    if (!initialFilter.isEmpty())
 
1830
    {
 
1831
        imageFileSaveDialog->filterWidget()->setCurrentFilter(initialFilter);
 
1832
    }
 
1833
    else
 
1834
    {
 
1835
        kWarning() << "Could not find a filter for extension " << ext
 
1836
                   << ". Is this really writable?";
 
1837
    }
 
1838
    kDebug() << "Using initial filter '" << initialFilter
 
1839
             << "' out of all possible ones:" << writablePattern;
1629
1840
    imageFileSaveDialog->setSelection(fileName);
1630
1841
 
1631
1842
    options->slotImageFileFormatChanged(ext);
1639
1850
    applyStandardSettings();
1640
1851
 
1641
1852
    KUrl newURL = imageFileSaveDialog->selectedUrl();
1642
 
 
1643
 
    // Check if target image format have been selected from Combo List of SaveAs dialog.
1644
 
 
1645
 
    QStringList mimes = KImageIO::typeForMime(imageFileSaveDialog->currentMimeFilter());
1646
 
    if (!mimes.isEmpty())
1647
 
    {
1648
 
        m_savingContext->format = mimes.first();
1649
 
    }
1650
 
    else
1651
 
    {
1652
 
        // Else, check if target image format have been add to target image file name using extension.
1653
 
 
1654
 
        QFileInfo fi(newURL.toLocalFile());
1655
 
        m_savingContext->format = fi.suffix();
1656
 
 
1657
 
        if ( m_savingContext->format.isEmpty() )
1658
 
        {
1659
 
            // If format is empty then file format is same as that of the original file.
1660
 
            m_savingContext->format = QImageReader::imageFormat(m_savingContext->srcURL.toLocalFile());
1661
 
        }
1662
 
        else
1663
 
        {
1664
 
            // Else, check if format from file name extension is include on file mime type list.
1665
 
 
1666
 
            QStringList types = KImageIO::types(KImageIO::Writing);
1667
 
            kDebug(digiKamAreaCode) << "KDE Offered types: " << types;
1668
 
 
1669
 
            types << "TIF";
1670
 
            types << "TIFF";
1671
 
            types << "JPG";
1672
 
            types << "JPEG";
1673
 
            types << "JPE";
1674
 
            types << "J2K";
1675
 
            types << "JP2";
1676
 
            types << "PGF";
1677
 
            QString imgExtList = types.join(" ");
1678
 
 
1679
 
            if ( !imgExtList.toUpper().contains( m_savingContext->format.toUpper() ) )
1680
 
            {
1681
 
                KMessageBox::error(this, i18n("Target image file format \"%1\" unsupported.", m_savingContext->format));
1682
 
                kWarning(digiKamAreaCode) << "target image file format " << m_savingContext->format << " unsupported!";
1683
 
                return false;
1684
 
            }
1685
 
        }
 
1853
    kDebug() << "Writing file to " << newURL;
 
1854
 
 
1855
    // select the format to save the image with
 
1856
    kDebug() << "filter from save dialog: " << imageFileSaveDialog->currentFilter();
 
1857
    QString dialogExtension = getExtensionFromFilter(imageFileSaveDialog->currentFilter());
 
1858
    kDebug() << "extracted extension from filter: " << dialogExtension;
 
1859
    bool validFormatSet = selectValidSavingFormat(dialogExtension, newURL);
 
1860
 
 
1861
    if (!validFormatSet)
 
1862
    {
 
1863
        KMessageBox::error(this, i18n("Unable to determine the format to save the target image with."));
 
1864
        return false;
1686
1865
    }
1687
1866
 
1688
1867
    if (!newURL.isValid())
1689
1868
    {
1690
1869
        KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".",
1691
 
                                      newURL.fileName(),
1692
 
                                      newURL.toLocalFile().section('/', -2, -2)));
1693
 
        kWarning(digiKamAreaCode) << "target URL is not valid !";
 
1870
                                      info.completeBaseName(),
 
1871
                                      newURL.prettyUrl()));
 
1872
        kWarning() << "target URL is not valid !";
1694
1873
        return false;
1695
1874
    }
1696
1875
 
1736
1915
 
1737
1916
    // Now do the actual saving -----------------------------------------------------
1738
1917
 
1739
 
    // use magic file extension which tells the digikamalbums ioslave to ignore the file
1740
 
 
1741
 
    QString tempDir = newURL.directory(KUrl::AppendTrailingSlash);
1742
 
 
1743
 
    m_savingContext->saveTempFile = new KTemporaryFile();
1744
 
    m_savingContext->saveTempFile->setPrefix(tempDir);
1745
 
    m_savingContext->saveTempFile->setSuffix(".digikamtempfile.tmp");
1746
 
    m_savingContext->saveTempFile->setAutoRemove(false);
1747
 
 
1748
 
    if (!m_savingContext->saveTempFile->open())
1749
 
    {
1750
 
        KMessageBox::error(this, i18n("Could not open a temporary file in the folder \"%1\": %2 (%3)",
1751
 
                                      tempDir, m_savingContext->saveTempFile->errorString(),
1752
 
                                      m_savingContext->saveTempFile->error()));
1753
 
        return false;
1754
 
    }
1755
 
    m_savingContext->saveTempFileName = m_savingContext->saveTempFile->fileName();
1756
 
    delete m_savingContext->saveTempFile;
1757
 
    m_savingContext->saveTempFile = 0;
 
1918
    setupTempSaveFile(newURL);
1758
1919
 
1759
1920
    m_savingContext->destinationURL = newURL;
1760
1921
    m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
1761
1922
    m_savingContext->savingState    = SavingContextContainer::SavingStateSaveAs;
 
1923
    m_savingContext->executedOperation = SavingContextContainer::SavingStateNone;
1762
1924
    m_savingContext->abortingSaving = false;
1763
1925
 
1764
1926
    m_canvas->saveAs(m_savingContext->saveTempFileName, m_IOFileSettings,
1795
1957
    return true;
1796
1958
}
1797
1959
 
1798
 
bool EditorWindow::moveFile()
 
1960
void EditorWindow::moveFile()
1799
1961
{
1800
 
    QByteArray dstFileName = QFile::encodeName(m_savingContext->destinationURL.toLocalFile());
 
1962
 
 
1963
    // how to move a file depends on if the file is on a local system or not.
 
1964
    if (m_savingContext->destinationURL.isLocalFile())
 
1965
    {
 
1966
 
 
1967
        kDebug() << "moving a local file";
 
1968
 
 
1969
        QByteArray dstFileName = QFile::encodeName(m_savingContext->destinationURL.toLocalFile());
1801
1970
#ifndef _WIN32
1802
 
    // Store old permissions:
1803
 
    // Just get the current umask.
1804
 
    mode_t curr_umask = umask(S_IREAD | S_IWRITE);
1805
 
    // Restore the umask.
1806
 
    umask(curr_umask);
1807
 
 
1808
 
    // For new files respect the umask setting.
1809
 
    mode_t filePermissions = (S_IREAD | S_IWRITE | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP) & ~curr_umask;
1810
 
 
1811
 
    // For existing files, use the mode of the original file.
1812
 
    if (m_savingContext->destinationExisted)
1813
 
    {
1814
 
        struct stat stbuf;
1815
 
        if (::stat(dstFileName, &stbuf) == 0)
 
1971
        // Store old permissions:
 
1972
        // Just get the current umask.
 
1973
        mode_t curr_umask = umask(S_IREAD | S_IWRITE);
 
1974
        // Restore the umask.
 
1975
        umask(curr_umask);
 
1976
 
 
1977
        // For new files respect the umask setting.
 
1978
        mode_t filePermissions = (S_IREAD | S_IWRITE | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP) & ~curr_umask;
 
1979
 
 
1980
        // For existing files, use the mode of the original file.
 
1981
        if (m_savingContext->destinationExisted)
1816
1982
        {
1817
 
            filePermissions = stbuf.st_mode;
 
1983
            struct stat stbuf;
 
1984
            if (::stat(dstFileName, &stbuf) == 0)
 
1985
            {
 
1986
                filePermissions = stbuf.st_mode;
 
1987
            }
1818
1988
        }
1819
 
    }
1820
1989
#endif
1821
 
    // rename tmp file to dest
1822
 
    int ret;
 
1990
        // rename tmp file to dest
 
1991
        int ret;
1823
1992
#if KDE_IS_VERSION(4,2,85)
1824
 
    // KDE 4.3.0
1825
 
    // KDE::rename() takes care of QString -> bytestring encoding
1826
 
    ret = KDE::rename(m_savingContext->saveTempFileName,
1827
 
                       m_savingContext->destinationURL.toLocalFile());
 
1993
        // KDE 4.3.0
 
1994
        // KDE::rename() takes care of QString -> bytestring encoding
 
1995
        ret = KDE::rename(m_savingContext->saveTempFileName,
 
1996
                           m_savingContext->destinationURL.toLocalFile());
1828
1997
#else
1829
 
    // KDE 4.2.x or 4.1.x
1830
 
    ret = KDE_rename(QFile::encodeName(m_savingContext->saveTempFileName),
1831
 
                      dstFileName);
1832
 
#endif
1833
 
    if (ret != 0)
1834
 
    {
1835
 
        KMessageBox::error(this, i18n("Failed to overwrite original file"),
 
1998
        // KDE 4.2.x or 4.1.x
 
1999
        ret = KDE_rename(QFile::encodeName(m_savingContext->saveTempFileName),
 
2000
                          dstFileName);
 
2001
#endif
 
2002
        if (ret != 0)
 
2003
        {
 
2004
            KMessageBox::error(this, i18n("Failed to overwrite original file"),
 
2005
                               i18n("Error Saving File"));
 
2006
            movingSaveFileFinished(false);
 
2007
            return;
 
2008
        }
 
2009
 
 
2010
#ifndef _WIN32
 
2011
        // restore permissions
 
2012
        if (::chmod(dstFileName, filePermissions) != 0)
 
2013
        {
 
2014
            kWarning() << "Failed to restore file permissions for file " << dstFileName;
 
2015
        }
 
2016
#endif
 
2017
        movingSaveFileFinished(true);
 
2018
        return;
 
2019
 
 
2020
    }
 
2021
    else
 
2022
    {
 
2023
 
 
2024
        // for remote destinations use kio to move the temp file over there
 
2025
 
 
2026
        kDebug() << "moving a remote file via KIO";
 
2027
 
 
2028
        KIO::CopyJob *moveJob = KIO::move(KUrl(
 
2029
                        m_savingContext->saveTempFileName),
 
2030
                        m_savingContext->destinationURL);
 
2031
        connect(moveJob, SIGNAL(result(KJob*)),
 
2032
                this, SLOT(slotKioMoveFinished(KJob*)));
 
2033
 
 
2034
    }
 
2035
 
 
2036
}
 
2037
 
 
2038
void EditorWindow::slotKioMoveFinished(KJob *job)
 
2039
{
 
2040
 
 
2041
    if (job->error())
 
2042
    {
 
2043
        KMessageBox::error(this, i18n("Failed to save file: %1", job->errorString()),
1836
2044
                           i18n("Error Saving File"));
1837
 
        return false;
1838
2045
    }
1839
2046
 
1840
 
#ifndef _WIN32
1841
 
    // restore permissions
1842
 
    if (::chmod(dstFileName, filePermissions) != 0)
1843
 
    {
1844
 
        kWarning(digiKamAreaCode) << "Failed to restore file permissions for file " << dstFileName;
1845
 
    }
1846
 
#endif
1847
 
    return true;
 
2047
    movingSaveFileFinished(!job->error());
1848
2048
}
1849
2049
 
1850
2050
void EditorWindow::slotColorManagementOptionsChanged()
1929
2129
    d->exposureSettings->underExposureIndicator = on;
1930
2130
    m_canvas->setExposureSettings(d->exposureSettings);
1931
2131
 
1932
 
    d->underExposureIndicator->setChecked(on);
 
2132
    d->underExposureIndicator->setEnabled(on);
1933
2133
    d->viewUnderExpoAction->setChecked(on);
1934
2134
    setUnderExposureToolTip(on);
1935
2135
}
1946
2146
    d->exposureSettings->overExposureIndicator = on;
1947
2147
    m_canvas->setExposureSettings(d->exposureSettings);
1948
2148
 
1949
 
    d->overExposureIndicator->setChecked(on);
 
2149
    d->overExposureIndicator->setEnabled(on);
1950
2150
    d->viewOverExpoAction->setChecked(on);
1951
2151
    setOverExposureToolTip(on);
1952
2152
}