kmail

subscriptiondialog.cpp
1/*
2 subscriptiondialog.cpp
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (C) 2002 Carsten Burghardt <burghardt@kde.org>
6
7 KMail is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License, version 2, as
9 published by the Free Software Foundation.
10
11 KMail is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 In addition, as a special exception, the copyright holders give
21 permission to link the code of this program with any edition of
22 the TQt library by Trolltech AS, Norway (or with modified versions
23 of TQt that use the same license as TQt), and distribute linked
24 combinations including the two. You must obey the GNU General
25 Public License in all respects for all of the code used other than
26 TQt. If you modify this file, you may extend this exception to
27 your version of the file, but you are not obligated to do so. If
28 you do not wish to do so, delete this exception statement from
29 your version.
30*/
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "subscriptiondialog.h"
37#include "folderstorage.h"
38#include "listjob.h"
39#include "imapaccountbase.h"
40
41#include <tdelocale.h>
42#include <kdebug.h>
43#include <tdemessagebox.h>
44
45
46namespace KMail {
47
48SubscriptionDialogBase::SubscriptionDialogBase( TQWidget *parent, const TQString &caption,
49 KAccount *acct, TQString startPath )
50 : KSubscription( parent, caption, acct, User1, TQString(), false ),
51 mStartPath( startPath ), mSubscribed( false ), mForceSubscriptionEnable( false)
52{
53 // hide unneeded checkboxes
54 hideTreeCheckbox();
55 hideNewOnlyCheckbox();
56
57 // ok-button
58 connect(this, TQ_SIGNAL(okClicked()), TQ_SLOT(slotSave()));
59
60 // reload-list button
61 connect(this, TQ_SIGNAL(user1Clicked()), TQ_SLOT(slotLoadFolders()));
62
63 // get the folders, delayed execution style, otherwise there's bother
64 // with virtuals from ctors and whatnot
65 TQTimer::singleShot(0, this, TQ_SLOT(slotLoadFolders()));
66}
67
68//------------------------------------------------------------------------------
69void SubscriptionDialogBase::slotListDirectory( const TQStringList& subfolderNames,
70 const TQStringList& subfolderPaths,
71 const TQStringList& subfolderMimeTypes,
72 const TQStringList& subfolderAttributes,
73 const ImapAccountBase::jobData& jobData )
74{
75 mFolderNames = subfolderNames;
76 mFolderPaths = subfolderPaths;
77 mFolderMimeTypes = subfolderMimeTypes;
78 mFolderAttributes = subfolderAttributes;
79 mJobData = jobData;
80
81 mCount = 0;
82
83 processFolderListing();
84}
85
86void SubscriptionDialogBase::moveChildrenToNewParent( GroupItem *oldItem, GroupItem *item )
87{
88 if ( !oldItem || !item ) return;
89
90 TQPtrList<TQListViewItem> itemsToMove;
91 TQListViewItem * myChild = oldItem->firstChild();
92 while (myChild)
93 {
94 itemsToMove.append(myChild);
95 myChild = myChild->nextSibling();
96 }
97 TQPtrListIterator<TQListViewItem> it( itemsToMove );
98 TQListViewItem *cur;
99 while ((cur = it.current()))
100 {
101 oldItem->takeItem(cur);
102 item->insertItem(cur);
103 if ( cur->isSelected() ) // we have new parents so open them
104 folderTree()->ensureItemVisible( cur );
105 ++it;
106 }
107 delete oldItem;
108 itemsToMove.clear();
109}
110
111void SubscriptionDialogBase::createListViewItem( int i )
112{
113 GroupItem *item = 0;
114 GroupItem *parent = 0;
115
116 // get the parent
117 GroupItem *oldItem = 0;
118 TQString parentPath;
119 findParentItem( mFolderNames[i], mFolderPaths[i], parentPath, &parent, &oldItem );
120
121 if (!parent && parentPath != "/")
122 {
123 // the parent is not available and it's no root-item
124 // this happens when the folders do not arrive in hierarchical order
125 // so we create each parent in advance
126 TQStringList folders = TQStringList::split(mDelimiter, parentPath);
127 uint i = 0;
128 for ( TQStringList::Iterator it = folders.begin(); it != folders.end(); ++it )
129 {
130 TQString name = *it;
131 if (name.startsWith("/"))
132 name = name.right(name.length()-1);
133 if (name.endsWith("/"))
134 name.truncate(name.length()-1);
135 KGroupInfo info(name);
136 info.subscribed = false;
137
138 TQStringList tmpPath;
139 for ( uint j = 0; j <= i; ++j )
140 tmpPath << folders[j];
141 TQString path = tmpPath.join(mDelimiter);
142 if (!path.startsWith("/"))
143 path = "/" + path;
144 if (!path.endsWith("/"))
145 path = path + "/";
146 info.path = path;
147 item = 0;
148 if (folders.count() > 1)
149 {
150 // we have to create more then one level, so better check if this
151 // folder already exists somewhere
152 item = mItemDict[path];
153 }
154 // as these items are "dummies" we create them non-checkable
155 if (!item)
156 {
157 if (parent)
158 item = new GroupItem(parent, info, this, false);
159 else
160 item = new GroupItem(folderTree(), info, this, false);
161 mItemDict.insert(info.path, item);
162 }
163
164 parent = item;
165 ++i;
166 } // folders
167 } // parent
168
169 KGroupInfo info(mFolderNames[i]);
170 if (mFolderNames[i].upper() == "INBOX" &&
171 mFolderPaths[i] == "/INBOX/")
172 info.name = i18n("inbox");
173 info.subscribed = false;
174 info.path = mFolderPaths[i];
175 // only checkable when the folder is selectable
176 bool checkable = ( mFolderMimeTypes[i] == "inode/directory" ) ? false : true;
177 // create a new item
178 if (parent)
179 item = new GroupItem(parent, info, this, checkable);
180 else
181 item = new GroupItem(folderTree(), info, this, checkable);
182
183 if (oldItem) // remove old item
184 mItemDict.remove(info.path);
185
186 mItemDict.insert(info.path, item);
187 if (oldItem)
188 moveChildrenToNewParent( oldItem, item );
189
190 // select the start item
191 if ( mFolderPaths[i] == mStartPath )
192 {
193 item->setSelected( true );
194 folderTree()->ensureItemVisible( item );
195 }
196}
197
198
199
200//------------------------------------------------------------------------------
201void SubscriptionDialogBase::findParentItem( TQString &name, TQString &path, TQString &parentPath,
202 GroupItem **parent, GroupItem **oldItem )
203{
204 // remove the name (and the separator) from the path to get the parent path
205 int start = path.length() - (name.length()+2);
206 int length = name.length()+1;
207 if (start < 0) start = 0;
208 parentPath = path;
209 parentPath.remove(start, length);
210
211 // find the parent by it's path
212 *parent = mItemDict[parentPath];
213
214 // check if the item already exists
215 *oldItem = mItemDict[path];
216}
217
218//------------------------------------------------------------------------------
219void SubscriptionDialogBase::slotSave()
220{
221 doSave();
222}
223
224//------------------------------------------------------------------------------
225void SubscriptionDialogBase::slotLoadFolders()
226{
227 ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
228 // we need a connection
229 if ( ai->makeConnection() == ImapAccountBase::Error )
230 {
231 kdWarning(5006) << "SubscriptionDialog - got no connection" << endl;
232 return;
233 } else if ( ai->makeConnection() == ImapAccountBase::Connecting )
234 {
235 // We'll wait for the connectionResult signal from the account.
236 kdDebug(5006) << "SubscriptionDialog - waiting for connection" << endl;
237 connect( ai, TQ_SIGNAL( connectionResult(int, const TQString&) ),
238 this, TQ_SLOT( slotConnectionResult(int, const TQString&) ) );
239 return;
240 }
241 // clear the views
242 KSubscription::slotLoadFolders();
243 mItemDict.clear();
244 mSubscribed = false;
245 mLoading = true;
246
247 // first step is to load a list of all available folders and create listview
248 // items for them
249 listAllAvailableAndCreateItems();
250}
251
252//------------------------------------------------------------------------------
253void SubscriptionDialogBase::processNext()
254{
255 if ( mPrefixList.isEmpty() )
256 {
257 if ( !mSubscribed )
258 {
259 mSubscribed = true;
260 initPrefixList();
261 if ( mPrefixList.isEmpty() )
262 {
263 // still empty? then we have nothing to do here as this is an error
264 loadingComplete();
265 return;
266 }
267 } else {
268 loadingComplete();
269 return;
270 }
271 }
272 ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
273 ImapAccountBase::ListType type = ( mSubscribed ?
274 ImapAccountBase::ListSubscribedNoCheck : ImapAccountBase::List );
275
276 bool completeListing = true;
277 mCurrentNamespace = mPrefixList.first();
278 mDelimiter = ai->delimiterForNamespace( mCurrentNamespace );
279 mPrefixList.pop_front();
280 if ( mCurrentNamespace == "/INBOX/" )
281 {
282 type = mSubscribed ?
283 ImapAccountBase::ListFolderOnlySubscribed : ImapAccountBase::ListFolderOnly;
284 completeListing = false;
285 }
286
287// kdDebug(5006) << "process " << mCurrentNamespace << ",subscribed=" << mSubscribed << endl;
288 ListJob* job = new ListJob( ai, type, 0, ai->addPathToNamespace( mCurrentNamespace ), completeListing );
289 connect( job, TQ_SIGNAL(receivedFolders(const TQStringList&, const TQStringList&,
290 const TQStringList&, const TQStringList&, const ImapAccountBase::jobData&)),
291 this, TQ_SLOT(slotListDirectory(const TQStringList&, const TQStringList&,
292 const TQStringList&, const TQStringList&, const ImapAccountBase::jobData&)));
293 job->start();
294}
295
296void SubscriptionDialogBase::loadingComplete()
297{
298 slotLoadingComplete();
299}
300
301
302//------------------------------------------------------------------------------
303// implementation for server side subscription
304//------------------------------------------------------------------------------
305
306SubscriptionDialog::SubscriptionDialog( TQWidget *parent, const TQString &caption,
307 KAccount *acct, TQString startPath )
308 : SubscriptionDialogBase( parent, caption, acct, startPath )
309{
310}
311
312/* virtual */
313SubscriptionDialog::~SubscriptionDialog()
314{
315
316}
317
318/* virtual */
319void SubscriptionDialog::listAllAvailableAndCreateItems()
320{
321 initPrefixList();
322 processNext();
323}
324
325//------------------------------------------------------------------------------
326void SubscriptionDialogBase::initPrefixList()
327{
328 ImapAccountBase* ai = static_cast<ImapAccountBase*>(account());
329 ImapAccountBase::nsMap map = ai->namespaces();
330 mPrefixList.clear();
331
332 bool hasInbox = false;
333 const TQStringList ns = map[ImapAccountBase::PersonalNS];
334 for ( TQStringList::ConstIterator it = ns.begin(); it != ns.end(); ++it )
335 {
336 if ( (*it).isEmpty() )
337 hasInbox = true;
338 }
339 if ( !hasInbox && !ns.isEmpty() )
340 {
341 // the namespaces includes no listing for the root so start a special
342 // listing for the INBOX to make sure we get it
343 mPrefixList += "/INBOX/";
344 }
345
346 mPrefixList += map[ImapAccountBase::PersonalNS];
347 mPrefixList += map[ImapAccountBase::OtherUsersNS];
348 mPrefixList += map[ImapAccountBase::SharedNS];
349}
350
351void SubscriptionDialogBase::slotConnectionResult( int errorCode, const TQString& errorMsg )
352{
353 Q_UNUSED( errorMsg );
354 if ( !errorCode )
355 slotLoadFolders();
356}
357
358void SubscriptionDialogBase::show()
359{
360 KDialogBase::show();
361}
362
363// =======
364/* virtual */
365void SubscriptionDialog::processFolderListing()
366{
367 processItems();
368}
369
370/* virtual */
371void SubscriptionDialog::doSave()
372{
373 KMail::ImapAccountBase *a = static_cast<KMail::ImapAccountBase*>(mAcct);
374 if( !a->onlySubscribedFolders() ) {
375 int result = KMessageBox::questionYesNoCancel( this,
376 i18n("Currently subscriptions are not used for server. %1\nDo you want to enable subscriptions?")
377 .arg( a->name() ),
378 i18n("Enable Subscriptions?"), i18n("Enable"), i18n("Do Not Enable"));
379 switch(result) {
380 case KMessageBox::Yes:
381 mForceSubscriptionEnable = true;
382 break;
383 case KMessageBox::No:
384 break;
385 case KMessageBox::Cancel:
386 cancel();
387 }
388 }
389
390 // subscribe
391 TQListViewItemIterator it(subView);
392 for ( ; it.current(); ++it)
393 {
394 static_cast<ImapAccountBase*>(account())->changeSubscription(true,
395 static_cast<GroupItem*>(it.current())->info().path);
396 }
397
398 // unsubscribe
399 TQListViewItemIterator it2(unsubView);
400 for ( ; it2.current(); ++it2)
401 {
402 static_cast<ImapAccountBase*>(account())->changeSubscription(false,
403 static_cast<GroupItem*>(it2.current())->info().path);
404 }
405
406 if ( mForceSubscriptionEnable ) {
407 a->setOnlySubscribedFolders(true);
408 }
409}
410
411void SubscriptionDialog::processItems()
412{
413 bool onlySubscribed = mJobData.onlySubscribed;
414 uint done = 0;
415 for (uint i = mCount; i < mFolderNames.count(); ++i)
416 {
417 // give the dialog a chance to repaint
418 if (done == 1000)
419 {
420 emit listChanged();
421 TQTimer::singleShot(0, this, TQ_SLOT(processItems()));
422 return;
423 }
424 ++mCount;
425 ++done;
426 if (!onlySubscribed && mFolderPaths.size() > 0)
427 {
428 createListViewItem( i );
429 } else if (onlySubscribed)
430 {
431 // find the item
432 if ( mItemDict[mFolderPaths[i]] )
433 {
434 GroupItem* item = mItemDict[mFolderPaths[i]];
435 item->setOn( true );
436 }
437 }
438 }
439
440 processNext();
441}
442} // namespace
443
444#include "subscriptiondialog.moc"
folderdiaquotatab.h
Definition: aboutdata.cpp:40