advanced call history plugin

cusax-fix
Yana Stamcheva 19 years ago
parent d5c8bd2e5f
commit 4a3d23171f

@ -743,7 +743,7 @@
<!-- Tell felix to run sip-communicator-->
<sysproperty key="felix.config.properties"
value="file:./lib/felix.client.run.properties"/>
<!-- Tell java.util.logging about our logging preferences -->
<sysproperty key="java.util.logging.config.file"
value="lib/logging.properties"/>
@ -751,8 +751,8 @@
<sysproperty key="java.net.preferIPv6Addresses"
value="false"/>
<!--sysproperty key="net.java.sip.communicator.SC_HOME_DIR_LOCATION"
value="${user.home}"/-->
<sysproperty key="net.java.sip.communicator.SC_HOME_DIR_LOCATION"
value="${user.home}/schome"/>
<!-- Setting properties necessary for dependencies on native libs.-->
<sysproperty key="java.library.path" path="${ld.library.path}:${path}:${dyld.library.path}"/>
@ -852,6 +852,7 @@
bundle-growlnotification,bundle-audionotifier,bundle-plugin-splashscreen,
bundle-systray,bundle-browserlauncher,bundle-gibberish,
bundle-gibberish-slick,bundle-plugin-gibberishaccregwizz,
bundle-plugin-extended-callhistory-search,
bundle-rss,bundle-plugin-rssaccregwizz,
bundle-pluginmanager"/>
@ -1545,6 +1546,17 @@ javax.swing.event, javax.swing.border"/>
prefix="net/java/sip/communicator/plugin/pluginmanager"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN-EXTENDED CALL HISTORY SEARCH -->
<target name="bundle-plugin-extended-callhistory-search">
<!-- Creates a bundle for a extended callhistory search-->
<jar compress="false" destfile="${bundles.dest}/extendedcallhistorysearch.jar"
manifest="src/net/java/sip/communicator/plugin/extendedcallhistorysearch/extendedcallhistorysearch.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/extendedcallhistorysearch"
prefix="net/java/sip/communicator/plugin/extendedcallhistorysearch"/>
<zipfileset src="${lib.noinst}/jcalendar-1.3.2.jar" prefix=""/>
</jar>
</target>
<!-- BUNDLE-RSS -->
<target name="bundle-rss">

@ -71,8 +71,8 @@ felix.auto.start.50= \
reference:file:sc-bundles/protocol-yahoo.jar \
reference:file:sc-bundles/protocol-gibberish.jar \
reference:file:sc-bundles/netaddr.jar \
reference:file:sc-bundles/meta-cl.jar \
reference:file:sc-bundles/protocol-rss.jar
reference:file:sc-bundles/protocol-rss.jar \
reference:file:sc-bundles/meta-cl.jar
felix.auto.start.60= \
reference:file:sc-bundles/history.jar \
@ -94,8 +94,9 @@ felix.auto.start.60= \
reference:file:sc-bundles/msnaccregwizz.jar \
reference:file:sc-bundles/yahooaccregwizz.jar \
reference:file:sc-bundles/gibberishaccregwizz.jar \
reference:file:sc-bundles/shutdown.jar \
reference:file:sc-bundles/rssaccregwizz.jar
reference:file:sc-bundles/extendedcallhistorysearch.jar \
reference:file:sc-bundles/rssaccregwizz.jar \
reference:file:sc-bundles/shutdown.jar
# Uncomment the following lines if you want to run the architect viewer
# bundle.

@ -0,0 +1,33 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
/**
* Through the <tt>AntialiasingManager</tt> the developer could activate the
* antialiasing mechanism when painting. The method that do the job is
* the <code>activateAntialiasing</code> method. It takes a <tt>Graphics</tt>
* object and activates the antialiasing for it.
*
* @author Yana Stamcheva
*/
public class AntialiasingManager {
/**
* Activates the antialiasing mechanism for the given <tt>Graphics</tt>
* object.
* @param g The <tt>Graphics</tt> object.
*/
public static void activateAntialiasing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
}

@ -0,0 +1,85 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* The <tt>CallList</tt> is the component that contains history call records.
*
* @author Yana Stamcheva
*/
public class CallList
extends JList
implements MouseListener
{
public CallList()
{
this.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
this.getSelectionModel().setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
this.setCellRenderer(new CallListCellRenderer());
this.setModel(new CallListModel());
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.addMouseListener(this);
}
public void addItem(Object item)
{
((CallListModel)this.getModel()).addElement(item);
}
public void addItem(Object item, int index)
{
((CallListModel)this.getModel()).addElement(index, item);
}
public void removeAll()
{
((CallListModel)this.getModel()).removeAll();
}
/**
* Closes or opens a group of calls.
*/
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
CallListModel listModel = (CallListModel) this.getModel();
Object element = listModel.getElementAt(this.getSelectedIndex());
if (element instanceof String) {
if (listModel.isDateClosed(element)) {
listModel.openDate(element);
} else {
listModel.closeDate(element);
}
}
}
}
public void mouseEntered(MouseEvent e)
{}
public void mouseExited(MouseEvent e)
{}
public void mousePressed(MouseEvent e)
{}
public void mouseReleased(MouseEvent e)
{}
}

