You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/kolourpaint/kpmainwindow_view.cpp

1152 lines
34 KiB

/*
Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define DEBUG_ZOOM_FLICKER 0
#include <kpmainwindow.h>
#include <kpmainwindow_p.h>
#include <tqdatetime.h>
#include <tqpainter.h>
#include <tqtimer.h>
#include <kactionclasses.h>
#include <kapplication.h>
#include <tdeconfig.h>
#include <kdebug.h>
#include <klocale.h>
#include <kstdaction.h>
#include <kpdefs.h>
#include <kpdocument.h>
#include <kpthumbnail.h>
#include <kptool.h>
#include <kptooltoolbar.h>
#include <kpunzoomedthumbnailview.h>
#include <kpviewmanager.h>
#include <kpviewscrollablecontainer.h>
#include <kpwidgetmapper.h>
#include <kpzoomedview.h>
#include <kpzoomedthumbnailview.h>
// private
void kpMainWindow::setupViewMenuActions ()
{
m_viewMenuDocumentActionsEnabled = false;
m_thumbnailSaveConfigTimer = 0;
KActionCollection *ac = actionCollection ();
/*m_actionFullScreen = KStdAction::fullScreen (0, 0, ac);
m_actionFullScreen->setEnabled (false);*/
m_actionActualSize = KStdAction::actualSize (TQT_TQOBJECT(this), TQT_SLOT (slotActualSize ()), ac);
/*m_actionFitToPage = KStdAction::fitToPage (TQT_TQOBJECT(this), TQT_SLOT (slotFitToPage ()), ac);
m_actionFitToWidth = KStdAction::fitToWidth (TQT_TQOBJECT(this), TQT_SLOT (slotFitToWidth ()), ac);
m_actionFitToHeight = KStdAction::fitToHeight (TQT_TQOBJECT(this), TQT_SLOT (slotFitToHeight ()), ac);*/
m_actionZoomIn = KStdAction::zoomIn (TQT_TQOBJECT(this), TQT_SLOT (slotZoomIn ()), ac);
m_actionZoomOut = KStdAction::zoomOut (TQT_TQOBJECT(this), TQT_SLOT (slotZoomOut ()), ac);
m_actionZoom = new KSelectAction (i18n ("&Zoom"), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotZoom ()), actionCollection (), "view_zoom_to");
m_actionZoom->setEditable (true);
// create the zoom list for the 1st call to zoomTo() below
m_zoomList.append (10); m_zoomList.append (25); m_zoomList.append (33);
m_zoomList.append (50); m_zoomList.append (67); m_zoomList.append (75);
m_zoomList.append (100);
m_zoomList.append (200); m_zoomList.append (300);
m_zoomList.append (400); m_zoomList.append (600); m_zoomList.append (800);
m_zoomList.append (1000); m_zoomList.append (1200); m_zoomList.append (1600);
m_actionShowGrid = new KToggleAction (i18n ("Show &Grid"), CTRL + Key_G,
TQT_TQOBJECT(this), TQT_SLOT (slotShowGridToggled ()), actionCollection (), "view_show_grid");
m_actionShowGrid->setCheckedState (i18n ("Hide &Grid"));
// TODO: This doesn't work when the thumbnail has focus.
// Testcase: Press CTRL+H twice on a fresh KolourPaint.
// The second CTRL+H doesn't close the thumbnail.
m_actionShowThumbnail = new KToggleAction (i18n ("Show T&humbnail"), CTRL + Key_H,
TQT_TQOBJECT(this), TQT_SLOT (slotShowThumbnailToggled ()), actionCollection (), "view_show_thumbnail");
m_actionShowThumbnail->setCheckedState (i18n ("Hide T&humbnail"));
// Please do not use setCheckedState() here - it wouldn't make sense
m_actionZoomedThumbnail = new KToggleAction (i18n ("Zoo&med Thumbnail Mode"), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotZoomedThumbnailToggled ()), actionCollection (), "view_zoomed_thumbnail");
// For consistency with the above action, don't use setCheckedState()
//
// Also, don't use "Show Thumbnail Rectangle" because if entire doc
// can be seen in scrollView, checking option won't "Show" anything
// since rect _surrounds_ entire doc (hence, won't be rendered).
d->m_actionShowThumbnailRectangle = new KToggleAction (
i18n ("Enable Thumbnail &Rectangle"),
0,
TQT_TQOBJECT(this), TQT_SLOT (slotThumbnailShowRectangleToggled ()),
actionCollection (), "view_show_thumbnail_rectangle");
enableViewMenuDocumentActions (false);
}
// private
bool kpMainWindow::viewMenuDocumentActionsEnabled () const
{
return m_viewMenuDocumentActionsEnabled;
}
// private
void kpMainWindow::enableViewMenuDocumentActions (bool enable)
{
m_viewMenuDocumentActionsEnabled = enable;
m_actionActualSize->setEnabled (enable);
/*m_actionFitToPage->setEnabled (enable);
m_actionFitToWidth->setEnabled (enable);
m_actionFitToHeight->setEnabled (enable);*/
m_actionZoomIn->setEnabled (enable);
m_actionZoomOut->setEnabled (enable);
m_actionZoom->setEnabled (enable);
actionShowGridUpdate ();
m_actionShowThumbnail->setEnabled (enable);
enableThumbnailOptionActions (enable);
// TODO: for the time being, assume that we start at zoom 100%
// with no grid
// This function is only called when a new document is created
// or an existing document is closed. So the following will
// always be correct:
zoomTo (100);
}
// private
void kpMainWindow::actionShowGridUpdate ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::actionShowGridUpdate()" << endl;
#endif
const bool enable = (viewMenuDocumentActionsEnabled () &&
m_mainView && m_mainView->canShowGrid ());
m_actionShowGrid->setEnabled (enable);
m_actionShowGrid->setChecked (enable && m_configShowGrid);
}
// private
void kpMainWindow::sendZoomListToActionZoom ()
{
TQStringList items;
const TQValueVector <int>::ConstIterator zoomListEnd (m_zoomList.end ());
for (TQValueVector <int>::ConstIterator it = m_zoomList.begin ();
it != zoomListEnd;
it++)
{
items << zoomLevelToString (*it);
}
// Work around a KDE bug - KSelectAction::setItems() enables the action.
// David Faure said it won't be fixed because it's a feature used by
// KRecentFilesAction.
bool e = m_actionZoom->isEnabled ();
m_actionZoom->setItems (items);
if (e != m_actionZoom->isEnabled ())
m_actionZoom->setEnabled (e);
}
// private
int kpMainWindow::zoomLevelFromString (const TQString &string)
{
// loop until not digit
int i;
for (i = 0; i < (int) string.length () && string.at (i).isDigit (); i++)
;
// convert zoom level to number
bool ok = false;
int zoomLevel = string.left (i).toInt (&ok);
if (!ok || zoomLevel <= 0 || zoomLevel > 3200)
return 0; // error
else
return zoomLevel;
}
// private
TQString kpMainWindow::zoomLevelToString (int zoomLevel)
{
return i18n ("%1%").arg (zoomLevel);
}
// private
void kpMainWindow::zoomTo (int zoomLevel, bool centerUnderCursor)
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::zoomTo (" << zoomLevel << ")" << endl;
#endif
if (zoomLevel <= 0)
zoomLevel = m_mainView ? m_mainView->zoomLevelX () : 100;
// mute point since the thumbnail suffers from this too
#if 0
else if (m_mainView && m_mainView->zoomLevelX () % 100 == 0 && zoomLevel % 100)
{
if (KMessageBox::warningContinueCancel (this,
i18n ("Setting the zoom level to a value that is not a multiple of 100% "
"results in imprecise editing and redraw glitches.\n"
"Do you really want to set to zoom level to %1%?")
.arg (zoomLevel),
TQString()/*caption*/,
i18n ("Set Zoom Level to %1%").arg (zoomLevel),
"DoNotAskAgain_ZoomLevelNotMultipleOf100") != KMessageBox::Continue)
{
zoomLevel = m_mainView->zoomLevelX ();
}
}
#endif
int index = 0;
TQValueVector <int>::Iterator it = m_zoomList.begin ();
while (index < (int) m_zoomList.count () && zoomLevel > *it)
it++, index++;
if (zoomLevel != *it)
m_zoomList.insert (it, zoomLevel);
sendZoomListToActionZoom ();
m_actionZoom->setCurrentItem (index);
if (viewMenuDocumentActionsEnabled ())
{
m_actionActualSize->setEnabled (zoomLevel != 100);
m_actionZoomIn->setEnabled (m_actionZoom->currentItem () < (int) m_zoomList.count () - 1);
m_actionZoomOut->setEnabled (m_actionZoom->currentItem () > 0);
}
if (m_viewManager)
m_viewManager->setQueueUpdates ();
if (m_scrollView)
{
m_scrollView->setUpdatesEnabled (false);
if (m_scrollView->viewport ())
m_scrollView->viewport ()->setUpdatesEnabled (false);
}
if (m_mainView)
{
m_mainView->setUpdatesEnabled (false);
if (m_scrollView && m_scrollView->viewport ())
{
// Ordinary flicker is better than the whole view moving
TQPainter p (m_mainView);
p.fillRect (m_mainView->rect (),
m_scrollView->viewport ()->colorGroup ().background ());
}
}
if (m_scrollView && m_mainView)
{
#if DEBUG_KP_MAIN_WINDOW && 1
kdDebug () << "\tscrollView contentsX=" << m_scrollView->contentsX ()
<< " contentsY=" << m_scrollView->contentsY ()
<< " contentsWidth=" << m_scrollView->contentsWidth ()
<< " contentsHeight=" << m_scrollView->contentsHeight ()
<< " visibleWidth=" << m_scrollView->visibleWidth ()
<< " visibleHeight=" << m_scrollView->visibleHeight ()
<< " oldZoomX=" << m_mainView->zoomLevelX ()
<< " oldZoomY=" << m_mainView->zoomLevelY ()
<< " newZoom=" << zoomLevel
<< " mainViewX=" << m_scrollView->childX (m_mainView)
<< " mainViewY=" << m_scrollView->childY (m_mainView)
<< endl;
#endif
// TODO: when changing from no scrollbars to scrollbars, TQt lies about
// visibleWidth() & visibleHeight() (doesn't take into account the
// space taken by the would-be scrollbars) until it updates the
// scrollview; hence the centring is off by about 5-10 pixels.
// TODO: use visibleRect() for greater accuracy?
int viewX, viewY;
bool targetDocAvail = false;
double targetDocX, targetDocY;
if (centerUnderCursor &&
m_viewManager && m_viewManager->viewUnderCursor ())
{
kpView *const vuc = m_viewManager->viewUnderCursor ();
TQPoint viewPoint = vuc->mouseViewPoint ();
// vuc->transformViewToDoc() returns TQPoint which only has int
// accuracy so we do X and Y manually.
targetDocX = vuc->transformViewToDocX (viewPoint.x ());
targetDocY = vuc->transformViewToDocY (viewPoint.y ());
targetDocAvail = true;
if (vuc != m_mainView)
viewPoint = vuc->transformViewToOtherView (viewPoint, m_mainView);
viewX = viewPoint.x ();
viewY = viewPoint.y ();
}
else
{
viewX = m_scrollView->contentsX () +
TQMIN (m_mainView->width (),
m_scrollView->visibleWidth ()) / 2;
viewY = m_scrollView->contentsY () +
TQMIN (m_mainView->height (),
m_scrollView->visibleHeight ()) / 2;
}
int newCenterX = viewX * zoomLevel / m_mainView->zoomLevelX ();
int newCenterY = viewY * zoomLevel / m_mainView->zoomLevelY ();
m_mainView->setZoomLevel (zoomLevel, zoomLevel);
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just setZoomLevel" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
#if DEBUG_KP_MAIN_WINDOW && 1
kdDebug () << "\tvisibleWidth=" << m_scrollView->visibleWidth ()
<< " visibleHeight=" << m_scrollView->visibleHeight ()
<< endl;
kdDebug () << "\tnewCenterX=" << newCenterX
<< " newCenterY=" << newCenterY << endl;
#endif
m_scrollView->center (newCenterX, newCenterY);
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just centred" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 2000)
;
}
#endif
if (centerUnderCursor &&
targetDocAvail &&
m_viewManager && m_viewManager->viewUnderCursor ())
{
kpView *const vuc = m_viewManager->viewUnderCursor ();
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tcenterUnderCursor: reposition cursor; viewUnderCursor="
<< vuc->name () << endl;
#endif
const double viewX = vuc->transformDocToViewX (targetDocX);
const double viewY = vuc->transformDocToViewY (targetDocY);
// Rounding error from zooming in and out :(
// TODO: do everything in terms of tool doc points in type "double".
const TQPoint viewPoint ((int) viewX, (int) viewY);
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tdoc: (" << targetDocX << "," << targetDocY << ")"
<< " viewUnderCursor: (" << viewX << "," << viewY << ")"
<< endl;
#endif
if (vuc->clipRegion ().contains (viewPoint))
{
const TQPoint globalPoint =
kpWidgetMapper::toGlobal (vuc, viewPoint);
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tglobalPoint=" << globalPoint << endl;
#endif
// TODO: Determine some sane cursor flashing indication -
// cursor movement is convenient but not conventional.
//
// Major problem: if using TQApplication::setOverrideCursor()
// and in some stage of flash and window quits.
//
// Or if using kpView::setCursor() and change tool.
TQCursor::setPos (globalPoint);
}
// e.g. Zoom to 200%, scroll mainView to bottom-right.
// Unzoomed Thumbnail shows top-left portion of bottom-right of
// mainView.
//
// Aim cursor at bottom-right of thumbnail and zoom out with
// CTRL+Wheel.
//
// If mainView is now small enough to largely not need scrollbars,
// Unzoomed Thumbnail scrolls to show _top-left_ portion
// _of top-left_ of mainView.
//
// Unzoomed Thumbnail no longer contains the point we zoomed out
// on top of.
else
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\twon't move cursor - would get outside view"
<< endl;
#endif
// TODO: Sane cursor flashing indication that indicates
// that the normal cursor movement didn't happen.
}
}
#if DEBUG_KP_MAIN_WINDOW && 1
kdDebug () << "\t\tcheck (contentsX=" << m_scrollView->contentsX ()
<< ",contentsY=" << m_scrollView->contentsY ()
<< ")" << endl;
#endif
}
if (m_mainView)
{
actionShowGridUpdate ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: updated grid action" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
updateMainViewGrid ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just updated grid" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
// Since Zoom Level KSelectAction on ToolBar grabs focus after changing
// Zoom, switch back to the Main View.
// TODO: back to the last view
m_mainView->setFocus ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just set focus to mainview" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
}
#if 1
// The view magnified and moved beneath the cursor
if (tool ())
tool ()->somethingBelowTheCursorChanged ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: signalled something below cursor" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
#endif
// HACK: make sure all of TQt's update() calls trigger
// kpView::paintEvent() _now_ so that they can be queued by us
// (until kpViewManager::restoreQueueUpdates()) to reduce flicker
// caused mainly by m_scrollView->center()
//
// TODO: remove flicker completely
//TQTimer::singleShot (0, TQT_TQOBJECT(this), TQT_SLOT (finishZoomTo ()));
// Later: I don't think there is an update() that needs to be queued
// - let's reduce latency instead.
finishZoomTo ();
}
// private slot
void kpMainWindow::finishZoomTo ()
{
#if DEBUG_KP_MAIN_WINDOW && 1
kdDebug () << "\tkpMainWindow::finishZoomTo enter" << endl;
#endif
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: inside finishZoomTo" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 2000)
;
}
#endif
// TODO: setUpdatesEnabled() should really return to old value
// - not neccessarily "true"
if (m_mainView)
{
m_mainView->setUpdatesEnabled (true);
m_mainView->update ();
}
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just updated mainView" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
if (m_scrollView)
{
if (m_scrollView->viewport ())
{
m_scrollView->viewport ()->setUpdatesEnabled (true);
m_scrollView->viewport ()->update ();
}
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just updated scrollView::viewport()" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
m_scrollView->setUpdatesEnabled (true);
m_scrollView->update ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: just updated scrollView" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
}
if (m_viewManager && m_viewManager->queueUpdates ()/*just in case*/)
m_viewManager->restoreQueueUpdates ();
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: restored vm queued updates" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
setStatusBarZoom (m_mainView ? m_mainView->zoomLevelX () : 0);
#if DEBUG_KP_MAIN_WINDOW && 1
kdDebug () << "\tkpMainWindow::finishZoomTo done" << endl;
#endif
#if DEBUG_ZOOM_FLICKER
{
kdDebug () << "FLICKER: finishZoomTo done" << endl;
TQTime timer; timer.start ();
while (timer.elapsed () < 1000)
;
}
#endif
}
// private slot
void kpMainWindow::slotActualSize ()
{
zoomTo (100);
}
// private slot
void kpMainWindow::slotFitToPage ()
{
if (!m_scrollView || !m_document)
return;
// doc_width * zoom / 100 <= view_width &&
// doc_height * zoom / 100 <= view_height &&
// 1 <= zoom <= 3200
zoomTo (TQMIN (3200, TQMAX (1, TQMIN (m_scrollView->visibleWidth () * 100 / m_document->width (),
m_scrollView->visibleHeight () * 100 / m_document->height ()))));
}
// private slot
void kpMainWindow::slotFitToWidth ()
{
if (!m_scrollView || !m_document)
return;
// doc_width * zoom / 100 <= view_width &&
// 1 <= zoom <= 3200
zoomTo (TQMIN (3200, TQMAX (1, m_scrollView->visibleWidth () * 100 / m_document->width ())));
}
// private slot
void kpMainWindow::slotFitToHeight ()
{
if (!m_scrollView || !m_document)
return;
// doc_height * zoom / 100 <= view_height &&
// 1 <= zoom <= 3200
zoomTo (TQMIN (3200, TQMAX (1, m_scrollView->visibleHeight () * 100 / m_document->height ())));
}
// public
void kpMainWindow::zoomIn (bool centerUnderCursor)
{
const int targetItem = m_actionZoom->currentItem () + 1;
if (targetItem >= (int) m_zoomList.count ())
return;
m_actionZoom->setCurrentItem (targetItem);
zoomAccordingToZoomAction (centerUnderCursor);
}
// public
void kpMainWindow::zoomOut (bool centerUnderCursor)
{
const int targetItem = m_actionZoom->currentItem () - 1;
if (targetItem < 0)
return;
m_actionZoom->setCurrentItem (targetItem);
zoomAccordingToZoomAction (centerUnderCursor);
}
// public slot
void kpMainWindow::slotZoomIn ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotZoomIn ()" << endl;
#endif
zoomIn (false/*don't center under cursor*/);
}
// public slot
void kpMainWindow::slotZoomOut ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotZoomOut ()" << endl;
#endif
zoomOut (false/*don't center under cursor*/);
}
// public
void kpMainWindow::zoomAccordingToZoomAction (bool centerUnderCursor)
{
zoomTo (zoomLevelFromString (m_actionZoom->currentText ()),
centerUnderCursor);
}
// private slot
void kpMainWindow::slotZoom ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotZoom () index=" << m_actionZoom->currentItem ()
<< " text='" << m_actionZoom->currentText () << "'" << endl;
#endif
zoomAccordingToZoomAction (false/*don't center under cursor*/);
}
// private slot
void kpMainWindow::slotShowGridToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotActionShowGridToggled()" << endl;
#endif
updateMainViewGrid ();
TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupGeneral);
TDEConfigBase *cfg = cfgGroupSaver.config ();
cfg->writeEntry (kpSettingShowGrid, m_configShowGrid = m_actionShowGrid->isChecked ());
cfg->sync ();
}
// private
void kpMainWindow::updateMainViewGrid ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::updateMainViewGrid ()" << endl;
#endif
if (m_mainView)
m_mainView->showGrid (m_actionShowGrid->isChecked ());
}
// private
TQRect kpMainWindow::mapToGlobal (const TQRect &rect) const
{
return kpWidgetMapper::toGlobal (this, rect);
}
// private
TQRect kpMainWindow::mapFromGlobal (const TQRect &rect) const
{
return kpWidgetMapper::fromGlobal (this, rect);
}
// public slot
void kpMainWindow::slotDestroyThumbnailIfNotVisible (bool tnIsVisible)
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotDestroyThumbnailIfNotVisible(isVisible="
<< tnIsVisible
<< ")"
<< endl;
#endif
if (!tnIsVisible)
{
slotDestroyThumbnailInitatedByUser ();
}
}
// private slot
void kpMainWindow::slotDestroyThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotDestroyThumbnail()" << endl;
#endif
m_actionShowThumbnail->setChecked (false);
enableThumbnailOptionActions (false);
updateThumbnail ();
}
// private slot
void kpMainWindow::slotDestroyThumbnailInitatedByUser ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotDestroyThumbnailInitiatedByUser()" << endl;
#endif
m_actionShowThumbnail->setChecked (false);
slotShowThumbnailToggled ();
}
// private slot
void kpMainWindow::slotCreateThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotCreateThumbnail()" << endl;
#endif
m_actionShowThumbnail->setChecked (true);
enableThumbnailOptionActions (true);
updateThumbnail ();
}
// public
void kpMainWindow::notifyThumbnailGeometryChanged ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::notifyThumbnailGeometryChanged()" << endl;
#endif
if (!m_thumbnailSaveConfigTimer)
{
m_thumbnailSaveConfigTimer = new TQTimer (this);
connect (m_thumbnailSaveConfigTimer, TQT_SIGNAL (timeout ()),
TQT_TQOBJECT(this), TQT_SLOT (slotSaveThumbnailGeometry ()));
}
m_thumbnailSaveConfigTimer->start (500/*msec*/, true/*single shot*/);
}
// private slot
void kpMainWindow::slotSaveThumbnailGeometry ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::saveThumbnailGeometry()" << endl;
#endif
if (!m_thumbnail)
return;
TQRect rect (m_thumbnail->x (), m_thumbnail->y (),
m_thumbnail->width (), m_thumbnail->height ());
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tthumbnail relative geometry=" << rect << endl;
#endif
m_configThumbnailGeometry = mapFromGlobal (rect);
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tCONFIG: saving thumbnail geometry "
<< m_configThumbnailGeometry
<< endl;
#endif
TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail);
TDEConfigBase *cfg = cfgGroupSaver.config ();
cfg->writeEntry (kpSettingThumbnailGeometry, m_configThumbnailGeometry);
cfg->sync ();
}
// private slot
void kpMainWindow::slotShowThumbnailToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotShowThumbnailToggled()" << endl;
#endif
m_configThumbnailShown = m_actionShowThumbnail->isChecked ();
TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail);
TDEConfigBase *cfg = cfgGroupSaver.config ();
cfg->writeEntry (kpSettingThumbnailShown, m_configThumbnailShown);
cfg->sync ();
enableThumbnailOptionActions (m_actionShowThumbnail->isChecked ());
updateThumbnail ();
}
// private slot
void kpMainWindow::updateThumbnailZoomed ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::updateThumbnailZoomed() zoomed="
<< m_actionZoomedThumbnail->isChecked () << endl;
#endif
if (!m_thumbnailView)
return;
destroyThumbnailView ();
createThumbnailView ();
}
// private slot
void kpMainWindow::slotZoomedThumbnailToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotZoomedThumbnailToggled()" << endl;
#endif
m_configZoomedThumbnail = m_actionZoomedThumbnail->isChecked ();
TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail);
TDEConfigBase *cfg = cfgGroupSaver.config ();
cfg->writeEntry (kpSettingThumbnailZoomed, m_configZoomedThumbnail);
cfg->sync ();
updateThumbnailZoomed ();
}
// private slot
void kpMainWindow::slotThumbnailShowRectangleToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::slotThumbnailShowRectangleToggled()" << endl;
#endif
d->m_configThumbnailShowRectangle = d->m_actionShowThumbnailRectangle->isChecked ();
TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail);
TDEConfigBase *cfg = cfgGroupSaver.config ();
cfg->writeEntry (kpSettingThumbnailShowRectangle, d->m_configThumbnailShowRectangle);
cfg->sync ();
if (m_thumbnailView)
{
m_thumbnailView->showBuddyViewScrollableContainerRectangle (
d->m_actionShowThumbnailRectangle->isChecked ());
}
}
// private
void kpMainWindow::enableViewZoomedThumbnail (bool enable)
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::enableSettingsViewZoomedThumbnail()" << endl;
#endif
m_actionZoomedThumbnail->setEnabled (enable &&
m_actionShowThumbnail->isChecked ());
// Note: Don't uncheck if disabled - being able to see the zoomed state
// before turning on the thumbnail can be useful.
m_actionZoomedThumbnail->setChecked (m_configZoomedThumbnail);
}
// private
void kpMainWindow::enableViewShowThumbnailRectangle (bool enable)
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::enableViewShowThumbnailRectangle()" << endl;
#endif
d->m_actionShowThumbnailRectangle->setEnabled (enable &&
m_actionShowThumbnail->isChecked ());
// Note: Don't uncheck if disabled for consistency with
// enableViewZoomedThumbnail()
d->m_actionShowThumbnailRectangle->setChecked (
d->m_configThumbnailShowRectangle);
}
// private
void kpMainWindow::enableThumbnailOptionActions (bool enable)
{
enableViewZoomedThumbnail (enable);
enableViewShowThumbnailRectangle (enable);
}
// private
void kpMainWindow::createThumbnailView ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tcreating new kpView:" << endl;
#endif
if (m_thumbnailView)
{
kdDebug () << "kpMainWindow::createThumbnailView() had to destroy view" << endl;
destroyThumbnailView ();
}
if (m_actionZoomedThumbnail->isChecked ())
{
m_thumbnailView = new kpZoomedThumbnailView (
m_document, m_toolToolBar, m_viewManager,
m_mainView,
0/*scrollableContainer*/,
m_thumbnail, "thumbnailView");
}
else
{
m_thumbnailView = new kpUnzoomedThumbnailView (
m_document, m_toolToolBar, m_viewManager,
m_mainView,
0/*scrollableContainer*/,
m_thumbnail, "thumbnailView");
}
m_thumbnailView->showBuddyViewScrollableContainerRectangle (
d->m_actionShowThumbnailRectangle->isChecked ());
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tgive kpThumbnail the kpView:" << endl;
#endif
if (m_thumbnail)
m_thumbnail->setView (m_thumbnailView);
else
kdError () << "kpMainWindow::createThumbnailView() no thumbnail" << endl;
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tregistering the kpView:" << endl;
#endif
if (m_viewManager)
m_viewManager->registerView (m_thumbnailView);
}
// private
void kpMainWindow::destroyThumbnailView ()
{
if (!m_thumbnailView)
return;
if (m_viewManager)
m_viewManager->unregisterView (m_thumbnailView);
if (m_thumbnail)
m_thumbnail->setView (0);
m_thumbnailView->deleteLater (); m_thumbnailView = 0;
}
// private
void kpMainWindow::updateThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "kpMainWindow::updateThumbnail()" << endl;
#endif
bool enable = m_actionShowThumbnail->isChecked ();
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tthumbnail="
<< bool (m_thumbnail)
<< " action_isChecked="
<< enable
<< endl;
#endif
if (bool (m_thumbnail) == enable)
return;
if (!m_thumbnail)
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tcreating thumbnail" << endl;
#endif
// Read last saved geometry before creating thumbnail & friends
// in case they call notifyThumbnailGeometryChanged()
TQRect thumbnailGeometry = m_configThumbnailGeometry;
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tlast used geometry=" << thumbnailGeometry << endl;
#endif
m_thumbnail = new kpThumbnail (this, "thumbnail");
createThumbnailView ();
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tmoving thumbnail to right place" << endl;
#endif
if (!thumbnailGeometry.isEmpty () &&
TQRect (0, 0, width (), height ()).intersects (thumbnailGeometry))
{
const TQRect geometry = mapToGlobal (thumbnailGeometry);
m_thumbnail->resize (geometry.size ());
m_thumbnail->move (geometry.topLeft ());
}
else
{
if (m_scrollView)
{
const int margin = 20;
const int initialWidth = 160, initialHeight = 120;
TQRect geometryRect (width () - initialWidth - margin * 2,
m_scrollView->y () + margin,
initialWidth,
initialHeight);
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tcreating geometry=" << geometryRect << endl;
#endif
geometryRect = mapToGlobal (geometryRect);
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tmap to global=" << geometryRect << endl;
#endif
m_thumbnail->resize (geometryRect.size ());
m_thumbnail->move (geometryRect.topLeft ());
}
}
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tshowing thumbnail" << endl;
#endif
m_thumbnail->show ();
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tconnecting thumbnail::visibilityChange to destroy slot" << endl;
#endif
connect (m_thumbnail, TQT_SIGNAL (visibilityChanged (bool)),
TQT_TQOBJECT(this), TQT_SLOT (slotDestroyThumbnailIfNotVisible (bool)));
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\t\tDONE" << endl;
#endif
}
else
{
#if DEBUG_KP_MAIN_WINDOW
kdDebug () << "\tdestroying thumbnail" << endl;
#endif
if (m_thumbnailSaveConfigTimer && m_thumbnailSaveConfigTimer->isActive ())
{
m_thumbnailSaveConfigTimer->stop ();
slotSaveThumbnailGeometry ();
}
destroyThumbnailView ();
disconnect (m_thumbnail, TQT_SIGNAL (visibilityChanged (bool)),
TQT_TQOBJECT(this), TQT_SLOT (slotDestroyThumbnailIfNotVisible (bool)));
m_thumbnail->deleteLater (); m_thumbnail = 0;
}
}