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