kplato

kptaccountspanel.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Dag Andersen <danders@get2net.dk>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation;
00007    version 2 of the License.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kptaccountspanel.h"
00021 #include "kptaccount.h"
00022 #include "kptcommand.h"
00023 #include "kptproject.h"
00024 
00025 #include <qcombobox.h>
00026 #include <qheader.h>
00027 #include <qlistview.h>
00028 #include <qpushbutton.h>
00029 #include <qstring.h>
00030 #include <qstringlist.h>
00031 
00032 #include <klistview.h>
00033 #include <klocale.h>
00034 
00035 #include <kdebug.h>
00036 
00037 namespace KPlato
00038 {
00039 
00040 class AccountItem : public KListViewItem {
00041 public:
00042     AccountItem(AccountsPanel &pan, QListView *parent)
00043     : KListViewItem(parent), account(0), panel(pan)
00044     { init(); }
00045     AccountItem(AccountsPanel &pan, QListViewItem *parent)
00046     : KListViewItem(parent), account(0), panel(pan)
00047     { init(); }
00048     AccountItem(AccountsPanel &pan, QListView *parent, QString label1, QString label2 = QString::null)
00049     : KListViewItem(parent, label1, label2), account(0), panel(pan)
00050     { init(); }
00051     AccountItem(AccountsPanel &pan, QListViewItem *parent, QString label1, QString label2 = QString::null)
00052     : KListViewItem(parent, label1, label2), account(0), panel(pan)
00053     { init(); }
00054     AccountItem(AccountsPanel &pan, QListView *parent, QListViewItem *after)
00055     : KListViewItem(parent, after), account(0), panel(pan)
00056     { init(); }
00057     AccountItem(AccountsPanel &pan, QListViewItem *parent, QListViewItem *after)
00058     : KListViewItem(parent, after), account(0), panel(pan)
00059     { init(); }
00060 
00061     Account *account;
00062     bool isDefault;
00063 
00064     QString oldText;
00065     AccountsPanel &panel;
00066 protected:
00067     virtual void cancelRename(int col) {
00068         //kdDebug()<<k_funcinfo<<endl;
00069         if ((col == 0 && oldText.isEmpty()) ||
00070             (!panel.isUnique(this))) {
00071             return;
00072         }
00073         panel.renameStopped(this);
00074         QListViewItem::cancelRename(col);
00075         setRenameEnabled(col, false);
00076     }
00077 private:
00078     void init() {
00079         setRenameEnabled(0, false);  
00080         setRenameEnabled(1, false);
00081         setOpen(true);
00082         isDefault = false;
00083     
00084     }
00085 };
00086 
00087 AccountsPanel::AccountsPanel(Accounts &acc, QWidget *p, const char *n)
00088     : AccountsPanelBase(p, n),
00089       m_accounts(acc),
00090       m_currentIndex(0),
00091       m_renameItem(0)
00092 {
00093 
00094     accountList->setRootIsDecorated(true);
00095     accountList->header()->setStretchEnabled(true, 1);
00096     accountList->setItemMargin(2);
00097     accountList->setDefaultRenameAction(QListView::Accept);
00098     addItems(accountList, acc);
00099 
00100     slotSelectionChanged();
00101     
00102     connect(accountList, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
00103     connect(accountList, SIGNAL(itemRenamed(QListViewItem*, int)), SLOT(slotItemRenamed(QListViewItem*, int)));
00104     connect(accountList, SIGNAL(doubleClicked(QListViewItem*, const QPoint &, int)), SLOT(slotListDoubleClicked(QListViewItem*, const QPoint &, int)));
00105     
00106     connect(removeBtn, SIGNAL(clicked()), SLOT(slotRemoveBtn()));
00107     connect(newBtn, SIGNAL(clicked()), SLOT(slotNewBtn()));
00108     connect(subBtn, SIGNAL(clicked()), SLOT(slotSubBtn()));
00109 
00110     connect(accountsComboBox, SIGNAL(activated(int)), SLOT(slotActivated(int)));
00111     
00112     // Internal hacks, to get renaming to behave along with unique names
00113     // Uses signals to not get in the way of QListView
00114     connect(this, SIGNAL(renameStarted(QListViewItem*, int)), SLOT(slotRenameStarted(QListViewItem*, int)));
00115     connect(this, SIGNAL(startRename(QListViewItem*, int)), SLOT(slotStartRename(QListViewItem*, int)));
00116     connect(this, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
00117 }
00118     
00119 void AccountsPanel::addItems(QListView *lv, Accounts &acc) {
00120     //kdDebug()<<k_funcinfo<<"No of accs: "<<acc.accountList().count()<<endl;
00121     AccountListIterator it = acc.accountList();
00122     for (; it.current(); ++it) {
00123         QString n = it.current()->name();
00124         QString d = it.current()->description();
00125         AccountItem *item = new AccountItem(*this, lv, n, d);
00126         item->account = it.current();
00127         item->isDefault = (it.current() == acc.defaultAccount());
00128         if (it.current()->isElement()) {
00129             addElement(item);
00130         }
00131         addItems(item, it.current());
00132     }
00133 }
00134 
00135 void AccountsPanel::addItems(QListViewItem *item, Account *acc) {
00136     AccountListIterator it = acc->accountList();
00137     for (; it.current(); ++it) {
00138         QString n = it.current()->name();
00139         QString d = it.current()->description();
00140         AccountItem *ai = new AccountItem(*this, item, n, d);
00141         ai->account = it.current();
00142         ai->isDefault = (it.current() == acc->list()->defaultAccount());
00143         if (it.current()->isElement()) {
00144             addElement(ai);
00145         }
00146         addItems(ai, it.current());
00147     }
00148 }
00149 
00150 void AccountsPanel::addElement(const QListViewItem *item) {
00151     if (item->parent()) {
00152         removeElement(item->parent());
00153     }
00154     m_elements.replace(item->text(0), item);
00155     //kdDebug()<<k_funcinfo<<item->text(0)<<endl;
00156     refreshDefaultAccount();
00157 }
00158 
00159 void AccountsPanel::removeElement(QListViewItem *item) {
00160     static_cast<AccountItem*>(item)->isDefault = false;
00161     m_elements.remove(item->text(0));
00162     refreshDefaultAccount();
00163 }
00164 
00165 void AccountsPanel::refreshDefaultAccount() {
00166     accountsComboBox->clear();
00167     m_currentIndex = 0;
00168     accountsComboBox->insertItem(i18n("None"));
00169     QDictIterator<QListViewItem> it(m_elements);
00170     for(int i=1; it.current(); ++it, ++i) {
00171         accountsComboBox->insertItem(it.currentKey());
00172         if (static_cast<AccountItem*>(it.current())->isDefault) {
00173             m_currentIndex = i;
00174             accountsComboBox->setCurrentItem(i);
00175             //kdDebug()<<k_funcinfo<<"Default="<<it.current()->text(0)<<endl;
00176         }
00177     }
00178     //kdDebug()<<k_funcinfo<<"size="<<accountsComboBox->count()<<endl;
00179 }
00180 void AccountsPanel::slotActivated(int index) {
00181     //kdDebug()<<k_funcinfo<<index<<endl;
00182     if (m_currentIndex >= (int)m_elements.count()) {
00183         kdError()<<k_funcinfo<<"currentIndex ("<<m_currentIndex<<") out of range ("<<m_elements.count()<<")"<<endl;
00184     } else if (m_currentIndex > 0) {
00185         AccountItem *i = static_cast<AccountItem*>(m_elements[accountsComboBox->text(m_currentIndex)]);
00186         if (i) 
00187             i->isDefault = false;
00188     }
00189     m_currentIndex = 0;
00190     if (index < (int)m_elements.size()) {
00191         AccountItem *i = static_cast<AccountItem*>(m_elements[accountsComboBox->currentText()]);
00192         if (i) {
00193             i->isDefault = true;
00194             m_currentIndex = index;
00195             //kdDebug()<<k_funcinfo<<"currentIndex="<<m_currentIndex<<", "<<m_elements[accountsComboBox->currentText()]->text(0)<<endl;
00196         }
00197     }
00198     slotChanged();
00199 }
00200 
00201 void AccountsPanel::slotChanged() {
00202     emit changed(true);
00203 }
00204 
00205 void AccountsPanel::slotSelectionChanged() {
00206     //kdDebug()<<k_funcinfo<<endl;
00207     if (m_renameItem) {
00208         removeBtn->setEnabled(false);
00209         newBtn->setEnabled(false);
00210         subBtn->setEnabled(false);
00211         accountList->setSelected(m_renameItem, true);
00212         return;
00213     }
00214     if (accountList->childCount() == 0) {
00215         removeBtn->setEnabled(false);
00216         newBtn->setEnabled(true);
00217         subBtn->setEnabled(false);
00218         return;
00219     }
00220     QListViewItem *i = accountList->selectedItem();
00221     removeBtn->setEnabled((bool)i);
00222     newBtn->setEnabled(true);
00223     subBtn->setEnabled((bool)i);
00224 }
00225 
00226 void AccountsPanel::slotItemRenamed(QListViewItem *item, int col) {
00227     //kdDebug()<<k_funcinfo<<item->text(0)<<endl;
00228     item->setRenameEnabled(col, false);
00229     m_renameItem = 0;
00230     if (col != 0) {
00231         renameStopped(item);
00232         slotChanged();
00233         return;
00234     }
00235     if (item->text(0).isEmpty()) {
00236         item->setText(0, static_cast<AccountItem*>(item)->oldText); // keep the old name
00237     }
00238     if (item->text(0).isEmpty()) {
00239         // Not allowed
00240         //kdDebug()<<k_funcinfo<<"name empty"<<endl;
00241         emit startRename(item, 0);
00242         return;
00243     }
00244     if (!isUnique(item)) {
00245         // name must be unique
00246         emit startRename(item, 0);
00247         return;
00248     }
00249     addElement(item);
00250     removeBtn->setEnabled(accountList->selectedItem());
00251     newBtn->setEnabled(accountList->selectedItem());
00252     subBtn->setEnabled(accountList->selectedItem());
00253     renameStopped(item);
00254     slotChanged();
00255 }
00256 
00257 bool AccountsPanel::isUnique(QListViewItem *item) {
00258     QListViewItemIterator it(accountList);
00259     for (; it.current(); ++it) {
00260         if (it.current() != item && it.current()->text(0) == item->text(0)) {
00261             return false;
00262         }
00263     }
00264     return true;
00265 }
00266 
00267 void AccountsPanel::slotRemoveBtn() {
00268     slotRemoveItem(accountList->selectedItem());
00269     slotChanged();
00270 }
00271 
00272 void AccountsPanel::slotNewBtn() {
00273     //kdDebug()<<k_funcinfo<<endl;
00274     QListViewItem *item = accountList->selectedItem();
00275     if (item && item->text(0).isEmpty()) {
00276         return;
00277     }
00278     QListViewItem *n;
00279     if (item) {
00280         if (item->parent()) {
00281             n = new AccountItem(*this, item->parent(), item);
00282         } else {
00283             n = new AccountItem(*this, accountList, item);
00284         }
00285     } else {
00286         n = new AccountItem(*this, accountList);
00287     }
00288     slotListDoubleClicked(n, QPoint(), 0);
00289 }
00290 
00291 void AccountsPanel::slotSubBtn() {
00292     //kdDebug()<<k_funcinfo<<endl;
00293     QListViewItem *item = accountList->selectedItem();
00294     if (item && item->text(0).isEmpty()) {
00295         return;
00296     }
00297     QListViewItem *n;
00298     if (item) {
00299         n = new AccountItem(*this, item);
00300     } else {
00301         n = new AccountItem(*this, accountList);
00302     }
00303     slotListDoubleClicked(n, QPoint(), 0);
00304 }
00305 
00306 KCommand *AccountsPanel::buildCommand(Part *part) {
00307     KMacroCommand *cmd = 0;
00308     // First remove
00309     QPtrListIterator<QListViewItem> rit = m_removedItems;
00310     for (;rit.current(); ++rit) {
00311         AccountItem *item = static_cast<AccountItem*>(rit.current());
00312         //kdDebug()<<k_funcinfo<<"Removed item"<<endl;
00313         if (!cmd) cmd = new KMacroCommand(i18n("Modify Accounts"));
00314         cmd->addCommand(new RemoveAccountCmd(part, part->getProject(), item->account));
00315     }
00316     m_removedItems.setAutoDelete(true);
00317     // Then add/modify
00318     KCommand *c = save(part, part->getProject());
00319     if (c) {
00320         if (!cmd) cmd = new KMacroCommand(i18n("Modify Accounts"));
00321         cmd->addCommand(c);
00322     }
00323     return cmd;
00324 }
00325 
00326 KCommand *AccountsPanel::save(Part *part, Project &project) {
00327     KMacroCommand *cmd=0;
00328     QListViewItem *myChild = accountList->firstChild();
00329     for (; myChild; myChild = myChild->nextSibling()) {
00330         KCommand *c = save(part, project, myChild);
00331         if (c) {
00332             if (!cmd) cmd = new KMacroCommand("");
00333             cmd->addCommand(c);
00334         }
00335     }
00336     return cmd;
00337 }
00338 
00339 KCommand *AccountsPanel::save(Part *part, Project &project, QListViewItem *i) {
00340     KMacroCommand *cmd=0;
00341     AccountItem *item = static_cast<AccountItem*>(i);
00342     if (item->account == 0) {
00343         if (!item->text(0).isEmpty()) {
00344             //kdDebug()<<k_funcinfo<<"New account: "<<item->text(0)<<endl;
00345             if (!cmd) cmd = new KMacroCommand("");
00346             item->account = new Account(item->text(0), item->text(1));
00347             if (item->parent()) {
00348                 //kdDebug()<<k_funcinfo<<"New account: "<<item->text(0)<<endl;
00349                 cmd->addCommand(new AddAccountCmd(part, project, item->account, item->parent()->text(0)));
00350             } else {
00351                 cmd->addCommand(new AddAccountCmd(part, project, item->account));
00352             }
00353         }
00354     } else {
00355         if (!item->text(0).isEmpty() && (item->text(0) != item->account->name())) {
00356             if (!cmd) cmd = new KMacroCommand("");
00357             //kdDebug()<<k_funcinfo<<"Renamed: "<<item->account->name()<<" to "<<item->text(0)<<endl;
00358             cmd->addCommand(new RenameAccountCmd(part, item->account, item->text(0)));
00359         }
00360         if (item->text(1) != item->account->description()) {
00361             if (!cmd) cmd = new KMacroCommand("");
00362             //kdDebug()<<k_funcinfo<<"New description: "<<item->account->description()<<" to "<<item->text(1)<<endl;
00363             cmd->addCommand(new ModifyAccountDescriptionCmd(part, item->account, item->text(1)));
00364         }
00365     }
00366     QListViewItem *myChild = item->firstChild();
00367     for (; myChild; myChild = myChild->nextSibling()) {
00368         KCommand *c = save(part, project, myChild);
00369         if (c) {
00370             if (!cmd) cmd = new KMacroCommand("");
00371             cmd->addCommand(c);
00372         }
00373     }
00374     AccountItem *ai = static_cast<AccountItem*>(m_elements[accountsComboBox->currentText()]);
00375     Account *newDefaultAccount = 0;
00376     if (ai) {
00377         newDefaultAccount = ai->account;
00378     }
00379     if (m_oldDefaultAccount != newDefaultAccount) {
00380         if (!cmd) cmd = new KMacroCommand("");
00381         cmd->addCommand(new ModifyDefaultAccountCmd(part, m_accounts, m_oldDefaultAccount, newDefaultAccount));
00382     }
00383     return cmd;
00384 }
00385 
00386 void AccountsPanel::slotListDoubleClicked(QListViewItem* item, const QPoint&, int col) {
00387     //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
00388     if (m_renameItem)
00389         return;
00390     slotStartRename(item, col);
00391 }
00392 
00393 void AccountsPanel::slotRenameStarted(QListViewItem */*item*/, int /*col*/) {
00394     //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
00395     if (accountList->isRenaming()) {
00396         removeBtn->setEnabled(false);
00397         newBtn->setEnabled(false);
00398         subBtn->setEnabled(false);
00399     }
00400 }
00401 
00402 void AccountsPanel::slotStartRename(QListViewItem *item, int col) {
00403     //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
00404     static_cast<AccountItem*>(item)->oldText = item->text(col);
00405     item->setRenameEnabled(col, true);
00406     item->startRename(col);
00407     m_renameItem = item;
00408     
00409     emit renameStarted(item, col);
00410 }
00411 
00412 void AccountsPanel::slotRemoveItem(QListViewItem *i) {
00413     AccountItem *item = static_cast<AccountItem*>(i);
00414     if (item == 0)
00415         return;
00416     //kdDebug()<<k_funcinfo<<item->text(0)<<endl;
00417     removeElement(item);
00418     QListViewItem *p = item->parent();
00419     if (p) {
00420         p->takeItem(item);
00421         if (item->account) {
00422             m_removedItems.append(item);
00423         } else {
00424             delete item;
00425         }
00426         if (p->childCount() == 0) {
00427             addElement(p);
00428         }
00429     } else {
00430         accountList->takeItem(item);
00431         if (item->account) {
00432             m_removedItems.append(item);
00433         } else {
00434             delete item;
00435         }
00436     }
00437 }
00438 
00439 // We don't get notified when rename is cancelled, this is called from the item
00440 void AccountsPanel::renameStopped(QListViewItem */*item*/) {
00441     //kdDebug()<<k_funcinfo<<endl;
00442     m_renameItem = 0;
00443     emit selectionChanged();
00444 }
00445 
00446 void AccountsPanel::slotOk() {
00447 
00448 }
00449 
00450 } //namespace KPlato
00451 
00452 #include "kptaccountspanel.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys