Bug 106508

Summary: Please change scaling behavior
Product: [Applications] digikam Reporter: Dik Takken <kde>
Component: ImageEditor-CanvasAssignee: Digikam Developers <digikam-bugs-null>
Status: RESOLVED FIXED    
Severity: wishlist CC: ach, anaselli, caulier.gilles, cimmino.marco
Priority: NOR    
Version: 0.7.2   
Target Milestone: ---   
Platform: Gentoo Packages   
OS: Linux   
Latest Commit: Version Fixed In: 0.9.2
Attachments: showfoto_print_improvement.patch.bz2

Description Dik Takken 2005-05-30 16:36:09 UTC
Version:           0.7.2 (using KDE KDE 3.3.2)
Installed from:    Gentoo Packages
OS:                Linux

It can be a bit frustrating when you always need to hit 'zoom out' ten times before you can see the whole image.

Please scale the image to fit in the window immediately after opening the image.
Comment 1 Joern Ahrens 2005-05-30 19:40:41 UTC
Then you should use "Zoom AutoFit" from the toolbar or the View menu.
We have a nice handbook ;-)
Comment 2 Dik Takken 2005-05-30 20:37:26 UTC
Sorry, It did not come to my mind that this option in the View menu could be a toggle. And I know a few other users who would be pleasantly surprised if I would show it to them as well.

The thing is, with other graphics applications, examining your photo's usually works like this:

* You open the image, it is automatically scaled to sane dimensions. By default.
* You use the 'zoom in' control to zoom in and check the detail level. Or even quicker: You choose '100%' from the zoom drop-down menu.

With DigiKam, 'fit to window' toggle disabled, it works different:

* You open the image, it is displayed at 100% by default, so you can't see a thing. 
* You use the 'zoom out' control five or six times to zoom out and see the whole image.
* You use the 'zoom in' control five or six times to zoom in again, to examine interesting parts of the image.

and when 'fit to window' is enabled:

* You open the image, it is automatically scaled to sane dimensions.
* You disable the 'fit to window' option in order to be able to use the zoom controls. The image viewer throws you back to 100% and you're completely lost again.
* You use the 'zoom out' function a couple of times to get an idea of where you are.
* You scroll to an interesting part of the image
* You use the 'zoom in' function a couple of times to examine the part of image you are interested in.

I guess people are so much used to the way things usually work, it does not come to their mind that DigiKam may work completely different in this respect. The 'fit to window' option is usually never a toggle but a function that just calculates the right zoom factor for you, and apply it. Also, most applications scale the image on opening to sane size, by default. People are used to that. Hitting the 'scale to fit window' button in DigiKam has another unexpected effect: it disables all zoom controls.

So consider this bugreport a usability report in stead.

And yes, I will RTFM when I find some time.. :)
Comment 3 Dik Takken 2005-06-02 13:59:17 UTC
Shall I reopen this bug and change the summary to a request for a different scaling behavior?
Comment 4 Renchi Raju 2005-06-02 19:02:51 UTC
please do
Comment 5 Joern Ahrens 2005-06-02 22:11:00 UTC
Yes, go ahead. There are some good points.
Comment 6 Dik Takken 2005-06-04 14:15:21 UTC
Reopened bug.
Comment 7 Wilbert Berendsen 2005-11-01 09:55:21 UTC
Yes, I was going to report this as well. I think that a good solution is to not disable the + and - buttons while autofit is enabled.

Then you can just zoom in instead of having to disable autofit first (which throws you at a 100% size which can be very large due to todays camera's (my new one has 7mp)).

But the autofit should not switch off when zooming. (If autofit is on, paging to the next photo will display it autofit again). The idea is thus that autofit is just a feature that kicks in on initial display of the image (and on resize of the viewport), but that after displaying the image leaves the user free to zoom it in or out without having to disable autofit first.
Comment 8 Marco Cimmino 2006-12-29 23:53:12 UTC
Totally agree with Wilbert last comment, ok for "fit to screen" buttons, but zoom ones never goes off.
It's totally user unfriendly the behaviour like it's now also in digikam 0.9

please change it :)
Comment 9 Achim Bohnet 2006-12-30 00:04:31 UTC
I stumbled too over the disabled zoom in/out buttons.
I had a look at gwenview, kpdf and kghostview.  Both
use the same zoom in/out/fit combo of buttons in the status
bar, with fit to window as default.

For consistency amoung KDE apps I also like to see digikam
using the same widgets for zoom handling, with fit to screen
as default.

Achim
FWIW: https://bugs.kde.org/show_bug.cgi?id=137236 is related,
if not a duplicate of this bug.
Comment 10 Angelo Naselli 2006-12-30 13:59:59 UTC
Well gwenview has a better implementation ;)
Can you test this patch? It's not all you asked for,
but I can improve it if you like, porting more code
from the one i implemented for gwenview.

To reporters, try to use gwenview by now for that
even if it has a little bug I'm working, that
does not restore the scale option enabled.

Regards,
	Angelo 

----------  Messaggio inoltrato  ----------

Subject: [Digikam-devel] image editor and print option (patch)
Date: 22:08, venerdì 29 dicembre 2006
From: Angelo Naselli <anaselli at linux dot it>
To: digikam-devel@kde.org

Hi,
first of all I'd like to introduce myself, as some of you know
I'm kipi's project coordinator and an occasional developer.
Since I like the way gwenview prints photos (maybe just
because I did, but I did because i'd have liked to have it :) )
I decided to port that code here. I mean there are two ways
to print, either using kipi-plugins or using image editor.
The first one is the best, but sometime i like to print out an
image just because i'm watching it. If I use gwenview the code
allows it and manages two options that are missed here e.g.
keep ratio and alignment. Well there is something more but i've 
spent a lot of time to insert gui objects, I'm not very good at it
and i prefer to use ui files and designer (Gilles I know you don't,
but it's very easy for occasional contributors), so the code is still
in gwenview. Just want to recall the B&W option I cannot believe someone
ever used it, two colors, better using grayscale, but that is a driver
option, so no need to add it ;) (even if the preview is not good)
IIRC the so called "fit to page" option works if an image has to
be enlarge and not shrinked... And all of that is in gwenview
code.
Anyway the attached patch is something that improve the print function.
Hope you'll like it and commit (i can do it if you like).

Just another thought, why trash is near print in the menu, it seems 
a bit dangerous...

Regards,
	Angelo


Created an attachment (id=19069)
showfoto_print_improvement.patch.bz2
Comment 11 Angelo Naselli 2006-12-30 14:20:38 UTC
sorry I've totally misunderstood the subject... I should stop drinking ;)
sorry again for my intrusion....
Comment 12 caulier.gilles 2007-03-19 23:52:12 UTC
SVN commit 644437 by cgilles:

digiKam from trunk : add a combo box with a pre-zoom selection options like gimp prvovide. You can enter a customized zoom scale value if you want.

BUG: 106508

 M  +22 -26    canvas/canvas.cpp  
 M  +1 -0      canvas/canvas.h  
 M  +2 -1      editor/digikamimagewindowui.rc  
 M  +56 -7     editor/editorwindow.cpp  
 M  +3 -1      editor/editorwindow.h  
 M  +8 -0      editor/editorwindowprivate.h  


--- trunk/extragear/graphics/digikam/utilities/imageeditor/canvas/canvas.cpp #644436:644437
@@ -1,6 +1,6 @@
 /* ============================================================
  * Authors: Renchi Raju <renchi@pooh.tam.uiuc.edu>
- *         Gilles Caulier <caulier dot gilles at gmail dot com>
+ *          Gilles Caulier <caulier dot gilles at gmail dot com>
  * Date   : 2003-01-09
  * Description : image editor canvas management class
  * 
@@ -70,16 +70,15 @@
 
 public:
 
-    CanvasPrivate() :
-        tileSize(128), maxZoom(8.0)
+    CanvasPrivate() : 
+        tileSize(128), minZoom(0.1), maxZoom(10.0), zoomStep(0.1) 
     {
-        tileCache.setMaxCost((10*1024*1024)/(tileSize*tileSize*4));
-        tileCache.setAutoDelete(true);
-
         parent          = 0;
         im              = 0;
         rubber          = 0;
         paintTimer      = 0;
+        tileCache.setMaxCost((10*1024*1024)/(tileSize*tileSize*4));
+        tileCache.setAutoDelete(true);
     }
 
     bool               autoZoom;
@@ -97,7 +96,9 @@
     int                midButtonY;
     
     double             zoom;
+    const double       minZoom;
     const double       maxZoom;
+    const double       zoomStep;
 
     QRect             *rubber;
     QRect              pixmapRect;
@@ -114,7 +115,6 @@
     QWidget           *parent;
     
     DImgInterface     *im;
-
 };
 
 Canvas::Canvas(QWidget *parent)
@@ -817,12 +817,12 @@
 
 bool Canvas::maxZoom()
 {
-    return ((d->zoom + 1.0/16.0) >= d->maxZoom);
+    return ((d->zoom + d->zoomStep) >= d->maxZoom);
 }
 
 bool Canvas::minZoom()
 {
-    return ((d->zoom - 1.0/16.0) <= 0.1);
+    return ((d->zoom - d->zoomStep) <= d->minZoom);
 }
 
 bool Canvas::exifRotated()
@@ -832,33 +832,29 @@
 
 void Canvas::slotIncreaseZoom()
 {
-    if (d->autoZoom || maxZoom())
+    if (maxZoom())
         return;
 
-    float cpx = (contentsX() + visibleWidth()  / 2.0) / d->zoom; 
-    float cpy = (contentsY() + visibleHeight() / 2.0) / d->zoom; 
+    setZoomFactor(d->zoom + d->zoomStep);
+}
 
-    d->zoom = d->zoom + 1.0/16.0;
-    d->im->zoom(d->zoom);
-    updateContentsSize();
+void Canvas::slotDecreaseZoom()
+{
+    if (minZoom())
+        return;
 
-    viewport()->setUpdatesEnabled(false);
-    center((int)(cpx * d->zoom), (int)(cpy * d->zoom));
-    viewport()->setUpdatesEnabled(true);
-    viewport()->update();
-
-    emit signalZoomChanged(d->zoom);
+    setZoomFactor(d->zoom - d->zoomStep);
 }
 
-void Canvas::slotDecreaseZoom()
+void Canvas::setZoomFactor(float zoom)
 {
-    if (d->autoZoom || minZoom())
+    if (d->autoZoom)
         return;
 
     float cpx = (contentsX() + visibleWidth()  / 2.0) / d->zoom; 
-    float cpy = (contentsY() + visibleHeight() / 2.0) / d->zoom;
- 
-    d->zoom = d->zoom - 1.0/16.0;    
+    float cpy = (contentsY() + visibleHeight() / 2.0) / d->zoom; 
+
+    d->zoom = zoom;
     d->im->zoom(d->zoom);
     updateContentsSize();
 
--- trunk/extragear/graphics/digikam/utilities/imageeditor/canvas/canvas.h #644436:644437
@@ -75,6 +75,7 @@
     DImg  currentImage();
     QString currentImageFileFormat();
 
+    void  setZoomFactor(float z);
     bool  maxZoom();
     bool  minZoom();
     bool  exifRotated();
--- trunk/extragear/graphics/digikam/utilities/imageeditor/editor/digikamimagewindowui.rc #644436:644437
@@ -1,5 +1,5 @@
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<gui version="10" name="digikamimagewindow" >
+<gui version="11" name="digikamimagewindow" >
 
 <MenuBar>
 
@@ -87,6 +87,7 @@
      <Action name="editorwindow_revert" />
      <Separator/>     
      <Action name="editorwindow_zoomplus" /> 
+     <Action name="editorwindow_zoomto" />
      <Action name="editorwindow_zoomminus" /> 
      <Action name="editorwindow_zoomfit" /> 
      <Separator/>     
--- trunk/extragear/graphics/digikam/utilities/imageeditor/editor/editorwindow.cpp #644436:644437
@@ -26,6 +26,10 @@
 #include <sys/stat.h>
 }
 
+// C++ includes.
+
+#include <cmath>
+
 // Qt includes.
 
 #include <qlabel.h>
@@ -70,6 +74,7 @@
 #include <kstatusbar.h>
 #include <kprogress.h>
 #include <kwin.h>
+#include <kcombobox.h>
 
 // Local includes.
 
@@ -311,12 +316,41 @@
 
     d->zoomPlusAction = KStdAction::zoomIn(m_canvas, SLOT(slotIncreaseZoom()),
                                           actionCollection(), "editorwindow_zoomplus");
+
+
     d->zoomMinusAction = KStdAction::zoomOut(m_canvas, SLOT(slotDecreaseZoom()),
                                              actionCollection(), "editorwindow_zoomminus");
+
     d->zoomFitAction = new KToggleAction(i18n("Zoom &AutoFit"), "viewmagfit",
                                          CTRL+SHIFT+Key_A, this, SLOT(slotToggleAutoZoom()),
                                          actionCollection(), "editorwindow_zoomfit");
 
+    d->zoomCombo = new KComboBox(true);
+    d->zoomCombo->setDuplicatesEnabled(false);
+    d->zoomCombo->setFocusPolicy(ClickFocus);
+    d->zoomCombo->setInsertionPolicy(QComboBox::NoInsertion);
+    d->zoomComboAction = new KWidgetAction(d->zoomCombo, i18n("Zoom"), 0, 0, 0, 
+                                           actionCollection(), "editorwindow_zoomto");
+
+    d->zoomCombo->insertItem(QString("10%"));
+    d->zoomCombo->insertItem(QString("25%"));
+    d->zoomCombo->insertItem(QString("50%"));
+    d->zoomCombo->insertItem(QString("75%"));
+    d->zoomCombo->insertItem(QString("100%"));
+    d->zoomCombo->insertItem(QString("150%"));
+    d->zoomCombo->insertItem(QString("200%"));
+    d->zoomCombo->insertItem(QString("300%"));
+    d->zoomCombo->insertItem(QString("450%"));
+    d->zoomCombo->insertItem(QString("600%"));
+    d->zoomCombo->insertItem(QString("800%"));
+
+    connect(d->zoomCombo, SIGNAL(activated(int)),
+            this, SLOT(slotZoomSelected()) );
+
+    connect(d->zoomCombo, SIGNAL(returnPressed(const QString&)),
+            this, SLOT(slotZoomTextChanged(const QString &)) );
+
+
 #if KDE_IS_VERSION(3,2,0)
     m_fullScreenAction = KStdAction::fullScreen(this, SLOT(slotToggleFullScreen()),
                                                 actionCollection(), this, "editorwindow_fullscreen");
@@ -618,21 +652,36 @@
     bool checked = d->zoomFitAction->isChecked();
 
     d->zoomPlusAction->setEnabled(!checked);
+    d->zoomComboAction->setEnabled(!checked);
     d->zoomMinusAction->setEnabled(!checked);
 
     m_canvas->slotToggleAutoZoom();
 }
 
+void EditorWindow::slotZoomTextChanged(const QString &txt)
+{
+    double zoom = KGlobal::locale()->readNumber(txt) / 100.0;
+    if (zoom > 0.0)
+        m_canvas->setZoomFactor(zoom);
+}
+
+void EditorWindow::slotZoomSelected()
+{
+    QString txt = d->zoomCombo->currentText();
+    txt = txt.left(txt.find('%'));
+    slotZoomTextChanged(txt);
+}
+
 void EditorWindow::slotZoomChanged(float zoom)
 {
-    m_zoomLabel->setText(i18n("Zoom: ") +
-                         QString::number(zoom*100, 'f', 2) +
-                         QString("%"));
+    m_zoomLabel->setText(i18n("Zoom: %1%").arg(QString::number(lround(zoom*100.0))));
 
-    d->zoomPlusAction->setEnabled(!m_canvas->maxZoom() &&
-                                 !d->zoomFitAction->isChecked());
-    d->zoomMinusAction->setEnabled(!m_canvas->minZoom() &&
-                                  !d->zoomFitAction->isChecked());
+    d->zoomPlusAction->setEnabled(!m_canvas->maxZoom() && !d->zoomFitAction->isChecked());
+    d->zoomMinusAction->setEnabled(!m_canvas->minZoom() && !d->zoomFitAction->isChecked());
+
+    d->zoomCombo->blockSignals(true);
+    d->zoomCombo->setCurrentText(QString::number(lround(zoom*100.0)) + QString("%"));
+    d->zoomCombo->blockSignals(false);
 }
 
 void EditorWindow::slotEscapePressed()
--- trunk/extragear/graphics/digikam/utilities/imageeditor/editor/editorwindow.h #644436:644437
@@ -173,7 +173,6 @@
     void slotEscapePressed();
 
     void slotToggleAutoZoom();
-    void slotZoomChanged(float zoom);
     void slotSelected(bool);
 
     void slotLoadingProgress(const QString& filePath, float progress);
@@ -206,6 +205,9 @@
     void slotSavingFinished(const QString &filename, bool success);
     void slotDonateMoney();
     void slotToggleSlideShow();
+    void slotZoomSelected();
+    void slotZoomTextChanged(const QString &);
+    void slotZoomChanged(float zoom);
 
 private:
 
--- trunk/extragear/graphics/digikam/utilities/imageeditor/editor/editorwindowprivate.h #644436:644437
@@ -24,8 +24,10 @@
 
 class QToolButton;
 
+class KComboBox;
 class KAction;
 class KToggleAction;
+class KWidgetAction;
 class KSelectAction;
 class KActionMenu;
 class KAccel;
@@ -72,6 +74,8 @@
         viewUnderExpoAction    = 0;
         viewOverExpoAction     = 0;
         slideShowAction        = 0;
+        zoomCombo              = 0;
+        zoomComboAction        = 0;
     }
 
     ~EditorWindowPriv()
@@ -82,6 +86,8 @@
     bool                       fullScreenHideToolBar;
     bool                       slideShowInFullScreen;
 
+    KComboBox                 *zoomCombo;
+
     QToolButton               *cmViewIndicator;
     QToolButton               *underExposureIndicator; 
     QToolButton               *overExposureIndicator; 
@@ -108,6 +114,8 @@
     KToggleAction             *viewUnderExpoAction;
     KToggleAction             *viewOverExpoAction;
 
+    KWidgetAction             *zoomComboAction;
+
     KAccel                    *accelerators;
 
     ICCSettingsContainer      *ICCSettings;
Comment 13 Arnd Baecker 2007-03-20 09:06:40 UTC
Hi Gilles, 

great that you tackle the issue of zooming!!!
However, I think not all points discussed above have been considered,
in particular #7: """ I think that a good solution is to not disable the + and - buttons while autofit is enabled."""

Apart from that: There is maybe one more issue with the Combo-Box: 
if you put it on (for example) 50% and then go 
from one image to the next, it switches back to 100%.
Shouldn't it just stay the same?

Maybe one could get completely rid of the "autozoom toggle"
if the Combo-box get's another entry "fit"?

(And, just for completeness: there is also the related 
http://bugs.kde.org/show_bug.cgi?id=103645)
Comment 14 caulier.gilles 2007-03-20 09:12:33 UTC
Arnd,

Yes, i know #103645. I will try to fix it too. I'm currently working on all editor Zoom stuff...

Gilles
Comment 15 Arnd Baecker 2007-05-17 05:00:47 UTC
While this bug has been marked as fixed, I don't think 
that it has been addressed completely.
Therefore I suggest to re-open because the following should
be realized:
- do not disable the + and - buttons while autofit is enabled. 

  This is the main open point, see #2, #7, #9.

Additionally:
- If auto-fit is active, and then zooming is used, the
  auto-fit should be de-activated.
  This ensures that one still (i.e. as it works nicely right now)
  can go from one image to the next without loosing the current 
  zoom-level and position; This allows to compare two (or more)
  images in a certain region by just going back-and-forth 

- Minor detail: 
  The order of the buttons should be changed to
  [- Zoom out] [ % ] [+ Zoom in]
  to be consistent with the usual ordering as in the preview widget
  or light-table.
Comment 16 Laurent COOPER 2007-07-20 23:40:39 UTC
Hello

(excuse broken english below)

Bug 137236 resolution patch introduces a strange behavior. When an image is small, the autofit toggle bring it to window size. Small images should, IMHO, not be resized BIGGER than what they are. This can produce ugly things.

Very annoying when I'm working on directories with two types of pictures : large pictures taken with DSLR, and small picture resized of the DSLR one to fit web pages.

The DSLR pictures are resized to fit into windows. Very good.

The web picture (600x400) are resized to almost 1200x800, so they definitely look ugly.

If I untoggle the autofit button, the next DSLR picture, 3800x2600 is impossible to look at. So I must toggle on each pictures.

Hope it helps. 

You can contact me for any explanation (in french if you like)
Comment 17 Krisztian Toth 2007-08-26 22:07:05 UTC
I have to say the same as Laurent did in #16. Meanwhile I found a bug report #126127. So I realized this behavior based on a wish. So could you make this feature configurable? I mean some people would like to see the low resolution picture enlarged when fit to window enabled, some people like Laurent and would like to see these pictures on original size. Because enlarged low resolution pictures are ugly.