📄 addressbook.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define QTOPIA_INTERNAL_FD#define QTOPIA_INTERNAL_FILEOPERATIONS#include "abeditor.h"#include "ablabel.h"#include <qtopia/pim/private/abtable_p.h>#include <qtopia/pim/private/contactfieldselector_p.h>#include "addressbook.h"#include <qtopia/qpeapplication.h>#include <qtopia/config.h>#include <qtopia/qdawg.h>#ifdef QTOPIA_PHONE#include <qtopia/speeddial.h>#endif#include <qtopia/pim/contact.h>#include <qtopia/global.h>#include <qtopia/resource.h>#include <qtopia/ir.h>#include <qtopia/qpemessagebox.h>#include <qtopia/categoryselect.h>#include <qtopia/services.h>#include <qtopia/categories.h>#include <qtopia/applnk.h>#include <qtopia/image.h>#ifdef Q_WS_QWS#include <qtopia/qcopenvelope_qws.h>#endif#include <qtopia/qpemenubar.h>#include <qtopia/qpetoolbar.h>#ifdef QTOPIA_PHONE# include <qtopia/categorydialog.h># include <qtopia/contextbar.h>#endif#ifdef QTOPIA_DATA_LINKING#include <qtopia/qdl.h>#endif#ifdef QTOPIA_PHONE#include <qtopia/phone/phone.h>#include <qtopia/phone/phonebook.h>#endif#include <qdialog.h>#include <qdir.h>#include <qfile.h>#include <qimage.h>#include <qlayout.h>#include <qpixmap.h>#include <qbuttongroup.h>#include <qradiobutton.h>#include <qpopupmenu.h>#include <qstringlist.h>#include <qtoolbutton.h>#include <qwhatsthis.h>#include <qvbox.h>#include <qlabel.h>#include <qlineedit.h>#include <qwhatsthis.h>#include <qcstring.h>#include <qmessagebox.h>#include <qpixmapcache.h>#include <stdlib.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#ifndef Q_OS_WIN32# include <unistd.h>#endif#include <qdatetime.h>static bool constructorDone = FALSE;static const struct { const char* desc; const char* fmt;} fileas_opt[] = { { QT_TRANSLATE_NOOP("AbSettings","First Last or Company"), "FirstName LastName | Company" }, // No tr { QT_TRANSLATE_NOOP("AbSettings","Last, First or Company"), "LastName , _ FirstName | Company" }, // No tr { 0, 0 }};class NameLearner { // Utility class for efficiently putting names from contacts into word lists.public: NameLearner() { } NameLearner(const PimContact &cnt) { learn(cnt); } ~NameLearner() { const QDawg& dawg = Global::dawg("addressbook-names"); const QDawg& gldawg = Global::dawg("local"); QStringList aw; QStringList glaw; for (QStringList::ConstIterator it=nw.begin(); it!=nw.end(); ++it) { if ( isLetters(*it) ) { if ( !dawg.contains(*it) ) aw.append(*it); if ( !gldawg.contains(*it) ) glaw.append(*it); } else { // Maybe just spaces (eg. multi-word names) QStringList ws = QStringList::split(QChar(' '),*it); for (QStringList::ConstIterator lit=ws.begin(); lit!=ws.end(); ++lit) { if ( isLetters(*lit) && !dawg.contains(*lit) ) aw.append(*lit); if ( isLetters(*lit) && !gldawg.contains(*lit) ) glaw.append(*lit); } } } Global::addWords("addressbook-names",aw); Global::addWords(glaw); } void learn(const PimContact &cnt) { static PimContact::ContactFields names[] = { PimContact::FirstName, PimContact::MiddleName, PimContact::LastName, PimContact::Company, PimContact::Spouse, PimContact::Assistant, PimContact::Manager }; for (uint i=0; i<sizeof(names)/sizeof(names[0]); i++) { QString n = cnt.field(names[i]); if ( !n.isEmpty() && !map.find(n) ) { nw.append(n); map.insert(n,(void*)1); } } }private: static bool isLetters(const QString& w) { for (int i=0; i<(int)w.length(); ++i) { if ( !w[i].isLetter() || w[i].unicode() >= 4096/*QDawg limit*/ ) return FALSE; } return TRUE; } QStringList nw; QDict<void> map;};AbSettings::AbSettings(QWidget *parent, const char *name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl){ setName("settings"); QGridLayout *grid = new QGridLayout(this);#ifdef QTOPIA_PHONE Config cfg("Contacts"); cfg.setGroup("formatting"); QString curfmt = cfg.readEntry("NameFormat"); setCaption(tr("Settings")); bg = new QButtonGroup(1,Horizontal,tr("File As"),this); bg->layout()->setMargin(4); for (int i=0; fileas_opt[i].desc; ++i) { QRadioButton *rb = new QRadioButton(tr(fileas_opt[i].desc),bg); if ( fileas_opt[i].fmt == curfmt || i==0 && curfmt.isEmpty() ) rb->setChecked(TRUE); } grid->addWidget(bg, 0, 0);#else setCaption(tr("Configure columns to display")); map = new FieldMap(this); grid->addWidget(map, 0, 0);#endif}AbSettings::~AbSettings(){}#ifdef QTOPIA_PHONEvoid AbSettings::saveFormat(){ Config cfg("Contacts"); cfg.setGroup("formatting"); cfg.writeEntry("NameFormat", fileas_opt[bg->id(bg->selected())].fmt);}#elsevoid AbSettings::setCurrentFields(const QValueList<int> &f){ QMap<int,QString> m = PimContact::trFieldsMap(); m.remove( PimRecord::Categories ); m.remove( PimContact::LastNamePronunciation ); m.remove( PimContact::FirstNamePronunciation ); m.remove( PimContact::CompanyPronunciation ); m.insert( AbTable::FREQ_CONTACT_FIELD, tr("Contact") ); map->setFields( m, f);}#endifclass LoadIndicator : public QLabel{public: LoadIndicator( QWidget *parent = 0, const char *name = 0, WFlags fl = WStyle_Customize | WPaintUnclipped | WStyle_Tool | WType_TopLevel | WStyle_StaysOnTop ); void center(); void bottom();protected: void showEvent( QShowEvent *e ); void paintEvent( QPaintEvent *e );};AddressbookWindow::AddressbookWindow( QWidget *parent, const char *name, WFlags f ) : QMainWindow( parent, name, f ), allowCloseEvent( FALSE ), mResetKeyChars( FALSE ), mCloseAfterView( FALSE ), contacts( ContactIO::ReadWrite ), abEditor(0), mView(0), searchBar(0), actionFind(0), actionPersonal(0), actionSetPersonal(0),#ifdef QTOPIA_PHONE mFindLE(0),#endif syncing(FALSE), showingPersonal(FALSE){#ifdef QTOPIA_PHONE mSimIndicator = 0; mGotSimEntries = FALSE; mToggleInternal = FALSE;#endif #ifdef Q_WS_QWS beamfile = Global::tempDir() + "obex"; QDir d; d.mkdir(beamfile); beamfile += "/contact.vcf";#endif setCaption( tr("Contacts") ); setIcon( Resource::loadPixmap( "AddressBook" ) ); setToolBarsMovable( FALSE ); setBackgroundMode( PaletteButton ); // Create Views listView = new QVBox( this );#ifdef QTOPIA_PHONE if( Global::mousePreferred() ) mFindLE = new QLineEdit( listView );#endif abList = new AbTable( &contacts, listView );#ifdef QTOPIA_PHONE if( Global::mousePreferred() ) { connect( mFindLE, SIGNAL(textChanged(const QString&)), this, SLOT(search(const QString&)) ); abList->setFocusPolicy( NoFocus ); listView->setFocusPolicy( NoFocus ); mFindLE->installEventFilter( this ); QPEApplication::setInputMethodHint(mFindLE,"addressbook-names"); }#endif actionNew = new QAction( tr( "New" ), Resource::loadIconSet( "new" ), QString::null, 0, this, 0 ); connect( actionNew, SIGNAL( activated() ), this, SLOT( slotListNew() ) ); actionNew->setWhatsThis( tr("Enter a new contact.") ); actionEdit = new QAction( tr( "Edit" ), Resource::loadIconSet( "edit" ), QString::null, 0, this, 0 ); actionEdit->setWhatsThis( tr("Edit the highlighted contact.") ); connect( actionEdit, SIGNAL( activated() ), this, SLOT( slotViewEdit() ) ); actionEdit->setEnabled(FALSE); actionTrash = new QAction( tr( "Delete" ), Resource::loadIconSet( "trash" ), QString::null, 0, this, 0 ); actionTrash->setWhatsThis( tr("Delete the selected contacts.") ); connect( actionTrash, SIGNAL( activated() ), this, SLOT( slotListDelete() ) ); actionTrash->setEnabled(FALSE); actionFind = new QAction( tr( "Find" ), Resource::loadIconSet( "find" ), QString::null, 0, this, 0 ); actionFind->setWhatsThis( tr("Find a contact.") ); actionFind->setToggleAction( TRUE ); connect( actionFind, SIGNAL(toggled(bool)), this, SLOT(slotFind(bool)) ); QAction *actionShowBCard; actionShowBCard = new QAction( tr("Show Business Card"), QString::null, 0, 0, 0, FALSE ); actionPersonal = actionShowBCard; actionShowBCard->setWhatsThis( tr("Show your business card entry.") ); connect( actionShowBCard, SIGNAL( activated() ), this, SLOT( slotPersonalView() ) ); QAction *actionSetBCard = new QAction( tr("Set as Business Card"), QString::null, 0, 0, 0, FALSE ); actionSetPersonal = actionSetBCard; actionSetBCard->setWhatsThis( tr("Set current entry as your business card.") ); connect( actionSetBCard, SIGNAL( activated() ), this, SLOT( markCurrentAsPersonal() ) );#ifndef QTOPIA_DESKTOP mSendService = new SendContactService( this ); if( mSendService->serverCount() != 0 ) { actionSend = new QAction( tr("Send..."), Resource::loadIconSet("beam"), QString::null, 0, this, 0 ); actionSend->setWhatsThis( tr("Send the contact to another person") ); connect( actionSend, SIGNAL(activated()), this, SLOT(sendContact()) ); actionSendCat = new QAction( tr("Send All..."), Resource::loadIconSet("beam"), QString::null, 0, this, 0 ); actionSendCat->setWhatsThis( tr("Send the visible contacts to another person") ); connect( actionSendCat, SIGNAL(activated()), this, SLOT(sendContactCat()) ); } else { delete mSendService; mSendService = 0; actionSend = 0; actionSendCat = 0; }#endif actionSettings = new QAction(tr("Settings..."), Resource::loadIconSet("settings"), QString::null, 0, this, 0); connect( actionSettings, SIGNAL(activated()), this, SLOT(configure()));#ifdef AB_PDA //FIXME : temporary duplicated icon from contextbar actionBack = new QAction(tr("Back"),Resource::loadIconSet("addressbook/back"), QString::null, 0, this, 0); connect( actionBack, SIGNAL(activated()), this, SLOT(viewClosed()) );#endif#ifndef QTOPIA_PHONE // Create Toolbars QPEToolBar *bar = new QPEToolBar( this ); bar->setHorizontalStretchable( TRUE ); QPEMenuBar *mbList = new QPEMenuBar( bar ); mbList->setMargin( 0 ); QPopupMenu *edit = new QPopupMenu( this ); mbList->insertItem( tr( "Contact" ), edit ); listTools = new QPEToolBar( this ); actionNew->addTo( edit ); actionNew->addTo( listTools ); actionEdit->addTo( edit ); actionEdit->addTo( listTools ); actionTrash->addTo( edit ); actionTrash->addTo( listTools );#ifndef QTOPIA_DESKTOP if( actionSend ) { actionSend->addTo( edit ); actionSend->addTo( listTools ); actionSendCat->addTo( edit ); }#endif actionFind->addTo( edit ); actionFind->addTo( listTools );#ifdef AB_PDA listTools->addSeparator(); actionBack->addTo( listTools );#endif#else contextMenu = new ContextMenu( this );#ifdef QTOPIA_PHONE if( Global::mousePreferred() ) contextMenu->addTo( mFindLE );#endif actionNew->addTo(contextMenu); actionEdit->addTo(contextMenu); actionTrash->addTo(contextMenu);#ifndef QTOPIA_DESKTOP if( actionSend ) { actionSend->addTo( contextMenu ); actionSendCat->addTo( contextMenu ); }#endif actionSetBCard->addTo(contextMenu); actionSpeedDial = new QAction(tr("Add to Speed Dial..."), Resource::loadIconSet("phone/speeddial"), QString::null, 0, this, 0); connect( actionSpeedDial, SIGNAL(activated()), this, SLOT(addToSpeedDial())); actionSpeedDial->addTo(contextMenu); actionOnSim = new QAction( tr( "Store on SIM" ), QString::null, 0, this, 0 ); actionOnSim->setToggleAction( TRUE ); connect( actionOnSim, SIGNAL(toggled(bool)), this, SLOT(storeOnSim(bool)) ); actionOnSim->addTo( contextMenu ); actionCategory = new QAction(tr("View Category..."), Resource::loadIconSet("viewcategory"), QString::null, 0, this, 0 ); connect( actionCategory, SIGNAL(activated()), this, SLOT(selectCategory())); actionCategory->addTo(contextMenu); actionSettings->addTo(contextMenu); categoryLbl = new QLabel(listView); categoryLbl->hide(); categoryDlg = 0;#endif#ifndef QTOPIA_PHONE edit->insertSeparator(); actionShowBCard->addTo( edit ); actionSetBCard->addTo( edit ); //listTools->addSeparator(); // Filter bar QHBox *hb = new QHBox( listView ); /* QComboBox *contactCombo = new QComboBox( hb ); connect( contactCombo, SIGNAL(activated(int)), this, SLOT(contactFilterSelected(int)) ); contactCombo->insertItem( PimContact::trFieldsMap()[PimContact::BusinessMobile] ); contactMap[0]=PimContact::BusinessMobile; contactCombo->insertItem( PimContact::trFieldsMap()[PimContact::HomeMobile] ); contactMap[1]=PimContact::HomeMobile; contactCombo->insertItem( PimContact::trFieldsMap()[PimContact::BusinessPhone] ); contactMap[2]=PimContact::BusinessPhone; contactCombo->insertItem( PimContact::trFieldsMap()[PimContact::HomePhone] ); contactMap[3]=PimContact::HomePhone; contactCombo->insertItem( PimContact::trFieldsMap()[PimContact::DefaultEmail] ); contactMap[4]=PimContact::DefaultEmail; contactCombo->setSizePolicy( QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred) ); contactCombo->setCurrentItem(0); contactFilterSelected( 0 ); QWhatsThis::add( contactCombo, tr("Show this contact information in the Contact column, if available.") ); */ cats.load(categoryFileName()); catSelect = new CategorySelect( hb ); catSelect->setRemoveCategoryEdit( TRUE ); connect( catSelect, SIGNAL(signalSelected(int)), this, SLOT(slotSetCategory(int)) ); QWhatsThis::add( catSelect, tr("Show contacts in this category.") ); QArray<int> vl( 0 ); catSelect->setCategories( vl, "Address Book", // No tr() tr("Address Book") ); catSelect->setAllCategories( TRUE );#endif abList->setSelectionMode( AbTable::Extended );// abList->setFrameStyle( QFrame::NoFrame ); connect( abList, SIGNAL( clicked() ), this, SLOT( selectClicked() ) ); connect( abList, SIGNAL(currentChanged()), this, SLOT(updateIcons()) ); QWhatsThis::add( abList, tr("List of contacts in the selected category. Click to view detailed information.") ); readConfig(); setCentralWidget( listView );#ifndef QTOPIA_PHONE// slotSetCategory(-2); contacts.setFilter( catSelect->currentCategory() ); setCaption( tr("Contacts") + " - " + categoryLabel( catSelect->currentCategory() ) );#else setCaption( tr("Contacts") );#endif abList->reload(); // force a reload initially constructorDone = TRUE; updateIcons(); connect(qApp, SIGNAL(categoriesChanged()), this, SLOT(catChanged()) ); // This call is to ensure that all records contains only valid categories catChanged(); connect( qApp, SIGNAL(appMessage(const QCString&,const QByteArray&)), this, SLOT(appMessage(const QCString&,const QByteArray&)) ); connect( qApp, SIGNAL(reload()), this, SLOT(reload()) ); connect( qApp, SIGNAL(flush()), this, SLOT(flush()) );#ifdef QTOPIA_PHONE mPhoneLine = new PhoneLine(); connect( mPhoneLine->phoneBook(), SIGNAL(entries(const PhoneLine&,const QString&, const QValueList<PhoneBookEntry>&)), this, SLOT(phonebookChanged(const PhoneLine&,const QString&, const QValueList<PhoneBookEntry>&)) ); connect( mPhoneLine, SIGNAL(queryResult(PhoneLine::QueryType,const QString&)), this, SLOT(setSimFieldLimits(PhoneLine::QueryType,const QString&)) ); mPhoneLine->phoneBook()->getEntries();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -