1 /***************************************************************************
2  *   Copyright (C) 2003 by Sébastien Laoût                                 *
3  *   slaout@linux62.org                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 #ifndef NOTE_H
22 #define NOTE_H
23 
24 #include <QtCore/QList>
25 #include <QtCore/QSet>
26 #include <QtCore/QDateTime>
27 #include <QGraphicsItemGroup>
28 
29 #include "basket_export.h"
30 #include "tag.h"
31 
32 class BasketScene;
33 class FilterData;
34 
35 class NoteContent;
36 class NoteSelection;
37 
38 class QPainter;
39 class QPixmap;
40 class QString;
41 class QGraphicsItemAnimation;
42 class QTimeLine;
43 
44 class NotePrivate;
45 
46 /** Handle basket notes and groups!\n
47   * After creation, the note is a group. You should create a NoteContent with this Note
48   * as constructor parameter to transform it to a note with content. eg:
49   * @code
50   * Note *note = new Note(basket);   // note is a group!
51   * new TextContent(note, fileName); // note is now a note with a text content!
52   * new ColorContent(note, Qt::red); // Should never be done!!!!! the old Content should be deleted...
53   * @endcode
54   * @author Sébastien Laoût
55   */
56 class BASKET_EXPORT Note : public QGraphicsItemGroup
57 {
58 /// CONSTRUCTOR AND DESTRUCTOR:
59 public:
60     Note(BasketScene *parent = 0);
61     ~Note();
62 
63 private:
64     NotePrivate* d;
65 
66 /// DOUBLY LINKED LIST:
67 public:
68     void  setNext(Note *next);
69     void  setPrev(Note *prev);
70     Note* next() const;
71     Note* prev() const;
72 
73 public:
74     void setWidth(qreal width);
75     void setWidthForceRelayout(qreal width);
76     //! Do not use it unless you know what you do!
77     void setInitialHeight(qreal height);
78 
79     void setXRecursively(qreal ax);
80     void setYRecursively(qreal ay);
81     void hideRecursively();
82     qreal width() const;
83     qreal height() const;
84     qreal bottom() const;
85     QRectF rect();
86     QRectF resizerRect();
87     QRectF visibleRect();
88     QRectF boundingRect() const;
89     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
90                 QWidget *widget);
91     void relayoutAt(qreal ax, qreal ay, bool animate);
92     qreal contentX() const;
93     qreal minWidth() const;
94     qreal minRight();
95     void unsetWidth();
96     void requestRelayout();
97     /** << DO NEVER USE IT!!! Only available when moving notes, groups should be recreated with the exact same state as before! */
98     void setHeight(qreal height);
99 
100 /// FREE AND COLUMN LAYOUTS MANAGEMENT:
101 private:
102     qreal m_groupWidth;
103 public:
104     qreal  groupWidth() const;
105     void setGroupWidth(qreal width);
106     qreal rightLimit() const;
107     qreal  finalRightLimit() const;
108     bool isFree() const;
109     bool isColumn() const;
110     bool hasResizer() const;
111     qreal resizerHeight() const;
112 
113 /// GROUPS MANAGEMENT:
114 private:
115     bool  m_isFolded;
116     Note *m_firstChild;
117     Note *m_parentNote;
118 public:
isGroup()119     inline bool isGroup() const           {
120         return m_content == 0L;
121     }
isFolded()122     inline bool isFolded()                {
123         return m_isFolded;
124     }
firstChild()125     inline Note* firstChild()             {
126         return m_firstChild;
127     }
parentNote()128     inline Note* parentNote() const       {
129         return m_parentNote;
130     }
131     /*inline*/ bool showSubNotes();//            { return !m_isFolded || !m_collapseFinished; }
setParentNote(Note * note)132     inline void setParentNote(Note *note) {
133         m_parentNote = note;
134     }
setFirstChild(Note * note)135     inline void setFirstChild(Note *note) {
136         m_firstChild = note;
137     }
138     bool isShown();
139     bool  toggleFolded();
140 
141     Note* noteAt(QPointF pos);
142     Note* firstRealChild();
143     Note* lastRealChild();
144     Note* lastChild();
145     Note* lastSibling();
146     qreal yExpander();
147     bool  isAfter(Note *note);
148     bool  containsNote(Note *note);
149 
150 /// NOTES VARIOUS PROPERTIES:       // CONTENT MANAGEMENT?
151 private:
152     BasketScene  *m_basket;
153     NoteContent *m_content;
154     QDateTime    m_addedDate;
155     QDateTime    m_lastModificationDate;
156 public:
basket()157     inline BasketScene*      basket() const {
158         return m_basket;
159     }
content()160     inline NoteContent* content() {
161         return m_content;
162     }
setAddedDate(const QDateTime & dateTime)163     inline void setAddedDate(const QDateTime &dateTime)            {
164         m_addedDate            = dateTime;
165     }
setLastModificationDate(const QDateTime & dateTime)166     inline void setLastModificationDate(const QDateTime &dateTime) {
167         m_lastModificationDate = dateTime;
168     }
169 
170     void setParentBasket(BasketScene *basket);
171 
addedDate()172     QDateTime addedDate()            {
173         return m_addedDate;
174     }
lastModificationDate()175     QDateTime lastModificationDate() {
176         return m_lastModificationDate;
177     }
178     QString addedStringDate();
179     QString lastModificationStringDate();
180     QString toText(const QString &cuttedFullPath);
181     bool saveAgain();
182     void deleteChilds();
183 
184 protected:
185     void setContent(NoteContent *content);
186     friend class NoteContent;
187     friend class AnimationContent;
188 
189 /// DRAWING:
190 private:
191     QPixmap m_bufferedPixmap;
192     QPixmap m_bufferedSelectionPixmap;
193 public:
194     void draw(QPainter *painter, const QRectF &clipRect);
195     void drawBufferOnScreen(QPainter *painter, const QPixmap &contentPixmap);
196     static void getGradientColors(const QColor &originalBackground, QColor *colorTop, QColor *colorBottom);
197     static void drawExpander(QPainter *painter, qreal x, qreal y, const QColor &background, bool expand, BasketScene *basket);
198     void drawHandle(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QColor &background, const QColor &foreground);
199     void drawResizer(QPainter *painter, qreal x, qreal y, qreal width, qreal height, const QColor &background, const QColor &foreground, bool rounded);
200     void drawRoundings(QPainter *painter, qreal x, qreal y, int type, qreal width = 0, qreal height = 0);
201     void unbufferizeAll();
unbufferize()202     inline void unbufferize()  {
203         m_bufferedPixmap = QPixmap(); m_bufferedSelectionPixmap = QPixmap();
204     }
isBufferized()205     inline bool isBufferized() {
206         return !m_bufferedPixmap.isNull();
207     }
208     void recomputeBlankRects(QList<QRectF> &blankAreas);
209     static void drawInactiveResizer(QPainter *painter, qreal x, qreal y, qreal height, const QColor &background, bool column);
210     QPalette palette() const;
211 
212 /// VISIBLE AREAS COMPUTATION:
213 private:
214     QList<QRectF> m_areas;
215     bool              m_computedAreas;
216     bool              m_onTop;
217     void recomputeAreas();
218     bool recomputeAreas(Note *note, bool noteIsAfterThis);
219 public:
220     void setOnTop(bool onTop);
isOnTop()221     inline bool isOnTop() {
222         return m_onTop;
223     }
224     bool isEditing();
225 
226 /// MANAGE ANIMATION:
227 private:
228     QGraphicsItemAnimation *m_animation;
229 public:
230     bool initAnimationLoad(QTimeLine *timeLine);
231     void animationFinished();
232 
233 /// USER INTERACTION:
234 public:
235     enum Zone { None = 0,
236                 Handle, TagsArrow, Custom0, /*CustomContent1, CustomContent2, */Content, Link,
237                 TopInsert, TopGroup, BottomInsert, BottomGroup, BottomColumn,
238                 Resizer,
239                 Group, GroupExpander,
240                 Emblem0
241               }; // Emblem0 should be at end, because we add 1 to get Emblem1, 2 to get Emblem2...
setHovered(bool hovered)242     inline void setHovered(bool hovered)  {
243         m_hovered     = hovered; unbufferize();
244     }
245     void        setHoveredZone(Zone zone);
hovered()246     inline bool hovered()                 {
247         return m_hovered;
248     }
hoveredZone()249     inline Zone hoveredZone()             {
250         return m_hoveredZone;
251     }
252     Zone zoneAt(const QPointF &pos, bool toAdd = false);
253     QRectF zoneRect(Zone zone, const QPointF &pos);
254     Qt::CursorShape cursorFromZone(Zone zone) const;
255     QString linkAt(const QPointF &pos);
256 private:
257     bool m_hovered;
258     Zone m_hoveredZone;
259 
260 /// SELECTION:
261 public:
262     NoteSelection* selectedNotes();
263     void setSelected(bool selected);
264     void setSelectedRecursively(bool selected);
265     void invertSelectionRecursively();
266     void selectIn(const QRectF &rect, bool invertSelection, bool unselectOthers = true);
267     void setFocused(bool focused);
isFocused()268     inline bool isFocused()  {
269         return m_focused;
270     }
isSelected()271     inline bool isSelected() {
272         return m_selected;
273     }
274     bool allSelected();
275     void resetWasInLastSelectionRect();
276     void unselectAllBut(Note *toSelect);
277     void invertSelectionOf(Note *toSelect);
278     Note* theSelectedNote();
279 private:
280     bool m_focused;
281     bool m_selected;
282     bool m_wasInLastSelectionRect;
283 
284 /// TAGS:
285 private:
286     State::List m_states;
287     State       m_computedState;
288     int         m_emblemsCount;
289     bool        m_haveInvisibleTags;
290 public:
291     /*const */State::List& states() const;
emblemsCount()292     inline int emblemsCount() {
293         return m_emblemsCount;
294     }
295     void addState(State *state, bool orReplace = true);
296     void addTag(Tag *tag);
297     void removeState(State *state);
298     void removeTag(Tag *tag);
299     void removeAllTags();
300     void addTagToSelectedNotes(Tag *tag);
301     void removeTagFromSelectedNotes(Tag *tag);
302     void removeAllTagsFromSelectedNotes();
303     void addStateToSelectedNotes(State *state, bool orReplace = true);
304     void changeStateOfSelectedNotes(State *state);
305     bool selectedNotesHaveTags();
306     void inheritTagsOf(Note *note);
307     bool hasTag(Tag *tag);
308     bool hasState(State *state);
309     State* stateOfTag(Tag *tag);
310     State* stateForEmblemNumber(int number) const;
311     bool stateForTagFromSelectedNotes(Tag *tag, State **state);
312     void   recomputeStyle();
313     void   recomputeAllStyles();
314     bool   removedStates(const QList<State*> &deletedStates);
315     QFont  font(); // Computed!
316     QColor backgroundColor(); // Computed!
317     QColor textColor(); // Computed!
318     bool allowCrossReferences();
319 
320 /// FILTERING:
321 private:
322     bool m_matching;
323 public:
324     bool computeMatching(const FilterData &data);
325     int  newFilter(const FilterData &data);
matching()326     bool matching() {
327         return m_matching;
328     }
329 
330 /// ADDED:
331 public:
332     /**
333      * @return true if this note could be deleted
334      **/
335     void deleteSelectedNotes(bool deleteFilesToo = true, QSet<Note*> *notesToBeDeleted = 0);
336     int count();
337     int countDirectChilds();
338 
339     QString fullPath();
340     Note* noteForFullPath(const QString &path);
341 
342     //void update();
343     void linkLookChanged();
344 
345     void usedStates(QList<State*> &states);
346 
347     void listUsedTags(QList<Tag*> &list);
348 
349 
350     Note* nextInStack();
351     Note* prevInStack();
352     Note* nextShownInStack();
353     Note* prevShownInStack();
354 
355     Note* parentPrimaryNote(); // TODO: There are places in the code where this methods is hand-copied / hand-inlined instead of called.
356 
357     Note* firstSelected();
358     Note* lastSelected();
359     Note* selectedGroup();
360     void groupIn(Note *group);
361 
362     bool tryExpandParent();
363     bool tryFoldParent();
364 
365     qreal distanceOnLeftRight(Note *note, int side);
366     qreal distanceOnTopBottom(Note *note, int side);
367 
368     bool convertTexts();
369 
370     void debug();
371 
372 /// SPEED OPTIMIZATION
373 public:
374     void finishLazyLoad();
375 
376 public:
377     // Values are provided here as info:
378     // Please see Settings::setBigNotes() to know whats values are assigned.
379     static qreal NOTE_MARGIN      /*= 2*/;
380     static qreal INSERTION_HEIGHT /*= 5*/;
381     static qreal EXPANDER_WIDTH   /*= 9*/;
382     static qreal EXPANDER_HEIGHT  /*= 9*/;
383     static qreal GROUP_WIDTH      /*= 2*NOTE_MARGIN + EXPANDER_WIDTH*/;
384     static qreal HANDLE_WIDTH     /*= GROUP_WIDTH*/;
385     static qreal RESIZER_WIDTH    /*= GROUP_WIDTH*/;
386     static qreal TAG_ARROW_WIDTH  /*= 5*/;
387     static qreal EMBLEM_SIZE      /*= 16*/;
388     static qreal MIN_HEIGHT       /*= 2*NOTE_MARGIN + EMBLEM_SIZE*/;
389 };
390 
391 /*
392  * Convenience functions:
393  */
394 void drawGradient(QPainter *p, const QColor &colorTop, const QColor & colorBottom,
395 		  qreal x, qreal y, qreal w, qreal h,
396 		  bool sunken, bool horz, bool flat);
397 
398 extern void substractRectOnAreas(const QRectF &rectToSubstract,
399 		QList<QRectF> &areas, bool andRemove = true);
400 
401 #endif // NOTE_H
402