@ -0,0 +1,211 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import javax.swing.*;
/**
* The <tt>ContactListCellRenderer</tt> is the custom cell renderer used in
* the SIP-Communicator's <tt>ContactList</tt>. It extends JPanel instead of
* JLabel, which allows adding different buttons and icons to the contact cell.
* The cell border and background are repainted.
*
* @author Yana Stamcheva
*/
public class CallListCellRenderer
extends JPanel
implements ListCellRenderer
{
private JPanel dataPanel = new JPanel(new BorderLayout());
private JLabel nameLabel = new JLabel();
private JPanel timePanel = new JPanel(new BorderLayout(8, 0));
private JLabel timeLabel = new JLabel();
private JLabel durationLabel = new JLabel();
private JLabel iconLabel = new JLabel();
private Icon incomingIcon = Resources.getImage("incomingCall");
private Icon outgoingIcon = Resources.getImage("outgoingCall");
private boolean isSelected = false;
private boolean isLeaf = true;
private String direction;
/**
* Initialize the panel containing the node.
*/
public CallListCellRenderer()
{
super(new BorderLayout(5, 5));
this.setBackground(Color.WHITE);
this.setOpaque(true);
this.dataPanel.setOpaque(false);
this.timePanel.setOpaque(false);
this.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.nameLabel.setIconTextGap(2);
this.nameLabel.setFont(this.getFont().deriveFont(Font.BOLD));
this.dataPanel.add(nameLabel, BorderLayout.WEST);
this.add(dataPanel, BorderLayout.CENTER);
}
/**
* Implements the <tt>ListCellRenderer</tt> method.
*
* Returns this panel that has been configured to display the meta contact
* and meta contact group cells.
*/
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus)
{
this.dataPanel.remove(timePanel);
this.dataPanel.remove(timeLabel);
this.dataPanel.remove(durationLabel);
this.remove(iconLabel);
if (value instanceof GuiCallParticipantRecord)
{
GuiCallParticipantRecord participant = (GuiCallParticipantRecord) value;
this.direction = participant.getDirection();
if (direction.equals(GuiCallParticipantRecord.INCOMING_CALL))
iconLabel.setIcon(incomingIcon);
else
iconLabel.setIcon(outgoingIcon);
this.nameLabel.setText(participant.getParticipantName());
this.timeLabel.setText(Resources.getString("at") + " "
+ GuiUtils.formatTime(participant.getStartTime()));
this.durationLabel.setText(Resources.getString("duration") + " "
+ GuiUtils.formatTime(participant.getCallTime()));
// this.nameLabel.setIcon(listModel
// .getMetaContactStatusIcon(contactItem));
this.timePanel.add(timeLabel, BorderLayout.WEST);
this.timePanel.add(durationLabel, BorderLayout.EAST);
this.dataPanel.add(timePanel, BorderLayout.EAST);
this.add(iconLabel, BorderLayout.WEST);
this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
// We should set the bounds of the cell explicitely in order to
// make getComponentAt work properly.
this.setBounds(0, 0, list.getWidth() - 2, 25);
this.isLeaf = true;
}
else if (value instanceof String)
{
String dateString = (String) value;
this.nameLabel.setText(dateString);
this.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
// We should set the bounds of the cell explicitely in order to
// make getComponentAt work properly.
this.setBounds(0, 0, list.getWidth() - 2, 20);
this.isLeaf = false;
}
this.isSelected = isSelected;
return this;
}
/**
* Paint a background for all groups and a round blue border and background
* when a cell is selected.
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AntialiasingManager.activateAntialiasing(g2);
if (!this.isLeaf)
{
GradientPaint p = new GradientPaint(0, 0,
Constants.BLUE_GRAY_BORDER_COLOR, this.getWidth(), this
.getHeight(), Constants.MOVER_END_COLOR);
g2.setPaint(p);
g2.fillRoundRect(1, 1, this.getWidth(), this.getHeight() - 1, 7, 7);
}
else
{
if (direction.equals(GuiCallParticipantRecord.INCOMING_CALL))
{
GradientPaint p = new GradientPaint(0, 0,
Constants.HISTORY_IN_CALL_COLOR, this.getWidth(), this
.getHeight(), Constants.MOVER_END_COLOR);
g2.setPaint(p);
g2.fillRoundRect(1, 1, this.getWidth(), this.getHeight() - 1,
7, 7);
}
else if (direction.equals(GuiCallParticipantRecord.OUTGOING_CALL))
{
GradientPaint p = new GradientPaint(0, 0,
Constants.HISTORY_OUT_CALL_COLOR, this.getWidth(), this
.getHeight(), Constants.MOVER_END_COLOR);
g2.setPaint(p);
g2.fillRoundRect(1, 1, this.getWidth(), this.getHeight() - 1,
7, 7);
}
}
if (this.isSelected)
{
g2.setColor(Constants.SELECTED_END_COLOR);
g2.fillRoundRect(1, 0, this.getWidth(), this.getHeight(), 7, 7);
g2.setColor(Constants.BLUE_GRAY_BORDER_DARKER_COLOR);
g2.setStroke(new BasicStroke(1.5f));
g2.drawRoundRect(1, 0, this.getWidth() - 2, this.getHeight() - 1,
7, 7);
}
}
}

@ -0,0 +1,156 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.util.*;
import javax.swing.*;
/**
* The data model of the Call list.
*
* @author Yana Stamcheva
*/
public class CallListModel extends AbstractListModel
{
private LinkedList callList = new LinkedList();
private Hashtable closedDates = new Hashtable();
/**
* Closes the given date by hiding all containing calls.
*
* @param date The date to close.
*/
public void closeDate(Object date)
{
int startIndex = this.indexOf(date);
int endIndex = startIndex;
int currentSize = getSize();
Collection c = new ArrayList();
for(int i = startIndex + 1; i < currentSize; i ++) {
Object o = this.getElementAt(i);
if(o instanceof GuiCallParticipantRecord) {
this.closedDates.put(o, date);
c.add(o);
endIndex++;
}
else
break;
}
removeAll(c);
fireIntervalRemoved(this, startIndex, endIndex);
}
/**
* Opens the given date by showing all containing calls.
*
* @param date The date to open.
*/
public void openDate(Object date)
{
int startIndex = this.indexOf(date);
int endIndex = startIndex;
Hashtable closedDatesCopy = (Hashtable)closedDates.clone();
if(closedDatesCopy.containsValue(date)) {
Iterator dates = closedDatesCopy.entrySet().iterator();
while(dates.hasNext()) {
Map.Entry entry = (Map.Entry)dates.next();
Object callRecord = entry.getKey();
Object callDate = entry.getValue();
if(callDate.equals(date)) {
endIndex++;
closedDates.remove(callRecord);
this.addElement(endIndex, callRecord);
}
}
}
fireIntervalAdded(this, startIndex, endIndex);
}
/**
* Checks whether the given date is closed.
*
* @param date The date to check.
* @return True if the date is closed, false - otherwise.
*/
public boolean isDateClosed(Object date) {
if (this.closedDates.containsValue(date))
return true;
else
return false;
}
public int getSize()
{
return callList.size();
}
public Object getElementAt(int index)
{
if (index>=0)
return callList.get(index);
else
return null;
}
public void addElement(Object item)
{
synchronized (callList) {
this.callList.add(item);
int index = callList.indexOf(item);
fireIntervalAdded(this, index, index);
}
}
public void addElement(int index, Object item)
{
synchronized (callList) {
this.callList.add(index, item);
fireIntervalAdded(this, index, index);
}
}
public void removeElement(Object item)
{
synchronized (callList) {
this.callList.remove(item);
}
}
public void removeAll(Collection c)
{
synchronized (callList) {
callList.removeAll(c);
}
}
public void removeAll()
{
int currentSize = getSize();
while(callList.size() > 0) {
synchronized (callList) {
callList.removeLast();
}
}
fireIntervalRemoved(this, 0, currentSize);
}
public int indexOf(Object item)
{
synchronized (callList) {
return callList.indexOf(item);
}
}
}

