File indexing completed on 2024-05-12 04:21:29

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 #define DEBUG_KP_VIEW_MANAGER 0
0030 
0031 
0032 #include "views/manager/kpViewManager.h"
0033 #include "kpViewManagerPrivate.h"
0034 
0035 
0036 #include "kpLogCategories.h"
0037 
0038 #include "kpDefs.h"
0039 #include "document/kpDocument.h"
0040 #include "mainWindow/kpMainWindow.h"
0041 #include "layers/tempImage/kpTempImage.h"
0042 #include "layers/selections/text/kpTextSelection.h"
0043 #include "tools/kpTool.h"
0044 #include "views/kpView.h"
0045 
0046 //---------------------------------------------------------------------
0047 
0048 kpViewManager::kpViewManager (kpMainWindow *mainWindow)
0049     : d (new kpViewManagerPrivate ())
0050 {
0051     Q_ASSERT (mainWindow);
0052 
0053     d->mainWindow = mainWindow;
0054 
0055     // d->views
0056     d->viewUnderCursor = nullptr;
0057 
0058     // d->cursor
0059 
0060     d->tempImage = nullptr;
0061 
0062     d->selectionBorderVisible = false;
0063     d->selectionBorderFinished = false;
0064 
0065 
0066     d->textCursorBlinkTimer = nullptr;
0067 
0068     d->textCursorRow = -1;
0069     d->textCursorCol = -1;
0070 
0071     d->textCursorBlinkState = true;
0072 
0073 
0074     d->queueUpdatesCounter = d->fastUpdatesCounter = 0;
0075 
0076     d->inputMethodEnabled = false;
0077 }
0078 
0079 //---------------------------------------------------------------------
0080 
0081 kpViewManager::~kpViewManager ()
0082 {
0083     unregisterAllViews ();
0084 
0085     delete d->tempImage;
0086     delete d;
0087 }
0088 
0089 //---------------------------------------------------------------------
0090 
0091 // private
0092 kpDocument *kpViewManager::document () const
0093 {
0094     return d->mainWindow->document ();
0095 }
0096 
0097 //---------------------------------------------------------------------
0098 
0099 // public
0100 void kpViewManager::registerView (kpView *view)
0101 {
0102 #if DEBUG_KP_VIEW_MANAGER && 1
0103     qCDebug(kpLogViews) << "kpViewManager::registerView (" << view << ")";
0104 #endif
0105     Q_ASSERT (view);
0106     Q_ASSERT (!d->views.contains (view));
0107 
0108 #if DEBUG_KP_VIEW_MANAGER && 1
0109     qCDebug(kpLogViews) << "\tadded view";
0110 #endif
0111     view->setCursor (d->cursor);
0112     d->views.append (view);
0113 }
0114 
0115 //---------------------------------------------------------------------
0116 
0117 // public
0118 void kpViewManager::unregisterView (kpView *view)
0119 {
0120     Q_ASSERT (view);
0121     Q_ASSERT (d->views.contains (view));
0122 
0123     if (view == d->viewUnderCursor) {
0124         d->viewUnderCursor = nullptr;
0125     }
0126 
0127     view->unsetCursor ();
0128     d->views.removeAll (view);
0129 }
0130 
0131 //---------------------------------------------------------------------
0132 
0133 // public
0134 void kpViewManager::unregisterAllViews ()
0135 {
0136     d->views.clear ();
0137 }
0138 
0139 //---------------------------------------------------------------------
0140 
0141 // public
0142 kpView *kpViewManager::viewUnderCursor (bool usingQt) const
0143 {
0144     if (!usingQt)
0145     {
0146         Q_ASSERT (!d->viewUnderCursor || d->views.contains (d->viewUnderCursor));
0147         return d->viewUnderCursor;
0148     }
0149 
0150 
0151     for (kpView *view : std::as_const(d->views))
0152       if ( view->underMouse() )
0153         return view;
0154 
0155     return nullptr;
0156 }
0157 
0158 //---------------------------------------------------------------------
0159 
0160 // public
0161 void kpViewManager::setViewUnderCursor (kpView *view)
0162 {
0163 #if DEBUG_KP_VIEW_MANAGER && 1
0164     qCDebug(kpLogViews) << "kpViewManager::setViewUnderCursor ("
0165                << (view ? view->objectName () : "(none)") << ")"
0166                << "  old=" << (d->viewUnderCursor ? d->viewUnderCursor->objectName () : "(none)");
0167 #endif
0168     if (view == d->viewUnderCursor) {
0169         return;
0170     }
0171 
0172     d->viewUnderCursor = view;
0173 
0174     if (d->viewUnderCursor) {
0175         d->viewUnderCursor->setAttribute (Qt::WA_InputMethodEnabled, d->inputMethodEnabled);
0176     }
0177 
0178     if (!d->viewUnderCursor)
0179     {
0180         // Hide the brush if the mouse cursor just left the view.
0181         if (d->tempImage && d->tempImage->isBrush ())
0182         {
0183         #if DEBUG_KP_VIEW_MANAGER && 1
0184             qCDebug(kpLogViews) << "\thiding brush pixmap since cursor left view";
0185         #endif
0186             updateViews (d->tempImage->rect ());
0187         }
0188     }
0189     else
0190     {
0191         if (d->mainWindow->tool ())
0192         {
0193         #if DEBUG_KP_VIEW_MANAGER && 1
0194             qCDebug(kpLogViews) << "\tnotify tool that something changed below cursor";
0195         #endif
0196             d->mainWindow->tool ()->somethingBelowTheCursorChanged ();
0197         }
0198     }
0199 }
0200 
0201 //---------------------------------------------------------------------
0202 
0203 // public
0204 bool kpViewManager::hasAViewWithFocus () const
0205 {
0206     for (kpView *view : std::as_const(d->views))
0207       if ( view->isActiveWindow() )
0208         return true;
0209 
0210     return false;
0211 }
0212 
0213 //---------------------------------------------------------------------
0214 
0215 // public
0216 void kpViewManager::setCursor(const QCursor &cursor)
0217 {
0218     for (kpView *view : std::as_const(d->views))
0219       view->setCursor(cursor);
0220 
0221     d->cursor = cursor;
0222 }
0223 
0224 //---------------------------------------------------------------------
0225 
0226 // public
0227 void kpViewManager::unsetCursor()
0228 {
0229     for (kpView *view : std::as_const(d->views))
0230       view->unsetCursor();
0231 
0232     d->cursor = QCursor();
0233 }
0234 
0235 //---------------------------------------------------------------------
0236 
0237 // public
0238 const kpTempImage *kpViewManager::tempImage () const
0239 {
0240     return d->tempImage;
0241 }
0242 
0243 //---------------------------------------------------------------------
0244 
0245 // public
0246 void kpViewManager::setTempImage (const kpTempImage &tempImage)
0247 {
0248 #if DEBUG_KP_VIEW_MANAGER
0249     qCDebug(kpLogViews) << "kpViewManager::setTempImage(isBrush="
0250                << tempImage.isBrush ()
0251                << ",topLeft=" << tempImage.topLeft ()
0252                << ",image.rect=" << tempImage.image ().rect ()
0253                << ")";
0254 #endif
0255 
0256     QRect oldRect;
0257 
0258     if (d->tempImage)
0259     {
0260         oldRect = d->tempImage->rect ();
0261         delete d->tempImage;
0262         d->tempImage = nullptr;
0263     }
0264 
0265     d->tempImage = new kpTempImage (tempImage);
0266 
0267     setQueueUpdates ();
0268     {
0269         if (oldRect.isValid ()) {
0270             updateViews (oldRect);
0271         }
0272         updateViews (d->tempImage->rect ());
0273     }
0274     restoreQueueUpdates ();
0275 }
0276 
0277 //---------------------------------------------------------------------
0278 
0279 // public
0280 void kpViewManager::invalidateTempImage ()
0281 {
0282     if (!d->tempImage) {
0283         return;
0284     }
0285 
0286     QRect oldRect = d->tempImage->rect ();
0287 
0288     delete d->tempImage;
0289     d->tempImage = nullptr;
0290 
0291     updateViews (oldRect);
0292 }
0293 
0294 //---------------------------------------------------------------------
0295 
0296 // public
0297 bool kpViewManager::selectionBorderVisible () const
0298 {
0299     return d->selectionBorderVisible;
0300 }
0301 
0302 //---------------------------------------------------------------------
0303 
0304 // public
0305 void kpViewManager::setSelectionBorderVisible (bool yes)
0306 {
0307     if (d->selectionBorderVisible == yes) {
0308         return;
0309     }
0310 
0311     d->selectionBorderVisible = yes;
0312 
0313     if (document ()->selection ()) {
0314         updateViews (document ()->selection ()->boundingRect ());
0315     }
0316 }
0317 
0318 //---------------------------------------------------------------------
0319 
0320 // public
0321 bool kpViewManager::selectionBorderFinished () const
0322 {
0323     return d->selectionBorderFinished;
0324 }
0325 
0326 //---------------------------------------------------------------------
0327 
0328 // public
0329 void kpViewManager::setSelectionBorderFinished (bool yes)
0330 {
0331     if (d->selectionBorderFinished == yes) {
0332         return;
0333     }
0334 
0335     d->selectionBorderFinished = yes;
0336 
0337     if (document ()->selection ()) {
0338         updateViews (document ()->selection ()->boundingRect ());
0339     }
0340 }
0341 
0342 //---------------------------------------------------------------------
0343 
0344 void kpViewManager::setInputMethodEnabled (bool inputMethodEnabled)
0345 {
0346     d->inputMethodEnabled = inputMethodEnabled;
0347     if (d->viewUnderCursor) {
0348         d->viewUnderCursor->setAttribute (Qt::WA_InputMethodEnabled, inputMethodEnabled);
0349     }
0350 }
0351 
0352 //---------------------------------------------------------------------
0353 
0354 #include "moc_kpViewManager.cpp"