/* Copyright (c) 2003,2004,2005 Clarence Dang 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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 ::ConstIterator zoomListEnd (m_zoomList.end ()); for (TQValueVector ::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 ::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 ()->tqcolorGroup ().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 ().tqcontains (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 (); KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupGeneral); KConfigBase *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 tqgeometry=" << rect << endl; #endif m_configThumbnailGeometry = mapFromGlobal (rect); #if DEBUG_KP_MAIN_WINDOW kdDebug () << "\tCONFIG: saving thumbnail tqgeometry " << m_configThumbnailGeometry << endl; #endif KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail); KConfigBase *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 (); KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail); KConfigBase *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 (); KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail); KConfigBase *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 (); KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupThumbnail); KConfigBase *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 tqgeometry before creating thumbnail & friends // in case they call notifyThumbnailGeometryChanged() TQRect thumbnailGeometry = m_configThumbnailGeometry; #if DEBUG_KP_MAIN_WINDOW kdDebug () << "\t\tlast used tqgeometry=" << 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 tqgeometry = mapToGlobal (thumbnailGeometry); m_thumbnail->resize (tqgeometry.size ()); m_thumbnail->move (tqgeometry.topLeft ()); } else { if (m_scrollView) { const int margin = 20; const int initialWidth = 160, initialHeight = 120; TQRect tqgeometryRect (width () - initialWidth - margin * 2, m_scrollView->y () + margin, initialWidth, initialHeight); #if DEBUG_KP_MAIN_WINDOW kdDebug () << "\t\tcreating tqgeometry=" << tqgeometryRect << endl; #endif tqgeometryRect = mapToGlobal (tqgeometryRect); #if DEBUG_KP_MAIN_WINDOW kdDebug () << "\t\tmap to global=" << tqgeometryRect << endl; #endif m_thumbnail->resize (tqgeometryRect.size ()); m_thumbnail->move (tqgeometryRect.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; } }