@ -0,0 +1,137 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import net.java.sip.communicator.util.*;
/**
* All look and feel related constants are stored here.
*
* @author Yana Stamcheva
*/
public class Constants {
private static Logger logger = Logger.getLogger(Constants.class);
/*
* ===================================================================
* ---------------------- CALLTYPE CONSTANTS -------------------------
* ===================================================================
*/
/**
* The incoming call flag.
*/
public static final int INCOMING_CALL = 1;
/**
* The outgoing call flag.
*/
public static final int OUTGOING_CALL = 2;
/**
* The Incoming & outcoming flag.
*/
public static final int INOUT_CALL = 3;
/*
* ======================================================================
* -------------------- FONTS AND COLOR CONSTANTS ------------------------
* ======================================================================
*/
/**
* The color used to paint the background of an incoming call history
* record.
*/
public static final Color HISTORY_DATE_COLOR
= new Color(255, 201, 102);
/**
* The color used to paint the background of an incoming call history
* record.
*/
public static final Color HISTORY_IN_CALL_COLOR
= new Color(249, 255, 197);
/**
* The color used to paint the background of an outgoing call history
* record.
*/
public static final Color HISTORY_OUT_CALL_COLOR
= new Color(243, 244, 247);
/**
* The end color used to paint a gradient selected background of some
* components.
*/
public static final Color SELECTED_END_COLOR
= new Color(209, 212, 225);
/**
* The start color used to paint a gradient mouse over background of some
* components.
*/
public static final Color MOVER_START_COLOR = new Color(230,
230, 230);
/**
* The end color used to paint a gradient mouse over background of some
* components.
*/
public static final Color MOVER_END_COLOR = new Color(255,
255, 255);
/**
* Gray color used to paint some borders, like the button border for
* example.
*/
public static final Color GRAY_COLOR = new Color(154, 154,
154);
/**
* A color between blue and gray used to paint some borders.
*/
public static final Color BLUE_GRAY_BORDER_COLOR = new Color(142, 160, 188);
/**
* A color between blue and gray (darker than the other one), used to paint
* some borders.
*/
public static final Color BLUE_GRAY_BORDER_DARKER_COLOR = new Color(131, 149,
178);
/*
* ======================================================================
* --------------------------- FONT CONSTANTS ---------------------------
* ======================================================================
*/
/**
* The name of the font used in this ui implementation.
*/
public static final String FONT_NAME = "Verdana";
/**
* The size of the font used in this ui implementation.
*/
public static final String FONT_SIZE = "12";
/**
* The default <tt>Font</tt> object used through this ui implementation.
*/
public static final Font FONT = new Font(Constants.FONT_NAME, Font.PLAIN,
new Integer(Constants.FONT_SIZE).intValue());
}

