File indexing completed on 2024-04-28 04:20:22
0001 0002 /* 0003 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0004 All rights reserved. 0005 0006 Redistribution and use in source and binary forms, with or without 0007 modification, are permitted provided that the following conditions 0008 are met: 0009 0010 1. Redistributions of source code must retain the above copyright 0011 notice, this list of conditions and the following disclaimer. 0012 2. Redistributions in binary form must reproduce the above copyright 0013 notice, this list of conditions and the following disclaimer in the 0014 documentation and/or other materials provided with the distribution. 0015 0016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0026 */ 0027 0028 0029 #include "mainWindow/kpMainWindow.h" 0030 #include "kpMainWindowPrivate.h" 0031 #include "kpLogCategories.h" 0032 0033 #include <QTimer> 0034 0035 #include <KSharedConfig> 0036 #include <KConfigGroup> 0037 #include <KToggleAction> 0038 #include <KActionCollection> 0039 #include <KLocalizedString> 0040 0041 #include "kpDefs.h" 0042 #include "document/kpDocument.h" 0043 #include "kpThumbnail.h" 0044 #include "tools/kpTool.h" 0045 #include "widgets/toolbars/kpToolToolBar.h" 0046 #include "views/kpUnzoomedThumbnailView.h" 0047 #include "views/manager/kpViewManager.h" 0048 #include "kpViewScrollableContainer.h" 0049 #include "generic/kpWidgetMapper.h" 0050 #include "views/kpZoomedView.h" 0051 #include "views/kpZoomedThumbnailView.h" 0052 0053 0054 // private 0055 void kpMainWindow::setupViewMenuThumbnailActions () 0056 { 0057 d->thumbnailSaveConfigTimer = nullptr; 0058 0059 KActionCollection *ac = actionCollection (); 0060 0061 0062 d->actionShowThumbnail = ac->add <KToggleAction> (QStringLiteral("view_show_thumbnail")); 0063 d->actionShowThumbnail->setText (i18n ("Show T&humbnail")); 0064 // TODO: This doesn't work when the thumbnail has focus. 0065 // Testcase: Press CTRL+H twice on a fresh KolourPaint. 0066 // The second CTRL+H doesn't close the thumbnail. 0067 ac->setDefaultShortcut (d->actionShowThumbnail, Qt::CTRL | Qt::Key_H); 0068 //d->actionShowThumbnail->setCheckedState (KGuiItem(i18n ("Hide T&humbnail"))); 0069 connect (d->actionShowThumbnail, &KToggleAction::triggered, 0070 this, &kpMainWindow::slotShowThumbnailToggled); 0071 0072 // Please do not use setCheckedState() here - it wouldn't make sense 0073 d->actionZoomedThumbnail = ac->add <KToggleAction> (QStringLiteral("view_zoomed_thumbnail")); 0074 d->actionZoomedThumbnail->setText (i18n ("Zoo&med Thumbnail Mode")); 0075 connect (d->actionZoomedThumbnail, &KToggleAction::triggered, 0076 this, &kpMainWindow::slotZoomedThumbnailToggled); 0077 0078 // For consistency with the above action, don't use setCheckedState() 0079 // 0080 // Also, don't use "Show Thumbnail Rectangle" because if entire doc 0081 // can be seen in scrollView, checking option won't "Show" anything 0082 // since rect _surrounds_ entire doc (hence, won't be rendered). 0083 d->actionShowThumbnailRectangle = ac->add <KToggleAction> (QStringLiteral("view_show_thumbnail_rectangle")); 0084 d->actionShowThumbnailRectangle->setText (i18n ("Enable Thumbnail &Rectangle")); 0085 connect (d->actionShowThumbnailRectangle, &KToggleAction::triggered, 0086 this, &kpMainWindow::slotThumbnailShowRectangleToggled); 0087 } 0088 0089 // private 0090 void kpMainWindow::enableViewMenuThumbnailDocumentActions (bool enable) 0091 { 0092 d->actionShowThumbnail->setEnabled (enable); 0093 enableThumbnailOptionActions (enable); 0094 } 0095 0096 // private slot 0097 void kpMainWindow::slotDestroyThumbnail () 0098 { 0099 #if DEBUG_KP_MAIN_WINDOW 0100 qCDebug(kpLogMainWindow) << "kpMainWindow::slotDestroyThumbnail()"; 0101 #endif 0102 0103 d->actionShowThumbnail->setChecked (false); 0104 enableThumbnailOptionActions (false); 0105 updateThumbnail (); 0106 } 0107 0108 // private slot 0109 void kpMainWindow::slotDestroyThumbnailInitatedByUser () 0110 { 0111 #if DEBUG_KP_MAIN_WINDOW 0112 qCDebug(kpLogMainWindow) << "kpMainWindow::slotDestroyThumbnailInitiatedByUser()"; 0113 #endif 0114 0115 d->actionShowThumbnail->setChecked (false); 0116 slotShowThumbnailToggled (); 0117 } 0118 0119 // private slot 0120 void kpMainWindow::slotCreateThumbnail () 0121 { 0122 #if DEBUG_KP_MAIN_WINDOW 0123 qCDebug(kpLogMainWindow) << "kpMainWindow::slotCreateThumbnail()"; 0124 #endif 0125 0126 d->actionShowThumbnail->setChecked (true); 0127 enableThumbnailOptionActions (true); 0128 updateThumbnail (); 0129 } 0130 0131 // public 0132 void kpMainWindow::notifyThumbnailGeometryChanged () 0133 { 0134 #if DEBUG_KP_MAIN_WINDOW 0135 qCDebug(kpLogMainWindow) << "kpMainWindow::notifyThumbnailGeometryChanged()"; 0136 #endif 0137 0138 if (!d->thumbnailSaveConfigTimer) 0139 { 0140 d->thumbnailSaveConfigTimer = new QTimer (this); 0141 d->thumbnailSaveConfigTimer->setSingleShot (true); 0142 connect (d->thumbnailSaveConfigTimer, &QTimer::timeout, 0143 this, &kpMainWindow::slotSaveThumbnailGeometry); 0144 } 0145 0146 // (single shot) 0147 d->thumbnailSaveConfigTimer->start (500/*msec*/); 0148 } 0149 0150 // private slot 0151 void kpMainWindow::slotSaveThumbnailGeometry () 0152 { 0153 #if DEBUG_KP_MAIN_WINDOW 0154 qCDebug(kpLogMainWindow) << "kpMainWindow::saveThumbnailGeometry()"; 0155 #endif 0156 0157 if (!d->thumbnail) { 0158 return; 0159 } 0160 0161 QRect rect (d->thumbnail->x (), d->thumbnail->y (), 0162 d->thumbnail->width (), d->thumbnail->height ()); 0163 #if DEBUG_KP_MAIN_WINDOW 0164 qCDebug(kpLogMainWindow) << "\tthumbnail relative geometry=" << rect; 0165 #endif 0166 0167 d->configThumbnailGeometry = mapFromGlobal (rect); 0168 0169 #if DEBUG_KP_MAIN_WINDOW 0170 qCDebug(kpLogMainWindow) << "\tCONFIG: saving thumbnail geometry " 0171 << d->configThumbnailGeometry; 0172 #endif 0173 0174 KConfigGroup cfg (KSharedConfig::openConfig (), QStringLiteral(kpSettingsGroupThumbnail)); 0175 0176 cfg.writeEntry (kpSettingThumbnailGeometry, d->configThumbnailGeometry); 0177 cfg.sync (); 0178 } 0179 0180 // private slot 0181 void kpMainWindow::slotShowThumbnailToggled () 0182 { 0183 #if DEBUG_KP_MAIN_WINDOW 0184 qCDebug(kpLogMainWindow) << "kpMainWindow::slotShowThumbnailToggled()"; 0185 #endif 0186 0187 d->configThumbnailShown = d->actionShowThumbnail->isChecked (); 0188 0189 KConfigGroup cfg (KSharedConfig::openConfig (), QStringLiteral(kpSettingsGroupThumbnail)); 0190 0191 cfg.writeEntry (kpSettingThumbnailShown, d->configThumbnailShown); 0192 cfg.sync (); 0193 0194 0195 enableThumbnailOptionActions (d->actionShowThumbnail->isChecked ()); 0196 updateThumbnail (); 0197 } 0198 0199 // private slot 0200 void kpMainWindow::updateThumbnailZoomed () 0201 { 0202 #if DEBUG_KP_MAIN_WINDOW 0203 qCDebug(kpLogMainWindow) << "kpMainWindow::updateThumbnailZoomed() zoomed=" 0204 << d->actionZoomedThumbnail->isChecked (); 0205 #endif 0206 0207 if (!d->thumbnailView) { 0208 return; 0209 } 0210 0211 destroyThumbnailView (); 0212 createThumbnailView (); 0213 } 0214 0215 // private slot 0216 void kpMainWindow::slotZoomedThumbnailToggled () 0217 { 0218 #if DEBUG_KP_MAIN_WINDOW 0219 qCDebug(kpLogMainWindow) << "kpMainWindow::slotZoomedThumbnailToggled()"; 0220 #endif 0221 0222 d->configZoomedThumbnail = d->actionZoomedThumbnail->isChecked (); 0223 0224 KConfigGroup cfg (KSharedConfig::openConfig (), QStringLiteral(kpSettingsGroupThumbnail)); 0225 0226 cfg.writeEntry (kpSettingThumbnailZoomed, d->configZoomedThumbnail); 0227 cfg.sync (); 0228 0229 0230 updateThumbnailZoomed (); 0231 } 0232 0233 // private slot 0234 void kpMainWindow::slotThumbnailShowRectangleToggled () 0235 { 0236 #if DEBUG_KP_MAIN_WINDOW 0237 qCDebug(kpLogMainWindow) << "kpMainWindow::slotThumbnailShowRectangleToggled()"; 0238 #endif 0239 0240 d->configThumbnailShowRectangle = d->actionShowThumbnailRectangle->isChecked (); 0241 0242 KConfigGroup cfg (KSharedConfig::openConfig (), QStringLiteral(kpSettingsGroupThumbnail)); 0243 0244 cfg.writeEntry (kpSettingThumbnailShowRectangle, d->configThumbnailShowRectangle); 0245 cfg.sync (); 0246 0247 0248 if (d->thumbnailView) 0249 { 0250 d->thumbnailView->showBuddyViewScrollableContainerRectangle ( 0251 d->actionShowThumbnailRectangle->isChecked ()); 0252 } 0253 } 0254 0255 // private 0256 void kpMainWindow::enableViewZoomedThumbnail (bool enable) 0257 { 0258 #if DEBUG_KP_MAIN_WINDOW 0259 qCDebug(kpLogMainWindow) << "kpMainWindow::enableSettingsViewZoomedThumbnail()"; 0260 #endif 0261 0262 d->actionZoomedThumbnail->setEnabled (enable && 0263 d->actionShowThumbnail->isChecked ()); 0264 0265 // Note: Don't uncheck if disabled - being able to see the zoomed state 0266 // before turning on the thumbnail can be useful. 0267 d->actionZoomedThumbnail->setChecked (d->configZoomedThumbnail); 0268 } 0269 0270 // private 0271 void kpMainWindow::enableViewShowThumbnailRectangle (bool enable) 0272 { 0273 #if DEBUG_KP_MAIN_WINDOW 0274 qCDebug(kpLogMainWindow) << "kpMainWindow::enableViewShowThumbnailRectangle()"; 0275 #endif 0276 0277 d->actionShowThumbnailRectangle->setEnabled (enable && 0278 d->actionShowThumbnail->isChecked ()); 0279 0280 // Note: Don't uncheck if disabled for consistency with 0281 // enableViewZoomedThumbnail() 0282 d->actionShowThumbnailRectangle->setChecked ( 0283 d->configThumbnailShowRectangle); 0284 } 0285 0286 // private 0287 void kpMainWindow::enableThumbnailOptionActions (bool enable) 0288 { 0289 enableViewZoomedThumbnail (enable); 0290 enableViewShowThumbnailRectangle (enable); 0291 } 0292 0293 0294 // private 0295 void kpMainWindow::createThumbnailView () 0296 { 0297 #if DEBUG_KP_MAIN_WINDOW 0298 qCDebug(kpLogMainWindow) << "\t\tcreating new kpView:"; 0299 #endif 0300 0301 if (d->thumbnailView) 0302 { 0303 qCDebug(kpLogMainWindow) << "kpMainWindow::createThumbnailView() had to destroy view"; 0304 destroyThumbnailView (); 0305 } 0306 0307 if (d->actionZoomedThumbnail->isChecked ()) 0308 { 0309 d->thumbnailView = new kpZoomedThumbnailView ( 0310 d->document, d->toolToolBar, d->viewManager, 0311 d->mainView, 0312 nullptr/*scrollableContainer*/, 0313 d->thumbnail); 0314 d->thumbnailView->setObjectName ( QStringLiteral("thumbnailView" )); 0315 } 0316 else 0317 { 0318 d->thumbnailView = new kpUnzoomedThumbnailView ( 0319 d->document, d->toolToolBar, d->viewManager, 0320 d->mainView, 0321 nullptr/*scrollableContainer*/, 0322 d->thumbnail); 0323 d->thumbnailView->setObjectName ( QStringLiteral("thumbnailView" )); 0324 } 0325 0326 d->thumbnailView->showBuddyViewScrollableContainerRectangle ( 0327 d->actionShowThumbnailRectangle->isChecked ()); 0328 0329 0330 #if DEBUG_KP_MAIN_WINDOW 0331 qCDebug(kpLogMainWindow) << "\t\tgive kpThumbnail the kpView:"; 0332 #endif 0333 0334 if (d->thumbnail) { 0335 d->thumbnail->setView (d->thumbnailView); 0336 } 0337 else { 0338 qCCritical(kpLogMainWindow) << "kpMainWindow::createThumbnailView() no thumbnail"; 0339 } 0340 0341 #if DEBUG_KP_MAIN_WINDOW 0342 qCDebug(kpLogMainWindow) << "\t\tregistering the kpView:"; 0343 #endif 0344 if (d->viewManager) { 0345 d->viewManager->registerView (d->thumbnailView); 0346 } 0347 } 0348 0349 // private 0350 void kpMainWindow::destroyThumbnailView () 0351 { 0352 if (!d->thumbnailView) { 0353 return; 0354 } 0355 0356 if (d->viewManager) { 0357 d->viewManager->unregisterView (d->thumbnailView); 0358 } 0359 0360 if (d->thumbnail) { 0361 d->thumbnail->setView (nullptr); 0362 } 0363 0364 d->thumbnailView->deleteLater (); d->thumbnailView = nullptr; 0365 } 0366 0367 0368 // private 0369 void kpMainWindow::updateThumbnail () 0370 { 0371 #if DEBUG_KP_MAIN_WINDOW 0372 qCDebug(kpLogMainWindow) << "kpMainWindow::updateThumbnail()"; 0373 #endif 0374 bool enable = d->actionShowThumbnail->isChecked (); 0375 0376 #if DEBUG_KP_MAIN_WINDOW 0377 qCDebug(kpLogMainWindow) << "\tthumbnail=" 0378 << bool (d->thumbnail) 0379 << " action_isChecked=" 0380 << enable; 0381 #endif 0382 0383 if (bool (d->thumbnail) == enable) { 0384 return; 0385 } 0386 0387 if (!d->thumbnail) 0388 { 0389 #if DEBUG_KP_MAIN_WINDOW 0390 qCDebug(kpLogMainWindow) << "\tcreating thumbnail"; 0391 #endif 0392 0393 // Read last saved geometry before creating thumbnail & friends 0394 // in case they call notifyThumbnailGeometryChanged() 0395 QRect thumbnailGeometry = d->configThumbnailGeometry; 0396 #if DEBUG_KP_MAIN_WINDOW 0397 qCDebug(kpLogMainWindow) << "\t\tlast used geometry=" << thumbnailGeometry; 0398 #endif 0399 0400 d->thumbnail = new kpThumbnail (this); 0401 0402 createThumbnailView (); 0403 0404 #if DEBUG_KP_MAIN_WINDOW 0405 qCDebug(kpLogMainWindow) << "\t\tmoving thumbnail to right place"; 0406 #endif 0407 if (!thumbnailGeometry.isEmpty () && 0408 QRect (0, 0, width (), height ()).intersects (thumbnailGeometry)) 0409 { 0410 const QRect geometry = mapToGlobal (thumbnailGeometry); 0411 d->thumbnail->resize (geometry.size ()); 0412 d->thumbnail->move (geometry.topLeft ()); 0413 } 0414 else 0415 { 0416 if (d->scrollView) 0417 { 0418 const int margin = 20; 0419 const int initialWidth = 160, initialHeight = 120; 0420 0421 QRect geometryRect (width () - initialWidth - margin * 2, 0422 d->scrollView->y () + margin, 0423 initialWidth, 0424 initialHeight); 0425 0426 #if DEBUG_KP_MAIN_WINDOW 0427 qCDebug(kpLogMainWindow) << "\t\tcreating geometry=" << geometryRect; 0428 #endif 0429 0430 geometryRect = mapToGlobal (geometryRect); 0431 #if DEBUG_KP_MAIN_WINDOW 0432 qCDebug(kpLogMainWindow) << "\t\tmap to global=" << geometryRect; 0433 #endif 0434 d->thumbnail->resize (geometryRect.size ()); 0435 d->thumbnail->move (geometryRect.topLeft ()); 0436 } 0437 } 0438 0439 #if DEBUG_KP_MAIN_WINDOW 0440 qCDebug(kpLogMainWindow) << "\t\tshowing thumbnail"; 0441 #endif 0442 d->thumbnail->show (); 0443 0444 #if DEBUG_KP_MAIN_WINDOW 0445 qCDebug(kpLogMainWindow) << "\t\tconnecting signal thumbnail::windowClosed to destroy slot"; 0446 #endif 0447 connect (d->thumbnail, &kpThumbnail::windowClosed, 0448 this, &kpMainWindow::slotDestroyThumbnailInitatedByUser); 0449 #if DEBUG_KP_MAIN_WINDOW 0450 qCDebug(kpLogMainWindow) << "\t\tDONE"; 0451 #endif 0452 } 0453 else 0454 { 0455 #if DEBUG_KP_MAIN_WINDOW 0456 qCDebug(kpLogMainWindow) << "\tdestroying thumbnail d->thumbnail=" 0457 << d->thumbnail; 0458 #endif 0459 0460 if (d->thumbnailSaveConfigTimer && d->thumbnailSaveConfigTimer->isActive ()) 0461 { 0462 d->thumbnailSaveConfigTimer->stop (); 0463 slotSaveThumbnailGeometry (); 0464 } 0465 0466 // Must be done before hiding the thumbnail to avoid triggering 0467 // this signal - re-entering this code. 0468 disconnect (d->thumbnail, &kpThumbnail::windowClosed, 0469 this, &kpMainWindow::slotDestroyThumbnailInitatedByUser); 0470 0471 // Avoid change/flicker of caption due to view delete 0472 // (destroyThumbnailView()) 0473 d->thumbnail->hide (); 0474 0475 destroyThumbnailView (); 0476 0477 d->thumbnail->deleteLater (); d->thumbnail = nullptr; 0478 } 0479 }