1 /****************************************************************************************
2 * Copyright (c) 2010 Rick W. Chen <stuffcorpse@archlinux.us> *
3 * *
4 * This program is free software; you can redistribute it and/or modify it under *
5 * the terms of the GNU General Public License as published by the Free Software *
6 * Foundation; either version 2 of the License, or (at your option) any later *
7 * version. *
8 * *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
12 * *
13 * You should have received a copy of the GNU General Public License along with *
14 * this program. If not, see <http://www.gnu.org/licenses/>. *
15 ****************************************************************************************/
16
17 #define DEBUG_PREFIX "UpcomingEventsStack"
18
19 #include "UpcomingEventsStack.h"
20 #include "UpcomingEventsStackItem.h"
21 #include "core/support/Debug.h"
22
23 #include <QGraphicsLinearLayout>
24 #include <QSet>
25 #include <QWeakPointer>
26
27 class UpcomingEventsStackPrivate
28 {
29 private:
30 UpcomingEventsStack *const q_ptr;
31 Q_DECLARE_PUBLIC( UpcomingEventsStack )
32
33 public:
34 UpcomingEventsStackPrivate( UpcomingEventsStack *parent );
35 ~UpcomingEventsStackPrivate();
36
37 QGraphicsLinearLayout *layout;
38 QHash< QString, QWeakPointer<UpcomingEventsStackItem> > items;
39
_itemDestroyed()40 void _itemDestroyed()
41 {
42 QHashIterator< QString, QWeakPointer<UpcomingEventsStackItem> > i(items);
43 while( i.hasNext() )
44 {
45 i.next();
46 if( i.value().isNull() )
47 items.remove( i.key() );
48 }
49 }
50 };
51
UpcomingEventsStackPrivate(UpcomingEventsStack * parent)52 UpcomingEventsStackPrivate::UpcomingEventsStackPrivate( UpcomingEventsStack *parent )
53 : q_ptr( parent )
54 , layout( 0 )
55 {
56 }
57
~UpcomingEventsStackPrivate()58 UpcomingEventsStackPrivate::~UpcomingEventsStackPrivate()
59 {
60 }
61
UpcomingEventsStack(QGraphicsItem * parent,Qt::WindowFlags wFlags)62 UpcomingEventsStack::UpcomingEventsStack( QGraphicsItem *parent, Qt::WindowFlags wFlags )
63 : QGraphicsWidget( parent, wFlags )
64 , d_ptr( new UpcomingEventsStackPrivate( this ) )
65 {
66 Q_D( UpcomingEventsStack );
67 d->layout = new QGraphicsLinearLayout( Qt::Vertical, this );
68 d->layout->setContentsMargins( 0, 0, 0, 0 );
69 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
70 }
71
~UpcomingEventsStack()72 UpcomingEventsStack::~UpcomingEventsStack()
73 {
74 delete d_ptr;
75 }
76
77 int
count() const78 UpcomingEventsStack::count() const
79 {
80 Q_D( const UpcomingEventsStack );
81 return d->layout->count();
82 }
83
84 void
clear()85 UpcomingEventsStack::clear()
86 {
87 prepareGeometryChange();
88 Q_D( UpcomingEventsStack );
89 int itemCount = d->layout->count();
90 while( --itemCount >= 0 )
91 {
92 QGraphicsLayoutItem *child = d->layout->itemAt( 0 );
93 d->layout->removeItem( child );
94 }
95 foreach( QWeakPointer<UpcomingEventsStackItem> item, d->items )
96 item.data()->deleteLater();
97 d->items.clear();
98 }
99
100 bool
isEmpty() const101 UpcomingEventsStack::isEmpty() const
102 {
103 Q_D( const UpcomingEventsStack );
104 return d->items.isEmpty();
105 }
106
107 bool
hasItem(const QString & name) const108 UpcomingEventsStack::hasItem( const QString &name ) const
109 {
110 Q_D( const UpcomingEventsStack );
111 if( d->items.value( name ) )
112 return true;
113 else
114 return false;
115 }
116
117 UpcomingEventsStackItem *
item(const QString & name) const118 UpcomingEventsStack::item( const QString &name ) const
119 {
120 Q_D( const UpcomingEventsStack );
121 Q_ASSERT( d->items.contains( name ) );
122 return d->items.value( name ).data();
123 }
124
125 QList<UpcomingEventsStackItem *>
items(const QRegExp & pattern) const126 UpcomingEventsStack::items( const QRegExp &pattern ) const
127 {
128 Q_D( const UpcomingEventsStack );
129 QList<UpcomingEventsStackItem *> matched;
130 QHashIterator< QString, QWeakPointer<UpcomingEventsStackItem> > i( d->items );
131 while( i.hasNext() )
132 {
133 i.next();
134 if( i.key().contains( pattern ) )
135 matched << i.value().data();
136 }
137 return matched;
138 }
139
140 UpcomingEventsStackItem *
create(const QString & name)141 UpcomingEventsStack::create( const QString &name )
142 {
143 if( hasItem( name ) )
144 return 0;
145
146 Q_D( UpcomingEventsStack );
147 QWeakPointer<UpcomingEventsStackItem> item = new UpcomingEventsStackItem( name, this );
148 d->layout->addItem( item.data() );
149 d->items.insert( name, item );
150 connect( item.data(), SIGNAL(destroyed()), SLOT(_itemDestroyed()) );
151 connect( item.data(), SIGNAL(collapseChanged(bool)), SIGNAL(collapseStateChanged()) );
152 return item.data();
153 }
154
155 void
remove(const QString & name)156 UpcomingEventsStack::remove( const QString &name )
157 {
158 Q_D( UpcomingEventsStack );
159 d->items.take( name ).data()->deleteLater();
160 }
161
162 void
maximizeItem(const QString & name)163 UpcomingEventsStack::maximizeItem( const QString &name )
164 {
165 if( hasItem( name ) )
166 {
167 Q_D( UpcomingEventsStack );
168 d->items.value( name ).data()->setCollapsed( false );
169 QHashIterator< QString, QWeakPointer<UpcomingEventsStackItem> > i( d->items );
170 while( i.hasNext() )
171 {
172 i.next();
173 if( i.value().data()->name() != name )
174 i.value().data()->setCollapsed( true );
175 }
176 }
177 }
178
179 void
cleanupListWidgets()180 UpcomingEventsStack::cleanupListWidgets()
181 {
182 Q_D( UpcomingEventsStack );
183 QHashIterator< QString, QWeakPointer<UpcomingEventsStackItem> > i( d->items );
184 while( i.hasNext() )
185 {
186 i.next();
187 if( i.value().isNull() )
188 d->items.remove( i.key() );
189 }
190 }
191
192