@ -0,0 +1,61 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import net.java.sip.communicator.service.callhistory.*;
import net.java.sip.communicator.service.gui.*;
import org.osgi.framework.*;
/**
* Call History Search PlugIn Activator
*
* @author Bourdon Maxime & Meyer Thomas
*/
public class ExtendedCallHistorySearchActivator
implements BundleActivator
{
private static BundleContext context;
public void start(BundleContext bc) throws Exception
{
context = bc;
ServiceReference uiServiceRef = bc.getServiceReference(
UIService.class.getName());
UIService uiService = (UIService) bc.getService(uiServiceRef);
if (uiService.isContainerSupported(UIService.CONTAINER_TOOLS_MENU))
{
ExtendedCallHistorySearchItem extendedSearch
= new ExtendedCallHistorySearchItem();
uiService.addComponent(UIService.CONTAINER_TOOLS_MENU,
extendedSearch);
}
}
public void stop(BundleContext bc) throws Exception
{
}
/**
* Returns an instance of the <tt>CallHistoryService</tt>.
*/
public static CallHistoryService getCallHistoryService()
{
ServiceReference callHistoryServiceRef = context
.getServiceReference(CallHistoryService.class.getName());
CallHistoryService callHistoryService = (CallHistoryService) context
.getService(callHistoryServiceRef);
return callHistoryService;
}
}

