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 
46 namespace KMail {
47 
48 SubscriptionDialogBase::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 //------------------------------------------------------------------------------
69 void 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 
86 void 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 
111 void 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 //------------------------------------------------------------------------------
201 void 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 //------------------------------------------------------------------------------
219 void SubscriptionDialogBase::slotSave()
220 {
221  doSave();
222 }
223 
224 //------------------------------------------------------------------------------
225 void 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 //------------------------------------------------------------------------------
253 void 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 
296 void SubscriptionDialogBase::loadingComplete()
297 {
298  slotLoadingComplete();
299 }
300 
301 
302 //------------------------------------------------------------------------------
303 // implementation for server side subscription
304 //------------------------------------------------------------------------------
305 
306 SubscriptionDialog::SubscriptionDialog( TQWidget *parent, const TQString &caption,
307  KAccount *acct, TQString startPath )
308  : SubscriptionDialogBase( parent, caption, acct, startPath )
309 {
310 }
311 
312 /* virtual */
313 SubscriptionDialog::~SubscriptionDialog()
314 {
315 
316 }
317 
318 /* virtual */
319 void SubscriptionDialog::listAllAvailableAndCreateItems()
320 {
321  initPrefixList();
322  processNext();
323 }
324 
325 //------------------------------------------------------------------------------
326 void 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 
351 void SubscriptionDialogBase::slotConnectionResult( int errorCode, const TQString& errorMsg )
352 {
353  Q_UNUSED( errorMsg );
354  if ( !errorCode )
355  slotLoadFolders();
356 }
357 
358 void SubscriptionDialogBase::show()
359 {
360  KDialogBase::show();
361 }
362 
363 // =======
364 /* virtual */
365 void SubscriptionDialog::processFolderListing()
366 {
367  processItems();
368 }
369 
370 /* virtual */
371 void 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 
411 void 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