00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ksubscription.h"
00014 #include "kaccount.h"
00015
00016 #include <qlayout.h>
00017 #include <qtimer.h>
00018 #include <qlabel.h>
00019 #include <qpushbutton.h>
00020 #include <qheader.h>
00021 #include <qtoolbutton.h>
00022
00023 #include <kseparator.h>
00024 #include <kapplication.h>
00025 #include <kiconloader.h>
00026 #include <klocale.h>
00027 #include <kdebug.h>
00028 #include <klineedit.h>
00029
00030
00031
00032
00033 KGroupInfo::KGroupInfo(const QString &name, const QString &description,
00034 bool newGroup, bool subscribed,
00035 Status status, QString path)
00036 : name(name), description(description),
00037 newGroup(newGroup), subscribed(subscribed),
00038 status(status), path(path)
00039 {
00040 }
00041
00042
00043 bool KGroupInfo::operator== (const KGroupInfo &gi2)
00044 {
00045 return (name == gi2.name);
00046 }
00047
00048
00049 bool KGroupInfo::operator< (const KGroupInfo &gi2)
00050 {
00051 return (name < gi2.name);
00052 }
00053
00054
00055
00056 GroupItem::GroupItem( QListView *v, const KGroupInfo &gi, KSubscription* browser,
00057 bool isCheckItem )
00058 : QCheckListItem( v, gi.name, isCheckItem ? CheckBox : CheckBoxController ),
00059 mInfo( gi ), mBrowser( browser ), mIsCheckItem( isCheckItem ),
00060 mIgnoreStateChange( false )
00061 {
00062 if (listView()->columns() > 1)
00063 setDescription();
00064 }
00065
00066
00067 GroupItem::GroupItem( QListViewItem *i, const KGroupInfo &gi, KSubscription* browser,
00068 bool isCheckItem )
00069 : QCheckListItem( i, gi.name, isCheckItem ? CheckBox : CheckBoxController ),
00070 mInfo( gi ), mBrowser( browser ), mIsCheckItem( isCheckItem ),
00071 mIgnoreStateChange( false )
00072 {
00073 if (listView()->columns() > 1)
00074 setDescription();
00075 }
00076
00077
00078 void GroupItem::setInfo( KGroupInfo info )
00079 {
00080 mInfo = info;
00081 setText(0, mInfo.name);
00082 if (listView()->columns() > 1)
00083 setDescription();
00084 }
00085
00086
00087 void GroupItem::setDescription()
00088 {
00089 setText(1, mInfo.description);
00090 }
00091
00092
00093 void GroupItem::setOn( bool on )
00094 {
00095 if (mBrowser->isLoading())
00096 {
00097
00098
00099 mInfo.subscribed = on;
00100 }
00101 if (isCheckItem())
00102 QCheckListItem::setOn(on);
00103 }
00104
00105
00106 void GroupItem::stateChange( bool on )
00107 {
00108
00109 if ( !mIgnoreStateChange )
00110 mBrowser->changeItemState(this, on);
00111 }
00112
00113
00114 void GroupItem::setVisible( bool b )
00115 {
00116 if (b)
00117 {
00118 QListViewItem::setVisible(b);
00119 setEnabled(true);
00120 }
00121 else
00122 {
00123 if (isCheckItem())
00124 {
00125 bool setInvisible = true;
00126 for (QListViewItem * lvchild = firstChild(); lvchild != 0;
00127 lvchild = lvchild->nextSibling())
00128 {
00129 if (lvchild->isVisible())
00130 setInvisible = false;
00131 }
00132 if (setInvisible)
00133 QListViewItem::setVisible(b);
00134 else
00135 {
00136
00137 setOpen(true);
00138 setEnabled(false);
00139 }
00140 }
00141 else
00142 {
00143
00144 QPtrList<QListViewItem> moveItems;
00145
00146 for (QListViewItem * lvchild = firstChild(); lvchild != 0;
00147 lvchild = lvchild->nextSibling())
00148 {
00149 if (static_cast<GroupItem*>(lvchild)->isCheckItem())
00150 {
00151
00152 moveItems.append(lvchild);
00153 }
00154 }
00155 QPtrListIterator<QListViewItem> it( moveItems );
00156 for ( ; it.current(); ++it)
00157 {
00158
00159 QListViewItem* parent = it.current()->parent();
00160 if (parent) parent->takeItem(it.current());
00161 listView()->insertItem(it.current());
00162 }
00163 QListViewItem::setVisible(false);
00164 }
00165 }
00166 }
00167
00168
00169 void GroupItem::paintCell( QPainter * p, const QColorGroup & cg,
00170 int column, int width, int align )
00171 {
00172 if (mIsCheckItem)
00173 return QCheckListItem::paintCell( p, cg, column, width, align );
00174 else
00175 return QListViewItem::paintCell( p, cg, column, width, align );
00176 }
00177
00178
00179 void GroupItem::paintFocus( QPainter * p, const QColorGroup & cg,
00180 const QRect & r )
00181 {
00182 if (mIsCheckItem)
00183 QCheckListItem::paintFocus(p, cg, r);
00184 else
00185 QListViewItem::paintFocus(p, cg, r);
00186 }
00187
00188
00189 int GroupItem::width( const QFontMetrics& fm, const QListView* lv, int column) const
00190 {
00191 if (mIsCheckItem)
00192 return QCheckListItem::width(fm, lv, column);
00193 else
00194 return QListViewItem::width(fm, lv, column);
00195 }
00196
00197
00198 void GroupItem::setup()
00199 {
00200 if (mIsCheckItem)
00201 QCheckListItem::setup();
00202 else
00203 QListViewItem::setup();
00204 }
00205
00206
00207
00208
00209 KSubscription::KSubscription( QWidget *parent, const QString &caption,
00210 KAccount * acct, int buttons, const QString &user1, bool descriptionColumn )
00211 : KDialogBase( parent, 0, true, caption, buttons | Help | Ok | Cancel, Ok,
00212 true, i18n("Reload &List"), user1 ),
00213 mAcct( acct )
00214 {
00215 mLoading = true;
00216 setWFlags( getWFlags() | WDestructiveClose );
00217
00218
00219 page = new QWidget(this);
00220 setMainWidget(page);
00221
00222 QLabel *comment = new QLabel("<p>"+
00223 i18n("Manage which mail folders you want to see in your folder view") + "</p>", page);
00224
00225 QToolButton *clearButton = new QToolButton( page );
00226 clearButton->setIconSet( KGlobal::iconLoader()->loadIconSet(
00227 KApplication::reverseLayout() ? "clear_left":"locationbar_erase", KIcon::Small, 0 ) );
00228 filterEdit = new KLineEdit(page);
00229 QLabel *l = new QLabel(filterEdit,i18n("S&earch:"), page);
00230 connect( clearButton, SIGNAL( clicked() ), filterEdit, SLOT( clear() ) );
00231
00232
00233 noTreeCB = new QCheckBox(i18n("Disable &tree view"), page);
00234 noTreeCB->setChecked(false);
00235 subCB = new QCheckBox(i18n("&Subscribed only"), page);
00236 subCB->setChecked(false);
00237 newCB = new QCheckBox(i18n("&New only"), page);
00238 newCB->setChecked(false);
00239
00240
00241 KSeparator *sep = new KSeparator(KSeparator::HLine, page);
00242
00243
00244 QFont fnt = font();
00245 fnt.setBold(true);
00246 leftLabel = new QLabel(i18n("Loading..."), page);
00247 rightLabel = new QLabel(i18n("Current changes:"), page);
00248 leftLabel->setFont(fnt);
00249 rightLabel->setFont(fnt);
00250
00251
00252 pmRight = BarIconSet("forward");
00253 pmLeft = BarIconSet("back");
00254
00255 arrowBtn1 = new QPushButton(page);
00256 arrowBtn1->setEnabled(false);
00257 arrowBtn2 = new QPushButton(page);
00258 arrowBtn2->setEnabled(false);
00259 arrowBtn1->setIconSet(pmRight);
00260 arrowBtn2->setIconSet(pmRight);
00261 arrowBtn1->setFixedSize(35,30);
00262 arrowBtn2->setFixedSize(35,30);
00263
00264
00265 groupView = new QListView(page);
00266 groupView->setRootIsDecorated(true);
00267 groupView->addColumn(i18n("Name"));
00268 groupView->setAllColumnsShowFocus(true);
00269 if (descriptionColumn)
00270 mDescrColumn = groupView->addColumn(i18n("Description"));
00271 else
00272 groupView->header()->setStretchEnabled(true, 0);
00273
00274
00275 QGridLayout *topL = new QGridLayout(page,4,1,0, KDialog::spacingHint());
00276 QHBoxLayout *filterL = new QHBoxLayout(KDialog::spacingHint());
00277 QVBoxLayout *arrL = new QVBoxLayout(KDialog::spacingHint());
00278 listL = new QGridLayout(2, 3, KDialog::spacingHint());
00279
00280 topL->addWidget(comment, 0,0);
00281 topL->addLayout(filterL, 1,0);
00282 topL->addWidget(sep,2,0);
00283 topL->addLayout(listL, 3,0);
00284
00285 filterL->addWidget(clearButton);
00286 filterL->addWidget(l);
00287 filterL->addWidget(filterEdit, 1);
00288 filterL->addWidget(noTreeCB);
00289 filterL->addWidget(subCB);
00290 filterL->addWidget(newCB);
00291
00292 listL->addWidget(leftLabel, 0,0);
00293 listL->addWidget(rightLabel, 0,2);
00294 listL->addWidget(groupView, 1,0);
00295 listL->addLayout(arrL, 1,1);
00296 listL->setRowStretch(1,1);
00297 listL->setColStretch(0,5);
00298 listL->setColStretch(2,2);
00299
00300 arrL->addWidget(arrowBtn1, AlignCenter);
00301 arrL->addWidget(arrowBtn2, AlignCenter);
00302
00303
00304 subView = new QListView(page);
00305 subView->addColumn(i18n("Subscribe To"));
00306 subView->header()->setStretchEnabled(true, 0);
00307 unsubView = new QListView(page);
00308 unsubView->addColumn(i18n("Unsubscribe From"));
00309 unsubView->header()->setStretchEnabled(true, 0);
00310
00311 QVBoxLayout *protL = new QVBoxLayout(3);
00312 listL->addLayout(protL, 1,2);
00313 protL->addWidget(subView);
00314 protL->addWidget(unsubView);
00315
00316
00317 enableButton(User1, false);
00318 enableButton(User2, false);
00319 newCB->setEnabled(false);
00320 noTreeCB->setEnabled(false);
00321 subCB->setEnabled(false);
00322
00323 filterEdit->setFocus();
00324
00325
00326 connect(groupView, SIGNAL(clicked(QListViewItem *)),
00327 this, SLOT(slotChangeButtonState(QListViewItem*)));
00328 connect(subView, SIGNAL(clicked(QListViewItem *)),
00329 this, SLOT(slotChangeButtonState(QListViewItem*)));
00330 connect(unsubView, SIGNAL(clicked(QListViewItem *)),
00331 this, SLOT(slotChangeButtonState(QListViewItem*)));
00332
00333
00334 connect(arrowBtn1, SIGNAL(clicked()), SLOT(slotButton1()));
00335 connect(arrowBtn2, SIGNAL(clicked()), SLOT(slotButton2()));
00336 connect(this, SIGNAL(user1Clicked()), SLOT(slotLoadFolders()));
00337
00338
00339 connect(subCB, SIGNAL(clicked()), SLOT(slotCBToggled()));
00340 connect(newCB, SIGNAL(clicked()), SLOT(slotCBToggled()));
00341 connect(noTreeCB, SIGNAL(clicked()), SLOT(slotCBToggled()));
00342
00343
00344 connect(filterEdit, SIGNAL(textChanged(const QString&)),
00345 SLOT(slotFilterTextChanged(const QString&)));
00346
00347
00348 connect(this, SIGNAL(listChanged()), SLOT(slotUpdateStatusLabel()));
00349 }
00350
00351
00352 KSubscription::~KSubscription()
00353 {
00354 }
00355
00356
00357 void KSubscription::setStartItem( const KGroupInfo &info )
00358 {
00359 QListViewItemIterator it(groupView);
00360
00361 for ( ; it.current(); ++it)
00362 {
00363 if (static_cast<GroupItem*>(it.current())->info() == info)
00364 {
00365 it.current()->setSelected(true);
00366 it.current()->setOpen(true);
00367 }
00368 }
00369 }
00370
00371
00372 void KSubscription::removeListItem( QListView *view, const KGroupInfo &gi )
00373 {
00374 if(!view) return;
00375 QListViewItemIterator it(view);
00376
00377 for ( ; it.current(); ++it)
00378 {
00379 if (static_cast<GroupItem*>(it.current())->info() == gi)
00380 {
00381 delete it.current();
00382 break;
00383 }
00384 }
00385 if (view == groupView)
00386 emit listChanged();
00387 }
00388
00389
00390 QListViewItem* KSubscription::getListItem( QListView *view, const KGroupInfo &gi )
00391 {
00392 if(!view) return 0;
00393 QListViewItemIterator it(view);
00394
00395 for ( ; it.current(); ++it)
00396 {
00397 if (static_cast<GroupItem*>(it.current())->info() == gi)
00398 return (it.current());
00399 }
00400 return 0;
00401 }
00402
00403
00404 bool KSubscription::itemInListView( QListView *view, const KGroupInfo &gi )
00405 {
00406 if(!view) return false;
00407 QListViewItemIterator it(view);
00408
00409 for ( ; it.current(); ++it)
00410 if (static_cast<GroupItem*>(it.current())->info() == gi)
00411 return true;
00412
00413 return false;
00414 }
00415
00416
00417 void KSubscription::setDirectionButton1( Direction dir )
00418 {
00419 mDirButton1 = dir;
00420 if (dir == Left)
00421 arrowBtn1->setIconSet(pmLeft);
00422 else
00423 arrowBtn1->setIconSet(pmRight);
00424 }
00425
00426
00427 void KSubscription::setDirectionButton2( Direction dir )
00428 {
00429 mDirButton2 = dir;
00430 if (dir == Left)
00431 arrowBtn2->setIconSet(pmLeft);
00432 else
00433 arrowBtn2->setIconSet(pmRight);
00434 }
00435
00436
00437 void KSubscription::changeItemState( GroupItem* item, bool on )
00438 {
00439
00440 if (!item->isCheckItem()) return;
00441
00442
00443 if (mLoading) return;
00444 if (on)
00445 {
00446 if (!itemInListView(unsubView, item->info()))
00447 {
00448 QListViewItem *p = item->parent();
00449 while (p)
00450 {
00451
00452 GroupItem* pi = static_cast<GroupItem*>(p);
00453 if (pi->isCheckItem() && !pi->isOn())
00454 {
00455 pi->setIgnoreStateChange(true);
00456 pi->setOn(true);
00457 pi->setIgnoreStateChange(false);
00458 new GroupItem(subView, pi->info(), this);
00459 }
00460 p = p->parent();
00461 }
00462 new GroupItem(subView, item->info(), this);
00463 }
00464
00465 removeListItem(unsubView, item->info());
00466 }
00467 else {
00468 if (!itemInListView(subView, item->info()))
00469 {
00470 new GroupItem(unsubView, item->info(), this);
00471 }
00472
00473 removeListItem(subView, item->info());
00474 }
00475
00476 slotChangeButtonState(item);
00477 }
00478
00479
00480 void KSubscription::filterChanged( QListViewItem* item, const QString & text )
00481 {
00482 if ( !item && groupView )
00483 item = groupView->firstChild();
00484 if ( !item )
00485 return;
00486
00487 do
00488 {
00489 if ( item->firstChild() )
00490 filterChanged(item->firstChild(), text);
00491
00492 GroupItem* gr = static_cast<GroupItem*>(item);
00493 if (subCB->isChecked() || newCB->isChecked() || !text.isEmpty() ||
00494 noTreeCB->isChecked())
00495 {
00496
00497 if ( subCB->isChecked() &&
00498 (!gr->isCheckItem() ||
00499 (gr->isCheckItem() && !gr->info().subscribed)) )
00500 {
00501
00502 gr->setVisible(false);
00503 continue;
00504 }
00505 if ( newCB->isChecked() &&
00506 (!gr->isCheckItem() ||
00507 (gr->isCheckItem() && !gr->info().newGroup)) )
00508 {
00509
00510 gr->setVisible(false);
00511 continue;
00512 }
00513 if ( !text.isEmpty() &&
00514 gr->text(0).find(text, 0, false) == -1)
00515 {
00516
00517 gr->setVisible(false);
00518 continue;
00519 }
00520 if ( noTreeCB->isChecked() &&
00521 !gr->isCheckItem() )
00522 {
00523
00524 gr->setVisible(false);
00525 continue;
00526 }
00527
00528 gr->setVisible(true);
00529
00530 } else {
00531 gr->setVisible(true);
00532 }
00533
00534 } while ((item = item->nextSibling()));
00535
00536 }
00537
00538
00539 uint KSubscription::activeItemCount()
00540 {
00541 QListViewItemIterator it(groupView);
00542
00543 uint count = 0;
00544 for ( ; it.current(); ++it)
00545 {
00546 if (static_cast<GroupItem*>(it.current())->isCheckItem() &&
00547 it.current()->isVisible() && it.current()->isEnabled())
00548 count++;
00549 }
00550
00551 return count;
00552 }
00553
00554
00555 void KSubscription::restoreOriginalParent()
00556 {
00557 QPtrList<QListViewItem> move;
00558 QListViewItemIterator it(groupView);
00559 for ( ; it.current(); ++it)
00560 {
00561 QListViewItem* origParent = static_cast<GroupItem*>(it.current())->
00562 originalParent();
00563 if (origParent && origParent != it.current()->parent())
00564 {
00565
00566 move.append(it.current());
00567 }
00568 }
00569 QPtrListIterator<QListViewItem> it2( move );
00570 for ( ; it2.current(); ++it2)
00571 {
00572
00573 QListViewItem* origParent = static_cast<GroupItem*>(it2.current())->
00574 originalParent();
00575 groupView->takeItem(it2.current());
00576 origParent->insertItem(it2.current());
00577 }
00578 }
00579
00580
00581 void KSubscription::saveOpenStates()
00582 {
00583 QListViewItemIterator it(groupView);
00584
00585 for ( ; it.current(); ++it)
00586 {
00587 static_cast<GroupItem*>(it.current())->setLastOpenState(
00588 it.current()->isOpen() );
00589 }
00590 }
00591
00592
00593 void KSubscription::restoreOpenStates()
00594 {
00595 QListViewItemIterator it(groupView);
00596
00597 for ( ; it.current(); ++it)
00598 {
00599 it.current()->setOpen(
00600 static_cast<GroupItem*>(it.current())->lastOpenState() );
00601 }
00602 }
00603
00604
00605 void KSubscription::slotLoadingComplete()
00606 {
00607 mLoading = false;
00608
00609 enableButton(User1, true);
00610 enableButton(User2, true);
00611 newCB->setEnabled(true);
00612 noTreeCB->setEnabled(true);
00613 subCB->setEnabled(true);
00614
00615
00616 QListViewItemIterator it(groupView);
00617 for ( ; it.current(); ++it)
00618 {
00619 static_cast<GroupItem*>(it.current())->
00620 setOriginalParent( it.current()->parent() );
00621 }
00622
00623 emit listChanged();
00624 }
00625
00626
00627 void KSubscription::slotChangeButtonState( QListViewItem *item )
00628 {
00629 if (!item ||
00630 (item->listView() == groupView &&
00631 !static_cast<GroupItem*>(item)->isCheckItem()))
00632 {
00633
00634 arrowBtn1->setEnabled(false);
00635 arrowBtn2->setEnabled(false);
00636 return;
00637 }
00638
00639 QListView* currentView = item->listView();
00640 if (currentView == groupView)
00641 {
00642 setDirectionButton1(Right);
00643 setDirectionButton2(Right);
00644 if (static_cast<GroupItem*>(item)->isOn())
00645 {
00646
00647 arrowBtn1->setEnabled(false);
00648 arrowBtn2->setEnabled(true);
00649 } else {
00650
00651 arrowBtn1->setEnabled(true);
00652 arrowBtn2->setEnabled(false);
00653 }
00654 } else if (currentView == subView)
00655 {
00656
00657 setDirectionButton1(Left);
00658
00659 arrowBtn1->setEnabled(true);
00660 arrowBtn2->setEnabled(false);
00661 } else if (currentView == unsubView)
00662 {
00663
00664 setDirectionButton2(Left);
00665
00666 arrowBtn1->setEnabled(false);
00667 arrowBtn2->setEnabled(true);
00668 }
00669 }
00670
00671
00672 void KSubscription::slotButton1()
00673 {
00674 if (mDirButton1 == Right)
00675 {
00676 if (groupView->currentItem() &&
00677 static_cast<GroupItem*>(groupView->currentItem())->isCheckItem())
00678 {
00679
00680 GroupItem* item = static_cast<GroupItem*>(groupView->currentItem());
00681 item->setOn(true);
00682 }
00683 }
00684 else {
00685 if (subView->currentItem())
00686 {
00687 GroupItem* item = static_cast<GroupItem*>(subView->currentItem());
00688
00689 QListViewItem* listitem = getListItem(groupView, item->info());
00690 if (listitem)
00691 {
00692
00693 GroupItem* chk = static_cast<GroupItem*>(listitem);
00694 chk->setOn(false);
00695 }
00696 }
00697 }
00698 }
00699
00700
00701 void KSubscription::slotButton2()
00702 {
00703 if (mDirButton2 == Right)
00704 {
00705 if (groupView->currentItem() &&
00706 static_cast<GroupItem*>(groupView->currentItem())->isCheckItem())
00707 {
00708
00709 GroupItem* item = static_cast<GroupItem*>(groupView->currentItem());
00710 item->setOn(false);
00711 }
00712 }
00713 else {
00714 if (unsubView->currentItem())
00715 {
00716 GroupItem* item = static_cast<GroupItem*>(unsubView->currentItem());
00717
00718 QListViewItem* listitem = getListItem(groupView, item->info());
00719 if (listitem)
00720 {
00721
00722 GroupItem* chk = static_cast<GroupItem*>(listitem);
00723 chk->setOn(true);
00724 }
00725 }
00726 }
00727 }
00728
00729
00730 void KSubscription::slotCBToggled()
00731 {
00732 if (!noTreeCB->isChecked() && !newCB->isChecked() && !subCB->isChecked())
00733 {
00734 restoreOriginalParent();
00735 }
00736
00737 filterChanged(groupView->firstChild());
00738 emit listChanged();
00739 }
00740
00741
00742 void KSubscription::slotFilterTextChanged( const QString & text )
00743 {
00744
00745 if (mLastText.isEmpty())
00746 saveOpenStates();
00747
00748 if (!mLastText.isEmpty() && text.length() < mLastText.length())
00749 {
00750
00751 restoreOriginalParent();
00752 QListViewItemIterator it(groupView);
00753 for ( ; it.current(); ++it)
00754 {
00755 it.current()->setVisible(true);
00756 it.current()->setEnabled(true);
00757 }
00758 }
00759
00760 filterChanged(groupView->firstChild(), text);
00761
00762 if (text.isEmpty())
00763 restoreOpenStates();
00764
00765 emit listChanged();
00766 mLastText = text;
00767 }
00768
00769
00770 void KSubscription::slotUpdateStatusLabel()
00771 {
00772 QString text;
00773 if (mLoading)
00774 text = i18n("Loading... (1 matching)", "Loading... (%n matching)",
00775 activeItemCount());
00776 else
00777 text = i18n("%1: (1 matching)", "%1: (%n matching)", activeItemCount())
00778 .arg(account()->name());
00779
00780 leftLabel->setText(text);
00781 }
00782
00783
00784 void KSubscription::slotLoadFolders()
00785 {
00786 enableButton(User1, false);
00787 mLoading = true;
00788 subView->clear();
00789 unsubView->clear();
00790 groupView->clear();
00791 }
00792
00793 #include "ksubscription.moc"