@ -0,0 +1,477 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.service.callhistory.*;
import com.toedter.calendar.*;
/**
* The <tt>ExtendedCallHistorySearchDialog</tt> allows to search in call
* history records, by specifying a period, or a call participant name, or type
* of the call (incoming or outgoing).
*
* @author Maxime Bourdon & Thomas Meyer
*/
public class ExtendedCallHistorySearchDialog
extends JDialog
implements ActionListener,
ItemListener
{
/* PANEL */
private JPanel mainSearchPanel = new JPanel(new BorderLayout());
private JPanel mainPanel = new JPanel(new BorderLayout(3, 1));
private JPanel searchPanel = new JPanel(new GridBagLayout());
private JPanel callTypePanel = new JPanel(new GridBagLayout());
private JPanel callListResultPanel = new JPanel(new BorderLayout());
/* BUTTON */
private JButton searchButton = new JButton(Resources.getString("search"),
Resources.getImage("searchIcon"));
/* TEXT FIELD */
private JTextField contactNameField = new JTextField();
/* LABEL */
private JLabel contactNameLabel = new JLabel(Resources
.getString("contactName") + ": ");
private JLabel sinceDateLabel
= new JLabel(Resources.getString("since") + ": ");
private JLabel untilDateLabel
= new JLabel(Resources.getString("until") + ": ");
private JLabel callTypeLabel
= new JLabel(Resources.getString("callType") + ": ");
/* CHECKBOX */
private JCheckBox inCheckBox = new JCheckBox(Resources
.getString("incoming"), true);
private JCheckBox outCheckBox = new JCheckBox(Resources
.getString("outgoing"), true);
/* SCROLL PANE */
private JScrollPane scrollPane = new JScrollPane();
/* contraint grid */
private GridBagConstraints constraintsGRbag = new GridBagConstraints();
Collection participants = null;
private CallList callList = new CallList();
/* Service */
CallHistoryService callAccessService;
private Date lastDateFromHistory = null;
private Collection callListCollection;
private JDateChooser untilDC
= new JDateChooser("dd/MM/yyyy", "##/##/####", ' ');
private JDateChooser sinceDC
= new JDateChooser("dd/MM/yyyy", "##/##/####", ' ');
private int direction;
/**
* Creates a new instance of <tt>ExtendedCallHistorySearchDialog</tt>.
*/
public ExtendedCallHistorySearchDialog()
{
this.mainPanel.setPreferredSize(new Dimension(650, 550));
this.setTitle(Resources.getString("advancedCallHistorySearch"));
this.initPanels();
this.initDateChooser();
this.searchPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Search"), BorderFactory
.createEmptyBorder(5, 5, 5, 5)));
this.callTypePanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(""), BorderFactory
.createEmptyBorder(5, 5, 5, 5)));
this.callListResultPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(""), BorderFactory
.createEmptyBorder(5, 5, 5, 5)));
this.getContentPane().add(mainPanel);
this.pack();
/* action listener */
searchButton.addActionListener(this);
inCheckBox.addItemListener(this);
outCheckBox.addItemListener(this);
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
/**
* Loads all calls from history and shows them in this dialog.
*/
public void loadHistoryCalls()
{
/* get the call list collection */
callAccessService = ExtendedCallHistorySearchActivator
.getCallHistoryService();
callListCollection = callAccessService.findByEndDate(new Date());
loadTableRecords(
callListCollection, Constants.INOUT_CALL, null, new Date());
}
/**
* Initialize the "until" date field to the current date.
*/
private void initDateChooser()
{
untilDC.getJCalendar().setWeekOfYearVisible(false);
untilDC.getJCalendar().setDate(new Date());
sinceDC.getJCalendar().setWeekOfYearVisible(false);
}
/**
* Init panels display.
*/
private void initPanels()
{
this.getRootPane().setDefaultButton(searchButton);
this.mainSearchPanel.add(searchPanel, BorderLayout.NORTH);
this.mainSearchPanel.add(callTypePanel, BorderLayout.CENTER);
this.mainPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
this.mainPanel.add(mainSearchPanel, BorderLayout.NORTH);
this.mainPanel.add(callListResultPanel, BorderLayout.CENTER);
/* SEARCH PANEL */
constraintsGRbag.anchor = GridBagConstraints.WEST;
constraintsGRbag.insets = new Insets(5, 5, 5, 5);
constraintsGRbag.gridwidth = 1;
constraintsGRbag.fill = GridBagConstraints.NONE;
this.searchPanel.add(contactNameLabel, constraintsGRbag);
constraintsGRbag.gridwidth = GridBagConstraints.REMAINDER;
constraintsGRbag.fill = GridBagConstraints.HORIZONTAL;
constraintsGRbag.weightx = 1.0;
constraintsGRbag.gridx = GridBagConstraints.RELATIVE;
this.searchPanel.add(contactNameField, constraintsGRbag);
/* DATE */
constraintsGRbag.anchor = GridBagConstraints.WEST;
constraintsGRbag.gridwidth = 1;
constraintsGRbag.gridy = 2;
constraintsGRbag.fill = GridBagConstraints.NONE;
this.searchPanel.add(sinceDateLabel, constraintsGRbag);
constraintsGRbag.gridwidth = GridBagConstraints.RELATIVE;
constraintsGRbag.fill = GridBagConstraints.HORIZONTAL;
constraintsGRbag.weightx = 1.0;
this.searchPanel.add(sinceDC, constraintsGRbag);
constraintsGRbag.gridy = 3;
constraintsGRbag.gridwidth = 1;
constraintsGRbag.fill = GridBagConstraints.NONE;
this.searchPanel.add(untilDateLabel, constraintsGRbag);
constraintsGRbag.fill = GridBagConstraints.HORIZONTAL;
this.searchPanel.add(untilDC, constraintsGRbag);
/* BUTTON */
constraintsGRbag.gridy = 4;
constraintsGRbag.gridx = 3;
constraintsGRbag.fill = GridBagConstraints.NONE;
constraintsGRbag.anchor = GridBagConstraints.EAST;
this.searchPanel.add(searchButton, constraintsGRbag);
/* CALL TYPE */
constraintsGRbag.anchor = GridBagConstraints.WEST;
constraintsGRbag.insets = new Insets(5, 5, 5, 5);
constraintsGRbag.gridwidth = 1;
constraintsGRbag.gridx = 1;
constraintsGRbag.gridy = 1;
this.callTypePanel.add(callTypeLabel, constraintsGRbag);
constraintsGRbag.gridx = 2;
this.callTypePanel.add(inCheckBox, constraintsGRbag);
constraintsGRbag.gridx = 3;
this.callTypePanel.add(outCheckBox, constraintsGRbag);
/* CALL LIST PANEL */
this.scrollPane.getViewport().add(callList);
this.callListResultPanel.add(scrollPane, BorderLayout.CENTER);
}
/**
* Loads the appropriate history calls when user clicks on the search
* button.
*/
public void actionPerformed(ActionEvent e)
{
JButton sourceButton = (JButton) e.getSource();
if (sourceButton.equals(searchButton))
{
/* update the callList */
new Thread()
{
public void run()
{
callListCollection = callAccessService
.findByEndDate(new Date());
if (inCheckBox.isSelected() && outCheckBox.isSelected())
{
direction = Constants.INOUT_CALL;
}
else
{
if (inCheckBox.isSelected())
direction = Constants.INCOMING_CALL;
else
{
if (outCheckBox.isSelected())
direction = Constants.OUTGOING_CALL;
else
direction = Constants.INOUT_CALL;
}
}
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
loadTableRecords(callListCollection, direction,
sinceDC.getDate(), untilDC.getDate());
}
});
}
}.start();
}
}
/**
* Remove or add calls to the list of calls depending on the state of
* incoming and outgoing checkboxes.
*/
public void itemStateChanged(ItemEvent e)
{
JCheckBox sourceCheckBox = (JCheckBox) e.getSource();
/* Incoming checkbox */
if (sourceCheckBox.equals(inCheckBox)
|| sourceCheckBox.equals(outCheckBox))
{
/* INCOMING box Checked */
if (inCheckBox.isSelected())
{
/* OUTCOMING box checked */
if (outCheckBox.isSelected() == true)
{
loadTableRecords(callListCollection,
Constants.INOUT_CALL,
sinceDC.getDate(), untilDC.getDate());
}
// only incoming is checked
else
{
loadTableRecords(callListCollection,
Constants.INCOMING_CALL,
sinceDC.getDate(), untilDC.getDate());
}
}
/* check the OUTCOMING box */
else
{
// checked
if (outCheckBox.isSelected() == true)
{
loadTableRecords(callListCollection,
Constants.OUTGOING_CALL,
sinceDC.getDate(), untilDC.getDate());
}
/* both are unchecked */
else
loadTableRecords(callListCollection,
Constants.INOUT_CALL,
sinceDC.getDate(), untilDC.getDate());
}
}
}
private String processDate(Date date)
{
String resultString;
long currentDate = System.currentTimeMillis();
if (GuiUtils.compareDates(date, new Date(currentDate)) == 0)
{
resultString = Resources.getString("today");
}
else
{
Calendar c = Calendar.getInstance();
c.setTime(date);
resultString = GuiUtils.formatDate(date);
}
return resultString;
}
/**
* Check if the callRecord direction equals the direction wanted by the user
*
* @param callType integer value (incoming = 1, outgoing = 2, in/out = 3)
* @param callrecord A Callrecord
* @return A string containing the callRecord direction if it equals the
* callType Call, null if not
*/
private String checkCallType(int callType, CallRecord callRecord)
{
String direction = null;
// in
if (callRecord.getDirection().equals(CallRecord.IN)
&& ((callType == Constants.INCOMING_CALL)
|| callType == Constants.INOUT_CALL))
direction = GuiCallParticipantRecord.INCOMING_CALL;
// out
else if (callRecord.getDirection().equals(CallRecord.OUT)
&& (callType == Constants.OUTGOING_CALL
|| callType == Constants.INOUT_CALL))
direction = GuiCallParticipantRecord.OUTGOING_CALL;
return direction;
}
/**
* Check if sinceDate <= callStartDate <= beforeDate
*
* @param callStartDate
* @param sinceDate
* @param beforeDate
* @return true if sinceDate <= callStartDate <= beforeDate false if not
*/
private boolean checkDate(Date callStartDate, Date sinceDate, Date untilDate)
{
/* Test callStartDate >= sinceDate */
if (sinceDate != null)
if (callStartDate.before(sinceDate))
return false;
/* Test callStartDate <= beforeDate */
if (untilDate != null)
if (callStartDate.after(untilDate))
return false;
/* sinceDate <= callStartDate <= beforeDate */
return true;
}
/**
* Loads the collection of call records in the table.
*
* @param historyCalls the collection of call records
* @param calltype the type of the call - could be incoming or outgoing
* @param since the start date of the search
* @param before the end date of the search
*/
private void loadTableRecords(Collection historyCalls, int calltype,
Date since, Date before)
{
boolean addMe = true;
lastDateFromHistory = null;
callList.removeAll();
// callList = new CallList();
Iterator lastCalls = historyCalls.iterator();
while (lastCalls.hasNext())
{
addMe = true;
CallRecord callRecord = (CallRecord) lastCalls.next();
/* DATE Checking */
Date callStartDate = callRecord.getStartTime();
if (checkDate(callStartDate, since, before))
{
if (lastDateFromHistory == null)
{
callList.addItem(processDate(callStartDate));
lastDateFromHistory = callStartDate;
}
else
{
int compareResult = GuiUtils.compareDates(callStartDate,
lastDateFromHistory);
if (compareResult != 0)
{
callList.addItem(processDate(callStartDate));
lastDateFromHistory = callStartDate;
}
}
}
else
addMe = false;
/* PARTICIPANTS Checking */
if (addMe)
{
Iterator participants = callRecord.getParticipantRecords()
.iterator();
while (participants.hasNext() && addMe)
{
CallParticipantRecord participantRecord
= (CallParticipantRecord) participants.next();
String participantName = participantRecord
.getParticipantAddress();
if (participantName.matches(
"(?i).*" + contactNameField.getText() + ".*"))
{
/* DIRECTION Checking */
String direction;
direction = checkCallType(calltype, callRecord);
if (direction != null)
callList.addItem(new GuiCallParticipantRecord(
participantRecord, direction));
else
addMe = false;
}
else
addMe = false; // useless
}
}
}
if (callList.getModel().getSize() > 0)
callList.addItem(Resources.getString("olderCalls") + "...");
}
}

