File indexing completed on 2024-03-24 17:24:36
0001 /** 0002 * SPDX-FileCopyrightText: (C) 2003 Sébastien Laoût <slaout@linux62.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef NOTE_H 0008 #define NOTE_H 0009 0010 #include <QGraphicsItemGroup> 0011 #include <QtCore/QDateTime> 0012 #include <QtCore/QList> 0013 #include <QtCore/QSet> 0014 0015 #include "basket_export.h" 0016 #include "tag.h" 0017 0018 class BasketScene; 0019 struct FilterData; 0020 0021 class NoteContent; 0022 class NoteSelection; 0023 0024 class QPainter; 0025 class QPixmap; 0026 class QString; 0027 class QGraphicsItemAnimation; 0028 class QTimeLine; 0029 0030 class NotePrivate; 0031 0032 /** Handle basket notes and groups!\n 0033 * After creation, the note is a group. You should create a NoteContent with this Note 0034 * as constructor parameter to transform it to a note with content. eg: 0035 * @code 0036 * Note *note = new Note(basket); // note is a group! 0037 * new TextContent(note, fileName); // note is now a note with a text content! 0038 * new ColorContent(note, Qt::red); // Should never be done!!!!! the old Content should be deleted... 0039 * @endcode 0040 * @author Sébastien Laoût 0041 */ 0042 class BASKET_EXPORT Note : public QGraphicsItemGroup 0043 { 0044 /// CONSTRUCTOR AND DESTRUCTOR: 0045 public: 0046 explicit Note(BasketScene *parent = nullptr); 0047 ~Note() override; 0048 0049 private: 0050 NotePrivate *d; 0051 0052 /// DOUBLY LINKED LIST: 0053 public: 0054 void setNext(Note *next); 0055 void setPrev(Note *prev); 0056 Note *next() const; 0057 Note *prev() const; 0058 0059 public: 0060 void setWidth(qreal width); 0061 void setWidthForceRelayout(qreal width); 0062 //! Do not use it unless you know what you do! 0063 void setInitialHeight(qreal height); 0064 0065 void setXRecursively(qreal ax); 0066 void setYRecursively(qreal ay); 0067 void hideRecursively(); 0068 qreal width() const; 0069 qreal height() const; 0070 qreal bottom() const; 0071 QRectF rect(); 0072 QRectF resizerRect(); 0073 QRectF visibleRect(); 0074 QRectF boundingRect() const override; 0075 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; 0076 void relayoutAt(qreal ax, qreal ay); 0077 qreal contentX() const; 0078 qreal minWidth() const; 0079 qreal minRight(); 0080 void unsetWidth(); 0081 void requestRelayout(); 0082 /** << DO NEVER USE IT!!! Only available when moving notes, groups should be recreated with the exact same state as before! */ 0083 void setHeight(qreal height); 0084 0085 /// FREE AND COLUMN LAYOUTS MANAGEMENT: 0086 private: 0087 qreal m_groupWidth; 0088 0089 public: 0090 qreal groupWidth() const; 0091 void setGroupWidth(qreal width); 0092 qreal rightLimit() const; 0093 qreal finalRightLimit() const; 0094 bool isFree() const; 0095 bool isColumn() const; 0096 bool hasResizer() const; 0097 qreal resizerHeight() const; 0098 0099 /// GROUPS MANAGEMENT: 0100 private: 0101 bool m_isFolded; 0102 Note *m_firstChild; 0103 Note *m_parentNote; 0104 0105 public: 0106 inline bool isGroup() const 0107 { 0108 return m_content == nullptr; 0109 } 0110 inline bool isFolded() 0111 { 0112 return m_isFolded; 0113 } 0114 inline Note *firstChild() 0115 { 0116 return m_firstChild; 0117 } 0118 inline Note *parentNote() const 0119 { 0120 return m_parentNote; 0121 } 0122 /*inline*/ bool showSubNotes(); // { return !m_isFolded || !m_collapseFinished; } 0123 inline void setParentNote(Note *note) 0124 { 0125 m_parentNote = note; 0126 } 0127 inline void setFirstChild(Note *note) 0128 { 0129 m_firstChild = note; 0130 } 0131 bool isShown(); 0132 bool toggleFolded(); 0133 0134 Note *noteAt(QPointF pos); 0135 Note *firstRealChild(); 0136 Note *lastRealChild(); 0137 Note *lastChild(); 0138 Note *lastSibling(); 0139 qreal yExpander(); 0140 bool isAfter(Note *note); 0141 bool containsNote(Note *note); 0142 0143 /// NOTES VARIOUS PROPERTIES: // CONTENT MANAGEMENT? 0144 private: 0145 BasketScene *m_basket; 0146 NoteContent *m_content; 0147 QDateTime m_addedDate; 0148 QDateTime m_lastModificationDate; 0149 0150 public: 0151 inline BasketScene *basket() const 0152 { 0153 return m_basket; 0154 } 0155 inline NoteContent *content() 0156 { 0157 return m_content; 0158 } 0159 inline void setAddedDate(const QDateTime &dateTime) 0160 { 0161 m_addedDate = dateTime; 0162 } 0163 inline void setLastModificationDate(const QDateTime &dateTime) 0164 { 0165 m_lastModificationDate = dateTime; 0166 } 0167 0168 void setParentBasket(BasketScene *basket); 0169 0170 QDateTime addedDate() 0171 { 0172 return m_addedDate; 0173 } 0174 QDateTime lastModificationDate() 0175 { 0176 return m_lastModificationDate; 0177 } 0178 QString addedStringDate(); 0179 QString lastModificationStringDate(); 0180 QString toText(const QString &cuttedFullPath); 0181 bool saveAgain(); 0182 void deleteChilds(); 0183 0184 protected: 0185 void setContent(NoteContent *content); 0186 friend class NoteContent; 0187 friend class AnimationContent; 0188 0189 /// DRAWING: 0190 private: 0191 QPixmap m_bufferedPixmap; 0192 QPixmap m_bufferedSelectionPixmap; 0193 0194 public: 0195 void draw(QPainter *painter, const QRectF &clipRect); 0196 void drawBufferOnScreen(QPainter *painter, const QPixmap &contentPixmap); 0197 static void getGradientColors(const QColor &originalBackground, QColor *colorTop, QColor *colorBottom); 0198 static void drawExpander(QPainter *painter, qreal x, qreal y, const QColor &background, bool expand, BasketScene *basket); 0199 void drawHandle(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QColor &background, const QColor &foreground, const QColor &lightForeground); 0200 void drawResizer(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QColor &background, const QColor &foreground, bool rounded); 0201 void drawRoundings(QPainter *painter, qreal x, qreal y, int type, qreal width = 0, qreal height = 0); 0202 void unbufferizeAll(); 0203 inline void unbufferize() 0204 { 0205 m_bufferedPixmap = QPixmap(); 0206 m_bufferedSelectionPixmap = QPixmap(); 0207 } 0208 inline bool isBufferized() 0209 { 0210 return !m_bufferedPixmap.isNull(); 0211 } 0212 void recomputeBlankRects(QList<QRectF> &blankAreas); 0213 static void drawInactiveResizer(QPainter *painter, qreal x, qreal y, qreal height, const QColor &background, bool column); 0214 QPalette palette() const; 0215 0216 /// VISIBLE AREAS COMPUTATION: 0217 private: 0218 QList<QRectF> m_areas; 0219 bool m_computedAreas; 0220 bool m_onTop; 0221 void recomputeAreas(); 0222 bool recomputeAreas(Note *note, bool noteIsAfterThis); 0223 0224 public: 0225 void setOnTop(bool onTop); 0226 inline bool isOnTop() 0227 { 0228 return m_onTop; 0229 } 0230 bool isEditing(); 0231 0232 /// MANAGE ANIMATION: 0233 private: 0234 QGraphicsItemAnimation *m_animation; 0235 0236 public: 0237 bool initAnimationLoad(QTimeLine *timeLine); 0238 void animationFinished(); 0239 0240 /// USER INTERACTION: 0241 public: 0242 enum Zone { 0243 None = 0, 0244 Handle, 0245 TagsArrow, 0246 Custom0, 0247 /*CustomContent1, CustomContent2, */ Content, 0248 Link, 0249 TopInsert, 0250 TopGroup, 0251 BottomInsert, 0252 BottomGroup, 0253 BottomColumn, 0254 Resizer, 0255 Group, 0256 GroupExpander, 0257 Emblem0 0258 }; // Emblem0 should be at end, because we add 1 to get Emblem1, 2 to get Emblem2... 0259 inline void setHovered(bool hovered) 0260 { 0261 m_hovered = hovered; 0262 unbufferize(); 0263 } 0264 void setHoveredZone(Zone zone); 0265 inline bool hovered() 0266 { 0267 return m_hovered; 0268 } 0269 inline Zone hoveredZone() 0270 { 0271 return m_hoveredZone; 0272 } 0273 Zone zoneAt(const QPointF &pos, bool toAdd = false); 0274 QRectF zoneRect(Zone zone, const QPointF &pos); 0275 Qt::CursorShape cursorFromZone(Zone zone) const; 0276 QString linkAt(const QPointF &pos); 0277 0278 private: 0279 bool m_hovered; 0280 Zone m_hoveredZone; 0281 0282 /// SELECTION: 0283 public: 0284 NoteSelection *selectedNotes(); 0285 void setSelected(bool selected); 0286 void setSelectedRecursively(bool selected); 0287 void invertSelectionRecursively(); 0288 void selectIn(const QRectF &rect, bool invertSelection, bool unselectOthers = true); 0289 void setFocused(bool focused); 0290 inline bool isFocused() 0291 { 0292 return m_focused; 0293 } 0294 inline bool isSelected() 0295 { 0296 return m_selected; 0297 } 0298 bool allSelected(); 0299 void resetWasInLastSelectionRect(); 0300 void unselectAllBut(Note *toSelect); 0301 void invertSelectionOf(Note *toSelect); 0302 Note *theSelectedNote(); 0303 0304 private: 0305 bool m_focused; 0306 bool m_selected; 0307 bool m_wasInLastSelectionRect; 0308 0309 /// TAGS: 0310 private: 0311 State::List m_states; 0312 State m_computedState; 0313 int m_emblemsCount; 0314 bool m_haveInvisibleTags; 0315 0316 public: 0317 /*const */ State::List &states() const; 0318 inline int emblemsCount() 0319 { 0320 return m_emblemsCount; 0321 } 0322 void addState(State *state, bool orReplace = true); 0323 void addTag(Tag *tag); 0324 void removeState(State *state); 0325 void removeTag(Tag *tag); 0326 void removeAllTags(); 0327 void addTagToSelectedNotes(Tag *tag); 0328 void removeTagFromSelectedNotes(Tag *tag); 0329 void removeAllTagsFromSelectedNotes(); 0330 void addStateToSelectedNotes(State *state, bool orReplace = true); 0331 void changeStateOfSelectedNotes(State *state); 0332 bool selectedNotesHaveTags(); 0333 void inheritTagsOf(Note *note); 0334 bool hasTag(Tag *tag); 0335 bool hasState(State *state); 0336 State *stateOfTag(Tag *tag); 0337 State *stateForEmblemNumber(int number) const; 0338 bool stateForTagFromSelectedNotes(Tag *tag, State **state); 0339 void recomputeStyle(); 0340 void recomputeAllStyles(); 0341 bool removedStates(const QList<State *> &deletedStates); 0342 QFont font(); // Computed! 0343 QColor backgroundColor(); // Computed! 0344 QColor textColor(); // Computed! 0345 bool allowCrossReferences(); 0346 0347 /// FILTERING: 0348 private: 0349 bool m_matching; 0350 0351 public: 0352 bool computeMatching(const FilterData &data); 0353 int newFilter(const FilterData &data); 0354 bool matching() 0355 { 0356 return m_matching; 0357 } 0358 0359 /// ADDED: 0360 public: 0361 /** 0362 * @return true if this note could be deleted 0363 **/ 0364 void deleteSelectedNotes(bool deleteFilesToo = true, QSet<Note *> *notesToBeDeleted = nullptr); 0365 int count(); 0366 int countDirectChilds(); 0367 0368 QString fullPath(); 0369 Note *noteForFullPath(const QString &path); 0370 0371 // void update(); 0372 void linkLookChanged(); 0373 0374 void usedStates(QList<State *> &states); 0375 0376 void listUsedTags(QList<Tag *> &list); 0377 0378 Note *nextInStack(); 0379 Note *prevInStack(); 0380 Note *nextShownInStack(); 0381 Note *prevShownInStack(); 0382 0383 Note *parentPrimaryNote(); // TODO: There are places in the code where this methods is hand-copied / hand-inlined instead of called. 0384 0385 Note *firstSelected(); 0386 Note *lastSelected(); 0387 Note *selectedGroup(); 0388 void groupIn(Note *group); 0389 0390 bool tryExpandParent(); 0391 bool tryFoldParent(); 0392 0393 qreal distanceOnLeftRight(Note *note, int side); 0394 qreal distanceOnTopBottom(Note *note, int side); 0395 0396 bool convertTexts(); 0397 0398 void debug(); 0399 0400 /// SPEED OPTIMIZATION 0401 public: 0402 void finishLazyLoad(); 0403 0404 public: 0405 // Values are provided here as info: 0406 // Please see Settings::setBigNotes() to know whats values are assigned. 0407 static qreal NOTE_MARGIN /*= 2*/; 0408 static qreal INSERTION_HEIGHT /*= 5*/; 0409 static qreal EXPANDER_WIDTH /*= 9*/; 0410 static qreal EXPANDER_HEIGHT /*= 9*/; 0411 static qreal GROUP_WIDTH /*= 2*NOTE_MARGIN + EXPANDER_WIDTH*/; 0412 static qreal HANDLE_WIDTH /*= GROUP_WIDTH*/; 0413 static qreal RESIZER_WIDTH /*= GROUP_WIDTH*/; 0414 static qreal TAG_ARROW_WIDTH /*= 5*/; 0415 static qreal EMBLEM_SIZE /*= 16*/; 0416 static qreal MIN_HEIGHT /*= 2*NOTE_MARGIN + EMBLEM_SIZE*/; 0417 }; 0418 0419 /* 0420 * Convenience functions: 0421 */ 0422 0423 extern void substractRectOnAreas(const QRectF &rectToSubstract, QList<QRectF> &areas, bool andRemove = true); 0424 0425 #endif // NOTE_H