kolourpaint/mainWindow/kpMainWindow_View_Thumbnail...

480 lines
14 KiB
C++
Raw Permalink Normal View History

2022-11-21 12:38:32 +08:00
/*
Copyright (c) 2003-2007 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.
*/
#include "mainWindow/kpMainWindow.h"
#include "kpMainWindowPrivate.h"
#include "kpLogCategories.h"
#include <QTimer>
#include <KSharedConfig>
#include <KConfigGroup>
#include <KToggleAction>
#include <KActionCollection>
#include <KLocalizedString>
#include "kpDefs.h"
#include "document/kpDocument.h"
#include "kpThumbnail.h"
#include "tools/kpTool.h"
#include "widgets/toolbars/kpToolToolBar.h"
#include "views/kpUnzoomedThumbnailView.h"
#include "views/manager/kpViewManager.h"
#include "kpViewScrollableContainer.h"
#include "generic/kpWidgetMapper.h"
#include "views/kpZoomedView.h"
#include "views/kpZoomedThumbnailView.h"
// private
void kpMainWindow::setupViewMenuThumbnailActions ()
{
d->thumbnailSaveConfigTimer = nullptr;
KActionCollection *ac = actionCollection ();
d->actionShowThumbnail = ac->add <KToggleAction> (QStringLiteral("view_show_thumbnail"));
d->actionShowThumbnail->setText (i18n ("Show T&humbnail"));
// 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.
ac->setDefaultShortcut (d->actionShowThumbnail, Qt::CTRL | Qt::Key_H);
//d->actionShowThumbnail->setCheckedState (KGuiItem(i18n ("Hide T&humbnail")));
connect (d->actionShowThumbnail, &KToggleAction::triggered,
this, &kpMainWindow::slotShowThumbnailToggled);
// Please do not use setCheckedState() here - it wouldn't make sense
d->actionZoomedThumbnail = ac->add <KToggleAction> (QStringLiteral("view_zoomed_thumbnail"));
d->actionZoomedThumbnail->setText (i18n ("Zoo&med Thumbnail Mode"));
connect (d->actionZoomedThumbnail, &KToggleAction::triggered,
this, &kpMainWindow::slotZoomedThumbnailToggled);
// 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->actionShowThumbnailRectangle = ac->add <KToggleAction> (QStringLiteral("view_show_thumbnail_rectangle"));
d->actionShowThumbnailRectangle->setText (i18n ("Enable Thumbnail &Rectangle"));
connect (d->actionShowThumbnailRectangle, &KToggleAction::triggered,
this, &kpMainWindow::slotThumbnailShowRectangleToggled);
}
// private
void kpMainWindow::enableViewMenuThumbnailDocumentActions (bool enable)
{
d->actionShowThumbnail->setEnabled (enable);
enableThumbnailOptionActions (enable);
}
// private slot
void kpMainWindow::slotDestroyThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotDestroyThumbnail()";
#endif
d->actionShowThumbnail->setChecked (false);
enableThumbnailOptionActions (false);
updateThumbnail ();
}
// private slot
void kpMainWindow::slotDestroyThumbnailInitatedByUser ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotDestroyThumbnailInitiatedByUser()";
#endif
d->actionShowThumbnail->setChecked (false);
slotShowThumbnailToggled ();
}
// private slot
void kpMainWindow::slotCreateThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotCreateThumbnail()";
#endif
d->actionShowThumbnail->setChecked (true);
enableThumbnailOptionActions (true);
updateThumbnail ();
}
// public
void kpMainWindow::notifyThumbnailGeometryChanged ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::notifyThumbnailGeometryChanged()";
#endif
if (!d->thumbnailSaveConfigTimer)
{
d->thumbnailSaveConfigTimer = new QTimer (this);
d->thumbnailSaveConfigTimer->setSingleShot (true);
connect (d->thumbnailSaveConfigTimer, &QTimer::timeout,
this, &kpMainWindow::slotSaveThumbnailGeometry);
}
// (single shot)
d->thumbnailSaveConfigTimer->start (500/*msec*/);
}
// private slot
void kpMainWindow::slotSaveThumbnailGeometry ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::saveThumbnailGeometry()";
#endif
if (!d->thumbnail) {
return;
}
QRect rect (d->thumbnail->x (), d->thumbnail->y (),
d->thumbnail->width (), d->thumbnail->height ());
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\tthumbnail relative geometry=" << rect;
#endif
d->configThumbnailGeometry = mapFromGlobal (rect);
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\tCONFIG: saving thumbnail geometry "
<< d->configThumbnailGeometry;
#endif
KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupThumbnail);
cfg.writeEntry (kpSettingThumbnailGeometry, d->configThumbnailGeometry);
cfg.sync ();
}
// private slot
void kpMainWindow::slotShowThumbnailToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotShowThumbnailToggled()";
#endif
d->configThumbnailShown = d->actionShowThumbnail->isChecked ();
KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupThumbnail);
cfg.writeEntry (kpSettingThumbnailShown, d->configThumbnailShown);
cfg.sync ();
enableThumbnailOptionActions (d->actionShowThumbnail->isChecked ());
updateThumbnail ();
}
// private slot
void kpMainWindow::updateThumbnailZoomed ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::updateThumbnailZoomed() zoomed="
<< d->actionZoomedThumbnail->isChecked ();
#endif
if (!d->thumbnailView) {
return;
}
destroyThumbnailView ();
createThumbnailView ();
}
// private slot
void kpMainWindow::slotZoomedThumbnailToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotZoomedThumbnailToggled()";
#endif
d->configZoomedThumbnail = d->actionZoomedThumbnail->isChecked ();
KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupThumbnail);
cfg.writeEntry (kpSettingThumbnailZoomed, d->configZoomedThumbnail);
cfg.sync ();
updateThumbnailZoomed ();
}
// private slot
void kpMainWindow::slotThumbnailShowRectangleToggled ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::slotThumbnailShowRectangleToggled()";
#endif
d->configThumbnailShowRectangle = d->actionShowThumbnailRectangle->isChecked ();
KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupThumbnail);
cfg.writeEntry (kpSettingThumbnailShowRectangle, d->configThumbnailShowRectangle);
cfg.sync ();
if (d->thumbnailView)
{
d->thumbnailView->showBuddyViewScrollableContainerRectangle (
d->actionShowThumbnailRectangle->isChecked ());
}
}
// private
void kpMainWindow::enableViewZoomedThumbnail (bool enable)
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::enableSettingsViewZoomedThumbnail()";
#endif
d->actionZoomedThumbnail->setEnabled (enable &&
d->actionShowThumbnail->isChecked ());
// Note: Don't uncheck if disabled - being able to see the zoomed state
// before turning on the thumbnail can be useful.
d->actionZoomedThumbnail->setChecked (d->configZoomedThumbnail);
}
// private
void kpMainWindow::enableViewShowThumbnailRectangle (bool enable)
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::enableViewShowThumbnailRectangle()";
#endif
d->actionShowThumbnailRectangle->setEnabled (enable &&
d->actionShowThumbnail->isChecked ());
// Note: Don't uncheck if disabled for consistency with
// enableViewZoomedThumbnail()
d->actionShowThumbnailRectangle->setChecked (
d->configThumbnailShowRectangle);
}
// private
void kpMainWindow::enableThumbnailOptionActions (bool enable)
{
enableViewZoomedThumbnail (enable);
enableViewShowThumbnailRectangle (enable);
}
// private
void kpMainWindow::createThumbnailView ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tcreating new kpView:";
#endif
if (d->thumbnailView)
{
qCDebug(kpLogMainWindow) << "kpMainWindow::createThumbnailView() had to destroy view";
destroyThumbnailView ();
}
if (d->actionZoomedThumbnail->isChecked ())
{
d->thumbnailView = new kpZoomedThumbnailView (
d->document, d->toolToolBar, d->viewManager,
d->mainView,
nullptr/*scrollableContainer*/,
d->thumbnail);
d->thumbnailView->setObjectName ( QStringLiteral("thumbnailView" ));
}
else
{
d->thumbnailView = new kpUnzoomedThumbnailView (
d->document, d->toolToolBar, d->viewManager,
d->mainView,
nullptr/*scrollableContainer*/,
d->thumbnail);
d->thumbnailView->setObjectName ( QStringLiteral("thumbnailView" ));
}
d->thumbnailView->showBuddyViewScrollableContainerRectangle (
d->actionShowThumbnailRectangle->isChecked ());
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tgive kpThumbnail the kpView:";
#endif
if (d->thumbnail) {
d->thumbnail->setView (d->thumbnailView);
}
else {
qCCritical(kpLogMainWindow) << "kpMainWindow::createThumbnailView() no thumbnail";
}
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tregistering the kpView:";
#endif
if (d->viewManager) {
d->viewManager->registerView (d->thumbnailView);
}
}
// private
void kpMainWindow::destroyThumbnailView ()
{
if (!d->thumbnailView) {
return;
}
if (d->viewManager) {
d->viewManager->unregisterView (d->thumbnailView);
}
if (d->thumbnail) {
d->thumbnail->setView (nullptr);
}
d->thumbnailView->deleteLater (); d->thumbnailView = nullptr;
}
// private
void kpMainWindow::updateThumbnail ()
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "kpMainWindow::updateThumbnail()";
#endif
bool enable = d->actionShowThumbnail->isChecked ();
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\tthumbnail="
<< bool (d->thumbnail)
<< " action_isChecked="
<< enable;
#endif
if (bool (d->thumbnail) == enable) {
return;
}
if (!d->thumbnail)
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\tcreating thumbnail";
#endif
// Read last saved geometry before creating thumbnail & friends
// in case they call notifyThumbnailGeometryChanged()
QRect thumbnailGeometry = d->configThumbnailGeometry;
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tlast used geometry=" << thumbnailGeometry;
#endif
d->thumbnail = new kpThumbnail (this);
createThumbnailView ();
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tmoving thumbnail to right place";
#endif
if (!thumbnailGeometry.isEmpty () &&
QRect (0, 0, width (), height ()).intersects (thumbnailGeometry))
{
const QRect geometry = mapToGlobal (thumbnailGeometry);
d->thumbnail->resize (geometry.size ());
d->thumbnail->move (geometry.topLeft ());
}
else
{
if (d->scrollView)
{
const int margin = 20;
const int initialWidth = 160, initialHeight = 120;
QRect geometryRect (width () - initialWidth - margin * 2,
d->scrollView->y () + margin,
initialWidth,
initialHeight);
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tcreating geometry=" << geometryRect;
#endif
geometryRect = mapToGlobal (geometryRect);
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tmap to global=" << geometryRect;
#endif
d->thumbnail->resize (geometryRect.size ());
d->thumbnail->move (geometryRect.topLeft ());
}
}
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tshowing thumbnail";
#endif
d->thumbnail->show ();
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tconnecting signal thumbnail::windowClosed to destroy slot";
#endif
connect (d->thumbnail, &kpThumbnail::windowClosed,
this, &kpMainWindow::slotDestroyThumbnailInitatedByUser);
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\t\tDONE";
#endif
}
else
{
#if DEBUG_KP_MAIN_WINDOW
qCDebug(kpLogMainWindow) << "\tdestroying thumbnail d->thumbnail="
<< d->thumbnail;
#endif
if (d->thumbnailSaveConfigTimer && d->thumbnailSaveConfigTimer->isActive ())
{
d->thumbnailSaveConfigTimer->stop ();
slotSaveThumbnailGeometry ();
}
// Must be done before hiding the thumbnail to avoid triggering
// this signal - re-entering this code.
disconnect (d->thumbnail, &kpThumbnail::windowClosed,
this, &kpMainWindow::slotDestroyThumbnailInitatedByUser);
// Avoid change/flicker of caption due to view delete
// (destroyThumbnailView())
d->thumbnail->hide ();
destroyThumbnailView ();
d->thumbnail->deleteLater (); d->thumbnail = nullptr;
}
}