@ -0,0 +1,59 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* The <tt>ExtendedCallHistorySearchButton</tt> is the button that will be
* added in the Call List panel and from which the user would be able to access
* the <tt>ExtendCallHistorySearchDialog</tt>.
*
* @author Bourdon Maxime & Meyer Thomas
*/
public class ExtendedCallHistorySearchItem
extends JMenuItem
implements
ActionListener
{
private ExtendedCallHistorySearchDialog callHistorySearchDialog = null;
/**
* Creates an instance of <tt>ExtendedCallHistoryButton</tt>.
*/
public ExtendedCallHistorySearchItem()
{
super(Resources.getString("advancedCallHistorySearch"));
this.setMnemonic(Resources.getMnemonic("advancedCallHistorySearch"));
this.addActionListener(this);
}
/**
* Launches the extended call history dialog when user clicks on this button.
*/
public void actionPerformed(ActionEvent e)
{
if (callHistorySearchDialog == null)
{
callHistorySearchDialog = new ExtendedCallHistorySearchDialog();
callHistorySearchDialog.setLocation(Toolkit.getDefaultToolkit()
.getScreenSize().width
/ 2 - callHistorySearchDialog.getWidth() / 2, Toolkit
.getDefaultToolkit().getScreenSize().height
/ 2 - callHistorySearchDialog.getHeight() / 2);
}
callHistorySearchDialog.loadHistoryCalls();
callHistorySearchDialog.setVisible(true);
}
}

@ -0,0 +1,119 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.util.*;
import net.java.sip.communicator.service.callhistory.*;
/**
* The <tt>GuiCallParticipantRecord</tt> is meant to be used in the call history
* to represent a history call participant record. It wraps a
* <tt>CallParticipant</tt> or a <tt>CallParticipantRecord</tt> object.
*
* @author Yana Stamcheva
*/
public class GuiCallParticipantRecord
{
public static final String INCOMING_CALL = "IncomingCall";
public static final String OUTGOING_CALL = "OutgoingCall";
private String direction;
private String participantName;
private Date startTime;
private Date callTime;
/**
* Creates an instance of <tt>GuiCallParticipantRecord</tt> by specifying
* the participant name, the call direction (incoming or outgoing), the
* time at which the call has started and the duration of the call.
*
* @param participantName the name of the call participant
* @param direction the direction of the call - INCOMING_CALL
* or OUTGOING_CALL
* @param startTime the time at which the call has started
* @param callTime the duration of the call
*/
public GuiCallParticipantRecord(String participantName,
String direction,
Date startTime,
Date callTime)
{
this.direction = direction;
this.participantName = participantName;
this.startTime = startTime;
this.callTime = callTime;
}
/**
* Creates an instance of <tt>GuiCallParticipantRecord</tt> by specifying
* the corresponding <tt>CallParticipantRecord</tt>, which gives all the
* information for the participant and the call duration.
*
* @param participantRecord the corresponding <tt>CallParticipantRecord</tt>
* @param direction the call direction - INCOMING_CALL or OUTGOING_CALL
*/
public GuiCallParticipantRecord(CallParticipantRecord participantRecord,
String direction)
{
this.direction = direction;
this.participantName = participantRecord.getParticipantAddress();
this.startTime = participantRecord.getStartTime();
this.callTime = GuiUtils.substractDates(
participantRecord.getEndTime(), startTime);
}
/**
* Returns the call direction - INCOMING_CALL or OUTGOING_CALL.
*
* @return the call direction - INCOMING_CALL or OUTGOING_CALL.
*/
public String getDirection()
{
return direction;
}
/**
* Returns the duration of the call.
*
* @return the duration of the call
*/
public Date getCallTime()
{
return callTime;
}
/**
* Returns the name of the participant.
*
* @return the name of the participant
*/
public String getParticipantName()
{
return participantName;
}
/**
* Returns the time at which the call has started.
*
* @return the time at which the call has started
*/
public Date getStartTime()
{
return startTime;
}
}

@ -0,0 +1,205 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.*;
import java.util.*;
import javax.swing.*;
/**
* The <tt>StringUtils</tt> class is used through this ui implementation for
* some special operations with strings.
*
* @author Yana Stamcheva
*/
public class GuiUtils {
private static Calendar c1 = Calendar.getInstance();
private static Calendar c2 = Calendar.getInstance();
/**
* Replaces some chars that are special in a regular expression.
* @param text The initial text.
* @return the formatted text
*/
public static String replaceSpecialRegExpChars(String text) {
return text.replaceAll("([.()^&$*|])", "\\\\$1");
}
/**
* Returns the width in pixels of a text.
* @param c the component where the text is contained
* @param text the text to measure
* @return the width in pixels of a text.
*/
public static int getStringWidth(Component c, String text) {
return SwingUtilities.computeStringWidth(c
.getFontMetrics(Constants.FONT), text);
}
/**
* Compares the two dates. The comparison is based only on the day, month
* and year values. Returns 0 if the two dates are equals, a value < 0 if
* the first date is before the second one and > 0 if the first date is after
* the second one.
* @param date1 the first date to compare
* @param date2 the second date to compare with
* @return Returns 0 if the two dates are equals, a value < 0 if
* the first date is before the second one and > 0 if the first date is after
* the second one
*/
public static int compareDates(Date date1, Date date2)
{
c1.setTime(date1);
c2.setTime(date2);
int day1 = c1.get(Calendar.DAY_OF_MONTH);
int month1 = c1.get(Calendar.MONTH);
int year1 = c1.get(Calendar.YEAR);
int day2 = c2.get(Calendar.DAY_OF_MONTH);
int month2 = c2.get(Calendar.MONTH);
int year2 = c2.get(Calendar.YEAR);
if((day1 == day2)
&& (month1 == month2)
&& (year1 == year2)) {
return 0;
}
else if((day1 < day2)
&& (month1 <= month2)
&& (year1 <= year2)) {
return -1;
}
else {
return 1;
}
}
/**
* Formats the given date. The result format is the following:
* [Month] [Day], [Year]. For example: Dec 24, 2000.
* @param date the date to format
* @return the formatted date string
*/
public static String formatDate(Date date)
{
c1.setTime(date);
return GuiUtils.processMonth(c1.get(Calendar.MONTH) + 1) + " "
+ GuiUtils.formatTime(c1.get(Calendar.DAY_OF_MONTH)) + ", "
+ GuiUtils.formatTime(c1.get(Calendar.YEAR));
}
/**
* Formats the time for the given date. The result format is the following:
* [Hour]:[Minute]:[Second]. For example: 12:25:30.
* @param date the date to format
* @return the formatted hour string
*/
public static String formatTime(Date date)
{
c1.setTime(date);
return GuiUtils.formatTime(c1.get(Calendar.HOUR_OF_DAY)) + ":"
+ GuiUtils.formatTime(c1.get(Calendar.MINUTE)) + ":"
+ GuiUtils.formatTime(c1.get(Calendar.SECOND)) ;
}
/**
* Substracts the two dates.
* @param date1 the first date argument
* @param date2 the second date argument
* @return the date resulted from the substracting
*/
public static Date substractDates(Date date1, Date date2)
{
long d1 = date1.getTime();
long d2 = date2.getTime();
long difMil = d1-d2;
long milPerDay = 1000*60*60*24;
long milPerHour = 1000*60*60;
long milPerMin = 1000*60;
long milPerSec = 1000;
long days = difMil / milPerDay;
int hour = (int)(( difMil - days*milPerDay ) / milPerHour);
int min
= (int)(( difMil - days*milPerDay - hour*milPerHour ) / milPerMin);
int sec
= (int)(( difMil - days*milPerDay - hour*milPerHour - min*milPerMin )
/ milPerSec);
c1.clear();
c1.set(Calendar.HOUR, hour);
c1.set(Calendar.MINUTE, min);
c1.set(Calendar.SECOND, sec);
return c1.getTime();
}
/**
* Replaces the month with its abbreviation.
* @param month Value from 1 to 12, which indicates the month.
* @return the corresponding month abbreviation
*/
private static String processMonth(int month)
{
String monthString = "";
if(month == 1)
monthString = Resources.getString("january");
else if(month == 2)
monthString = Resources.getString("february");
else if(month == 3)
monthString = Resources.getString("march");
else if(month == 4)
monthString = Resources.getString("april");
else if(month == 5)
monthString = Resources.getString("may");
else if(month == 6)
monthString = Resources.getString("june");
else if(month == 7)
monthString = Resources.getString("july");
else if(month == 8)
monthString = Resources.getString("august");
else if(month == 9)
monthString = Resources.getString("september");
else if(month == 10)
monthString = Resources.getString("october");
else if(month == 11)
monthString = Resources.getString("november");
else if(month == 12)
monthString = Resources.getString("december");
return monthString;
}
/**
* Adds a 0 in the beginning of one digit numbers.
*
* @param time The time parameter could be hours, minutes or seconds.
* @return The formatted minutes string.
*/
private static String formatTime(int time)
{
String timeString = new Integer(time).toString();
String resultString = "";
if (timeString.length() < 2)
resultString = resultString.concat("0").concat(timeString);
else
resultString = timeString;
return resultString;
}
}

@ -0,0 +1,129 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.extendedcallhistorysearch;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import net.java.sip.communicator.util.*;
/**
* The Messages class manages the access to the internationalization
* properties files.
* @author Yana Stamcheva
*/
public class Resources {
private static Logger log = Logger.getLogger(Resources.class);
private static final String BUNDLE_NAME
= "net.java.sip.communicator.plugin.extendedcallhistorysearch.resources";
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
.getBundle(BUNDLE_NAME);
/**
* Returns an internationalized string corresponding to the given key.
* @param key The key of the string.
* @return An internationalized string corresponding to the given key.
*/
public static String getString(String key)
{
String resourceString;
try
{
resourceString = RESOURCE_BUNDLE.getString(key);
int mnemonicIndex = resourceString.indexOf('&');
if(mnemonicIndex > -1)
{
String firstPart = resourceString.substring(0, mnemonicIndex);
String secondPart = resourceString.substring(mnemonicIndex + 1);
resourceString = firstPart.concat(secondPart);
}
}
catch (MissingResourceException e)
{
resourceString = '!' + key + '!';
}
return resourceString;
}
/**
* Loads an image from a given image identifier.
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public static ImageIcon getImage(String imageID) {
BufferedImage image = null;
String path = Resources.getString(imageID);
try {
image = ImageIO.read(Resources.class.getClassLoader()
.getResourceAsStream(path));
} catch (IOException e) {
log.error("Failed to load image:" + path, e);
}
return new ImageIcon(image);
}
/**
* Returns an internationalized string corresponding to the given key.
* @param key The key of the string.
* @return An internationalized string corresponding to the given key.
*/
public static char getMnemonic(String key)
{
String resourceString;
try {
resourceString = RESOURCE_BUNDLE.getString(key);
int mnemonicIndex = resourceString.indexOf('&');
if(mnemonicIndex > -1)
{
return resourceString.charAt(mnemonicIndex + 1);
}
}
catch (MissingResourceException e)
{
return '!';
}
return '!';
}
/**
* Loads an image from a given image identifier.
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public static byte[] getImageInBytes(String imageID) {
byte[] image = new byte[100000];
String path = Resources.getString(imageID);
try {
Resources.class.getClassLoader()
.getResourceAsStream(path).read(image);
} catch (IOException e) {
log.error("Failed to load image:" + path, e);
}
return image;
}
}

@ -0,0 +1,27 @@
Bundle-Activator: net.java.sip.communicator.plugin.extendedcallhistorysearch.ExtendedCallHistorySearchActivator
Bundle-Name: Extended Call History Search
Bundle-Description: An Extended Call History Search
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
Import-Package: org.osgi.framework,
net.java.sip.communicator.util,
net.java.sip.communicator.service.contactlist,
net.java.sip.communicator.service.contactlist.event,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.gui.event,
net.java.sip.communicator.service.callhistory,
net.java.sip.communicator.service.configuration,
javax.swing,
javax.swing.event,
javax.swing.table,
javax.swing.text,
javax.accessibility,
javax.swing.plaf,
javax.swing.plaf.metal,
javax.swing.plaf.basic,
javax.imageio,
javax.swing.filechooser,
javax.swing.tree,
javax.swing.border

@ -0,0 +1,31 @@
advancedCallHistorySearch=&Advanced call history search
search=Search
contactName=Contact Name
since=Since
until=Until
callType=Call Type
incoming=Incoming
outgoing=Outgoing
olderCalls=Older Calls
duration=Duration
at=at
all=all
today=Today
january=Jan
february=Feb
march=Mar
april=Apr
may=May
june=Jun
july=Jul
august=Aug
september=Sep
october=Oct
november=Nov
december=Dec
searchIcon=net/java/sip/communicator/plugin/extendedcallhistorysearch/resources/searchIcon.png
historyMenuIcon=net/java/sip/communicator/plugin/extendedcallhistorysearch/resources/history16x16.png
incomingCall=net/java/sip/communicator/plugin/extendedcallhistorysearch/resources/incomingCall.png
outgoingCall=net/java/sip/communicator/plugin/extendedcallhistorysearch/resources/outgoingCall.png
calendarIcon=net/java/sip/communicator/plugin/extendedcallhistorysearch/resources/calendarIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Loading…
Cancel
Save