You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
735 lines
21 KiB
735 lines
21 KiB
/***************************************************************************
|
|
configlist.h - description
|
|
-------------------
|
|
begin : Tue May 9 2000
|
|
copyright : (C) 2000-2001 by Eggert Ehmke
|
|
(C) 2007 by Ulrich Weigelt
|
|
email : eggert.ehmke@berlin.de
|
|
ulrich.weigelt@gmx.de
|
|
|
|
26 Sep 2002 - Allow for columns to be hidden. Allistar Melville
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef CONFIGLIST_H
|
|
#define CONFIGLIST_H
|
|
|
|
//TQt header
|
|
#include <tqptrlist.h>
|
|
#include <tqlistview.h>
|
|
#include <tqobject.h>
|
|
|
|
//KDE headers
|
|
#include <kcombobox.h>
|
|
#include <kprocess.h>
|
|
#include <kdebug.h>
|
|
|
|
//KShowmail headers
|
|
#include "configelem.h"
|
|
#include "constants.h"
|
|
#include "kshowmailview.h"
|
|
#include "types.h"
|
|
#include "encryption.h"
|
|
#include "tdewalletaccess.h"
|
|
#include "filteritem.h"
|
|
#include "headerfilter.h"
|
|
#include "filterlog.h"
|
|
|
|
using namespace Constants;
|
|
using namespace Types;
|
|
using namespace Encryption;
|
|
|
|
class ConfigElem;
|
|
class KshowmailView;
|
|
|
|
/**
|
|
* Contains the application and account settings. The account
|
|
* settings are stored in ConfigElem objects.
|
|
* @author Eggert Ehmke
|
|
* @author Ulrich Weigelt
|
|
*/
|
|
class ConfigList : public TQObject, public TQPtrList<ConfigElem>
|
|
{
|
|
|
|
TQ_OBJECT
|
|
|
|
public:
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
ConfigList ();
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~ConfigList () {};
|
|
|
|
/**
|
|
* Reads the setup from the configuration file (kshowmailrc) and
|
|
* sets the properties.
|
|
* @param view pointer to the account list view
|
|
*/
|
|
void refreshSetup( TDEListView* view );
|
|
|
|
/**
|
|
* Reloads the filter settings
|
|
*/
|
|
void refreshFilterSetup();
|
|
|
|
/**
|
|
* Returns the auto refresh time interval.
|
|
* @return refresh time interval [minutes]
|
|
*/
|
|
int getRefreshTimeInterval() const;
|
|
|
|
/**
|
|
* Sets the auto refresh time interval.
|
|
* @param interval the new time interval [minutes]
|
|
*/
|
|
void setRefreshTimeInterval( unsigned int interval );
|
|
|
|
/**
|
|
* Returns whether auto refresh is on.
|
|
* @return TRUE - auto refresh is on; FALSE - auto refresh is off
|
|
*/
|
|
bool AutoRefreshOn() const;
|
|
|
|
/**
|
|
* Sets whether the user has to confirm a deletion.
|
|
* @param confirm TRUE - user has to confirm; FALSE - the user does not have to confirm
|
|
*/
|
|
void setConfirmDeletion( bool confirm );
|
|
|
|
/**
|
|
* Returns whether the user has to confirm a deletion.
|
|
* @return TRUE - the user has to confirm
|
|
* @return FALSE - the user does not have to confirm
|
|
*/
|
|
bool confirmDeletion();
|
|
|
|
/**
|
|
* Returns whether the user has to confirm window close.
|
|
* @return TRUE - user has to confirm
|
|
* @return FALSE - user does not have to confirm
|
|
*/
|
|
bool confirmClose() const;
|
|
|
|
/**
|
|
* Returns whether the app shall start minimized.
|
|
* @return TRUE - start minimized
|
|
* @return FALSE - don't start minimized
|
|
*/
|
|
bool startMinimized() const;
|
|
|
|
/**
|
|
* Returns whether the close button leaves the application running in tray.
|
|
* @return TRUE - leaves running
|
|
* @return FALSE - app will be closed
|
|
*/
|
|
bool closeToTray() const;
|
|
|
|
/**
|
|
* Returns whether minimizes to the tray rather than to the taskbar.
|
|
* @return TRUE - minimizes to the tray
|
|
* @return FALSE - minimizes to the taskbar
|
|
*/
|
|
bool minimizesToTray() const;
|
|
|
|
/**
|
|
* Returns whether connection errors will be shown during refresh.
|
|
* @return TRUE - show errors
|
|
* @return FALSE - don't show errors
|
|
*/
|
|
bool showConnectionErrors() const;
|
|
|
|
/**
|
|
* Sets whether the mail show dialog has to use HTML.
|
|
* @param allowHTML TRUE - the dialog has to use HTML; FALSE - the dialog must not use HTML
|
|
* @see m_bAllowHTML
|
|
* */
|
|
void setAllowHTML( bool allowHTML );
|
|
|
|
/**
|
|
* Returns whether the mail show dialog has to use HTML.
|
|
* @return TRUE - the dialog has to use HTML
|
|
* @return FALSE - the dialog must not use HTML
|
|
* @see m_bAllowHTML
|
|
*/
|
|
bool allowHTML() const;
|
|
|
|
/**
|
|
* Returns whether there are active accounts.
|
|
* Doesn't set the current account.
|
|
* @return TRUE - Yes, there are active accounts (at least one :o) ); FALSE - no active accounts
|
|
*/
|
|
bool hasActiveAccounts();
|
|
|
|
/**
|
|
* Returns the number of seconds the application will be wait for a pop3 job.
|
|
* @return seconds to timeout
|
|
*/
|
|
uint getTimeoutTime() const;
|
|
|
|
/**
|
|
* Sets the number of seconds the application will be wait for a pop3 job.
|
|
* Minimum time is POP3_MINIMUM_TIMEOUT_TIME seconds.
|
|
* @param time seconds to timeout
|
|
* @see constants.h
|
|
*/
|
|
void setTimeoutTime( uint time );
|
|
|
|
/**
|
|
* Returns the first account, for which an appropriate item is
|
|
* selected in the account list view.
|
|
* @return pointer to the selected account object
|
|
* @return NULL - no account is selected
|
|
*/
|
|
ConfigElem* getSelectedAccount();
|
|
|
|
/**
|
|
* Deletes all selected mails from the servers and the mail lists.
|
|
* This just starts the deletion and returns after then. When all
|
|
* accounts are ready the signal sigDeleteReady will be emitted.
|
|
*/
|
|
void deleteSelectedMails();
|
|
|
|
/**
|
|
* Connects the signals of the accounts with the slots of this
|
|
* class.
|
|
* It is necessary to do this after an account has been appended to the
|
|
* list and it is a good idea to call this method before you invoke
|
|
* an operation on an account that may emit a signal.
|
|
* The reason is that the pointer list seemingly often changes the
|
|
* adresses of the inserted accounts. After that the connections are corrupt.
|
|
*/
|
|
void connectAccounts();
|
|
|
|
/**
|
|
* Returns the subjects of the selected mails.
|
|
* @return subjects of selected mails
|
|
*/
|
|
TQStringList getSelectedSubjects() const;
|
|
|
|
/**
|
|
* Returns whether there are mails in this list which are selected
|
|
* in the list view.
|
|
* @return TRUE - there are selected mails
|
|
* @return FALSE - there aren't selected mails
|
|
*/
|
|
bool hasSelectedMails();
|
|
|
|
/**
|
|
* Downloads and shows the bodies of the selected mails.
|
|
* This just starts the download and returns after then. When all
|
|
* bodies are downloaded and shown the signal sigShowBodiesReady will be
|
|
* emitted.
|
|
*/
|
|
void showSelectedMails();
|
|
|
|
/**
|
|
* Refreshes the mail list of all accounts.
|
|
* This just starts the refresh and returns after then. When all
|
|
* accounts have refreshed their mail list the signal sigRefreshReady will be
|
|
* emitted.
|
|
* @param log Pointer to the filter log.
|
|
*/
|
|
void refreshMailLists( FilterLog* log = NULL );
|
|
|
|
/**
|
|
* Returns the number of new mails.
|
|
* @return number of new mails
|
|
*/
|
|
int getNumberNewMails();
|
|
|
|
/**
|
|
* Returns the number of mails.
|
|
* @return number of mails
|
|
*/
|
|
int getNumberMails();
|
|
|
|
/**
|
|
* Returns the total size of all mails.
|
|
* @return total size
|
|
*/
|
|
long getTotalSize();
|
|
|
|
/**
|
|
* Creates for every mail a list view item and inserts it
|
|
* into the mail list view.
|
|
* @param view pointer to the application view
|
|
*/
|
|
void fillMailListView( KshowmailView* view );
|
|
|
|
/**
|
|
* Returns whether the main window will be shown, if
|
|
* new mails was received.
|
|
* @return TRUE - main window will be shown
|
|
* @return FALSE - main window will not be shown
|
|
*/
|
|
bool showMainWindowForNewMails();
|
|
|
|
/**
|
|
* Returns whether an alert message will be shown if
|
|
* new mails were received.
|
|
* @return TRUE - will be shown
|
|
* @return FALSE - will not be shown
|
|
*/
|
|
bool showAlertMessageForNewMails();
|
|
|
|
/**
|
|
* Returns whether the app will be terminated if
|
|
* no new mails were received.
|
|
* @return TRUE - will be terminated
|
|
* @return FALSE - will not be terminated
|
|
*/
|
|
bool quitNoNewMails();
|
|
|
|
/**
|
|
* Returns whether the main window will be minimized, if
|
|
* no new mails were received.
|
|
* @return TRUE - main window will be minimized
|
|
* @return FALSE - main window will not be minimized
|
|
*/
|
|
bool minimizeMainWindowNoNewMails();
|
|
|
|
/**
|
|
* Returns the configured time to the first refresh.
|
|
* @return time to the first refresh (seconds)
|
|
*/
|
|
int getInitTime();
|
|
|
|
/**
|
|
* Sets the time to the first refresh.
|
|
* @param time time (seconds) to the first refresh
|
|
*/
|
|
void setInitTime( int time );
|
|
|
|
/**
|
|
* Returns whether a time to first refresh is configured.
|
|
* @return TRUE - init time configured
|
|
* @return FALSE - no init time configured
|
|
*/
|
|
bool hasInitTime();
|
|
|
|
/**
|
|
* Refreshes the account list (number of mails and total size).
|
|
*/
|
|
void refreshAccountList();
|
|
|
|
/**
|
|
* Kills all running pop3 jobs.
|
|
*/
|
|
void killPOP3Jobs();
|
|
|
|
/**
|
|
* Shows the headers of all selected mails.
|
|
*/
|
|
void showSelectedHeaders();
|
|
|
|
/**
|
|
* Executes the configure new mail command.
|
|
* Does nothing, if the command option is switched off (m_bCommand == false).
|
|
*/
|
|
void executeNewMailCommand();
|
|
|
|
/**
|
|
* Returns whether all new mails will keep new status until the app is closed.
|
|
* @return TRUE - mails keep new status at next refresh
|
|
* @return FALSE - mails don't keep new status at next refresh
|
|
*/
|
|
bool keepNew();
|
|
|
|
/**
|
|
* Prints the setup.
|
|
*/
|
|
void printSetup();
|
|
|
|
/**
|
|
* Saves the current mails data and the account setups.
|
|
* The mails data will be saved into an XML file (kshowmail.xml).
|
|
* The account setups will be saved into the application config file (kshowmailrc).
|
|
*/
|
|
void saveOptions();
|
|
|
|
/**
|
|
* Reads stored mails data.
|
|
* At every setup saving (e.g. at exit) the mails data will be stored into the file kshowmail.xml.
|
|
* At application start we read this file to identify mails which are not new at first refresh.
|
|
*/
|
|
void readStoredMails();
|
|
|
|
/**
|
|
* Returns the action to used on spam mails
|
|
* @return action to used on spam mails
|
|
*/
|
|
FilterAction_Type getSpamAction();
|
|
|
|
/**
|
|
* Returns the mailbox for spam mails
|
|
* @return mailbox for spam
|
|
*/
|
|
TQString getSpamMailbox();
|
|
|
|
/**
|
|
* Returns the number of deleted mails by last refresh.
|
|
* @return number of deleted mails by last refresh
|
|
*/
|
|
int numberDeletedMailsLastRefresh();
|
|
|
|
/**
|
|
* Returns the number of deleted mails since start.
|
|
* @return number of deleted mails since start
|
|
*/
|
|
int numberDeletedMailsStart();
|
|
|
|
/**
|
|
* Returns the number of moved mails by last refresh.
|
|
* @return number of moved mails by last refresh
|
|
*/
|
|
int numberMovedMailsLastRefresh();
|
|
|
|
/**
|
|
* Returns the number of moved mails since start.
|
|
* @return number of moved mails since start
|
|
*/
|
|
int numberMovedMailsStart();
|
|
|
|
/**
|
|
* Returns the number of ignored mails by last refresh.
|
|
* @return number of ignored mails by last refresh
|
|
*/
|
|
int numberIgnoredMails();
|
|
|
|
/**
|
|
* Returns the senders of the selected mails
|
|
* @return senders of the selected mails
|
|
*/
|
|
TQStringList getSelectedSenders() const;
|
|
|
|
bool setItem (const char* item);
|
|
void setList (TQListView* list);
|
|
void beep ();
|
|
void playSound ();
|
|
void playSound (const char* file);
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
* Connector to the configuration file
|
|
*/
|
|
TDEConfig* config;
|
|
|
|
/**
|
|
* Time in minutes to the next automatic refresh.
|
|
*/
|
|
int m_nIntervalTimer;
|
|
|
|
/**
|
|
* Number of seconds the application will wait for a pop3 job to complete.
|
|
*/
|
|
uint m_nPop3Timer;
|
|
|
|
/**
|
|
* This map is used by the delete methods.
|
|
* deleteSelectedMails() clears it and after that inserts for every account
|
|
* an item. The Key is the account name and the data is TRUE.
|
|
* When slotCheckDeletionState() is invoked by a signal sent by an account,
|
|
* this slot will set the appropriate item data to FALSE. If the data of all
|
|
* items are set to FALSE, the method will know all accounts have ended the
|
|
* deletion and will emit sigDeleteReady.
|
|
* @see deleteSelectedMails()
|
|
* @see slotCheckDeletionState()
|
|
*/
|
|
AccountTaskMap_Type AccountDeletionMap;
|
|
|
|
/**
|
|
* This map is used by the methods to show the mail body.
|
|
* showSelectedMails() clears it and after that inserts for every account
|
|
* an item. The Key is the account name and the data is TRUE.
|
|
* When slotCheckShowBodiesState() is invoked by a signal sent by an account,
|
|
* this slot will set the appropriate item data to FALSE. If the data of all
|
|
* items are set to FALSE, the method will know all accounts have shown the
|
|
* mail body and will emit sigShowBodiesReady.
|
|
* @see showSelectedMails()
|
|
* @see slotCheckShowBodiesState()
|
|
*/
|
|
AccountTaskMap_Type AccountShowBodiesMap;
|
|
|
|
/**
|
|
* This map is used by the methods to refresh the account mail lists.
|
|
* refreshMailLists() clears it and after that inserts for every account
|
|
* an item. The Key ist the account name and the data is TRUE.
|
|
* When slotCheckRefreshState() is invoked by a signal sent by an account,
|
|
* this slot will set the appropriate item data to FALSE. If the data of all
|
|
* items are set to FALSE, the method will know all accounts have refreshed their
|
|
* mail list and will emit sigRefreshReady.
|
|
* @see refreshMailLists()
|
|
* @see slotCheckRefreshState()
|
|
*/
|
|
AccountTaskMap_Type AccountRefreshMap;
|
|
|
|
/**
|
|
* TRUE - the user has to confirm a deletion,
|
|
* FALSE - the user does not have to confirm a deletion
|
|
*/
|
|
bool m_bConfirmDelete;
|
|
|
|
/**
|
|
* TRUE - allow HTML formatting in the mail show dialog box
|
|
* FALSE - don't allow HTML formatting
|
|
* @see setAllowHTML()
|
|
* @see allowHTML()
|
|
*/
|
|
bool m_bAllowHTML;
|
|
|
|
/**
|
|
* Number of windows, which have been opened by the accounts to show mails.
|
|
* Used by slotMessageWindowOpened() and slotMessageWindowClosed().
|
|
* @see slotMessageWindowOpened
|
|
* @see slotMessageWindowClosed
|
|
*/
|
|
int ctrOpenMessageWindows;
|
|
|
|
/**
|
|
* Contains the time (seconds) to first refresh.
|
|
* @see setInitTime()
|
|
* @see getInitTime()
|
|
*/
|
|
int m_nInitTimer;
|
|
|
|
/**
|
|
* TRUE - If a new mail is arrived an alert window will be shown.
|
|
*/
|
|
bool m_bShowMessage;
|
|
|
|
/**
|
|
* TRUE - If a new mail is arrived the main window will be shown.
|
|
*/
|
|
bool m_bShowMainWindow;
|
|
|
|
/**
|
|
* TRUE - If a new mail is arrived the system will beep.
|
|
*/
|
|
bool m_bBeep;
|
|
|
|
/**
|
|
* TRUE - If a new mail is arrived a sound will be played.
|
|
*/
|
|
bool m_bSound;
|
|
|
|
/**
|
|
* Sound file which will be played if a new mail is arrived.
|
|
*/
|
|
TQString m_strSoundFile;
|
|
|
|
/**
|
|
* TRUE - If a new mail is arrived a command will be executed.
|
|
*/
|
|
bool m_bCommand;
|
|
|
|
/**
|
|
* Path to command which will be executed if a new mail is arrived.
|
|
*/
|
|
TQString m_strCommandPath;
|
|
|
|
/**
|
|
* TRUE - If no new mail is arrived the application will be ended.
|
|
*/
|
|
bool m_bTerminate;
|
|
|
|
/**
|
|
* TRUE - If no new mail is arrived the main window will be minimized.
|
|
*/
|
|
bool m_bMinimize;
|
|
|
|
/**
|
|
* TRUE - If a connection error occures during refresh an error message will be shown.
|
|
*/
|
|
bool m_bShowConnectionErrors;
|
|
|
|
/**
|
|
* TRUE - The user has to confirm window close.
|
|
*/
|
|
bool m_bConfirmClose;
|
|
|
|
/**
|
|
* TRUE - the app starts minimized.
|
|
*/
|
|
bool m_bStartMinimized;
|
|
|
|
/**
|
|
* TRUE - the close button leaves the application running in tray
|
|
*/
|
|
bool m_bCloseMinimizes;
|
|
|
|
/**
|
|
* TRUE - minimizes to the tray rather than to the taskbar
|
|
*/
|
|
bool m_bMinimizeToTray;
|
|
|
|
/**
|
|
* TRUE - mails keep new until termination
|
|
*/
|
|
bool m_bKeepNew;
|
|
|
|
/**
|
|
* Mailbox for Spam, if configured
|
|
*/
|
|
TQString spamMailbox;
|
|
|
|
/**
|
|
* Action which shall be done, if the mail is Spam
|
|
*/
|
|
FilterAction_Type spamAction;
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Makes a copy from the given account object and returns the pointer to it.
|
|
* Reimplementation of TQPtrList::newItem().
|
|
* Used by TQPtrList to add new items.
|
|
* @param item account object
|
|
* @return pointer to the new account object
|
|
*/
|
|
virtual TQPtrCollection::Item newItem( TQPtrCollection::Item item );
|
|
|
|
/**
|
|
* Compares two ConfigElem objects.
|
|
* Reimplementation of TQPtrList::compareItems(). Used by inSort().
|
|
* @param item1 account 1
|
|
* @param item2 account 2
|
|
* @return 0 if account name 1 == account name 2
|
|
* @return nonzero if account name 2 != account name 2
|
|
*/
|
|
virtual int compareItems( TQPtrCollection::Item item1, TQPtrCollection::Item item2 );
|
|
|
|
/**
|
|
* Returns whether the given account is in the list
|
|
* @param name name of the searched account
|
|
* @return TRUE - account is existent
|
|
* @return FALSE - account is not existent
|
|
*/
|
|
bool hasAccount( const TQString& name ) const;
|
|
|
|
/**
|
|
* Returns the pointer to the account named like the given name.
|
|
* @param name of the searched account
|
|
* @return account or NULL, if the account was not found
|
|
*/
|
|
ConfigElem* getAccount( const TQString& name ) const;
|
|
|
|
protected slots:
|
|
|
|
/**
|
|
* Connected with signal sigConfigChanged of all accounts.
|
|
* Emits the signal sigConfigChanged.
|
|
*/
|
|
void slotAccountConfigChanged();
|
|
|
|
/**
|
|
* Connected with signal sigDeleteReady of all accounts.
|
|
* When an account has sent this signal its appropriate item
|
|
* in AccountDeletionMap will set to FALSE.
|
|
* When all accounts have done the deletion it will emit signal
|
|
* sigDeleteReady.
|
|
* @param account name of the account which has emitted the signal
|
|
* @see AccountDeletionMap
|
|
*/
|
|
void slotCheckDeletionState( TQString account );
|
|
|
|
/**
|
|
* Connected with signal sigShowBodiesReady of all accounts.
|
|
* When an account has sent this signal its appropriate item
|
|
* in AccountShowBodiesMap will set to FALSE.
|
|
* When all accounts have shown the mail it will emit signal
|
|
* sigShowBodiesReady.
|
|
* @param account name of the account which has emitted the signal
|
|
* @see AccountShowBodiesMap
|
|
*/
|
|
void slotCheckShowBodiesState( TQString account );
|
|
|
|
/**
|
|
* Connected with signal sigMessageWindowOpened of all accounts.
|
|
* When an account has sent this signal the counter ctrOpenMessageWindows
|
|
* will be incremented.
|
|
* When the counter was incremented from zero (the first window was opened)
|
|
* the signal sigMessageWindowOpened will be emitted.
|
|
* @see ctrOpenMessageWindows
|
|
* @see sigMessageWindowOpened
|
|
*/
|
|
void slotMessageWindowOpened();
|
|
|
|
/**
|
|
* Connected with signal sigMessageWindowClosed of all accounts.
|
|
* When an account has sent this signal the counter ctrOpenMessageWindows
|
|
* will be decremented.
|
|
* When the counter has reached zero the signal sigAllMessageWindowsClosed
|
|
* will be emitted.
|
|
* @see ctrOpenMessageWindows
|
|
* @see sigAllMessageWindowsClosed
|
|
*/
|
|
void slotMessageWindowClosed();
|
|
|
|
/**
|
|
* Connected with signal sigRefreshReady of all accounts.
|
|
* When an account has sent this signal its appropriate item
|
|
* in AccountRefreshMap will set to FALSE.
|
|
* When all accounts have refreshed their mail list it will emit
|
|
* signal sigRefreshReady.
|
|
* @param account name of the account which has emitted the signal
|
|
* @see AccountRefreshMap
|
|
*/
|
|
void slotCheckRefreshState( TQString account );
|
|
|
|
signals:
|
|
|
|
/**
|
|
* Will be emitted when the configuration of an account or of the app
|
|
* was changed.
|
|
*/
|
|
void sigConfigChanged();
|
|
|
|
/**
|
|
* Will be emitted when all selected mails are deleted.
|
|
*/
|
|
void sigDeleteReady();
|
|
|
|
/**
|
|
* Will be emitted when all selected mails are shown.
|
|
*/
|
|
void sigShowBodiesReady();
|
|
|
|
/**
|
|
* Will be emitted by slotMessageWindowOpened when an account has
|
|
* opened a window to show a mail.
|
|
* @see slotMessageWindowOpened
|
|
*/
|
|
void sigMessageWindowOpened();
|
|
|
|
/**
|
|
* Will be emitted by slotMessageWindowClosed when all accounts have
|
|
* closed their windows to show mails.
|
|
* @see slotMessageWindowClosed
|
|
*/
|
|
void sigAllMessageWindowsClosed();
|
|
|
|
/**
|
|
* Will be emitted, when all accounts have refreshed their mail list.
|
|
*/
|
|
void sigRefreshReady();
|
|
|
|
};
|
|
|
|
#endif
|